shithub: libvpx

Download patch

ref: d3aaac367bd716b2db06e774f0a8eea7768dd184
parent: e37ee40f7ee0dbafa41e7d1c32dc34740727c7a1
author: Paul Wilkins <paulwilkins@google.com>
date: Wed Mar 31 12:58:51 EDT 2021

Change calculation of rd multiplier.

Change the way the rd multiplier is adjusted for Q and frame type.

Previously in VP9 the rd multiplier was adjusted based on crude Q bins
and whether the frame was a key frame or inter frame.

The Q bins create some problems as they potentially introduce
discontinuities in the RD curve. For example, rate rising with a
stepwise increase in Q instead of falling. As such, in AV1 they
have been removed.

A further issue was identified when examining the first round of
results from from the Vizier project. Here the multiplier for each Q bin
and each frame type was optimized for a training set, for various video
formats, using single point encodes at the appropriate YT rates.

These initial results appeared to show a trend for increased rd
multiplier at higher Q for key frames. This fits with intuition as in
this encoding context a higher Q indicates that a clip is harder to
encode and frames  less well predicted.  However, the situation
appeared to reverse for inter frames with higher rd multipliers
chosen at low Q.

My initial suspicion was that this was a result of over fitting, but on
closer analysis I realized that this may be more related to frame type
within the broader inter frame classification. Specifically frames coded
at low Q are predominantly ARF frames, for the mid Q bin there will
likely be a mix of ARF and normal inter frames, and for the high Q bin
the frames will almost exclusively be normal inter frames from difficult
content.

ARF frames are inherently less well predicted than other inter frames
being further apart and not having access to as many prediction modes.
We also know from previous work that ARF frames have a higher
incidence of INTRA coding and may well behave more like key frames
in this context.

This patch replaces the bin based approach with a linear function
that applies a small but smooth Q based adjustment. It also splits
ARF frames and normal inter frames into separate categories.

With this done number of parameters that will be exposed for the
next round of Vizier training is reduced from 7 to 3 (one adjustment
factor each for inter, ARF and key frames)

This patch gives net BDATE gains for our test sets even with the
baseline / default factors as follows: (% BDRATE change in overall
PSNR and SSIM, -ve is better)

LowRes 		-0.231, -0.050
ugc360p		 0.160,  -0.315
midres2		-0.348, -1.170
hdres2		-0.407, -0.691

Change-Id: I46dd2fea77b1c2849c122f10fd0df74bbd3fcc7f

--- a/vp9/encoder/vp9_rd.c
+++ b/vp9/encoder/vp9_rd.c
@@ -205,62 +205,36 @@
   // Make sure this function is floating point safe.
   vpx_clear_system_state();
 
-  rdc->rd_mult_key_high_qp_fac = 1.0;  // Default: no Vizer values yet
+  rdc->rd_mult_arf_qp_fac = 1.0;  // Default: No Vizier values yet
 
