shithub: libvpx

Download patch

ref: 8d7f53f04c59471942aa46b3051495da3e973d0f
parent: f03627347edfc63fc4127af4cc2aa0f41a32fa91
author: paulwilkins <paulwilkins@google.com>
date: Fri Feb 20 08:41:25 EST 2015

Account for rate error in GF group Q calculation.

When GF group adaptive maxQ is enabled this patch accounts
somewhat for accumulated error in the rate control.

This improves accuracy quite a bit on many clips especially
when there is  overshoot.

Examples when the overshoot and undershoot command line
parameters are set to 100:

Hall @ 1200 overshoot is reduced from 67-24%.
Akiyo @ 400 undershoot is reduced from 28%-15%.

Setting a lower value for undershoot or overshoot still
reduces the error further.

Impact on metrics is mixed with some gains in average psnr
but generally a little lower (e.g. 0.5%) on overall and ssim.

The GF group adaptation is still off by default in this patch.
Compared to with the head, enabling this mode now gives
big average psnr gains on the YT sets (e.g. YT_HD >11.2%),
a drop in overall PSNR (YT-HD 3.9%) and a smaller drop or
neutral for SSIM.

Change-Id: If4b32cd0740d3fb941317b374f9c2951954eee90

--- a/vp9/encoder/vp9_firstpass.c
+++ b/vp9/encoder/vp9_firstpass.c
@@ -57,6 +57,8 @@
 #define SVC_FACTOR_PT_LOW   0.45
 #define DARK_THRESH         64
 #define DEFAULT_GRP_WEIGHT  1.0
+#define RC_FACTOR_MIN       0.75
+#define RC_FACTOR_MAX       1.75
 
 #define DOUBLE_DIVIDE_CHECK(x) ((x) < 0 ? (x) - 0.000001 : (x) + 0.000001)
 
@@ -1960,16 +1962,21 @@
     const int vbr_group_bits_per_frame =
       (int)(gf_group_bits / rc->baseline_gf_interval);
     const double group_av_err = gf_group_raw_error  / rc->baseline_gf_interval;
-    const int tmp_q =
-      get_twopass_worst_quality(cpi, group_av_err, vbr_group_bits_per_frame,
-                                twopass->kfgroup_inter_fraction);
-
-    if (tmp_q < twopass->baseline_active_worst_quality) {
-      twopass->active_worst_quality =
-        (tmp_q + twopass->baseline_active_worst_quality + 1) / 2;
+    int tmp_q;
+    // rc factor is a weight factor that corrects for local rate control drift.
+    double rc_factor = 1.0;
+    if (rc->rate_error_estimate > 0) {
+      rc_factor = MAX(RC_FACTOR_MIN,
+                      (double)(100 - rc->rate_error_estimate) / 100.0);
     } else {
-      twopass->active_worst_quality = tmp_q;
+      rc_factor = MIN(RC_FACTOR_MAX,
+                      (double)(100 - rc->rate_error_estimate) / 100.0);
     }
+    tmp_q =
+      get_twopass_worst_quality(cpi, group_av_err, vbr_group_bits_per_frame,
+                                twopass->kfgroup_inter_fraction * rc_factor);
+    twopass->active_worst_quality =
+      MAX(tmp_q, twopass->active_worst_quality >> 1);
   }
 #endif
 
@@ -2577,7 +2584,7 @@
   subtract_stats(&twopass->total_left_stats, &this_frame);
 }
 
-#define MINQ_ADJ_LIMIT 32
+#define MINQ_ADJ_LIMIT 48
 void vp9_twopass_postencode_update(VP9_COMP *cpi) {
   TWO_PASS *const twopass = &cpi->twopass;
   RATE_CONTROL *const rc = &cpi->rc;
@@ -2610,8 +2617,7 @@
   // Increment the gf group index ready for the next frame.
   ++twopass->gf_group.index;
 
-  // If the rate control is drifting consider adjustment ot min or maxq.
-  // Only make adjustments on gf/arf
+  // If the rate control is drifting consider adjustment to min or maxq.
   if ((cpi->oxcf.rc_mode == VPX_VBR) &&
       (cpi->twopass.gf_zeromotion_pct < VLOW_MOTION_THRESHOLD) &&
       !cpi->rc.is_src_frame_alt_ref) {
@@ -2640,6 +2646,7 @@
       else if (rc->rolling_target_bits > rc->rolling_actual_bits)
         --twopass->extend_maxq;
     }
+
     twopass->extend_minq = clamp(twopass->extend_minq, 0, MINQ_ADJ_LIMIT);
     twopass->extend_maxq = clamp(twopass->extend_maxq, 0, maxq_adj_limit);
   }
--- a/vp9/vp9_cx_iface.c
+++ b/vp9/vp9_cx_iface.c
@@ -158,8 +158,8 @@
   RANGE_CHECK_HI(cfg, g_threads,          64);
   RANGE_CHECK_HI(cfg, g_lag_in_frames,    MAX_LAG_BUFFERS);
   RANGE_CHECK(cfg, rc_end_usage,          VPX_VBR, VPX_Q);
-  RANGE_CHECK_HI(cfg, rc_undershoot_pct,  1000);
-  RANGE_CHECK_HI(cfg, rc_overshoot_pct,   1000);
+  RANGE_CHECK_HI(cfg, rc_undershoot_pct,  100);
+  RANGE_CHECK_HI(cfg, rc_overshoot_pct,   100);
   RANGE_CHECK_HI(cfg, rc_2pass_vbr_bias_pct, 100);
   RANGE_CHECK(cfg, kf_mode,               VPX_KF_DISABLED, VPX_KF_AUTO);
   RANGE_CHECK_BOOL(cfg,                   rc_resize_allowed);