diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c index c8f1313f4..9752668b1 100644 --- a/vp9/encoder/vp9_firstpass.c +++ b/vp9/encoder/vp9_firstpass.c @@ -51,7 +51,6 @@ #define KF_MAX_BOOST 128.0 #define MIN_ARF_GF_BOOST 240 #define MIN_DECAY_FACTOR 0.01 -#define MIN_GF_INTERVAL 4 #define MIN_KF_BOOST 300 #define NEW_MV_MODE_PENALTY 32 #define SVC_FACTOR_PT_LOW 0.45 @@ -1323,14 +1322,17 @@ static double get_prediction_decay_rate(const VP9_COMP *cpi, // Function to test for a condition where a complex transition is followed // by a static section. For example in slide shows where there is a fade // between slides. This is to help with more optimal kf and gf positioning. -static int detect_transition_to_still(const TWO_PASS *twopass, +static int detect_transition_to_still(VP9_COMP *cpi, int frame_interval, int still_interval, double loop_decay_rate, double last_decay_rate) { + TWO_PASS *const twopass = &cpi->twopass; + RATE_CONTROL *const rc = &cpi->rc; + // Break clause to detect very still sections after motion // For example a static image after a fade or other transition // instead of a clean scene cut. - if (frame_interval > MIN_GF_INTERVAL && + if (frame_interval > rc->min_gf_interval && loop_decay_rate >= 0.999 && last_decay_rate < 0.9) { int j; @@ -1838,7 +1840,7 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { int int_lbq = (int)(vp9_convert_qindex_to_q(rc->last_boosted_qindex, cpi->common.bit_depth)); - active_min_gf_interval = MIN_GF_INTERVAL + MIN(2, int_max_q / 200); + active_min_gf_interval = rc->min_gf_interval + MIN(2, int_max_q / 200); if (active_min_gf_interval > rc->max_gf_interval) active_min_gf_interval = rc->max_gf_interval; @@ -1894,7 +1896,7 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { // Break clause to detect very still sections after motion. For example, // a static image after a fade or other transition. - if (detect_transition_to_still(twopass, i, 5, loop_decay_rate, + if (detect_transition_to_still(cpi, i, 5, loop_decay_rate, last_loop_decay_rate)) { allow_alt_ref = 0; break; @@ -1960,7 +1962,7 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { // Should we use the alternate reference frame. if (allow_alt_ref && (i < cpi->oxcf.lag_in_frames) && - (i >= MIN_GF_INTERVAL)) { + (i >= rc->min_gf_interval)) { // Calculate the boost for alt ref. rc->gfu_boost = calc_arf_boost(cpi, 0, (i - 1), (i - 1), &f_boost, &b_boost); @@ -2239,7 +2241,7 @@ static void find_next_key_frame(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { // Special check for transition or high motion followed by a // static scene. - if (detect_transition_to_still(twopass, i, cpi->oxcf.key_freq - i, + if (detect_transition_to_still(cpi, i, cpi->oxcf.key_freq - i, loop_decay_rate, decay_accumulator)) break; diff --git a/vp9/encoder/vp9_ratectrl.c b/vp9/encoder/vp9_ratectrl.c index 8713caa73..4c33ffd97 100644 --- a/vp9/encoder/vp9_ratectrl.c +++ b/vp9/encoder/vp9_ratectrl.c @@ -1609,12 +1609,19 @@ int vp9_compute_qdelta_by_rate(const RATE_CONTROL *rc, FRAME_TYPE frame_type, return target_index - qindex; } -void vp9_rc_set_gf_max_interval(const VP9_COMP *const cpi, - RATE_CONTROL *const rc) { +#define MIN_GF_INTERVAL 4 +#define MAX_GF_INTERVAL 16 +void vp9_rc_set_gf_interval_range(const VP9_COMP *const cpi, + RATE_CONTROL *const rc) { const VP9EncoderConfig *const oxcf = &cpi->oxcf; + + // Set a minimum interval. + rc->min_gf_interval = + MIN(MAX_GF_INTERVAL, MAX(MIN_GF_INTERVAL, (int)(cpi->framerate * 0.125))); + // Set Maximum gf/arf interval. rc->max_gf_interval = - MIN(16, (int)(cpi->framerate / 2.0)); + MIN(MAX_GF_INTERVAL, (int)(cpi->framerate * 0.75)); // Round up to next even number if odd. rc->max_gf_interval += (rc->max_gf_interval & 0x01); @@ -1628,6 +1635,9 @@ void vp9_rc_set_gf_max_interval(const VP9_COMP *const cpi, if (rc->max_gf_interval > rc->static_scene_max_gf_interval) rc->max_gf_interval = rc->static_scene_max_gf_interval; + + // Clamp min to max + rc->min_gf_interval = MIN(rc->min_gf_interval, rc->max_gf_interval); } void vp9_rc_update_framerate(VP9_COMP *cpi) { @@ -1654,7 +1664,7 @@ void vp9_rc_update_framerate(VP9_COMP *cpi) { rc->max_frame_bandwidth = MAX(MAX((cm->MBs * MAX_MB_RATE), MAXRATE_1080P), vbr_max_bits); - vp9_rc_set_gf_max_interval(cpi, rc); + vp9_rc_set_gf_interval_range(cpi, rc); } #define VBR_PCT_ADJUSTMENT_LIMIT 50 diff --git a/vp9/encoder/vp9_ratectrl.h b/vp9/encoder/vp9_ratectrl.h index 705796a8d..869f6e59e 100644 --- a/vp9/encoder/vp9_ratectrl.h +++ b/vp9/encoder/vp9_ratectrl.h @@ -73,6 +73,7 @@ typedef struct { int frames_since_golden; int frames_till_gf_update_due; + int min_gf_interval; int max_gf_interval; int static_scene_max_gf_interval; int baseline_gf_interval; @@ -238,8 +239,8 @@ int vp9_frame_type_qdelta(const struct VP9_COMP *cpi, int rf_level, int q); void vp9_rc_update_framerate(struct VP9_COMP *cpi); -void vp9_rc_set_gf_max_interval(const struct VP9_COMP *const cpi, - RATE_CONTROL *const rc); +void vp9_rc_set_gf_interval_range(const struct VP9_COMP *const cpi, + RATE_CONTROL *const rc); void vp9_set_target_rate(struct VP9_COMP *cpi); diff --git a/vp9/encoder/vp9_svc_layercontext.c b/vp9/encoder/vp9_svc_layercontext.c index e122397b3..b3491a27a 100644 --- a/vp9/encoder/vp9_svc_layercontext.c +++ b/vp9/encoder/vp9_svc_layercontext.c @@ -195,7 +195,7 @@ void vp9_update_spatial_layer_framerate(VP9_COMP *const cpi, double framerate) { oxcf->two_pass_vbrmin_section / 100); lrc->max_frame_bandwidth = (int)(((int64_t)lrc->avg_frame_bandwidth * oxcf->two_pass_vbrmax_section) / 100); - vp9_rc_set_gf_max_interval(cpi, lrc); + vp9_rc_set_gf_interval_range(cpi, lrc); } void vp9_restore_layer_context(VP9_COMP *const cpi) {