Commit 0ddc9d55 authored by Loren Merritt's avatar Loren Merritt

--crf: 1pass quality-based VBR.



git-svn-id: svn://svn.videolan.org/x264/trunk@334 df754926-b1dd-0310-bc7b-ec298dee348c
parent 06f1dafd
...@@ -89,6 +89,7 @@ void x264_param_default( x264_param_t *param ) ...@@ -89,6 +89,7 @@ void x264_param_default( x264_param_t *param )
param->rc.i_vbv_buffer_size = 0; param->rc.i_vbv_buffer_size = 0;
param->rc.f_vbv_buffer_init = 0.9; param->rc.f_vbv_buffer_init = 0.9;
param->rc.i_qp_constant = 26; param->rc.i_qp_constant = 26;
param->rc.i_rf_constant = 0;
param->rc.i_qp_min = 10; param->rc.i_qp_min = 10;
param->rc.i_qp_max = 51; param->rc.i_qp_max = 51;
param->rc.i_qp_step = 4; param->rc.i_qp_step = 4;
......
...@@ -352,6 +352,10 @@ static int x264_validate_parameters( x264_t *h ) ...@@ -352,6 +352,10 @@ static int x264_validate_parameters( x264_t *h )
} }
#endif #endif
if( h->param.rc.i_rf_constant > 0 )
h->param.rc.i_qp_constant = h->param.rc.i_rf_constant;
h->param.rc.i_rf_constant = x264_clip3( h->param.rc.i_rf_constant, 0, 51 );
h->param.rc.i_qp_constant = x264_clip3( h->param.rc.i_qp_constant, 0, 51 );
if( !h->param.rc.b_cbr && h->param.rc.i_qp_constant == 0 ) if( !h->param.rc.b_cbr && h->param.rc.i_qp_constant == 0 )
{ {
h->mb.b_lossless = 1; h->mb.b_lossless = 1;
...@@ -412,7 +416,6 @@ static int x264_validate_parameters( x264_t *h ) ...@@ -412,7 +416,6 @@ static int x264_validate_parameters( x264_t *h )
h->param.rc.f_qblur = 0; h->param.rc.f_qblur = 0;
if( h->param.rc.f_complexity_blur < 0 ) if( h->param.rc.f_complexity_blur < 0 )
h->param.rc.f_complexity_blur = 0; h->param.rc.f_complexity_blur = 0;
h->param.rc.i_qp_constant = x264_clip3(h->param.rc.i_qp_constant, 0, 51);
return 0; return 0;
} }
...@@ -519,7 +522,7 @@ x264_t *x264_encoder_open ( x264_param_t *param ) ...@@ -519,7 +522,7 @@ x264_t *x264_encoder_open ( x264_param_t *param )
h->frames.i_max_ref1 = h->sps->vui.i_num_reorder_frames; h->frames.i_max_ref1 = h->sps->vui.i_num_reorder_frames;
h->frames.i_max_dpb = h->sps->vui.i_max_dec_frame_buffering + 1; h->frames.i_max_dpb = h->sps->vui.i_max_dec_frame_buffering + 1;
h->frames.b_have_lowres = !h->param.rc.b_stat_read h->frames.b_have_lowres = !h->param.rc.b_stat_read
&& ( h->param.rc.b_cbr || h->param.b_bframe_adaptive ); && ( h->param.rc.b_cbr || h->param.rc.i_rf_constant || h->param.b_bframe_adaptive );
for( i = 0; i < X264_BFRAME_MAX + 3; i++ ) for( i = 0; i < X264_BFRAME_MAX + 3; i++ )
{ {
......
...@@ -105,6 +105,7 @@ struct x264_ratecontrol_t ...@@ -105,6 +105,7 @@ struct x264_ratecontrol_t
double cbr_decay; double cbr_decay;
double short_term_cplxsum; double short_term_cplxsum;
double short_term_cplxcount; double short_term_cplxcount;
double rate_factor_constant;
/* 2pass stuff */ /* 2pass stuff */
FILE *p_stat_file_out; FILE *p_stat_file_out;
...@@ -173,7 +174,7 @@ int x264_ratecontrol_new( x264_t *h ) ...@@ -173,7 +174,7 @@ int x264_ratecontrol_new( x264_t *h )
h->rc = rc = x264_malloc( sizeof( x264_ratecontrol_t ) ); h->rc = rc = x264_malloc( sizeof( x264_ratecontrol_t ) );
memset(rc, 0, sizeof(*rc)); memset(rc, 0, sizeof(*rc));
rc->b_abr = h->param.rc.b_cbr && !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; h->mb.b_variable_qp = 0;
...@@ -189,6 +190,8 @@ int x264_ratecontrol_new( x264_t *h ) ...@@ -189,6 +190,8 @@ int x264_ratecontrol_new( x264_t *h )
rc->last_non_b_pict_type = -1; rc->last_non_b_pict_type = -1;
rc->cbr_decay = 1.0; rc->cbr_decay = 1.0;
if( rc->b_2pass && h->param.rc.i_rf_constant )
x264_log(h, X264_LOG_ERROR, "constant rate-factor is incompatible with 2pass.\n");
if( h->param.rc.i_vbv_max_bitrate < h->param.rc.i_bitrate && if( h->param.rc.i_vbv_max_bitrate < h->param.rc.i_bitrate &&
h->param.rc.i_vbv_max_bitrate > 0) h->param.rc.i_vbv_max_bitrate > 0)
x264_log(h, X264_LOG_ERROR, "max bitrate less than average bitrate, ignored.\n"); x264_log(h, X264_LOG_ERROR, "max bitrate less than average bitrate, ignored.\n");
...@@ -217,13 +220,21 @@ int x264_ratecontrol_new( x264_t *h ) ...@@ -217,13 +220,21 @@ int x264_ratecontrol_new( x264_t *h )
{ {
/* FIXME shouldn't need to arbitrarily specify a QP, /* FIXME shouldn't need to arbitrarily specify a QP,
* but this is more robust than BPP measures */ * but this is more robust than BPP measures */
#define ABR_INIT_QP 24 #define ABR_INIT_QP ( h->param.rc.i_rf_constant > 0 ? h->param.rc.i_rf_constant : 24 )
rc->accum_p_norm = .01; rc->accum_p_norm = .01;
rc->accum_p_qp = ABR_INIT_QP * rc->accum_p_norm; rc->accum_p_qp = ABR_INIT_QP * rc->accum_p_norm;
rc->cplxr_sum = .01; rc->cplxr_sum = .01;
rc->wanted_bits_window = .01; rc->wanted_bits_window = .01;
} }
if( h->param.rc.i_rf_constant )
{
/* arbitrary rescaling to make CRF somewhat similar to QP */
double base_cplx = h->mb.i_mb_count * (h->param.i_bframe ? 120 : 80);
rc->rate_factor_constant = pow( base_cplx, 1 - h->param.rc.f_qcompress )
/ qp2qscale( h->param.rc.i_rf_constant );
}
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( (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_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( (int)( qscale2qp( qp2qscale( h->param.rc.i_qp_constant ) * fabs( h->param.rc.f_pb_factor )) + 0.5 ), 0, 51 );
...@@ -895,12 +906,21 @@ static float rate_estimate_qscale(x264_t *h, int pict_type) ...@@ -895,12 +906,21 @@ static float rate_estimate_qscale(x264_t *h, int pict_type)
rce.s_count = 0; rce.s_count = 0;
rce.qscale = 1; rce.qscale = 1;
rce.pict_type = pict_type; rce.pict_type = pict_type;
q = get_qscale(h, &rce, rcc->wanted_bits_window / rcc->cplxr_sum, h->fenc->i_frame);
wanted_bits = h->fenc->i_frame * rcc->bitrate / rcc->fps; if( h->param.rc.i_rf_constant )
abr_buffer *= X264_MAX( 1, sqrt(h->fenc->i_frame/25) ); {
overflow = x264_clip3f( 1.0 + (total_bits - wanted_bits) / abr_buffer, .5, 2 ); q = get_qscale( h, &rce, rcc->rate_factor_constant, h->fenc->i_frame );
q *= overflow; overflow = 1;
}
else
{
q = get_qscale( h, &rce, rcc->wanted_bits_window / rcc->cplxr_sum, h->fenc->i_frame );
wanted_bits = h->fenc->i_frame * rcc->bitrate / rcc->fps;
abr_buffer *= X264_MAX( 1, sqrt(h->fenc->i_frame/25) );
overflow = x264_clip3f( 1.0 + (total_bits - wanted_bits) / abr_buffer, .5, 2 );
q *= overflow;
}
if( pict_type == SLICE_TYPE_I if( pict_type == SLICE_TYPE_I
/* should test _next_ pict type, but that isn't decided yet */ /* should test _next_ pict type, but that isn't decided yet */
......
...@@ -206,6 +206,7 @@ static void Help( x264_param_t *defaults ) ...@@ -206,6 +206,7 @@ static void Help( x264_param_t *defaults )
"\n" "\n"
" -q, --qp <integer> Set QP (0=lossless) [%d]\n" " -q, --qp <integer> Set QP (0=lossless) [%d]\n"
" -B, --bitrate <integer> Set bitrate\n" " -B, --bitrate <integer> Set bitrate\n"
" --crf <integer> Quality-based VBR (nominal QP)\n"
" --qpmin <integer> Set min QP [%d]\n" " --qpmin <integer> Set min QP [%d]\n"
" --qpmax <integer> Set max QP [%d]\n" " --qpmax <integer> Set max QP [%d]\n"
" --qpstep <integer> Set max QP step [%d]\n" " --qpstep <integer> Set max QP step [%d]\n"
...@@ -470,6 +471,7 @@ static int Parse( int argc, char **argv, ...@@ -470,6 +471,7 @@ static int Parse( int argc, char **argv,
#define OPT_COLOURMATRIX 312 #define OPT_COLOURMATRIX 312
#define OPT_CHROMALOC 313 #define OPT_CHROMALOC 313
#define OPT_MIXED_REFS 314 #define OPT_MIXED_REFS 314
#define OPT_CRF 315
static struct option long_options[] = static struct option long_options[] =
{ {
...@@ -489,6 +491,7 @@ static int Parse( int argc, char **argv, ...@@ -489,6 +491,7 @@ static int Parse( int argc, char **argv,
{ "qpmin", required_argument, NULL, OPT_QPMIN }, { "qpmin", required_argument, NULL, OPT_QPMIN },
{ "qpmax", required_argument, NULL, OPT_QPMAX }, { "qpmax", required_argument, NULL, OPT_QPMAX },
{ "qpstep", required_argument, NULL, OPT_QPSTEP }, { "qpstep", required_argument, NULL, OPT_QPSTEP },
{ "crf", required_argument, NULL, OPT_CRF },
{ "ref", required_argument, NULL, 'r' }, { "ref", required_argument, NULL, 'r' },
{ "no-asm", no_argument, NULL, 'C' }, { "no-asm", no_argument, NULL, 'C' },
{ "sar", required_argument, NULL, OPT_SAR }, { "sar", required_argument, NULL, OPT_SAR },
...@@ -571,6 +574,9 @@ static int Parse( int argc, char **argv, ...@@ -571,6 +574,9 @@ static int Parse( int argc, char **argv,
param->rc.i_bitrate = atol( optarg ); param->rc.i_bitrate = atol( optarg );
param->rc.b_cbr = 1; param->rc.b_cbr = 1;
break; break;
case OPT_CRF:
param->rc.i_rf_constant = atol( optarg );
break;
case 'b': case 'b':
param->i_bframe = atol( optarg ); param->i_bframe = atol( optarg );
break; break;
......
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
#include <stdarg.h> #include <stdarg.h>
#define X264_BUILD 36 #define X264_BUILD 37
/* x264_t: /* x264_t:
* opaque handler for decoder and encoder */ * opaque handler for decoder and encoder */
...@@ -204,13 +204,14 @@ typedef struct ...@@ -204,13 +204,14 @@ typedef struct
/* Rate control parameters */ /* Rate control parameters */
struct struct
{ {
int i_qp_constant; /* 1-51 */ int i_qp_constant; /* 0-51 */
int i_qp_min; /* min allowed QP value */ int i_qp_min; /* min allowed QP value */
int i_qp_max; /* max allowed QP value */ int i_qp_max; /* max allowed QP value */
int i_qp_step; /* max QP step between frames */ int i_qp_step; /* max QP step between frames */
int b_cbr; /* use bitrate instead of CQP */ int b_cbr; /* use bitrate instead of CQP */
int i_bitrate; int i_bitrate;
int i_rf_constant; /* 1pass VBR, nominal QP */
float f_rate_tolerance; float f_rate_tolerance;
int i_vbv_max_bitrate; int i_vbv_max_bitrate;
int i_vbv_buffer_size; int i_vbv_buffer_size;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment