Add RATECTRL_LOG

Since we need to record the rate control decision for
vbr / q / bitrate_accuracy mode, separate the log
object from VBR_RATECTRL_INFO

Add several functions to interact with RATECTRL_LOG

Other additional features:
1) Make bitrate_accuracy mode works with q mode.
bitrate_accuracy with q mode will be used for training rate model parameters

2) Fix update_type bug.
Properly set up update_type_list in vbr_rc_info

BUG=aomedia:3045

Change-Id: I498bdedb42e14c566d95bfcae6a7adb80f09f120
diff --git a/av1/encoder/encode_strategy.c b/av1/encoder/encode_strategy.c
index d60aa9e..caf7aa5 100644
--- a/av1/encoder/encode_strategy.c
+++ b/av1/encoder/encode_strategy.c
@@ -1214,13 +1214,24 @@
       aom_free(tpl_info);
     }
     av1_close_second_pass_log(cpi);
-    vbr_rc_info->base_q_index = av1_vbr_rc_info_estimate_base_q(
-        vbr_rc_info->total_bit_budget, cm->seq_params->bit_depth,
-        vbr_rc_info->scale_factors, vbr_rc_info->total_frame_count,
-        vbr_rc_info->update_type_list, vbr_rc_info->qstep_ratio_list,
-        vbr_rc_info->txfm_stats_list, vbr_rc_info->q_index_list,
-        vbr_rc_info->estimated_bitrate_byframe);
+    if (cpi->oxcf.rc_cfg.mode == AOM_Q) {
+      vbr_rc_info->base_q_index = cpi->oxcf.rc_cfg.cq_level;
+      av1_vbr_rc_compute_q_indices(
+          vbr_rc_info->base_q_index, vbr_rc_info->total_frame_count,
+          vbr_rc_info->qstep_ratio_list, cm->seq_params->bit_depth,
+          vbr_rc_info->q_index_list);
+    } else {
+      vbr_rc_info->base_q_index = av1_vbr_rc_info_estimate_base_q(
+          vbr_rc_info->total_bit_budget, cm->seq_params->bit_depth,
+          vbr_rc_info->scale_factors, vbr_rc_info->total_frame_count,
+          vbr_rc_info->update_type_list, vbr_rc_info->qstep_ratio_list,
+          vbr_rc_info->txfm_stats_list, vbr_rc_info->q_index_list, NULL);
+    }
     vbr_rc_info->ready = 1;
+#if CONFIG_RATECTRL_LOG
+    rc_log_record_chunk_info(&cpi->rc_log, vbr_rc_info->base_q_index,
+                             vbr_rc_info->total_frame_count);
+#endif  // CONFIG_RATECTRL_LOG
   }
 #endif  // CONFIG_BITRATE_ACCURACY && CONFIG_THREE_PASS
 
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index 039dc80..b7c87dc 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -1541,6 +1541,11 @@
 
 void av1_remove_compressor(AV1_COMP *cpi) {
   if (!cpi) return;
+#if CONFIG_RATECTRL_LOG
+  if (cpi->oxcf.pass == 3) {
+    rc_log_show(&cpi->rc_log);
+  }
+#endif  // CONFIG_RATECTRL_LOG
 
   AV1_COMMON *cm = &cpi->common;
   if (cm->current_frame.frame_number > 0) {
@@ -2694,23 +2699,18 @@
 #endif  // CONFIG_THREE_PASS
 #endif  // CONFIG_BITRATE_ACCURACY
 
-#if CONFIG_RATECTRL_LOG && CONFIG_THREE_PASS
+#if CONFIG_RATECTRL_LOG && CONFIG_THREE_PASS && CONFIG_BITRATE_ACCURACY
     // TODO(angiebird): Move this into a function.
     if (oxcf->pass == AOM_RC_THIRD_PASS) {
-#if CONFIG_BITRATE_ACCURACY
       int frame_coding_idx =
           av1_vbr_rc_frame_coding_idx(&cpi->vbr_rc_info, cpi->gf_frame_index);
       double qstep_ratio = cpi->vbr_rc_info.qstep_ratio_list[frame_coding_idx];
-#else
-      double qstep_ratio =
-          av1_tpl_get_qstep_ratio(&cpi->ppi->tpl_data, cpi->gf_frame_index);
-#endif  // CONFIG_BITRATE_ACCURACY
-      printf("gf_frame_index %d update_type %d q %d qstep_ratio %f\n",
-             cpi->gf_frame_index,
-             cpi->ppi->gf_group.update_type[cpi->gf_frame_index], q,
-             qstep_ratio);
+      FRAME_UPDATE_TYPE update_type =
+          cpi->vbr_rc_info.update_type_list[frame_coding_idx];
+      rc_log_frame_encode_param(&cpi->rc_log, frame_coding_idx, qstep_ratio, q,
+                                update_type);
     }
-#endif  // CONFIG_RATECTRL_LOG && CONFIG_THREE_PASS
+#endif  // CONFIG_RATECTRL_LOG && CONFIG_THREE_PASS && CONFIG_BITRATE_ACCURACY
 
     av1_set_quantizer(cm, q_cfg->qm_minlevel, q_cfg->qm_maxlevel, q,
                       q_cfg->enable_chroma_deltaq, q_cfg->enable_hdr_deltaq);
@@ -2817,11 +2817,6 @@
         return AOM_CODEC_ERROR;
       }
 
-#if CONFIG_BITRATE_ACCURACY
-      cpi->vbr_rc_info.actual_coeff_bitrate_byframe[cpi->gf_frame_index] =
-          rc->coefficient_size;
-#endif
-
       // bits used for this frame
       rc->projected_frame_size = (int)(*size) << 3;
 #if CONFIG_RD_COMMAND
@@ -2835,18 +2830,14 @@
       }
 #endif  // CONFIG_RD_COMMAND
 
