From b8692db2efa98c719332979f6dc8fc39af8f1eff Mon Sep 17 00:00:00 2001 From: Loren Merritt Date: Tue, 18 Jul 2006 01:10:54 +0000 Subject: [PATCH] api change: select ratecontrol method with an enum (param.rc.i_rc_method) instead of a bunch of booleans. git-svn-id: svn://svn.videolan.org/x264/trunk@537 df754926-b1dd-0310-bc7b-ec298dee348c --- common/common.c | 16 ++++++++-------- encoder/analyse.c | 2 +- encoder/encoder.c | 24 +++++++++++++++--------- encoder/ratecontrol.c | 34 ++++++++++++++++++---------------- encoder/set.c | 4 ++-- vfw/codec.c | 5 +++-- x264.c | 4 +++- x264.h | 9 +++++++-- 8 files changed, 57 insertions(+), 41 deletions(-) diff --git a/common/common.c b/common/common.c index f48c50a5..d882484b 100644 --- a/common/common.c +++ b/common/common.c @@ -80,7 +80,7 @@ void x264_param_default( x264_param_t *param ) param->b_cabac = 1; param->i_cabac_init_idc = 0; - param->rc.b_cbr = 0; + param->rc.i_rc_method = X264_RC_CQP; param->rc.i_bitrate = 0; param->rc.f_rate_tolerance = 1.0; param->rc.i_vbv_max_bitrate = 0; @@ -494,12 +494,12 @@ char *x264_param2string( x264_param_t *p, int b_res ) s += sprintf( s, " keyint=%d keyint_min=%d scenecut=%d", p->i_keyint_max, p->i_keyint_min, p->i_scenecut_threshold ); - s += sprintf( s, " rc=%s", p->rc.b_stat_read && p->rc.b_cbr ? "2pass" : - p->rc.b_cbr ? p->rc.i_vbv_buffer_size ? "cbr" : "abr" : - p->rc.i_rf_constant ? "crf" : "cqp" ); - if( p->rc.b_cbr || p->rc.i_rf_constant ) + s += sprintf( s, " rc=%s", p->rc.i_rc_method == X264_RC_ABR ? + ( p->rc.b_stat_read ? "2pass" : p->rc.i_vbv_buffer_size ? "cbr" : "abr" ) + : p->rc.i_rc_method == X264_RC_CRF ? "crf" : "cqp" ); + if( p->rc.i_rc_method == X264_RC_ABR || p->rc.i_rc_method == X264_RC_CRF ) { - if( p->rc.i_rf_constant ) + if( p->rc.i_rc_method == X264_RC_CRF ) s += sprintf( s, " crf=%d", p->rc.i_rf_constant ); else s += sprintf( s, " bitrate=%d ratetol=%.1f", @@ -514,9 +514,9 @@ char *x264_param2string( x264_param_t *p, int b_res ) s += sprintf( s, " vbv_maxrate=%d vbv_bufsize=%d", p->rc.i_vbv_max_bitrate, p->rc.i_vbv_buffer_size ); } - else + else if( p->rc.i_rc_method == X264_RC_CQP ) s += sprintf( s, " qp=%d", p->rc.i_qp_constant ); - if( p->rc.b_cbr || p->rc.i_qp_constant != 0 ) + if( !(p->rc.i_rc_method == X264_RC_CQP && p->rc.i_qp_constant == 0) ) { s += sprintf( s, " ip_ratio=%.2f", p->rc.f_ip_factor ); if( p->i_bframe ) diff --git a/encoder/analyse.c b/encoder/analyse.c index 5b085716..424c5da1 100644 --- a/encoder/analyse.c +++ b/encoder/analyse.c @@ -422,7 +422,7 @@ static void x264_mb_analyse_intra_chroma( x264_t *h, x264_mb_analysis_t *a ) int i; int i_max; - int predict_mode[9]; + int predict_mode[4]; uint8_t *p_dstc[2], *p_srcc[2]; diff --git a/encoder/encoder.c b/encoder/encoder.c index e8472c3f..51af962a 100644 --- a/encoder/encoder.c +++ b/encoder/encoder.c @@ -341,20 +341,25 @@ static int x264_validate_parameters( x264_t *h ) } #endif - if( h->param.rc.b_cbr ) - h->param.rc.i_rf_constant = 0; - if( h->param.rc.i_rf_constant > 0 ) - h->param.rc.i_qp_constant = h->param.rc.i_rf_constant; + if( h->param.rc.i_rc_method < 0 || h->param.rc.i_rc_method > 2 ) + { + x264_log( h, X264_LOG_ERROR, "invalid RC method\n" ); + return -1; + } 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.i_rc_method == X264_RC_CRF ) + h->param.rc.i_qp_constant = h->param.rc.i_rf_constant; + if( (h->param.rc.i_rc_method == X264_RC_CQP || h->param.rc.i_rc_method == X264_RC_CRF) + && h->param.rc.i_qp_constant == 0 ) { h->mb.b_lossless = 1; - h->param.analyse.b_transform_8x8 = 0; h->param.i_cqm_preset = X264_CQM_FLAT; h->param.psz_cqm_file = NULL; + h->param.rc.i_rc_method = X264_RC_CQP; h->param.rc.f_ip_factor = 1; h->param.rc.f_pb_factor = 1; + h->param.analyse.b_transform_8x8 = 0; h->param.analyse.b_psnr = 0; h->param.analyse.i_chroma_qp_offset = 0; h->param.analyse.i_trellis = 0; @@ -448,7 +453,6 @@ static int x264_validate_parameters( x264_t *h ) BOOLIFY( analyse.b_bidir_me ); BOOLIFY( analyse.b_chroma_me ); BOOLIFY( analyse.b_fast_pskip ); - BOOLIFY( rc.b_cbr ); BOOLIFY( rc.b_stat_write ); BOOLIFY( rc.b_stat_read ); #undef BOOLIFY @@ -522,7 +526,7 @@ x264_t *x264_encoder_open ( x264_param_t *param ) /* Init x264_t */ h->out.i_nal = 0; h->out.i_bitstream = X264_MAX( 1000000, h->param.i_width * h->param.i_height * 1.7 - * ( h->param.rc.b_cbr ? pow( 0.5, h->param.rc.i_qp_min ) + * ( h->param.rc.i_rc_method == X264_RC_ABR ? pow( 0.5, h->param.rc.i_qp_min ) : pow( 0.5, h->param.rc.i_qp_constant ) * X264_MAX( 1, h->param.rc.f_ip_factor ))); h->out.p_bitstream = x264_malloc( h->out.i_bitstream ); @@ -548,7 +552,9 @@ 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_dpb = h->sps->vui.i_max_dec_frame_buffering + 1; h->frames.b_have_lowres = !h->param.rc.b_stat_read - && ( h->param.rc.b_cbr || h->param.rc.i_rf_constant || h->param.b_bframe_adaptive ); + && ( h->param.rc.i_rc_method == X264_RC_ABR + || h->param.rc.i_rc_method == X264_RC_CRF + || h->param.b_bframe_adaptive ); for( i = 0; i < X264_BFRAME_MAX + 3; i++ ) { diff --git a/encoder/ratecontrol.c b/encoder/ratecontrol.c index 9a7e25d2..7393261f 100644 --- a/encoder/ratecontrol.c +++ b/encoder/ratecontrol.c @@ -200,8 +200,8 @@ int x264_ratecontrol_new( x264_t *h ) h->rc = rc = x264_malloc( h->param.i_threads * sizeof(x264_ratecontrol_t) ); 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_2pass = h->param.rc.b_cbr && h->param.rc.b_stat_read; + rc->b_abr = h->param.rc.i_rc_method != X264_RC_CQP && !h->param.rc.b_stat_read; + rc->b_2pass = h->param.rc.i_rc_method == X264_RC_ABR && h->param.rc.b_stat_read; /* FIXME: use integers */ if(h->param.i_fps_num > 0 && h->param.i_fps_den > 0) @@ -215,18 +215,20 @@ int x264_ratecontrol_new( x264_t *h ) rc->last_non_b_pict_type = -1; rc->cbr_decay = 1.0; - if( h->param.rc.i_rf_constant && h->param.rc.b_stat_read ) + if( h->param.rc.i_rc_method == X264_RC_CRF && h->param.rc.b_stat_read ) { x264_log(h, X264_LOG_ERROR, "constant rate-factor is incompatible with 2pass.\n"); return -1; } - if( h->param.rc.i_vbv_buffer_size && !h->param.rc.b_cbr && !h->param.rc.i_rf_constant ) - x264_log(h, X264_LOG_WARNING, "VBV is incompatible with constant QP.\n"); - if( h->param.rc.i_vbv_buffer_size && h->param.rc.b_cbr - && h->param.rc.i_vbv_max_bitrate == 0 ) + if( h->param.rc.i_vbv_buffer_size ) { - x264_log( h, X264_LOG_DEBUG, "VBV maxrate unspecified, assuming CBR\n" ); - h->param.rc.i_vbv_max_bitrate = h->param.rc.i_bitrate; + if( h->param.rc.i_rc_method == X264_RC_CQP ) + x264_log(h, X264_LOG_WARNING, "VBV is incompatible with constant QP, ignored.\n"); + else if( h->param.rc.i_vbv_max_bitrate == 0 ) + { + x264_log( h, X264_LOG_DEBUG, "VBV maxrate unspecified, assuming CBR\n" ); + 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) @@ -259,14 +261,14 @@ int x264_ratecontrol_new( x264_t *h ) { /* FIXME shouldn't need to arbitrarily specify a QP, * but this is more robust than BPP measures */ -#define ABR_INIT_QP ( h->param.rc.i_rf_constant > 0 ? h->param.rc.i_rf_constant : 24 ) +#define ABR_INIT_QP ( h->param.rc.i_rc_method == X264_RC_CRF ? h->param.rc.i_rf_constant : 24 ) rc->accum_p_norm = .01; rc->accum_p_qp = ABR_INIT_QP * rc->accum_p_norm; rc->cplxr_sum = .01; rc->wanted_bits_window = .01; } - if( h->param.rc.i_rf_constant ) + if( h->param.rc.i_rc_method == X264_RC_CRF ) { /* arbitrary rescaling to make CRF somewhat similar to QP */ double base_cplx = h->mb.i_mb_count * (h->param.i_bframe ? 120 : 80); @@ -342,7 +344,7 @@ int x264_ratecontrol_new( x264_t *h ) x264_log( h, X264_LOG_WARNING, "different keyint than 1st pass (%d vs %d)\n", h->param.i_keyint_max, i ); - if( strstr( opts, "qp=0" ) && h->param.rc.b_cbr ) + if( strstr( opts, "qp=0" ) && h->param.rc.i_rc_method == X264_RC_ABR ) x264_log( h, X264_LOG_WARNING, "1st pass was lossless, bitrate prediction will be inaccurate\n" ); } @@ -432,7 +434,7 @@ int x264_ratecontrol_new( x264_t *h ) x264_free(stats_buf); - if(h->param.rc.b_cbr) + if(h->param.rc.i_rc_method == X264_RC_ABR) { if(init_pass2(h) < 0) return -1; } /* else we're using constant quant, so no need to run the bitrate allocation */ @@ -524,7 +526,7 @@ static int parse_zones( x264_t *h ) void x264_ratecontrol_summary( x264_t *h ) { x264_ratecontrol_t *rc = h->rc; - if( rc->b_abr && !h->param.rc.i_rf_constant && !h->param.rc.i_vbv_max_bitrate ) + if( rc->b_abr && h->param.rc.i_rc_method == X264_RC_ABR && !h->param.rc.i_vbv_max_bitrate ) { double base_cplx = h->mb.i_mb_count * (h->param.i_bframe ? 120 : 80); x264_log( h, X264_LOG_INFO, "final ratefactor: %.2f\n", @@ -739,7 +741,7 @@ int x264_ratecontrol_slice_type( x264_t *h, int frame_num ) rc->b_abr = 0; rc->b_2pass = 0; - h->param.rc.b_cbr = 0; + h->param.rc.i_rc_method = X264_RC_CQP; h->param.rc.b_stat_read = 0; h->param.b_bframe_adaptive = 0; if( h->param.i_bframe > 1 ) @@ -1235,7 +1237,7 @@ static float rate_estimate_qscale(x264_t *h, int pict_type) rce.qscale = 1; rce.pict_type = pict_type; - if( h->param.rc.i_rf_constant ) + if( h->param.rc.i_rc_method == X264_RC_CRF ) { q = get_qscale( h, &rce, rcc->rate_factor_constant, h->fenc->i_frame ); overflow = 1; diff --git a/encoder/set.c b/encoder/set.c index 7a67c5fd..bf88670b 100644 --- a/encoder/set.c +++ b/encoder/set.c @@ -77,7 +77,7 @@ void x264_sps_init( x264_sps_t *sps, int i_id, x264_param_t *param ) { sps->i_id = i_id; - sps->b_qpprime_y_zero_transform_bypass = !param->rc.b_cbr && param->rc.i_qp_constant == 0; + sps->b_qpprime_y_zero_transform_bypass = param->rc.i_rc_method == X264_RC_CQP && param->rc.i_qp_constant == 0; if( sps->b_qpprime_y_zero_transform_bypass ) sps->i_profile_idc = PROFILE_HIGH444; else if( param->analyse.b_transform_8x8 || param->i_cqm_preset != X264_CQM_FLAT ) @@ -376,7 +376,7 @@ void x264_pps_init( x264_pps_t *pps, int i_id, x264_param_t *param, x264_sps_t * pps->b_weighted_pred = 0; pps->b_weighted_bipred = param->analyse.b_weighted_bipred ? 2 : 0; - pps->i_pic_init_qp = param->rc.b_cbr ? 26 : param->rc.i_qp_constant; + pps->i_pic_init_qp = param->rc.i_rc_method == X264_RC_ABR ? 26 : param->rc.i_qp_constant; pps->i_pic_init_qs = 26; pps->i_chroma_qp_index_offset = param->analyse.i_chroma_qp_offset; diff --git a/vfw/codec.c b/vfw/codec.c index f9cd9c37..c9c3a61f 100644 --- a/vfw/codec.c +++ b/vfw/codec.c @@ -282,10 +282,11 @@ LRESULT compress_begin(CODEC * codec, BITMAPINFO * lpbiInput, BITMAPINFO * lpbiO switch( config->i_encoding_type ) { case 0: /* 1 PASS ABR */ - param.rc.b_cbr = 1; + param.rc.i_rc_method = X264_RC_ABR; param.rc.i_bitrate = config->bitrate; break; case 1: /* 1 PASS CQ */ + param.rc.i_rc_method = X264_RC_CQP; param.rc.i_qp_constant = config->i_qp; break; default: @@ -312,8 +313,8 @@ LRESULT compress_begin(CODEC * codec, BITMAPINFO * lpbiInput, BITMAPINFO * lpbiO return ICERR_ERROR; } + param.rc.i_rc_method = X264_RC_ABR; param.rc.i_bitrate = config->i_2passbitrate; - param.rc.b_cbr = 1; if( config->i_pass == 1 ) { diff --git a/x264.c b/x264.c index 4a75fcbe..d7074bfd 100644 --- a/x264.c +++ b/x264.c @@ -560,10 +560,11 @@ static int Parse( int argc, char **argv, break; case 'B': param->rc.i_bitrate = atol( optarg ); - param->rc.b_cbr = 1; + param->rc.i_rc_method = X264_RC_ABR; break; case OPT_CRF: param->rc.i_rf_constant = atol( optarg ); + param->rc.i_rc_method = X264_RC_CRF; break; case 'b': param->i_bframe = atol( optarg ); @@ -603,6 +604,7 @@ static int Parse( int argc, char **argv, } case 'q': param->rc.i_qp_constant = atoi( optarg ); + param->rc.i_rc_method = X264_RC_CQP; break; case OPT_QPMIN: param->rc.i_qp_min = atoi( optarg ); diff --git a/x264.h b/x264.h index 07fa4877..f2ff831e 100644 --- a/x264.h +++ b/x264.h @@ -35,7 +35,7 @@ #include -#define X264_BUILD 47 +#define X264_BUILD 48 /* x264_t: * opaque handler for decoder and encoder */ @@ -73,6 +73,10 @@ typedef struct x264_t x264_t; #define X264_CQM_JVT 1 #define X264_CQM_CUSTOM 2 +#define X264_RC_CQP 0 +#define X264_RC_CRF 1 +#define X264_RC_ABR 2 + static const char * const x264_direct_pred_names[] = { "none", "spatial", "temporal", "auto", 0 }; static const char * const x264_motion_est_names[] = { "dia", "hex", "umh", "esa", 0 }; @@ -212,12 +216,13 @@ typedef struct /* Rate control parameters */ struct { + int i_rc_method; /* X264_RC_* */ + int i_qp_constant; /* 0-51 */ int i_qp_min; /* min allowed QP value */ int i_qp_max; /* max allowed QP value */ int i_qp_step; /* max QP step between frames */ - int b_cbr; /* use bitrate instead of CQP */ int i_bitrate; int i_rf_constant; /* 1pass VBR, nominal QP */ float f_rate_tolerance; -- 2.40.0