Let firstpass_info support past stats

We need past stats for keyframe detection.
In this CL cur_index is added to indicate current frame's index.
start_index is indicating the first available stats.
When cur_index != start_index, it means there are past stats
available.

We use FIRSTPASS_INFO_STATS_PAST_MIN to control the past stats size.

BUG=aomedia:3069
BUG=aomedia:3070

Change-Id: I5f359c5081ffeced21c50662f716ee958186eb79
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index 3d9afeb..18863d7 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -3938,8 +3938,14 @@
 static AOM_INLINE void update_keyframe_counters(AV1_COMP *cpi) {
   if (cpi->common.show_frame && cpi->rc.frames_to_key) {
 #if !CONFIG_REALTIME_ONLY
-    FIRSTPASS_STATS dummy_stats;
-    av1_firstpass_info_pop(&cpi->ppi->twopass.firstpass_info, &dummy_stats);
+    FIRSTPASS_INFO *firstpass_info = &cpi->ppi->twopass.firstpass_info;
+    if (firstpass_info->past_stats_count > FIRSTPASS_INFO_STATS_PAST_MIN) {
+      av1_firstpass_info_move_cur_index_and_pop(firstpass_info);
+    } else {
+      // When there is not enough past stats, we move the current
+      // index without poping the past stats
+      av1_firstpass_info_move_cur_index(firstpass_info);
+    }
 #endif
     cpi->rc.frames_since_key++;
     cpi->rc.frames_to_key--;
diff --git a/av1/encoder/firstpass.c b/av1/encoder/firstpass.c
index 4051b0c..28d527a 100644
--- a/av1/encoder/firstpass.c
+++ b/av1/encoder/firstpass.c
@@ -1390,7 +1390,10 @@
         sizeof(firstpass_info->static_stats_buf) /
         sizeof(firstpass_info->static_stats_buf[0]);
     firstpass_info->start_index = 0;
+    firstpass_info->cur_index = 0;
     firstpass_info->stats_count = 0;
+    firstpass_info->future_stats_count = 0;
+    firstpass_info->past_stats_count = 0;
     av1_zero(firstpass_info->total_stats);
     if (ext_stats_buf_size == 0) {
       return AOM_CODEC_OK;
@@ -1401,7 +1404,10 @@
     firstpass_info->stats_buf = ext_stats_buf;
     firstpass_info->stats_buf_size = ext_stats_buf_size;
     firstpass_info->start_index = 0;
+    firstpass_info->cur_index = 0;
     firstpass_info->stats_count = firstpass_info->stats_buf_size;
+    firstpass_info->future_stats_count = firstpass_info->stats_count;
+    firstpass_info->past_stats_count = 0;
     av1_zero(firstpass_info->total_stats);
     for (int i = 0; i < firstpass_info->stats_count; ++i) {
       av1_accumulate_stats(&firstpass_info->total_stats,
@@ -1411,20 +1417,43 @@
   return AOM_CODEC_OK;
 }
 
-aom_codec_err_t av1_firstpass_info_pop(FIRSTPASS_INFO *firstpass_info,
-                                       FIRSTPASS_STATS *output_stats) {
-  if (firstpass_info->stats_count > 0) {
-    const int next_start =
-        (firstpass_info->start_index + 1) % firstpass_info->stats_buf_size;
-    *output_stats = firstpass_info->stats_buf[firstpass_info->start_index];
-    firstpass_info->start_index = next_start;
-    --firstpass_info->stats_count;
+aom_codec_err_t av1_firstpass_info_move_cur_index(
+    FIRSTPASS_INFO *firstpass_info) {
+  assert(firstpass_info->future_stats_count +
+             firstpass_info->past_stats_count ==
+         firstpass_info->stats_count);
+  if (firstpass_info->future_stats_count > 1) {
+    firstpass_info->cur_index =
+        (firstpass_info->cur_index + 1) % firstpass_info->stats_buf_size;
+    --firstpass_info->future_stats_count;
+    ++firstpass_info->past_stats_count;
     return AOM_CODEC_OK;
   } else {
     return AOM_CODEC_ERROR;
   }
 }
 
+aom_codec_err_t av1_firstpass_info_pop(FIRSTPASS_INFO *firstpass_info) {
+  if (firstpass_info->stats_count > 0 && firstpass_info->past_stats_count > 0) {
+    const int next_start =
+        (firstpass_info->start_index + 1) % firstpass_info->stats_buf_size;
+    firstpass_info->start_index = next_start;
+    --firstpass_info->stats_count;
+    --firstpass_info->past_stats_count;
+    return AOM_CODEC_OK;
+  } else {
+    return AOM_CODEC_ERROR;
+  }
+}
+
+aom_codec_err_t av1_firstpass_info_move_cur_index_and_pop(
+    FIRSTPASS_INFO *firstpass_info) {
+  aom_codec_err_t ret = av1_firstpass_info_move_cur_index(firstpass_info);
+  if (ret != AOM_CODEC_OK) return ret;
+  ret = av1_firstpass_info_pop(firstpass_info);
+  return ret;
+}
+
 aom_codec_err_t av1_firstpass_info_push(FIRSTPASS_INFO *firstpass_info,
                                         const FIRSTPASS_STATS *input_stats) {
   if (firstpass_info->stats_count < firstpass_info->stats_buf_size) {
@@ -1433,6 +1462,7 @@
         firstpass_info->stats_buf_size;
     firstpass_info->stats_buf[next_index] = *input_stats;
     ++firstpass_info->stats_count;
+    ++firstpass_info->future_stats_count;
     av1_accumulate_stats(&firstpass_info->total_stats, input_stats);
     return AOM_CODEC_OK;
   } else {
@@ -1441,12 +1471,29 @@
 }
 
 const FIRSTPASS_STATS *av1_firstpass_info_peek(
-    const FIRSTPASS_INFO *firstpass_info, int index_offset) {
-  if (index_offset >= 0 && index_offset < firstpass_info->stats_count) {
-    const int index = (firstpass_info->start_index + index_offset) %
+    const FIRSTPASS_INFO *firstpass_info, int offset_from_cur) {
+  if (offset_from_cur >= -firstpass_info->past_stats_count &&
+      offset_from_cur < firstpass_info->future_stats_count) {
+    const int index = (firstpass_info->cur_index + offset_from_cur) %
                       firstpass_info->stats_buf_size;
     return &firstpass_info->stats_buf[index];
   } else {
     return NULL;
   }
 }
+
+int av1_firstpass_info_future_count(const FIRSTPASS_INFO *firstpass_info,
+                                    int offset_from_cur) {
+  if (offset_from_cur < firstpass_info->future_stats_count) {
+    return firstpass_info->future_stats_count - offset_from_cur;
+  }
+  return 0;
+}
+
+int av1_firstpass_info_past_count(const FIRSTPASS_INFO *firstpass_info,
+                                  int offset_from_cur) {
+  if (offset_from_cur >= -firstpass_info->past_stats_count) {
+    return offset_from_cur + firstpass_info->past_stats_count;
+  }
+  return 0;
+}
diff --git a/av1/encoder/firstpass.h b/av1/encoder/firstpass.h
index 1367cdb..8e3518e 100644
--- a/av1/encoder/firstpass.h
+++ b/av1/encoder/firstpass.h
@@ -162,7 +162,17 @@
   double cor_coeff;
 } FIRSTPASS_STATS;
 
-/*!\cond */
+// We want to keep one past stats for key frame detection
+// in test_candidate_kf()
+#define FIRSTPASS_INFO_STATS_PAST_MIN 1
+
+// The size of static buffer used in FIRSTPASS_INFO.
+#define FIRSTPASS_INFO_STATIC_BUF_SIZE \
+  (MAX_LAP_BUFFERS + FIRSTPASS_INFO_STATS_PAST_MIN)
+
+/*!
+ * \brief  Data structure used for managing first pass stats
+ */
 typedef struct {
   /*!
    * An static buffer that will be used when no ext_stats_buf is assigned.
@@ -173,7 +183,7 @@
    * encode the video in the same pass. In this scenario, the stats will
    * be pushed and popped from static_stats_buf.
    */
-  FIRSTPASS_STATS static_stats_buf[MAX_LAP_BUFFERS];
+  FIRSTPASS_STATS static_stats_buf[FIRSTPASS_INFO_STATIC_BUF_SIZE];
   /*!
    * A pointer point to first pass stats.
    * Note that this buffer will be used as ring buffer.
@@ -184,15 +194,37 @@
    */
   int stats_buf_size;
   /*!
-   * start_index of the current frame's stats
+   * start index of the available frame stats
+   * Note that start_index doesn't always point to
+   * current frame's stats because we need to
+   * keep past stats as well. To access current
+   * frame's stats, please use cur_index.
    */
   int start_index;
+
   /*!
    * count available stats stored in stats_buf
+   * the following condition should stay true
+   * stats_count = future_stats_count + past_stats_count
    */
   int stats_count;
 
   /*!
+   *  index of the current frame's stats
+   */
+  int cur_index;
+
+  /*!
+   * count available future stats including current stats
+   */
+  int future_stats_count;
+
+  /*!
+   * count available past stats EXCLUDING current stats
+   */
+  int past_stats_count;
+
+  /*!
    * Accumulation of the stats being pushed into firstpass_info
    */
   FIRSTPASS_STATS total_stats;
@@ -214,15 +246,31 @@
                                         FIRSTPASS_STATS *ext_stats_buf,
                                         int ext_stats_buf_size);
 
+/*!\brief Move cur_index by 1
+ *
+ * \ingroup rate_control
+ * \param[out]   firstpass_info      struct of firstpass_info.
+ * \return status
+ */
+aom_codec_err_t av1_firstpass_info_move_cur_index(
+    FIRSTPASS_INFO *firstpass_info);
+
 /*!\brief Pop a stats from firstpass_info
  *
  * \ingroup rate_control
  * \param[out]   firstpass_info      struct of firstpass_info.
- * \param[out]   output_stats        output stats
  * \return status
  */
-aom_codec_err_t av1_firstpass_info_pop(FIRSTPASS_INFO *firstpass_info,
-                                       FIRSTPASS_STATS *output_stats);
+aom_codec_err_t av1_firstpass_info_pop(FIRSTPASS_INFO *firstpass_info);
+
+/*!\brief Move cur_index by 1 and pop a stats from firstpass_info
+ *
+ * \ingroup rate_control
+ * \param[out]   firstpass_info      struct of firstpass_info.
+ * \return status
+ */
+aom_codec_err_t av1_firstpass_info_move_cur_index_and_pop(
+    FIRSTPASS_INFO *firstpass_info);
 
 /*!\brief Push a stats into firstpass_info
  *
@@ -237,23 +285,57 @@
 
 /*!\brief Peek at a stats from firstpass_info
  *
+ * The target index is as follows.
+ * (cur_index + offset_from_cur) % firstpass_info->stats_buf_size
+ *
  * \ingroup rate_control
  * \param[in]  firstpass_info      struct of firstpass_info.
- * \param[in]  stats_index_offset  index offset.
+ * \param[in]  offset_from_cur  index offset from cur_index.
  * \return pointer to the stats. The pointer will be NULL if
  *         stats_index_offset is invalid.
  */
 const FIRSTPASS_STATS *av1_firstpass_info_peek(
-    const FIRSTPASS_INFO *firstpass_info, int stats_index_offset);
+    const FIRSTPASS_INFO *firstpass_info, int offset_from_cur);
 
+/*!\brief Count the future stats from the target in firstpass_info
+ * Note that the target stats will be counted as well.
+ * The target index is as follows.
+ * (cur_index + offset_from_curr) % firstpass_info->stats_buf_size
+ *
+ * \ingroup rate_control
+ * \param[in]  firstpass_info    struct of firstpass_info.
+ * \param[in]  offset_from_cur  target stats's inffset
+ *                               from cur_index.
+ * \return Number of stats in the future after the target stats
+ *         including itself.
+ */
+int av1_firstpass_info_future_count(const FIRSTPASS_INFO *firstpass_info,
+                                    int offset_from_cur);
+
+/*!\brief Count the past stats before the target in firstpass_info
+ * Note that the target stats will NOT be counted.
+ * The target index is as follows.
+ * (cur_index + offset_from_cur) % firstpass_info->stats_buf_size
+ *
+ * \ingroup rate_control
+ * \param[in]  firstpass_info    struct of firstpass_info.
+ * \param[in]  offset_from_cur  target stats's index offset
+ *                               from cur_index.
+ * \return Number of stats in the past before the target stats
+ *         excluding itself.
+ */
+int av1_firstpass_info_past_count(const FIRSTPASS_INFO *firstpass_info,
+                                  int offset_from_cur);
+
+/*!\cond */
 #define FC_ANIMATION_THRESH 0.15
 enum {
   FC_NORMAL = 0,
   FC_GRAPHICS_ANIMATION = 1,
   FRAME_CONTENT_TYPES = 2
 } UENUM1BYTE(FRAME_CONTENT_TYPE);
-
 /*!\endcond */
+
 /*!
  * \brief  Data related to the current GF/ARF group and the
  * individual frames within the group
diff --git a/av1/encoder/pass2_strategy.c b/av1/encoder/pass2_strategy.c
index 2b258dd..4e2f1a7 100644
--- a/av1/encoder/pass2_strategy.c
+++ b/av1/encoder/pass2_strategy.c
@@ -417,7 +417,8 @@
   // instead of a clean scene cut.
   if (frame_interval > min_gf_interval && loop_decay_rate >= 0.999 &&
       last_decay_rate < 0.9) {
-    int stats_left = firstpass_info->stats_count - next_stats_index;
+    int stats_left =
+        av1_firstpass_info_future_count(firstpass_info, next_stats_index);
     if (stats_left >= still_interval) {
       int j;
       // Look ahead a few frames to see if static condition persists...
@@ -2649,16 +2650,15 @@
                              int this_stats_index, int frame_count_so_far,
                              enum aom_rc_mode rc_mode, int scenecut_mode,
                              int num_mbs) {
-  if (this_stats_index < 1 ||
-      this_stats_index + 1 >= firstpass_info->stats_count) {
-    return 0;
-  }
   const FIRSTPASS_STATS *last_stats =
       av1_firstpass_info_peek(firstpass_info, this_stats_index - 1);
   const FIRSTPASS_STATS *this_stats =
       av1_firstpass_info_peek(firstpass_info, this_stats_index);
   const FIRSTPASS_STATS *next_stats =
       av1_firstpass_info_peek(firstpass_info, this_stats_index + 1);
+  if (last_stats == NULL || this_stats == NULL || next_stats == NULL) {
+    return 0;
+  }
 
   int is_viable_kf = 0;
   double pcnt_intra = 1.0 - this_stats->pcnt_inter;
@@ -2669,8 +2669,12 @@
   int frames_to_test_after_candidate_key = SCENE_CUT_KEY_TEST_INTERVAL;
   int count_for_tolerable_prediction = 3;
 
+  // We do "-1" because the candidate key is not counted.
+  int stats_after_this_stats =
+      av1_firstpass_info_future_count(firstpass_info, this_stats_index) - 1;
+
   if (scenecut_mode == ENABLE_SCENECUT_MODE_1) {
-    if (this_stats_index + 3 >= firstpass_info->stats_count) {
+    if (stats_after_this_stats < 3) {
       return 0;
     } else {
       frames_to_test_after_candidate_key = 3;
@@ -2678,10 +2682,8 @@
     }
   }
   // Make sure we have enough stats after the candidate key.
-  // We do "-1" because the candidate key is not counted.
   frames_to_test_after_candidate_key =
-      AOMMIN(frames_to_test_after_candidate_key,
-             firstpass_info->stats_count - this_stats_index - 1);
+      AOMMIN(frames_to_test_after_candidate_key, stats_after_this_stats);
 
   // Does the frame satisfy the primary criteria of a key frame?
   // See above for an explanation of the test criteria.
@@ -2842,7 +2844,9 @@
                           : cpi->common.mi_params.MBs;
   const FIRSTPASS_STATS *this_stats =
       av1_firstpass_info_peek(firstpass_info, 0);
-  while (frames_to_key < firstpass_info->stats_count &&
+  const int future_stats_count =
+      av1_firstpass_info_future_count(firstpass_info, 0);
+  while (frames_to_key < future_stats_count &&
          frames_to_key < num_frames_to_detect_scenecut) {
     // Accumulate total number of stats available till next key frame
     num_stats_used_for_kf_boost++;
@@ -2860,7 +2864,7 @@
 
     // Provided that we are not at the end of the file...
     if ((cpi->ppi->p_rc.enable_scenecut_detection > 0) && kf_cfg->auto_key &&
-        frames_to_key + 1 < firstpass_info->stats_count) {
+        frames_to_key + 1 < future_stats_count) {
       const FIRSTPASS_STATS *next_stats =
           av1_firstpass_info_peek(firstpass_info, frames_to_key + 1);
       double loop_decay_rate;
@@ -2925,7 +2929,7 @@
     frames_to_key = num_frames_to_next_key;
 
   if (!kf_cfg->fwd_kf_enabled || scenecut_detected ||
-      frames_to_key == firstpass_info->stats_count) {
+      frames_to_key == future_stats_count) {
     p_rc->next_is_fwd_key = 0;
   }
 
@@ -3197,8 +3201,10 @@
   if (kf_cfg->fwd_kf_enabled)
     p_rc->next_is_fwd_key |= p_rc->next_key_frame_forced;
 
+  const int future_stats_count =
+      av1_firstpass_info_future_count(firstpass_info, 0);
   // Special case for the last key frame of the file.
-  if (frames_to_key == firstpass_info->stats_count) {
+  if (frames_to_key == future_stats_count) {
     // Accumulate kf group error.
     // TODO(angiebird): Why do we need to add last frame's stats
     // here? Move it to a proper place.
diff --git a/test/firstpass_test.cc b/test/firstpass_test.cc
index 11cc0ec..ae75f2a 100644
--- a/test/firstpass_test.cc
+++ b/test/firstpass_test.cc
@@ -28,6 +28,9 @@
   aom_codec_err_t ret =
       av1_firstpass_info_init(&firstpass_info, ext_stats_buf, 10);
   EXPECT_EQ(firstpass_info.stats_count, ref_stats_size);
+  EXPECT_EQ(firstpass_info.future_stats_count + firstpass_info.past_stats_count,
+            firstpass_info.stats_count);
+  EXPECT_EQ(firstpass_info.cur_index, 0);
   EXPECT_EQ(ret, AOM_CODEC_OK);
 }
 
@@ -35,37 +38,42 @@
   FIRSTPASS_INFO firstpass_info;
   aom_codec_err_t ret = av1_firstpass_info_init(&firstpass_info, NULL, 0);
   EXPECT_EQ(firstpass_info.stats_count, 0);
+  EXPECT_EQ(firstpass_info.cur_index, 0);
   EXPECT_EQ(ret, AOM_CODEC_OK);
 }
 
 TEST(FirstpassTest, FirstpassInfoPushPop) {
   FIRSTPASS_INFO firstpass_info;
   av1_firstpass_info_init(&firstpass_info, NULL, 0);
-  EXPECT_EQ(firstpass_info.stats_buf_size, 48);
-  for (int i = 0; i < 48; ++i) {
+  EXPECT_EQ(firstpass_info.stats_buf_size, FIRSTPASS_INFO_STATIC_BUF_SIZE);
+  for (int i = 0; i < FIRSTPASS_INFO_STATIC_BUF_SIZE; ++i) {
     FIRSTPASS_STATS stats;
     av1_zero(stats);
     stats.frame = i;
     aom_codec_err_t ret = av1_firstpass_info_push(&firstpass_info, &stats);
     EXPECT_EQ(ret, AOM_CODEC_OK);
   }
-  EXPECT_EQ(firstpass_info.stats_count, 48);
-  for (int i = 0; i < 20; ++i) {
-    FIRSTPASS_STATS stats;
-    av1_zero(stats);
-    aom_codec_err_t ret = av1_firstpass_info_pop(&firstpass_info, &stats);
-    EXPECT_EQ(stats.frame, i);
+  EXPECT_EQ(firstpass_info.stats_count, FIRSTPASS_INFO_STATIC_BUF_SIZE);
+  const int pop_count = FIRSTPASS_INFO_STATIC_BUF_SIZE / 2;
+  for (int i = 0; i < pop_count; ++i) {
+    const FIRSTPASS_STATS *stats = av1_firstpass_info_peek(&firstpass_info, 0);
+    aom_codec_err_t ret =
+        av1_firstpass_info_move_cur_index_and_pop(&firstpass_info);
+    EXPECT_NE(stats, nullptr);
+    EXPECT_EQ(stats->frame, i);
     EXPECT_EQ(ret, AOM_CODEC_OK);
   }
-  EXPECT_EQ(firstpass_info.stats_count, 28);
+  EXPECT_EQ(firstpass_info.stats_count,
+            FIRSTPASS_INFO_STATIC_BUF_SIZE - pop_count);
 
-  for (int i = 0; i < 20; ++i) {
+  const int push_count = FIRSTPASS_INFO_STATIC_BUF_SIZE / 2;
+  for (int i = 0; i < push_count; ++i) {
     FIRSTPASS_STATS stats;
     av1_zero(stats);
     aom_codec_err_t ret = av1_firstpass_info_push(&firstpass_info, &stats);
     EXPECT_EQ(ret, AOM_CODEC_OK);
   }
-  EXPECT_EQ(firstpass_info.stats_count, 48);
+  EXPECT_EQ(firstpass_info.stats_count, FIRSTPASS_INFO_STATIC_BUF_SIZE);
 
   EXPECT_EQ(firstpass_info.stats_count, firstpass_info.stats_buf_size);
   // Pusht a stats when the queue is full.
@@ -88,4 +96,67 @@
   EXPECT_EQ(firstpass_info.total_stats.count, 10);
 }
 
+TEST(FirstpassTest, FirstpassInfoMoveCurr) {
+  FIRSTPASS_INFO firstpass_info;
+  av1_firstpass_info_init(&firstpass_info, NULL, 0);
+  int frame_cnt = 0;
+  EXPECT_EQ(firstpass_info.stats_buf_size, FIRSTPASS_INFO_STATIC_BUF_SIZE);
+  for (int i = 0; i < FIRSTPASS_INFO_STATIC_BUF_SIZE; ++i) {
+    FIRSTPASS_STATS stats;
+    av1_zero(stats);
+    stats.frame = frame_cnt;
+    ++frame_cnt;
+    aom_codec_err_t ret = av1_firstpass_info_push(&firstpass_info, &stats);
+    EXPECT_EQ(ret, AOM_CODEC_OK);
+  }
+  EXPECT_EQ(firstpass_info.cur_index, firstpass_info.start_index);
+  aom_codec_err_t ret = av1_firstpass_info_pop(&firstpass_info);
+  // We cannot pop when cur_index == start_index
+  EXPECT_EQ(ret, AOM_CODEC_ERROR);
+  int ref_frame_cnt = 0;
+  const int move_count = FIRSTPASS_INFO_STATIC_BUF_SIZE * 2 / 3;
+  for (int i = 0; i < move_count; ++i) {
+    const FIRSTPASS_STATS *this_stats =
+        av1_firstpass_info_peek(&firstpass_info, 0);
+    EXPECT_EQ(this_stats->frame, ref_frame_cnt);
+    ++ref_frame_cnt;
+    av1_firstpass_info_move_cur_index(&firstpass_info);
+  }
+  EXPECT_EQ(firstpass_info.future_stats_count,
+            FIRSTPASS_INFO_STATIC_BUF_SIZE - move_count);
+  EXPECT_EQ(firstpass_info.past_stats_count, move_count);
+  EXPECT_EQ(firstpass_info.stats_count, FIRSTPASS_INFO_STATIC_BUF_SIZE);
+
+  const int test_count = FIRSTPASS_INFO_STATIC_BUF_SIZE / 2;
+  for (int i = 0; i < test_count; ++i) {
+    aom_codec_err_t ret = av1_firstpass_info_pop(&firstpass_info);
+    EXPECT_EQ(ret, AOM_CODEC_OK);
+  }
+
+  // Pop #test_count stats
+  for (int i = 0; i < test_count; ++i) {
+    FIRSTPASS_STATS stats;
+    av1_zero(stats);
+    stats.frame = frame_cnt;
+    ++frame_cnt;
+    aom_codec_err_t ret = av1_firstpass_info_push(&firstpass_info, &stats);
+    EXPECT_EQ(ret, AOM_CODEC_OK);
+  }
+
+  // peek and move #test_count stats
+  for (int i = 0; i < test_count; ++i) {
+    const FIRSTPASS_STATS *this_stats =
+        av1_firstpass_info_peek(&firstpass_info, 0);
+    EXPECT_EQ(this_stats->frame, ref_frame_cnt);
+    ++ref_frame_cnt;
+    av1_firstpass_info_move_cur_index(&firstpass_info);
+  }
+
+  // pop #test_count stats
+  for (int i = 0; i < test_count; ++i) {
+    aom_codec_err_t ret = av1_firstpass_info_pop(&firstpass_info);
+    EXPECT_EQ(ret, AOM_CODEC_OK);
+  }
+}
+
 }  // namespace