From 21ff7bdc72f0eb9ee3d13a4cc8067ad7484873bc Mon Sep 17 00:00:00 2001 From: Paul Wilkins Date: Tue, 16 Apr 2013 18:59:39 +0100 Subject: Adjustments to key frame sizing. Adjustments take heavier account of the frame near a kf in deciding boost and limit the total number that can contribute. Also adjusted the minq calculations such that in most cases we generate a smaller key frame. Modified the code that accounts for how static the sequence is and added some adjustment based on image size. This is still very crude but smaller images tend to behave better with a larger delta between KF Q and other frames than larger image formats. Changes give sizable gains in overall PSNR on all the test sets but the biggest gains (~3%) were on the std-hd set. The gains were smaller for SSIM but still significant. Average PSNR results are mixed because this metric can very easily be altered by having a very good / lossless coding of one or two frames. Some of the YT and YT-HD clips in particular have blank lead ins and allowing lossless coding of these appears to make a big difference to average PSNR but it reality does not help much at all. Change-Id: I6bfe485a1d330b47c783832f1717c95c535464ec --- vp9/encoder/vp9_firstpass.c | 50 ++++++++++++++--------------- vp9/encoder/vp9_onyx_if.c | 76 ++++++++++++++++++++++++++------------------- 2 files changed, 67 insertions(+), 59 deletions(-) diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c index 04ef55513..a995ab351 100644 --- a/vp9/encoder/vp9_firstpass.c +++ b/vp9/encoder/vp9_firstpass.c @@ -38,7 +38,7 @@ #define IIFACTOR 12.5 #define IIKFACTOR1 12.5 #define IIKFACTOR2 15.0 -#define RMAX 128.0 +#define RMAX 512.0 #define GF_RMAX 96.0 #define ERR_DIVISOR 150.0 #define MIN_DECAY_FACTOR 0.1 @@ -2350,7 +2350,6 @@ static void find_next_key_frame(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { double decay_accumulator = 1.0; double zero_motion_accumulator = 1.0; double boost_score = 0; - double old_boost_score = 0.0; double loop_decay_rate; double kf_mod_err = 0.0; @@ -2522,22 +2521,13 @@ static void find_next_key_frame(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { boost_score = 0.0; loop_decay_rate = 1.00; // Starting decay rate + // Scan through the kf group collating various stats. for (i = 0; i < cpi->twopass.frames_to_key; i++) { double r; if (EOF == input_stats(cpi, &next_frame)) break; - if (next_frame.intra_error > cpi->twopass.kf_intra_err_min) - r = (IIKFACTOR2 * next_frame.intra_error / - DOUBLE_DIVIDE_CHECK(next_frame.coded_error)); - else - r = (IIKFACTOR2 * cpi->twopass.kf_intra_err_min / - DOUBLE_DIVIDE_CHECK(next_frame.coded_error)); - - if (r > RMAX) - r = RMAX; - // Monitor for static sections. if ((next_frame.pcnt_inter - next_frame.pcnt_motion) < zero_motion_accumulator) { @@ -2545,22 +2535,28 @@ static void find_next_key_frame(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { (next_frame.pcnt_inter - next_frame.pcnt_motion); } - // How fast is prediction quality decaying - if (!detect_flash(cpi, 0)) { - loop_decay_rate = get_prediction_decay_rate(cpi, &next_frame); - decay_accumulator = decay_accumulator * loop_decay_rate; - decay_accumulator = decay_accumulator < MIN_DECAY_FACTOR - ? MIN_DECAY_FACTOR : decay_accumulator; - } + // For the first few frames collect data to decide kf boost. + if (i <= (cpi->max_gf_interval * 2)) { + if (next_frame.intra_error > cpi->twopass.kf_intra_err_min) + r = (IIKFACTOR2 * next_frame.intra_error / + DOUBLE_DIVIDE_CHECK(next_frame.coded_error)); + else + r = (IIKFACTOR2 * cpi->twopass.kf_intra_err_min / + DOUBLE_DIVIDE_CHECK(next_frame.coded_error)); - boost_score += (decay_accumulator * r); + if (r > RMAX) + r = RMAX; - if ((i > MIN_GF_INTERVAL) && - ((boost_score - old_boost_score) < 6.25)) { - break; - } + // How fast is prediction quality decaying + if (!detect_flash(cpi, 0)) { + loop_decay_rate = get_prediction_decay_rate(cpi, &next_frame); + decay_accumulator = decay_accumulator * loop_decay_rate; + decay_accumulator = decay_accumulator < MIN_DECAY_FACTOR + ? MIN_DECAY_FACTOR : decay_accumulator; + } - old_boost_score = boost_score; + boost_score += (decay_accumulator * r); + } } { @@ -2590,8 +2586,8 @@ static void find_next_key_frame(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { int allocation_chunks; int alt_kf_bits; - if (kf_boost < (cpi->twopass.frames_to_key * 5)) - kf_boost = (cpi->twopass.frames_to_key * 5); + if (kf_boost < (cpi->twopass.frames_to_key * 3)) + kf_boost = (cpi->twopass.frames_to_key * 3); if (kf_boost < 300) // Min KF boost kf_boost = 300; diff --git a/vp9/encoder/vp9_onyx_if.c b/vp9/encoder/vp9_onyx_if.c index dc02f146e..2ebb24ba5 100644 --- a/vp9/encoder/vp9_onyx_if.c +++ b/vp9/encoder/vp9_onyx_if.c @@ -177,15 +177,16 @@ static void init_minq_luts(void) { kf_low_motion_minq[i] = calculate_minq_index(maxq, - 0.0000003, - -0.000015, - 0.074, + 0.000001, + -0.0004, + 0.15, 0.0); kf_high_motion_minq[i] = calculate_minq_index(maxq, - 0.0000004, - -0.000125, - 0.14, + 0.000002, + -0.0012, + 0.5, 0.0); + gf_low_motion_minq[i] = calculate_minq_index(maxq, 0.0000015, -0.0009, @@ -2757,31 +2758,7 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, q = cpi->active_worst_quality; if (cm->frame_type == KEY_FRAME) { -#if CONFIG_MULTIPLE_ARF - double current_q; -#endif - int high = 2000; - int low = 400; - - if (cpi->kf_boost > high) { - cpi->active_best_quality = kf_low_motion_minq[q]; - } else if (cpi->kf_boost < low) { - cpi->active_best_quality = kf_high_motion_minq[q]; - } else { - const int gap = high - low; - const int offset = high - cpi->kf_boost; - const int qdiff = kf_high_motion_minq[q] - kf_low_motion_minq[q]; - const int adjustment = ((offset * qdiff) + (gap >> 1)) / gap; - - cpi->active_best_quality = kf_low_motion_minq[q] + adjustment; - } - - // Make an adjustment based on the % static - // The main impact of this is at lower Q to prevent overly large key - // frames unless a lot of the image is static. - if (cpi->kf_zeromotion_pct < 64) - cpi->active_best_quality += 4 - (cpi->kf_zeromotion_pct >> 4); - +#if !CONFIG_MULTIPLE_ARF // Special case for key frames forced because we have reached // the maximum key frame interval. Here force the Q to a range // based on the ambient Q to reduce the risk of popping @@ -2794,8 +2771,43 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, (last_boosted_q * 0.75)); cpi->active_best_quality = MAX(qindex + delta_qindex, cpi->best_quality); + } else { + int high = 5000; + int low = 400; + double q_adj_factor = 1.0; + double q_val; + + // Baseline value derived from cpi->active_worst_quality and kf boost + if (cpi->kf_boost > high) { + cpi->active_best_quality = kf_low_motion_minq[q]; + } else if (cpi->kf_boost < low) { + cpi->active_best_quality = kf_high_motion_minq[q]; + } else { + const int gap = high - low; + const int offset = high - cpi->kf_boost; + const int qdiff = kf_high_motion_minq[q] - kf_low_motion_minq[q]; + const int adjustment = ((offset * qdiff) + (gap >> 1)) / gap; + + cpi->active_best_quality = kf_low_motion_minq[q] + adjustment; + } + + + // Allow somewhat lower kf minq with small image formats. + if ((cm->width * cm->height) <= (352 * 288)) { + q_adj_factor -= 0.25; + } + + // Make a further adjustment based on the kf zero motion measure. + q_adj_factor += 0.05 - (0.001 * (double)cpi->kf_zeromotion_pct); + + // Convert the adjustment factor to a qindex delta on active_best_quality. + q_val = vp9_convert_qindex_to_q(cpi->active_best_quality); + cpi->active_best_quality += + compute_qdelta(cpi, q_val, (q_val * q_adj_factor)); } -#if CONFIG_MULTIPLE_ARF +#else + double current_q; + // Force the KF quantizer to be 30% of the active_worst_quality. current_q = vp9_convert_qindex_to_q(cpi->active_worst_quality); cpi->active_best_quality = cpi->active_worst_quality -- cgit v1.2.3