[x264-devel] commit: Improve scenecut detection a bit (Jason Garrett-Glaser )
git at videolan.org
git at videolan.org
Thu Jul 15 04:08:43 CEST 2010
x264 | branch: master | Jason Garrett-Glaser <darkshikari at gmail.com> | Thu Jul 8 12:45:25 2010 -0700| [27e4a3a732c8284225dd55a2c2c43bb08368f3fa] | committer: Jason Garrett-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.
> http://git.videolan.org/gitweb.cgi/x264.git/?a=commit;h=27e4a3a732c8284225dd55a2c2c43bb08368f3fa
---
common/common.c | 8 ++++++--
encoder/encoder.c | 4 ++--
encoder/ratecontrol.c | 15 ++++++++++++++-
encoder/slicetype.c | 11 +++++------
4 files changed, 27 insertions(+), 11 deletions(-)
diff --git a/common/common.c b/common/common.c
index 728dfab..ea6dc2e 100644
--- a/common/common.c
+++ b/common/common.c
@@ -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 );
diff --git a/encoder/encoder.c b/encoder/encoder.c
index f7e0e38..5af3e03 100644
--- a/encoder/encoder.c
+++ b/encoder/encoder.c
@@ -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 ) );
}
diff --git a/encoder/ratecontrol.c b/encoder/ratecontrol.c
index 8d0b7ae..a426f5f 100644
--- a/encoder/ratecontrol.c
+++ b/encoder/ratecontrol.c
@@ -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" );
diff --git a/encoder/slicetype.c b/encoder/slicetype.c
index ad2a8c2..2ff9d23 100644
--- a/encoder/slicetype.c
+++ b/encoder/slicetype.c
@@ -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;
More information about the x264-devel
mailing list