-#if CONFIG_BITRATE_ACCURACY
-      cpi->vbr_rc_info.actual_bitrate_byframe[cpi->gf_frame_index] =
-          rc->projected_frame_size;
-      cpi->vbr_rc_info.actual_mv_bitrate_byframe[cpi->gf_frame_index] =
-          rc->projected_frame_size -
-          cpi->vbr_rc_info.actual_coeff_bitrate_byframe[cpi->gf_frame_index];
-#if 0
-      vbr_rc_info_log(&cpi->vbr_rc_info, cpi->gf_frame_index,
-                      cpi->ppi->gf_group.size, cpi->ppi->gf_group.update_type);
-#endif
-
-#endif
+#if CONFIG_RATECTRL_LOG && CONFIG_THREE_PASS && CONFIG_BITRATE_ACCURACY
+      if (oxcf->pass == AOM_RC_THIRD_PASS) {
+        int frame_coding_idx =
+            av1_vbr_rc_frame_coding_idx(&cpi->vbr_rc_info, cpi->gf_frame_index);
+        rc_log_frame_entropy(&cpi->rc_log, frame_coding_idx,
+                             rc->projected_frame_size, rc->coefficient_size);
+      }
+#endif  // CONFIG_RATECTRL_LOG && CONFIG_THREE_PASS && CONFIG_BITRATE_ACCURACY
     }
 
 #if CONFIG_TUNE_VMAF
@@ -3384,6 +3375,16 @@
   }
 
   if (encode_show_existing_frame(cm)) {
+#if CONFIG_RATECTRL_LOG && CONFIG_THREE_PASS && CONFIG_BITRATE_ACCURACY
+    // TODO(angiebird): Move this into a function.
+    if (oxcf->pass == AOM_RC_THIRD_PASS) {
+      int frame_coding_idx =
+          av1_vbr_rc_frame_coding_idx(&cpi->vbr_rc_info, cpi->gf_frame_index);
+      rc_log_frame_encode_param(
+          &cpi->rc_log, frame_coding_idx, 1, 255,
+          cpi->ppi->gf_group.update_type[cpi->gf_frame_index]);
+    }
+#endif
     av1_finalize_encoded_frame(cpi);
     // Build the bitstream
     int largest_tile_id = 0;  // Output from bitstream: unused here
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h
index 3d9d479..57782a9 100644
--- a/av1/encoder/encoder.h
+++ b/av1/encoder/encoder.h
@@ -3312,6 +3312,13 @@
   VBR_RATECTRL_INFO vbr_rc_info;
 #endif
 
+#if CONFIG_RATECTRL_LOG
+  /*!
+   * Structure stores information of rate control decisions.
+   */
+  RATECTRL_LOG rc_log;
+#endif  // CONFIG_RATECTRL_LOG
+
   /*!
    * Frame level twopass status and control data
    */
diff --git a/av1/encoder/pass2_strategy.c b/av1/encoder/pass2_strategy.c
index 8bbd1d7..9e086ee 100644
--- a/av1/encoder/pass2_strategy.c
+++ b/av1/encoder/pass2_strategy.c
@@ -3919,6 +3919,10 @@
                   (int)round(stats->count));
 #endif
 
+#if CONFIG_RATECTRL_LOG
+  rc_log_init(&cpi->rc_log);
+#endif
+
   // This variable monitors how far behind the second ref update is lagging.
   twopass->sr_update_lag = 1;
 
diff --git a/av1/encoder/thirdpass.c b/av1/encoder/thirdpass.c
index 68944d7..d526554 100644
--- a/av1/encoder/thirdpass.c
+++ b/av1/encoder/thirdpass.c
@@ -732,6 +732,7 @@
     for (int i = 0; i < tpl_info->gf_length; ++i) {
       tpl_info->txfm_stats_list[i] = tpl_data->txfm_stats_list[i];
       tpl_info->qstep_ratio_ls[i] = av1_tpl_get_qstep_ratio(tpl_data, i);
+      tpl_info->update_type_list[i] = gf_group->update_type[i];
     }
   }
 }
@@ -750,6 +751,9 @@
     fwrite_and_check(&tpl_info->qstep_ratio_ls,
                      sizeof(tpl_info->qstep_ratio_ls[0]), tpl_info->gf_length,
                      log_stream, error);
+    fwrite_and_check(&tpl_info->update_type_list,
+                     sizeof(tpl_info->update_type_list[0]), tpl_info->gf_length,
+                     log_stream, error);
   }
 }
 
