From 97da8b8c3395ba3de5e13b8d77a8432b9a462b78 Mon Sep 17 00:00:00 2001 From: Paul Wilkins Date: Mon, 25 Feb 2013 12:36:38 +0000 Subject: [PATCH] Minor rate control refactoring and experiments. Some minor refactoring code relating to estimates of bits per MB at a given Q and estimating the allowed Q range. Most of the changes here were included in a previous commit. This commit seeks to separate out the refactoring from more the material changes. Two #define control flags have been added for experimentation. ONE_SHOT_Q_ESTIMATE force the two pass encoder to use its initial Q range estimate for the whole clip even if this results in a miss on the target data rate. In effect this tightens the Q range seen at the expense of rate control accuracy. DISABLE_RC_LONG_TERM_MEM is a related flag that disables the long term memory in the rate control. Local adjustments are still made to try and better hit the rate target on a per frame basis but the impact of rate control misses is not propagated to the remainder of the clip. This means that for example an overshoot early on will not cause frames later in the clip to be starved of bits. Again the result of this relaxation amy be less rate control accuracy especially on short clips. The flags are disabled by default for now. Change-Id: I7482f980146d8ea033b5d50cc689f772e4bd119e --- vp9/encoder/vp9_firstpass.c | 79 ++++++++------------------------------------- vp9/encoder/vp9_onyx_if.c | 23 ++++++++++--- vp9/encoder/vp9_onyx_int.h | 4 +++ vp9/encoder/vp9_ratectrl.c | 31 ++++++++++-------- vp9/encoder/vp9_ratectrl.h | 3 +- 5 files changed, 55 insertions(+), 85 deletions(-) diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c index 0a407df..a492487 100644 --- a/vp9/encoder/vp9_firstpass.c +++ b/vp9/encoder/vp9_firstpass.c @@ -844,16 +844,13 @@ static double calc_correction_factor(double err_per_mb, power_term = (vp9_convert_qindex_to_q(Q) * 0.01) + pt_low; power_term = (power_term > pt_high) ? pt_high : power_term; - // Adjustments to error term - // TBD - // Calculate correction factor correction_factor = pow(error_term, power_term); // Clip range correction_factor = (correction_factor < 0.05) - ? 0.05 : (correction_factor > 2.0) ? 2.0 : correction_factor; + ? 0.05 : (correction_factor > 5.0) ? 5.0 : correction_factor; return correction_factor; } @@ -887,8 +884,7 @@ static void adjust_maxq_qrange(VP9_COMP *cpi) { static int estimate_max_q(VP9_COMP *cpi, FIRSTPASS_STATS *fpstats, - int section_target_bandwitdh, - int overhead_bits) { + int section_target_bandwitdh) { int Q; int num_mbs = cpi->common.MBs; int target_norm_bits_per_mb; @@ -899,7 +895,6 @@ static int estimate_max_q(VP9_COMP *cpi, double err_per_mb = section_err / num_mbs; double err_correction_factor; double speed_correction = 1.0; - double overhead_bits_per_mb; if (section_target_bandwitdh <= 0) return cpi->twopass.maxq_max_limit; // Highest value allowed @@ -951,13 +946,6 @@ static int estimate_max_q(VP9_COMP *cpi, speed_correction = 1.25; } - // Estimate of overhead bits per mb - // Correction to overhead bits for min allowed Q. - // PGW TODO.. This code is broken for the extended Q range - // for now overhead set to 0. - overhead_bits_per_mb = overhead_bits / num_mbs; - overhead_bits_per_mb *= pow(0.98, (double)cpi->twopass.maxq_min_limit); - // Try and pick a max Q that will be high enough to encode the // content at the given rate. for (Q = cpi->twopass.maxq_min_limit; Q < cpi->twopass.maxq_max_limit; Q++) { @@ -968,23 +956,9 @@ static int estimate_max_q(VP9_COMP *cpi, sr_correction * speed_correction * cpi->twopass.est_max_qcorrection_factor; - if (err_correction_factor < 0.05) - err_correction_factor = 0.05; - else if (err_correction_factor > 5.0) - err_correction_factor = 5.0; bits_per_mb_at_this_q = - vp9_bits_per_mb(INTER_FRAME, Q) + (int)overhead_bits_per_mb; - - bits_per_mb_at_this_q = (int)(.5 + err_correction_factor * - (double)bits_per_mb_at_this_q); - - // Mode and motion overhead - // As Q rises in real encode loop rd code will force overhead down - // We make a crude adjustment for this here as *.98 per Q step. - // PGW TODO.. This code is broken for the extended Q range - // for now overhead set to 0. - // overhead_bits_per_mb = (int)((double)overhead_bits_per_mb * 0.98); + vp9_bits_per_mb(INTER_FRAME, Q, err_correction_factor); if (bits_per_mb_at_this_q <= target_norm_bits_per_mb) break; @@ -1002,7 +976,7 @@ static int estimate_max_q(VP9_COMP *cpi, // PGW TODO.. This code is broken for the extended Q range if ((cpi->ni_frames > ((int)cpi->twopass.total_stats->count >> 8)) && - (cpi->ni_frames > 150)) { + (cpi->ni_frames > 25)) { adjust_maxq_qrange(cpi); } @@ -1013,8 +987,7 @@ static int estimate_max_q(VP9_COMP *cpi, // complexity and data rate. static int estimate_cq(VP9_COMP *cpi, FIRSTPASS_STATS *fpstats, - int section_target_bandwitdh, - int overhead_bits) { + int section_target_bandwitdh) { int Q; int num_mbs = cpi->common.MBs; int target_norm_bits_per_mb; @@ -1027,15 +1000,11 @@ static int estimate_cq(VP9_COMP *cpi, double speed_correction = 1.0; double clip_iiratio; double clip_iifactor; - double overhead_bits_per_mb; - target_norm_bits_per_mb = (section_target_bandwitdh < (1 << 20)) ? (512 * section_target_bandwitdh) / num_mbs : 512 * (section_target_bandwitdh / num_mbs); - // Estimate of overhead bits per mb - overhead_bits_per_mb = overhead_bits / num_mbs; // Corrections for higher compression speed settings // (reduced compression expected) @@ -1074,23 +1043,8 @@ static int estimate_cq(VP9_COMP *cpi, calc_correction_factor(err_per_mb, 100.0, 0.4, 0.90, Q) * sr_correction * speed_correction * clip_iifactor; - if (err_correction_factor < 0.05) - err_correction_factor = 0.05; - else if (err_correction_factor > 5.0) - err_correction_factor = 5.0; - bits_per_mb_at_this_q = - vp9_bits_per_mb(INTER_FRAME, Q) + (int)overhead_bits_per_mb; - - bits_per_mb_at_this_q = (int)(.5 + err_correction_factor * - (double)bits_per_mb_at_this_q); - - // Mode and motion overhead - // As Q rises in real encode loop rd code will force overhead down - // We make a crude adjustment for this here as *.98 per Q step. - // PGW TODO.. This code is broken for the extended Q range - // for now overhead set to 0. - overhead_bits_per_mb = (int)((double)overhead_bits_per_mb * 0.98); + vp9_bits_per_mb(INTER_FRAME, Q, err_correction_factor); if (bits_per_mb_at_this_q <= target_norm_bits_per_mb) break; @@ -1953,8 +1907,6 @@ void vp9_second_pass(VP9_COMP *cpi) { double this_frame_intra_error; double this_frame_coded_error; - int overhead_bits; - if (!cpi->twopass.stats_in) { return; } @@ -2018,11 +1970,6 @@ void vp9_second_pass(VP9_COMP *cpi) { if (cpi->target_bandwidth < 0) cpi->target_bandwidth = 0; - - // Account for mv, mode and other overheads. - overhead_bits = (int)estimate_modemvcost( - cpi, cpi->twopass.total_left_stats); - // Special case code for first frame. if (cpi->common.current_video_frame == 0) { cpi->twopass.est_max_qcorrection_factor = 1.0; @@ -2034,8 +1981,7 @@ void vp9_second_pass(VP9_COMP *cpi) { est_cq = estimate_cq(cpi, cpi->twopass.total_left_stats, - (int)(cpi->twopass.bits_left / frames_left), - overhead_bits); + (int)(cpi->twopass.bits_left / frames_left)); cpi->cq_target_quality = cpi->oxcf.cq_level; if (est_cq > cpi->cq_target_quality) @@ -2049,21 +1995,23 @@ void vp9_second_pass(VP9_COMP *cpi) { tmp_q = estimate_max_q( cpi, cpi->twopass.total_left_stats, - (int)(cpi->twopass.bits_left / frames_left), - overhead_bits); + (int)(cpi->twopass.bits_left / frames_left)); cpi->active_worst_quality = tmp_q; cpi->ni_av_qi = tmp_q; cpi->avg_q = vp9_convert_qindex_to_q(tmp_q); +#ifndef ONE_SHOT_Q_ESTIMATE // Limit the maxq value returned subsequently. // This increases the risk of overspend or underspend if the initial // estimate for the clip is bad, but helps prevent excessive // variation in Q, especially near the end of a clip // where for example a small overspend may cause Q to crash adjust_maxq_qrange(cpi); +#endif } +#ifndef ONE_SHOT_Q_ESTIMATE // The last few frames of a clip almost always have to few or too many // bits and for the sake of over exact rate control we dont want to make // radical adjustments to the allowed quantizer range just to use up a @@ -2078,13 +2026,13 @@ void vp9_second_pass(VP9_COMP *cpi) { tmp_q = estimate_max_q( cpi, cpi->twopass.total_left_stats, - (int)(cpi->twopass.bits_left / frames_left), - overhead_bits); + (int)(cpi->twopass.bits_left / frames_left)); // Make a damped adjustment to active max Q cpi->active_worst_quality = adjust_active_maxq(cpi->active_worst_quality, tmp_q); } +#endif cpi->twopass.frames_to_key--; @@ -2092,7 +2040,6 @@ void vp9_second_pass(VP9_COMP *cpi) { subtract_stats(cpi->twopass.total_left_stats, &this_frame); } - static int test_candidate_kf(VP9_COMP *cpi, FIRSTPASS_STATS *last_frame, FIRSTPASS_STATS *this_frame, diff --git a/vp9/encoder/vp9_onyx_if.c b/vp9/encoder/vp9_onyx_if.c index 40a1263..feb1e36 100644 --- a/vp9/encoder/vp9_onyx_if.c +++ b/vp9/encoder/vp9_onyx_if.c @@ -3321,11 +3321,19 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, if (cpi->bits_off_target > cpi->oxcf.maximum_buffer_size) cpi->bits_off_target = cpi->oxcf.maximum_buffer_size; - // Rolling monitors of whether we are over or underspending used to help regulate min and Max Q in two pass. - cpi->rolling_target_bits = ((cpi->rolling_target_bits * 3) + cpi->this_frame_target + 2) / 4; - cpi->rolling_actual_bits = ((cpi->rolling_actual_bits * 3) + cpi->projected_frame_size + 2) / 4; - cpi->long_rolling_target_bits = ((cpi->long_rolling_target_bits * 31) + cpi->this_frame_target + 16) / 32; - cpi->long_rolling_actual_bits = ((cpi->long_rolling_actual_bits * 31) + cpi->projected_frame_size + 16) / 32; + // Rolling monitors of whether we are over or underspending used to help + // regulate min and Max Q in two pass. + if (cm->frame_type != KEY_FRAME) { + cpi->rolling_target_bits = + ((cpi->rolling_target_bits * 3) + cpi->this_frame_target + 2) / 4; + cpi->rolling_actual_bits = + ((cpi->rolling_actual_bits * 3) + cpi->projected_frame_size + 2) / 4; + cpi->long_rolling_target_bits = + ((cpi->long_rolling_target_bits * 31) + cpi->this_frame_target + 16) / 32; + cpi->long_rolling_actual_bits = + ((cpi->long_rolling_actual_bits * 31) + + cpi->projected_frame_size + 16) / 32; + } // Actual bits spent cpi->total_actual_bits += cpi->projected_frame_size; @@ -3551,7 +3559,12 @@ static void Pass2Encode(VP9_COMP *cpi, unsigned long *size, vp9_second_pass(cpi); encode_frame_to_data_rate(cpi, size, dest, frame_flags); + +#ifdef DISABLE_RC_LONG_TERM_MEM + cpi->twopass.bits_left -= cpi->this_frame_target; +#else cpi->twopass.bits_left -= 8 * *size; +#endif if (!cpi->refresh_alt_ref_frame) { double lower_bounds_min_rate = FRAME_OVERHEAD_BITS * cpi->oxcf.frame_rate; diff --git a/vp9/encoder/vp9_onyx_int.h b/vp9/encoder/vp9_onyx_int.h index 6b9bf87..9b509ea 100644 --- a/vp9/encoder/vp9_onyx_int.h +++ b/vp9/encoder/vp9_onyx_int.h @@ -29,6 +29,10 @@ #include "vp9/common/vp9_findnearmv.h" #include "vp9/encoder/vp9_lookahead.h" +// Experimental rate control switches +// #define ONE_SHOT_Q_ESTIMATE 1 +// #define DISABLE_RC_LONG_TERM_MEM 1 + // #define SPEEDSTATS 1 #define MIN_GF_INTERVAL 4 #define DEFAULT_GF_INTERVAL 7 diff --git a/vp9/encoder/vp9_ratectrl.c b/vp9/encoder/vp9_ratectrl.c index 53d931c..a2a7957 100644 --- a/vp9/encoder/vp9_ratectrl.c +++ b/vp9/encoder/vp9_ratectrl.c @@ -114,13 +114,19 @@ static int kfboost_qadjust(int qindex) { return retval; } -int vp9_bits_per_mb(FRAME_TYPE frame_type, int qindex) { - if (frame_type == KEY_FRAME) - return (int)(4500000 / vp9_convert_qindex_to_q(qindex)); - else - return (int)(2850000 / vp9_convert_qindex_to_q(qindex)); -} +int vp9_bits_per_mb(FRAME_TYPE frame_type, int qindex, + double correction_factor) { + int enumerator; + double q = vp9_convert_qindex_to_q(qindex); + + if (frame_type == KEY_FRAME) { + enumerator = 4500000; + } else { + enumerator = 2850000; + } + return (int)(0.5 + (enumerator * correction_factor / q)); +} void vp9_save_coding_context(VP9_COMP *cpi) { CODING_CONTEXT *const cc = &cpi->coding_context; @@ -259,7 +265,7 @@ void vp9_setup_inter_frame(VP9_COMP *cpi) { static int estimate_bits_at_q(int frame_kind, int Q, int MBs, double correction_factor) { - int Bpm = (int)(.5 + correction_factor * vp9_bits_per_mb(frame_kind, Q)); + int Bpm = (int)(vp9_bits_per_mb(frame_kind, Q, correction_factor)); /* Attempt to retain reasonable accuracy without overflow. The cutoff is * chosen such that the maximum product of Bpm and MBs fits 31 bits. The @@ -397,12 +403,12 @@ void vp9_update_rate_correction_factors(VP9_COMP *cpi, int damp_var) { rate_correction_factor = cpi->rate_correction_factor; } - // Work out how big we would have expected the frame to be at this Q given the current correction factor. + // Work out how big we would have expected the frame to be at this Q given + // the current correction factor. // Stay in double to avoid int overflow when values are large projected_size_based_on_q = - (int)(((.5 + rate_correction_factor * - vp9_bits_per_mb(cpi->common.frame_type, Q)) * - cpi->common.MBs) / (1 << BPER_MB_NORMBITS)); + estimate_bits_at_q(cpi->common.frame_type, Q, + cpi->common.MBs, rate_correction_factor); // Work out a size correction factor. // if ( cpi->this_frame_target > 0 ) @@ -485,8 +491,7 @@ int vp9_regulate_q(VP9_COMP *cpi, int target_bits_per_frame) { do { bits_per_mb_at_this_q = - (int)(.5 + correction_factor * - vp9_bits_per_mb(cpi->common.frame_type, i)); + (int)(vp9_bits_per_mb(cpi->common.frame_type, i, correction_factor)); if (bits_per_mb_at_this_q <= target_bits_per_mb) { if ((target_bits_per_mb - bits_per_mb_at_this_q) <= last_error) diff --git a/vp9/encoder/vp9_ratectrl.h b/vp9/encoder/vp9_ratectrl.h index c5817d7..4733176 100644 --- a/vp9/encoder/vp9_ratectrl.h +++ b/vp9/encoder/vp9_ratectrl.h @@ -32,7 +32,8 @@ int vp9_pick_frame_size(VP9_COMP *cpi); double vp9_convert_qindex_to_q(int qindex); int vp9_gfboost_qadjust(int qindex); -int vp9_bits_per_mb(FRAME_TYPE frame_type, int qindex); +extern int vp9_bits_per_mb(FRAME_TYPE frame_type, int qindex, + double correction_factor); void vp9_setup_inter_frame(VP9_COMP *cpi); #endif // VP9_ENCODER_VP9_RATECTRL_H_ -- 2.7.4