Refactor refresh_frame_flags/refresh_frame_mask

* Introduce a new finalize_encoded_frame() function which is called
  after encoding a frame but before packing the bitstream.  This will
  take care of a few things which are currently inside
  av1_pack_bitstream but aren't anything to do with actually writing out
  the bitstream.
* Move get_refresh_mask() from bitstream.c to encoder.c, rename it to
  get_refresh_frame_flags(), call it from finalize_encoded_frame()
  instead of write_uncompressed_header().
* Merge cpi->refresh_frame_mask in the encoder and
  pbi->refresh_frame_flags in the decoder to the common variable
  cm->current_frame.refresh_frame_flags
* Clean-up get_refresh_frame_flags()
* Clean-up some of write_uncompressed_header()

This forms part of wider restructuring and refactoring in order to
achieve a clean API separation at the entry to the low-level encoder.

BUG=aomedia:2244

Change-Id: I0e3a12fa3cfa986164512a41e7aeaf3130929e65
diff --git a/av1/av1_dx_iface.c b/av1/av1_dx_iface.c
index d3ed571..227a0f6 100644
--- a/av1/av1_dx_iface.c
+++ b/av1/av1_dx_iface.c
@@ -908,7 +908,8 @@
       AVxWorker *const worker = ctx->frame_workers;
       FrameWorkerData *const frame_worker_data =
           (FrameWorkerData *)worker->data1;
