[FFmpeg-cvslog] avcodec/mpegvideo: Move bitstream_buffer to mpeg4videodec

Andreas Rheinhardt git at videolan.org
Tue Mar 4 14:35:39 EET 2025


ffmpeg | branch: master | Andreas Rheinhardt <andreas.rheinhardt at outlook.com> | Tue Feb 25 00:48:08 2025 +0100| [e3ebc1073e06b87ecf110476194c88c4af9b181f] | committer: Andreas Rheinhardt

avcodec/mpegvideo: Move bitstream_buffer to mpeg4videodec

This is possible by moving the code using it to open a GetBitContext
from h263dec.c to mpeg4videodec.c.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt at outlook.com>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=e3ebc1073e06b87ecf110476194c88c4af9b181f
---

 libavcodec/h263dec.c           | 25 ++---------
 libavcodec/mpeg4video_parser.c |  4 +-
 libavcodec/mpeg4videodec.c     | 95 ++++++++++++++++++++++++++++++++----------
 libavcodec/mpeg4videodec.h     |  8 +++-
 libavcodec/mpegvideo.c         |  5 ---
 libavcodec/mpegvideo.h         |  3 --
 libavcodec/mpegvideo_dec.c     |  3 --
 7 files changed, 85 insertions(+), 58 deletions(-)

diff --git a/libavcodec/h263dec.c b/libavcodec/h263dec.c
index 2d8c200589..84895a93d4 100644
--- a/libavcodec/h263dec.c
+++ b/libavcodec/h263dec.c
@@ -446,26 +446,8 @@ int ff_h263_decode_frame(AVCodecContext *avctx, AVFrame *pict,
     }
 
 retry:
-    if (s->divx_packed && s->bitstream_buffer_size) {
-        int i;
-        for(i=0; i < buf_size-3; i++) {
-            if (buf[i]==0 && buf[i+1]==0 && buf[i+2]==1) {
-                if (buf[i+3]==0xB0) {
-                    av_log(s->avctx, AV_LOG_WARNING, "Discarding excessive bitstream in packed xvid\n");
-                    s->bitstream_buffer_size = 0;
-                }
-                break;
-            }
-        }
-    }
-
-    if (s->bitstream_buffer_size && (s->divx_packed || buf_size <= MAX_NVOP_SIZE)) // divx 5.01+/xvid frame reorder
-        ret = init_get_bits8(&s->gb, s->bitstream_buffer,
-                             s->bitstream_buffer_size);
-    else
-        ret = init_get_bits8(&s->gb, buf, buf_size);
-
-    s->bitstream_buffer_size = 0;
+    // s->gb might be overridden in ff_mpeg4_decode_picture_header() below.
+    ret = init_get_bits8(&s->gb, buf, buf_size);
     if (ret < 0)
         return ret;
 
@@ -480,7 +462,7 @@ retry:
         ret = ff_msmpeg4_decode_picture_header(s);
 #endif
     } else if (CONFIG_MPEG4_DECODER && avctx->codec_id == AV_CODEC_ID_MPEG4) {
-        ret = ff_mpeg4_decode_picture_header(avctx->priv_data, &s->gb, 0, 0);
+        ret = ff_mpeg4_decode_picture_header(s);
         s->skipped_last_frame = (ret == FRAME_SKIPPED);
     } else if (CONFIG_H263I_DECODER && s->codec_id == AV_CODEC_ID_H263I) {
         ret = ff_intel_h263_decode_picture_header(s);
@@ -631,7 +613,6 @@ retry:
             ff_msmpeg4_decode_ext_header(s, buf_size) < 0)
             s->er.error_status_table[s->mb_num - 1] = ER_MB_ERROR;
 
-    av_assert1(s->bitstream_buffer_size == 0);
 frame_end:
     if (!s->studio_profile)
         ff_er_frame_end(&s->er, NULL);
