[FFmpeg-devel] [PATCH v2 08/13] avpriv_find_start_code(): add parameter for ignoring history

Scott Theisen scott.the.elm at gmail.com
Thu Feb 3 20:44:45 EET 2022


If true, this skips the for loop at the beginning of avpriv_find_start_code().

If the state/start_code input is a local variable and only one buffer is used,
then no history is needed.

In loops and inline functions: if ignoring history, don't initialize start_code,
so it isn't reset twice each time.

cbs_mpeg2.c needs further changes to use output_only = true.

Use output_only = 0 for no functional change.  For example, if the state/start_code
is passed into the function calling avpriv_find_start_code().
---
 libavcodec/cavsdec.c                  |  2 +-
 libavcodec/cbs_mpeg2.c                |  4 ++--
 libavcodec/extract_extradata_bsf.c    |  4 ++--
 libavcodec/h264_parser.c              |  2 +-
 libavcodec/internal.h                 |  9 ++++++++-
 libavcodec/mpeg12.c                   |  2 +-
 libavcodec/mpeg12dec.c                |  9 ++++-----
 libavcodec/mpeg4_unpack_bframes_bsf.c |  3 +--
 libavcodec/mpegvideo_parser.c         |  5 ++---
 libavcodec/remove_extradata_bsf.c     |  8 ++++----
 libavcodec/utils.c                    | 14 +++++++++++++-
 libavcodec/vc1_common.h               |  4 ++--
 libavformat/avidec.c                  |  6 +++---
 libavformat/avs2dec.c                 |  2 +-
 libavformat/avs3dec.c                 |  2 +-
 libavformat/cavsvideodec.c            |  2 +-
 libavformat/mpegtsenc.c               |  4 ++--
 libavformat/mpegvideodec.c            |  2 +-
 libavformat/mxfenc.c                  |  2 +-
 libavformat/rtpenc_mpv.c              |  4 ++--
 20 files changed, 53 insertions(+), 37 deletions(-)

