Put a minimum value on the scenecut threshold; makes x264 more likely to catch successive scenecuts (but might increase the odds of false detection).
This also fixes scenecut detection with keyint=infinite.
Also print keyint=infinite in the x264 SEI and statsfile correctly.
}
s += sprintf( s, " weightp=%d", p->analyse.i_weighted_pred > 0 ? p->analyse.i_weighted_pred : 0 );
- s += sprintf( s, " keyint=%d keyint_min=%d scenecut=%d intra_refresh=%d",
- p->i_keyint_max, p->i_keyint_min, p->i_scenecut_threshold, p->b_intra_refresh );
+ if( p->i_keyint_max == X264_KEYINT_MAX_INFINITE )
+ s += sprintf( s, " keyint=infinite" );
+ else
+ s += sprintf( s, " keyint=%d", p->i_keyint_max );
+ s += sprintf( s, " keyint_min=%d scenecut=%d intra_refresh=%d",
+ p->i_keyint_min, p->i_scenecut_threshold, p->b_intra_refresh );
if( p->rc.b_mb_tree || p->rc.i_vbv_buffer_size )
s += sprintf( s, " rc_lookahead=%d", p->rc.i_lookahead );
x264_log( h, X264_LOG_WARNING, "intra-refresh is not compatible with open-gop\n" );
h->param.i_open_gop = X264_OPEN_GOP_NONE;
}
+ float fps = h->param.i_fps_num > 0 && h->param.i_fps_den > 0 ? (float) h->param.i_fps_num / h->param.i_fps_den : 25.0;
if( h->param.i_keyint_min == X264_KEYINT_MIN_AUTO )
- h->param.i_keyint_min = h->param.i_keyint_max / 10;
+ h->param.i_keyint_min = X264_MIN( h->param.i_keyint_max / 10, fps );
h->param.i_keyint_min = x264_clip3( h->param.i_keyint_min, 1, h->param.i_keyint_max/2+1 );
h->param.rc.i_lookahead = x264_clip3( h->param.rc.i_lookahead, 0, X264_LOOKAHEAD_MAX );
{
int maxrate = X264_MAX( h->param.rc.i_vbv_max_bitrate, h->param.rc.i_bitrate );
float bufsize = maxrate ? (float)h->param.rc.i_vbv_buffer_size / maxrate : 0;
- float fps = h->param.i_fps_num > 0 && h->param.i_fps_den > 0 ? (float) h->param.i_fps_num / h->param.i_fps_den : 25.0;
h->param.rc.i_lookahead = X264_MIN( h->param.rc.i_lookahead, X264_MAX( h->param.i_keyint_max, bufsize*fps ) );
}
CMP_OPT_FIRST_PASS( "bframes", h->param.i_bframe );
CMP_OPT_FIRST_PASS( "b_pyramid", h->param.i_bframe_pyramid );
CMP_OPT_FIRST_PASS( "intra_refresh", h->param.b_intra_refresh );
- CMP_OPT_FIRST_PASS( "keyint", h->param.i_keyint_max );
CMP_OPT_FIRST_PASS( "open_gop", h->param.i_open_gop );
+ if( (p = strstr( opts, "keyint=" )) )
+ {
+ p += 7;
+ char buf[13] = "infinite ";
+ if( h->param.i_keyint_max != X264_KEYINT_MAX_INFINITE )
+ sprintf( buf, "%d ", h->param.i_keyint_max );
+ if( strncmp( p, buf, strlen(buf) ) )
+ {
+ x264_log( h, X264_LOG_ERROR, "different keyint setting than first pass (%.*s vs %.*s)\n",
+ strlen(buf)-1, buf, strcspn(p, " "), p );
+ return -1;
+ }
+ }
+
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" );
int i_gop_size = frame->i_frame - h->lookahead->i_last_keyframe;
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. );
+ float f_thresh_min = f_thresh_max * 0.25;
int res;
if( h->param.i_keyint_min == h->param.i_keyint_max )
- f_thresh_min= f_thresh_max;
- if( i_gop_size < h->param.i_keyint_min / 4 || h->param.b_intra_refresh )
+ f_thresh_min = f_thresh_max;
+ if( i_gop_size <= h->param.i_keyint_min / 4 || h->param.b_intra_refresh )
f_bias = f_thresh_min / 4;
else if( i_gop_size <= h->param.i_keyint_min )
f_bias = f_thresh_min * i_gop_size / h->param.i_keyint_min;
{
f_bias = f_thresh_min
+ ( f_thresh_max - f_thresh_min )
- * ( i_gop_size - h->param.i_keyint_min )
- / ( h->param.i_keyint_max - h->param.i_keyint_min ) ;
+ * ( i_gop_size - h->param.i_keyint_min )
+ / ( h->param.i_keyint_max - h->param.i_keyint_min );
}
res = pcost >= (1.0 - f_bias) * icost;