From 883fdd45cfbb1b12ff746fbb88df88522e20b5c1 Mon Sep 17 00:00:00 2001 From: paulwilkins Date: Thu, 7 May 2015 11:55:53 +0100 Subject: [PATCH] Fast feedback of bits on undershoot. This patch provides a partial rapid feedback of bits resulting from extreme undershoot. Some improvement on some problem animated material but in its current form only a small impact on the metrics results of our standard test sets. Change-Id: Ie03036ea8123bc2553437cb8c8c9e7a9fc5dac5d --- vp9/encoder/vp9_encoder.c | 8 ++++++-- vp9/encoder/vp9_firstpass.c | 31 ++++++++++++++++++++++++++++++- vp9/encoder/vp9_firstpass.h | 2 ++ vp9/encoder/vp9_ratectrl.c | 28 ++++++++++++++++++++++------ vp9/encoder/vp9_ratectrl.h | 1 + 5 files changed, 61 insertions(+), 9 deletions(-) diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c index 0add45ec5..9da47cf24 100644 --- a/vp9/encoder/vp9_encoder.c +++ b/vp9/encoder/vp9_encoder.c @@ -2796,8 +2796,9 @@ static void output_frame_level_debug_stats(VP9_COMP *cpi) { if (cpi->twopass.total_left_stats.coded_error != 0.0) fprintf(f, "%10u %dx%d %d %d %10d %10d %10d %10d" - "%10"PRId64" %10"PRId64" %10"PRId64" %10"PRId64" %10d " - "%7.2lf %7.2lf %7.2lf %7.2lf %7.2lf" + "%10"PRId64" %10"PRId64" %5d %5d %10"PRId64" " + "%10"PRId64" %10"PRId64" %10d " + "%7.2lf %7.2lf %7.2lf %7.2lf %7.2lf" "%6d %6d %5d %5d %5d " "%10"PRId64" %10.3lf" "%10lf %8u %10"PRId64" %10d %10d\n", @@ -2810,6 +2811,9 @@ static void output_frame_level_debug_stats(VP9_COMP *cpi) { cpi->rc.projected_frame_size / cpi->common.MBs, (cpi->rc.projected_frame_size - cpi->rc.this_frame_target), cpi->rc.vbr_bits_off_target, + cpi->rc.vbr_bits_off_target_fast, + cpi->twopass.extend_minq, + cpi->twopass.extend_minq_fast, cpi->rc.total_target_vs_actual, (cpi->rc.starting_buffer_level - cpi->rc.bits_off_target), cpi->rc.total_actual_bits, cm->base_qindex, diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c index 40f65c3e0..2f96a7948 100644 --- a/vp9/encoder/vp9_firstpass.c +++ b/vp9/encoder/vp9_firstpass.c @@ -1247,8 +1247,9 @@ void vp9_init_second_pass(VP9_COMP *cpi) { twopass->modified_error_left = modified_error_total; } - // Reset the vbr bits off target counter + // Reset the vbr bits off target counters cpi->rc.vbr_bits_off_target = 0; + cpi->rc.vbr_bits_off_target_fast = 0; cpi->rc.rate_error_estimate = 0; @@ -2650,6 +2651,7 @@ void vp9_rc_get_second_pass_params(VP9_COMP *cpi) { #define MINQ_ADJ_LIMIT 48 #define MINQ_ADJ_LIMIT_CQ 20 +#define HIGH_UNDERSHOOT_RATIO 2 void vp9_twopass_postencode_update(VP9_COMP *cpi) { TWO_PASS *const twopass = &cpi->twopass; RATE_CONTROL *const rc = &cpi->rc; @@ -2716,5 +2718,32 @@ void vp9_twopass_postencode_update(VP9_COMP *cpi) { twopass->extend_minq = clamp(twopass->extend_minq, 0, minq_adj_limit); twopass->extend_maxq = clamp(twopass->extend_maxq, 0, maxq_adj_limit); + + // If there is a big and undexpected undershoot then feed the extra + // bits back in quickly. One situation where this may happen is if a + // frame is unexpectedly almost perfectly predicted by the ARF or GF + // but not very well predcited by the previous frame. + if (!frame_is_kf_gf_arf(cpi) && !cpi->rc.is_src_frame_alt_ref) { + int fast_extra_thresh = rc->base_frame_target / HIGH_UNDERSHOOT_RATIO; + if (rc->projected_frame_size < fast_extra_thresh) { + rc->vbr_bits_off_target_fast += + fast_extra_thresh - rc->projected_frame_size; + rc->vbr_bits_off_target_fast = + MIN(rc->vbr_bits_off_target_fast, (4 * rc->avg_frame_bandwidth)); + + // Fast adaptation of minQ if necessary to use up the extra bits. + if (rc->avg_frame_bandwidth) { + twopass->extend_minq_fast = + (int)(rc->vbr_bits_off_target_fast * 8 / rc->avg_frame_bandwidth); + } + twopass->extend_minq_fast = MIN(twopass->extend_minq_fast, + minq_adj_limit - twopass->extend_minq); + } else if (rc->vbr_bits_off_target_fast) { + twopass->extend_minq_fast = MIN(twopass->extend_minq_fast, + minq_adj_limit - twopass->extend_minq); + } else { + twopass->extend_minq_fast = 0; + } + } } } diff --git a/vp9/encoder/vp9_firstpass.h b/vp9/encoder/vp9_firstpass.h index 08e7a8bf1..4a0385506 100644 --- a/vp9/encoder/vp9_firstpass.h +++ b/vp9/encoder/vp9_firstpass.h @@ -122,6 +122,7 @@ typedef struct { int baseline_active_worst_quality; int extend_minq; int extend_maxq; + int extend_minq_fast; GF_GROUP gf_group; } TWO_PASS; @@ -135,6 +136,7 @@ void vp9_end_first_pass(struct VP9_COMP *cpi); void vp9_init_second_pass(struct VP9_COMP *cpi); void vp9_rc_get_second_pass_params(struct VP9_COMP *cpi); +void vp9_twopass_postencode_update(struct VP9_COMP *cpi); // Post encode update of the rate control parameters for 2-pass void vp9_twopass_postencode_update(struct VP9_COMP *cpi); diff --git a/vp9/encoder/vp9_ratectrl.c b/vp9/encoder/vp9_ratectrl.c index 7211e9992..98095ac32 100644 --- a/vp9/encoder/vp9_ratectrl.c +++ b/vp9/encoder/vp9_ratectrl.c @@ -1061,10 +1061,12 @@ static int rc_pick_q_and_bounds_two_pass(const VP9_COMP *cpi, if (frame_is_intra_only(cm) || (!rc->is_src_frame_alt_ref && (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame))) { - active_best_quality -= cpi->twopass.extend_minq; + active_best_quality -= + (cpi->twopass.extend_minq + cpi->twopass.extend_minq_fast); active_worst_quality += (cpi->twopass.extend_maxq / 2); } else { - active_best_quality -= cpi->twopass.extend_minq / 2; + active_best_quality -= + (cpi->twopass.extend_minq + cpi->twopass.extend_minq_fast) / 2; active_worst_quality += cpi->twopass.extend_maxq; } } @@ -1671,9 +1673,9 @@ void vp9_rc_update_framerate(VP9_COMP *cpi) { #define VBR_PCT_ADJUSTMENT_LIMIT 50 // For VBR...adjustment to the frame target based on error from previous frames -static void vbr_rate_correction(VP9_COMP *cpi, - int *this_frame_target, - int64_t vbr_bits_off_target) { +static void vbr_rate_correction(VP9_COMP *cpi, int *this_frame_target) { + RATE_CONTROL *const rc = &cpi->rc; + int64_t vbr_bits_off_target = rc->vbr_bits_off_target; int max_delta; double position_factor = 1.0; @@ -1697,6 +1699,20 @@ static void vbr_rate_correction(VP9_COMP *cpi, (vbr_bits_off_target < -max_delta) ? max_delta : (int)-vbr_bits_off_target; } + + // Fast redistribution of bits arising from massive local undershoot. + // Dont do it for kf,arf,gf or overlay frames. + if (!frame_is_kf_gf_arf(cpi) && !rc->is_src_frame_alt_ref && + rc->vbr_bits_off_target_fast) { + int one_frame_bits = MAX(rc->avg_frame_bandwidth, *this_frame_target); + int fast_extra_bits; + fast_extra_bits = + (int)MIN(rc->vbr_bits_off_target_fast, one_frame_bits); + fast_extra_bits = (int)MIN(fast_extra_bits, + MAX(one_frame_bits / 8, rc->vbr_bits_off_target_fast / 8)); + *this_frame_target += (int)fast_extra_bits; + rc->vbr_bits_off_target_fast -= fast_extra_bits; + } } void vp9_set_target_rate(VP9_COMP *cpi) { @@ -1705,6 +1721,6 @@ void vp9_set_target_rate(VP9_COMP *cpi) { // Correction to rate target based on prior over or under shoot. if (cpi->oxcf.rc_mode == VPX_VBR || cpi->oxcf.rc_mode == VPX_CQ) - vbr_rate_correction(cpi, &target_rate, rc->vbr_bits_off_target); + vbr_rate_correction(cpi, &target_rate); vp9_rc_set_frame_target(cpi, target_rate); } diff --git a/vp9/encoder/vp9_ratectrl.h b/vp9/encoder/vp9_ratectrl.h index a2e069929..e12d200be 100644 --- a/vp9/encoder/vp9_ratectrl.h +++ b/vp9/encoder/vp9_ratectrl.h @@ -100,6 +100,7 @@ typedef struct { int64_t buffer_level; int64_t bits_off_target; int64_t vbr_bits_off_target; + int64_t vbr_bits_off_target_fast; int decimation_factor; int decimation_count;