[x264-devel] commit: Support infinite keyint (--keyint infinite). (Jason Garrett-Glaser )

git at videolan.org git at videolan.org
Mon Jul 5 03:41:42 CEST 2010


x264 | branch: master | Jason Garrett-Glaser <darkshikari at gmail.com> | Wed Jun 30 13:55:46 2010 -0700| [293b47bc2c52abe5143913ef3d126e6170edaf5c] | committer: Jason Garrett-Glaser 

Support infinite keyint (--keyint infinite).
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).

> http://git.videolan.org/gitweb.cgi/x264.git/?a=commit;h=293b47bc2c52abe5143913ef3d126e6170edaf5c
---

 common/common.c       |    7 ++++---
 encoder/encoder.c     |    8 ++++----
 encoder/ratecontrol.c |   10 +++++-----
 encoder/set.c         |   29 +++++++++++++++++------------
 encoder/slicetype.c   |    2 +-
 x264.c                |    2 +-
 x264.h                |    3 ++-
 7 files changed, 34 insertions(+), 27 deletions(-)

diff --git a/common/common.c b/common/common.c
index 8c7cf3c..14dd716 100644
--- a/common/common.c
+++ b/common/common.c
@@ -638,9 +638,10 @@ int x264_param_parse( x264_param_t *p, const char *name, const char *value )
         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")
     {
diff --git a/encoder/encoder.c b/encoder/encoder.c
index 5cd3307..31cb84a 100644
--- a/encoder/encoder.c
+++ b/encoder/encoder.c
@@ -567,8 +567,7 @@ static int x264_validate_parameters( x264_t *h )
 
     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 )
@@ -627,9 +626,10 @@ static int x264_validate_parameters( x264_t *h )
     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 )
diff --git a/encoder/ratecontrol.c b/encoder/ratecontrol.c
index 1030ef2..6fdaa98 100644
--- a/encoder/ratecontrol.c
+++ b/encoder/ratecontrol.c
@@ -492,13 +492,13 @@ void x264_ratecontrol_init_reconfigurable( x264_t *h, int b_init )
             // 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
 
@@ -1781,10 +1781,10 @@ void x264_hrd_fullness( x264_t *h )
     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);
diff --git a/encoder/set.c b/encoder/set.c
index 8ea6eac..9e6e736 100644
--- a/encoder/set.c
+++ b/encoder/set.c
@@ -99,6 +99,7 @@ static void x264_sei_write( bs_t *s, uint8_t *p_start )
 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 )
@@ -118,15 +119,27 @@ void x264_sps_init( x264_sps_t *sps, int i_id, x264_param_t *param )
     /* 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 )
     {
@@ -219,14 +232,6 @@ void x264_sps_init( x264_sps_t *sps, int i_id, x264_param_t *param )
 
     // 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 )
     {
diff --git a/encoder/slicetype.c b/encoder/slicetype.c
index 4ede8cf..7d69b71 100644
--- a/encoder/slicetype.c
+++ b/encoder/slicetype.c
@@ -1009,7 +1009,7 @@ static int scenecut_internal( x264_t *h, x264_mb_analysis_t *a, x264_frame_t **f
     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 )
diff --git a/x264.c b/x264.c
index 741570c..0bede93 100644
--- a/x264.c
+++ b/x264.c
@@ -409,7 +409,7 @@ static void Help( x264_param_t *defaults, int longhelp )
     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 );
diff --git a/x264.h b/x264.h
index 86f7426..097365a 100644
--- a/x264.h
+++ b/x264.h
@@ -35,7 +35,7 @@
 
 #include <stdarg.h>
 
-#define X264_BUILD 101
+#define X264_BUILD 102
 
 /* x264_t:
  *      opaque handler for encoder */
@@ -152,6 +152,7 @@ typedef struct
 #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



More information about the x264-devel mailing list