[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