@@ -768,6 +772,9 @@
     fread_and_check(&tpl_info->qstep_ratio_ls,
                     sizeof(tpl_info->qstep_ratio_ls[0]), tpl_info->gf_length,
                     log_stream, error);
+    fread_and_check(&tpl_info->update_type_list,
+                    sizeof(tpl_info->update_type_list[0]), tpl_info->gf_length,
+                    log_stream, error);
   }
 }
 #endif  // CONFIG_BITRATE_ACCURACY
diff --git a/av1/encoder/thirdpass.h b/av1/encoder/thirdpass.h
index 4117532..8080c06 100644
--- a/av1/encoder/thirdpass.h
+++ b/av1/encoder/thirdpass.h
@@ -41,6 +41,7 @@
   int tpl_ready;
   TplTxfmStats txfm_stats_list[MAX_LENGTH_TPL_FRAME_STATS];
   double qstep_ratio_ls[MAX_LENGTH_TPL_FRAME_STATS];
+  FRAME_UPDATE_TYPE update_type_list[MAX_LENGTH_TPL_FRAME_STATS];
 } TPL_INFO;
 #endif  // CONFIG_BITRATE_ACCURACY
 
diff --git a/av1/encoder/tpl_model.c b/av1/encoder/tpl_model.c
index 764de09..79d313b 100644
--- a/av1/encoder/tpl_model.c
+++ b/av1/encoder/tpl_model.c
@@ -1502,12 +1502,16 @@
     gf_group->update_type[gf_index] = LF_UPDATE;
 
 #if CONFIG_BITRATE_ACCURACY && CONFIG_THREE_PASS
-    // TODO(angiebird): Find a more adaptive method to decide pframe_qindex
-    // override the pframe_qindex in the second pass when bitrate accuracy is
-    // on. We found that setting this pframe_qindex make the tpl stats more
-    // stable.
     if (cpi->oxcf.pass == AOM_RC_SECOND_PASS) {
-      *pframe_qindex = 128;
+      if (cpi->oxcf.rc_cfg.mode == AOM_Q) {
+        *pframe_qindex = cpi->oxcf.rc_cfg.cq_level;
+      } else if (cpi->oxcf.rc_cfg.mode == AOM_VBR) {
+        // TODO(angiebird): Find a more adaptive method to decide pframe_qindex
+        // override the pframe_qindex in the second pass when bitrate accuracy
+        // is on. We found that setting this pframe_qindex make the tpl stats
+        // more stable.
+        *pframe_qindex = 128;
+      }
     }
 #endif  // CONFIG_BITRATE_ACCURACY && CONFIG_THREE_PASS
     gf_group->q_val[gf_index] = *pframe_qindex;
@@ -1698,6 +1702,14 @@
     }
     av1_tpl_txfm_stats_update_abs_coeff_mean(&cpi->td.tpl_txfm_stats);
     av1_tpl_store_txfm_stats(tpl_data, &cpi->td.tpl_txfm_stats, frame_idx);
+#if CONFIG_RATECTRL_LOG && CONFIG_THREE_PASS && CONFIG_BITRATE_ACCURACY
+    if (cpi->oxcf.pass == AOM_RC_THIRD_PASS) {
+      int frame_coding_idx =
+          av1_vbr_rc_frame_coding_idx(&cpi->vbr_rc_info, frame_idx);
+      rc_log_frame_stats(&cpi->rc_log, frame_coding_idx,
+                         &cpi->td.tpl_txfm_stats);
+    }
+#endif  // CONFIG_RATECTRL_LOG
 
     aom_extend_frame_borders(tpl_data->tpl_frame[frame_idx].rec_picture,
                              av1_num_planes(cm));
@@ -2059,22 +2071,12 @@
         tpl_info->txfm_stats_list[i];
     vbr_rc_info->qstep_ratio_list[gop_start_idx + i] =
         tpl_info->qstep_ratio_ls[i];
-    // TODO(angiebird): This is a temporary solution. We currently apply same
-    // scale factor for each update_type, therefore setting everything to
-    // ARF_UPDATE is temporarily okay. Properly set the update_type later.
-    vbr_rc_info->update_type_list[gop_start_idx + i] = ARF_UPDATE;
+    vbr_rc_info->update_type_list[gop_start_idx + i] =
+        tpl_info->update_type_list[i];
   }
   vbr_rc_info->total_frame_count += tpl_info->gf_length;
   vbr_rc_info->gop_count++;
 }
-
-#if CONFIG_RATECTRL_LOG
-void av1_rc_frame_log(int gf_frame_index, FRAME_UPDATE_TYPE update_type, int q,
-                      double qstep_ratio) {
-  printf("gf_frame_index %d update_type %d q %d qstep_ratio %f\n",
-         gf_frame_index, update_type, q, qstep_ratio);
-}
-#endif  //  CONFIG_RATECTRL_LOG
 #endif  // CONFIG_THREE_PASS
 
 void av1_vbr_rc_set_gop_bit_budget(VBR_RATECTRL_INFO *vbr_rc_info,
@@ -2085,10 +2087,10 @@
                                 vbr_rc_info->show_frame_count;
 }
 
