From 11dffbe1dac97a475d36706bd65a469342ba5793 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 12 Dec 2003 21:30:47 +0000 Subject: [PATCH] stuffing to stay above min_bitrate Originally committed as revision 2602 to svn://svn.ffmpeg.org/ffmpeg/trunk --- libavcodec/mpegvideo.c | 28 ++++++++++++++++++++++++++-- libavcodec/mpegvideo.h | 1 + libavcodec/ratecontrol.c | 20 +++++++++++++------- 3 files changed, 40 insertions(+), 9 deletions(-) diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index 4774709486..0259c4c8bf 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -1715,7 +1715,7 @@ int MPV_encode_picture(AVCodecContext *avctx, { MpegEncContext *s = avctx->priv_data; AVFrame *pic_arg = data; - int i; + int i, stuffing_count; if(avctx->pix_fmt != PIX_FMT_YUV420P){ av_log(avctx, AV_LOG_ERROR, "this codec supports only YUV420P\n"); @@ -1767,11 +1767,35 @@ int MPV_encode_picture(AVCodecContext *avctx, flush_put_bits(&s->pb); s->frame_bits = (pbBufPtr(&s->pb) - s->pb.buf) * 8; + + stuffing_count= ff_vbv_update(s, s->frame_bits); + if(stuffing_count){ + switch(s->codec_id){ + case CODEC_ID_MPEG1VIDEO: + case CODEC_ID_MPEG2VIDEO: + while(stuffing_count--){ + put_bits(&s->pb, 8, 0); + } + break; + case CODEC_ID_MPEG4: + put_bits(&s->pb, 16, 0); + put_bits(&s->pb, 16, 0x1C3); + stuffing_count -= 4; + while(stuffing_count--){ + put_bits(&s->pb, 8, 0xFF); + } + break; + default: + av_log(s->avctx, AV_LOG_ERROR, "vbv buffer overflow\n"); + } + flush_put_bits(&s->pb); + s->frame_bits = (pbBufPtr(&s->pb) - s->pb.buf) * 8; + } s->total_bits += s->frame_bits; avctx->frame_bits = s->frame_bits; - return pbBufPtr(&s->pb) - s->pb.buf; + return s->frame_bits/8; } #endif //CONFIG_ENCODERS diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index c47159d77c..f7d89f5eba 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -897,6 +897,7 @@ double ff_eval(char *s, double *const_value, const char **const_name, double (**func1)(void *, double), const char **func1_name, double (**func2)(void *, double, double), char **func2_name, void *opaque); +int ff_vbv_update(MpegEncContext *s, int frame_size); #endif /* AVCODEC_MPEGVIDEO_H */ diff --git a/libavcodec/ratecontrol.c b/libavcodec/ratecontrol.c index d86c5aed79..37d173f8ac 100644 --- a/libavcodec/ratecontrol.c +++ b/libavcodec/ratecontrol.c @@ -195,7 +195,7 @@ static inline double bits2qp(RateControlEntry *rce, double bits){ return rce->qscale * (double)(rce->i_tex_bits + rce->p_tex_bits+1)/ bits; } -static void update_rc_buffer(MpegEncContext *s, int frame_size){ +int ff_vbv_update(MpegEncContext *s, int frame_size){ RateControlContext *rcc= &s->rc_context; const double fps= (double)s->avctx->frame_rate / (double)s->avctx->frame_rate_base; const double buffer_size= s->avctx->rc_buffer_size; @@ -216,10 +216,19 @@ static void update_rc_buffer(MpegEncContext *s, int frame_size){ rcc->buffer_index += clip(left, min_rate, max_rate); if(rcc->buffer_index > s->avctx->rc_buffer_size){ - av_log(s->avctx, AV_LOG_ERROR, "rc buffer overflow\n"); - rcc->buffer_index= s->avctx->rc_buffer_size; + int stuffing= ceil((rcc->buffer_index - s->avctx->rc_buffer_size)/8); + + if(stuffing < 4 && s->codec_id == CODEC_ID_MPEG4) + stuffing=4; + rcc->buffer_index -= 8*stuffing; + + if(s->avctx->debug & FF_DEBUG_RC) + av_log(s->avctx, AV_LOG_DEBUG, "stuffing %d bytes\n", stuffing); + + return stuffing; } } + return 0; } /** @@ -619,9 +628,6 @@ float ff_rate_estimate_qscale(MpegEncContext *s) rce->b_code = s->b_code; rce->misc_bits= 1; - if(picture_number>0) - update_rc_buffer(s, s->frame_bits); - bits= predict_size(&rcc->pred[pict_type], rce->qscale, sqrt(var)); if(pict_type== I_TYPE){ rce->i_count = s->mb_num; @@ -814,7 +820,7 @@ static int init_pass2(MpegEncContext *s) rce->new_qscale= modify_qscale(s, rce, blured_qscale[i], i); bits= qp2bits(rce, rce->new_qscale) + rce->mv_bits + rce->misc_bits; //printf("%d %f\n", rce->new_bits, blured_qscale[i]); - update_rc_buffer(s, bits); + bits += 8*ff_vbv_update(s, bits); rce->expected_bits= expected_bits; expected_bits += bits;