+  // These hard wired estimates for the Vizier values will be removed later
+  // as the per format factors will be set on the command line.
   if (0) {
     unsigned int screen_area = (cpi->common.width * cpi->common.height);
 
     if (screen_area <= 176 * 144) {
-      rdc->rd_mult_inter_low_qp_fac = 1.018;
-      rdc->rd_mult_inter_mid_qp_fac = 0.896;
-      rdc->rd_mult_inter_high_qp_fac = 1.432;
-      rdc->rd_mult_key_ultralow_qp_fac = 1.073;
-      rdc->rd_mult_key_low_qp_fac = 1.630;
-      rdc->rd_mult_key_mid_qp_fac = 1.050;
+      rdc->rd_mult_inter_qp_fac = 0.896;
+      rdc->rd_mult_key_qp_fac = 1.050;
     } else if (screen_area <= 320 * 240) {
-      rdc->rd_mult_inter_low_qp_fac = 1.127;
-      rdc->rd_mult_inter_mid_qp_fac = 0.998;
-      rdc->rd_mult_inter_high_qp_fac = 1.463;
-      rdc->rd_mult_key_ultralow_qp_fac = 1.054;
-      rdc->rd_mult_key_low_qp_fac = 1.285;
-      rdc->rd_mult_key_mid_qp_fac = 0.952;
+      rdc->rd_mult_inter_qp_fac = 0.998;
+      rdc->rd_mult_key_qp_fac = 0.952;
     } else if (screen_area <= 640 * 360) {
-      rdc->rd_mult_inter_low_qp_fac = 1.183;
-      rdc->rd_mult_inter_mid_qp_fac = 0.959;
-      rdc->rd_mult_inter_high_qp_fac = 1.457;
-      rdc->rd_mult_key_ultralow_qp_fac = 1.144;
-      rdc->rd_mult_key_low_qp_fac = 1.734;
-      rdc->rd_mult_key_mid_qp_fac = 1.071;
+      rdc->rd_mult_inter_qp_fac = 0.959;
+      rdc->rd_mult_key_qp_fac = 1.071;
     } else if (screen_area <= 854 * 480) {
-      rdc->rd_mult_inter_low_qp_fac = 1.203;
-      rdc->rd_mult_inter_mid_qp_fac = 1.027;
-      rdc->rd_mult_inter_high_qp_fac = 1.027;
-      rdc->rd_mult_key_ultralow_qp_fac = 1.246;
-      rdc->rd_mult_key_low_qp_fac = 1.246;
-      rdc->rd_mult_key_mid_qp_fac = 1.280;
+      rdc->rd_mult_inter_qp_fac = 1.027;
+      rdc->rd_mult_key_qp_fac = 1.280;
     } else if (screen_area <= 1280 * 720) {
-      rdc->rd_mult_inter_low_qp_fac = 1.280;
-      rdc->rd_mult_inter_mid_qp_fac = 1.004;
-      rdc->rd_mult_inter_high_qp_fac = 1.470;
-      rdc->rd_mult_key_ultralow_qp_fac = 0.987;
-      rdc->rd_mult_key_low_qp_fac = 1.671;
-      rdc->rd_mult_key_mid_qp_fac = 1.193;
+      rdc->rd_mult_inter_qp_fac = 1.004;
+      rdc->rd_mult_key_qp_fac = 1.193;
     } else {
-      rdc->rd_mult_inter_low_qp_fac = 1.50;
-      rdc->rd_mult_inter_mid_qp_fac = 0.874;
-      rdc->rd_mult_inter_high_qp_fac = 1.07;
-      rdc->rd_mult_key_ultralow_qp_fac = 1.1;
-      rdc->rd_mult_key_low_qp_fac = 2.35;
-      rdc->rd_mult_key_mid_qp_fac = 0.837;
+      rdc->rd_mult_inter_qp_fac = 0.874;
+      rdc->rd_mult_key_qp_fac = 0.837;
     }
   } else {
     // For now force defaults unless testing
-    rdc->rd_mult_inter_low_qp_fac = 1.0;
-    rdc->rd_mult_inter_mid_qp_fac = 1.0;
-    rdc->rd_mult_inter_high_qp_fac = 1.0;
-    rdc->rd_mult_key_ultralow_qp_fac = 1.0;
-    rdc->rd_mult_key_low_qp_fac = 1.0;
-    rdc->rd_mult_key_mid_qp_fac = 1.0;
+    rdc->rd_mult_inter_qp_fac = 1.0;
+    rdc->rd_mult_key_qp_fac = 1.0;
   }
 }
 
@@ -273,6 +247,27 @@
 #define KEY_MID_QP_RDM 4.5
 #define KEY_HIGH_QP_RDM 7.5
 
