shithub: libvpx

Download patch

ref: 7ca417f66547dc5e9e3ad36c45e147f05e66522a
parent: 806e1c9843b90a94607e1ef3673b0e094d5df551
author: Jingning Han <jingning@google.com>
date: Fri Nov 30 05:23:33 EST 2018

Simplify constant q mode qp selection

Decouple the constant q mode qp selection from vbr/cbr/cq modes.
Skip vp9_frame_type_qdelta() adjustment for non-ARF inter frames,
instead keep using the cq-level. It improves the compresson
performance:

         avg PSNR       overall PSNR     SSIM
lowres   -0.17%         -0.20%           -0.1%
midres   -0.21%         -0.24%           -0.08%
hdres    -0.15%         -0.19%           -0.04%

Change-Id: I52fd5f8edbd3fdcbeda31ee3a6d6eb016091a7e3

--- a/vp9/encoder/vp9_ratectrl.c
+++ b/vp9/encoder/vp9_ratectrl.c
@@ -1272,14 +1272,10 @@
 
 #define STATIC_MOTION_THRESH 95
 
-static int pick_kf_q_bound_two_pass(const VP9_COMP *cpi, int *bottom_index,
-                                    int *top_index) {
+static void pick_kf_q_bound_two_pass(const VP9_COMP *cpi, int *bottom_index,
+                                     int *top_index) {
   const VP9_COMMON *const cm = &cpi->common;
   const RATE_CONTROL *const rc = &cpi->rc;
-  const VP9EncoderConfig *const oxcf = &cpi->oxcf;
-  const int cq_level = get_active_cq_level_two_pass(&cpi->twopass, rc, oxcf);
-
-  int q = cq_level;
   int active_best_quality;
   int active_worst_quality = cpi->twopass.active_worst_quality;
 
@@ -1338,7 +1334,46 @@
   }
   *top_index = active_worst_quality;
   *bottom_index = active_best_quality;
+}
 
+static int rc_constant_q(const VP9_COMP *cpi, int *bottom_index, int *top_index,
+                         int gf_group_index) {
+  const VP9_COMMON *const cm = &cpi->common;
+  const RATE_CONTROL *const rc = &cpi->rc;
+  const VP9EncoderConfig *const oxcf = &cpi->oxcf;
+  const GF_GROUP *gf_group = &cpi->twopass.gf_group;
+  const int is_intra_frame = frame_is_intra_only(cm);
+
+  const int cq_level = get_active_cq_level_two_pass(&cpi->twopass, rc, oxcf);
+
+  int q = cq_level;
+  int active_best_quality = cq_level;
+  int active_worst_quality = cq_level;
+
+  // Key frame qp decision
+  if (is_intra_frame && rc->frames_to_key > 1)
+    pick_kf_q_bound_two_pass(cpi, &active_best_quality, &active_worst_quality);
+
+  // ARF / GF qp decision
+  if (!is_intra_frame && !rc->is_src_frame_alt_ref &&
+      cpi->refresh_alt_ref_frame) {
+    active_best_quality = get_gf_active_quality(cpi, q, cm->bit_depth);
+
+    // Modify best quality for second level arfs. For mode VPX_Q this
+    // becomes the baseline frame q.
+    if (gf_group->rf_level[gf_group_index] == GF_ARF_LOW) {
+      const int layer_depth = gf_group->layer_depth[gf_group_index];
+      // linearly fit the frame q depending on the layer depth index from
+      // the base layer ARF.
+      active_best_quality = ((layer_depth - 1) * cq_level +
+                             active_best_quality + layer_depth / 2) /
+                            layer_depth;
+    }
+  }
+
+  q = active_best_quality;
+  *top_index = active_worst_quality;
+  *bottom_index = active_best_quality;
   return q;
 }
 
@@ -1354,6 +1389,9 @@
   int q;
   int *inter_minq;
   ASSIGN_MINQ_TABLE(cm->bit_depth, inter_minq);
+
+  if (oxcf->rc_mode == VPX_Q)
+    return rc_constant_q(cpi, bottom_index, top_index, gf_group_index);
 
   if (frame_is_intra_only(cm)) {
     if (rc->frames_to_key == 1 && oxcf->rc_mode == VPX_Q) {