From baa3581cdeaa44afeb39dc3bed03b7e465b8492b Mon Sep 17 00:00:00 2001 From: Anton Mitrofanov Date: Tue, 6 Jul 2010 18:23:33 +0400 Subject: [PATCH] Fix scenecut detection with --keyint infinite (and other large values). Also write keyint=infinite to option SEI instead of keyint=1073741824 --- common/common.c | 8 ++++++-- encoder/encoder.c | 4 ++-- encoder/ratecontrol.c | 21 ++++++++++++++++++++- encoder/slicetype.c | 26 +++++++++++++++++++------- 4 files changed, 47 insertions(+), 12 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 a2c4cfe..2308b37 100644 --- a/encoder/ratecontrol.c +++ b/encoder/ratecontrol.c @@ -724,9 +724,28 @@ 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( strstr( opts, "keyint=infinite" ) ) + { + if( h->param.i_keyint_max != X264_KEYINT_MAX_INFINITE ) + { + x264_log( h, X264_LOG_ERROR, "different keyint setting than first pass (%d vs infinite)\n", h->param.i_keyint_max ); + return -1; + } + } + else + { + if( ( p = strstr( opts, "keyint=" ) ) && sscanf( p, "keyint=%d", &i ) && h->param.i_keyint_max != i ) + { + if( h->param.i_keyint_max == X264_KEYINT_MAX_INFINITE ) + x264_log( h, X264_LOG_ERROR, "different keyint setting than first pass (infinite vs %d)\n", i ); + else + x264_log( h, X264_LOG_ERROR, "different keyint setting than first pass (%d vs %d)\n", h->param.i_keyint_max, i ); + 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..9dab743 100644 --- a/encoder/slicetype.c +++ b/encoder/slicetype.c @@ -1008,22 +1008,34 @@ 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 / 40.0; 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_bias = f_thresh_min / 4; + 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.0; else if( i_gop_size <= h->param.i_keyint_min ) f_bias = f_thresh_min * i_gop_size / h->param.i_keyint_min; + else if( h->param.i_keyint_max == X264_KEYINT_MAX_INFINITE ) + { + int i_inf_keyint = X264_MIN( h->param.i_keyint_min * 10.0, X264_KEYINT_MAX_INFINITE ); + if( i_gop_size < i_inf_keyint ) + { + f_bias = f_thresh_min + + ( f_thresh_max - f_thresh_min ) + * ( i_gop_size - h->param.i_keyint_min ) + / ( i_inf_keyint - h->param.i_keyint_min ) ; + } + else + f_bias = f_thresh_max; + } else { 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; -- 1.6.1.9.g97c34