diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2006-10-05 19:27:18 +0000 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2006-10-05 19:27:18 +0000 |
commit | 075060023d978975ed5328e269d6e20163e669d2 (patch) | |
tree | 6335d81f345000f08da9a02b299d7c2933658406 | |
parent | e1931c59f6dcbc851c92af4a3f7932ac04b5358e (diff) | |
download | ffmpeg-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.c | 46 | ||||
-rw-r--r-- | libavcodec/mpegvideo.h | 1 |
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 */ |