Adjust rate control enumerator. This adjustment is to improve behavior when stricter rate control is specified on the command line. When the undershoot and overshoot limits are set to 25% the metrics improvements are as follows. (Av psnr, Ov psnr, SSIM Psnr-hvs) Low Res -0.947 -1.032 -0.490 -1.092 UGC 360 -0.587 -0.735 0.229 -0.966 Mid Res -0.335 -0.408 -0.127 -0.517 Hd Res -1.012 -1.108 -0.224 -0.930 However the setting best for 25% os/us is a little worse for 100% which was the setting previously used to tune this number. Low Res 0.068 0.149 0.166 0.047 UGC 360 0.357 0.226 0.936 -0.035 Mid Res -0.061 0.101 0.248 -0.293 Hd Res 0.025 0.236 0.060 0.019 So why the difference ? In general using tighter rate control hurts metrics. If we are targeting the number of bits spent on the clip closely we may spend extra bits, for example, on frames where there is little objective or subjective benefit simply because of undershoot on earlier frames. Two rate control metrics come into play here. One (1) is forward looking and if there was undershoot or overshoot in previous ARF groups it tries to do better in subsequent groups, but does not try and re-allocate bits. The second (2) more specifically targets the total bits spent in the clip by reallocation of the bit budget. Lowering the value of the enumerator used in choosing the active Q range a little seems to improve rate accuracy from (1) slightly and this has a small negative impact on metrics when the rate error tolerance is 100 (which effectively disables (2)). However, when we set a tolerance of 25% the mechanism for (2) is activated less with a lower enumerator and the improvements in metrics that result more than offset the negative impact. Hence the observations here reflect the balance between the two rate control methods and using (1) more aggressively and (2) less seems to give a better outcome. Note also that a reduction of the enumerator compared to that used in VP9 makes sense given the expectation that AV1 has improved compression efficiency. Final results better for lower values of os/us % but neutral for 100% STATS_CHANGED Change-Id: I9c9cfcfce66e74b739aac370c97c6391128b30bb
diff --git a/av1/encoder/pass2_strategy.c b/av1/encoder/pass2_strategy.c index 17cd1e4..4edcf30 100644 --- a/av1/encoder/pass2_strategy.c +++ b/av1/encoder/pass2_strategy.c
@@ -160,11 +160,16 @@ twopass->bpm_factor = AOMMAX(0.25, AOMMIN(4.0, twopass->bpm_factor)); } +static int qbpm_enumerator(int rate_err_tol) { + return 1350000 + ((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( int desired_bits_per_mb, aom_bit_depth_t bit_depth, double error_per_mb, - double group_weight_factor, int best_qindex, int worst_qindex) { + 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; @@ -173,7 +178,7 @@ const int mid = (low + high) >> 1; 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 = 1650000; + const int enumerator = qbpm_enumerator(rate_err_tol); const int mid_bits_per_mb = (int)((enumerator * mid_factor * group_weight_factor) / q); @@ -206,13 +211,15 @@ const int target_norm_bits_per_mb = (int)((uint64_t)section_target_bandwidth << BPER_MB_NORMBITS) / active_mbs; + int rate_err_tol = + AOMMIN(cpi->oxcf.under_shoot_pct, cpi->oxcf.over_shoot_pct); twopass_update_bpm_factor(&cpi->twopass); // Try and pick a max Q that will be high enough to encode the // 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, group_weight_factor, rc->best_quality, + av_err_per_mb, group_weight_factor, rate_err_tol, rc->best_quality, rc->worst_quality); // Restriction on active max q for constrained quality mode.