From: Fiona Glaser Date: Wed, 30 Jun 2010 20:55:46 +0000 (-0700) Subject: Support infinite keyint (--keyint infinite). X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=b7789b1f08e27103576d9b9f0feea9b75e2eca56;p=x264 Support infinite keyint (--keyint infinite). This just means x264 won't insert non-scenecut keyframes. Useful for streaming when using interactive error recovery or some other mechanism that makes keyframes unnecessary. Also change POC logic to limit POC/framenum LSB size (to save bits per slice). Also fix a bug in the CPB underflow detection code (didn't affect the bitstream, just resulted in the failure to print certain warning messages). --- diff --git a/common/common.c b/common/common.c index 8c7cf3c3..14dd7167 100644 --- a/common/common.c +++ b/common/common.c @@ -638,9 +638,10 @@ int x264_param_parse( x264_param_t *p, const char *name, const char *value ) p->i_dpb_size = atoi(value); OPT("keyint") { - p->i_keyint_max = atoi(value); - if( p->i_keyint_min > p->i_keyint_max ) - p->i_keyint_min = p->i_keyint_max; + if( strstr( value, "infinite" ) ) + p->i_keyint_max = X264_KEYINT_MAX_INFINITE; + else + p->i_keyint_max = atoi(value); } OPT2("min-keyint", "keyint-min") { diff --git a/encoder/encoder.c b/encoder/encoder.c index 27f33235..6a2aacb7 100644 --- a/encoder/encoder.c +++ b/encoder/encoder.c @@ -567,8 +567,7 @@ static int x264_validate_parameters( x264_t *h ) h->param.i_frame_reference = x264_clip3( h->param.i_frame_reference, 1, 16 ); h->param.i_dpb_size = x264_clip3( h->param.i_dpb_size, 1, 16 ); - if( h->param.i_keyint_max <= 0 ) - h->param.i_keyint_max = 1; + h->param.i_keyint_max = x264_clip3( h->param.i_keyint_max, 1, X264_KEYINT_MAX_INFINITE ); if( h->param.i_scenecut_threshold < 0 ) h->param.i_scenecut_threshold = 0; if( !h->param.analyse.i_subpel_refine && h->param.analyse.i_direct_mv_pred > X264_DIRECT_PRED_SPATIAL ) @@ -627,9 +626,10 @@ static int x264_validate_parameters( x264_t *h ) h->param.rc.f_qcompress = x264_clip3f( h->param.rc.f_qcompress, 0.0, 1.0 ); if( h->param.i_keyint_max == 1 || h->param.rc.f_qcompress == 1 ) h->param.rc.b_mb_tree = 0; - if( !h->param.rc.i_lookahead && !h->param.b_intra_refresh && h->param.rc.b_mb_tree ) + if( (!h->param.b_intra_refresh && h->param.i_keyint_max != X264_KEYINT_MAX_INFINITE) && + !h->param.rc.i_lookahead && h->param.rc.b_mb_tree ) { - x264_log( h, X264_LOG_WARNING, "lookaheadless mb-tree requires intra refresh\n" ); + x264_log( h, X264_LOG_WARNING, "lookaheadless mb-tree requires intra refresh or infinite keyint\n" ); h->param.rc.b_mb_tree = 0; } if( h->param.rc.b_stat_read ) diff --git a/encoder/ratecontrol.c b/encoder/ratecontrol.c index a588de90..7f5ba962 100644 --- a/encoder/ratecontrol.c +++ b/encoder/ratecontrol.c @@ -492,13 +492,13 @@ void x264_ratecontrol_init_reconfigurable( x264_t *h, int b_init ) // arbitrary #define MAX_DURATION 0.5 - int max_cpb_output_delay = h->param.i_keyint_max * MAX_DURATION * h->sps->vui.i_time_scale / h->sps->vui.i_num_units_in_tick; + int max_cpb_output_delay = X264_MIN( h->param.i_keyint_max * MAX_DURATION * h->sps->vui.i_time_scale / h->sps->vui.i_num_units_in_tick, INT_MAX ); int max_dpb_output_delay = h->sps->vui.i_max_dec_frame_buffering * MAX_DURATION * h->sps->vui.i_time_scale / h->sps->vui.i_num_units_in_tick; int max_delay = (int)(90000.0 * (double)h->sps->vui.hrd.i_cpb_size_unscaled / h->sps->vui.hrd.i_bit_rate_unscaled + 0.5); h->sps->vui.hrd.i_initial_cpb_removal_delay_length = 2 + x264_clip3( 32 - x264_clz( max_delay ), 4, 22 ); - h->sps->vui.hrd.i_cpb_removal_delay_length = x264_clip3( 32 - x264_clz( max_cpb_output_delay ), 4, 32 ); - h->sps->vui.hrd.i_dpb_output_delay_length = x264_clip3( 32 - x264_clz( max_dpb_output_delay ), 4, 32 ); + h->sps->vui.hrd.i_cpb_removal_delay_length = x264_clip3( 32 - x264_clz( max_cpb_output_delay ), 4, 31 ); + h->sps->vui.hrd.i_dpb_output_delay_length = x264_clip3( 32 - x264_clz( max_dpb_output_delay ), 4, 31 ); #undef MAX_DURATION @@ -1781,10 +1781,10 @@ void x264_hrd_fullness( x264_t *h ) uint64_t cpb_size = (uint64_t)h->sps->vui.hrd.i_cpb_size_unscaled * h->sps->vui.i_time_scale; uint64_t multiply_factor = 180000 / rct->hrd_multiply_denom; - if( cpb_state < 0 || cpb_state > cpb_size ) + if( rct->buffer_fill_final < 0 || rct->buffer_fill_final > cpb_size ) { x264_log( h, X264_LOG_WARNING, "CPB %s: %.0lf bits in a %.0lf-bit buffer\n", - cpb_state < 0 ? "underflow" : "overflow", (float)cpb_state/denom, (float)cpb_size/denom ); + rct->buffer_fill_final < 0 ? "underflow" : "overflow", (float)rct->buffer_fill_final/denom, (float)cpb_size/denom ); } h->initial_cpb_removal_delay = (multiply_factor * cpb_state + denom) / (2*denom); diff --git a/encoder/set.c b/encoder/set.c index 8ea6eac8..9e6e736b 100644 --- a/encoder/set.c +++ b/encoder/set.c @@ -99,6 +99,7 @@ static void x264_sei_write( bs_t *s, uint8_t *p_start ) void x264_sps_init( x264_sps_t *sps, int i_id, x264_param_t *param ) { sps->i_id = i_id; + int max_frame_num; 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 ) @@ -118,15 +119,27 @@ void x264_sps_init( x264_sps_t *sps, int i_id, x264_param_t *param ) /* Never set constraint_set2, it is not necessary and not used in real world. */ sps->b_constraint_set2 = 0; - sps->i_log2_max_frame_num = 4; /* at least 4 */ - while( (1 << sps->i_log2_max_frame_num) <= param->i_keyint_max && sps->i_log2_max_frame_num < 10 ) + sps->vui.i_num_reorder_frames = param->i_bframe_pyramid ? 2 : param->i_bframe ? 1 : 0; + /* extra slot with pyramid so that we don't have to override the + * order of forgetting old pictures */ + sps->vui.i_max_dec_frame_buffering = + sps->i_num_ref_frames = X264_MIN(16, X264_MAX4(param->i_frame_reference, 1 + sps->vui.i_num_reorder_frames, + param->i_bframe_pyramid ? 4 : 1, param->i_dpb_size)); + sps->i_num_ref_frames -= param->i_bframe_pyramid == X264_B_PYRAMID_STRICT; + + /* number of refs + current frame */ + max_frame_num = sps->vui.i_max_dec_frame_buffering * (!!param->i_bframe_pyramid+1) + 1; + sps->i_log2_max_frame_num = 4; + while( (1 << sps->i_log2_max_frame_num) <= max_frame_num ) sps->i_log2_max_frame_num++; - sps->i_log2_max_frame_num++; sps->i_poc_type = 0; if( sps->i_poc_type == 0 ) { - sps->i_log2_max_poc_lsb = sps->i_log2_max_frame_num + 1; /* max poc = 2*frame_num */ + int max_delta_poc = (param->i_bframe + 2) * (!!param->i_bframe_pyramid + 1) * 2; + sps->i_log2_max_poc_lsb = 4; + while( (1 << sps->i_log2_max_poc_lsb) <= max_delta_poc * 2 ) + sps->i_log2_max_poc_lsb++; } else if( sps->i_poc_type == 1 ) { @@ -219,14 +232,6 @@ void x264_sps_init( x264_sps_t *sps, int i_id, x264_param_t *param ) // NOTE: HRD related parts of the SPS are initialised in x264_ratecontrol_init_reconfigurable - sps->vui.i_num_reorder_frames = param->i_bframe_pyramid ? 2 : param->i_bframe ? 1 : 0; - /* extra slot with pyramid so that we don't have to override the - * order of forgetting old pictures */ - sps->vui.i_max_dec_frame_buffering = - sps->i_num_ref_frames = X264_MIN(16, X264_MAX4(param->i_frame_reference, 1 + sps->vui.i_num_reorder_frames, - param->i_bframe_pyramid ? 4 : 1, param->i_dpb_size)); - sps->i_num_ref_frames -= param->i_bframe_pyramid == X264_B_PYRAMID_STRICT; - sps->vui.b_bitstream_restriction = 1; if( sps->vui.b_bitstream_restriction ) { diff --git a/encoder/slicetype.c b/encoder/slicetype.c index 566ce627..84a82de1 100644 --- a/encoder/slicetype.c +++ b/encoder/slicetype.c @@ -1009,7 +1009,7 @@ static int scenecut_internal( x264_t *h, x264_mb_analysis_t *a, x264_frame_t **f float f_thresh_max = h->param.i_scenecut_threshold / 100.0; /* magic numbers pulled out of thin air */ float f_thresh_min = f_thresh_max * h->param.i_keyint_min - / ( h->param.i_keyint_max * 4 ); + / ( h->param.i_keyint_max * 4. ); int res; if( h->param.i_keyint_min == h->param.i_keyint_max ) diff --git a/x264.c b/x264.c index 741570c7..0bede93b 100644 --- a/x264.c +++ b/x264.c @@ -409,7 +409,7 @@ static void Help( x264_param_t *defaults, int longhelp ) H0( "\n" ); H0( "Frame-type options:\n" ); H0( "\n" ); - H0( " -I, --keyint Maximum GOP size [%d]\n", defaults->i_keyint_max ); + H0( " -I, --keyint Maximum GOP size [%d]\n", defaults->i_keyint_max ); H2( " -i, --min-keyint Minimum GOP size [auto]\n" ); H2( " --no-scenecut Disable adaptive I-frame decision\n" ); H2( " --scenecut How aggressively to insert extra I-frames [%d]\n", defaults->i_scenecut_threshold ); diff --git a/x264.h b/x264.h index 86f7426a..097365a4 100644 --- a/x264.h +++ b/x264.h @@ -35,7 +35,7 @@ #include -#define X264_BUILD 101 +#define X264_BUILD 102 /* x264_t: * opaque handler for encoder */ @@ -152,6 +152,7 @@ typedef struct #define X264_B_PYRAMID_STRICT 1 #define X264_B_PYRAMID_NORMAL 2 #define X264_KEYINT_MIN_AUTO 0 +#define X264_KEYINT_MAX_INFINITE (1<<30) #define X264_OPEN_GOP_NONE 0 #define X264_OPEN_GOP_NORMAL 1 #define X264_OPEN_GOP_BLURAY 2