Fixed av1_estimate_gop_bitrate

Only compute coefficient rate when it's tpl stats is valid

Change-Id: If278f138ffdd8d69fd9699660d4d3c32bd6c5422
diff --git a/av1/encoder/tpl_model.c b/av1/encoder/tpl_model.c
index a21e0fa..d2c1b7d 100644
--- a/av1/encoder/tpl_model.c
+++ b/av1/encoder/tpl_model.c
@@ -1869,25 +1869,28 @@
 
 double av1_estimate_gop_bitrate(const int *q_index_list, const int frame_count,
                                 const TplTxfmStats *stats_list,
+                                const int *stats_valid_list,
                                 double *bitrate_byframe_list) {
   double gop_bitrate = 0;
   for (int frame_index = 0; frame_index < frame_count; frame_index++) {
-    int q_index = q_index_list[frame_index];
-    TplTxfmStats frame_stats = stats_list[frame_index];
+    if (stats_valid_list[frame_index]) {
+      int q_index = q_index_list[frame_index];
+      TplTxfmStats frame_stats = stats_list[frame_index];
 
-    /* Convert to mean absolute deviation */
-    double abs_coeff_mean[256] = { 0 };
-    for (int i = 0; i < 256; i++) {
-      abs_coeff_mean[i] =
-          frame_stats.abs_coeff_sum[i] / frame_stats.txfm_block_count;
-    }
+      /* Convert to mean absolute deviation */
+      double abs_coeff_mean[256] = { 0 };
+      for (int i = 0; i < 256; i++) {
+        abs_coeff_mean[i] =
+            frame_stats.abs_coeff_sum[i] / frame_stats.txfm_block_count;
+      }
 
-    double frame_bitrate = av1_laplace_estimate_frame_rate(
-        q_index, frame_stats.txfm_block_count, abs_coeff_mean, 256);
-    gop_bitrate += frame_bitrate;
+      double frame_bitrate = av1_laplace_estimate_frame_rate(
+          q_index, frame_stats.txfm_block_count, abs_coeff_mean, 256);
+      gop_bitrate += frame_bitrate;
 
-    if (bitrate_byframe_list != NULL) {
-      bitrate_byframe_list[frame_index] = frame_bitrate;
+      if (bitrate_byframe_list != NULL) {
+        bitrate_byframe_list[frame_index] = frame_bitrate;
+      }
     }
   }
   return gop_bitrate;
@@ -1946,13 +1949,20 @@
 }
 #endif  // CONFIG_RD_COMMAND
 
+void get_tpl_stats_valid_list(const TplParams *tpl_data, int gop_size,
+                              int *stats_valid_list) {
+  for (int i = 0; i < gop_size; ++i) {
+    stats_valid_list[i] = av1_tpl_stats_ready(tpl_data, i);
+  }
+}
+
 /*
  * Estimate the optimal base q index for a GOP.
  */
 int av1_q_mode_estimate_base_q(const GF_GROUP *gf_group,
                                const TplTxfmStats *txfm_stats_list,
-                               double bit_budget, int gf_frame_index,
-                               double arf_qstep_ratio,
+                               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 *q_index_list,
                                double *estimated_bitrate_byframe) {
@@ -1962,19 +1972,19 @@
 
   av1_q_mode_compute_gop_q_indices(gf_frame_index, q_max, arf_qstep_ratio,
                                    bit_depth, gf_group, q_index_list);
-  double q_max_estimate = av1_estimate_gop_bitrate(q_index_list, gf_group->size,
-                                                   txfm_stats_list, NULL);
+  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,
                                    bit_depth, gf_group, q_index_list);
-  double q_min_estimate = av1_estimate_gop_bitrate(q_index_list, gf_group->size,
-                                                   txfm_stats_list, NULL);
+  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,
                                      bit_depth, gf_group, q_index_list);
 
-    double estimate = av1_estimate_gop_bitrate(q_index_list, gf_group->size,
-                                               txfm_stats_list, NULL);
+    double estimate = av1_estimate_gop_bitrate(
+        q_index_list, gf_group->size, txfm_stats_list, stats_valid_list, NULL);
 
     estimate *= scale_factor;
 
@@ -2004,7 +2014,7 @@
   av1_q_mode_compute_gop_q_indices(gf_frame_index, q, arf_qstep_ratio,
                                    bit_depth, gf_group, q_index_list);
   av1_estimate_gop_bitrate(q_index_list, gf_group->size, txfm_stats_list,
-                           estimated_bitrate_byframe);
+                           stats_valid_list, estimated_bitrate_byframe);
   return q;
 }
 
@@ -2069,9 +2079,11 @@
         av1_tpl_get_qstep_ratio(tpl_data, gf_frame_index);
     // 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 };