-static INLINE void compute_q_indices(int base_q_index, int frame_count,
-                                     const double *qstep_ratio_list,
-                                     aom_bit_depth_t bit_depth,
-                                     int *q_index_list) {
+void av1_vbr_rc_compute_q_indices(int base_q_index, int frame_count,
+                                  const double *qstep_ratio_list,
+                                  aom_bit_depth_t bit_depth,
+                                  int *q_index_list) {
   for (int i = 0; i < frame_count; ++i) {
     q_index_list[i] = av1_get_q_index_from_qstep_ratio(
         base_q_index, qstep_ratio_list[i], bit_depth);
@@ -2101,26 +2103,25 @@
     const FRAME_UPDATE_TYPE *update_type_list, const double *qstep_ratio_list,
     const TplTxfmStats *stats_list, int *q_index_list,
     double *estimated_bitrate_byframe) {
-  compute_q_indices(base_q_index, frame_count, qstep_ratio_list, bit_depth,
-                    q_index_list);
+  av1_vbr_rc_compute_q_indices(base_q_index, frame_count, qstep_ratio_list,
+                               bit_depth, q_index_list);
+  double estimated_gop_bitrate = 0;
   for (int frame_index = 0; frame_index < frame_count; frame_index++) {
     const TplTxfmStats *frame_stats = &stats_list[frame_index];
+    double frame_bitrate = 0;
     if (frame_stats->ready) {
       int q_index = q_index_list[frame_index];
 
-      double frame_bitrate = av1_laplace_estimate_frame_rate(
+      frame_bitrate = av1_laplace_estimate_frame_rate(
           q_index, frame_stats->txfm_block_count, frame_stats->abs_coeff_mean,
           frame_stats->coeff_num);
-      estimated_bitrate_byframe[frame_index] = frame_bitrate;
-    } else {
-      estimated_bitrate_byframe[frame_index] = 0;
     }
-  }
-  double estimated_gop_bitrate = 0;
-  for (int i = 0; i < frame_count; ++i) {
-    FRAME_UPDATE_TYPE update_type = update_type_list[i];
+    FRAME_UPDATE_TYPE update_type = update_type_list[frame_index];
     estimated_gop_bitrate +=
-        estimated_bitrate_byframe[i] * update_type_scale_factors[update_type];
+        frame_bitrate * update_type_scale_factors[update_type];
+    if (estimated_bitrate_byframe != NULL) {
+      estimated_bitrate_byframe[frame_index] = frame_bitrate;
+    }
   }
   return estimated_gop_bitrate;
 }
@@ -2180,7 +2181,17 @@
     vbr_rc_info->qstep_ratio_list[i] = av1_tpl_get_qstep_ratio(tpl_data, i);
   }
 
-  double mv_bits = av1_tpl_compute_mv_bits(tpl_data, gf_group, vbr_rc_info);
+  double mv_bits = 0;
+  for (int i = 0; i < gf_group->size; i++) {
+    double frame_mv_bits = 0;
+    if (av1_tpl_stats_ready(tpl_data, i)) {
+      TplDepFrame *tpl_frame = &tpl_data->tpl_frame[i];
+      frame_mv_bits = av1_tpl_compute_frame_mv_entropy(
+          tpl_frame, tpl_data->tpl_stats_block_mis_log2);
+      FRAME_UPDATE_TYPE updae_type = gf_group->update_type[i];
+      mv_bits += frame_mv_bits * vbr_rc_info->mv_scale_factors[updae_type];
+    }
+  }
 
   mv_bits = AOMMIN(mv_bits, 0.6 * gop_bit_budget);
   gop_bit_budget -= mv_bits;
@@ -2188,34 +2199,9 @@
   vbr_rc_info->base_q_index = av1_vbr_rc_info_estimate_base_q(
       gop_bit_budget, bit_depth, vbr_rc_info->scale_factors, gf_group->size,
       gf_group->update_type, vbr_rc_info->qstep_ratio_list,
-      tpl_data->txfm_stats_list, vbr_rc_info->q_index_list,
-      vbr_rc_info->estimated_bitrate_byframe);
+      tpl_data->txfm_stats_list, vbr_rc_info->q_index_list, NULL);
 }
 
-/* For a GOP, calculate the bits used by motion vectors. */
-double av1_tpl_compute_mv_bits(const TplParams *tpl_data,
-                               const GF_GROUP *gf_group,
-                               VBR_RATECTRL_INFO *vbr_rc_info) {
-  double total_mv_bits = 0;
-
-  // Loop through each frame.
-  for (int i = 0; i < gf_group->size; i++) {
-    if (av1_tpl_stats_ready(tpl_data, i)) {
-      TplDepFrame *tpl_frame = &tpl_data->tpl_frame[i];
-      double frame_mv_bits = av1_tpl_compute_frame_mv_entropy(
-          tpl_frame, tpl_data->tpl_stats_block_mis_log2);
-      vbr_rc_info->estimated_mv_bitrate_byframe[i] = frame_mv_bits;
-      FRAME_UPDATE_TYPE updae_type = gf_group->update_type[i];
-      total_mv_bits +=
-          frame_mv_bits * vbr_rc_info->mv_scale_factors[updae_type];
-    } else {
-      vbr_rc_info->estimated_mv_bitrate_byframe[i] = 0;
-    }
-  }
-
-  // Scale the final result by the scale factor.
-  return total_mv_bits;
-}
 #endif  // CONFIG_BITRATE_ACCURACY
 
 // Use upper and left neighbor block as the reference MVs.