+// Returns the default rd multiplier for inter frames for a given qindex.
+// The function here is a first pass estimate based on data from
+// a previous Vizer run
+static double def_inter_rd_multiplier(int qindex) {
+  return 4.15 + (0.001 * (double)qindex);
+}
+
+// Returns the default rd multiplier for ARF/Golden Frames for a given qindex.
+// The function here is a first pass estimate based on data from
+// a previous Vizer run
+static double def_arf_rd_multiplier(int qindex) {
+  return 4.25 + (0.001 * (double)qindex);
+}
+
+// Returns the default rd multiplier for key frames for a given qindex.
+// The function here is a first pass estimate based on data from
+// a previous Vizer run
+static double def_kf_rd_multiplier(int qindex) {
+  return 4.35 + (0.001 * (double)qindex);
+}
+
 int vp9_compute_rd_mult_based_on_qindex(const VP9_COMP *cpi, int qindex) {
   const RD_CONTROL *rdc = &cpi->rd_ctrl;
   const int q = vp9_dc_quant(qindex, 0, cpi->common.bit_depth);
@@ -282,31 +277,16 @@
   // Make sure this function is floating point safe.
   vpx_clear_system_state();
 
-  if (cpi->common.frame_type != KEY_FRAME) {
-    if (qindex < 128) {
-      rdmult = (int)((double)rdmult * INTER_LOW_QP_RDM *
-                     rdc->rd_mult_inter_low_qp_fac);
-    } else if (qindex < 190) {
-      rdmult = (int)((double)rdmult * INTER_MID_QP_RDM *
-                     rdc->rd_mult_inter_mid_qp_fac);
-    } else {
-      rdmult = (int)((double)rdmult * INTER_HIGH_QP_RDM *
-                     rdc->rd_mult_inter_high_qp_fac);
-    }
+  if (cpi->common.frame_type == KEY_FRAME) {
+    double def_rd_q_mult = def_kf_rd_multiplier(qindex);
+    rdmult = (int)((double)rdmult * def_rd_q_mult * rdc->rd_mult_key_qp_fac);
+  } else if (!cpi->rc.is_src_frame_alt_ref &&
+             (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)) {
+    double def_rd_q_mult = def_arf_rd_multiplier(qindex);
+    rdmult = (int)((double)rdmult * def_rd_q_mult * rdc->rd_mult_arf_qp_fac);
   } else {
-    if (qindex < 64) {
-      rdmult = (int)((double)rdmult * KEY_ULOW_QP_RDM *
-                     rdc->rd_mult_key_ultralow_qp_fac);
-    } else if (qindex <= 128) {
-      rdmult =
-          (int)((double)rdmult * KEY_LOW_QP_RDM * rdc->rd_mult_key_low_qp_fac);
-    } else if (qindex < 190) {
-      rdmult =
-          (int)((double)rdmult * KEY_MID_QP_RDM * rdc->rd_mult_key_mid_qp_fac);
-    } else {
-      rdmult = (int)((double)rdmult * KEY_HIGH_QP_RDM *
-                     rdc->rd_mult_key_high_qp_fac);
-    }
+    double def_rd_q_mult = def_inter_rd_multiplier(qindex);
+    rdmult = (int)((double)rdmult * def_rd_q_mult * rdc->rd_mult_inter_qp_fac);
   }
 
 #if CONFIG_VP9_HIGHBITDEPTH
--- a/vp9/encoder/vp9_rd.h
+++ b/vp9/encoder/vp9_rd.h
@@ -103,13 +103,9 @@
 
 typedef struct {
   // RD multiplier control factors added for Vizier project.
-  double rd_mult_inter_low_qp_fac;
-  double rd_mult_inter_mid_qp_fac;
-  double rd_mult_inter_high_qp_fac;
-  double rd_mult_key_ultralow_qp_fac;
-  double rd_mult_key_low_qp_fac;
-  double rd_mult_key_mid_qp_fac;
-  double rd_mult_key_high_qp_fac;
+  double rd_mult_inter_qp_fac;
+  double rd_mult_arf_qp_fac;
+  double rd_mult_key_qp_fac;
 } RD_CONTROL;
 
 typedef struct RD_OPT {