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).
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")
{
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 )
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 )
// 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
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);
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 )
/* 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 )
{
// 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 )
{
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 )
H0( "\n" );
H0( "Frame-type options:\n" );
H0( "\n" );
- H0( " -I, --keyint <integer> Maximum GOP size [%d]\n", defaults->i_keyint_max );
+ H0( " -I, --keyint <integer or \"infinite\"> Maximum GOP size [%d]\n", defaults->i_keyint_max );
H2( " -i, --min-keyint <integer> Minimum GOP size [auto]\n" );
H2( " --no-scenecut Disable adaptive I-frame decision\n" );
H2( " --scenecut <integer> How aggressively to insert extra I-frames [%d]\n", defaults->i_scenecut_threshold );
#include <stdarg.h>
-#define X264_BUILD 101
+#define X264_BUILD 102
/* x264_t:
* opaque handler for encoder */
#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