Adjust the rate estimation logic in vbr mode Up to 11% speedup for all speed levels with -0.4% to -0.6% ovr_psnr gain. Change-Id: I3a742f2d8f5e218e4aaa56624691716a9cabad9d
diff --git a/av1/encoder/pass2_strategy.c b/av1/encoder/pass2_strategy.c index 99dcfb8..a109109 100644 --- a/av1/encoder/pass2_strategy.c +++ b/av1/encoder/pass2_strategy.c
@@ -164,12 +164,28 @@ return (int)max_bits; } +static const double q_pow_term[(QINDEX_RANGE >> 5) + 1] = { 0.65, 0.70, 0.75, + 0.80, 0.85, 0.90, + 0.95, 0.95, 0.95 }; +#define ERR_DIVISOR 96.0 +static double calc_correction_factor(double err_per_mb, int q) { + const double error_term = err_per_mb / ERR_DIVISOR; + const int index = q >> 5; + // Adjustment to power term based on qindex + const double power_term = + q_pow_term[index] + + (((q_pow_term[index + 1] - q_pow_term[index]) * (q % 32)) / 32.0); + assert(error_term >= 0.0); + return fclamp(pow(error_term, power_term), 0.05, 5.0); +} + // Based on history adjust expectations of bits per macroblock. static void twopass_update_bpm_factor(AV1_COMP *cpi, int rate_err_tol) { TWO_PASS *const twopass = &cpi->ppi->twopass; const PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc; // Based on recent history adjust expectations of bits per macroblock. + double damp_fac = AOMMAX(5.0, rate_err_tol / 10.0); double rate_err_factor = 1.0; const double adj_limit = AOMMAX(0.2, (double)(100 - rate_err_tol) / 200.0); const double min_fac = 1.0 - adj_limit; @@ -204,7 +220,9 @@ #endif // CONFIG_THREE_PASS int err_estimate = p_rc->rate_error_estimate; + int64_t bits_left = twopass->bits_left; int64_t total_actual_bits = p_rc->total_actual_bits; + int64_t bits_off_target = p_rc->vbr_bits_off_target; double rolling_arf_group_actual_bits = (double)twopass->rolling_arf_group_actual_bits; double rolling_arf_group_target_bits = @@ -219,6 +237,10 @@ : 0; total_actual_bits = simulate_parallel_frame ? p_rc->temp_total_actual_bits : p_rc->total_actual_bits; + bits_off_target = simulate_parallel_frame ? p_rc->temp_vbr_bits_off_target + : p_rc->vbr_bits_off_target; + bits_left = + simulate_parallel_frame ? p_rc->temp_bits_left : twopass->bits_left; rolling_arf_group_target_bits = (double)(simulate_parallel_frame ? p_rc->temp_rolling_arf_group_target_bits @@ -231,22 +253,22 @@ : p_rc->rate_error_estimate; #endif - if ((p_rc->bits_off_target && total_actual_bits > 0) && - (rolling_arf_group_target_bits >= 1.0)) { - if (rolling_arf_group_actual_bits > rolling_arf_group_target_bits) { - double error_fraction = - (rolling_arf_group_actual_bits - rolling_arf_group_target_bits) / - rolling_arf_group_target_bits; - error_fraction = (error_fraction > 1.0) ? 1.0 : error_fraction; - rate_err_factor = 1.0 + error_fraction; + if (p_rc->bits_off_target && total_actual_bits > 0) { + if (cpi->ppi->lap_enabled) { + rate_err_factor = rolling_arf_group_actual_bits / + DOUBLE_DIVIDE_CHECK(rolling_arf_group_target_bits); } else { - double error_fraction = - (rolling_arf_group_target_bits - rolling_arf_group_actual_bits) / - rolling_arf_group_target_bits; - rate_err_factor = 1.0 - error_fraction; + rate_err_factor = 1.0 - ((double)(bits_off_target) / + AOMMAX(total_actual_bits, bits_left)); } - rate_err_factor = fclamp(rate_err_factor, min_fac, max_fac); + // Adjustment is damped if this is 1 pass with look ahead processing + // (as there are only ever a few frames of data) and for all but the first + // GOP in normal two pass. + if ((twopass->bpm_factor != 1.0) || cpi->ppi->lap_enabled) { + rate_err_factor = 1.0 + ((rate_err_factor - 1.0) / damp_fac); + } + rate_err_factor = AOMMAX(min_fac, AOMMIN(max_fac, rate_err_factor)); } // Is the rate control trending in the right direction. Only make @@ -254,44 +276,36 @@ if ((rate_err_factor < 1.0 && err_estimate >= 0) || (rate_err_factor > 1.0 && err_estimate <= 0)) { twopass->bpm_factor *= rate_err_factor; - twopass->bpm_factor = fclamp(twopass->bpm_factor, min_fac, max_fac); + if (rate_err_tol >= 100) { + twopass->bpm_factor = + AOMMAX(min_fac, AOMMIN(max_fac, twopass->bpm_factor)); + } else { + twopass->bpm_factor = AOMMAX(0.1, AOMMIN(10.0, twopass->bpm_factor)); + } } } -static const double q_div_term[(QINDEX_RANGE >> 4) + 1] = { - 18.0, 30.0, 38.0, 44.0, 47.0, 50.0, 52.0, 54.0, 56.0, - 58.0, 60.0, 62.0, 64.0, 66.0, 68.0, 70.0, 72.0 -}; - -#define EPMB_SCALER 1250000 -static double calc_correction_factor(double err_per_mb, int q) { - double power_term = 0.90; - const int index = q >> 4; - const double divisor = - q_div_term[index] + - (((q_div_term[index + 1] - q_div_term[index]) * (q % 16)) / 16.0); - double error_term = EPMB_SCALER * pow(err_per_mb, power_term); - return error_term / divisor; +static int qbpm_enumerator(int rate_err_tol) { + return 1200000 + ((300000 * AOMMIN(75, AOMMAX(rate_err_tol - 25, 0))) / 75); } // Similar to find_qindex_by_rate() function in ratectrl.c, but includes // calculation of a correction_factor. -static int find_qindex_by_rate_with_correction(uint64_t desired_bits_per_mb, - aom_bit_depth_t bit_depth, - double error_per_mb, - double group_weight_factor, - int best_qindex, - int worst_qindex) { +static int find_qindex_by_rate_with_correction( + uint64_t desired_bits_per_mb, aom_bit_depth_t bit_depth, + double error_per_mb, double group_weight_factor, int rate_err_tol, + int best_qindex, int worst_qindex) { assert(best_qindex <= worst_qindex); int low = best_qindex; int high = worst_qindex; while (low < high) { const int mid = (low + high) >> 1; - const double q_factor = calc_correction_factor(error_per_mb, mid); + const double mid_factor = calc_correction_factor(error_per_mb, mid); const double q = av1_convert_qindex_to_q(mid, bit_depth); + const int enumerator = qbpm_enumerator(rate_err_tol); const uint64_t mid_bits_per_mb = - (uint64_t)((q_factor * group_weight_factor) / q); + (uint64_t)((enumerator * mid_factor * group_weight_factor) / q); if (mid_bits_per_mb > desired_bits_per_mb) { low = mid + 1; @@ -343,10 +357,6 @@ const uint64_t target_norm_bits_per_mb = ((uint64_t)av_target_bandwidth << BPER_MB_NORMBITS) / active_mbs; int rate_err_tol = AOMMIN(rc_cfg->under_shoot_pct, rc_cfg->over_shoot_pct); - const double size_factor = - (active_mbs < 500) ? 0.925 : ((active_mbs > 3000) ? 1.05 : 1.0); - const double speed_factor = - AOMMIN(1.02, (0.975 + (0.005 * cpi->oxcf.speed))); // Update bpm correction factor based on previous GOP rate error. twopass_update_bpm_factor(cpi, rate_err_tol); @@ -355,8 +365,7 @@ // content at the given rate. int q = find_qindex_by_rate_with_correction( target_norm_bits_per_mb, cpi->common.seq_params->bit_depth, - av_err_per_mb, - cpi->ppi->twopass.bpm_factor * speed_factor * size_factor, + av_err_per_mb, cpi->ppi->twopass.bpm_factor, rate_err_tol, rc->best_quality, rc->worst_quality); // Restriction on active max q for constrained quality mode. @@ -4274,7 +4283,7 @@ int maxq_adj_limit; minq_adj_limit = (rc_cfg->mode == AOM_CQ ? MINQ_ADJ_LIMIT_CQ : MINQ_ADJ_LIMIT); - maxq_adj_limit = (rc->worst_quality - rc->active_worst_quality); + maxq_adj_limit = rc->worst_quality - rc->active_worst_quality; // Undershoot if ((rc_cfg->under_shoot_pct < 100) && @@ -4286,9 +4295,8 @@ if ((pct_error >= rc_cfg->under_shoot_pct) && (p_rc->rate_error_estimate > 0)) { twopass->extend_minq += 1; - twopass->extend_maxq -= 1; } - + twopass->extend_maxq -= 1; // Overshoot } else if ((rc_cfg->over_shoot_pct < 100) && (p_rc->rolling_actual_bits > p_rc->rolling_target_bits)) { @@ -4300,8 +4308,18 @@ if ((pct_error >= rc_cfg->over_shoot_pct) && (p_rc->rate_error_estimate < 0)) { twopass->extend_maxq += 1; - twopass->extend_minq -= 1; } + twopass->extend_minq -= 1; + } else { + // Adjustment for extreme local overshoot. + // Only applies when normal adjustment above is not used (e.g. + // when threshold is set to 100). + if (rc->projected_frame_size > (2 * rc->base_frame_target) && + rc->projected_frame_size > (2 * rc->avg_frame_bandwidth)) + ++twopass->extend_maxq; + // Unwind extreme overshoot adjustment. + else if (p_rc->rolling_target_bits > p_rc->rolling_actual_bits) + --twopass->extend_maxq; } twopass->extend_minq = clamp(twopass->extend_minq, -minq_adj_limit, minq_adj_limit);
diff --git a/av1/encoder/ratectrl.c b/av1/encoder/ratectrl.c index 085cc9f..0953089 100644 --- a/av1/encoder/ratectrl.c +++ b/av1/encoder/ratectrl.c
@@ -1843,8 +1843,8 @@ } #else (void)is_intrl_arf_boost; - active_best_quality -= cpi->ppi->twopass.extend_minq / 8; - active_worst_quality += cpi->ppi->twopass.extend_maxq / 4; + active_best_quality -= cpi->ppi->twopass.extend_minq / 4; + active_worst_quality += cpi->ppi->twopass.extend_maxq; #endif }
diff --git a/test/level_test.cc b/test/level_test.cc index dd8981c..70f4b21 100644 --- a/test/level_test.cc +++ b/test/level_test.cc
@@ -135,12 +135,12 @@ // To save run time, we only test speed 4. if (cpu_used_ == 4) { libaom_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, - 30, 1, 0, 30); + 30, 1, 0, 40); target_level_ = kLevelKeepStats; cfg_.rc_target_bitrate = 1000; - cfg_.g_limit = 30; + cfg_.g_limit = 40; ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); - ASSERT_LE(level_[0], 0); + ASSERT_EQ(level_[0], 0); } } @@ -148,12 +148,12 @@ // To save run time, we only test speed 4. if (cpu_used_ == 4) { libaom_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, - 30, 1, 0, 30); + 30, 1, 0, 40); target_level_ = kLevelKeepStats; cfg_.rc_target_bitrate = 4000; - cfg_.g_limit = 30; + cfg_.g_limit = 40; ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); - ASSERT_LE(level_[0], 4); + ASSERT_EQ(level_[0], 4); } } @@ -166,7 +166,7 @@ target_level_ = target_level; cfg_.rc_target_bitrate = 4000; ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); - ASSERT_LE(level_[0], target_level); + ASSERT_EQ(level_[0], target_level); } }