[x264-devel] commit: Improve scenecut detection a bit (Jason Garrett-Glaser )

git at videolan.org git at videolan.org
Thu Jul 15 04:08:58 CEST 2010


x264 | branch: stable | 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