-      *update_info = frame_worker_data->pbi->refresh_frame_flags;
+      *update_info =
+          frame_worker_data->pbi->common.current_frame.refresh_frame_flags;
       return AOM_CODEC_OK;
     } else {
       return AOM_CODEC_ERROR;
diff --git a/av1/common/onyxc_int.h b/av1/common/onyxc_int.h
index 8773a49..c114148 100644
--- a/av1/common/onyxc_int.h
+++ b/av1/common/onyxc_int.h
@@ -315,6 +315,7 @@
   unsigned int order_hint;
   unsigned int frame_number;
   SkipModeInfo skip_mode_info;
+  int refresh_frame_flags;  // Which ref frames are overwritten by this frame
 } CurrentFrame;
 
 typedef struct AV1Common {
diff --git a/av1/decoder/decodeframe.c b/av1/decoder/decodeframe.c
index 802c2eb..cb9cad8 100644
--- a/av1/decoder/decodeframe.c
+++ b/av1/decoder/decodeframe.c
@@ -4696,7 +4696,7 @@
   // frame buffer index in cm->next_ref_frame_map, we need to increase the
   // frame buffer's ref_count.
   int ref_index = 0;
-  for (int mask = pbi->refresh_frame_flags; mask; mask >>= 1) {
+  for (int mask = cm->current_frame.refresh_frame_flags; mask; mask >>= 1) {
     if (mask & 1) {
       cm->next_ref_frame_map[ref_index] = cm->cur_frame;
     } else {
@@ -4724,7 +4724,7 @@
 
   cm->current_frame.frame_type = KEY_FRAME;
 
-  pbi->refresh_frame_flags = (1 << REF_FRAMES) - 1;
+  cm->current_frame.refresh_frame_flags = (1 << REF_FRAMES) - 1;
 
   for (int i = 0; i < INTER_REFS_PER_FRAME; ++i) {
     cm->remapped_ref_idx[i] = INVALID_IDX;
@@ -4741,7 +4741,7 @@
        Note that the displayed frame be valid for referencing
        in order to have been selected.
     */
-    int refresh_frame_flags = pbi->refresh_frame_flags;
+    int refresh_frame_flags = cm->current_frame.refresh_frame_flags;
     int display_frame_id = cm->ref_frame_id[existing_frame_idx];
     for (int i = 0; i < REF_FRAMES; i++) {
       if ((refresh_frame_flags >> i) & 1) {
@@ -4870,7 +4870,7 @@
       if (cm->reset_decoder_state) {
         show_existing_frame_reset(pbi, existing_frame_idx);
       } else {
-        pbi->refresh_frame_flags = 0;
+        current_frame->refresh_frame_flags = 0;
       }
 
       return 0;
@@ -5015,10 +5015,11 @@
     }
   }
   if (current_frame->frame_type == KEY_FRAME) {
-    if (!cm->show_frame)  // unshown keyframe (forward keyframe)
-      pbi->refresh_frame_flags = aom_rb_read_literal(rb, REF_FRAMES);
-    else  // shown keyframe
-      pbi->refresh_frame_flags = (1 << REF_FRAMES) - 1;
+    if (!cm->show_frame) {  // unshown keyframe (forward keyframe)
+      current_frame->refresh_frame_flags = aom_rb_read_literal(rb, REF_FRAMES);
+    } else {  // shown keyframe
+      current_frame->refresh_frame_flags = (1 << REF_FRAMES) - 1;
+    }
 
     for (int i = 0; i < INTER_REFS_PER_FRAME; ++i) {
       cm->remapped_ref_idx[i] = INVALID_IDX;
@@ -5029,8 +5030,8 @@
     }
   } else {
     if (current_frame->frame_type == INTRA_ONLY_FRAME) {
-      pbi->refresh_frame_flags = aom_rb_read_literal(rb, REF_FRAMES);
-      if (pbi->refresh_frame_flags == 0xFF) {
+      current_frame->refresh_frame_flags = aom_rb_read_literal(rb, REF_FRAMES);
+      if (current_frame->refresh_frame_flags == 0xFF) {
         aom_internal_error(&cm->error, AOM_CODEC_UNSUP_BITSTREAM,
                            "Intra only frames cannot have refresh flags 0xFF");
       }
@@ -5039,12 +5040,12 @@
         pbi->need_resync = 0;
       }
     } else if (pbi->need_resync != 1) { /* Skip if need resync */
-      pbi->refresh_frame_flags =
+      current_frame->refresh_frame_flags =
           frame_is_sframe(cm) ? 0xFF : aom_rb_read_literal(rb, REF_FRAMES);
     }
   }
 
-  if (!frame_is_intra_only(cm) || pbi->refresh_frame_flags != 0xFF) {
+  if (!frame_is_intra_only(cm) || current_frame->refresh_frame_flags != 0xFF) {
     // Read all ref frame order hints if error_resilient_mode == 1
     if (cm->error_resilient_mode &&
         seq_params->order_hint_info.enable_order_hint) {
@@ -5229,7 +5230,7 @@
   if (seq_params->frame_id_numbers_present_flag) {
     /* If bitmask is set, update reference frame id values and
        mark frames as valid for reference */
-    int refresh_frame_flags = pbi->refresh_frame_flags;
+    int refresh_frame_flags = current_frame->refresh_frame_flags;
     for (int i = 0; i < REF_FRAMES; i++) {
       if ((refresh_frame_flags >> i) & 1) {
         cm->ref_frame_id[i] = cm->current_frame_id;
diff --git a/av1/decoder/decoder.c b/av1/decoder/decoder.c
index 082e9ed..31edd1d 100644
--- a/av1/decoder/decoder.c
+++ b/av1/decoder/decoder.c
@@ -358,14 +358,15 @@
     if (!pbi->camera_frame_header_ready) {
       // If we are not holding reference buffers in cm->next_ref_frame_map,
       // assert that the following two for loops are no-ops.
-      assert(IMPLIES(!pbi->hold_ref_buf, pbi->refresh_frame_flags == 0));
+      assert(IMPLIES(!pbi->hold_ref_buf,
+                     cm->current_frame.refresh_frame_flags == 0));
       assert(IMPLIES(!pbi->hold_ref_buf,
                      cm->show_existing_frame && !cm->reset_decoder_state));
 
       // The following two for loops need to release the reference stored in
       // cm->ref_frame_map[ref_index] before transferring the reference stored
       // in cm->next_ref_frame_map[ref_index] to cm->ref_frame_map[ref_index].
-      for (mask = pbi->refresh_frame_flags; mask; mask >>= 1) {
+      for (mask = cm->current_frame.refresh_frame_flags; mask; mask >>= 1) {
         decrease_ref_count(cm->ref_frame_map[ref_index], pool);
         cm->ref_frame_map[ref_index] = cm->next_ref_frame_map[ref_index];
         cm->next_ref_frame_map[ref_index] = NULL;
diff --git a/av1/decoder/decoder.h b/av1/decoder/decoder.h
index 72e117c..885f9d8 100644
--- a/av1/decoder/decoder.h
+++ b/av1/decoder/decoder.h
@@ -163,8 +163,6 @@
 
   DECLARE_ALIGNED(32, AV1_COMMON, common);
 
-  int refresh_frame_flags;
-
   AVxWorker lf_worker;
   AV1LfSync lf_row_sync;
   AV1LrSync lr_row_sync;
diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c
index dd56d1e..1e6dd16 100644
--- a/av1/encoder/bitstream.c
+++ b/av1/encoder/bitstream.c
@@ -2190,65 +2190,6 @@
   }
 }
 
-static int get_refresh_mask(AV1_COMP *cpi) {
-  const AV1_COMMON *const cm = &cpi->common;
-
-  if ((cm->current_frame.frame_type == KEY_FRAME && cm->show_frame) ||
-      frame_is_sframe(cm))
-    return 0xFF;
-
-  int refresh_mask = 0;
-
-  // NOTE(zoeliu): When LAST_FRAME is to get refreshed, the decoder will be
-  // notified to get LAST3_FRAME refreshed and then the virtual indexes for all
-  // the 3 LAST reference frames will be updated accordingly, i.e.:
-  // (1) The original virtual index for LAST3_FRAME will become the new virtual
-  //     index for LAST_FRAME; and
-  // (2) The original virtual indexes for LAST_FRAME and LAST2_FRAME will be
-  //     shifted and become the new virtual indexes for LAST2_FRAME and
-  //     LAST3_FRAME.
-  refresh_mask |=
-      (cpi->refresh_last_frame << get_ref_frame_map_idx(cm, LAST3_FRAME));
-
-#if USE_SYMM_MULTI_LAYER
-  const int bwd_ref_frame =
-      (cpi->new_bwdref_update_rule == 1) ? EXTREF_FRAME : BWDREF_FRAME;
-#else
-  const int bwd_ref_frame = BWDREF_FRAME;
-#endif
-  refresh_mask |=
-      (cpi->refresh_bwd_ref_frame << get_ref_frame_map_idx(cm, bwd_ref_frame));
-
-  refresh_mask |=
-      (cpi->refresh_alt2_ref_frame << get_ref_frame_map_idx(cm, ALTREF2_FRAME));
-
-  if (av1_preserve_existing_gf(cpi)) {
-    // We have decided to preserve the previously existing golden frame as our
-    // new ARF frame. However, in the short term we leave it in the GF slot and,
-    // if we're updating the GF with the current decoded frame, we save it
-    // instead to the ARF slot.
-    // Later, in the function av1_encoder.c:av1_update_reference_frames() we
-    // will swap gld_fb_idx and alt_fb_idx to achieve our objective. We do it
-    // there so that it can be done outside of the recode loop.
-    // Note: This is highly specific to the use of ARF as a forward reference,
-    // and this needs to be generalized as other uses are implemented
-    // (like RTC/temporal scalability).
-
-    if (cpi->preserve_arf_as_gld) {
-      return refresh_mask;
-    } else {
-      return refresh_mask | (cpi->refresh_golden_frame
-                             << get_ref_frame_map_idx(cm, ALTREF_FRAME));
-    }
-  } else {
-    const int arf_idx = get_ref_frame_map_idx(cm, ALTREF_FRAME);
-    return refresh_mask |
-           (cpi->refresh_golden_frame
-            << get_ref_frame_map_idx(cm, GOLDEN_FRAME)) |
-           (cpi->refresh_alt_ref_frame << arf_idx);
-  }
-}
-
 static INLINE int find_identical_tile(
     const int tile_row, const int tile_col,
     TileBufferEnc (*const tile_buffers)[MAX_TILE_COLS]) {
@@ -3018,63 +2959,33 @@
       }
     }
   }
-  cpi->refresh_frame_mask = get_refresh_mask(cpi);
-  if (current_frame->frame_type == KEY_FRAME) {
-    if (!cm->show_frame) {  // unshown keyframe (forward keyframe)
-      aom_wb_write_literal(wb, cpi->refresh_frame_mask, REF_FRAMES);
-    } else {
-      assert(cpi->refresh_frame_mask == 0xFF);
-    }
-  } else {
-    if (current_frame->frame_type == INTRA_ONLY_FRAME) {
-      assert(cpi->refresh_frame_mask != 0xFF);
-      int updated_fb = -1;
-      for (int i = 0; i < REF_FRAMES; i++) {
-        // If more than one frame is refreshed, it doesn't matter which one
-        // we pick, so pick the first.
-        if (cpi->refresh_frame_mask & (1 << i)) {
-          updated_fb = i;
-          break;
-        }
-      }
-      assert(updated_fb >= 0);
-      cm->fb_of_context_type[cm->frame_context_idx] = updated_fb;
-      aom_wb_write_literal(wb, cpi->refresh_frame_mask, REF_FRAMES);
-    } else if (current_frame->frame_type == INTER_FRAME ||
-               frame_is_sframe(cm)) {
-      if (current_frame->frame_type == INTER_FRAME) {
-        aom_wb_write_literal(wb, cpi->refresh_frame_mask, REF_FRAMES);
-      } else {
-        assert(frame_is_sframe(cm) && cpi->refresh_frame_mask == 0xFF);
-      }
-      int updated_fb = -1;
-      for (int i = 0; i < REF_FRAMES; i++) {
-        // If more than one frame is refreshed, it doesn't matter which one
-        // we pick, so pick the first.
-        if (cpi->refresh_frame_mask & (1 << i)) {
-          updated_fb = i;
-          break;
-        }
-      }
-      // large scale tile sometimes won't refresh any fbs
-      if (updated_fb >= 0) {
-        cm->fb_of_context_type[cm->frame_context_idx] = updated_fb;
+
+  // Shown keyframes and switch-frames automatically refreshes all reference
+  // frames.  For all other frame types, we need to write refresh_frame_flags.
+  if ((current_frame->frame_type == KEY_FRAME && !cm->show_frame) ||
+      current_frame->frame_type == INTER_FRAME ||
+      current_frame->frame_type == INTRA_ONLY_FRAME)
+    aom_wb_write_literal(wb, current_frame->refresh_frame_flags, REF_FRAMES);
+
+  // For non-keyframes, we need to update the buffer of reference frame ids.
+  // If more than one frame is refreshed, it doesn't matter which one we pick,
+  // so pick the first.  LST sometimes doesn't refresh any: this is ok
+  if (current_frame->frame_type != KEY_FRAME) {
+    for (int i = 0; i < REF_FRAMES; i++) {
+      if (current_frame->refresh_frame_flags & (1 << i)) {
+        cm->fb_of_context_type[cm->frame_context_idx] = i;
+        break;
       }
     }
   }
 
-  if (!frame_is_intra_only(cm) || cpi->refresh_frame_mask != 0xFF) {
+  if (!frame_is_intra_only(cm) || current_frame->refresh_frame_flags != 0xff) {
     // Write all ref frame order hints if error_resilient_mode == 1
     if (cm->error_resilient_mode &&
         seq_params->order_hint_info.enable_order_hint) {
       for (int ref_idx = 0; ref_idx < REF_FRAMES; ref_idx++) {
-        // Get buffer index
-        const RefCntBuffer *buf = cm->ref_frame_map[ref_idx];
-        assert(buf != NULL);
-
-        // Write order hint to bit stream
         aom_wb_write_literal(
-            wb, buf->order_hint,
+            wb, cm->ref_frame_map[ref_idx]->order_hint,
             seq_params->order_hint_info.order_hint_bits_minus_1 + 1);
       }
     }
diff --git a/av1/encoder/bitstream.h b/av1/encoder/bitstream.h
index 465ccae..9f9166a 100644
--- a/av1/encoder/bitstream.h
+++ b/av1/encoder/bitstream.h
@@ -35,7 +35,7 @@
 
 int av1_pack_bitstream(AV1_COMP *const cpi, uint8_t *dest, size_t *size);
 
-static INLINE int av1_preserve_existing_gf(AV1_COMP *cpi) {
+static INLINE int av1_preserve_existing_gf(const AV1_COMP *const cpi) {
   // Do not swap gf and arf indices for internal overlay frames
   return cpi->rc.is_src_frame_alt_ref && !cpi->rc.is_src_frame_ext_arf;
 }
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index 708cc34..c3f6917 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -4522,6 +4522,72 @@
   return AOM_CODEC_OK;
 }
 
+static int get_refresh_frame_flags(const AV1_COMP *const cpi) {
+  const AV1_COMMON *const cm = &cpi->common;
+
+  // Switch frames and shown key-frames overwrite all reference slots
+  if ((cm->current_frame.frame_type == KEY_FRAME && cm->show_frame) ||
+      frame_is_sframe(cm))
+    return 0xFF;
+
+  int refresh_mask = 0;
+
+  // NOTE(zoeliu): When LAST_FRAME is to get refreshed, the decoder will be
+  // notified to get LAST3_FRAME refreshed and then the virtual indexes for all
+  // the 3 LAST reference frames will be updated accordingly, i.e.:
+  // (1) The original virtual index for LAST3_FRAME will become the new virtual
+  //     index for LAST_FRAME; and
+  // (2) The original virtual indexes for LAST_FRAME and LAST2_FRAME will be
+  //     shifted and become the new virtual indexes for LAST2_FRAME and
+  //     LAST3_FRAME.
+  refresh_mask |=
+      (cpi->refresh_last_frame << get_ref_frame_map_idx(cm, LAST3_FRAME));
+
+#if USE_SYMM_MULTI_LAYER
+  const int bwd_ref_frame =
+      (cpi->new_bwdref_update_rule == 1) ? EXTREF_FRAME : BWDREF_FRAME;
+#else
+  const int bwd_ref_frame = BWDREF_FRAME;
+#endif
+  refresh_mask |=
+      (cpi->refresh_bwd_ref_frame << get_ref_frame_map_idx(cm, bwd_ref_frame));
+
+  refresh_mask |=
+      (cpi->refresh_alt2_ref_frame << get_ref_frame_map_idx(cm, ALTREF2_FRAME));
+
+  if (av1_preserve_existing_gf(cpi)) {
+    // We have decided to preserve the previously existing golden frame as our
+    // new ARF frame. However, in the short term we leave it in the GF slot and,
+    // if we're updating the GF with the current decoded frame, we save it
+    // instead to the ARF slot.
+    // Later, in the function av1_encoder.c:av1_update_reference_frames() we
+    // will swap gld_fb_idx and alt_fb_idx to achieve our objective. We do it
+    // there so that it can be done outside of the recode loop.
+    // Note: This is highly specific to the use of ARF as a forward reference,
+    // and this needs to be generalized as other uses are implemented
+    // (like RTC/temporal scalability).
+
+    if (!cpi->preserve_arf_as_gld) {
+      refresh_mask |= (cpi->refresh_golden_frame
+                       << get_ref_frame_map_idx(cm, ALTREF_FRAME));
+    }
+  } else {
+    refresh_mask |=
+        (cpi->refresh_golden_frame << get_ref_frame_map_idx(cm, GOLDEN_FRAME));
+    refresh_mask |=
+        (cpi->refresh_alt_ref_frame << get_ref_frame_map_idx(cm, ALTREF_FRAME));
+  }
+  return refresh_mask;
+}
+
+static void finalize_encoded_frame(AV1_COMP *const cpi) {
+  AV1_COMMON *const cm = &cpi->common;
+
+  // This bitfield indicates which reference frame slots will be overwritten by
+  // the current frame
+  cm->current_frame.refresh_frame_flags = get_refresh_frame_flags(cpi);
+}
+
 static int encode_with_recode_loop(AV1_COMP *cpi, size_t *size, uint8_t *dest) {
   AV1_COMMON *const cm = &cpi->common;
   RATE_CONTROL *const rc = &cpi->rc;
@@ -4632,6 +4698,7 @@
     if (cpi->sf.recode_loop >= ALLOW_RECODE_KFARFGF) {
       restore_coding_context(cpi);
 
+      finalize_encoded_frame(cpi);
       if (av1_pack_bitstream(cpi, dest, size) != AOM_CODEC_OK)
         return AOM_CODEC_ERROR;
 
@@ -5054,6 +5121,7 @@
 
     restore_coding_context(cpi);
 
+    finalize_encoded_frame(cpi);
     // Build the bitstream
     if (av1_pack_bitstream(cpi, dest, size) != AOM_CODEC_OK)
       return AOM_CODEC_ERROR;
@@ -5266,6 +5334,7 @@
   aom_write_one_yuv_frame(cm, &cm->cur_frame->buf);
 #endif
 
+  finalize_encoded_frame(cpi);
   // Build the bitstream
   if (av1_pack_bitstream(cpi, dest, size) != AOM_CODEC_OK)
     return AOM_CODEC_ERROR;
@@ -5274,11 +5343,10 @@
 
   if (skip_adapt) return AOM_CODEC_OK;
 
+  // Update reference frame ids for reference frames this frame will overwrite
   if (seq_params->frame_id_numbers_present_flag) {
-    int i;
-    // Update reference frame id values based on the value of refresh_frame_mask
-    for (i = 0; i < REF_FRAMES; i++) {
-      if ((cpi->refresh_frame_mask >> i) & 1) {
+    for (int i = 0; i < REF_FRAMES; i++) {
+      if ((current_frame->refresh_frame_flags >> i) & 1) {
         cm->ref_frame_id[i] = cm->current_frame_id;
       }
     }
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h
index 6945cd3..29cb51a 100644
--- a/av1/encoder/encoder.h
+++ b/av1/encoder/encoder.h
@@ -798,7 +798,6 @@
   int num_workers;
   AVxWorker *workers;
   struct EncWorkerData *tile_thr_data;
-  int refresh_frame_mask;
   int existing_fb_idx_to_show;
   int is_arf_filter_off[MAX_EXT_ARFS + 1];
   int num_extra_arfs;