Commit b4217e40 authored by Fiona Glaser's avatar Fiona Glaser

Improve scenecut detection a bit

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.
parent de8a6e9d
......@@ -1220,8 +1220,12 @@ char *x264_param2string( x264_param_t *p, int b_res )
}
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 );
......
......@@ -608,14 +608,14 @@ static int x264_validate_parameters( x264_t *h )
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 ) );
}
......
......@@ -724,9 +724,22 @@ int x264_ratecontrol_new( x264_t *h )
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" );
......
......@@ -1008,13 +1008,12 @@ static int scenecut_internal( x264_t *h, x264_mb_analysis_t *a, x264_frame_t **f
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;
......@@ -1022,8 +1021,8 @@ static int scenecut_internal( x264_t *h, x264_mb_analysis_t *a, x264_frame_t **f
{
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;
......
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