Assign q indices based on qstep_ratio.

Previously, we computed the highest level frame's qstep_ratio, then used
av1_q_mode_compute_gop_q_indices to determine the other frames' q
indices.

This change instead calculates the qstep_ratio for each frame in the GOP
and stores them in the vbr_rc_info struct. Then, each frame q index is
determined from the individual qstep_ratios.

We see a slight performance drop in PSNR and abs_rc_error in this CL.
This is because we use the unfiltered ARF when calculating the
qstep_ratios. This performance drop will be compensated in a
following CL. We evaluate this CL on lowres dataset with --limit=17.
The results for this CL are below.

              avg_psnr   ovr_psnr   abs_rc_error
previous CL   0.148%     -1.044%    -9.046%
this CL       0.384%     -0.588%    -7.979%

BUG=aomedia:3045

Change-Id: I6f40c5bff908e1898f25229337426fb4308c5b13
diff --git a/av1/encoder/ratectrl.c b/av1/encoder/ratectrl.c
index 6bd432d..79dc8ef 100644
--- a/av1/encoder/ratectrl.c
+++ b/av1/encoder/ratectrl.c
@@ -2900,16 +2900,13 @@
  * Intended to be used only with AOM_Q mode.
  */
 void av1_q_mode_compute_gop_q_indices(int gf_frame_index, int base_q_index,
-                                      double arf_qstep_ratio,
+                                      const double *qstep_ratio_list,
                                       aom_bit_depth_t bit_depth,
                                       const struct GF_GROUP *gf_group,
                                       int *q_index_list) {
-  const int arf_q = av1_get_q_index_from_qstep_ratio(
-      base_q_index, arf_qstep_ratio, bit_depth);
-  for (int gf_index = gf_frame_index; gf_index < gf_group->size; ++gf_index) {
-    const int height = gf_group_pyramid_level(gf_group, gf_index);
-    q_index_list[gf_index] = av1_q_mode_get_q_index(
-        base_q_index, gf_group->update_type[gf_index], height, arf_q);
+  for (int i = gf_frame_index; i < gf_group->size; ++i) {
+    q_index_list[i] = av1_get_q_index_from_qstep_ratio(
+        base_q_index, qstep_ratio_list[i], bit_depth);
   }
 }
 #endif  // !CONFIG_REALTIME_ONLY
diff --git a/av1/encoder/ratectrl.h b/av1/encoder/ratectrl.h
index 4ae0da0..07c98a4 100644
--- a/av1/encoder/ratectrl.h
+++ b/av1/encoder/ratectrl.h
@@ -663,8 +663,7 @@
  *
  * \param[in]       gf_frame_index    Index of the current frame
  * \param[in]       base_q_index      Base q index
- * \param[in]       arf_qstep_ratio   The quantize step ratio between arf q
- *                                    index and base q index
+ * \param[in]       qstep_ratio_list  Stores the qstep_ratio for each frame
  * \param[in]       bit_depth         Bit depth
  * \param[in]       gf_group          Pointer to the GOP
  * \param[out]      q_index_list      An array to store output gop q indices.
@@ -672,7 +671,7 @@
  *                                    greater than gf_group.size()
  */
 void av1_q_mode_compute_gop_q_indices(int gf_frame_index, int base_q_index,
-                                      double arf_qstep_ratio,
+                                      const double *qstep_ratio_list,
                                       aom_bit_depth_t bit_depth,
                                       const struct GF_GROUP *gf_group,
                                       int *q_index_list);
diff --git a/av1/encoder/tpl_model.c b/av1/encoder/tpl_model.c
index 70817d6..33a0dcc 100644
--- a/av1/encoder/tpl_model.c
+++ b/av1/encoder/tpl_model.c
@@ -1960,25 +1960,26 @@
 int av1_q_mode_estimate_base_q(const GF_GROUP *gf_group,
                                const TplTxfmStats *txfm_stats_list,
                                const int *stats_valid_list, double bit_budget,
-                               int gf_frame_index, double arf_qstep_ratio,
-                               aom_bit_depth_t bit_depth, double scale_factor,
+                               int gf_frame_index, aom_bit_depth_t bit_depth,
+                               double scale_factor,
+                               const double *qstep_ratio_list,
                                int *q_index_list,
                                double *estimated_bitrate_byframe) {
   int q_max = 255;  // Maximum q value.
   int q_min = 0;    // Minimum q value.
   int q = (q_max + q_min) / 2;
 
-  av1_q_mode_compute_gop_q_indices(gf_frame_index, q_max, arf_qstep_ratio,
+  av1_q_mode_compute_gop_q_indices(gf_frame_index, q_max, qstep_ratio_list,
                                    bit_depth, gf_group, q_index_list);
   double q_max_estimate = av1_estimate_gop_bitrate(
       q_index_list, gf_group->size, txfm_stats_list, stats_valid_list, NULL);
-  av1_q_mode_compute_gop_q_indices(gf_frame_index, q_min, arf_qstep_ratio,
+  av1_q_mode_compute_gop_q_indices(gf_frame_index, q_min, qstep_ratio_list,
                                    bit_depth, gf_group, q_index_list);
   double q_min_estimate = av1_estimate_gop_bitrate(
       q_index_list, gf_group->size, txfm_stats_list, stats_valid_list, NULL);
 
   while (true) {
-    av1_q_mode_compute_gop_q_indices(gf_frame_index, q, arf_qstep_ratio,
+    av1_q_mode_compute_gop_q_indices(gf_frame_index, q, qstep_ratio_list,
                                      bit_depth, gf_group, q_index_list);
 
     double estimate = av1_estimate_gop_bitrate(
@@ -2009,7 +2010,7 @@
   }
 
   // Update q_index_list and vbr_rc_info.
-  av1_q_mode_compute_gop_q_indices(gf_frame_index, q, arf_qstep_ratio,
+  av1_q_mode_compute_gop_q_indices(gf_frame_index, q, qstep_ratio_list,
                                    bit_depth, gf_group, q_index_list);
   av1_estimate_gop_bitrate(q_index_list, gf_group->size, txfm_stats_list,
                            stats_valid_list, estimated_bitrate_byframe);
@@ -2017,6 +2018,10 @@
 }
 
 double av1_tpl_get_qstep_ratio(const TplParams *tpl_data, int gf_frame_index) {
+  if (!av1_tpl_stats_ready(tpl_data, gf_frame_index)) {
+    return 1;
+  }
+
   const TplDepFrame *tpl_frame = &tpl_data->tpl_frame[gf_frame_index];
   const TplDepStats *tpl_stats = tpl_frame->tpl_stats_ptr;
 
@@ -2069,9 +2074,11 @@
   if (gf_frame_index == 0) {
     vbr_rc_info->q_index_list_ready = 1;
     double gop_bit_budget = vbr_rc_info->gop_bit_budget;
-    // Use the gop_bit_budget to determine q_index_list.
-    const double arf_qstep_ratio =
-        av1_tpl_get_qstep_ratio(tpl_data, gf_frame_index);
+
+    for (int i = gf_frame_index; i < gf_group->size; i++) {
+      vbr_rc_info->qstep_ratio_list[i] = av1_tpl_get_qstep_ratio(tpl_data, i);
+    }
+
     // We update the q indices in vbr_rc_info in vbr_rc_info->q_index_list
     // rather than gf_group->q_val to avoid conflicts with the existing code.
     int stats_valid_list[MAX_LENGTH_TPL_FRAME_STATS] = { 0 };
@@ -2089,7 +2096,7 @@
 
     av1_q_mode_estimate_base_q(
         gf_group, tpl_data->txfm_stats_list, stats_valid_list, gop_bit_budget,
-        gf_frame_index, arf_qstep_ratio, bit_depth, scale_factor,
+        gf_frame_index, bit_depth, scale_factor, vbr_rc_info->qstep_ratio_list,
         vbr_rc_info->q_index_list, vbr_rc_info->estimated_bitrate_byframe);
   }
 }
diff --git a/av1/encoder/tpl_model.h b/av1/encoder/tpl_model.h
index 718d447..aa61253 100644
--- a/av1/encoder/tpl_model.h
+++ b/av1/encoder/tpl_model.h
@@ -254,6 +254,9 @@
   int actual_bitrate_byframe[MAX_LENGTH_TPL_FRAME_STATS];
   int actual_mv_bitrate_byframe[MAX_LENGTH_TPL_FRAME_STATS];
   int actual_coeff_bitrate_byframe[MAX_LENGTH_TPL_FRAME_STATS];
+
+  // Array to store qstep_ratio for each frame in a GOP
+  double qstep_ratio_list[MAX_LENGTH_TPL_FRAME_STATS];
 } VBR_RATECTRL_INFO;
 
 static INLINE void vbr_rc_reset_gop_data(VBR_RATECTRL_INFO *vbr_rc_info) {
@@ -550,10 +553,10 @@
  *                                    exists
  * \param[in]       bit_budget        The specified bit budget to achieve
  * \param[in]       gf_frame_index    current frame in the GOP
- * \param[in]       arf_qstep_ratio   ARF q step ratio
  * \param[in]       bit_depth         bit depth
  * \param[in]       scale_factor      Scale factor to improve budget estimation
- * \param[out]       q_index_list     array of q_index, one per frame
+ * \param[in]       qstep_ratio_list  Stores the qstep_ratio for each frame
+ * \param[out]      q_index_list      array of q_index, one per frame
  * \param[out]      estimated_bitrate_byframe  bits usage per frame in the GOP
  *
  * \return Returns the optimal base q index to use.
@@ -561,8 +564,9 @@
 int av1_q_mode_estimate_base_q(const struct GF_GROUP *gf_group,
                                const TplTxfmStats *txfm_stats_list,
                                const int *stats_valid_list, double bit_budget,
-                               int gf_frame_index, double arf_qstep_ratio,
-                               aom_bit_depth_t bit_depth, double scale_factor,
+                               int gf_frame_index, aom_bit_depth_t bit_depth,
+                               double scale_factor,
+                               const double *qstep_ratio_list,
                                int *q_index_list,
                                double *estimated_bitrate_byframe);
 
diff --git a/test/ratectrl_test.cc b/test/ratectrl_test.cc
index 67adf27..4b462e3 100644
--- a/test/ratectrl_test.cc
+++ b/test/ratectrl_test.cc
@@ -41,7 +41,7 @@
 // TODO(angiebird): Move this test to tpl_mode_test.cc
 TEST(RatectrlTest, QModeComputeGOPQIndicesTest) {
   const int base_q_index = 80;
-  const double arf_qstep_ratio = 0.5;
+  double qstep_ratio_list[5] = { 0.5, 1, 1, 1, 0.5 };
   const aom_bit_depth_t bit_depth = AOM_BITS_8;
 
   const int gf_frame_index = 0;
@@ -58,10 +58,10 @@
   }
 
   const int arf_q = av1_get_q_index_from_qstep_ratio(
-      base_q_index, arf_qstep_ratio, bit_depth);
+      base_q_index, qstep_ratio_list[0], bit_depth);
 
   av1_q_mode_compute_gop_q_indices(gf_frame_index, base_q_index,
-                                   arf_qstep_ratio, bit_depth, &gf_group,
+                                   qstep_ratio_list, bit_depth, &gf_group,
                                    gf_group.q_val);
 
   for (int i = 0; i < gf_group.size; i++) {
diff --git a/test/tpl_model_test.cc b/test/tpl_model_test.cc
index 3094c6c..da5a821 100644
--- a/test/tpl_model_test.cc
+++ b/test/tpl_model_test.cc
@@ -235,7 +235,7 @@
  * Helper method to brute-force search for the closest q_index
  * that achieves the specified bit budget.
  */
-int find_gop_q_iterative(double bit_budget, double arf_qstep_ratio,
+int find_gop_q_iterative(double bit_budget, const double *qstep_ratio_list,
                          GF_GROUP gf_group, const int *stats_valid_list,
                          TplTxfmStats *stats_list, int gf_frame_index,
                          aom_bit_depth_t bit_depth) {
@@ -243,7 +243,7 @@
   // Use the result to test against the binary search result.
 
   // Initial estimate when q = 255
-  av1_q_mode_compute_gop_q_indices(gf_frame_index, 255, arf_qstep_ratio,
+  av1_q_mode_compute_gop_q_indices(gf_frame_index, 255, qstep_ratio_list,
                                    bit_depth, &gf_group, gf_group.q_val);
   double curr_estimate = av1_estimate_gop_bitrate(
       gf_group.q_val, gf_group.size, stats_list, stats_valid_list, NULL);
@@ -252,7 +252,7 @@
 
   // Start at q = 254 because we already have an estimate for q = 255.
   for (int q = 254; q >= 0; q--) {
-    av1_q_mode_compute_gop_q_indices(gf_frame_index, q, arf_qstep_ratio,
+    av1_q_mode_compute_gop_q_indices(gf_frame_index, q, qstep_ratio_list,
                                      bit_depth, &gf_group, gf_group.q_val);
     curr_estimate = av1_estimate_gop_bitrate(
         gf_group.q_val, gf_group.size, stats_list, stats_valid_list, NULL);
@@ -274,10 +274,14 @@
                                           5, 6, 6, 1, 5, 1, 5, 6, 1, 5, 1, 4 };
   int stats_valid_list[25] = { 0 };
   const int gf_frame_index = 0;
-  const double arf_qstep_ratio = 2;
   const aom_bit_depth_t bit_depth = AOM_BITS_8;
   const double scale_factor = 1.0;
 
+  double qstep_ratio_list[25];
+  for (int i = 0; i < 25; i++) {
+    qstep_ratio_list[i] = 1;
+  }
+
   for (int i = 0; i < gf_group.size; i++) {
     stats_valid_list[i] = 1;
     gf_group.update_type[i] = gf_group_update_types[i];
@@ -297,9 +301,9 @@
     // Binary search method to find the optimal q.
     const int result = av1_q_mode_estimate_base_q(
         &gf_group, stats_list, stats_valid_list, bit_budget, gf_frame_index,
-        arf_qstep_ratio, bit_depth, scale_factor, q_index_list, NULL);
+        bit_depth, scale_factor, qstep_ratio_list, q_index_list, NULL);
     const int test_result = find_gop_q_iterative(
-        bit_budget, arf_qstep_ratio, gf_group, stats_valid_list, stats_list,
+        bit_budget, qstep_ratio_list, gf_group, stats_valid_list, stats_list,
         gf_frame_index, bit_depth);
 
     if (bit_budget == 0) {