From 3af3593c8ecb2a724c3c9f63e2186366550854fa Mon Sep 17 00:00:00 2001 From: Paul Wilkins Date: Fri, 7 Jan 2011 16:33:59 +0000 Subject: [PATCH] Limit Q variability in two pass. In two pass encoding each frame is given an active Q range to work with. This change limits how much this Q range can be altered over time from the initial estimate made for the clip as a whole. There is some danger this could lead to overshoot or undershoot in some corner cases but it helps considerably in regard to clips where either there is a glut or famine of bits in some sections, particularly near the end of a clip. Change-Id: I34fcd1af31d2ee3d5444f93e334645254043026e --- vp8/encoder/firstpass.c | 51 ++++++++++++++++++++++------------------- vp8/encoder/onyx_int.h | 3 +++ 2 files changed, 30 insertions(+), 24 deletions(-) diff --git a/vp8/encoder/firstpass.c b/vp8/encoder/firstpass.c index da4d740cb..ce273b9af 100644 --- a/vp8/encoder/firstpass.c +++ b/vp8/encoder/firstpass.c @@ -66,7 +66,6 @@ extern const int vp8_gf_boost_qadjustment[QINDEX_RANGE]; static int vscale_lookup[7] = {0, 1, 1, 2, 2, 3, 3}; static int hscale_lookup[7] = {0, 0, 1, 1, 2, 2, 3}; - void vp8_find_next_key_frame(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame); int vp8_input_stats(VP8_COMP *cpi, FIRSTPASS_STATS *fps); @@ -907,7 +906,7 @@ static int estimate_max_q(VP8_COMP *cpi, double section_err, int section_target_ double pow_lowq = 0.40; if (section_target_bandwitdh <= 0) - return MAXQ; + return cpi->maxq_max_limit; // Highest value allowed target_norm_bits_per_mb = (section_target_bandwitdh < (1 << 20)) ? (512 * section_target_bandwitdh) / num_mbs : 512 * (section_target_bandwitdh / num_mbs); @@ -943,10 +942,12 @@ static int estimate_max_q(VP8_COMP *cpi, double section_err, int section_target_ // Correction factor used for Q values >= 20 corr_high = pow(err_per_mb / BASE_ERRPERMB, pow_highq); - corr_high = (corr_high < 0.05) ? 0.05 : (corr_high > 5.0) ? 5.0 : corr_high; + corr_high = (corr_high < 0.05) + ? 0.05 : (corr_high > 5.0) ? 5.0 : corr_high; - // Try and pick a Q that should be high enough to encode the content at the given rate. - for (Q = 0; Q < MAXQ; Q++) + // Try and pick a Q that should be high enough to encode the + // content at the given rate. + for (Q = cpi->maxq_min_limit; Q < cpi->maxq_max_limit; Q++) { int bits_per_mb_at_this_q; @@ -1993,20 +1994,29 @@ void vp8_second_pass(VP8_COMP *cpi) if (cpi->common.current_video_frame == 0) { - // guess at 2nd pass q + // guess at 2nd pass max q cpi->est_max_qcorrection_factor = 1.0; - tmp_q = estimate_max_q(cpi, (cpi->total_coded_error_left / frames_left), (int)(cpi->bits_left / frames_left), cpi->common.Height, cpi->common.Width); - if (tmp_q < cpi->worst_quality) - { - cpi->active_worst_quality = tmp_q; - cpi->ni_av_qi = tmp_q; - } - else - { - cpi->active_worst_quality = cpi->worst_quality; - cpi->ni_av_qi = cpi->worst_quality; - } + cpi->maxq_max_limit = cpi->worst_quality; + cpi->maxq_min_limit = cpi->best_quality; + tmp_q = estimate_max_q( cpi, + (cpi->total_coded_error_left / frames_left), + (int)(cpi->bits_left / frames_left), + cpi->common.Height, + cpi->common.Width); + + // Limit the maxq value retuned subsequently. + // This increases the risk of overspend 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 + cpi->maxq_max_limit = ((tmp_q + 32) < cpi->worst_quality) + ? (tmp_q + 32) : cpi->worst_quality; + cpi->maxq_min_limit = ((tmp_q - 32) > cpi->best_quality) + ? (tmp_q - 32) : cpi->best_quality; + + cpi->active_worst_quality = tmp_q; + cpi->ni_av_qi = tmp_q; } // 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 @@ -2029,13 +2039,6 @@ void vp8_second_pass(VP8_COMP *cpi) cpi->active_worst_quality --; cpi->active_worst_quality = ((cpi->active_worst_quality * 3) + tmp_q + 2) / 4; - - // Clamp to user set limits - if (cpi->active_worst_quality > cpi->worst_quality) - cpi->active_worst_quality = cpi->worst_quality; - else if (cpi->active_worst_quality < cpi->best_quality) - cpi->active_worst_quality = cpi->best_quality; - } cpi->frames_to_key --; diff --git a/vp8/encoder/onyx_int.h b/vp8/encoder/onyx_int.h index 2f9cc4776..6a21d0f80 100644 --- a/vp8/encoder/onyx_int.h +++ b/vp8/encoder/onyx_int.h @@ -447,6 +447,9 @@ typedef struct int best_quality; int active_best_quality; + int maxq_max_limit; + int maxq_min_limit; + int drop_frames_allowed; // Are we permitted to drop frames? int drop_frame; // Drop this frame? int drop_count; // How many frames have we dropped?