From 915b7f85499a2e9ba90075d44e064539bd499668 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Tue, 25 Feb 2025 16:21:07 +0100 Subject: [PATCH 26/30] avcodec/mpeg4videodec: Avoid copying packed bitstream data Signed-off-by: Andreas Rheinhardt --- libavcodec/h263dec.c | 2 +- libavcodec/mpeg4videodec.c | 57 ++++++++++++++------------------------ libavcodec/mpeg4videodec.h | 7 ++--- 3 files changed, 25 insertions(+), 41 deletions(-) diff --git a/libavcodec/h263dec.c b/libavcodec/h263dec.c index 84895a93d4..9ccdd914ce 100644 --- a/libavcodec/h263dec.c +++ b/libavcodec/h263dec.c @@ -626,7 +626,7 @@ frame_end: ff_mpv_frame_end(s); if (CONFIG_MPEG4_DECODER && avctx->codec_id == AV_CODEC_ID_MPEG4) - ff_mpeg4_frame_end(avctx, buf, buf_size); + ff_mpeg4_frame_end(avctx, avpkt); av_assert1(s->pict_type == s->cur_pic.ptr->f->pict_type); if (s->pict_type == AV_PICTURE_TYPE_B || s->low_delay) { diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c index e2ae09125a..eace43b4cb 100644 --- a/libavcodec/mpeg4videodec.c +++ b/libavcodec/mpeg4videodec.c @@ -25,7 +25,6 @@ #include "config_components.h" #include "libavutil/internal.h" -#include "libavutil/mem.h" #include "libavutil/opt.h" #include "libavutil/thread.h" #include "codec_internal.h" @@ -3626,9 +3625,9 @@ int ff_mpeg4_decode_picture_header(MpegEncContext *s) { Mpeg4DecContext *const ctx = (Mpeg4DecContext*)s; - if (ctx->bitstream_buffer_size) { + if (ctx->bitstream_buffer) { int buf_size = get_bits_left(&s->gb) / 8U; - int bitstream_buffer_size = ctx->bitstream_buffer_size; + int bitstream_buffer_size = ctx->bitstream_buffer->size; const uint8_t *buf = s->gb.buffer; if (s->divx_packed) { @@ -3642,31 +3641,33 @@ int ff_mpeg4_decode_picture_header(MpegEncContext *s) } } } - ctx->bitstream_buffer_size = 0; + 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, + int ret = init_get_bits8(&s->gb, ctx->bitstream_buffer->data, bitstream_buffer_size); if (ret < 0) return ret; - } + } else + av_buffer_unref(&ctx->bitstream_buffer); } 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) +int ff_mpeg4_frame_end(AVCodecContext *avctx, const AVPacket *pkt) { Mpeg4DecContext *ctx = avctx->priv_data; MpegEncContext *s = &ctx->m; + int ret; - av_assert1(ctx->bitstream_buffer_size == 0); + av_assert1(!ctx->bitstream_buffer || !ctx->bitstream_buffer->size); /* 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 == ctx->bitstream_buffer ? 0 : (get_bits_count(&s->gb) >> 3); + int current_pos = ctx->bitstream_buffer && s->gb.buffer == ctx->bitstream_buffer->data ? 0 : (get_bits_count(&s->gb) >> 3); int startcode_found = 0; + uint8_t *buf = pkt->data; + int buf_size = pkt->size; if (buf_size - current_pos > 7) { @@ -3689,16 +3690,12 @@ 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(&ctx->bitstream_buffer, - &ctx->allocated_bitstream_buffer_size, - buf_size - current_pos); - if (!ctx->bitstream_buffer) { - ctx->bitstream_buffer_size = 0; - return AVERROR(ENOMEM); - } - memcpy(ctx->bitstream_buffer, buf + current_pos, - buf_size - current_pos); - ctx->bitstream_buffer_size = buf_size - current_pos; + ret = av_buffer_replace(&ctx->bitstream_buffer, pkt->buf); + if (ret < 0) + return ret; + + ctx->bitstream_buffer->data = buf + current_pos; + ctx->bitstream_buffer->size = buf_size - current_pos; } } @@ -3750,18 +3747,7 @@ 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->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->bitstream_buffer_size = s1->bitstream_buffer_size; - memcpy(s->bitstream_buffer, s1->bitstream_buffer, - s1->bitstream_buffer_size); - } + ret = av_buffer_replace(&s->bitstream_buffer, s1->bitstream_buffer); if (!init && s1->xvid_build >= 0) ff_xvid_idct_init(&s->m.idsp, dst); @@ -3870,7 +3856,7 @@ static av_cold void mpeg4_flush(AVCodecContext *avctx) { Mpeg4DecContext *const ctx = avctx->priv_data; - ctx->bitstream_buffer_size = 0; + av_buffer_unref(&ctx->bitstream_buffer); ff_mpeg_flush(avctx); } @@ -3878,8 +3864,7 @@ static av_cold int mpeg4_close(AVCodecContext *avctx) { Mpeg4DecContext *const ctx = avctx->priv_data; - ctx->bitstream_buffer_size = 0; - av_freep(&ctx->bitstream_buffer); + av_buffer_unref(&ctx->bitstream_buffer); return ff_mpv_decode_close(avctx); } diff --git a/libavcodec/mpeg4videodec.h b/libavcodec/mpeg4videodec.h index c4f6897c73..bb14d24c88 100644 --- a/libavcodec/mpeg4videodec.h +++ b/libavcodec/mpeg4videodec.h @@ -70,9 +70,8 @@ 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; + /// Divx 5.01 puts several frames in a single one, this is used to reorder them + AVBufferRef *bitstream_buffer; int vo_type; @@ -110,7 +109,7 @@ int ff_mpeg4_decode_studio_slice_header(Mpeg4DecContext *ctx); int ff_mpeg4_workaround_bugs(AVCodecContext *avctx); void ff_mpeg4_pred_ac(MpegEncContext *s, int16_t *block, int n, int dir); -int ff_mpeg4_frame_end(AVCodecContext *avctx, const uint8_t *buf, int buf_size); +int ff_mpeg4_frame_end(AVCodecContext *avctx, const AVPacket *pkt); #endif -- 2.45.2