+    get_tpl_stats_valid_list(tpl_data, gf_group->size, stats_valid_list);
     av1_q_mode_estimate_base_q(
-        gf_group, tpl_data->txfm_stats_list, gop_bit_budget, gf_frame_index,
-        arf_qstep_ratio, bit_depth, vbr_rc_info->scale_factor,
+        gf_group, tpl_data->txfm_stats_list, stats_valid_list, gop_bit_budget,
+        gf_frame_index, arf_qstep_ratio, bit_depth, vbr_rc_info->scale_factor,
         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 c24d77e..922a6e5 100644
--- a/av1/encoder/tpl_model.h
+++ b/av1/encoder/tpl_model.h
@@ -405,16 +405,19 @@
 /*
  *!\brief Compute the number of bits needed to encode a GOP
  *
- * \param[in]    q_index_list    array of q_index, one per frame
- * \param[in]    frame_count     number of frames in the GOP
- * \param[in]    stats           array of transform stats, one per frame
- * \param[in]    bitrate_byframe_list    Array to keep track of frame bitrate
+ * \param[in]    q_index_list      array of q_index, one per frame
+ * \param[in]    frame_count       number of frames in the GOP
+ * \param[in]    stats             array of transform stats, one per frame
+ * \param[in]    stats_valid_list  List indicates whether transform stats
+ *                                 exists
+ * \param[out]   bitrate_byframe_list    Array to keep track of frame bitrate
  *
  * \return The estimated GOP bitrate.
  *
  */
 double av1_estimate_gop_bitrate(const int *q_index_list, const int frame_count,
                                 const TplTxfmStats *stats,
+                                const int *stats_valid_list,
                                 double *bitrate_byframe_list);
 
 /*
@@ -510,21 +513,23 @@
  * a binary search to find q to achieve the specified bit rate.
  *
  * \param[in]       gf_group          GOP structure
- * \param[in]       stats             Transform stats struct
+ * \param[in]       txfm_stats_list   Transform stats struct
+ * \param[in]       stats_valid_list  List indicates whether transform stats
+ *                                    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[in]       q_index_list      array of q_index, one per frame
- * \param[in]       estimated_bitrate_byframe    bit depth
+ * \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.
  */
 int av1_q_mode_estimate_base_q(const struct GF_GROUP *gf_group,
                                const TplTxfmStats *txfm_stats_list,
-                               double bit_budget, int gf_frame_index,
-                               double arf_qstep_ratio,
+                               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 *q_index_list,
                                double *estimated_bitrate_byframe);
diff --git a/test/tpl_model_test.cc b/test/tpl_model_test.cc
index d426ef1..3094c6c 100644
--- a/test/tpl_model_test.cc
+++ b/test/tpl_model_test.cc
@@ -156,10 +156,12 @@
   const int txfm_size = 256;  // 16x16
   const int frame_count = 16;
   int q_index_list[16];
+  int valid_list[16];
   TplTxfmStats stats_list[16];
 
   for (int i = 0; i < frame_count; i++) {
     q_index_list[i] = 1;
+    valid_list[i] = 1;
     stats_list[i].txfm_block_count = 8;
 
     for (int j = 0; j < txfm_size; j++) {
@@ -167,8 +169,8 @@
     }
   }
 
-  double result =
-      av1_estimate_gop_bitrate(q_index_list, frame_count, stats_list, NULL);
+  double result = av1_estimate_gop_bitrate(q_index_list, frame_count,
+                                           stats_list, valid_list, NULL);
   EXPECT_NEAR(result, 0, 0.1);
 }
 
@@ -234,16 +236,17 @@
  * that achieves the specified bit budget.
  */
 int find_gop_q_iterative(double bit_budget, double arf_qstep_ratio,
-                         GF_GROUP gf_group, TplTxfmStats *stats_list,
-                         int gf_frame_index, aom_bit_depth_t bit_depth) {
+                         GF_GROUP gf_group, const int *stats_valid_list,
+                         TplTxfmStats *stats_list, int gf_frame_index,
+                         aom_bit_depth_t bit_depth) {
   // Brute force iterative method to find the optimal q.
   // 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,
                                    bit_depth, &gf_group, gf_group.q_val);
-  double curr_estimate =
-      av1_estimate_gop_bitrate(gf_group.q_val, gf_group.size, stats_list, NULL);
+  double curr_estimate = av1_estimate_gop_bitrate(
+      gf_group.q_val, gf_group.size, stats_list, stats_valid_list, NULL);
   double best_estimate_budget_distance = fabs(curr_estimate - bit_budget);
   int best_q = 255;
 
@@ -251,8 +254,8 @@
   for (int q = 254; q >= 0; q--) {
     av1_q_mode_compute_gop_q_indices(gf_frame_index, q, arf_qstep_ratio,
                                      bit_depth, &gf_group, gf_group.q_val);
-    curr_estimate = av1_estimate_gop_bitrate(gf_group.q_val, gf_group.size,
-                                             stats_list, NULL);
+    curr_estimate = av1_estimate_gop_bitrate(
+        gf_group.q_val, gf_group.size, stats_list, stats_valid_list, NULL);
     double curr_estimate_budget_distance = fabs(curr_estimate - bit_budget);
     if (curr_estimate_budget_distance <= best_estimate_budget_distance) {
       best_estimate_budget_distance = curr_estimate_budget_distance;
@@ -269,12 +272,14 @@
   int q_index_list[25];
   const int gf_group_update_types[25] = { 0, 3, 6, 6, 6, 1, 5, 1, 5, 6, 1, 5, 1,
                                           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;
 
   for (int i = 0; i < gf_group.size; i++) {
+    stats_valid_list[i] = 1;
     gf_group.update_type[i] = gf_group_update_types[i];
     stats_list[i].txfm_block_count = 8;
 
@@ -291,11 +296,11 @@
   for (double bit_budget : bit_budgets) {
     // Binary search method to find the optimal q.
     const int result = av1_q_mode_estimate_base_q(
-        &gf_group, stats_list, bit_budget, gf_frame_index, arf_qstep_ratio,
-        bit_depth, scale_factor, q_index_list, NULL);
-    const int test_result =
-        find_gop_q_iterative(bit_budget, arf_qstep_ratio, gf_group, stats_list,
-                             gf_frame_index, bit_depth);
+        &gf_group, stats_list, stats_valid_list, bit_budget, gf_frame_index,
+        arf_qstep_ratio, bit_depth, scale_factor, q_index_list, NULL);
+    const int test_result = find_gop_q_iterative(
+        bit_budget, arf_qstep_ratio, gf_group, stats_valid_list, stats_list,
+        gf_frame_index, bit_depth);
 
     if (bit_budget == 0) {
       EXPECT_EQ(result, 255);