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

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@outlook.com>
This commit is contained in:
Andreas Rheinhardt
2025-02-25 00:48:08 +01:00
parent e4470a8e30
commit e3ebc1073e
7 changed files with 85 additions and 58 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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),

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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;
}