FPMT SIMULATION: Set target size and qindex for parallel frames

Introduce temporary members related to error propogation and rate
control buffer level. Frame target bits are corrected based on the
error corresponding to the frames previous to parallel frames. The
updates of these temporary variables are enabled based on
do_frame_update_flag.

Change-Id: Iafde8eb12cf09c29e967faf6d9ea74b9b8947a60
diff --git a/av1/encoder/encoder_utils.c b/av1/encoder/encoder_utils.c
index 733daef..911a889 100644
--- a/av1/encoder/encoder_utils.c
+++ b/av1/encoder/encoder_utils.c
@@ -864,7 +864,16 @@
     int *projected_size_pass, PSNR_STATS *psnr) {
   AV1_COMMON *const cm = &cpi->common;
   FeatureFlags *const features = &cm->features;
-  projected_size_pass[pass] = cpi->rc.projected_frame_size;
+  int projected_frame_size;
+#if CONFIG_FRAME_PARALLEL_ENCODE
+  projected_frame_size =
+      (cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] > 0)
+          ? cpi->ppi->p_rc.temp_projected_frame_size
+          : cpi->rc.projected_frame_size;
+#else
+  projected_frame_size = cpi->rc.projected_frame_size;
+#endif
+  projected_size_pass[pass] = projected_frame_size;
 #if CONFIG_AV1_HIGHBITDEPTH
   const uint32_t in_bit_depth = cpi->oxcf.input_cfg.input_bit_depth;
   const uint32_t bit_depth = cpi->td.mb.e_mbd.bd;
diff --git a/av1/encoder/pass2_strategy.c b/av1/encoder/pass2_strategy.c
index 5550d17..3510f95 100644
--- a/av1/encoder/pass2_strategy.c
+++ b/av1/encoder/pass2_strategy.c
@@ -191,7 +191,7 @@
 static void twopass_update_bpm_factor(AV1_COMP *cpi, int rate_err_tol) {
   TWO_PASS *twopass = &cpi->ppi->twopass;
   const RATE_CONTROL *const rc = &cpi->rc;
-  int err_estimate = rc->rate_error_estimate;
+  int err_estimate;
 
   // Based on recent history adjust expectations of bits per macroblock.
   double damp_fac = AOMMAX(5.0, rate_err_tol / 10.0);
@@ -199,16 +199,56 @@
   const double adj_limit = AOMMAX(0.20, (double)(100 - rate_err_tol) / 200.0);
   const double min_fac = 1.0 - adj_limit;
   const double max_fac = 1.0 + adj_limit;
+  int64_t local_total_actual_bits, local_vbr_bits_off_target, local_bits_left;
+  double local_rolling_arf_group_actual_bits,
+      local_rolling_arf_group_target_bits;
+#if CONFIG_FRAME_PARALLEL_ENCODE
+  local_total_actual_bits =
+      (cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] > 0)
+          ? cpi->ppi->p_rc.temp_total_actual_bits
+          : rc->total_actual_bits;
+  local_vbr_bits_off_target =
+      (cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] > 0)
+          ? cpi->ppi->p_rc.temp_vbr_bits_off_target
+          : rc->vbr_bits_off_target;
+  local_bits_left =
+      (cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] > 0)
+          ? cpi->ppi->p_rc.temp_bits_left
+          : cpi->ppi->twopass.bits_left;
+  local_rolling_arf_group_target_bits =
+      (double)((cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] >
+                0)
+                   ? cpi->ppi->p_rc.temp_rolling_arf_group_target_bits
+                   : twopass->rolling_arf_group_target_bits);
+  local_rolling_arf_group_actual_bits =
+      (double)((cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] >
+                0)
+                   ? cpi->ppi->p_rc.temp_rolling_arf_group_actual_bits
+                   : twopass->rolling_arf_group_actual_bits);
+  err_estimate =
+      (cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] > 0)
+          ? cpi->ppi->p_rc.temp_rate_error_estimate
+          : rc->rate_error_estimate;
+#else
+  local_total_actual_bits = rc->total_actual_bits;
+  local_vbr_bits_off_target = rc->vbr_bits_off_target;
+  local_bits_left = cpi->ppi->twopass.bits_left;
+  local_rolling_arf_group_target_bits =
+      (double)twopass->rolling_arf_group_target_bits;
+  local_rolling_arf_group_actual_bits =
+      (double)twopass->rolling_arf_group_actual_bits;
+  err_estimate = rc->rate_error_estimate;
+#endif
 