diff --git a/av1/encoder/tpl_model.h b/av1/encoder/tpl_model.h
index a974f98..b77a19f 100644
--- a/av1/encoder/tpl_model.h
+++ b/av1/encoder/tpl_model.h
@@ -225,13 +225,11 @@
 
 } TplParams;
 
-#if CONFIG_BITRATE_ACCURACY
-
-#if CONFIG_THREE_PASS
+#if CONFIG_BITRATE_ACCURACY || CONFIG_RATECTRL_LOG
 #define VBR_RC_INFO_MAX_FRAMES 500
-#else  // CONFIG_THREE_PASS
-#define VBR_RC_INFO_MAX_FRAMES MAX_LENGTH_TPL_FRAME_STATS
-#endif  //  CONFIG_THREE_PASS
+#endif  //  CONFIG_BITRATE_ACCURACY || CONFIG_RATECTRL_LOG
+
+#if CONFIG_BITRATE_ACCURACY
 
 /*!
  * \brief This structure stores information needed for bitrate accuracy
@@ -254,12 +252,6 @@
   int q_index_list_ready;
   int q_index_list[VBR_RC_INFO_MAX_FRAMES];  // q indices for the current
                                              // GOP
-  // Arrays to store frame level bitrate accuracy data.
-  double estimated_bitrate_byframe[VBR_RC_INFO_MAX_FRAMES];
-  double estimated_mv_bitrate_byframe[VBR_RC_INFO_MAX_FRAMES];
-  int actual_bitrate_byframe[VBR_RC_INFO_MAX_FRAMES];
-  int actual_mv_bitrate_byframe[VBR_RC_INFO_MAX_FRAMES];
-  int actual_coeff_bitrate_byframe[VBR_RC_INFO_MAX_FRAMES];
 
   // Array to store qstep_ratio for each frame in a GOP
   double qstep_ratio_list[VBR_RC_INFO_MAX_FRAMES];
@@ -278,11 +270,6 @@
 static INLINE void vbr_rc_reset_gop_data(VBR_RATECTRL_INFO *vbr_rc_info) {
   vbr_rc_info->q_index_list_ready = 0;
   av1_zero(vbr_rc_info->q_index_list);
-  av1_zero(vbr_rc_info->estimated_bitrate_byframe);
-  av1_zero(vbr_rc_info->estimated_mv_bitrate_byframe);
-  av1_zero(vbr_rc_info->actual_bitrate_byframe);
-  av1_zero(vbr_rc_info->actual_mv_bitrate_byframe);
-  av1_zero(vbr_rc_info->actual_coeff_bitrate_byframe);
 }
 
 void av1_vbr_rc_init(VBR_RATECTRL_INFO *vbr_rc_info, double total_bit_budget,
@@ -293,28 +280,13 @@
 
 void av1_vbr_rc_append_tpl_info(VBR_RATECTRL_INFO *vbr_rc_info,
                                 const struct TPL_INFO *tpl_info);
+
 void av1_vbr_rc_set_gop_bit_budget(VBR_RATECTRL_INFO *vbr_rc_info,
                                    int gop_showframe_count);
 
-static INLINE void vbr_rc_info_log(const VBR_RATECTRL_INFO *vbr_rc_info,
-                                   int gf_frame_index, int gf_group_size,
-                                   FRAME_UPDATE_TYPE *update_type) {
-  // Add +2 here because this is the last frame this method is called at.
-  if (gf_frame_index + 2 >= gf_group_size) {
-    printf(
-        "\ni, \test_bitrate, \test_mv_bitrate, \tact_bitrate, "
-        "\tact_mv_bitrate, \tact_coeff_bitrate, \tq, \tupdate_type\n");
-    for (int i = 0; i < gf_group_size; i++) {
-      printf("%d, \t%f, \t%f, \t%d, \t%d, \t%d, \t%d, \t%d\n", i,
-             vbr_rc_info->estimated_bitrate_byframe[i],
-             vbr_rc_info->estimated_mv_bitrate_byframe[i],
-             vbr_rc_info->actual_bitrate_byframe[i],
-             vbr_rc_info->actual_mv_bitrate_byframe[i],
-             vbr_rc_info->actual_coeff_bitrate_byframe[i],
-             vbr_rc_info->q_index_list[i], update_type[i]);
-    }
-  }
-}
+void av1_vbr_rc_compute_q_indices(int base_q_index, int frame_count,
+                                  const double *qstep_ratio_list,
+                                  aom_bit_depth_t bit_depth, int *q_index_list);
 
 /*!\brief Update q_index_list in vbr_rc_info based on tpl stats
  *
@@ -331,18 +303,21 @@
 /*
  *!\brief Compute the number of bits needed to encode a GOP
  *
- * \param[in]    base_q_index      base layer q_index
- * \param[in]    bit_depth         bit depth
+ * \param[in]    base_q_index              base layer q_index
+ * \param[in]    bit_depth                 bit depth
  * \param[in]    update_type_scale_factors array of scale factors for each
- *                                 update_type
- * \param[in]    frame_count       size of update_type_list, qstep_ratio_list
- *                                 stats_list, q_index_list and
- *                                 estimated_bitrate_byframe
- * \param[in]    update_type_list  array of update_type, one per frame
- * \param[in]    qstep_ratio_list  array of qstep_ratio, one per frame
- * \param[in]    stats_list        array of transform stats, one per frame
- * \param[out]   q_index_list      array of q_index, one per frame
- * \param[out]   estimated_bitrate_byframe Array to keep track of frame bitrate
+ *                                         update_type
+ * \param[in]    frame_count               size of update_type_list,
+ *                                         qstep_ratio_list stats_list,
+ *                                         q_index_list and
+ *                                         estimated_bitrate_byframe
+ * \param[in]    update_type_list          array of update_type, one per frame
+ * \param[in]    qstep_ratio_list          array of qstep_ratio, one per frame
+ * \param[in]    stats_list                array of transform stats, one per
+ *                                         frame
+ * \param[out]   q_index_list              array of q_index, one per frame
+ * \param[out]   estimated_bitrate_byframe array to keep track of frame
+ *                                         bitrate
  *
  * \return The estimated GOP bitrate.
  *
@@ -370,7 +345,8 @@
  * \param[in]    qstep_ratio_list  array of qstep_ratio, one per frame
  * \param[in]    stats_list        array of transform stats, one per frame
  * \param[out]   q_index_list      array of q_index, one per frame
- * \param[out]   estimated_bitrate_byframe Array to keep track of frame bitrate
+ * \param[out]   estimated_bitrate_byframe Array to keep track of frame
+ * bitrate
  *
  * \return Returns the optimal base q index to use.
  */
