FPMT SIMULATION: Delay avg_frame_qindex update

This patch introduces temp_avg_frame_qindex variable
which retains the avg_frame_qindex value previous to
the parallel frames.  The temp_avg_frame_qindex updates
are enabled based on do_frame_update_flag. The changes
are done only in AOM_Q path and is used for quality
simulation purpose.

Change-Id: I7ec08db5b6b723a0ff9d1c2200f8a2293c5cae31
diff --git a/av1/encoder/aq_cyclicrefresh.c b/av1/encoder/aq_cyclicrefresh.c
index f78d90c..40b8c25 100644
--- a/av1/encoder/aq_cyclicrefresh.c
+++ b/av1/encoder/aq_cyclicrefresh.c
@@ -398,11 +398,20 @@
   int qp_thresh = AOMMIN(20, rc->best_quality << 1);
   int qp_max_thresh = 118 * MAXQ >> 7;
   cr->apply_cyclic_refresh = 1;
+  int avg_frame_qindex_inter_frame;
+#if CONFIG_FRAME_PARALLEL_ENCODE
+  avg_frame_qindex_inter_frame =
+      (cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] > 0)
+          ? cpi->ppi->temp_avg_frame_qindex[INTER_FRAME]
+          : rc->avg_frame_qindex[INTER_FRAME];
+#else
+  avg_frame_qindex_inter_frame = rc->avg_frame_qindex[INTER_FRAME];
+#endif  // CONFIG_FRAME_PARALLEL_ENCODE
   if (frame_is_intra_only(cm) || is_lossless_requested(&cpi->oxcf.rc_cfg) ||
       cpi->svc.temporal_layer_id > 0 ||
-      rc->avg_frame_qindex[INTER_FRAME] < qp_thresh ||
+      avg_frame_qindex_inter_frame < qp_thresh ||
       (rc->frames_since_key > 20 &&
-       rc->avg_frame_qindex[INTER_FRAME] > qp_max_thresh) ||
+       avg_frame_qindex_inter_frame > qp_max_thresh) ||
       (rc->avg_frame_low_motion < 45 && rc->frames_since_key > 40)) {
     cr->apply_cyclic_refresh = 0;
     return;
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h
index f3aac06..89c1ac1 100644
--- a/av1/encoder/encoder.h
+++ b/av1/encoder/encoder.h
@@ -2179,6 +2179,12 @@
    * Temporary variable simulating the delayed frame_probability update.
    */
   FrameProbInfo temp_frame_probs;
+
+  /*!
+   * Temporary variable used in simulating the delayed update of
+   * avg_frame_qindex.
+   */
+  int temp_avg_frame_qindex[FRAME_TYPES];
 #endif  // CONFIG_FRAME_PARALLEL_ENCODE
   /*!
    * Encode stage top level structure
diff --git a/av1/encoder/ratectrl.c b/av1/encoder/ratectrl.c
index f34d460..7a5c529 100644
--- a/av1/encoder/ratectrl.c
+++ b/av1/encoder/ratectrl.c
@@ -1175,10 +1175,25 @@
     // Use the lower of active_worst_quality and recent
     // average Q as basis for GF/ARF best Q limit unless last frame was
     // a key frame.
+    int avg_frame_qindex_inter_frame;
+    int avg_frame_qindex_key_frame;
+#if CONFIG_FRAME_PARALLEL_ENCODE
+    avg_frame_qindex_inter_frame =
+        (cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] > 0)
+            ? cpi->ppi->temp_avg_frame_qindex[INTER_FRAME]
+            : cpi->rc.avg_frame_qindex[INTER_FRAME];
+    avg_frame_qindex_key_frame =
+        (cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] > 0)
+            ? cpi->ppi->temp_avg_frame_qindex[KEY_FRAME]
+            : cpi->rc.avg_frame_qindex[KEY_FRAME];
+#else
+    avg_frame_qindex_inter_frame = rc->avg_frame_qindex[INTER_FRAME];
+    avg_frame_qindex_key_frame = rc->avg_frame_qindex[KEY_FRAME];
+#endif
     q = (rc->frames_since_key > 1 &&
-         rc->avg_frame_qindex[INTER_FRAME] < active_worst_quality)
-            ? rc->avg_frame_qindex[INTER_FRAME]
-            : rc->avg_frame_qindex[KEY_FRAME];
+         avg_frame_qindex_inter_frame < active_worst_quality)
+            ? avg_frame_qindex_inter_frame
+            : avg_frame_qindex_key_frame;
     // For constrained quality dont allow Q less than the cq level
     if (rc_mode == AOM_CQ) {
       if (q < cq_level) q = cq_level;
@@ -1545,6 +1560,7 @@
   const GF_GROUP *gf_group = &cpi->ppi->gf_group;
   const enum aom_rc_mode rc_mode = oxcf->rc_cfg.mode;
   int *inter_minq;
+  int avg_frame_qindex_inter_frame;
   ASSIGN_MINQ_TABLE(bit_depth, inter_minq);
   int active_best_quality = 0;
   const int is_intrl_arf_boost =
@@ -1575,12 +1591,22 @@
 
   // Determine active_best_quality for frames that are not leaf or overlay.
   int q = active_worst_quality;
+#if CONFIG_FRAME_PARALLEL_ENCODE
+  // For quality simulation purpose - for parallel frames use previous
+  // avg_frame_qindex
+  avg_frame_qindex_inter_frame =
+      (cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] > 0)
+          ? cpi->ppi->temp_avg_frame_qindex[INTER_FRAME]
+          : rc->avg_frame_qindex[INTER_FRAME];
+#else
+  avg_frame_qindex_inter_frame = rc->avg_frame_qindex[INTER_FRAME];
+#endif  // CONFIG_FRAME_PARALLEL_ENCODE
   // Use the lower of active_worst_quality and recent
   // average Q as basis for GF/ARF best Q limit unless last frame was
   // a key frame.
   if (rc->frames_since_key > 1 &&
-      rc->avg_frame_qindex[INTER_FRAME] < active_worst_quality) {
-    q = rc->avg_frame_qindex[INTER_FRAME];
+      avg_frame_qindex_inter_frame < active_worst_quality) {
+    q = avg_frame_qindex_inter_frame;
   }
   if (rc_mode == AOM_CQ && q < cq_level) q = cq_level;
   active_best_quality = get_gf_active_quality(p_rc, q, bit_depth);
@@ -1878,7 +1904,23 @@
       rc->ni_av_qi = rc->ni_tot_qi / rc->ni_frames;
     }
   }
-
+#if CONFIG_FRAME_PARALLEL_ENCODE
+  /* TODO(FPMT): The current update is happening in cpi->rc.avg_frame_qindex,
+   * this need to be taken care appropriately in final FPMT implementation
+   * to carry these values to subsequent frames. The avg_frame_qindex update
+   * is accumulated across frames, so the values from all individual parallel
+   * frames need to be taken into account after all the parallel frames are
+   * encoded.
+   *
+   * The variable temp_avg_frame_qindex introduced only for quality simulation
+   * purpose, it retains the value previous to the parallel encode frames. The
+   * variable is updated based on the update flag.
+   */
+  if (cpi->do_frame_data_update && !rc->is_src_frame_alt_ref) {
+    for (int index = 0; index < FRAME_TYPES; index++)
+      cpi->ppi->temp_avg_frame_qindex[index] = rc->avg_frame_qindex[index];
+  }
+#endif  // CONFIG_FRAME_PARALLEL_ENCODE
   // Keep record of last boosted (KF/GF/ARF) Q value.
   // If the current frame is coded at a lower Q then we also update it.
   // If all mbs in this group are skipped only update if the Q value is
diff --git a/av1/encoder/temporal_filter.c b/av1/encoder/temporal_filter.c
index d58c960..6833ac8 100644
--- a/av1/encoder/temporal_filter.c
+++ b/av1/encoder/temporal_filter.c
@@ -754,8 +754,17 @@
 int av1_get_q(const AV1_COMP *cpi) {
   const GF_GROUP *gf_group = &cpi->ppi->gf_group;
   const FRAME_TYPE frame_type = gf_group->frame_type[cpi->gf_frame_index];
-  const int q = (int)av1_convert_qindex_to_q(
-      cpi->rc.avg_frame_qindex[frame_type], cpi->common.seq_params->bit_depth);
+  int avg_frame_qindex;
+#if CONFIG_FRAME_PARALLEL_ENCODE
+  avg_frame_qindex =
+      (cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] > 0)
+          ? cpi->ppi->temp_avg_frame_qindex[frame_type]
+          : cpi->rc.avg_frame_qindex[frame_type];
+#else
+  avg_frame_qindex = cpi->rc.avg_frame_qindex[frame_type];
+#endif  // CONFIG_FRAME_PARALLEL_ENCODE
+  const int q = (int)av1_convert_qindex_to_q(avg_frame_qindex,
+                                             cpi->common.seq_params->bit_depth);
   return q;
 }