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);