@@ -381,17 +357,6 @@
     const TplTxfmStats *stats_list, int *q_index_list,
     double *estimated_bitrate_byframe);
 
-/*!\brief For a GOP, calculate the bits used by motion vectors.
- *
- * \param[in]       tpl_data          TPL struct
- * \param[in]       gf_group          GOP struct
- * \param[in]       vbr_rc_info       Rate control info struct
- *
- * \return Bits used by the motion vectors for the GOP.
- */
-double av1_tpl_compute_mv_bits(const TplParams *tpl_data,
-                               const GF_GROUP *gf_group,
-                               VBR_RATECTRL_INFO *vbr_rc_info);
 #endif  // CONFIG_BITRATE_ACCURACY
 
 #if CONFIG_RD_COMMAND
@@ -520,8 +485,8 @@
  *!\brief Accumulate TplTxfmStats
  *
  * \param[in]  sub_stats          a structure for storing sub transform stats
- * \param[out] accumulated_stats  a structure for storing accumulated transform
- *stats
+ * \param[out] accumulated_stats  a structure for storing accumulated
+ *transform stats
  *
  */
 void av1_accumulate_tpl_txfm_stats(const TplTxfmStats *sub_stats,
@@ -552,13 +517,13 @@
  *
  *\ingroup tpl_modelling
  *
- * This function is equivalent to -log2(laplace_prob()), where laplace_prob() is
- * defined in tpl_model_test.cc
+ * This function is equivalent to -log2(laplace_prob()), where laplace_prob()
+ *is defined in tpl_model_test.cc
  *
  * \param[in]    q_step          quantizer step size without any scaling
- * \param[in]    b               mean absolute deviation of Laplace distribution
- * \param[in]    zero_bin_ratio  zero bin's size is zero_bin_ratio * q_step
- * \param[in]    qcoeff          quantized coefficient
+ * \param[in]    b               mean absolute deviation of Laplace
+ *distribution \param[in]    zero_bin_ratio  zero bin's size is zero_bin_ratio
+ ** q_step \param[in]    qcoeff          quantized coefficient
  *
  * \return estimated coefficient entropy
  *
@@ -626,8 +591,8 @@
 double av1_tpl_get_frame_importance(const TplParams *tpl_data,
                                     int gf_frame_index);
 
-/*!\brief Compute the ratio between arf q step and the leaf q step based on TPL
- * stats
+/*!\brief Compute the ratio between arf q step and the leaf q step based on
+ * TPL stats
  *
  * \param[in]       tpl_data          TPL struct
  * \param[in]       gf_frame_index    current frame index in the GOP
@@ -641,16 +606,16 @@
 /*!\brief Find a q index whose step size is near qstep_ratio * leaf_qstep
  *
  * \param[in]       leaf_qindex       q index of leaf frame
- * \param[in]       qstep_ratio       step ratio between target q index and leaf
- *                                    q index
- * \param[in]       bit_depth         bit depth
+ * \param[in]       qstep_ratio       step ratio between target q index and
+ * leaf q index \param[in]       bit_depth         bit depth
  *
  * \return q_index
  */
 int av1_get_q_index_from_qstep_ratio(int leaf_qindex, double qstep_ratio,
                                      aom_bit_depth_t bit_depth);
 
-/*!\brief Improve the motion vector estimation by taking neighbors into account.
+/*!\brief Improve the motion vector estimation by taking neighbors into
+ * account.
  *
  * Use the upper and left neighbor block as the reference MVs.
  * Compute the minimum difference between current MV and reference MV.
@@ -660,7 +625,8 @@
  * \param[in]       col               Current column
  * \param[in]       step              Step parameter for av1_tpl_ptr_pos
  * \param[in]       tpl_stride        Stride parameter for av1_tpl_ptr_pos
- * \param[in]       right_shift       Right shift parameter for av1_tpl_ptr_pos
+ * \param[in]       right_shift       Right shift parameter for
+ * av1_tpl_ptr_pos
  */
 int_mv av1_compute_mv_difference(const TplDepFrame *tpl_frame, int row, int col,
                                  int step, int tpl_stride, int right_shift);
@@ -675,6 +641,83 @@
 double av1_tpl_compute_frame_mv_entropy(const TplDepFrame *tpl_frame,
                                         uint8_t right_shift);
 
+#if CONFIG_RATECTRL_LOG
+typedef struct {
+  int coding_frame_count;
+  int base_q_index;
+
+  // Encode decision
+  int q_index_list[VBR_RC_INFO_MAX_FRAMES];
+  double qstep_ratio_list[VBR_RC_INFO_MAX_FRAMES];
+  FRAME_UPDATE_TYPE update_type_list[VBR_RC_INFO_MAX_FRAMES];
+
+  // Frame stats
+  TplTxfmStats txfm_stats_list[VBR_RC_INFO_MAX_FRAMES];
+
+  // Estimated encode results
+  double est_coeff_rate_list[VBR_RC_INFO_MAX_FRAMES];
+
+  // Actual encode results
+  double act_rate_list[VBR_RC_INFO_MAX_FRAMES];
+  double act_coeff_rate_list[VBR_RC_INFO_MAX_FRAMES];
+} RATECTRL_LOG;
+
+static INLINE void rc_log_init(RATECTRL_LOG *rc_log) { av1_zero(*rc_log); }
+
+static INLINE void rc_log_frame_stats(RATECTRL_LOG *rc_log, int coding_index,
+                                      const TplTxfmStats *txfm_stats) {
+  rc_log->txfm_stats_list[coding_index] = *txfm_stats;
+}
+
+static INLINE void rc_log_frame_encode_param(RATECTRL_LOG *rc_log,
+                                             int coding_index,
+                                             double qstep_ratio, int q_index,
+                                             FRAME_UPDATE_TYPE update_type) {
+  rc_log->qstep_ratio_list[coding_index] = qstep_ratio;
+  rc_log->q_index_list[coding_index] = q_index;
+  rc_log->update_type_list[coding_index] = update_type;
+  const TplTxfmStats *txfm_stats = &rc_log->txfm_stats_list[coding_index];
+  rc_log->est_coeff_rate_list[coding_index] = 0;
+  if (txfm_stats->ready) {
+    rc_log->est_coeff_rate_list[coding_index] = av1_laplace_estimate_frame_rate(
+        q_index, txfm_stats->txfm_block_count, txfm_stats->abs_coeff_mean,
+        txfm_stats->coeff_num);
+  }
+}
+
+static INLINE void rc_log_frame_entropy(RATECTRL_LOG *rc_log, int coding_index,
+                                        double act_rate,
+                                        double act_coeff_rate) {
+  rc_log->act_rate_list[coding_index] = act_rate;
+  rc_log->act_coeff_rate_list[coding_index] = act_coeff_rate;
+}
+
+static INLINE void rc_log_record_chunk_info(RATECTRL_LOG *rc_log,
+                                            int base_q_index,
+                                            int coding_frame_count) {
+  rc_log->base_q_index = base_q_index;
+  rc_log->coding_frame_count = coding_frame_count;
+}
+
+static INLINE void rc_log_show(const RATECTRL_LOG *rc_log) {
+  printf("= chunk 1\n");
+  printf("coding_frame_count %d base_q_index %d\n", rc_log->coding_frame_count,
+         rc_log->base_q_index);
+  printf("= frame %d\n", rc_log->coding_frame_count);
+  for (int coding_idx = 0; coding_idx < rc_log->coding_frame_count;
+       coding_idx++) {
+    printf(
+        "coding_idx %d update_type %d q %d qstep_ratio %f est_coeff_rate %f "
+        "act_coeff_rate %f act_rate %f\n",
+        coding_idx, rc_log->update_type_list[coding_idx],
+        rc_log->q_index_list[coding_idx], rc_log->qstep_ratio_list[coding_idx],
+        rc_log->est_coeff_rate_list[coding_idx],
+        rc_log->act_coeff_rate_list[coding_idx],
+        rc_log->act_rate_list[coding_idx]);
+  }
+}
+#endif  // CONFIG_RATECTRL_LOG
+
 /*!\endcond */
 #ifdef __cplusplus
 }  // extern "C"
