[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