From 57136a268ab52d2874aa75859e43f663ca98e67c Mon Sep 17 00:00:00 2001 From: Paul Wilkins Date: Tue, 18 Jan 2011 15:19:05 +0000 Subject: [PATCH] Further CQ, Key frame and ARF changes This code fixes a bug in the calculation of the minimum Q for alt ref frames. It also allows an extended gf/arf interval for sections of clips that completely static (or nearly so). Change-Id: I1a21aaa16d4f0578e5f99b13bebd78d59403c73b --- vp8/encoder/encodeframe.c | 2 -- vp8/encoder/firstpass.c | 18 ++++++++++-------- vp8/encoder/onyx_if.c | 36 +++++++++++++++++++++++++----------- vp8/encoder/onyx_int.h | 1 + 4 files changed, 36 insertions(+), 21 deletions(-) diff --git a/vp8/encoder/encodeframe.c b/vp8/encoder/encodeframe.c index 2a89c59..4c95f28 100644 --- a/vp8/encoder/encodeframe.c +++ b/vp8/encoder/encodeframe.c @@ -710,9 +710,7 @@ void vp8_encode_frame(VP8_COMP *cpi) } vp8_initialize_rd_consts(cpi, vp8_dc_quant(cm->base_qindex, cm->y1dc_delta_q)); - //vp8_initialize_rd_consts( cpi, vp8_dc_quant(cpi->avg_frame_qindex, cm->y1dc_delta_q) ); vp8cx_initialize_me_consts(cpi, cm->base_qindex); - //vp8cx_initialize_me_consts( cpi, cpi->avg_frame_qindex); // Copy data over into macro block data sturctures. diff --git a/vp8/encoder/firstpass.c b/vp8/encoder/firstpass.c index c596138..32a39c5 100644 --- a/vp8/encoder/firstpass.c +++ b/vp8/encoder/firstpass.c @@ -1375,7 +1375,7 @@ static void define_gf_group(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame) // what level of boost is appropriate for the GF or ARF that will be coded with the group i = 0; - while (((i < cpi->max_gf_interval) || ((cpi->frames_to_key - i) < MIN_GF_INTERVAL)) && (i < cpi->frames_to_key)) + while (((i < cpi->static_scene_max_gf_interval) || ((cpi->frames_to_key - i) < MIN_GF_INTERVAL)) && (i < cpi->frames_to_key)) { double r; double this_frame_mvr_ratio; @@ -1485,18 +1485,20 @@ static void define_gf_group(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame) boost_score += (decay_accumulator * r); // Break out conditions. - if ( /* i>4 || */ + if ( /* i>4 || */ + // Break at cpi->max_gf_interval unless almost totally static + (i >= cpi->max_gf_interval && (loop_decay_rate < 0.99)) || ( - (i > MIN_GF_INTERVAL) && // Dont break out with a very short interval - ((cpi->frames_to_key - i) >= MIN_GF_INTERVAL) && // Dont break out very close to a key frame + // Dont break out with a very short interval + (i > MIN_GF_INTERVAL) && + // Dont break out very close to a key frame + ((cpi->frames_to_key - i) >= MIN_GF_INTERVAL) && ((boost_score > 20.0) || (next_frame.pcnt_inter < 0.75)) && ((mv_ratio_accumulator > 100.0) || (abs_mv_in_out_accumulator > 3.0) || (mv_in_out_accumulator < -2.0) || - ((boost_score - old_boost_score) < 2.0) - ) - ) - ) + ((boost_score - old_boost_score) < 2.0)) + ) ) { boost_score = old_boost_score; break; diff --git a/vp8/encoder/onyx_if.c b/vp8/encoder/onyx_if.c index 47fc3f7..846ebb4 100644 --- a/vp8/encoder/onyx_if.c +++ b/vp8/encoder/onyx_if.c @@ -1497,21 +1497,25 @@ void vp8_new_frame_rate(VP8_COMP *cpi, double framerate) cpi->per_frame_bandwidth = (int)(cpi->oxcf.target_bandwidth / cpi->output_frame_rate); cpi->av_per_frame_bandwidth = (int)(cpi->oxcf.target_bandwidth / cpi->output_frame_rate); cpi->min_frame_bandwidth = (int)(cpi->av_per_frame_bandwidth * cpi->oxcf.two_pass_vbrmin_section / 100); - cpi->max_gf_interval = (int)(cpi->output_frame_rate / 2) + 2; - //cpi->max_gf_interval = (int)(cpi->output_frame_rate * 2 / 3) + 1; - //cpi->max_gf_interval = 24; + // Set Maximum gf/arf interval + cpi->max_gf_interval = max(((int)(cpi->output_frame_rate / 2.0) + 2), 12); - if (cpi->max_gf_interval < 12) - cpi->max_gf_interval = 12; + // Extended interval for genuinely static scenes + cpi->static_scene_max_gf_interval = cpi->key_frame_frequency >> 1; - - // Special conditions when altr ref frame enabled in lagged compress mode + // Special conditions when altr ref frame enabled in lagged compress mode if (cpi->oxcf.play_alternate && cpi->oxcf.lag_in_frames) { if (cpi->max_gf_interval > cpi->oxcf.lag_in_frames - 1) cpi->max_gf_interval = cpi->oxcf.lag_in_frames - 1; + + if (cpi->static_scene_max_gf_interval > cpi->oxcf.lag_in_frames - 1) + cpi->static_scene_max_gf_interval = cpi->oxcf.lag_in_frames - 1; } + + if ( cpi->max_gf_interval > cpi->static_scene_max_gf_interval ) + cpi->max_gf_interval = cpi->static_scene_max_gf_interval; } @@ -3846,9 +3850,21 @@ static void encode_frame_to_data_rate else if (cm->refresh_golden_frame || cpi->common.refresh_alt_ref_frame) { - if (cpi->avg_frame_qindex < cpi->active_worst_quality) + // Use the lower of cpi->active_worst_quality and recent + // average Q as basis for GF/ARF Q limit unless last frame was + // a key frame. + if ( (cpi->frames_since_key > 1) && + (cpi->avg_frame_qindex < cpi->active_worst_quality) ) + { Q = cpi->avg_frame_qindex; + if ( (cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY) && + (Q < cpi->oxcf.cq_level) ) + { + Q = cpi->oxcf.cq_level; + } + } + if ( cpi->pass == 2 ) { if ( cpi->gfu_boost > 1000 ) @@ -4528,9 +4544,7 @@ static void encode_frame_to_data_rate } // Keep a record of ambient average Q. - if (cm->frame_type == KEY_FRAME) - cpi->avg_frame_qindex = cm->base_qindex; - else + if (cm->frame_type != KEY_FRAME) cpi->avg_frame_qindex = (2 + 3 * cpi->avg_frame_qindex + cm->base_qindex) >> 2; // Keep a record from which we can calculate the average Q excluding GF updates and key frames diff --git a/vp8/encoder/onyx_int.h b/vp8/encoder/onyx_int.h index 45fafd5..8a97e98 100644 --- a/vp8/encoder/onyx_int.h +++ b/vp8/encoder/onyx_int.h @@ -402,6 +402,7 @@ typedef struct int kf_overspend_bits; // Extra bits spent on key frames that need to be recovered on inter frames int kf_bitrate_adjustment; // Current number of bit s to try and recover on each inter frame. int max_gf_interval; + int static_scene_max_gf_interval; int baseline_gf_interval; int gf_decay_rate; int active_arnr_frames; // <= cpi->oxcf.arnr_max_frames -- 2.7.4