From 065321c48d0d371c1735b3cc9d368b43e1b64aaa Mon Sep 17 00:00:00 2001 From: Anton Mitrofanov Date: Tue, 5 Jan 2016 02:41:43 +0300 Subject: [PATCH] Revise the row VBV algorithm (part 2) Should fix rare cases of VBV emergency mode activation caused by too much trust to the row predictors. --- encoder/ratecontrol.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/encoder/ratecontrol.c b/encoder/ratecontrol.c index e4a085c4..ab804602 100644 --- a/encoder/ratecontrol.c +++ b/encoder/ratecontrol.c @@ -1551,10 +1551,10 @@ static int row_bits_so_far( x264_t *h, int y ) return bits; } -static float predict_row_size_sum( x264_t *h, int y, float qp ) +static float predict_row_size_to_end( x264_t *h, int y, float qp ) { float qscale = qp2qscale( qp ); - float bits = row_bits_so_far( h, y ); + float bits = 0; for( int i = y+1; i < h->i_threadslice_end; i++ ) bits += predict_row_size( h, i, qscale ); return bits; @@ -1606,6 +1606,7 @@ int x264_ratecontrol_mb( x264_t *h, int bits ) 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 slice_size_planned = h->param.b_sliced_threads ? rc->slice_size_planned : rc->frame_size_planned; + float bits_so_far = row_bits_so_far( h, y ); 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 ); @@ -1635,11 +1636,12 @@ int x264_ratecontrol_mb( x264_t *h, int bits ) 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; + float b1 = bits_so_far + predict_row_size_to_end( h, y, rc->qpm ) + size_of_other_slices; + float trust_coeff = x264_clip3f( bits_so_far / slice_size_planned, 0.0, 1.0 ); /* Don't increase the row QPs until a sufficent amount of the bits of the frame have been processed, in case a flat */ /* area at the top of the frame was measured inaccurately. */ - if( row_bits_so_far( h, y ) < 0.05f * slice_size_planned ) + if( trust_coeff < 0.05f ) qp_max = qp_absolute_max = prev_row_qp; if( h->sh.i_type != SLICE_TYPE_I ) @@ -1654,18 +1656,20 @@ int x264_ratecontrol_mb( x264_t *h, int bits ) (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; + b1 = bits_so_far + predict_row_size_to_end( h, y, rc->qpm ) + size_of_other_slices; } + float b_max = b1 + ((rc->buffer_fill - rc->buffer_size + rc->buffer_rate) * 0.90f - b1) * trust_coeff; rc->qpm -= step_size; + float b2 = bits_so_far + predict_row_size_to_end( h, y, rc->qpm ) + size_of_other_slices; while( rc->qpm > qp_min && rc->qpm < prev_row_qp && (rc->qpm > h->fdec->f_row_qp[0] || rc->single_frame_vbv) - && (b1 < max_frame_size) - && ((b1 < rc->frame_size_planned * 0.8f) || - (b1 < (rc->buffer_fill - rc->buffer_size + rc->buffer_rate) * 0.95f)) ) + && (b2 < max_frame_size) + && ((b2 < rc->frame_size_planned * 0.8f) || (b2 < b_max)) ) { - b1 = predict_row_size_sum( h, y, rc->qpm ) + size_of_other_slices; + b1 = b2; rc->qpm -= step_size; + b2 = bits_so_far + predict_row_size_to_end( h, y, rc->qpm ) + size_of_other_slices; } rc->qpm += step_size; @@ -1673,7 +1677,7 @@ int x264_ratecontrol_mb( x264_t *h, int bits ) 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; + b1 = bits_so_far + predict_row_size_to_end( h, y, rc->qpm ) + size_of_other_slices; } h->rc->frame_size_estimated = b1 - size_of_other_slices; @@ -1692,12 +1696,12 @@ int x264_ratecontrol_mb( x264_t *h, int bits ) } else { - h->rc->frame_size_estimated = predict_row_size_sum( h, y, rc->qpm ); + h->rc->frame_size_estimated = bits_so_far; /* Last-ditch attempt: if the last row of the frame underflowed the VBV, * try again. */ if( rc->qpm < qp_max && can_reencode_row - && (h->rc->frame_size_estimated + size_of_other_slices > max_frame_size) ) + && (h->rc->frame_size_estimated + size_of_other_slices > X264_MIN( rc->frame_size_maximum, rc->buffer_fill )) ) { rc->qpm = qp_max; rc->qpa_rc = rc->qpa_rc_prev; -- 2.39.2