Add ARF stack buffer operations

Allow the encoder to track its reference frame usage in stack
buffer.

Change-Id: Ib9fefc688e6ca7d4bcc1fa1abc150baa4e510c17
diff --git a/av1/encoder/encode_strategy.c b/av1/encoder/encode_strategy.c
index ff6af67..79b1519 100644
--- a/av1/encoder/encode_strategy.c
+++ b/av1/encoder/encode_strategy.c
@@ -773,6 +773,12 @@
                                  FRAME_UPDATE_TYPE frame_update_type) {
   AV1_COMMON *const cm = &cpi->common;
 
+  if (cm->current_frame.frame_type == KEY_FRAME && cm->show_frame) {
+    stack_reset(cpi->lst_stack, &cpi->lst_stack_size);
+    stack_reset(cpi->gld_stack, &cpi->gld_stack_size);
+    stack_reset(cpi->arf_stack, &cpi->arf_stack_size);
+  }
+
   // If check_frame_refs_short_signaling() decided to set
   // frame_refs_short_signaling=1 then we update remapped_ref_idx[] here.  Every
   // reference will still map to the same RefCntBuffer (through ref_frame_map[])
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h
index 255f5ef..5bbed8b 100644
--- a/av1/encoder/encoder.h
+++ b/av1/encoder/encoder.h
@@ -865,6 +865,14 @@
 
   GF_GROUP gf_group;
 
+  // To control the reference frame buffer and selection.
+  int arf_stack[FRAME_BUFFERS];
+  int arf_stack_size;
+  int lst_stack[FRAME_BUFFERS];
+  int lst_stack_size;
+  int gld_stack[FRAME_BUFFERS];
+  int gld_stack_size;
+
   YV12_BUFFER_CONFIG alt_ref_buffer;
 
   YV12_BUFFER_CONFIG source_kf_buffer;
@@ -1134,6 +1142,35 @@
                                         CompoundTypeRdBuffers *const bufs);
 void av1_release_compound_type_rd_buffers(CompoundTypeRdBuffers *const bufs);
 
+// TODO(jingning): Move these functions as primitive members for the new cpi
+// class.
+static INLINE void stack_push(int *stack, int *stack_size, int item) {
+  for (int i = 0; i < *stack_size; ++i) stack[i + 1] = stack[i];
+  stack[0] = item;
+  ++*stack_size;
+}
+
+static INLINE int stack_pop(int *stack, int *stack_size) {
+  int item = stack[0];
+  for (int i = 0; i < *stack_size; ++i) stack[i] = stack[i + 1];
+  --*stack_size;
+
+  return item;
+}
+
+static INLINE int stack_pop_end(int *stack, int *stack_size) {
+  int item = stack[*stack_size - 1];
+  stack[*stack_size - 1] = -1;
+  --*stack_size;
+
+  return item;
+}
+
+static INLINE void stack_reset(int *stack, int *stack_size) {
+  for (int i = 0; i < *stack_size; ++i) stack[i] = INVALID_IDX;
+  *stack_size = 0;
+}
+
 // av1 uses 10,000,000 ticks/second as time stamp
 #define TICKS_PER_SEC 10000000LL