diff --git a/test/tpl_model_test.cc b/test/tpl_model_test.cc
index a875ed6..ed2f593 100644
--- a/test/tpl_model_test.cc
+++ b/test/tpl_model_test.cc
@@ -436,31 +436,32 @@
 
   std::vector<TplTxfmStats> stats_list(gf_group.size);
   init_toy_tpl_txfm_stats(&stats_list);
+
+  std::vector<double> est_bitrate_list(gf_group.size);
+  init_toy_tpl_txfm_stats(&stats_list);
   const aom_bit_depth_t bit_depth = AOM_BITS_8;
 
   const int q = 125;
 
   // Case1: all scale factors are 0
   double scale_factors[FRAME_UPDATE_TYPES] = { 0 };
-  memcpy(vbr_rc_info.scale_factors, scale_factors, sizeof(scale_factors));
   double estimate = av1_vbr_rc_info_estimate_gop_bitrate(
-      q, bit_depth, vbr_rc_info.scale_factors, gf_group.size,
-      gf_group.update_type, vbr_rc_info.qstep_ratio_list, stats_list.data(),
-      vbr_rc_info.q_index_list, vbr_rc_info.estimated_bitrate_byframe);
+      q, bit_depth, scale_factors, gf_group.size, gf_group.update_type,
+      vbr_rc_info.qstep_ratio_list, stats_list.data(), vbr_rc_info.q_index_list,
+      est_bitrate_list.data());
   EXPECT_NEAR(estimate, 0, epsilon);
 
   // Case2: all scale factors are 1
   for (int i = 0; i < FRAME_UPDATE_TYPES; i++) {
     scale_factors[i] = 1;
   }