-  if (rc->vbr_bits_off_target && rc->total_actual_bits > 0) {
+  if (local_vbr_bits_off_target && local_total_actual_bits > 0) {
     if (cpi->ppi->lap_enabled) {
       rate_err_factor =
-          (double)twopass->rolling_arf_group_actual_bits /
-          DOUBLE_DIVIDE_CHECK((double)twopass->rolling_arf_group_target_bits);
+          local_rolling_arf_group_actual_bits /
+          DOUBLE_DIVIDE_CHECK(local_rolling_arf_group_target_bits);
     } else {
       rate_err_factor =
-          1.0 - ((double)(rc->vbr_bits_off_target) /
-                 AOMMAX(rc->total_actual_bits, cpi->ppi->twopass.bits_left));
+          1.0 - ((double)(local_vbr_bits_off_target) /
+                 AOMMAX(local_total_actual_bits, local_bits_left));
     }
 
     rate_err_factor = AOMMAX(min_fac, AOMMIN(max_fac, rate_err_factor));
@@ -4025,6 +4065,26 @@
   } else {
     rc->rate_error_estimate = 0;
   }
+#if CONFIG_FRAME_PARALLEL_ENCODE
+  /* TODO(FPMT): The current  update is happening in cpi->rc members,
+   * this need to be taken care appropriately in final FPMT implementation
+   * to carry these values to subsequent frames.
+   * The variables temp_vbr_bits_off_target, temp_bits_left,
+   * temp_rolling_arf_group_target_bits, temp_rolling_arf_group_actual_bits
+   * temp_rate_error_estimate are introduced for quality simulation purpose,
+   * it retains the value previous to the parallel encode frames. The
+   * variables are updated based on the update flag.
+   */
+  if (cpi->do_frame_data_update) {
+    cpi->ppi->p_rc.temp_vbr_bits_off_target = rc->vbr_bits_off_target;
+    cpi->ppi->p_rc.temp_bits_left = twopass->bits_left;
+    cpi->ppi->p_rc.temp_rolling_arf_group_target_bits =
+        twopass->rolling_arf_group_target_bits;
+    cpi->ppi->p_rc.temp_rolling_arf_group_actual_bits =
+        twopass->rolling_arf_group_actual_bits;
+    cpi->ppi->p_rc.temp_rate_error_estimate = rc->rate_error_estimate;
+  }
+#endif
 
   // Update the active best quality pyramid.
   if (!rc->is_src_frame_alt_ref) {
@@ -4075,58 +4135,80 @@
 
   // If the rate control is drifting consider adjustment to min or maxq.
   if ((rc_cfg->mode != AOM_Q) && !cpi->rc.is_src_frame_alt_ref) {
-    const int maxq_adj_limit = rc->worst_quality - rc->active_worst_quality;
-    const int minq_adj_limit =
+    int maxq_adj_limit;
+    int minq_adj_limit;
+    maxq_adj_limit = rc->worst_quality - rc->active_worst_quality;
+    minq_adj_limit =
         (rc_cfg->mode == AOM_CQ ? MINQ_ADJ_LIMIT_CQ : MINQ_ADJ_LIMIT);
-
-    // Undershoot.
-    if (rc->rate_error_estimate > rc_cfg->under_shoot_pct) {
-      --twopass->extend_maxq;
-      if (rc->rolling_target_bits >= rc->rolling_actual_bits)
-        ++twopass->extend_minq;
-      // Overshoot.
-    } else if (rc->rate_error_estimate < -rc_cfg->over_shoot_pct) {
-      --twopass->extend_minq;
-      if (rc->rolling_target_bits < rc->rolling_actual_bits)
-        ++twopass->extend_maxq;
-    } else {
-      // Adjustment for extreme local overshoot.
-      if (rc->projected_frame_size > (2 * rc->base_frame_target) &&
-          rc->projected_frame_size > (2 * rc->avg_frame_bandwidth))
-        ++twopass->extend_maxq;
-
-      // Unwind undershoot or overshoot adjustment.
-      if (rc->rolling_target_bits < rc->rolling_actual_bits)
-        --twopass->extend_minq;
-      else if (rc->rolling_target_bits > rc->rolling_actual_bits)
+    int update_extend_minq_maxq = 1;
+#if CONFIG_FRAME_PARALLEL_ENCODE
+    if (!cpi->do_frame_data_update) update_extend_minq_maxq = 0;
+#endif
+    if (update_extend_minq_maxq) {
+      // Undershoot.
+      if (rc->rate_error_estimate > rc_cfg->under_shoot_pct) {
         --twopass->extend_maxq;
+        if (rc->rolling_target_bits >= rc->rolling_actual_bits)
+          ++twopass->extend_minq;
+        // Overshoot.
+      } else if (rc->rate_error_estimate < -rc_cfg->over_shoot_pct) {
+        --twopass->extend_minq;
+        if (rc->rolling_target_bits < rc->rolling_actual_bits)
+          ++twopass->extend_maxq;
+      } else {
+        // Adjustment for extreme local overshoot.
+        if (rc->projected_frame_size > (2 * rc->base_frame_target) &&
+            rc->projected_frame_size > (2 * rc->avg_frame_bandwidth))
+          ++twopass->extend_maxq;
+
+        // Unwind undershoot or overshoot adjustment.
+        if (rc->rolling_target_bits < rc->rolling_actual_bits)
+          --twopass->extend_minq;
+        else if (rc->rolling_target_bits > rc->rolling_actual_bits)
+          --twopass->extend_maxq;
+      }
+      twopass->extend_minq = clamp(twopass->extend_minq, 0, minq_adj_limit);
+      twopass->extend_maxq = clamp(twopass->extend_maxq, 0, maxq_adj_limit);
     }
-
-    twopass->extend_minq = clamp(twopass->extend_minq, 0, minq_adj_limit);
-    twopass->extend_maxq = clamp(twopass->extend_maxq, 0, maxq_adj_limit);
-
     // If there is a big and undexpected undershoot then feed the extra
     // bits back in quickly. One situation where this may happen is if a
     // frame is unexpectedly almost perfectly predicted by the ARF or GF
     // but not very well predcited by the previous frame.
     if (!frame_is_kf_gf_arf(cpi) && !cpi->rc.is_src_frame_alt_ref) {
       int fast_extra_thresh = rc->base_frame_target / HIGH_UNDERSHOOT_RATIO;
+      int64_t vbr_bits_off_target_fast;
+#if CONFIG_FRAME_PARALLEL_ENCODE
+      vbr_bits_off_target_fast = cpi->ppi->p_rc.temp_vbr_bits_off_target_fast;
+#else
+      vbr_bits_off_target_fast = rc->vbr_bits_off_target_fast;
+#endif
       if (rc->projected_frame_size < fast_extra_thresh) {
         rc->vbr_bits_off_target_fast +=
             fast_extra_thresh - rc->projected_frame_size;
         rc->vbr_bits_off_target_fast =
             AOMMIN(rc->vbr_bits_off_target_fast, (4 * rc->avg_frame_bandwidth));
 
-        // Fast adaptation of minQ if necessary to use up the extra bits.
-        if (rc->avg_frame_bandwidth) {
-          twopass->extend_minq_fast =
-              (int)(rc->vbr_bits_off_target_fast * 8 / rc->avg_frame_bandwidth);
+#if CONFIG_FRAME_PARALLEL_ENCODE
+        if (update_extend_minq_maxq)
+          cpi->ppi->p_rc.temp_vbr_bits_off_target_fast =
+              rc->vbr_bits_off_target_fast;
+        vbr_bits_off_target_fast = cpi->ppi->p_rc.temp_vbr_bits_off_target_fast;
+#else
+        vbr_bits_off_target_fast = rc->vbr_bits_off_target_fast;
+#endif
+        if (vbr_bits_off_target_fast && update_extend_minq_maxq) {
+          // Fast adaptation of minQ if necessary to use up the extra bits.
+          if (rc->avg_frame_bandwidth) {
+            twopass->extend_minq_fast =
+                (int)(vbr_bits_off_target_fast * 8 / rc->avg_frame_bandwidth);
+          }
+          twopass->extend_minq_fast = AOMMIN(
+              twopass->extend_minq_fast, minq_adj_limit - twopass->extend_minq);
         }
-        twopass->extend_minq_fast = AOMMIN(
-            twopass->extend_minq_fast, minq_adj_limit - twopass->extend_minq);
-      } else if (rc->vbr_bits_off_target_fast) {
-        twopass->extend_minq_fast = AOMMIN(
-            twopass->extend_minq_fast, minq_adj_limit - twopass->extend_minq);
+      } else if (vbr_bits_off_target_fast) {
+        if (update_extend_minq_maxq)
+          twopass->extend_minq_fast = AOMMIN(
+              twopass->extend_minq_fast, minq_adj_limit - twopass->extend_minq);
       } else {
         twopass->extend_minq_fast = 0;
       }
diff --git a/av1/encoder/ratectrl.c b/av1/encoder/ratectrl.c
index 9601f8f..2561ae0 100644
--- a/av1/encoder/ratectrl.c
+++ b/av1/encoder/ratectrl.c
@@ -260,6 +260,19 @@
 
   if (cpi->ppi->use_svc)
     update_layer_buffer_level(&cpi->svc, encoded_frame_size);
+
+#if CONFIG_FRAME_PARALLEL_ENCODE
+  /* TODO(FPMT): The current  update is happening in cpi->rc member,
+   * this need to be taken care appropriately in final FPMT implementation
+   * to carry this value to subsequent frames.
+   * The variable temp_buffer_level is introduced 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) {
+    p_rc->temp_buffer_level = rc->buffer_level;
+  }
+#endif
 }
 
 int av1_rc_get_default_min_gf_interval(int width, int height,
@@ -361,17 +374,29 @@
   rc->resize_avg_qp = 0;
   rc->resize_buffer_underflow = 0;
   rc->resize_count = 0;
+#if CONFIG_FRAME_PARALLEL_ENCODE
+  rc->frame_level_fast_extra_bits = 0;
+#endif
 }
 
 int av1_rc_drop_frame(AV1_COMP *cpi) {
   const AV1EncoderConfig *oxcf = &cpi->oxcf;
   RATE_CONTROL *const rc = &cpi->rc;
   PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc;
+  int64_t buffer_level;
+#if CONFIG_FRAME_PARALLEL_ENCODE
+  buffer_level =
+      (cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] > 0)
+          ? p_rc->temp_buffer_level
+          : rc->buffer_level;
+#else
+  buffer_level = rc->buffer_level;
+#endif
 
   if (!oxcf->rc_cfg.drop_frames_water_mark) {
     return 0;
   } else {
-    if (rc->buffer_level < 0) {
+    if (buffer_level < 0) {
       // Always drop if buffer is below 0.
       return 1;
     } else {
@@ -379,9 +404,9 @@
       // (starting with the next frame) until it increases back over drop_mark.
       int drop_mark = (int)(oxcf->rc_cfg.drop_frames_water_mark *
                             p_rc->optimal_buffer_level / 100);
-      if ((rc->buffer_level > drop_mark) && (rc->decimation_factor > 0)) {
+      if ((buffer_level > drop_mark) && (rc->decimation_factor > 0)) {
         --rc->decimation_factor;
-      } else if (rc->buffer_level <= drop_mark && rc->decimation_factor == 0) {
+      } else if (buffer_level <= drop_mark && rc->decimation_factor == 0) {
         rc->decimation_factor = 1;
       }
       if (rc->decimation_factor > 0) {
@@ -496,22 +521,53 @@
   const RATE_CONTROL *const rc = &cpi->rc;
   const RefreshFrameFlagsInfo *const refresh_frame_flags = &cpi->refresh_frame;
   double rcf;
+  double rate_correction_factors_kfstd;
+  double rate_correction_factors_gfarfstd;
+  double rate_correction_factors_internormal;
+#if CONFIG_FRAME_PARALLEL_ENCODE
+  rate_correction_factors_kfstd =
+      (cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] > 0)
+          ? cpi->ppi->p_rc.temp_rate_correction_factors[KF_STD]
+          : rc->rate_correction_factors[KF_STD];
+  rate_correction_factors_gfarfstd =
+      (cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] > 0)
+          ? cpi->ppi->p_rc.temp_rate_correction_factors[GF_ARF_STD]
+          : rc->rate_correction_factors[GF_ARF_STD];
+  rate_correction_factors_internormal =
+      (cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] > 0)
+          ? cpi->ppi->p_rc.temp_rate_correction_factors[INTER_NORMAL]
+          : rc->rate_correction_factors[INTER_NORMAL];
+#else
+  rate_correction_factors_kfstd = rc->rate_correction_factors[KF_STD];
+  rate_correction_factors_gfarfstd = rc->rate_correction_factors[GF_ARF_STD];
+  rate_correction_factors_internormal =
+      rc->rate_correction_factors[INTER_NORMAL];
+#endif
 
   if (cpi->common.current_frame.frame_type == KEY_FRAME) {
-    rcf = rc->rate_correction_factors[KF_STD];
+    rcf = rate_correction_factors_kfstd;
   } else if (is_stat_consumption_stage(cpi)) {
     const RATE_FACTOR_LEVEL rf_lvl =
         get_rate_factor_level(&cpi->ppi->gf_group, cpi->gf_frame_index);
-    rcf = rc->rate_correction_factors[rf_lvl];
+    double rate_correction_factors_rflvl;
+#if CONFIG_FRAME_PARALLEL_ENCODE
+    rate_correction_factors_rflvl =
+        (cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] > 0)
+            ? cpi->ppi->p_rc.temp_rate_correction_factors[rf_lvl]
+            : rc->rate_correction_factors[rf_lvl];
+#else
+    rate_correction_factors_rflvl = rc->rate_correction_factors[rf_lvl];
+#endif
+    rcf = rate_correction_factors_rflvl;
   } else {
     if ((refresh_frame_flags->alt_ref_frame ||
          refresh_frame_flags->golden_frame) &&
         !rc->is_src_frame_alt_ref && !cpi->ppi->use_svc &&
         (cpi->oxcf.rc_cfg.mode != AOM_CBR ||
          cpi->oxcf.rc_cfg.gf_cbr_boost_pct > 20))
-      rcf = rc->rate_correction_factors[GF_ARF_STD];
+      rcf = rate_correction_factors_gfarfstd;
     else
-      rcf = rc->rate_correction_factors[INTER_NORMAL];
+      rcf = rate_correction_factors_internormal;
   }
   rcf *= resize_rate_factor(&cpi->oxcf.frm_dim_cfg, width, height);
   return fclamp(rcf, MIN_BPB_FACTOR, MAX_BPB_FACTOR);
@@ -2118,6 +2174,10 @@
     }
     p_rc->temp_avg_q = rc->avg_q;
     p_rc->temp_last_boosted_qindex = rc->last_boosted_qindex;
+    p_rc->temp_total_actual_bits = rc->total_actual_bits;
+    p_rc->temp_projected_frame_size = rc->projected_frame_size;
+    for (int i = 0; i < RATE_FACTOR_LEVELS; i++)
+      p_rc->temp_rate_correction_factors[i] = rc->rate_correction_factors[i];
   }
 #endif  // CONFIG_FRAME_PARALLEL_ENCODE
 
@@ -2286,7 +2346,15 @@
 // For VBR...adjustment to the frame target based on error from previous frames
 static void vbr_rate_correction(AV1_COMP *cpi, int *this_frame_target) {
   RATE_CONTROL *const rc = &cpi->rc;
-  int64_t vbr_bits_off_target = rc->vbr_bits_off_target;
+  int64_t vbr_bits_off_target;
+#if CONFIG_FRAME_PARALLEL_ENCODE
+  vbr_bits_off_target =
+      (cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] > 0)
+          ? cpi->ppi->p_rc.temp_vbr_bits_off_target
+          : rc->vbr_bits_off_target;
+#else
+  vbr_bits_off_target = rc->vbr_bits_off_target;
+#endif
   const int stats_count =
       cpi->ppi->twopass.stats_buf_ctx->total_stats != NULL
           ? (int)cpi->ppi->twopass.stats_buf_ctx->total_stats->count
@@ -2308,14 +2376,34 @@
   // Dont do it for kf,arf,gf or overlay frames.
   if (!frame_is_kf_gf_arf(cpi) && !rc->is_src_frame_alt_ref &&
       rc->vbr_bits_off_target_fast) {
+    int64_t vbr_bits_off_target_fast;
+#if CONFIG_FRAME_PARALLEL_ENCODE
+    vbr_bits_off_target_fast =
+        (cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] > 0)
+            ? cpi->ppi->p_rc.temp_vbr_bits_off_target_fast
+            : rc->vbr_bits_off_target_fast;
+#else
+    vbr_bits_off_target_fast = rc->vbr_bits_off_target_fast;
+#endif
     int one_frame_bits = AOMMAX(rc->avg_frame_bandwidth, *this_frame_target);
     int fast_extra_bits;
-    fast_extra_bits = (int)AOMMIN(rc->vbr_bits_off_target_fast, one_frame_bits);
-    fast_extra_bits = (int)AOMMIN(
-        fast_extra_bits,
-        AOMMAX(one_frame_bits / 8, rc->vbr_bits_off_target_fast / 8));
+    fast_extra_bits = (int)AOMMIN(vbr_bits_off_target_fast, one_frame_bits);
+    fast_extra_bits =
+        (int)AOMMIN(fast_extra_bits,
+                    AOMMAX(one_frame_bits / 8, vbr_bits_off_target_fast / 8));
     *this_frame_target += (int)fast_extra_bits;
+#if CONFIG_FRAME_PARALLEL_ENCODE
+    rc->frame_level_fast_extra_bits += fast_extra_bits;
+    if (cpi->do_frame_data_update) {
+      // Subtract the previously accumulated fast extra bits.
+      rc->vbr_bits_off_target_fast -= rc->frame_level_fast_extra_bits;
+      cpi->ppi->p_rc.temp_vbr_bits_off_target_fast =
+          rc->vbr_bits_off_target_fast;
+      rc->frame_level_fast_extra_bits = 0;
+    }
+#else
     rc->vbr_bits_off_target_fast -= fast_extra_bits;
+#endif
   }
 }
 
diff --git a/av1/encoder/ratectrl.h b/av1/encoder/ratectrl.h
index 62f8638..96279de 100644
--- a/av1/encoder/ratectrl.h
+++ b/av1/encoder/ratectrl.h
@@ -261,6 +261,9 @@
   int resize_avg_qp;
   int resize_buffer_underflow;
   int resize_count;
+#if CONFIG_FRAME_PARALLEL_ENCODE
+  int frame_level_fast_extra_bits;
+#endif
   /*!\endcond */
 } RATE_CONTROL;
 
@@ -381,6 +384,66 @@
    * last_q.
    */
   int temp_last_q[FRAME_TYPES];
+
+  /*!
+   * Temporary variable used in simulating the delayed update of
+   * projected_frame_size.
+   */
+  int temp_projected_frame_size;
+
+  /*!
+   * Temporary variable used in simulating the delayed update of
+   * total_actual_bits.
+   */
+  int64_t temp_total_actual_bits;
+
+  /*!
+   * Temporary variable used in simulating the delayed update of
+   * buffer_level.
+   */
+  int64_t temp_buffer_level;
+
+  /*!
+   * Temporary variable used in simulating the delayed update of
+   * vbr_bits_off_target.
+   */
+  int64_t temp_vbr_bits_off_target;
+
+  /*!
+   * Temporary variable used in simulating the delayed update of
+   * vbr_bits_off_target_fast.
+   */
+  int64_t temp_vbr_bits_off_target_fast;
+
+  /*!
+   * Temporary variable used in simulating the delayed update of
+   * rate_correction_factors.
+   */
+  double temp_rate_correction_factors[RATE_FACTOR_LEVELS];
+
+  /*!
+   * Temporary variable used in simulating the delayed update of
+   * rate_error_estimate.
+   */
+  int temp_rate_error_estimate;
+
+  /*!
+   * Temporary variable used in simulating the delayed update of
+   * rolling_arf_group_target_bits.
+   */
+  int temp_rolling_arf_group_target_bits;
+
+  /*!
+   * Temporary variable used in simulating the delayed update of
+   * rolling_arf_group_actual_bits;.
+   */
+  int temp_rolling_arf_group_actual_bits;
+
+  /*!
+   * Temporary variable used in simulating the delayed update of
+   * bits_left;.
+   */
+  int64_t temp_bits_left;
 #endif
 } PRIMARY_RATE_CONTROL;