You've already forked FFmpeg
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:
@ -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
|
||||
// s->gb might be overridden in ff_mpeg4_decode_picture_header() below.
|
||||
ret = init_get_bits8(&s->gb, buf, buf_size);
|
||||
|
||||
s->bitstream_buffer_size = 0;
|
||||
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);
|
||||
|
@ -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);
|
||||
|
@ -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,7 +3464,7 @@ 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 ff_mpeg4_parse_picture_header(Mpeg4DecContext *ctx, GetBitContext *gb,
|
||||
int header, int parse_only)
|
||||
{
|
||||
MpegEncContext *s = &ctx->m;
|
||||
@ -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),
|
||||
|
@ -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,7 +95,8 @@ typedef struct Mpeg4DecContext {
|
||||
int16_t dpcm_macroblock[3][256];
|
||||
} Mpeg4DecContext;
|
||||
|
||||
int ff_mpeg4_decode_picture_header(Mpeg4DecContext *ctx, GetBitContext *gb,
|
||||
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,
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user