diff --git a/libavcodec/cavsdec.c b/libavcodec/cavsdec.c
index a62177d520..c4c78cd534 100644
--- a/libavcodec/cavsdec.c
+++ b/libavcodec/cavsdec.c
@@ -1248,7 +1248,7 @@ static int cavs_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
     buf_ptr = buf;
     buf_end = buf + buf_size;
     for(;;) {
-        buf_ptr = avpriv_find_start_code(buf_ptr, buf_end, &stc);
+        buf_ptr = avpriv_find_start_code(buf_ptr, buf_end, &stc, 1);
         if (!avpriv_start_code_is_valid(stc) || buf_ptr == buf_end) {
             if (!h->stc)
                 av_log(h->avctx, AV_LOG_WARNING, "no frame decoded\n");
diff --git a/libavcodec/cbs_mpeg2.c b/libavcodec/cbs_mpeg2.c
index eb45929132..d41477620e 100644
--- a/libavcodec/cbs_mpeg2.c
+++ b/libavcodec/cbs_mpeg2.c
@@ -151,7 +151,7 @@ static int cbs_mpeg2_split_fragment(CodedBitstreamContext *ctx,
     int err, i, final = 0;
 
     start = avpriv_find_start_code(frag->data, frag->data + frag->data_size,
-                                   &start_code);
+                                   &start_code, 1);
     if (!avpriv_start_code_is_valid(start_code)) {
         // No start code found.
         return AVERROR_INVALIDDATA;
@@ -169,7 +169,7 @@ static int cbs_mpeg2_split_fragment(CodedBitstreamContext *ctx,
         }
 
         end = avpriv_find_start_code(start--, frag->data + frag->data_size,
-                                     &start_code);
+                                     &start_code, 0);
 
         // start points to the byte containing the start_code_identifier
         // (may be the last byte of fragment->data); end points to the byte
diff --git a/libavcodec/extract_extradata_bsf.c b/libavcodec/extract_extradata_bsf.c
index 4df1c97139..1a3ddceff2 100644
--- a/libavcodec/extract_extradata_bsf.c
+++ b/libavcodec/extract_extradata_bsf.c
@@ -237,7 +237,7 @@ static int extract_extradata_vc1(AVBSFContext *ctx, AVPacket *pkt,
     int has_extradata = 0, extradata_size = 0;
 
     while (ptr < end) {
-        ptr = avpriv_find_start_code(ptr, end, &state);
+        ptr = avpriv_find_start_code(ptr, end, &state, 1);
         if (state == VC1_CODE_SEQHDR || state == VC1_CODE_ENTRYPOINT) {
             has_extradata = 1;
         } else if (has_extradata && avpriv_start_code_is_valid(state)) {
@@ -300,7 +300,7 @@ static int extract_extradata_mpeg4(AVBSFContext *ctx, AVPacket *pkt,
     uint32_t state = UINT32_MAX;
 
     while (ptr < end) {
-        ptr = avpriv_find_start_code(ptr, end, &state);
+        ptr = avpriv_find_start_code(ptr, end, &state, 1);
         if (state == 0x1B3 || state == 0x1B6) {
             if (ptr - pkt->data > 4) {
                 *size = ptr - 4 - pkt->data;
diff --git a/libavcodec/h264_parser.c b/libavcodec/h264_parser.c
index 4002bcad77..0ca411c592 100644
--- a/libavcodec/h264_parser.c
+++ b/libavcodec/h264_parser.c
@@ -72,7 +72,7 @@ static int find_start_code(const uint8_t *buf, int buf_size,
 {
     uint32_t state = -1;
 
-    buf_index = avpriv_find_start_code(buf + buf_index, buf + next_avc + 1, &state) - buf - 1;
+    buf_index = avpriv_find_start_code(buf + buf_index, buf + next_avc + 1, &state, 1) - buf - 1;
 
     return FFMIN(buf_index, buf_size);
 }
diff --git a/libavcodec/internal.h b/libavcodec/internal.h
index dadd8d4a10..57e2816a95 100644
--- a/libavcodec/internal.h
+++ b/libavcodec/internal.h
@@ -309,6 +309,9 @@ static av_always_inline int avpriv_start_code_is_valid(uint32_t start_code) {
  * By preserving the <b>@p start_code</b> value between subsequent calls, the caller can
  * detect start codes across buffer boundaries.
  *
+ * If <b>@p output_only</b> is true, <b>@p start_code</b> is reset to <b>@c ~0 </b>
+ * if @f$ p - end < 4 @f$.
+ *
  * @param[in] p     A pointer to the start of the memory buffer to scan.
  * @param[in] end   A pointer to the past-the-end memory address for the buffer
  *                  given by @p p.  <b>@p p</b> must be ≤ <b>@p end</b>.
@@ -321,12 +324,16 @@ static av_always_inline int avpriv_start_code_is_valid(uint32_t start_code) {
  *                     start code (the 4 bytes prior to the returned value,
  *                     using the input history if @f$ p - end < 4 @f$).
  *
+ * @param[in] output_only   Boolean that if true makes <b>@p start_code</b> an
+ *                          output only parameter.
+ *
  * @return A pointer to the memory address following the found start code, or <b>@p end</b>
  *         if no start code was found.
  */
 const uint8_t *avpriv_find_start_code(const uint8_t *p,
                                       const uint8_t * const end,
-                                      uint32_t * const start_code);
+                                      uint32_t * const start_code,
+                                      int output_only);
 
 int avpriv_codec_get_cap_skip_frame_fill_param(const AVCodec *codec);
 
diff --git a/libavcodec/mpeg12.c b/libavcodec/mpeg12.c
index e45bc74479..d788aeb9e2 100644
--- a/libavcodec/mpeg12.c
+++ b/libavcodec/mpeg12.c
@@ -203,7 +203,7 @@ int ff_mpeg1_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size,
             }
             state++;
         } else {
-            i = avpriv_find_start_code(buf + i, buf + buf_size, &state) - buf - 1;
+            i = avpriv_find_start_code(buf + i, buf + buf_size, &state, 0) - buf - 1;
             if (pc->frame_start_found == 0 && state >= SLICE_MIN_START_CODE && state <= SLICE_MAX_START_CODE) {
                 i++;
                 pc->frame_start_found = 4;
diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c
index 6b0b84ae64..cad17d1b1a 100644
--- a/libavcodec/mpeg12dec.c
+++ b/libavcodec/mpeg12dec.c
@@ -1771,7 +1771,7 @@ static int mpeg_decode_slice(MpegEncContext *s, int mb_y,
     if (avctx->hwaccel && avctx->hwaccel->decode_slice) {
         const uint8_t *buf_end, *buf_start = *buf - 4; /* include start_code */
         uint32_t start_code = ~0;
-        buf_end = avpriv_find_start_code(buf_start + 2, *buf + buf_size, &start_code);
+        buf_end = avpriv_find_start_code(buf_start + 2, *buf + buf_size, &start_code, 1);
         if (buf_end < *buf + buf_size)
             buf_end -= 4;
         s->mb_y = mb_y;
@@ -2020,8 +2020,7 @@ static int slice_decode_thread(AVCodecContext *c, void *arg)
         if (s->mb_y == s->end_mb_y)
             return 0;
 
-        start_code = -1;
-        buf        = avpriv_find_start_code(buf, s->gb.buffer_end, &start_code);
+        buf        = avpriv_find_start_code(buf, s->gb.buffer_end, &start_code, 1);
         if (start_code < SLICE_MIN_START_CODE || start_code > SLICE_MAX_START_CODE)
             return AVERROR_INVALIDDATA;
         mb_y       = start_code - SLICE_MIN_START_CODE;
@@ -2475,8 +2474,8 @@ static int decode_chunks(AVCodecContext *avctx, AVFrame *picture,
 
     for (;;) {
         /* find next start code */
-        uint32_t start_code = -1;
-        buf_ptr = avpriv_find_start_code(buf_ptr, buf_end, &start_code);
+        uint32_t start_code;
+        buf_ptr = avpriv_find_start_code(buf_ptr, buf_end, &start_code, 1);
         if (!avpriv_start_code_is_valid(start_code)) {
             if (!skip_frame) {
                 if (HAVE_THREADS &&
diff --git a/libavcodec/mpeg4_unpack_bframes_bsf.c b/libavcodec/mpeg4_unpack_bframes_bsf.c
index 6f8595713d..37fb0e4b66 100644
--- a/libavcodec/mpeg4_unpack_bframes_bsf.c
+++ b/libavcodec/mpeg4_unpack_bframes_bsf.c
@@ -36,8 +36,7 @@ static void scan_buffer(const uint8_t *buf, int buf_size,
     const uint8_t *end = buf + buf_size, *pos = buf;
 
     while (pos < end) {
-        startcode = -1;
-        pos = avpriv_find_start_code(pos, end, &startcode);
+        pos = avpriv_find_start_code(pos, end, &startcode, 1);
 
         if (startcode == USER_DATA_STARTCODE && pos_p) {
             /* check if the (DivX) userdata string ends with 'p' (packed) */
diff --git a/libavcodec/mpegvideo_parser.c b/libavcodec/mpegvideo_parser.c
index f0897e7e2c..14e350eaea 100644
--- a/libavcodec/mpegvideo_parser.c
+++ b/libavcodec/mpegvideo_parser.c
@@ -68,7 +68,7 @@ static int mpeg1_find_frame_end(ParseContext *pc, const uint8_t *buf,
             }
             state++;
         } else {
-            i = avpriv_find_start_code(buf + i, buf + buf_size, &state) - buf - 1;
+            i = avpriv_find_start_code(buf + i, buf + buf_size, &state, 0) - buf - 1;
             if (pc->frame_start_found == 0 && state >= SLICE_MIN_START_CODE && state <= SLICE_MAX_START_CODE) {
                 i++;
                 pc->frame_start_found = 4;
@@ -120,8 +120,7 @@ static void mpegvideo_extract_headers(AVCodecParserContext *s,
     s->repeat_pict = 0;
 
     while (buf < buf_end) {
-        start_code= -1;
-        buf= avpriv_find_start_code(buf, buf_end, &start_code);
+        buf = avpriv_find_start_code(buf, buf_end, &start_code, 1);
         bytes_left = buf_end - buf;
         switch(start_code) {
         case PICTURE_START_CODE:
diff --git a/libavcodec/remove_extradata_bsf.c b/libavcodec/remove_extradata_bsf.c
index 0e42174912..46e914053d 100644
--- a/libavcodec/remove_extradata_bsf.c
+++ b/libavcodec/remove_extradata_bsf.c
@@ -70,7 +70,7 @@ static int h264_split(const uint8_t *buf, int buf_size)
     int nalu_type;
 
     while (ptr < end) {
-        ptr = avpriv_find_start_code(ptr, end, &state);
+        ptr = avpriv_find_start_code(ptr, end, &state, 1);
         if (!avpriv_start_code_is_valid(state))
             break;
         nalu_type = state & 0x1F;
@@ -108,7 +108,7 @@ static int hevc_split(const uint8_t *buf, int buf_size)
     int nut;
 
     while (ptr < end) {
-        ptr = avpriv_find_start_code(ptr, end, &state);
+        ptr = avpriv_find_start_code(ptr, end, &state, 1);
         if (!avpriv_start_code_is_valid(state))
             break;
         nut = (state >> 1) & 0x3F;
@@ -151,7 +151,7 @@ static int mpeg4video_split(const uint8_t *buf, int buf_size)
     uint32_t state = -1;
 
     while (ptr < end) {
-        ptr = avpriv_find_start_code(ptr, end, &state);
+        ptr = avpriv_find_start_code(ptr, end, &state, 1);
         if (state == 0x1B3 || state == 0x1B6)
             return ptr - 4 - buf;
     }
@@ -166,7 +166,7 @@ static int vc1_split(const uint8_t *buf, int buf_size)
     int charged = 0;
 
     while (ptr < end) {
-        ptr = avpriv_find_start_code(ptr, end, &state);
+        ptr = avpriv_find_start_code(ptr, end, &state, 1);
         if (state == VC1_CODE_SEQHDR || state == VC1_CODE_ENTRYPOINT) {
             charged = 1;
         } else if (charged && avpriv_start_code_is_valid(state))
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index cf92d29f67..da057bad3e 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -942,9 +942,20 @@ void ff_thread_report_progress2(AVCodecContext *avctx, int field, int thread, in
 
 const uint8_t *avpriv_find_start_code(const uint8_t *av_restrict p,
                                       const uint8_t * const end,
-                                      uint32_t * const av_restrict start_code)
+                                      uint32_t * const av_restrict start_code,
+                                      const int output_only)
 {
     av_assert0(p <= end);
+    if (output_only) {
+        // minimum length for a start code
+        if (p + 4 > end) {
+            *start_code = ~0; // set to an invalid start code
+            return end;
+        }
+
+        p += 3; // offset for negative indices in while loop
+    }
+    else {
     if (p >= end)
         return end;
 
@@ -958,6 +969,7 @@ const uint8_t *avpriv_find_start_code(const uint8_t *av_restrict p,
             return p;
     }
     // p is now properly incremented for the negative indices in the while loop
+    }
 
     /* with memory address increasing left to right, we are looking for (in hexadecimal):
      * 00 00 01 XX
diff --git a/libavcodec/vc1_common.h b/libavcodec/vc1_common.h
index 483f86a4ee..453dec34c6 100644
--- a/libavcodec/vc1_common.h
+++ b/libavcodec/vc1_common.h
@@ -57,8 +57,8 @@ enum Profile {
 static av_always_inline const uint8_t* find_next_marker(const uint8_t *src, const uint8_t *end)
 {
     if (end - src >= 4) {
-        uint32_t mrk = 0xFFFFFFFF;
-        src = avpriv_find_start_code(src, end, &mrk);
+        uint32_t mrk;
+        src = avpriv_find_start_code(src, end, &mrk, 1);
         if (avpriv_start_code_is_valid(mrk))
             return src - 4;
     }
diff --git a/libavformat/avidec.c b/libavformat/avidec.c
index 86f857b1e3..674f313e84 100644
--- a/libavformat/avidec.c
+++ b/libavformat/avidec.c
@@ -1530,12 +1530,12 @@ resync:
                 if (index >= 0 && e->timestamp == ast->frame_offset) {
                     if (index == sti->nb_index_entries-1) {
                         int key=1;
-                        uint32_t state=-1;
                         if (st->codecpar->codec_id == AV_CODEC_ID_MPEG4) {
                             const uint8_t *ptr = pkt->data, *end = ptr + FFMIN(size, 256);
                             while (ptr < end) {
-                                ptr = avpriv_find_start_code(ptr, end, &state);
-                                if (state == 0x1B6 && ptr < end) {
+                                uint32_t start_code;
+                                ptr = avpriv_find_start_code(ptr, end, &start_code, 1);
+                                if (start_code == 0x1B6 && ptr < end) {
                                     key = !(*ptr & 0xC0);
                                     break;
                                 }
diff --git a/libavformat/avs2dec.c b/libavformat/avs2dec.c
index bdeb746fc7..f2349dde45 100644
--- a/libavformat/avs2dec.c
+++ b/libavformat/avs2dec.c
@@ -41,7 +41,7 @@ static int avs2_probe(const AVProbeData *p)
     }
 
     while (ptr < end) {
-        ptr = avpriv_find_start_code(ptr, end, &code);
+        ptr = avpriv_find_start_code(ptr, end, &code, 1);
         if (avpriv_start_code_is_valid(code)) {
             state = code & 0xFF;
             if (AVS2_ISUNIT(state)) {
diff --git a/libavformat/avs3dec.c b/libavformat/avs3dec.c
index 2daccd3d15..2238193ff4 100644
--- a/libavformat/avs3dec.c
+++ b/libavformat/avs3dec.c
@@ -35,7 +35,7 @@ static int avs3video_probe(const AVProbeData *p)
     int ret = 0;
 
     while (ptr < end) {
-        ptr = avpriv_find_start_code(ptr, end, &code);
+        ptr = avpriv_find_start_code(ptr, end, &code, 1);
         if (avpriv_start_code_is_valid(code)) {
             state = code & 0xFF;
             if (state < AVS3_SEQ_START_CODE) {
diff --git a/libavformat/cavsvideodec.c b/libavformat/cavsvideodec.c
index 1d007708cc..8f4004acea 100644
--- a/libavformat/cavsvideodec.c
+++ b/libavformat/cavsvideodec.c
@@ -37,7 +37,7 @@ static int cavsvideo_probe(const AVProbeData *p)
     const uint8_t *ptr = p->buf, *end = p->buf + p->buf_size;
 
     while (ptr < end) {
-        ptr = avpriv_find_start_code(ptr, end, &code);
+        ptr = avpriv_find_start_code(ptr, end, &code, 1);
         if (avpriv_start_code_is_valid(code)) {
             if(code < CAVS_SEQ_START_CODE) {
                 /* slices have to be consecutive */
diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c
index 92b4cc8087..483c65be17 100644
--- a/libavformat/mpegtsenc.c
+++ b/libavformat/mpegtsenc.c
@@ -1881,7 +1881,7 @@ static int mpegts_write_packet_internal(AVFormatContext *s, AVPacket *pkt)
             extradd = 0;
 
         do {
-            p = avpriv_find_start_code(p, buf_end, &state);
+            p = avpriv_find_start_code(p, buf_end, &state, 1);
             av_log(s, AV_LOG_TRACE, "nal %"PRId32"\n", state & 0x1f);
             if ((state & 0x1f) == 7)
                 extradd = 0;
@@ -1947,7 +1947,7 @@ static int mpegts_write_packet_internal(AVFormatContext *s, AVPacket *pkt)
             extradd = 0;
 
         do {
-            p = avpriv_find_start_code(p, buf_end, &state);
+            p = avpriv_find_start_code(p, buf_end, &state, 1);
             av_log(s, AV_LOG_TRACE, "nal %"PRId32"\n", (state & 0x7e)>>1);
             if ((state & 0x7e) == 2*32)
                 extradd = 0;
diff --git a/libavformat/mpegvideodec.c b/libavformat/mpegvideodec.c
index a9829dc1df..840d3565af 100644
--- a/libavformat/mpegvideodec.c
+++ b/libavformat/mpegvideodec.c
@@ -43,7 +43,7 @@ static int mpegvideo_probe(const AVProbeData *p)
     int j;
 
     while (ptr < end) {
-        ptr = avpriv_find_start_code(ptr, end, &code);
+        ptr = avpriv_find_start_code(ptr, end, &code, 1);
         if (avpriv_start_code_is_valid(code)) {
             switch(code){
             case     SEQ_START_CODE:
diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c
index 5e068c8220..8cec44e89c 100644
--- a/libavformat/mxfenc.c
+++ b/libavformat/mxfenc.c
@@ -2242,7 +2242,7 @@ static int mxf_parse_h264_frame(AVFormatContext *s, AVStream *st,
     int i, frame_size, slice_type, has_sps = 0, intra_only = 0, ret;
 
     for (;;) {
-        buf = avpriv_find_start_code(buf, buf_end, &state);
+        buf = avpriv_find_start_code(buf, buf_end, &state, 1);
         if (buf >= buf_end)
             break;
 
diff --git a/libavformat/rtpenc_mpv.c b/libavformat/rtpenc_mpv.c
index 91c07574bb..3c7168c482 100644
--- a/libavformat/rtpenc_mpv.c
+++ b/libavformat/rtpenc_mpv.c
@@ -54,8 +54,8 @@ void ff_rtp_send_mpegvideo(AVFormatContext *s1, const uint8_t *buf1, int size)
 
             r1 = buf1;
             while (1) {
-                uint32_t start_code = ~0;
-                r = avpriv_find_start_code(r1, end, &start_code);
+                uint32_t start_code;
+                r = avpriv_find_start_code(r1, end, &start_code, 1);
                 if (avpriv_start_code_is_valid(start_code)) {
                     /* New start code found */
                     if (start_code == 0x100) {
-- 
2.32.0



More information about the ffmpeg-devel mailing list