[Ffmpeg-devel] [patch] rc buffer bits reservation for I-frames
Jindrich Makovicka
makovick
Fri Nov 24 16:11:32 CET 2006
Hi,
when using a short RC buffer and tight bitrate restrictions (typically
when encoding for DVB), the rate control sometimes tends to use too
much bits for P-frames, and when an I-frame gets encoded, there is not
enough bits available, causing a sudden quality decrease.
The attached patch adds an option to reserve a specified multiple of
the last I-frame size in the RC buffer. Default value if 0, i.e.
unchanged from the current state.
Sample mpeg2 movies with reservation factor set to 0 and 1 are available at
http://kmlinux.fjfi.cvut.cz/~makovick/res0.avi
http://kmlinux.fjfi.cvut.cz/~makovick/res1.avi .
The movies were encoded using mplayer with -lavcopts
vcodec=mpeg2video:mbd=2:vbitrate=1500:vrc_maxrate=1500:vrc_buf_size=750
The difference is clearly visible when you open the movies in avidemux
and look at the I-frames.
Regards,
--
Jindrich Makovicka
-------------- next part --------------
Index: utils.c
===================================================================
--- utils.c (revision 7165)
+++ utils.c (working copy)
@@ -539,6 +539,7 @@
{"minrate", "set min video bitrate tolerance (in bits/s)", OFFSET(rc_min_rate), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, V|E},
{"bufsize", "set ratecontrol buffer size (in bits)", OFFSET(rc_buffer_size), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, V|E},
{"rc_buf_aggressivity", NULL, OFFSET(rc_buffer_aggressivity), FF_OPT_TYPE_FLOAT, 1.0, FLT_MIN, FLT_MAX, V|E},
+{"rc_buf_iframe_reserve", NULL, OFFSET(rc_buffer_iframe_reserve), FF_OPT_TYPE_FLOAT, 0.0, 0.0, FLT_MAX, V|E},
{"i_qfactor", "qp factor between p and i frames", OFFSET(i_quant_factor), FF_OPT_TYPE_FLOAT, -0.8, -FLT_MAX, FLT_MAX, V|E},
{"i_qoffset", "qp offset between p and i frames", OFFSET(i_quant_offset), FF_OPT_TYPE_FLOAT, 0.0, -FLT_MAX, FLT_MAX, V|E},
{"rc_init_cplx", "initial complexity for 1-pass encoding", OFFSET(rc_initial_cplx), FF_OPT_TYPE_FLOAT, DEFAULT, -FLT_MAX, FLT_MAX, V|E},
Index: avcodec.h
===================================================================
--- avcodec.h (revision 7165)
+++ avcodec.h (working copy)
@@ -1131,6 +1131,7 @@
*/
int rc_buffer_size;
float rc_buffer_aggressivity;
+ float rc_buffer_iframe_reserve;
/**
* qscale factor between p and i frames.
Index: ratecontrol.c
===================================================================
--- ratecontrol.c (revision 7165)
+++ ratecontrol.c (working copy)
@@ -125,6 +125,7 @@
rcc->last_qscale_for[i]=FF_QP2LAMBDA * 5;
}
rcc->buffer_index= s->avctx->rc_initial_buffer_occupancy;
+ rcc->prev_iframe_bits= 0;
if(s->flags&CODEC_FLAG_PASS2){
int i;
@@ -426,7 +427,7 @@
*qmax_ret= qmax;
}
-static double modify_qscale(MpegEncContext *s, RateControlEntry *rce, double q, int frame_num){
+static double modify_qscale(MpegEncContext *s, RateControlEntry *rce, double q, int frame_num, double reserve){
RateControlContext *rcc= &s->rc_context;
int qmin, qmax;
double bits;
@@ -446,7 +447,7 @@
//printf("q:%f\n", q);
/* buffer overflow/underflow protection */
if(buffer_size){
- double expected_size= rcc->buffer_index;
+ double expected_size= rcc->buffer_index - reserve;
double q_limit;
if(min_rate){
@@ -455,7 +456,7 @@
else if(d<0.0001) d=0.0001;
q*= pow(d, 1.0/s->avctx->rc_buffer_aggressivity);
- q_limit= bits2qp(rce, FFMAX((min_rate - buffer_size + rcc->buffer_index)*3, 1));
+ q_limit= bits2qp(rce, FFMAX((min_rate - buffer_size + rcc->buffer_index - reserve)*3, 1));
if(q > q_limit){
if(s->avctx->debug&FF_DEBUG_RC){
av_log(s->avctx, AV_LOG_DEBUG, "limiting QP %f -> %f\n", q, q_limit);
@@ -470,7 +471,7 @@
else if(d<0.0001) d=0.0001;
q/= pow(d, 1.0/s->avctx->rc_buffer_aggressivity);
- q_limit= bits2qp(rce, FFMAX(rcc->buffer_index/3, 1));
+ q_limit= bits2qp(rce, FFMAX((rcc->buffer_index - reserve)/3, 1));
if(q < q_limit){
if(s->avctx->debug&FF_DEBUG_RC){
av_log(s->avctx, AV_LOG_DEBUG, "limiting QP %f -> %f\n", q, q_limit);
@@ -711,6 +712,8 @@
q= rce->new_qscale / br_compensation;
//printf("%f %f %f last:%d var:%d type:%d//\n", q, rce->new_qscale, br_compensation, s->frame_bits, var, pict_type);
}else{
+ double reserve;
+
rce->pict_type=
rce->new_pict_type= pict_type;
rce->mc_mb_var_sum= pic->mc_mb_var_sum;
@@ -763,8 +766,17 @@
}
assert(q>0.0);
- q= modify_qscale(s, rce, q, picture_number);
+ if (pict_type != I_TYPE)
+ reserve = rcc->prev_iframe_bits * s->avctx->rc_buffer_iframe_reserve;
+ else
+ reserve = 0;
+ q= modify_qscale(s, rce, q, picture_number, reserve);
+
+ if (pict_type == I_TYPE) {
+ rcc->prev_iframe_bits = predict_size(&rcc->pred[I_TYPE], q, sqrt(var));
+ }
+
rcc->pass1_wanted_bits+= s->bit_rate/fps;
assert(q>0.0);
@@ -888,7 +900,7 @@
for(i=0; i<rcc->num_entries; i++){
RateControlEntry *rce= &rcc->entry[i];
double bits;
- rce->new_qscale= modify_qscale(s, rce, blured_qscale[i], i);
+ rce->new_qscale= modify_qscale(s, rce, blured_qscale[i], i, 0);
bits= qp2bits(rce, rce->new_qscale) + rce->mv_bits + rce->misc_bits;
//printf("%d %f\n", rce->new_bits, blured_qscale[i]);
bits += 8*ff_vbv_update(s, bits);
Index: ratecontrol.h
===================================================================
--- ratecontrol.h (revision 7165)
+++ ratecontrol.h (working copy)
@@ -63,6 +63,7 @@
int num_entries; ///< number of RateControlEntries
RateControlEntry *entry;
double buffer_index; ///< amount of bits in the video/audio buffer
+ double prev_iframe_bits;
Predictor pred[5];
double short_term_qsum; ///< sum of recent qscales
double short_term_qcount; ///< count of recent qscales
More information about the ffmpeg-devel
mailing list