diff --git a/libavcodec/mpeg4video_parser.c b/libavcodec/mpeg4video_parser.c
index b00b523bde..ef9ea923f6 100644
--- a/libavcodec/mpeg4video_parser.c
+++ b/libavcodec/mpeg4video_parser.c
@@ -92,13 +92,13 @@ static int mpeg4_decode_header(AVCodecParserContext *s1, AVCodecContext *avctx,
 
     if (avctx->extradata_size && pc->first_picture) {
         init_get_bits(gb, avctx->extradata, avctx->extradata_size * 8);
-        ret = ff_mpeg4_decode_picture_header(dec_ctx, gb, 1, 1);
+        ret = ff_mpeg4_parse_picture_header(dec_ctx, gb, 1, 1);
         if (ret < 0)
             av_log(avctx, AV_LOG_WARNING, "Failed to parse extradata\n");
     }
 
     init_get_bits(gb, buf, 8 * buf_size);
-    ret = ff_mpeg4_decode_picture_header(dec_ctx, gb, 0, 1);
+    ret = ff_mpeg4_parse_picture_header(dec_ctx, gb, 0, 1);
     if (s->width && (!avctx->width || !avctx->height ||
                      !avctx->coded_width || !avctx->coded_height)) {
         ret = ff_set_dimensions(avctx, s->width, s->height);
diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c
index 14e4de9a45..e2ae09125a 100644
--- a/libavcodec/mpeg4videodec.c
+++ b/libavcodec/mpeg4videodec.c
@@ -25,6 +25,7 @@
 #include "config_components.h"
 
 #include "libavutil/internal.h"
+#include "libavutil/mem.h"
 #include "libavutil/opt.h"
 #include "libavutil/thread.h"
 #include "codec_internal.h"
@@ -3463,8 +3464,8 @@ static int decode_studiovisualobject(Mpeg4DecContext *ctx, GetBitContext *gb)
  *         FRAME_SKIPPED if a not coded VOP is found
  *         0 else
  */
-int ff_mpeg4_decode_picture_header(Mpeg4DecContext *ctx, GetBitContext *gb,
-                                   int header, int parse_only)
+int ff_mpeg4_parse_picture_header(Mpeg4DecContext *ctx, GetBitContext *gb,
+                                  int header, int parse_only)
 {
     MpegEncContext *s = &ctx->m;
     unsigned startcode, v;
@@ -3621,16 +3622,50 @@ end:
         return decode_vop_header(ctx, gb, parse_only);
 }
 
+int ff_mpeg4_decode_picture_header(MpegEncContext *s)
+{
+    Mpeg4DecContext *const ctx = (Mpeg4DecContext*)s;
+
+    if (ctx->bitstream_buffer_size) {
+        int buf_size = get_bits_left(&s->gb) / 8U;
+        int bitstream_buffer_size = ctx->bitstream_buffer_size;
+        const uint8_t *buf = s->gb.buffer;
+
+        if (s->divx_packed) {
+            for (int i = 0; i < buf_size - 3; i++) {
+                if (buf[i] == 0 && buf[i+1] == 0 && buf[i+2] == 1) {
+                    if (buf[i+3] == 0xB0) {
+                        av_log(s->avctx, AV_LOG_WARNING, "Discarding excessive bitstream in packed xvid\n");
+                        bitstream_buffer_size = 0;
+                    }
+                    break;
+                }
+            }
+        }
+        ctx->bitstream_buffer_size = 0;
+        if (bitstream_buffer_size && (s->divx_packed || buf_size <= MAX_NVOP_SIZE)) {// divx 5.01+/xvid frame reorder
+            int ret = init_get_bits8(&s->gb, ctx->bitstream_buffer,
+                                     bitstream_buffer_size);
+            if (ret < 0)
+                return ret;
+        }
+    }
+
+    return ff_mpeg4_parse_picture_header(ctx, &s->gb, 0, 0);
+}
+
 int ff_mpeg4_frame_end(AVCodecContext *avctx, const uint8_t *buf, int buf_size)
 {
     Mpeg4DecContext *ctx = avctx->priv_data;
     MpegEncContext    *s = &ctx->m;
 
+    av_assert1(ctx->bitstream_buffer_size == 0);
+
     /* divx 5.01+ bitstream reorder stuff */
     /* Since this clobbers the input buffer and hwaccel codecs still need the
      * data during hwaccel->end_frame we should not do this any earlier */
     if (s->divx_packed) {
-        int current_pos     = s->gb.buffer == s->bitstream_buffer ? 0 : (get_bits_count(&s->gb) >> 3);
+        int current_pos     = s->gb.buffer == ctx->bitstream_buffer ? 0 : (get_bits_count(&s->gb) >> 3);
         int startcode_found = 0;
 
         if (buf_size - current_pos > 7) {
@@ -3654,16 +3689,16 @@ int ff_mpeg4_frame_end(AVCodecContext *avctx, const uint8_t *buf, int buf_size)
                        "Consider using the mpeg4_unpack_bframes bitstream filter without encoding but stream copy to fix it.\n");
                 ctx->showed_packed_warning = 1;
             }
-            av_fast_padded_malloc(&s->bitstream_buffer,
-                           &s->allocated_bitstream_buffer_size,
+            av_fast_padded_malloc(&ctx->bitstream_buffer,
+                           &ctx->allocated_bitstream_buffer_size,
                            buf_size - current_pos);
-            if (!s->bitstream_buffer) {
-                s->bitstream_buffer_size = 0;
+            if (!ctx->bitstream_buffer) {
+                ctx->bitstream_buffer_size = 0;
                 return AVERROR(ENOMEM);
             }
-            memcpy(s->bitstream_buffer, buf + current_pos,
+            memcpy(ctx->bitstream_buffer, buf + current_pos,
                    buf_size - current_pos);
-            s->bitstream_buffer_size = buf_size - current_pos;
+            ctx->bitstream_buffer_size = buf_size - current_pos;
         }
     }
 
@@ -3715,17 +3750,17 @@ static int mpeg4_update_thread_context(AVCodecContext *dst,
     memcpy(s->sprite_shift, s1->sprite_shift, sizeof(s1->sprite_shift));
     memcpy(s->sprite_traj,  s1->sprite_traj,  sizeof(s1->sprite_traj));
 
-    if (s1->m.bitstream_buffer) {
-        av_fast_padded_malloc(&s->m.bitstream_buffer,
-                              &s->m.allocated_bitstream_buffer_size,
-                              s1->m.bitstream_buffer_size);
-        if (!s->m.bitstream_buffer) {
-            s->m.bitstream_buffer_size = 0;
+    if (s1->bitstream_buffer) {
+        av_fast_padded_malloc(&s->bitstream_buffer,
+                              &s->allocated_bitstream_buffer_size,
+                              s1->bitstream_buffer_size);
+        if (!s->bitstream_buffer) {
+            s->bitstream_buffer_size = 0;
             return AVERROR(ENOMEM);
         }
-        s->m.bitstream_buffer_size = s1->m.bitstream_buffer_size;
-        memcpy(s->m.bitstream_buffer, s1->m.bitstream_buffer,
-               s1->m.bitstream_buffer_size);
+        s->bitstream_buffer_size = s1->bitstream_buffer_size;
+        memcpy(s->bitstream_buffer, s1->bitstream_buffer,
+               s1->bitstream_buffer_size);
     }
 
     if (!init && s1->xvid_build >= 0)
@@ -3825,12 +3860,30 @@ static av_cold int decode_init(AVCodecContext *avctx)
         GetBitContext gb;
 
         if (init_get_bits8(&gb, avctx->extradata, avctx->extradata_size) >= 0)
-            ff_mpeg4_decode_picture_header(ctx, &gb, 1, 0);
+            ff_mpeg4_parse_picture_header(ctx, &gb, 1, 0);
     }
 
     return 0;
 }
 
+static av_cold void mpeg4_flush(AVCodecContext *avctx)
+{
+    Mpeg4DecContext *const ctx = avctx->priv_data;
+
+    ctx->bitstream_buffer_size = 0;
+    ff_mpeg_flush(avctx);
+}
+
+static av_cold int mpeg4_close(AVCodecContext *avctx)
+{
+    Mpeg4DecContext *const ctx = avctx->priv_data;
+
+    ctx->bitstream_buffer_size = 0;
+    av_freep(&ctx->bitstream_buffer);
+
+    return ff_mpv_decode_close(avctx);
+}
+
 #define OFFSET(x) offsetof(MpegEncContext, x)
 #define FLAGS AV_OPT_FLAG_EXPORT | AV_OPT_FLAG_READONLY
 static const AVOption mpeg4_options[] = {
@@ -3854,12 +3907,12 @@ const FFCodec ff_mpeg4_decoder = {
     .priv_data_size        = sizeof(Mpeg4DecContext),
     .init                  = decode_init,
     FF_CODEC_DECODE_CB(ff_h263_decode_frame),
-    .close                 = ff_mpv_decode_close,
+    .close                 = mpeg4_close,
     .p.capabilities        = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1 |
                              AV_CODEC_CAP_DELAY | AV_CODEC_CAP_FRAME_THREADS,
     .caps_internal         = FF_CODEC_CAP_INIT_CLEANUP |
                              FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM,
-    .flush                 = ff_mpeg_flush,
+    .flush                 = mpeg4_flush,
     .p.max_lowres          = 3,
     .p.profiles            = NULL_IF_CONFIG_SMALL(ff_mpeg4_video_profiles),
     UPDATE_THREAD_CONTEXT(mpeg4_update_thread_context),
diff --git a/libavcodec/mpeg4videodec.h b/libavcodec/mpeg4videodec.h
index 734237b16f..c4f6897c73 100644
--- a/libavcodec/mpeg4videodec.h
+++ b/libavcodec/mpeg4videodec.h
@@ -70,6 +70,9 @@ typedef struct Mpeg4DecContext {
     int divx_build;
     int xvid_build;
     int lavc_build;
+    uint8_t *bitstream_buffer; //Divx 5.01 puts several frames in a single one, this is used to reorder them
+    int bitstream_buffer_size;
+    unsigned int allocated_bitstream_buffer_size;
 
     int vo_type;
 
@@ -92,8 +95,9 @@ typedef struct Mpeg4DecContext {
     int16_t dpcm_macroblock[3][256];
 } Mpeg4DecContext;
 
-int ff_mpeg4_decode_picture_header(Mpeg4DecContext *ctx, GetBitContext *gb,
-                                   int header, int parse_only);
+int ff_mpeg4_decode_picture_header(MpegEncContext *s);
+int ff_mpeg4_parse_picture_header(Mpeg4DecContext *ctx, GetBitContext *gb,
+                                  int header, int parse_only);
 void ff_mpeg4_decode_studio(MpegEncContext *s, uint8_t *dest_y, uint8_t *dest_cb,
                             uint8_t *dest_cr, int block_size, int uvlinesize,
                             int dct_linesize, int dct_offset);
diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c
index 804c8095b2..73c513acbd 100644
--- a/libavcodec/mpegvideo.c
+++ b/libavcodec/mpegvideo.c
@@ -660,8 +660,6 @@ static void clear_context(MpegEncContext *s)
     memset(&s->sc, 0, sizeof(s->sc));
 
 
-    s->bitstream_buffer = NULL;
-    s->allocated_bitstream_buffer_size = 0;
     s->p_field_mv_table_base = NULL;
     for (int i = 0; i < 2; i++)
         for (int j = 0; j < 2; j++)
@@ -777,9 +775,6 @@ void ff_mpv_common_end(MpegEncContext *s)
     if (s->slice_context_count > 1)
         s->slice_context_count = 1;
 
-    av_freep(&s->bitstream_buffer);
-    s->allocated_bitstream_buffer_size = 0;
-
     ff_mpv_unref_picture(&s->last_pic);
     ff_mpv_unref_picture(&s->cur_pic);
     ff_mpv_unref_picture(&s->next_pic);
diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h
index eb71198190..48fc1d418e 100644
--- a/libavcodec/mpegvideo.h
+++ b/libavcodec/mpegvideo.h
@@ -395,9 +395,6 @@ typedef struct MpegEncContext {
 
     /* divx specific, used to workaround (many) bugs in divx5 */
     int divx_packed;
-    uint8_t *bitstream_buffer; //Divx 5.01 puts several frames in a single one, this is used to reorder them
-    int bitstream_buffer_size;
-    unsigned int allocated_bitstream_buffer_size;
 
     /* RV10 specific */
     int rv10_version; ///< RV10 version: 0 or 3
diff --git a/libavcodec/mpegvideo_dec.c b/libavcodec/mpegvideo_dec.c
index 8d4ba341d5..532d8cf5c1 100644
--- a/libavcodec/mpegvideo_dec.c
+++ b/libavcodec/mpegvideo_dec.c
@@ -97,8 +97,6 @@ int ff_mpeg_update_thread_context(AVCodecContext *dst,
         s->context_reinit        = 0;
         s->avctx                 = dst;
         s->private_ctx           = private_ctx;
-        s->bitstream_buffer      = NULL;
-        s->bitstream_buffer_size = s->allocated_bitstream_buffer_size = 0;
 
         if (s1->context_initialized) {
             if ((err = ff_mpv_common_init(s)) < 0)
@@ -439,7 +437,6 @@ void ff_mpeg_flush(AVCodecContext *avctx)
 
     s->mb_x = s->mb_y = 0;
 
-    s->bitstream_buffer_size = 0;
     s->pp_time = 0;
 }
 



More information about the ffmpeg-cvslog mailing list