[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