Correct reference updates in error resilient mode

Error resilient mode disables show_existing_frame,
but it is still necessary to keep track of which frames
would have originally been show_existing in order to properly
update the gf_group index and reference buffers.

BUG=aomedia:2021
BUG=aomedia:1994

Change-Id: Idc1f3038f313fd6c1efb90c992780a17a1423f8e
diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c
index 2070755..dab5184 100644
--- a/av1/encoder/bitstream.c
+++ b/av1/encoder/bitstream.c
@@ -2954,7 +2954,7 @@
     assert(cm->frame_type == KEY_FRAME);
   }
   if (!seq_params->reduced_still_picture_hdr) {
-    if (cm->show_existing_frame) {
+    if (encode_show_existing_frame(cm)) {
       RefCntBuffer *const frame_bufs = cm->buffer_pool->frame_bufs;
       const int frame_to_show = cm->ref_frame_map[cpi->existing_fb_idx_to_show];
 
@@ -3990,7 +3990,8 @@
     data += obu_header_size + obu_payload_size + length_field_size;
   }
 
-  const int write_frame_header = (cm->num_tg > 1 || cm->show_existing_frame);
+  const int write_frame_header =
+      (cm->num_tg > 1 || encode_show_existing_frame(cm));
   struct aom_write_bit_buffer saved_wb;
   if (write_frame_header) {
     // Write Frame Header OBU.
@@ -4017,7 +4018,7 @@
     saved_wb.bit_buffer += length_field_size;
   }
 
-  if (cm->show_existing_frame) {
+  if (encode_show_existing_frame(cm)) {
     data_size = 0;
   } else {
     //  Each tile group obu will be preceded by 4-byte size of the tile group
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index 849086a..f4af986 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -3424,6 +3424,21 @@
   //       for the purpose to verify no mismatch between encoder and decoder.
   if (cm->show_frame) cpi->last_show_frame_buf_idx = cm->new_fb_idx;
 
+  // In the case of show_existing frame, we will not send fresh flag
+  // to decoder. Any change in the reference frame buffer can be done by
+  // switching the virtual indices.
+  if (cm->show_existing_frame) {
+    cpi->refresh_last_frame = 0;
+    cpi->refresh_golden_frame = 0;
+    cpi->refresh_bwd_ref_frame = 0;
+    cpi->refresh_alt2_ref_frame = 0;
+    cpi->refresh_alt_ref_frame = 0;
+
+    cpi->rc.is_bwd_ref_frame = 0;
+    cpi->rc.is_last_bipred_frame = 0;
+    cpi->rc.is_bipred_frame = 0;
+  }
+
 #if USE_GF16_MULTI_LAYER
   if (cpi->rc.baseline_gf_interval == 16) {
     update_reference_frames_gf16(cpi);
@@ -4914,7 +4929,7 @@
   if (cm->current_video_frame > 0)
     cpi->ref_frame_flags = get_ref_frame_flags(cpi);
 
-  if (cm->show_existing_frame) {
+  if (encode_show_existing_frame(cm)) {
     // NOTE(zoeliu): In BIDIR_PRED, the existing frame to show is the current
     //               BWDREF_FRAME in the reference frame buffer.
     if (cm->frame_type == KEY_FRAME) {
@@ -4925,20 +4940,6 @@
     cm->show_frame = 1;
     cpi->frame_flags = *frame_flags;
 
-    // In the case of show_existing frame, we will not send fresh flag
-    // to decoder. Any change in the reference frame buffer can be done by
-    // switching the virtual indices.
-
-    cpi->refresh_last_frame = 0;
-    cpi->refresh_golden_frame = 0;
-    cpi->refresh_bwd_ref_frame = 0;
-    cpi->refresh_alt2_ref_frame = 0;
-    cpi->refresh_alt_ref_frame = 0;
-
-    cpi->rc.is_bwd_ref_frame = 0;
-    cpi->rc.is_last_bipred_frame = 0;
-    cpi->rc.is_bipred_frame = 0;
-
     restore_coding_context(cpi);
 
     // Build the bitstream
@@ -5320,11 +5321,17 @@
 #endif
 
   // Do not do post-encoding update for those frames that do not have a spot
-  // in
-  // a gf group, but note that an OVERLAY frame always has a spot in a gf
-  // group,
-  // even when show_existing_frame is used.
-  if (!cpi->common.show_existing_frame || cpi->rc.is_src_frame_alt_ref) {
+  // in a gf group, but note that an OVERLAY frame always has a spot in a gf
+  // group, even when show_existing_frame is used.
+  // Error resilient frames cannot be true show_existing_frames, as this
+  // would require displaying a frame that was encoded in the past.
+  // In this case, any frame that would traditionally be a
+  // show_existing_frame will need to be re-encoded at display time,
+  // making it necessary to do this postencode_update. If error resilient mode
+  // is disabled, a show_existing_frame should never enter this function unless
+  // it was the source of an altref.
+  if (cpi->common.error_resilient_mode || !cpi->common.show_existing_frame ||
+      cpi->rc.is_src_frame_alt_ref) {
     av1_twopass_postencode_update(cpi);
   }
   check_show_existing_frame(cpi);
@@ -5850,16 +5857,15 @@
   struct lookahead_entry *lookahead_src = NULL;
   if (cm->current_video_frame > 0)
     lookahead_src = av1_lookahead_peek(cpi->lookahead, 0);
-  if (lookahead_src != NULL &&
-      ((cpi->oxcf.error_resilient_mode |
-        ((lookahead_src->flags & AOM_EFLAG_ERROR_RESILIENT) != 0)) ||
-       (cpi->oxcf.s_frame_mode |
-        ((lookahead_src->flags & AOM_EFLAG_SET_S_FRAME) != 0))) &&
-      !(rc->frames_to_key == 0 || (cpi->frame_flags & FRAMEFLAGS_KEY))) {
-    cm->show_existing_frame = 0;
-  }
+  int use_show_existing =
+      !(lookahead_src != NULL &&
+        ((cpi->oxcf.error_resilient_mode |
+          ((lookahead_src->flags & AOM_EFLAG_ERROR_RESILIENT) != 0)) ||
+         (cpi->oxcf.s_frame_mode |
+          ((lookahead_src->flags & AOM_EFLAG_SET_S_FRAME) != 0))) &&
+        !(rc->frames_to_key == 0 || (cpi->frame_flags & FRAMEFLAGS_KEY)));
 
-  if (oxcf->pass == 2 && cm->show_existing_frame) {
+  if (oxcf->pass == 2 && cm->show_existing_frame && use_show_existing) {
     // Manage the source buffer and flush out the source frame that has been
     // coded already; Also get prepared for PSNR calculation if needed.
     if ((source = av1_lookahead_pop(cpi->lookahead, flush)) == NULL) {
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h
index 6cb531c..86101b1 100644
--- a/av1/encoder/encoder.h
+++ b/av1/encoder/encoder.h
@@ -887,6 +887,14 @@
   return !av1_superres_scaled(cm) && av1_resize_scaled(cm);
 }
 
+// Don't allow a show_existing_frame to coincide with an error resilient
+// frame. An exception can be made for a forward keyframe since it has no
+// previous dependencies.
+static INLINE int encode_show_existing_frame(const AV1_COMMON *cm) {
+  return cm->show_existing_frame &&
+         (!cm->error_resilient_mode || cm->frame_type == KEY_FRAME);
+}
+
 #ifdef __cplusplus
 }  // extern "C"
 #endif
diff --git a/av1/encoder/firstpass.c b/av1/encoder/firstpass.c
index fdba252..f73aebe 100644
--- a/av1/encoder/firstpass.c
+++ b/av1/encoder/firstpass.c
@@ -4025,6 +4025,9 @@
   RATE_CONTROL *const rc = &cpi->rc;
   const int bits_used = rc->base_frame_target;
 
+  assert(IMPLIES(cpi->common.show_existing_frame && !rc->is_src_frame_alt_ref,
+                 cpi->common.error_resilient_mode));
+
   // VBR correction is done through rc->vbr_bits_off_target. Based on the
   // sign of this value, a limited % adjustment is made to the target rate
   // of subsequent frames, to try and push it back towards 0. This method
@@ -4048,8 +4051,12 @@
   }
   twopass->kf_group_bits = AOMMAX(twopass->kf_group_bits, 0);
 
-  // Increment the gf group index ready for the next frame.
-  ++twopass->gf_group.index;
+  // Increment the gf group index ready for the next frame. If this is
+  // a show_existing_frame with a source other than altref, the index
+  // was incremented when it was originally encoded.
+  if (!cpi->common.show_existing_frame || rc->is_src_frame_alt_ref) {
+    ++twopass->gf_group.index;
+  }
 
   // If the rate control is drifting consider adjustment to min or maxq.
   if ((cpi->oxcf.rc_mode != AOM_Q) &&