vp9: Adjust cyclic refresh and limit frame-level q.
authorMarco Paniconi <marpan@google.com>
Tue, 29 May 2018 04:08:57 +0000 (21:08 -0700)
committerMarco Paniconi <marpan@google.com>
Tue, 29 May 2018 22:19:49 +0000 (15:19 -0700)
For CBR mode with aq-mode=3: reduce delta-q for second
segment and limit how much the frame-level q can decreae
from one frame to the next.

Reduces bitrate spikes in slide/sreen content.

Change-Id: Id9ac4b7270f07e09690380755cfbef4aec5c26dc

vp9/encoder/vp9_aq_cyclicrefresh.c
vp9/encoder/vp9_aq_cyclicrefresh.h
vp9/encoder/vp9_ratectrl.c

index b8c5572..3aaec2e 100644 (file)
@@ -459,6 +459,15 @@ void vp9_cyclic_refresh_update_parameters(VP9_COMP *const cpi) {
       cr->rate_boost_fac = 13;
     }
   }
+  // For screen-content: keep rate_ratio_qdelta to 2.0 (segment#1 boost) and
+  // percent_refresh (refresh rate) to 10. But reduce rate boost for segment#2
+  // (rate_boost_fac = 10 disables segment#2).
+  // TODO(marpan): Consider increasing refresh rate after slide change.
+  if (cpi->oxcf.content == VP9E_CONTENT_SCREEN) {
+    cr->percent_refresh = 10;
+    cr->rate_ratio_qdelta = 2.0;
+    cr->rate_boost_fac = 10;
+  }
   // Adjust some parameters for low resolutions.
   if (cm->width <= 352 && cm->height <= 288) {
     if (rc->avg_frame_bandwidth < 3000) {
@@ -589,3 +598,11 @@ void vp9_cyclic_refresh_reset_resize(VP9_COMP *const cpi) {
   cpi->refresh_golden_frame = 1;
   cpi->refresh_alt_ref_frame = 1;
 }
+
+void vp9_cyclic_refresh_limit_q(CYCLIC_REFRESH *const cr, int prev_q, int *q) {
+  // For now apply hard limit to frame-level decrease in q, if the cyclic
+  // refresh is active (percent_refresh > 0).
+  if (cr->percent_refresh > 0 && prev_q - *q > 8) {
+    *q = prev_q - 8;
+  }
+}
index 77fa67c..ce72fcb 100644 (file)
@@ -139,6 +139,8 @@ static INLINE int cyclic_refresh_segment_id(int segment_id) {
     return CR_SEGMENT_ID_BASE;
 }
 
+void vp9_cyclic_refresh_limit_q(CYCLIC_REFRESH *const cr, int prev_q, int *q);
+
 #ifdef __cplusplus
 }  // extern "C"
 #endif
index 2c339ae..01c1ab4 100644 (file)
@@ -712,21 +712,26 @@ int vp9_rc_regulate_q(const VP9_COMP *cpi, int target_bits_per_frame,
     }
   } while (++i <= active_worst_quality);
 
-  // In CBR mode, this makes sure q is between oscillating Qs to prevent
-  // resonance.
-  if (cpi->oxcf.rc_mode == VPX_CBR && !cpi->rc.reset_high_source_sad &&
-      (!cpi->oxcf.gf_cbr_boost_pct ||
-       !(cpi->refresh_alt_ref_frame || cpi->refresh_golden_frame)) &&
-      (cpi->rc.rc_1_frame * cpi->rc.rc_2_frame == -1) &&
-      cpi->rc.q_1_frame != cpi->rc.q_2_frame) {
-    int qclamp = clamp(q, VPXMIN(cpi->rc.q_1_frame, cpi->rc.q_2_frame),
-                       VPXMAX(cpi->rc.q_1_frame, cpi->rc.q_2_frame));
-    // If the previous had overshoot and the current q needs to increase above
-    // the clamped value, reduce the clamp for faster reaction to overshoot.
-    if (cpi->rc.rc_1_frame == -1 && q > qclamp)
-      q = (q + qclamp) >> 1;
-    else
-      q = qclamp;
+  // Adjustment to q for CBR mode.
+  if (cpi->oxcf.rc_mode == VPX_CBR) {
+    // This makes sure q is between oscillating Qs to prevent resonance.
+    if (!cpi->rc.reset_high_source_sad &&
+        (!cpi->oxcf.gf_cbr_boost_pct ||
+         !(cpi->refresh_alt_ref_frame || cpi->refresh_golden_frame)) &&
+        (cpi->rc.rc_1_frame * cpi->rc.rc_2_frame == -1) &&
+        cpi->rc.q_1_frame != cpi->rc.q_2_frame) {
+      int qclamp = clamp(q, VPXMIN(cpi->rc.q_1_frame, cpi->rc.q_2_frame),
+                         VPXMAX(cpi->rc.q_1_frame, cpi->rc.q_2_frame));
+      // If the previous frame had overshoot and the current q needs to increase
+      // above the clamped value, reduce the clamp for faster reaction to
+      // overshoot.
+      if (cpi->rc.rc_1_frame == -1 && q > qclamp)
+        q = (q + qclamp) >> 1;
+      else
+        q = qclamp;
+    }
+    if (cpi->oxcf.content == VP9E_CONTENT_SCREEN)
+      vp9_cyclic_refresh_limit_q(cr, cpi->rc.q_1_frame, &q);
   }
   return q;
 }