[FFmpeg-cvslog] avcodec/mpegvideo: Allocate ac_val jointly

Andreas Rheinhardt git at videolan.org
Sat Jun 21 23:21:19 EEST 2025


ffmpeg | branch: master | Andreas Rheinhardt <andreas.rheinhardt at outlook.com> | Fri Jun 13 06:10:27 2025 +0200| [c4ebe55f94ff9e55bada7dbe9ff2fb9e75d85800] | committer: Andreas Rheinhardt

avcodec/mpegvideo: Allocate ac_val jointly

They are currently allocated separately per slice; allocating them
jointly allows to avoid saving them in ff_update_duplicate_context().

The way it is done also avoids allocating ac_val for encoders that
don't need it (e.g. H.263 or H.263+ with AIC).

This entailed moving setting nb_slices to ff_mpv_init_context_frame()
which is called from ff_mpv_common_frame_size_change(). The resultant
nb_slices will always be one when called from a decoder using
ff_mpv_common_frame_size_change().

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

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

 libavcodec/mpegvideo.c     | 60 ++++++++++++++++++++++------------------------
 libavcodec/mpegvideo_enc.c | 36 ++++++++++++++++++----------
 2 files changed, 52 insertions(+), 44 deletions(-)

diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c
index e528935f68..ae0c847aa4 100644
--- a/libavcodec/mpegvideo.c
+++ b/libavcodec/mpegvideo.c
@@ -120,18 +120,6 @@ static av_cold int init_duplicate_context(MpegEncContext *s)
         return AVERROR(ENOMEM);
     s->block = s->blocks[0];
 
-    if (s->out_format == FMT_H263) {
-        int mb_height = s->msmpeg4_version == MSMP4_VC1 ?
-                            FFALIGN(s->mb_height, 2) : s->mb_height;
-        int y_size = s->b8_stride * (2 * mb_height + 1);
-        int c_size = s->mb_stride * (mb_height + 1);
-        int yc_size = y_size + 2 * c_size;
-        /* ac values */
-        if (!FF_ALLOCZ_TYPED_ARRAY(s->ac_val_base,  yc_size))
-            return AVERROR(ENOMEM);
-        s->ac_val = s->ac_val_base + s->b8_stride + 1;
-    }
-
     return 0;
 }
 
@@ -171,7 +159,6 @@ static av_cold void free_duplicate_context(MpegEncContext *s)
     s->sc.linesize = 0;
 
     av_freep(&s->blocks);
-    av_freep(&s->ac_val_base);
     s->block = NULL;
 }
 
@@ -192,7 +179,6 @@ static void backup_duplicate_context(MpegEncContext *bak, MpegEncContext *src)
     COPY(block);
     COPY(start_mb_y);
     COPY(end_mb_y);
-    COPY(ac_val_base);
     COPY(ac_val);
 #undef COPY
 }
