aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2006-10-05 19:27:18 +0000
committerMichael Niedermayer <michaelni@gmx.at>2006-10-05 19:27:18 +0000
commit075060023d978975ed5328e269d6e20163e669d2 (patch)
tree6335d81f345000f08da9a02b299d7c2933658406
parente1931c59f6dcbc851c92af4a3f7932ac04b5358e (diff)
downloadffmpeg-075060023d978975ed5328e269d6e20163e669d2.tar.gz
fix buffer underflows by reencoding the current frame with a higher QP
Originally committed as revision 6565 to svn://svn.ffmpeg.org/ffmpeg/trunk
-rw-r--r--libavcodec/mpegvideo.c46
-rw-r--r--libavcodec/mpegvideo.h1
2 files changed, 39 insertions, 8 deletions
diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c
index 7314a0632d..cbdfb1475f 100644
--- a/libavcodec/mpegvideo.c
+++ b/libavcodec/mpegvideo.c
@@ -2139,7 +2139,10 @@ static int load_input_picture(MpegEncContext *s, AVFrame *pic_arg){
int w= s->width >>h_shift;
int h= s->height>>v_shift;
uint8_t *src= pic_arg->data[i];
- uint8_t *dst= pic->data[i] + INPLACE_OFFSET;
+ uint8_t *dst= pic->data[i];
+
+ if(!s->avctx->rc_buffer_size)
+ dst +=INPLACE_OFFSET;
if(src_stride==dst_stride)
memcpy(dst, src, src_stride*h);
@@ -2438,21 +2441,22 @@ no_output_pic:
copy_picture(&s->new_picture, s->reordered_input_picture[0]);
- if(s->reordered_input_picture[0]->type == FF_BUFFER_TYPE_SHARED){
+ if(s->reordered_input_picture[0]->type == FF_BUFFER_TYPE_SHARED || s->avctx->rc_buffer_size){
// input is a shared pix, so we can't modifiy it -> alloc a new one & ensure that the shared one is reuseable
int i= ff_find_unused_picture(s, 0);
Picture *pic= &s->picture[i];
+ pic->reference = s->reordered_input_picture[0]->reference;
+ alloc_picture(s, pic, 0);
+
/* mark us unused / free shared pic */
+ if(s->reordered_input_picture[0]->type == FF_BUFFER_TYPE_INTERNAL)
+ s->avctx->release_buffer(s->avctx, (AVFrame*)s->reordered_input_picture[0]);
for(i=0; i<4; i++)
s->reordered_input_picture[0]->data[i]= NULL;
s->reordered_input_picture[0]->type= 0;
- pic->reference = s->reordered_input_picture[0]->reference;
-
- alloc_picture(s, pic, 0);
-
copy_picture_attributes(s, (AVFrame*)pic, (AVFrame*)s->reordered_input_picture[0]);
s->current_picture_ptr= pic;
@@ -2506,7 +2510,7 @@ int MPV_encode_picture(AVCodecContext *avctx,
//emms_c();
//printf("qs:%f %f %d\n", s->new_picture.quality, s->current_picture.quality, s->qscale);
MPV_frame_start(s, avctx);
-
+vbv_retry:
if (encode_picture(s, s->picture_number) < 0)
return -1;
@@ -2525,6 +2529,28 @@ int MPV_encode_picture(AVCodecContext *avctx,
if (s->out_format == FMT_MJPEG)
mjpeg_picture_trailer(s);
+ if(avctx->rc_buffer_size){
+ RateControlContext *rcc= &s->rc_context;
+ int max_size= rcc->buffer_index/3;
+
+ if(put_bits_count(&s->pb) > max_size && s->qscale < s->avctx->qmax){
+ s->next_lambda= s->lambda*(s->qscale+1) / s->qscale;
+ s->mb_skipped = 0; //done in MPV_frame_start()
+ if(s->pict_type==P_TYPE){ //done in encode_picture() so we must undo it
+ if(s->flipflop_rounding || s->codec_id == CODEC_ID_H263P || s->codec_id == CODEC_ID_MPEG4)
+ s->no_rounding ^= 1;
+ }
+// av_log(NULL, AV_LOG_ERROR, "R:%d ", s->next_lambda);
+ for(i=0; i<avctx->thread_count; i++){
+ PutBitContext *pb= &s->thread_context[i]->pb;
+ init_put_bits(pb, pb->buf, pb->buf_end - pb->buf);
+ }
+ goto vbv_retry;
+ }
+
+ assert(s->avctx->rc_max_rate);
+ }
+
if(s->flags&CODEC_FLAG_PASS1)
ff_write_pass1_stats(s);
@@ -5469,7 +5495,11 @@ static void merge_context_after_encode(MpegEncContext *dst, MpegEncContext *src)
}
static int estimate_qp(MpegEncContext *s, int dry_run){
- if (!s->fixed_qscale) {
+ if (s->next_lambda){
+ s->current_picture_ptr->quality=
+ s->current_picture.quality = s->next_lambda;
+ if(!dry_run) s->next_lambda= 0;
+ } else if (!s->fixed_qscale) {
s->current_picture_ptr->quality=
s->current_picture.quality = ff_rate_estimate_qscale(s, dry_run);
if (s->current_picture.quality < 0)
diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h
index 442bdd4ec5..0cd1c59b49 100644
--- a/libavcodec/mpegvideo.h
+++ b/libavcodec/mpegvideo.h
@@ -459,6 +459,7 @@ typedef struct MpegEncContext {
int64_t wanted_bits;
int64_t total_bits;
int frame_bits; ///< bits used for the current frame
+ int next_lambda; ///< next lambda used for retrying to encode a frame
RateControlContext rc_context; ///< contains stuff only accessed in ratecontrol.c
/* statistics, used for 2-pass encoding */