From: Anton Mitrofanov Date: Tue, 22 Sep 2015 17:19:23 +0000 (+0300) Subject: Revise the row VBV algorithm X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=de24c8c189364013e62d58d1e8f2fef878eb62bf;p=x264 Revise the row VBV algorithm --- diff --git a/encoder/ratecontrol.c b/encoder/ratecontrol.c index 8b8e76e6..2a310944 100644 --- a/encoder/ratecontrol.c +++ b/encoder/ratecontrol.c @@ -1605,9 +1605,10 @@ int x264_ratecontrol_mb( x264_t *h, int bits ) float qp_max = X264_MIN( prev_row_qp + h->param.rc.i_qp_step, qp_absolute_max ); float qp_min = X264_MAX( prev_row_qp - h->param.rc.i_qp_step, h->param.rc.i_qp_min ); float step_size = 0.5f; - float buffer_left_planned = rc->buffer_fill - rc->frame_size_planned; float slice_size_planned = h->param.b_sliced_threads ? rc->slice_size_planned : rc->frame_size_planned; - float max_frame_error = X264_MAX( 0.05f, 1.0f / h->mb.i_mb_height ); + float max_frame_error = x264_clip3f( 1.0 / h->mb.i_mb_height, 0.05, 0.25 ); + float max_frame_size = rc->frame_size_maximum - rc->frame_size_maximum * max_frame_error; + max_frame_size = X264_MIN( max_frame_size, rc->buffer_fill - rc->buffer_rate * max_frame_error ); float size_of_other_slices = 0; if( h->param.b_sliced_threads ) { @@ -1630,6 +1631,8 @@ int x264_ratecontrol_mb( x264_t *h, int bits ) rc->qpm = X264_MAX( rc->qpm, qp_min ); } + float buffer_left_planned = rc->buffer_fill - rc->frame_size_planned; + buffer_left_planned = X264_MAX( buffer_left_planned, 0.f ); /* More threads means we have to be more cautious in letting ratecontrol use up extra bits. */ float rc_tol = buffer_left_planned / h->param.i_threads * rc->rate_tolerance; float b1 = predict_row_size_sum( h, y, rc->qpm ) + size_of_other_slices; @@ -1647,26 +1650,27 @@ int x264_ratecontrol_mb( x264_t *h, int bits ) while( rc->qpm < qp_max && ((b1 > rc->frame_size_planned + rc_tol) || - (rc->buffer_fill - b1 < buffer_left_planned * 0.5f) || - (b1 > rc->frame_size_planned && rc->qpm < rc->qp_novbv)) ) + (b1 > rc->frame_size_planned && rc->qpm < rc->qp_novbv) || + (b1 > rc->buffer_fill - buffer_left_planned * 0.5f)) ) { rc->qpm += step_size; b1 = predict_row_size_sum( h, y, rc->qpm ) + size_of_other_slices; } - while( rc->qpm > qp_min + rc->qpm -= step_size; + while( rc->qpm > qp_min && rc->qpm < prev_row_qp && (rc->qpm > h->fdec->f_row_qp[0] || rc->single_frame_vbv) - && ((b1 < rc->frame_size_planned * 0.8f && rc->qpm <= prev_row_qp) - || b1 < (rc->buffer_fill - rc->buffer_size + rc->buffer_rate) * 1.1f) ) + && (b1 < max_frame_size) + && ((b1 < rc->frame_size_planned * 0.8f) || + (b1 < (rc->buffer_fill - rc->buffer_size + rc->buffer_rate) * 0.95f)) ) { - rc->qpm -= step_size; b1 = predict_row_size_sum( h, y, rc->qpm ) + size_of_other_slices; + rc->qpm -= step_size; } + rc->qpm += step_size; /* avoid VBV underflow or MinCR violation */ - while( (rc->qpm < qp_absolute_max) - && ((rc->buffer_fill - b1 < rc->buffer_rate * max_frame_error) || - (rc->frame_size_maximum - b1 < rc->frame_size_maximum * max_frame_error))) + while( rc->qpm < qp_absolute_max && (b1 > max_frame_size) ) { rc->qpm += step_size; b1 = predict_row_size_sum( h, y, rc->qpm ) + size_of_other_slices; @@ -1692,8 +1696,8 @@ int x264_ratecontrol_mb( x264_t *h, int bits ) /* Last-ditch attempt: if the last row of the frame underflowed the VBV, * try again. */ - if( (h->rc->frame_size_estimated + size_of_other_slices) > (rc->buffer_fill - rc->buffer_rate * max_frame_error) && - rc->qpm < qp_max && can_reencode_row ) + if( rc->qpm < qp_max && can_reencode_row + && (h->rc->frame_size_estimated + size_of_other_slices > max_frame_size) ) { rc->qpm = qp_max; rc->qpa_rc = rc->qpa_rc_prev; @@ -2677,7 +2681,7 @@ void x264_threads_distribute_ratecontrol( x264_t *h ) for( int i = 0; i < h->param.i_threads; i++ ) { x264_t *t = h->thread[i]; - float max_frame_error = X264_MAX( 0.05, 1.0 / (t->i_threadslice_end - t->i_threadslice_start) ); + float max_frame_error = x264_clip3f( 1.0 / (t->i_threadslice_end - t->i_threadslice_start), 0.05, 0.25 ); t->rc->slice_size_planned += 2 * max_frame_error * rc->frame_size_planned; } x264_threads_normalize_predictors( h );