@@ -245,15 +231,34 @@ static av_cold void free_buffer_pools(BufferPoolContext *pools)
 
 av_cold int ff_mpv_init_context_frame(MpegEncContext *s)
 {
+    int nb_slices = (HAVE_THREADS &&
+                     s->avctx->active_thread_type & FF_THREAD_SLICE) ?
+                    s->avctx->thread_count : 1;
     BufferPoolContext *const pools = &s->buffer_pools;
     int y_size, c_size, yc_size, i, mb_array_size, mv_table_size, x, y;
     int mb_height;
 
+    if (s->encoding && s->avctx->slices)
+        nb_slices = s->avctx->slices;
+
     if (s->codec_id == AV_CODEC_ID_MPEG2VIDEO && !s->progressive_sequence)
         s->mb_height = (s->height + 31) / 32 * 2;
     else
         s->mb_height = (s->height + 15) / 16;
 
+    if (nb_slices > MAX_THREADS || (nb_slices > s->mb_height && s->mb_height)) {
+        int max_slices;
+        if (s->mb_height)
+            max_slices = FFMIN(MAX_THREADS, s->mb_height);
+        else
+            max_slices = MAX_THREADS;
+        av_log(s->avctx, AV_LOG_WARNING, "too many threads/slices (%d),"
+               " reducing to %d\n", nb_slices, max_slices);
+        nb_slices = max_slices;
+    }
+
+    s->slice_context_count = nb_slices;
+
     /* VC-1 can change from being progressive to interlaced on a per-frame
      * basis. We therefore allocate certain buffers so big that they work
      * in both instances. */
@@ -332,6 +337,14 @@ av_cold int ff_mpv_init_context_frame(MpegEncContext *s)
     }
 
     if (s->h263_pred || s->h263_aic || !s->encoding) {
+        size_t allslice_yc_size = yc_size * (s->encoding ? nb_slices : 1);
+        if (s->out_format == FMT_H263) {
+            /* ac values */
+            if (!FF_ALLOCZ_TYPED_ARRAY(s->ac_val_base, allslice_yc_size))
+                return AVERROR(ENOMEM);
+            s->ac_val = s->ac_val_base + s->b8_stride + 1;
+        }
+
         /* dc values */
         // MN: we need these for error resilience of intra-frames
         // Allocating them unconditionally for decoders also means
@@ -381,14 +394,8 @@ av_cold int ff_mpv_init_context_frame(MpegEncContext *s)
  */
 av_cold int ff_mpv_common_init(MpegEncContext *s)
 {
-    int nb_slices = (HAVE_THREADS &&
-                     s->avctx->active_thread_type & FF_THREAD_SLICE) ?
-                    s->avctx->thread_count : 1;
     int ret;
 
-    if (s->encoding && s->avctx->slices)
-        nb_slices = s->avctx->slices;
-
     if (s->avctx->pix_fmt == AV_PIX_FMT_NONE) {
         av_log(s->avctx, AV_LOG_ERROR,
                "decoding to AV_PIX_FMT_NONE is not supported.\n");
@@ -411,20 +418,8 @@ av_cold int ff_mpv_common_init(MpegEncContext *s)
     if ((ret = ff_mpv_init_context_frame(s)))
         goto fail;
 
-    if (nb_slices > MAX_THREADS || (nb_slices > s->mb_height && s->mb_height)) {
-        int max_slices;
-        if (s->mb_height)
-            max_slices = FFMIN(MAX_THREADS, s->mb_height);
-        else
-            max_slices = MAX_THREADS;
-        av_log(s->avctx, AV_LOG_WARNING, "too many threads/slices (%d),"
-               " reducing to %d\n", nb_slices, max_slices);
-        nb_slices = max_slices;
-    }
-
     s->context_initialized = 1;
     s->thread_context[0]   = s;
-    s->slice_context_count = nb_slices;
 
 //     if (s->width && s->height) {
     if (!s->encoding) {
@@ -450,6 +445,7 @@ av_cold void ff_mpv_free_context_frame(MpegEncContext *s)
         for (int j = 0; j < 2; j++)
             s->p_field_mv_table[i][j] = NULL;
 
+    av_freep(&s->ac_val_base);
     av_freep(&s->dc_val_base);
     av_freep(&s->coded_block_base);
     av_freep(&s->mbintra_table);
diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c
index 870cf7f5a7..3bec6b57cf 100644
--- a/libavcodec/mpegvideo_enc.c
+++ b/libavcodec/mpegvideo_enc.c
@@ -518,24 +518,36 @@ static av_cold int init_slice_buffers(MPVMainEncContext *const m)
     static_assert(DCT_ERROR_SIZE * MAX_THREADS + ALIGN - 1 <= SIZE_MAX,
                   "Need checks for potential overflow.");
     unsigned nb_slices = s->c.slice_context_count;
+    char *dct_error = NULL;
 
-    if (!m->noise_reduction)
-        return 0;
+    if (m->noise_reduction) {
+        if (!FF_ALLOCZ_TYPED_ARRAY(s->dct_offset, 2))
+            return AVERROR(ENOMEM);
+        dct_error = av_mallocz(ALIGN - 1 + nb_slices * DCT_ERROR_SIZE);
+        if (!dct_error)
+            return AVERROR(ENOMEM);
+        m->dct_error_sum_base = dct_error;
+        dct_error += FFALIGN((uintptr_t)dct_error, ALIGN) - (uintptr_t)dct_error;
+    }
 
-    if (!FF_ALLOCZ_TYPED_ARRAY(s->dct_offset, 2))
-        return AVERROR(ENOMEM);
-    char *dct_error = av_mallocz(ALIGN - 1 + nb_slices * DCT_ERROR_SIZE);
-    if (!dct_error)
-        return AVERROR(ENOMEM);
-    m->dct_error_sum_base = dct_error;
-    dct_error += FFALIGN((uintptr_t)dct_error, ALIGN) - (uintptr_t)dct_error;
+    const int y_size  = s->c.b8_stride * (2 * s->c.mb_height + 1);
+    const int c_size  = s->c.mb_stride * (s->c.mb_height + 1);
+    const int yc_size = y_size + 2 * c_size;
+    ptrdiff_t offset = 0;
 
     for (unsigned i = 0; i < nb_slices; ++i) {
         MPVEncContext *const s2 = s->c.enc_contexts[i];
 
-        s2->dct_offset    = s->dct_offset;
-        s2->dct_error_sum = (void*)dct_error;
-        dct_error        += DCT_ERROR_SIZE;
+        if (dct_error) {
+            s2->dct_offset    = s->dct_offset;
+            s2->dct_error_sum = (void*)dct_error;
+            dct_error        += DCT_ERROR_SIZE;
+        }
+
+        if (s2->c.ac_val) {
+            s2->c.ac_val += offset;
+            offset       += yc_size;
+        }
     }
     return 0;
 }



More information about the ffmpeg-cvslog mailing list