-  memcpy(vbr_rc_info.scale_factors, scale_factors, sizeof(scale_factors));
   estimate = av1_vbr_rc_info_estimate_gop_bitrate(
-      q, bit_depth, vbr_rc_info.scale_factors, gf_group.size,
-      gf_group.update_type, vbr_rc_info.qstep_ratio_list, stats_list.data(),
-      vbr_rc_info.q_index_list, vbr_rc_info.estimated_bitrate_byframe);
+      q, bit_depth, scale_factors, gf_group.size, gf_group.update_type,
+      vbr_rc_info.qstep_ratio_list, stats_list.data(), vbr_rc_info.q_index_list,
+      est_bitrate_list.data());
   double ref_estimate = 0;
   for (int i = 0; i < gf_group.size; i++) {
-    ref_estimate += vbr_rc_info.estimated_bitrate_byframe[i];
+    ref_estimate += est_bitrate_list[i];
   }
   EXPECT_NEAR(estimate, ref_estimate, epsilon);
 
@@ -472,15 +473,14 @@
       scale_factors[i] = 1;
     }
   }
-  memcpy(vbr_rc_info.scale_factors, scale_factors, sizeof(scale_factors));
   estimate = av1_vbr_rc_info_estimate_gop_bitrate(
-      q, bit_depth, vbr_rc_info.scale_factors, gf_group.size,
-      gf_group.update_type, vbr_rc_info.qstep_ratio_list, stats_list.data(),
-      vbr_rc_info.q_index_list, vbr_rc_info.estimated_bitrate_byframe);
+      q, bit_depth, scale_factors, gf_group.size, gf_group.update_type,
+      vbr_rc_info.qstep_ratio_list, stats_list.data(), vbr_rc_info.q_index_list,
+      est_bitrate_list.data());
   ref_estimate = 0;
   for (int i = 0; i < gf_group.size; i++) {
     if (gf_group.update_type[i] != KF_UPDATE) {
-      ref_estimate += vbr_rc_info.estimated_bitrate_byframe[i];
+      ref_estimate += est_bitrate_list[i];
     }
   }
   EXPECT_NEAR(estimate, ref_estimate, epsilon);
@@ -493,9 +493,6 @@
   VBR_RATECTRL_INFO vbr_rc_info;
   init_toy_vbr_rc_info(&vbr_rc_info, gf_group.size);
 
-  VBR_RATECTRL_INFO ref_vbr_rc_info;
-  init_toy_vbr_rc_info(&ref_vbr_rc_info, gf_group.size);
-
   std::vector<TplTxfmStats> stats_list(gf_group.size);
   init_toy_tpl_txfm_stats(&stats_list);
   const aom_bit_depth_t bit_depth = AOM_BITS_8;
@@ -509,11 +506,11 @@
     const int base_q = av1_vbr_rc_info_estimate_base_q(
         bit_budget, bit_depth, vbr_rc_info.scale_factors, gf_group.size,
         gf_group.update_type, vbr_rc_info.qstep_ratio_list, stats_list.data(),
-        vbr_rc_info.q_index_list, vbr_rc_info.estimated_bitrate_byframe);
+        vbr_rc_info.q_index_list, NULL);
     const int ref_base_q = find_gop_q_iterative(
         bit_budget, bit_depth, vbr_rc_info.scale_factors, gf_group.size,
         gf_group.update_type, vbr_rc_info.qstep_ratio_list, stats_list.data(),
-        vbr_rc_info.q_index_list, vbr_rc_info.estimated_bitrate_byframe);
+        vbr_rc_info.q_index_list, NULL);
     if (bit_budget == 0) {
       EXPECT_EQ(base_q, 255);
     } else if (bit_budget == DBL_MAX) {