Commit 4ff7ae6260 for aom
commit 4ff7ae62609a8734bacb63dc06572119815c58ac
Author: Lin Zheng <linzhen@google.com>
Date: Wed May 20 15:44:13 2026 +0000
Tweak the bmp_factor update logic in vbr mode
The changes enhanced coding efficiency for all speed levels in GOOD mode, while maintaining a neutral impact on encoding speed.
By testing across various resolutions for speeds 0 through 4, gains were
observed as follows on average:
-0.42% for psnr1411, -0.52% for ssim, -0.86% for uvq, and -0.18% for vmaf. The rc_error and abs_rc_error are 0.347% and 0.504%, respectively.
Notably, it shows decent improvement for ugc1080p on average from speed
0 to 4: psnr1411/ssim/vmaf/uvq gains are -0.84%/-0.98%/-0.58%/-1.377%.
In this case, rc_error is -0.298% and abs_rc_error is 0.428%.
Change-Id: I2bd85e3303948a43d6751286041539d49dee1b35
diff --git a/av1/encoder/pass2_strategy.c b/av1/encoder/pass2_strategy.c
index 81adede24f..19ce429368 100644
--- a/av1/encoder/pass2_strategy.c
+++ b/av1/encoder/pass2_strategy.c
@@ -187,37 +187,6 @@ static void twopass_update_bpm_factor(AV1_COMP *cpi, int rate_err_tol) {
// 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;
- const double max_fac = 1.0 + adj_limit;
-
-#if CONFIG_THREE_PASS
- if (cpi->third_pass_ctx && cpi->third_pass_ctx->frame_info_count > 0) {
- int64_t actual_bits = 0;
- int64_t target_bits = 0;
- double factor = 0.0;
- int count = 0;
- for (int i = 0; i < cpi->third_pass_ctx->frame_info_count; i++) {
- actual_bits += cpi->third_pass_ctx->frame_info[i].actual_bits;
- target_bits += cpi->third_pass_ctx->frame_info[i].bits_allocated;
- factor += cpi->third_pass_ctx->frame_info[i].bpm_factor;
- count++;
- }
-
- if (count == 0) {
- factor = 1.0;
- } else {
- factor /= (double)count;
- }
-
- factor *= (double)actual_bits / DOUBLE_DIVIDE_CHECK((double)target_bits);
-
- if ((twopass->bpm_factor <= 1 && factor < twopass->bpm_factor) ||
- (twopass->bpm_factor >= 1 && factor > twopass->bpm_factor)) {
- twopass->bpm_factor = fclamp(factor, min_fac, max_fac);
- }
- }
-#endif // CONFIG_THREE_PASS
int err_estimate = p_rc->rate_error_estimate;
int64_t bits_left = twopass->bits_left;
@@ -252,6 +221,62 @@ static void twopass_update_bpm_factor(AV1_COMP *cpi, int rate_err_tol) {
err_estimate = simulate_parallel_frame ? p_rc->temp_rate_error_estimate
: p_rc->rate_error_estimate;
#endif
+ double adj_limit_cap;
+
+ if (rate_err_tol) {
+ const double initial_adj_limit = 0.0626;
+ const double abs_err_tol = 0.6 * rate_err_tol;
+ const double step_size =
+ (0.2 - initial_adj_limit) / (rate_err_tol - abs_err_tol);
+ const double abs_err_till_now =
+ 100 *
+ fabs((double)(bits_off_target) / AOMMAX(total_actual_bits, bits_left));
+ adj_limit_cap = initial_adj_limit;
+
+ // Increase the adj_limit_cap (i.e., allow a swifter adjustment rate) as the
+ // abs_err_till_now increases.
+ if (abs_err_till_now >= abs_err_tol) {
+ adj_limit_cap =
+ AOMMIN(0.2, initial_adj_limit +
+ (abs_err_till_now - abs_err_tol) * step_size);
+ }
+ } else {
+ // Force adj_limit_cap to 0.2 when rate_err_tol is 0.
+ adj_limit_cap = 0.2;
+ }
+
+ const double adj_limit =
+ AOMMAX(adj_limit_cap, (double)(100 - rate_err_tol) / 200.0);
+ const double min_fac = 1.0 - adj_limit;
+ const double max_fac = 1.0 + adj_limit;
+
+#if CONFIG_THREE_PASS
+ if (cpi->third_pass_ctx && cpi->third_pass_ctx->frame_info_count > 0) {
+ int64_t actual_bits = 0;
+ int64_t target_bits = 0;
+ double factor = 0.0;
+ int count = 0;
+ for (int i = 0; i < cpi->third_pass_ctx->frame_info_count; i++) {
+ actual_bits += cpi->third_pass_ctx->frame_info[i].actual_bits;
+ target_bits += cpi->third_pass_ctx->frame_info[i].bits_allocated;
+ factor += cpi->third_pass_ctx->frame_info[i].bpm_factor;
+ count++;
+ }
+
+ if (count == 0) {
+ factor = 1.0;
+ } else {
+ factor /= (double)count;
+ }
+
+ factor *= (double)actual_bits / DOUBLE_DIVIDE_CHECK((double)target_bits);
+
+ if ((twopass->bpm_factor <= 1 && factor < twopass->bpm_factor) ||
+ (twopass->bpm_factor >= 1 && factor > twopass->bpm_factor)) {
+ twopass->bpm_factor = fclamp(factor, min_fac, max_fac);
+ }
+ }
+#endif // CONFIG_THREE_PASS
if (p_rc->bits_off_target && total_actual_bits > 0) {
if (cpi->ppi->lap_enabled) {
@@ -285,8 +310,9 @@ static void twopass_update_bpm_factor(AV1_COMP *cpi, int rate_err_tol) {
}
}
-static int qbpm_enumerator(int rate_err_tol) {
- return 1200000 + ((300000 * AOMMIN(75, AOMMAX(rate_err_tol - 25, 0))) / 75);
+static int qbpm_enumerator(int rate_err_tol, bool use_smaller_enumerator) {
+ return (use_smaller_enumerator ? 1050000 : 1125750) +
+ ((300000 * AOMMIN(75, AOMMAX(rate_err_tol - 25, 0))) / 75);
}
// Similar to find_qindex_by_rate() function in ratectrl.c, but includes
@@ -294,7 +320,7 @@ static int qbpm_enumerator(int rate_err_tol) {
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) {
+ int best_qindex, int worst_qindex, bool use_smaller_enumerator) {
assert(best_qindex <= worst_qindex);
int low = best_qindex;
int high = worst_qindex;
@@ -303,7 +329,8 @@ static int find_qindex_by_rate_with_correction(
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 = qbpm_enumerator(rate_err_tol);
+ const int enumerator =
+ qbpm_enumerator(rate_err_tol, use_smaller_enumerator);
const uint64_t mid_bits_per_mb =
(uint64_t)((enumerator * mid_factor * group_weight_factor) / q);
@@ -346,6 +373,10 @@ static int get_twopass_worst_quality(AV1_COMP *cpi, const double av_frame_err,
const RateControlCfg *const rc_cfg = &oxcf->rc_cfg;
inactive_zone = fclamp(inactive_zone, 0.0, 0.9999);
+ // Use a smaller qbpm_enumerator for the first GOP.
+ const bool use_smaller_enumerator =
+ ((cpi->ppi->p_rc.total_actual_bits == 0) ? true : false);
+
if (av_target_bandwidth <= 0) {
return rc->worst_quality; // Highest value allowed
} else {
@@ -366,7 +397,7 @@ static int get_twopass_worst_quality(AV1_COMP *cpi, const double av_frame_err,
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, rate_err_tol,
- rc->best_quality, rc->worst_quality);
+ rc->best_quality, rc->worst_quality, use_smaller_enumerator);
// Restriction on active max q for constrained quality mode.
if (rc_cfg->mode == AOM_CQ) q = AOMMAX(q, rc_cfg->cq_level);