Commit d8e790ca authored by Loren Merritt's avatar Loren Merritt

macroblock-level ratecontrol: improved vbv strictness, and improved quality when using vbv.



git-svn-id: svn://svn.videolan.org/x264/trunk@464 df754926-b1dd-0310-bc7b-ec298dee348c
parent 79389771
...@@ -55,6 +55,10 @@ ...@@ -55,6 +55,10 @@
#define UNUSED #define UNUSED
#endif #endif
#define X264_BFRAME_MAX 16
#define X264_SLICE_MAX 4
#define X264_NAL_MAX (4 + X264_SLICE_MAX)
/**************************************************************************** /****************************************************************************
* Includes * Includes
****************************************************************************/ ****************************************************************************/
...@@ -217,10 +221,6 @@ static const int x264_scan8[16+2*4] = ...@@ -217,10 +221,6 @@ static const int x264_scan8[16+2*4] =
5 R R 5 R R
*/ */
#define X264_BFRAME_MAX 16
#define X264_SLICE_MAX 4
#define X264_NAL_MAX (4 + X264_SLICE_MAX)
typedef struct x264_ratecontrol_t x264_ratecontrol_t; typedef struct x264_ratecontrol_t x264_ratecontrol_t;
typedef struct x264_vlc_table_t x264_vlc_table_t; typedef struct x264_vlc_table_t x264_vlc_table_t;
......
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
x264_frame_t *x264_frame_new( x264_t *h ) x264_frame_t *x264_frame_new( x264_t *h )
{ {
x264_frame_t *frame = x264_malloc( sizeof( x264_frame_t ) ); x264_frame_t *frame = x264_malloc( sizeof( x264_frame_t ) );
int i; int i, j;
int i_mb_count = h->mb.i_mb_count; int i_mb_count = h->mb.i_mb_count;
int i_stride; int i_stride;
...@@ -116,20 +116,27 @@ x264_frame_t *x264_frame_new( x264_t *h ) ...@@ -116,20 +116,27 @@ x264_frame_t *x264_frame_new( x264_t *h )
frame->ref[1] = NULL; frame->ref[1] = NULL;
} }
frame->i_row_bits = x264_malloc( i_lines/16 * sizeof( int ) );
frame->i_row_qp = x264_malloc( i_lines/16 * sizeof( int ) );
for( i = 0; i < h->param.i_bframe + 2; i++ )
for( j = 0; j < h->param.i_bframe + 2; j++ )
frame->i_row_satds[i][j] = x264_malloc( i_lines/16 * sizeof( int ) );
return frame; return frame;
} }
void x264_frame_delete( x264_frame_t *frame ) void x264_frame_delete( x264_frame_t *frame )
{ {
int i; int i, j;
for( i = 0; i < frame->i_plane; i++ ) for( i = 0; i < frame->i_plane; i++ )
{
x264_free( frame->buffer[i] ); x264_free( frame->buffer[i] );
}
for( i = 4; i < 12; i++ ) /* filtered planes */ for( i = 4; i < 12; i++ ) /* filtered planes */
{
x264_free( frame->buffer[i] ); x264_free( frame->buffer[i] );
} for( i = 0; i < X264_BFRAME_MAX+2; i++ )
for( j = 0; j < X264_BFRAME_MAX+2; j++ )
x264_free( frame->i_row_satds[i][j] );
x264_free( frame->i_row_bits );
x264_free( frame->i_row_qp );
x264_free( frame->mb_type ); x264_free( frame->mb_type );
x264_free( frame->mv[0] ); x264_free( frame->mv[0] );
x264_free( frame->mv[1] ); x264_free( frame->mv[1] );
......
...@@ -36,6 +36,7 @@ typedef struct ...@@ -36,6 +36,7 @@ typedef struct
int i_frame; /* Presentation frame number */ int i_frame; /* Presentation frame number */
int i_frame_num; /* Coded frame number */ int i_frame_num; /* Coded frame number */
int b_kept_as_ref; int b_kept_as_ref;
float f_qp_avg;
/* YUV buffer */ /* YUV buffer */
int i_plane; int i_plane;
...@@ -62,8 +63,13 @@ typedef struct ...@@ -62,8 +63,13 @@ typedef struct
/* for adaptive B-frame decision. /* for adaptive B-frame decision.
* contains the SATD cost of the lowres frame encoded in various modes * contains the SATD cost of the lowres frame encoded in various modes
* FIXME: how big an array do we need? */ * FIXME: how big an array do we need? */
int i_cost_est[16][16]; int i_cost_est[X264_BFRAME_MAX+2][X264_BFRAME_MAX+2];
int i_intra_mbs[16]; int i_satd; // the i_cost_est of the selected frametype
int i_intra_mbs[X264_BFRAME_MAX+2];
int *i_row_satds[X264_BFRAME_MAX+2][X264_BFRAME_MAX+2];
int *i_row_satd;
int *i_row_bits;
int *i_row_qp;
} x264_frame_t; } x264_frame_t;
......
...@@ -254,6 +254,18 @@ static void block_residual_write_cavlc( x264_t *h, bs_t *s, int i_idx, int *l, i ...@@ -254,6 +254,18 @@ static void block_residual_write_cavlc( x264_t *h, bs_t *s, int i_idx, int *l, i
} }
} }
static void cavlc_qp_delta( x264_t *h, bs_t *s )
{
int i_dqp = h->mb.i_qp - h->mb.i_last_qp;
if( i_dqp )
{
i_dqp = i_dqp <= 0 ? (-2*i_dqp) : (2*i_dqp - 1);
if( i_dqp > 52 )
i_dqp = 103 - i_dqp;
}
bs_write_ue( s, i_dqp );
}
static void x264_sub_mb_mv_write_cavlc( x264_t *h, bs_t *s, int i_list ) static void x264_sub_mb_mv_write_cavlc( x264_t *h, bs_t *s, int i_list )
{ {
int i; int i;
...@@ -676,7 +688,7 @@ void x264_macroblock_write_cavlc( x264_t *h, bs_t *s ) ...@@ -676,7 +688,7 @@ void x264_macroblock_write_cavlc( x264_t *h, bs_t *s )
/* write residual */ /* write residual */
if( i_mb_type == I_16x16 ) if( i_mb_type == I_16x16 )
{ {
bs_write_se( s, h->mb.i_qp - h->mb.i_last_qp ); cavlc_qp_delta( h, s );
/* DC Luma */ /* DC Luma */
block_residual_write_cavlc( h, s, BLOCK_INDEX_LUMA_DC , h->dct.luma16x16_dc, 16 ); block_residual_write_cavlc( h, s, BLOCK_INDEX_LUMA_DC , h->dct.luma16x16_dc, 16 );
...@@ -688,7 +700,7 @@ void x264_macroblock_write_cavlc( x264_t *h, bs_t *s ) ...@@ -688,7 +700,7 @@ void x264_macroblock_write_cavlc( x264_t *h, bs_t *s )
} }
else if( h->mb.i_cbp_luma != 0 || h->mb.i_cbp_chroma != 0 ) else if( h->mb.i_cbp_luma != 0 || h->mb.i_cbp_chroma != 0 )
{ {
bs_write_se( s, h->mb.i_qp - h->mb.i_last_qp ); cavlc_qp_delta( h, s );
x264_macroblock_luma_write_cavlc( h, s ); x264_macroblock_luma_write_cavlc( h, s );
} }
if( h->mb.i_cbp_chroma != 0 ) if( h->mb.i_cbp_chroma != 0 )
......
...@@ -189,7 +189,7 @@ static void x264_slice_header_init( x264_t *h, x264_slice_header_t *sh, ...@@ -189,7 +189,7 @@ static void x264_slice_header_init( x264_t *h, x264_slice_header_t *sh,
/* If effective qp <= 15, deblocking would have no effect anyway */ /* If effective qp <= 15, deblocking would have no effect anyway */
if( param->b_deblocking_filter if( param->b_deblocking_filter
&& ( h->mb.b_variable_qp && ( h->mb.b_variable_qp
|| 15 < i_qp + X264_MAX(param->i_deblocking_filter_alphac0, param->i_deblocking_filter_beta) ) ) || 15 < i_qp + 2 * X264_MAX(param->i_deblocking_filter_alphac0, param->i_deblocking_filter_beta) ) )
{ {
sh->i_disable_deblocking_filter_idc = 0; sh->i_disable_deblocking_filter_idc = 0;
} }
...@@ -633,6 +633,7 @@ x264_t *x264_encoder_open ( x264_param_t *param ) ...@@ -633,6 +633,7 @@ x264_t *x264_encoder_open ( x264_param_t *param )
param->cpu&X264_CPU_ALTIVEC ? "Altivec " : "" ); param->cpu&X264_CPU_ALTIVEC ? "Altivec " : "" );
h->thread[0] = h; h->thread[0] = h;
h->i_thread_num = 0;
for( i = 1; i < param->i_threads; i++ ) for( i = 1; i < param->i_threads; i++ )
h->thread[i] = x264_malloc( sizeof(x264_t) ); h->thread[i] = x264_malloc( sizeof(x264_t) );
...@@ -1087,6 +1088,7 @@ static inline int x264_slices_write( x264_t *h ) ...@@ -1087,6 +1088,7 @@ static inline int x264_slices_write( x264_t *h )
if( h->param.i_threads == 1 ) if( h->param.i_threads == 1 )
{ {
x264_ratecontrol_threads_start( h );
x264_slice_write( h ); x264_slice_write( h );
i_frame_size = h->out.nal[h->out.i_nal-1].i_payload; i_frame_size = h->out.nal[h->out.i_nal-1].i_payload;
} }
...@@ -1104,11 +1106,13 @@ static inline int x264_slices_write( x264_t *h ) ...@@ -1104,11 +1106,13 @@ static inline int x264_slices_write( x264_t *h )
memcpy( t, h, sizeof(x264_t) ); memcpy( t, h, sizeof(x264_t) );
t->out.p_bitstream += i*i_bs_size; t->out.p_bitstream += i*i_bs_size;
bs_init( &t->out.bs, t->out.p_bitstream, i_bs_size ); bs_init( &t->out.bs, t->out.p_bitstream, i_bs_size );
t->i_thread_num = i;
} }
t->sh.i_first_mb = (i * h->sps->i_mb_height / h->param.i_threads) * h->sps->i_mb_width; t->sh.i_first_mb = (i * h->sps->i_mb_height / h->param.i_threads) * h->sps->i_mb_width;
t->sh.i_last_mb = ((i+1) * h->sps->i_mb_height / h->param.i_threads) * h->sps->i_mb_width; t->sh.i_last_mb = ((i+1) * h->sps->i_mb_height / h->param.i_threads) * h->sps->i_mb_width;
t->out.i_nal = i_nal + i; t->out.i_nal = i_nal + i;
} }
x264_ratecontrol_threads_start( h );
/* dispatch */ /* dispatch */
#if HAVE_PTHREAD #if HAVE_PTHREAD
...@@ -1498,24 +1502,21 @@ do_encode: ...@@ -1498,24 +1502,21 @@ do_encode:
/* ---------------------- Update encoder state ------------------------- */ /* ---------------------- Update encoder state ------------------------- */
/* update rc */
x264_cpu_restore( h->param.cpu );
x264_ratecontrol_end( h, i_frame_size * 8 );
/* handle references */ /* handle references */
if( i_nal_ref_idc != NAL_PRIORITY_DISPOSABLE ) if( i_nal_ref_idc != NAL_PRIORITY_DISPOSABLE )
{
x264_reference_update( h ); x264_reference_update( h );
} x264_frame_put( h->frames.unused, h->fenc );
/* increase frame count */ /* increase frame count */
h->i_frame++; h->i_frame++;
/* restore CPU state (before using float again) */ /* restore CPU state (before using float again) */
/* XXX: not needed? (done above) */
x264_cpu_restore( h->param.cpu ); x264_cpu_restore( h->param.cpu );
/* update rc */
x264_ratecontrol_end( h, i_frame_size * 8 );
x264_frame_put( h->frames.unused, h->fenc );
x264_noise_reduction_update( h ); x264_noise_reduction_update( h );
TIMER_STOP( i_mtime_encode_frame ); TIMER_STOP( i_mtime_encode_frame );
......
...@@ -84,6 +84,7 @@ struct x264_ratecontrol_t ...@@ -84,6 +84,7 @@ struct x264_ratecontrol_t
/* constants */ /* constants */
int b_abr; int b_abr;
int b_2pass; int b_2pass;
int b_vbv;
double fps; double fps;
double bitrate; double bitrate;
double rate_tolerance; double rate_tolerance;
...@@ -93,7 +94,8 @@ struct x264_ratecontrol_t ...@@ -93,7 +94,8 @@ struct x264_ratecontrol_t
/* current frame */ /* current frame */
ratecontrol_entry_t *rce; ratecontrol_entry_t *rce;
int qp; /* qp for current frame */ int qp; /* qp for current frame */
float qpa; /* average of macroblocks' qp (same as qp if no adaptive quant) */ int qpm; /* qp for current macroblock */
float qpa; /* average of macroblocks' qp */
int slice_type; int slice_type;
int qp_force; int qp_force;
...@@ -113,6 +115,8 @@ struct x264_ratecontrol_t ...@@ -113,6 +115,8 @@ struct x264_ratecontrol_t
double short_term_cplxsum; double short_term_cplxsum;
double short_term_cplxcount; double short_term_cplxcount;
double rate_factor_constant; double rate_factor_constant;
double ip_offset;
double pb_offset;
/* 2pass stuff */ /* 2pass stuff */
FILE *p_stat_file_out; FILE *p_stat_file_out;
...@@ -134,6 +138,15 @@ struct x264_ratecontrol_t ...@@ -134,6 +138,15 @@ struct x264_ratecontrol_t
double mv_bits_sum[5]; double mv_bits_sum[5];
int frame_count[5]; /* number of frames of each type */ int frame_count[5]; /* number of frames of each type */
/* MBRC stuff */
double frame_size_planned;
int first_row, last_row; /* region of the frame to be encoded by this thread */
predictor_t *row_pred;
predictor_t row_preds[5];
predictor_t pred_b_from_p; /* predict B-frame size from P-frame satd */
int bframes; /* # consecutive B-frames before this P-frame */
int bframe_bits; /* total cost of those frames */
int i_zones; int i_zones;
x264_zone_t *zones; x264_zone_t *zones;
}; };
...@@ -143,6 +156,8 @@ static int parse_zones( x264_t *h ); ...@@ -143,6 +156,8 @@ static int parse_zones( x264_t *h );
static int init_pass2(x264_t *); static int init_pass2(x264_t *);
static float rate_estimate_qscale( x264_t *h, int pict_type ); static float rate_estimate_qscale( x264_t *h, int pict_type );
static void update_vbv( x264_t *h, int bits ); static void update_vbv( x264_t *h, int bits );
static double predict_size( predictor_t *p, double q, double var );
static void update_predictor( predictor_t *p, double q, double var, double bits );
int x264_rc_analyse_slice( x264_t *h ); int x264_rc_analyse_slice( x264_t *h );
/* Terminology: /* Terminology:
...@@ -179,12 +194,11 @@ int x264_ratecontrol_new( x264_t *h ) ...@@ -179,12 +194,11 @@ int x264_ratecontrol_new( x264_t *h )
x264_cpu_restore( h->param.cpu ); x264_cpu_restore( h->param.cpu );
h->rc = rc = x264_malloc( sizeof( x264_ratecontrol_t ) ); h->rc = rc = x264_malloc( h->param.i_threads * sizeof(x264_ratecontrol_t) );
memset(rc, 0, sizeof(*rc)); memset( rc, 0, h->param.i_threads * sizeof(x264_ratecontrol_t) );
rc->b_abr = ( h->param.rc.b_cbr || h->param.rc.i_rf_constant ) && !h->param.rc.b_stat_read; rc->b_abr = ( h->param.rc.b_cbr || h->param.rc.i_rf_constant ) && !h->param.rc.b_stat_read;
rc->b_2pass = h->param.rc.b_cbr && h->param.rc.b_stat_read; rc->b_2pass = h->param.rc.b_cbr && h->param.rc.b_stat_read;
h->mb.b_variable_qp = 0;
/* FIXME: use integers */ /* FIXME: use integers */
if(h->param.i_fps_num > 0 && h->param.i_fps_den > 0) if(h->param.i_fps_num > 0 && h->param.i_fps_den > 0)
...@@ -217,8 +231,8 @@ int x264_ratecontrol_new( x264_t *h ) ...@@ -217,8 +231,8 @@ int x264_ratecontrol_new( x264_t *h )
else if( h->param.rc.i_vbv_max_bitrate > 0 && else if( h->param.rc.i_vbv_max_bitrate > 0 &&
h->param.rc.i_vbv_buffer_size > 0 ) h->param.rc.i_vbv_buffer_size > 0 )
{ {
if( h->param.rc.i_vbv_buffer_size < 10 * h->param.rc.i_vbv_max_bitrate / rc->fps ) { if( h->param.rc.i_vbv_buffer_size < 3 * h->param.rc.i_vbv_max_bitrate / rc->fps ) {
h->param.rc.i_vbv_buffer_size = 10 * h->param.rc.i_vbv_max_bitrate / rc->fps; h->param.rc.i_vbv_buffer_size = 3 * h->param.rc.i_vbv_max_bitrate / rc->fps;
x264_log( h, X264_LOG_ERROR, "VBV buffer size too small, using %d kbit\n", x264_log( h, X264_LOG_ERROR, "VBV buffer size too small, using %d kbit\n",
h->param.rc.i_vbv_buffer_size ); h->param.rc.i_vbv_buffer_size );
} }
...@@ -227,6 +241,7 @@ int x264_ratecontrol_new( x264_t *h ) ...@@ -227,6 +241,7 @@ int x264_ratecontrol_new( x264_t *h )
rc->buffer_fill = rc->buffer_size * h->param.rc.f_vbv_buffer_init; rc->buffer_fill = rc->buffer_size * h->param.rc.f_vbv_buffer_init;
rc->cbr_decay = 1.0 - rc->buffer_rate / rc->buffer_size rc->cbr_decay = 1.0 - rc->buffer_rate / rc->buffer_size
* 0.5 * X264_MAX(0, 1.5 - rc->buffer_rate * rc->fps / rc->bitrate); * 0.5 * X264_MAX(0, 1.5 - rc->buffer_rate * rc->fps / rc->bitrate);
rc->b_vbv = 1;
} }
else if( h->param.rc.i_vbv_max_bitrate ) else if( h->param.rc.i_vbv_max_bitrate )
x264_log(h, X264_LOG_ERROR, "VBV maxrate specified, but no bufsize.\n"); x264_log(h, X264_LOG_ERROR, "VBV maxrate specified, but no bufsize.\n");
...@@ -235,6 +250,8 @@ int x264_ratecontrol_new( x264_t *h ) ...@@ -235,6 +250,8 @@ int x264_ratecontrol_new( x264_t *h )
rc->rate_tolerance = 0.01; rc->rate_tolerance = 0.01;
} }
h->mb.b_variable_qp = rc->b_vbv;
if( rc->b_abr ) if( rc->b_abr )
{ {
/* FIXME shouldn't need to arbitrarily specify a QP, /* FIXME shouldn't need to arbitrarily specify a QP,
...@@ -254,9 +271,11 @@ int x264_ratecontrol_new( x264_t *h ) ...@@ -254,9 +271,11 @@ int x264_ratecontrol_new( x264_t *h )
/ qp2qscale( h->param.rc.i_rf_constant ); / qp2qscale( h->param.rc.i_rf_constant );
} }
rc->ip_offset = 6.0 * log(h->param.rc.f_ip_factor) / log(2.0);
rc->pb_offset = 6.0 * log(h->param.rc.f_pb_factor) / log(2.0);
rc->qp_constant[SLICE_TYPE_P] = h->param.rc.i_qp_constant; rc->qp_constant[SLICE_TYPE_P] = h->param.rc.i_qp_constant;
rc->qp_constant[SLICE_TYPE_I] = x264_clip3( (int)( qscale2qp( qp2qscale( h->param.rc.i_qp_constant ) / fabs( h->param.rc.f_ip_factor )) + 0.5 ), 0, 51 ); rc->qp_constant[SLICE_TYPE_I] = x264_clip3( h->param.rc.i_qp_constant - rc->ip_offset + 0.5, 0, 51 );
rc->qp_constant[SLICE_TYPE_B] = x264_clip3( (int)( qscale2qp( qp2qscale( h->param.rc.i_qp_constant ) * fabs( h->param.rc.f_pb_factor )) + 0.5 ), 0, 51 ); rc->qp_constant[SLICE_TYPE_B] = x264_clip3( h->param.rc.i_qp_constant + rc->pb_offset + 0.5, 0, 51 );
rc->lstep = exp2f(h->param.rc.i_qp_step / 6.0); rc->lstep = exp2f(h->param.rc.i_qp_step / 6.0);
rc->last_qscale = qp2qscale(26); rc->last_qscale = qp2qscale(26);
...@@ -268,7 +287,11 @@ int x264_ratecontrol_new( x264_t *h ) ...@@ -268,7 +287,11 @@ int x264_ratecontrol_new( x264_t *h )
rc->pred[i].coeff= 2.0; rc->pred[i].coeff= 2.0;
rc->pred[i].count= 1.0; rc->pred[i].count= 1.0;
rc->pred[i].decay= 0.5; rc->pred[i].decay= 0.5;
rc->row_preds[i].coeff= .25;
rc->row_preds[i].count= 1.0;
rc->row_preds[i].decay= 0.5;
} }
rc->pred_b_from_p = rc->pred[0];
if( parse_zones( h ) < 0 ) if( parse_zones( h ) < 0 )
return -1; return -1;
...@@ -552,19 +575,34 @@ void x264_ratecontrol_start( x264_t *h, int i_slice_type, int i_force_qp ) ...@@ -552,19 +575,34 @@ void x264_ratecontrol_start( x264_t *h, int i_slice_type, int i_force_qp )
} }
} }
if( h->fdec->i_row_bits )
{
memset( h->fdec->i_row_bits, 0, h->sps->i_mb_height * sizeof(int) );
}
if( i_slice_type != SLICE_TYPE_B )
{
rc->bframe_bits = 0;
rc->bframes = 0;
while( h->frames.current[rc->bframes] && IS_X264_TYPE_B(h->frames.current[rc->bframes]->i_type) )
rc->bframes++;
}
rc->qpa = 0;
if( i_force_qp ) if( i_force_qp )
{ {
rc->qpa = rc->qp = i_force_qp - 1; rc->qpm = rc->qp = i_force_qp - 1;
} }
else if( rc->b_abr ) else if( rc->b_abr )
{ {
rc->qpa = rc->qp = rc->qpm = rc->qp =
x264_clip3( (int)(qscale2qp( rate_estimate_qscale( h, i_slice_type ) ) + .5), 0, 51 ); x264_clip3( (int)(qscale2qp( rate_estimate_qscale( h, i_slice_type ) ) + .5), 0, 51 );
} }
else if( rc->b_2pass ) else if( rc->b_2pass )
{ {
rce->new_qscale = rate_estimate_qscale( h, i_slice_type ); rce->new_qscale = rate_estimate_qscale( h, i_slice_type );
rc->qpa = rc->qp = rce->new_qp = rc->qpm = rc->qp = rce->new_qp =
x264_clip3( (int)(qscale2qp(rce->new_qscale) + 0.5), 0, 51 ); x264_clip3( (int)(qscale2qp(rce->new_qscale) + 0.5), 0, 51 );
} }
else /* CQP */ else /* CQP */
...@@ -574,18 +612,103 @@ void x264_ratecontrol_start( x264_t *h, int i_slice_type, int i_force_qp ) ...@@ -574,18 +612,103 @@ void x264_ratecontrol_start( x264_t *h, int i_slice_type, int i_force_qp )
q = ( rc->qp_constant[ SLICE_TYPE_B ] + rc->qp_constant[ SLICE_TYPE_P ] ) / 2; q = ( rc->qp_constant[ SLICE_TYPE_B ] + rc->qp_constant[ SLICE_TYPE_P ] ) / 2;
else else
q = rc->qp_constant[ i_slice_type ]; q = rc->qp_constant[ i_slice_type ];
rc->qpa = rc->qp = q; rc->qpm = rc->qp = q;
} }
} }
double predict_row_size( x264_t *h, int y, int qp )
{
/* average between two predictors:
* absolute SATD, and scaled bit cost of the colocated row in the previous frame */
x264_ratecontrol_t *rc = h->rc;
double pred_s = predict_size( rc->row_pred, qp2qscale(qp), h->fdec->i_row_satd[y] );
double pred_t = 0;
if( rc->slice_type != SLICE_TYPE_I
&& h->fref0[0]->i_type == h->fdec->i_type
&& h->fref0[0]->i_row_satd[y] > 0 )
{
pred_t = h->fref0[0]->i_row_bits[y] * h->fdec->i_row_satd[y] / h->fref0[0]->i_row_satd[y]
* qp2qscale(h->fref0[0]->i_row_qp[y]) / qp2qscale(qp);
}
if( pred_t == 0 )
pred_t = pred_s;
return (pred_s + pred_t) / 2;
}
double predict_row_size_sum( x264_t *h, int y, int qp )
{
int i;
double bits = 0;
for( i = h->rc->first_row; i <= y; i++ )
bits += h->fdec->i_row_bits[i];
for( i = y+1; i <= h->rc->last_row; i++ )
bits += predict_row_size( h, i, qp );
return bits;
}
void x264_ratecontrol_mb( x264_t *h, int bits ) void x264_ratecontrol_mb( x264_t *h, int bits )
{ {
/* currently no adaptive quant */ x264_ratecontrol_t *rc = h->rc;
const int y = h->mb.i_mb_y;
x264_cpu_restore( h->param.cpu );
h->fdec->i_row_bits[y] += bits;
rc->qpa += rc->qpm;
if( h->mb.i_mb_x != h->sps->i_mb_width - 1 || !rc->b_vbv )
return;
h->fdec->i_row_qp[y] = rc->qpm;
if( rc->slice_type == SLICE_TYPE_B )
{
/* B-frames shouldn't use lower QP than their reference frames */
if( y < rc->last_row )
{
rc->qpm = X264_MAX( rc->qp,
X264_MIN( h->fref0[0]->i_row_qp[y+1],
h->fref1[0]->i_row_qp[y+1] ));
}
}
else
{
update_predictor( rc->row_pred, qp2qscale(rc->qpm), h->fdec->i_row_satd[y], h->fdec->i_row_bits[y] );
/* tweak quality based on difference from predicted size */
if( y < rc->last_row && h->stat.i_slice_count[rc->slice_type] > 0 )
{
int prev_row_qp = h->fdec->i_row_qp[y];
int b0 = predict_row_size_sum( h, y, rc->qpm );
int b1 = b0;
int i_qp_max = X264_MIN( prev_row_qp + h->param.rc.i_qp_step, h->param.rc.i_qp_max );
int i_qp_min = X264_MAX( prev_row_qp - h->param.rc.i_qp_step, h->param.rc.i_qp_min );
float buffer_left_planned = rc->buffer_fill - rc->frame_size_planned;
while( rc->qpm < i_qp_max
&& (b1 > rc->frame_size_planned * 1.15
|| (rc->buffer_fill - b1 < buffer_left_planned * 0.5)))
{
rc->qpm ++;
b1 = predict_row_size_sum( h, y, rc->qpm );
}
while( rc->qpm > i_qp_min
&& buffer_left_planned > rc->buffer_size * 0.4
&& ((b1 < rc->frame_size_planned * 0.8 && rc->qpm <= prev_row_qp)
|| b1 < (rc->buffer_fill - rc->buffer_size + rc->buffer_rate) * 1.1) )
{
rc->qpm --;
b1 = predict_row_size_sum( h, y, rc->qpm );
}
}
}
}