1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2025-08-04 22:03:09 +02:00

avcodec/mpeg4videodec: Avoid copying packed bitstream data

This is possible because the packet is reference-counted
and because we never combine the data from several packets.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
This commit is contained in:
Andreas Rheinhardt
2025-02-25 16:21:07 +01:00
parent e3ebc1073e
commit 4f2becc2dc
3 changed files with 25 additions and 41 deletions

View File

@ -626,7 +626,7 @@ frame_end:
ff_mpv_frame_end(s); ff_mpv_frame_end(s);
if (CONFIG_MPEG4_DECODER && avctx->codec_id == AV_CODEC_ID_MPEG4) 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); av_assert1(s->pict_type == s->cur_pic.ptr->f->pict_type);
if (s->pict_type == AV_PICTURE_TYPE_B || s->low_delay) { if (s->pict_type == AV_PICTURE_TYPE_B || s->low_delay) {

View File

@ -25,7 +25,6 @@
#include "config_components.h" #include "config_components.h"
#include "libavutil/internal.h" #include "libavutil/internal.h"
#include "libavutil/mem.h"
#include "libavutil/opt.h" #include "libavutil/opt.h"
#include "libavutil/thread.h" #include "libavutil/thread.h"
#include "codec_internal.h" #include "codec_internal.h"
@ -3626,9 +3625,9 @@ int ff_mpeg4_decode_picture_header(MpegEncContext *s)
{ {
Mpeg4DecContext *const ctx = (Mpeg4DecContext*)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 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; const uint8_t *buf = s->gb.buffer;
if (s->divx_packed) { 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 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); bitstream_buffer_size);
if (ret < 0) if (ret < 0)
return ret; return ret;
} } else
av_buffer_unref(&ctx->bitstream_buffer);
} }
return ff_mpeg4_parse_picture_header(ctx, &s->gb, 0, 0); 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; Mpeg4DecContext *ctx = avctx->priv_data;
MpegEncContext *s = &ctx->m; 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 */ /* 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) { 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; int startcode_found = 0;
uint8_t *buf = pkt->data;
int buf_size = pkt->size;
if (buf_size - current_pos > 7) { 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"); "Consider using the mpeg4_unpack_bframes bitstream filter without encoding but stream copy to fix it.\n");
ctx->showed_packed_warning = 1; ctx->showed_packed_warning = 1;
} }
av_fast_padded_malloc(&ctx->bitstream_buffer, ret = av_buffer_replace(&ctx->bitstream_buffer, pkt->buf);
&ctx->allocated_bitstream_buffer_size, if (ret < 0)
buf_size - current_pos); return ret;
if (!ctx->bitstream_buffer) {
ctx->bitstream_buffer_size = 0; ctx->bitstream_buffer->data = buf + current_pos;
return AVERROR(ENOMEM); ctx->bitstream_buffer->size = buf_size - current_pos;
}
memcpy(ctx->bitstream_buffer, buf + current_pos,
buf_size - 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_shift, s1->sprite_shift, sizeof(s1->sprite_shift));
memcpy(s->sprite_traj, s1->sprite_traj, sizeof(s1->sprite_traj)); memcpy(s->sprite_traj, s1->sprite_traj, sizeof(s1->sprite_traj));
if (s1->bitstream_buffer) { ret = av_buffer_replace(&s->bitstream_buffer, 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);
}
if (!init && s1->xvid_build >= 0) if (!init && s1->xvid_build >= 0)
ff_xvid_idct_init(&s->m.idsp, dst); 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; Mpeg4DecContext *const ctx = avctx->priv_data;
ctx->bitstream_buffer_size = 0; av_buffer_unref(&ctx->bitstream_buffer);
ff_mpeg_flush(avctx); ff_mpeg_flush(avctx);
} }
@ -3878,8 +3864,7 @@ static av_cold int mpeg4_close(AVCodecContext *avctx)
{ {
Mpeg4DecContext *const ctx = avctx->priv_data; Mpeg4DecContext *const ctx = avctx->priv_data;
ctx->bitstream_buffer_size = 0; av_buffer_unref(&ctx->bitstream_buffer);
av_freep(&ctx->bitstream_buffer);
return ff_mpv_decode_close(avctx); return ff_mpv_decode_close(avctx);
} }

View File

@ -70,9 +70,8 @@ typedef struct Mpeg4DecContext {
int divx_build; int divx_build;
int xvid_build; int xvid_build;
int lavc_build; int lavc_build;
uint8_t *bitstream_buffer; //Divx 5.01 puts several frames in a single one, this is used to reorder them /// Divx 5.01 puts several frames in a single one, this is used to reorder them
int bitstream_buffer_size; AVBufferRef *bitstream_buffer;
unsigned int allocated_bitstream_buffer_size;
int vo_type; int vo_type;
@ -110,7 +109,7 @@ int ff_mpeg4_decode_studio_slice_header(Mpeg4DecContext *ctx);
int ff_mpeg4_workaround_bugs(AVCodecContext *avctx); int ff_mpeg4_workaround_bugs(AVCodecContext *avctx);
void ff_mpeg4_pred_ac(MpegEncContext *s, int16_t *block, int n, void ff_mpeg4_pred_ac(MpegEncContext *s, int16_t *block, int n,
int dir); 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 #endif