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:
|
retry:
|
||||||
if (s->divx_packed && s->bitstream_buffer_size) {
|
// s->gb might be overridden in ff_mpeg4_decode_picture_header() below.
|
||||||
int i;
|
ret = init_get_bits8(&s->gb, buf, buf_size);
|
||||||
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;
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -480,7 +462,7 @@ retry:
|
|||||||
ret = ff_msmpeg4_decode_picture_header(s);
|
ret = ff_msmpeg4_decode_picture_header(s);
|
||||||
#endif
|
#endif
|
||||||
} else if (CONFIG_MPEG4_DECODER && avctx->codec_id == AV_CODEC_ID_MPEG4) {
|
} 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);
|
s->skipped_last_frame = (ret == FRAME_SKIPPED);
|
||||||
} else if (CONFIG_H263I_DECODER && s->codec_id == AV_CODEC_ID_H263I) {
|
} else if (CONFIG_H263I_DECODER && s->codec_id == AV_CODEC_ID_H263I) {
|
||||||
ret = ff_intel_h263_decode_picture_header(s);
|
ret = ff_intel_h263_decode_picture_header(s);
|
||||||
@ -631,7 +613,6 @@ retry:
|
|||||||
ff_msmpeg4_decode_ext_header(s, buf_size) < 0)
|
ff_msmpeg4_decode_ext_header(s, buf_size) < 0)
|
||||||
s->er.error_status_table[s->mb_num - 1] = ER_MB_ERROR;
|
s->er.error_status_table[s->mb_num - 1] = ER_MB_ERROR;
|
||||||
|
|
||||||
av_assert1(s->bitstream_buffer_size == 0);
|
|
||||||
frame_end:
|
frame_end:
|
||||||
if (!s->studio_profile)
|
if (!s->studio_profile)
|
||||||
ff_er_frame_end(&s->er, NULL);
|
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) {
|
if (avctx->extradata_size && pc->first_picture) {
|
||||||
init_get_bits(gb, avctx->extradata, avctx->extradata_size * 8);
|
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)
|
if (ret < 0)
|
||||||
av_log(avctx, AV_LOG_WARNING, "Failed to parse extradata\n");
|
av_log(avctx, AV_LOG_WARNING, "Failed to parse extradata\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
init_get_bits(gb, buf, 8 * buf_size);
|
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 ||
|
if (s->width && (!avctx->width || !avctx->height ||
|
||||||
!avctx->coded_width || !avctx->coded_height)) {
|
!avctx->coded_width || !avctx->coded_height)) {
|
||||||
ret = ff_set_dimensions(avctx, s->width, s->height);
|
ret = ff_set_dimensions(avctx, s->width, s->height);
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#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"
|
||||||
@ -3463,8 +3464,8 @@ static int decode_studiovisualobject(Mpeg4DecContext *ctx, GetBitContext *gb)
|
|||||||
* FRAME_SKIPPED if a not coded VOP is found
|
* FRAME_SKIPPED if a not coded VOP is found
|
||||||
* 0 else
|
* 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)
|
int header, int parse_only)
|
||||||
{
|
{
|
||||||
MpegEncContext *s = &ctx->m;
|
MpegEncContext *s = &ctx->m;
|
||||||
unsigned startcode, v;
|
unsigned startcode, v;
|
||||||
@ -3621,16 +3622,50 @@ end:
|
|||||||
return decode_vop_header(ctx, gb, parse_only);
|
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)
|
int ff_mpeg4_frame_end(AVCodecContext *avctx, const uint8_t *buf, int buf_size)
|
||||||
{
|
{
|
||||||
Mpeg4DecContext *ctx = avctx->priv_data;
|
Mpeg4DecContext *ctx = avctx->priv_data;
|
||||||
MpegEncContext *s = &ctx->m;
|
MpegEncContext *s = &ctx->m;
|
||||||
|
|
||||||
|
av_assert1(ctx->bitstream_buffer_size == 0);
|
||||||
|
|
||||||
/* divx 5.01+ bitstream reorder stuff */
|
/* divx 5.01+ bitstream reorder stuff */
|
||||||
/* Since this clobbers the input buffer and hwaccel codecs still need the
|
/* Since this clobbers the input buffer and hwaccel codecs still need the
|
||||||
* data during hwaccel->end_frame we should not do this any earlier */
|
* 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 == 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;
|
int startcode_found = 0;
|
||||||
|
|
||||||
if (buf_size - current_pos > 7) {
|
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");
|
"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(&s->bitstream_buffer,
|
av_fast_padded_malloc(&ctx->bitstream_buffer,
|
||||||
&s->allocated_bitstream_buffer_size,
|
&ctx->allocated_bitstream_buffer_size,
|
||||||
buf_size - current_pos);
|
buf_size - current_pos);
|
||||||
if (!s->bitstream_buffer) {
|
if (!ctx->bitstream_buffer) {
|
||||||
s->bitstream_buffer_size = 0;
|
ctx->bitstream_buffer_size = 0;
|
||||||
return AVERROR(ENOMEM);
|
return AVERROR(ENOMEM);
|
||||||
}
|
}
|
||||||
memcpy(s->bitstream_buffer, buf + current_pos,
|
memcpy(ctx->bitstream_buffer, buf + current_pos,
|
||||||
buf_size - 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_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->m.bitstream_buffer) {
|
if (s1->bitstream_buffer) {
|
||||||
av_fast_padded_malloc(&s->m.bitstream_buffer,
|
av_fast_padded_malloc(&s->bitstream_buffer,
|
||||||
&s->m.allocated_bitstream_buffer_size,
|
&s->allocated_bitstream_buffer_size,
|
||||||
s1->m.bitstream_buffer_size);
|
s1->bitstream_buffer_size);
|
||||||
if (!s->m.bitstream_buffer) {
|
if (!s->bitstream_buffer) {
|
||||||
s->m.bitstream_buffer_size = 0;
|
s->bitstream_buffer_size = 0;
|
||||||
return AVERROR(ENOMEM);
|
return AVERROR(ENOMEM);
|
||||||
}
|
}
|
||||||
s->m.bitstream_buffer_size = s1->m.bitstream_buffer_size;
|
s->bitstream_buffer_size = s1->bitstream_buffer_size;
|
||||||
memcpy(s->m.bitstream_buffer, s1->m.bitstream_buffer,
|
memcpy(s->bitstream_buffer, s1->bitstream_buffer,
|
||||||
s1->m.bitstream_buffer_size);
|
s1->bitstream_buffer_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!init && s1->xvid_build >= 0)
|
if (!init && s1->xvid_build >= 0)
|
||||||
@ -3825,12 +3860,30 @@ static av_cold int decode_init(AVCodecContext *avctx)
|
|||||||
GetBitContext gb;
|
GetBitContext gb;
|
||||||
|
|
||||||
if (init_get_bits8(&gb, avctx->extradata, avctx->extradata_size) >= 0)
|
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;
|
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 OFFSET(x) offsetof(MpegEncContext, x)
|
||||||
#define FLAGS AV_OPT_FLAG_EXPORT | AV_OPT_FLAG_READONLY
|
#define FLAGS AV_OPT_FLAG_EXPORT | AV_OPT_FLAG_READONLY
|
||||||
static const AVOption mpeg4_options[] = {
|
static const AVOption mpeg4_options[] = {
|
||||||
@ -3854,12 +3907,12 @@ const FFCodec ff_mpeg4_decoder = {
|
|||||||
.priv_data_size = sizeof(Mpeg4DecContext),
|
.priv_data_size = sizeof(Mpeg4DecContext),
|
||||||
.init = decode_init,
|
.init = decode_init,
|
||||||
FF_CODEC_DECODE_CB(ff_h263_decode_frame),
|
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 |
|
.p.capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1 |
|
||||||
AV_CODEC_CAP_DELAY | AV_CODEC_CAP_FRAME_THREADS,
|
AV_CODEC_CAP_DELAY | AV_CODEC_CAP_FRAME_THREADS,
|
||||||
.caps_internal = FF_CODEC_CAP_INIT_CLEANUP |
|
.caps_internal = FF_CODEC_CAP_INIT_CLEANUP |
|
||||||
FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM,
|
FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM,
|
||||||
.flush = ff_mpeg_flush,
|
.flush = mpeg4_flush,
|
||||||
.p.max_lowres = 3,
|
.p.max_lowres = 3,
|
||||||
.p.profiles = NULL_IF_CONFIG_SMALL(ff_mpeg4_video_profiles),
|
.p.profiles = NULL_IF_CONFIG_SMALL(ff_mpeg4_video_profiles),
|
||||||
UPDATE_THREAD_CONTEXT(mpeg4_update_thread_context),
|
UPDATE_THREAD_CONTEXT(mpeg4_update_thread_context),
|
||||||
|
@ -70,6 +70,9 @@ 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
|
||||||
|
int bitstream_buffer_size;
|
||||||
|
unsigned int allocated_bitstream_buffer_size;
|
||||||
|
|
||||||
int vo_type;
|
int vo_type;
|
||||||
|
|
||||||
@ -92,8 +95,9 @@ typedef struct Mpeg4DecContext {
|
|||||||
int16_t dpcm_macroblock[3][256];
|
int16_t dpcm_macroblock[3][256];
|
||||||
} Mpeg4DecContext;
|
} Mpeg4DecContext;
|
||||||
|
|
||||||
int ff_mpeg4_decode_picture_header(Mpeg4DecContext *ctx, GetBitContext *gb,
|
int ff_mpeg4_decode_picture_header(MpegEncContext *s);
|
||||||
int header, int parse_only);
|
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,
|
void ff_mpeg4_decode_studio(MpegEncContext *s, uint8_t *dest_y, uint8_t *dest_cb,
|
||||||
uint8_t *dest_cr, int block_size, int uvlinesize,
|
uint8_t *dest_cr, int block_size, int uvlinesize,
|
||||||
int dct_linesize, int dct_offset);
|
int dct_linesize, int dct_offset);
|
||||||
|
@ -660,8 +660,6 @@ static void clear_context(MpegEncContext *s)
|
|||||||
memset(&s->sc, 0, sizeof(s->sc));
|
memset(&s->sc, 0, sizeof(s->sc));
|
||||||
|
|
||||||
|
|
||||||
s->bitstream_buffer = NULL;
|
|
||||||
s->allocated_bitstream_buffer_size = 0;
|
|
||||||
s->p_field_mv_table_base = NULL;
|
s->p_field_mv_table_base = NULL;
|
||||||
for (int i = 0; i < 2; i++)
|
for (int i = 0; i < 2; i++)
|
||||||
for (int j = 0; j < 2; j++)
|
for (int j = 0; j < 2; j++)
|
||||||
@ -777,9 +775,6 @@ void ff_mpv_common_end(MpegEncContext *s)
|
|||||||
if (s->slice_context_count > 1)
|
if (s->slice_context_count > 1)
|
||||||
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->last_pic);
|
||||||
ff_mpv_unref_picture(&s->cur_pic);
|
ff_mpv_unref_picture(&s->cur_pic);
|
||||||
ff_mpv_unref_picture(&s->next_pic);
|
ff_mpv_unref_picture(&s->next_pic);
|
||||||
|
@ -395,9 +395,6 @@ typedef struct MpegEncContext {
|
|||||||
|
|
||||||
/* divx specific, used to workaround (many) bugs in divx5 */
|
/* divx specific, used to workaround (many) bugs in divx5 */
|
||||||
int divx_packed;
|
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 */
|
/* RV10 specific */
|
||||||
int rv10_version; ///< RV10 version: 0 or 3
|
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->context_reinit = 0;
|
||||||
s->avctx = dst;
|
s->avctx = dst;
|
||||||
s->private_ctx = private_ctx;
|
s->private_ctx = private_ctx;
|
||||||
s->bitstream_buffer = NULL;
|
|
||||||
s->bitstream_buffer_size = s->allocated_bitstream_buffer_size = 0;
|
|
||||||
|
|
||||||
if (s1->context_initialized) {
|
if (s1->context_initialized) {
|
||||||
if ((err = ff_mpv_common_init(s)) < 0)
|
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->mb_x = s->mb_y = 0;
|
||||||
|
|
||||||
s->bitstream_buffer_size = 0;
|
|
||||||
s->pp_time = 0;
|
s->pp_time = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user