diff --git a/vp10/encoder/bitstream.c b/vp10/encoder/bitstream.c
index 81d8991f66e6144acbb7fad91246d67d7cf3da5f..9dc283a2f992a87aeadea2967f5be26fa516d0d1 100644
--- a/vp10/encoder/bitstream.c
+++ b/vp10/encoder/bitstream.c
@@ -2649,6 +2649,7 @@ static void write_tile_info(const VP10_COMMON *const cm,
   if (cm->log2_tile_rows != 0) vpx_wb_write_bit(wb, cm->log2_tile_rows != 1);
 #endif  // CONFIG_EXT_TILE
 }
+
 static int get_refresh_mask(VP10_COMP *cpi) {
   int refresh_mask = 0;
 
@@ -2663,8 +2664,12 @@ static int get_refresh_mask(VP10_COMP *cpi) {
   //     LAST3_FRAME.
   refresh_mask |=
       (cpi->refresh_last_frame << cpi->lst_fb_idxes[LAST_REF_FRAMES - 1]);
-
-  refresh_mask |= (cpi->refresh_bwd_ref_frame << cpi->bwd_fb_idx);
+  if (cpi->rc.is_bwd_ref_frame && cpi->num_extra_arfs) {
+    // We have swapped the virtual indices
+    refresh_mask |= (cpi->refresh_bwd_ref_frame << cpi->arf_map[0]);
+  } else {
+    refresh_mask |= (cpi->refresh_bwd_ref_frame << cpi->bwd_fb_idx);
+  }
 #else
   refresh_mask |= (cpi->refresh_last_frame << cpi->lst_fb_idx);
 #endif  // CONFIG_EXT_REFS
@@ -2683,10 +2688,15 @@ static int get_refresh_mask(VP10_COMP *cpi) {
     return refresh_mask | (cpi->refresh_golden_frame << cpi->alt_fb_idx);
   } else {
     int arf_idx = cpi->alt_fb_idx;
+#if CONFIG_EXT_REFS
+    const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
+    arf_idx = cpi->arf_map[gf_group->arf_update_idx[gf_group->index]];
+#else
     if ((cpi->oxcf.pass == 2) && cpi->multi_arf_allowed) {
       const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
       arf_idx = gf_group->arf_update_idx[gf_group->index];
     }
+#endif  // CONFIG_EXT_REFS
     return refresh_mask | (cpi->refresh_golden_frame << cpi->gld_fb_idx) |
            (cpi->refresh_alt_ref_frame << arf_idx);
   }
diff --git a/vp10/encoder/bitstream.h b/vp10/encoder/bitstream.h
index 615c4e482dcbc9a481a6dfd0cc6447dd3d35337c..5b6d8f0372b0a0b74158a00a74d509702d4d2714 100644
--- a/vp10/encoder/bitstream.h
+++ b/vp10/encoder/bitstream.h
@@ -23,11 +23,13 @@ void vp10_encode_token_init(void);
 
 static INLINE int vp10_preserve_existing_gf(VP10_COMP *cpi) {
 #if CONFIG_EXT_REFS
-  return !cpi->multi_arf_allowed && cpi->rc.is_src_frame_alt_ref;
+  // Do not swap gf and arf indices for internal overlay frames
+  return !cpi->multi_arf_allowed &&
+         cpi->rc.is_src_frame_alt_ref && !cpi->rc.is_src_frame_ext_arf;
 #else
   return !cpi->multi_arf_allowed && cpi->refresh_golden_frame &&
          cpi->rc.is_src_frame_alt_ref;
-#endif
+#endif  // CONFIG_EXT_REFS
 }
 
 #ifdef __cplusplus
diff --git a/vp10/encoder/encodeframe.c b/vp10/encoder/encodeframe.c
index 25e8ac5168fb1f09450a8f6e349f28c479e20a56..d1f019a7d70bf44629556342527a09ecca42c95a 100644
--- a/vp10/encoder/encodeframe.c
+++ b/vp10/encoder/encodeframe.c
@@ -4289,7 +4289,13 @@ static void reset_skip_tx_size(VP10_COMMON *cm, TX_SIZE max_tx_size) {
 static MV_REFERENCE_FRAME get_frame_type(const VP10_COMP *cpi) {
   if (frame_is_intra_only(&cpi->common))
     return INTRA_FRAME;
+#if CONFIG_EXT_REFS
+  // We will not update the golden frame with an internal overlay frame
+  else if ((cpi->rc.is_src_frame_alt_ref && cpi->refresh_golden_frame) ||
+      cpi->rc.is_src_frame_ext_arf)
+#else
   else if (cpi->rc.is_src_frame_alt_ref && cpi->refresh_golden_frame)
+#endif
     return ALTREF_FRAME;
   else if (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)
     return GOLDEN_FRAME;
diff --git a/vp10/encoder/encoder.c b/vp10/encoder/encoder.c
index 823c8610aaa0848b5051eaa2d871d412c22f6576..32a6ae37bbe55ecf2cb1527048f51e2399461b10 100644
--- a/vp10/encoder/encoder.c
+++ b/vp10/encoder/encoder.c
@@ -79,7 +79,6 @@
                                        // now so that HIGH_PRECISION is always
                                        // chosen.
 // #define OUTPUT_YUV_REC
-
 #ifdef OUTPUT_YUV_DENOISED
 FILE *yuv_denoised_file = NULL;
 #endif
@@ -897,6 +896,8 @@ static void init_buffer_indices(VP10_COMP *cpi) {
   cpi->gld_fb_idx = LAST_REF_FRAMES;
   cpi->bwd_fb_idx = LAST_REF_FRAMES + 1;
   cpi->alt_fb_idx = LAST_REF_FRAMES + 2;
+  for (fb_idx = 0; fb_idx < MAX_EXT_ARFS + 1; ++fb_idx)
+    cpi->arf_map[fb_idx] = LAST_REF_FRAMES + 2 + fb_idx;
 #else
   cpi->lst_fb_idx = 0;
   cpi->gld_fb_idx = 1;
@@ -2726,7 +2727,7 @@ static void check_show_existing_frame(VP10_COMP *cpi) {
   VP10_COMMON *const cm = &cpi->common;
   const FRAME_UPDATE_TYPE next_frame_update_type =
       gf_group->update_type[gf_group->index];
-
+  const int which_arf = gf_group->arf_update_idx[gf_group->index];
   if (cpi->rc.is_last_bipred_frame) {
     // NOTE(zoeliu): If the current frame is a last bi-predictive frame, it is
     //               needed next to show the BWDREF_FRAME, which is pointed by
@@ -2734,19 +2735,21 @@ static void check_show_existing_frame(VP10_COMP *cpi) {
     cpi->rc.is_last_bipred_frame = 0;
     cm->show_existing_frame = 1;
     cpi->existing_fb_idx_to_show = cpi->lst_fb_idxes[0];
-  } else if (next_frame_update_type == OVERLAY_UPDATE &&
-             cpi->is_arf_filter_off) {
+  } else if (cpi->is_arf_filter_off[which_arf] &&
+             (next_frame_update_type == OVERLAY_UPDATE ||
+              next_frame_update_type == INTNL_OVERLAY_UPDATE)) {
     // Other parameters related to OVERLAY_UPDATE will be taken care of
     // in vp10_rc_get_second_pass_params(cpi)
     cm->show_existing_frame = 1;
     cpi->rc.is_src_frame_alt_ref = 1;
     cpi->existing_fb_idx_to_show = cpi->alt_fb_idx;
-    cpi->is_arf_filter_off = 0;
+    cpi->is_arf_filter_off[which_arf] = 0;
   } else {
     cm->show_existing_frame = 0;
   }
+  cpi->rc.is_src_frame_ext_arf = 0;
 }
-#endif
+#endif  // CONFIG_EXT_REFS
 
 #ifdef OUTPUT_YUV_REC
 void vp10_write_one_yuv_frame(VP10_COMMON *cm, YV12_BUFFER_CONFIG *s) {
@@ -3063,6 +3066,27 @@ static void dump_ref_frame_images(VP10_COMP *cpi) {
 }
 #endif  // DUMP_REF_FRAME_IMAGES == 1
 
+#if CONFIG_EXT_REFS
+// This function is used to shift the virtual indices of last reference frames
+// as follows:
+// LAST_FRAME -> LAST2_FRAME -> LAST3_FRAME
+// when the LAST_FRAME is updated.
+static INLINE void shift_last_ref_frames(VP10_COMP *cpi) {
+  int ref_frame;
+  for (ref_frame = LAST_REF_FRAMES - 1; ref_frame > 0; --ref_frame) {
+    cpi->lst_fb_idxes[ref_frame] = cpi->lst_fb_idxes[ref_frame - 1];
+
+    // [0] is allocated to the current coded frame. The statistics for the
+    // reference frames start at [1].
+    if (!cpi->rc.is_src_frame_alt_ref) {
+      memcpy(cpi->interp_filter_selected[ref_frame + 1],
+             cpi->interp_filter_selected[ref_frame],
+             sizeof(cpi->interp_filter_selected[ref_frame]));
+    }
+  }
+}
+#endif
+
 void vp10_update_reference_frames(VP10_COMP *cpi) {
   VP10_COMMON *const cm = &cpi->common;
   BufferPool *const pool = cm->buffer_pool;
@@ -3087,10 +3111,10 @@ void vp10_update_reference_frames(VP10_COMP *cpi) {
 
       new_uidx = upsample_ref_frame(cpi, ref);
 #if CONFIG_EXT_REFS
+      assert(new_uidx != INVALID_IDX);
     }
 #endif  // CONFIG_EXT_REFS
   }
-
   // At this point the new frame has been encoded.
   // If any buffer copy / swapping is signaled it should be done here.
   if (cm->frame_type == KEY_FRAME) {
@@ -3134,23 +3158,21 @@ void vp10_update_reference_frames(VP10_COMP *cpi) {
     cpi->alt_fb_idx = cpi->gld_fb_idx;
     cpi->gld_fb_idx = tmp;
 
-// TODO(zoeliu): Do we need to copy cpi->interp_filter_selected[0] over to
-// cpi->interp_filter_selected[GOLDEN_FRAME]?
+#if CONFIG_EXT_REFS
+    // We need to modify the mapping accordingly
+    cpi->arf_map[0] = cpi->alt_fb_idx;
+#endif
+    // TODO(zoeliu): Do we need to copy cpi->interp_filter_selected[0] over to
+    // cpi->interp_filter_selected[GOLDEN_FRAME]?
 #if CONFIG_EXT_REFS
   } else if (cpi->rc.is_last_bipred_frame) {
     // Refresh the LAST_FRAME with the BWDREF_FRAME and retire the LAST3_FRAME
     // by updating the virtual indices. Note that the frame BWDREF_FRAME points
     // to now should be retired, and it should not be used before refreshed.
-    int ref_frame, tmp = cpi->lst_fb_idxes[LAST_REF_FRAMES - 1];
-    for (ref_frame = LAST_REF_FRAMES - 1; ref_frame > 0; --ref_frame) {
-      cpi->lst_fb_idxes[ref_frame] = cpi->lst_fb_idxes[ref_frame - 1];
+    int tmp = cpi->lst_fb_idxes[LAST_REF_FRAMES-1];
+
+    shift_last_ref_frames(cpi);
 
-      if (!cpi->rc.is_src_frame_alt_ref) {
-        memcpy(cpi->interp_filter_selected[ref_frame],
-               cpi->interp_filter_selected[ref_frame - 1],
-               sizeof(cpi->interp_filter_selected[ref_frame - 1]));
-      }
-    }
     cpi->lst_fb_idxes[0] = cpi->bwd_fb_idx;
     if (!cpi->rc.is_src_frame_alt_ref) {
       memcpy(cpi->interp_filter_selected[0],
@@ -3159,20 +3181,48 @@ void vp10_update_reference_frames(VP10_COMP *cpi) {
     }
     cpi->bwd_fb_idx = tmp;
 #endif     // CONFIG_EXT_REFS
+#if CONFIG_EXT_REFS
+  } else if (cpi->rc.is_src_frame_ext_arf && cm->show_existing_frame) {
+    // Deal with the special case for showing existing internal ALTREF_FRAME
+    // Refresh the LAST_FRAME with the ALTREF_FRAME and retire the LAST3_FRAME
+    // by updating the virtual indices.
+    const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
+    int which_arf = gf_group->arf_ref_idx[gf_group->index];
+    int tmp = cpi->lst_fb_idxes[LAST_REF_FRAMES-1];
+
+    shift_last_ref_frames(cpi);
+
+    cpi->lst_fb_idxes[0] = cpi->alt_fb_idx;
+    memcpy(cpi->interp_filter_selected[LAST_FRAME],
+           cpi->interp_filter_selected[ALTREF_FRAME + which_arf],
+           sizeof(cpi->interp_filter_selected[ALTREF_FRAME + which_arf]));
+
+    cpi->alt_fb_idx = tmp;
+    // We need to modify the mapping accordingly
+    cpi->arf_map[which_arf] = cpi->alt_fb_idx;
+#endif  // CONFIG_EXT_REFS
   } else { /* For non key/golden frames */
     if (cpi->refresh_alt_ref_frame) {
       int arf_idx = cpi->alt_fb_idx;
+      int which_arf = 0;
+#if CONFIG_EXT_REFS
+      if (cpi->oxcf.pass == 2) {
+        const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
+        which_arf = gf_group->arf_update_idx[gf_group->index];
+        arf_idx = cpi->arf_map[which_arf];
+      }
+#else
       if ((cpi->oxcf.pass == 2) && cpi->multi_arf_allowed) {
         const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
         arf_idx = gf_group->arf_update_idx[gf_group->index];
       }
-
+#endif  // CONFIG_EXT_REFS
       ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[arf_idx], cm->new_fb_idx);
       if (use_upsampled_ref)
         uref_cnt_fb(cpi->upsampled_ref_bufs, &cpi->upsampled_ref_idx[arf_idx],
                     new_uidx);
 
-      memcpy(cpi->interp_filter_selected[ALTREF_FRAME],
+      memcpy(cpi->interp_filter_selected[ALTREF_FRAME + which_arf],
              cpi->interp_filter_selected[0],
              sizeof(cpi->interp_filter_selected[0]));
     }
@@ -3184,18 +3234,35 @@ void vp10_update_reference_frames(VP10_COMP *cpi) {
         uref_cnt_fb(cpi->upsampled_ref_bufs,
                     &cpi->upsampled_ref_idx[cpi->gld_fb_idx], new_uidx);
 
-      if (!cpi->rc.is_src_frame_alt_ref)
+      if (!cpi->rc.is_src_frame_alt_ref) {
         memcpy(cpi->interp_filter_selected[GOLDEN_FRAME],
                cpi->interp_filter_selected[0],
                sizeof(cpi->interp_filter_selected[0]));
-      else
+      } else {
+        int which_arf = 0;
+#if CONFIG_EXT_REFS
+        if (cpi->oxcf.pass == 2) {
+          const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
+          which_arf = gf_group->arf_update_idx[gf_group->index];
+        }
+#endif  // CONFIG_EXT_REFS
         memcpy(cpi->interp_filter_selected[GOLDEN_FRAME],
-               cpi->interp_filter_selected[ALTREF_FRAME],
-               sizeof(cpi->interp_filter_selected[ALTREF_FRAME]));
+               cpi->interp_filter_selected[ALTREF_FRAME + which_arf],
+               sizeof(cpi->interp_filter_selected[ALTREF_FRAME + which_arf]));
+      }
     }
 
 #if CONFIG_EXT_REFS
     if (cpi->refresh_bwd_ref_frame) {
+      if (cpi->rc.is_bwd_ref_frame && cpi->num_extra_arfs) {
+        // We have swapped the virtual indices to allow bwd_ref_frame to use
+        // ALT0 as reference frame. We need to swap them back.
+        // NOTE: The ALT_REFs' are indexed reversely, and ALT0 refers to the
+        //       farthest ALT_REF from the first frame in the gf group.
+        int tmp = cpi->arf_map[0];
+        cpi->arf_map[0] = cpi->bwd_fb_idx;
+        cpi->bwd_fb_idx = tmp;
+      }
       ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[cpi->bwd_fb_idx],
                  cm->new_fb_idx);
       if (use_upsampled_ref)
@@ -3267,16 +3334,10 @@ void vp10_update_reference_frames(VP10_COMP *cpi) {
             &cpi->upsampled_ref_idx[cpi->lst_fb_idxes[LAST_REF_FRAMES - 1]],
             new_uidx);
 
-      tmp = cpi->lst_fb_idxes[LAST_REF_FRAMES - 1];
-      for (ref_frame = LAST_REF_FRAMES - 1; ref_frame > 0; --ref_frame) {
-        cpi->lst_fb_idxes[ref_frame] = cpi->lst_fb_idxes[ref_frame - 1];
+      tmp = cpi->lst_fb_idxes[LAST_REF_FRAMES-1];
+
+      shift_last_ref_frames(cpi);
 
-        if (!cpi->rc.is_src_frame_alt_ref) {
-          memcpy(cpi->interp_filter_selected[ref_frame],
-                 cpi->interp_filter_selected[ref_frame - 1],
-                 sizeof(cpi->interp_filter_selected[ref_frame - 1]));
-        }
-      }
       cpi->lst_fb_idxes[0] = tmp;
 
       if (!cpi->rc.is_src_frame_alt_ref) {
@@ -4272,7 +4333,8 @@ static int get_ref_frame_flags(const VP10_COMP *cpi) {
 
 #if CONFIG_EXT_REFS
   // Disable the use of BWDREF_FRAME for non-bipredictive frames.
-  if (!(cpi->rc.is_bipred_frame || cpi->rc.is_last_bipred_frame))
+  if (!(cpi->rc.is_bipred_frame || cpi->rc.is_last_bipred_frame ||
+      (cpi->rc.is_bwd_ref_frame && cpi->num_extra_arfs)))
     flags &= ~VPX_BWD_FLAG;
 #endif  // CONFIG_EXT_REFS
 
@@ -4348,7 +4410,13 @@ YV12_BUFFER_CONFIG *vp10_scale_if_required(VP10_COMMON *cm,
 static void set_arf_sign_bias(VP10_COMP *cpi) {
   VP10_COMMON *const cm = &cpi->common;
   int arf_sign_bias;
-
+#if CONFIG_EXT_REFS
+  const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
+  // The arf_sign_bias will be one for internal ARFs'
+  arf_sign_bias = cpi->rc.source_alt_ref_active &&
+                  (!cpi->refresh_alt_ref_frame ||
+                  (gf_group->rf_level[gf_group->index] == GF_ARF_LOW));
+#else
   if ((cpi->oxcf.pass == 2) && cpi->multi_arf_allowed) {
     const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
     arf_sign_bias = cpi->rc.source_alt_ref_active &&
@@ -4358,6 +4426,7 @@ static void set_arf_sign_bias(VP10_COMP *cpi) {
     arf_sign_bias =
         (cpi->rc.source_alt_ref_active && !cpi->refresh_alt_ref_frame);
   }
+#endif
   cm->ref_frame_sign_bias[ALTREF_FRAME] = arf_sign_bias;
 #if CONFIG_EXT_REFS
   cm->ref_frame_sign_bias[BWDREF_FRAME] = cm->ref_frame_sign_bias[ALTREF_FRAME];
@@ -4369,12 +4438,30 @@ static int setup_interp_filter_search_mask(VP10_COMP *cpi) {
   int ref_total[TOTAL_REFS_PER_FRAME] = { 0 };
   MV_REFERENCE_FRAME ref;
   int mask = 0;
+  int arf_idx = ALTREF_FRAME;
+
+#if CONFIG_EXT_REFS
+  // Get which arf used as ALTREF_FRAME
+  if (cpi->oxcf.pass == 2)
+    arf_idx += cpi->twopass.gf_group.arf_ref_idx[cpi->twopass.gf_group.index];
+#endif
+
   if (cpi->common.last_frame_type == KEY_FRAME || cpi->refresh_alt_ref_frame)
     return mask;
-  for (ref = LAST_FRAME; ref <= ALTREF_FRAME; ++ref)
+
+#if CONFIG_EXT_REFS
+  for (ref = LAST_FRAME; ref < ALTREF_FRAME; ++ref)
     for (ifilter = EIGHTTAP_REGULAR; ifilter < SWITCHABLE_FILTERS; ++ifilter)
       ref_total[ref] += cpi->interp_filter_selected[ref][ifilter];
 
+  for (ifilter = EIGHTTAP_REGULAR; ifilter < SWITCHABLE_FILTERS; ++ifilter)
+    ref_total[ref] += cpi->interp_filter_selected[arf_idx][ifilter];
+#else
+  for (ref = LAST_FRAME; ref <= ALTREF_FRAME; ++ref)
+      for (ifilter = EIGHTTAP_REGULAR; ifilter < SWITCHABLE_FILTERS; ++ifilter)
+        ref_total[ref] += cpi->interp_filter_selected[ref][ifilter];
+#endif
+
   for (ifilter = EIGHTTAP_REGULAR; ifilter < SWITCHABLE_FILTERS; ++ifilter) {
     if ((ref_total[LAST_FRAME] &&
          cpi->interp_filter_selected[LAST_FRAME][ifilter] == 0) &&
@@ -4395,8 +4482,8 @@ static int setup_interp_filter_search_mask(VP10_COMP *cpi) {
              ref_total[BWDREF_FRAME]) &&
 #endif  // CONFIG_EXT_REFS
         (ref_total[ALTREF_FRAME] == 0 ||
-         cpi->interp_filter_selected[ALTREF_FRAME][ifilter] * 50 <
-             ref_total[ALTREF_FRAME]))
+         cpi->interp_filter_selected[arf_idx][ifilter] * 50 <
+         ref_total[ALTREF_FRAME]))
       mask |= 1 << ifilter;
   }
   return mask;
@@ -4465,7 +4552,6 @@ static void encode_frame_to_data_rate(VP10_COMP *cpi, size_t *size,
   const VP10EncoderConfig *const oxcf = &cpi->oxcf;
   struct segmentation *const seg = &cm->seg;
   TX_SIZE t;
-
   set_ext_overrides(cpi);
   vpx_clear_system_state();
 
@@ -4484,11 +4570,14 @@ static void encode_frame_to_data_rate(VP10_COMP *cpi, size_t *size,
   if (cm->show_existing_frame) {
     // NOTE(zoeliu): In BIDIR_PRED, the existing frame to show is the current
     //               BWDREF_FRAME in the reference frame buffer.
-
     cm->frame_type = INTER_FRAME;
     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;
@@ -4953,10 +5042,16 @@ static void check_src_altref(VP10_COMP *cpi,
                              const struct lookahead_entry *source) {
   RATE_CONTROL *const rc = &cpi->rc;
 
+  // If pass == 2, the parameters set here will be reset in
+  // vp10_rc_get_second_pass_params()
+
   if (cpi->oxcf.pass == 2) {
     const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
     rc->is_src_frame_alt_ref =
-        (gf_group->update_type[gf_group->index] == OVERLAY_UPDATE);
+#if CONFIG_EXT_REFS
+      (gf_group->update_type[gf_group->index] == INTNL_OVERLAY_UPDATE) ||
+#endif
+      (gf_group->update_type[gf_group->index] == OVERLAY_UPDATE);
   } else {
     rc->is_src_frame_alt_ref =
         cpi->alt_ref_source && (source == cpi->alt_ref_source);
@@ -5143,7 +5238,6 @@ int vp10_get_compressed_data(VP10_COMP *cpi, unsigned int *frame_flags,
       return -1;
     }
     cpi->Source = &source->img;
-
     // TODO(zoeliu): To track down to determine whether it's needed to adjust
     // the frame rate.
     *time_stamp = source->ts_start;
@@ -5187,7 +5281,6 @@ int vp10_get_compressed_data(VP10_COMP *cpi, unsigned int *frame_flags,
     vpx_clear_system_state();
 
     cm->show_existing_frame = 0;
-
     return 0;
   }
 #endif  // CONFIG_EXT_REFS
@@ -5310,6 +5403,12 @@ int vp10_get_compressed_data(VP10_COMP *cpi, unsigned int *frame_flags,
 
   cm->cur_frame = &pool->frame_bufs[cm->new_fb_idx];
 
+#if CONFIG_EXT_REFS
+  if (oxcf->pass == 2) {
+    const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
+    cpi->alt_fb_idx = cpi->arf_map[gf_group->arf_ref_idx[gf_group->index]];
+  }
+#else
   if (cpi->multi_arf_allowed) {
     if (cm->frame_type == KEY_FRAME) {
       init_buffer_indices(cpi);
@@ -5318,7 +5417,7 @@ int vp10_get_compressed_data(VP10_COMP *cpi, unsigned int *frame_flags,
       cpi->alt_fb_idx = gf_group->arf_ref_idx[gf_group->index];
     }
   }
-
+#endif
   // Start with a 0 size frame.
   *size = 0;
 
diff --git a/vp10/encoder/encoder.h b/vp10/encoder/encoder.h
index 1c08b492c472bf9b6cdee8244d3c6f617598db12..fca8b6fbecde625cd984b4fe51a7c2b826c35eda 100644
--- a/vp10/encoder/encoder.h
+++ b/vp10/encoder/encoder.h
@@ -622,7 +622,9 @@ typedef struct VP10_COMP {
 #if CONFIG_EXT_REFS
   int refresh_frame_mask;
   int existing_fb_idx_to_show;
-  int is_arf_filter_off;
+  int is_arf_filter_off[MAX_EXT_ARFS + 1];
+  int num_extra_arfs;
+  int arf_map[MAX_EXT_ARFS + 1];
 #endif  // CONFIG_EXT_REFS
 #if CONFIG_GLOBAL_MOTION
   int global_motion_used[TOTAL_REFS_PER_FRAME];
diff --git a/vp10/encoder/firstpass.c b/vp10/encoder/firstpass.c
index 317b689422cc0a497fa4e8e9a26831541b97b2a7..1d1bf520165c64d0e0baadd7c39b9e4993a5d833 100644
--- a/vp10/encoder/firstpass.c
+++ b/vp10/encoder/firstpass.c
@@ -1548,6 +1548,7 @@ static int calculate_boost_bits(int frame_count, int boost,
                 0);
 }
 
+#if !CONFIG_EXT_REFS
 // Current limit on maximum number of active arfs in a GF/ARF group.
 #define MAX_ACTIVE_ARFS 2
 #define ARF_SLOT1 2
@@ -1559,6 +1560,7 @@ static void get_arf_buffer_indices(unsigned char *arf_buffer_indices) {
   arf_buffer_indices[0] = ARF_SLOT1;
   arf_buffer_indices[1] = ARF_SLOT2;
 }
+#endif
 
 static void allocate_gf_group_bits(VP10_COMP *cpi, int64_t gf_group_bits,
                                    double group_error, int gf_arf_bits) {
@@ -1576,9 +1578,10 @@ static void allocate_gf_group_bits(VP10_COMP *cpi, int64_t gf_group_bits,
   double modified_err = 0.0;
   double err_fraction;
   int mid_boost_bits = 0;
+#if !CONFIG_EXT_REFS
   int mid_frame_idx;
   unsigned char arf_buffer_indices[MAX_ACTIVE_ARFS];
-
+#endif
 #if CONFIG_EXT_REFS
   // The use of bi-predictive frames are only enabled when following 3
   // conditions are met:
@@ -1592,11 +1595,25 @@ static void allocate_gf_group_bits(VP10_COMP *cpi, int64_t gf_group_bits,
           (rc->baseline_gf_interval - rc->source_alt_ref_pending);
   int bipred_group_end = 0;
   int bipred_frame_index = 0;
+  int arf_pos[MAX_EXT_ARFS+1];
+  const unsigned char ext_arf_interval = (unsigned char)
+      (rc->baseline_gf_interval / (cpi->num_extra_arfs + 1) - 1);
+  int which_arf = cpi->num_extra_arfs;
+  int subgroup_interval[MAX_EXT_ARFS+1];
+  int ext_arf_boost[MAX_EXT_ARFS];
+  int is_sg_bipred_enabled = is_bipred_enabled;
+  int accumulative_subgroup_interval = 0;
 #endif  // CONFIG_EXT_REFS
 
+#if CONFIG_EXT_REFS
+  vp10_zero_array(ext_arf_boost, MAX_EXT_ARFS);
+#endif
+
   key_frame = cpi->common.frame_type == KEY_FRAME;
 
+#if !CONFIG_EXT_REFS
   get_arf_buffer_indices(arf_buffer_indices);
+#endif
 
   // For key frames the frame target rate is already set and it
   // is also the golden frame.
@@ -1610,9 +1627,13 @@ static void allocate_gf_group_bits(VP10_COMP *cpi, int64_t gf_group_bits,
       gf_group->rf_level[frame_index] = GF_ARF_STD;
       gf_group->bit_allocation[frame_index] = gf_arf_bits;
     }
+#if CONFIG_EXT_REFS
+    gf_group->arf_update_idx[frame_index] = 0;
+    gf_group->arf_ref_idx[frame_index] = 0;
+#else
     gf_group->arf_update_idx[frame_index] = arf_buffer_indices[0];
     gf_group->arf_ref_idx[frame_index] = arf_buffer_indices[0];
-
+#endif
     // Step over the golden frame / overlay frame
     if (EOF == input_stats(twopass, &frame_stats)) return;
   }
@@ -1641,19 +1662,55 @@ static void allocate_gf_group_bits(VP10_COMP *cpi, int64_t gf_group_bits,
     gf_group->arf_src_offset[frame_index] =
         (unsigned char)(rc->baseline_gf_interval - 1);
 
+#if CONFIG_EXT_REFS
+    gf_group->arf_update_idx[frame_index] = 0;
+    gf_group->arf_ref_idx[frame_index] = 0;
+#else
     gf_group->arf_update_idx[frame_index] = arf_buffer_indices[0];
     gf_group->arf_ref_idx[frame_index] =
         arf_buffer_indices[cpi->multi_arf_last_grp_enabled &&
                            rc->source_alt_ref_active];
-
+#endif  // CONFIG_EXT_REFS && CONFIG_EXT_ARFS
 #if CONFIG_EXT_REFS
     gf_group->bidir_pred_enabled[frame_index] = 0;
     gf_group->brf_src_offset[frame_index] = 0;
 // NOTE: "bidir_pred_frame_index" stays unchanged for ARF_UPDATE frames.
 #endif  // CONFIG_EXT_REFS
 
+#if CONFIG_EXT_REFS
+    // Work out the ARFs' positions in this gf group
+    // NOTE(weitinglin): ALT_REFs' are indexed inversely, but coded in display
+    // order (except for the original ARF). In the example of three ALT_REF's,
+    // We index ALTREF's as: KEY ----- ALT2 ----- ALT1 ----- ALT0
+    // but code them in the following order:
+    // KEY-ALT0-ALT2 ----- OVERLAY2-ALT1 ----- OVERLAY1 ----- OVERLAY0
+    arf_pos[0] = frame_index + cpi->num_extra_arfs +
+                 gf_group->arf_src_offset[1] + 1;
+    for (i = 0; i < cpi->num_extra_arfs; ++i) {
+      arf_pos[i + 1] = frame_index +
+                       (cpi->num_extra_arfs - i)*(ext_arf_interval + 2);
+      subgroup_interval[i] = arf_pos[i] - arf_pos[i + 1] - (i == 0 ? 1 : 2);
+    }
+    subgroup_interval[cpi->num_extra_arfs] = arf_pos[cpi->num_extra_arfs] -
+        frame_index - (cpi->num_extra_arfs == 0 ? 1 : 2);
+#endif  // CONFIG_EXT_REFS
+
     ++frame_index;
 
+#if CONFIG_EXT_REFS
+    // Insert an extra ARF
+    if (cpi->num_extra_arfs) {
+      gf_group->update_type[frame_index] = ARF_UPDATE;
+      // Note (weitinglin): GF_ARF_LOW is also used as an identifier
+      //                    for internal ALT_REF's:
+      gf_group->rf_level[frame_index] = GF_ARF_LOW;
+      gf_group->arf_src_offset[frame_index] = ext_arf_interval;
+      gf_group->arf_update_idx[frame_index] = which_arf;
+      gf_group->arf_ref_idx[frame_index] = 0;
+      ++frame_index;
+    }
+    accumulative_subgroup_interval += subgroup_interval[cpi->num_extra_arfs];
+#else
     if (cpi->multi_arf_enabled) {
       // Set aside a slot for a level 1 arf.
       gf_group->update_type[frame_index] = ARF_UPDATE;
@@ -1664,14 +1721,19 @@ static void allocate_gf_group_bits(VP10_COMP *cpi, int64_t gf_group_bits,
       gf_group->arf_ref_idx[frame_index] = arf_buffer_indices[0];
       ++frame_index;
     }
+#endif  // CONFIG_EXT_ARFS
   }
 
+#if !CONFIG_EXT_REFS
   // Define middle frame
   mid_frame_idx = frame_index + (rc->baseline_gf_interval >> 1) - 1;
+#endif
 
   // Allocate bits to the other frames in the group.
   for (i = 0; i < rc->baseline_gf_interval - rc->source_alt_ref_pending; ++i) {
+#if !CONFIG_EXT_REFS
     int arf_idx = 0;
+#endif
     if (EOF == input_stats(twopass, &frame_stats)) break;
 
     modified_err = calculate_modified_err(cpi, twopass, oxcf, &frame_stats);
@@ -1686,21 +1748,32 @@ static void allocate_gf_group_bits(VP10_COMP *cpi, int64_t gf_group_bits,
     if (rc->source_alt_ref_pending && cpi->multi_arf_enabled) {
       mid_boost_bits += (target_frame_size >> 4);
       target_frame_size -= (target_frame_size >> 4);
-
+#if !CONFIG_EXT_REFS
       if (frame_index <= mid_frame_idx) arf_idx = 1;
+#endif
     }
+#if CONFIG_EXT_REFS
+    gf_group->arf_update_idx[frame_index] = which_arf;
+    gf_group->arf_ref_idx[frame_index] = which_arf;
+#else
     gf_group->arf_update_idx[frame_index] = arf_buffer_indices[arf_idx];
     gf_group->arf_ref_idx[frame_index] = arf_buffer_indices[arf_idx];
-
+#endif  // CONFIG_EXT_REFS
     target_frame_size =
         clamp(target_frame_size, 0, VPXMIN(max_bits, (int)total_group_bits));
 
 #if CONFIG_EXT_REFS
+    // If we are going to have ARFs, check if we can have BWDREF in this
+    // subgroup.
+    if (rc->source_alt_ref_pending) {
+      is_sg_bipred_enabled =  is_bipred_enabled &&
+          (subgroup_interval[which_arf] > rc->bipred_group_interval);
+    }
     // NOTE: BIDIR_PRED is only enabled when the length of the bi-predictive
     //       frame group interval is strictly smaller than that of the GOLDEN
     //       FRAME group interval.
     // TODO(zoeliu): Currently BIDIR_PRED is only enabled when alt-ref is on.
-    if (is_bipred_enabled && !bipred_group_end) {
+    if (is_sg_bipred_enabled && !bipred_group_end) {
       const int cur_brf_src_offset = rc->bipred_group_interval - 1;
 
       // --- BRF_UPDATE ---
@@ -1727,9 +1800,8 @@ static void allocate_gf_group_bits(VP10_COMP *cpi, int64_t gf_group_bits,
       // included within the current golden frame group.
       // In addition, we need to avoid coding a BRF right before an ARF.
       if (bipred_frame_index == 1 &&
-          (i + 2 + cur_brf_src_offset) >=
-              (rc->baseline_gf_interval - rc->source_alt_ref_pending)) {
-        bipred_group_end = 1;
+          (i + 2 + cur_brf_src_offset) >= accumulative_subgroup_interval) {
+          bipred_group_end = 1;
       }
     } else {
 #endif  // CONFIG_EXT_REFS
@@ -1765,19 +1837,54 @@ static void allocate_gf_group_bits(VP10_COMP *cpi, int64_t gf_group_bits,
 #endif  // CONFIG_EXT_REFS
 
     ++frame_index;
+#if CONFIG_EXT_REFS
+    // Check if we need to update the ARF
+    if (cpi->num_extra_arfs && frame_index > arf_pos[which_arf]) {
+      --which_arf;
+      accumulative_subgroup_interval += subgroup_interval[which_arf] + 1;
+      // Meet the new subgroup. Reset the bipred_group_end flag;
+      bipred_group_end = 0;
+      // Insert another extra ARF after the overlay frame
+      if (which_arf) {
+        gf_group->update_type[frame_index] = ARF_UPDATE;
+        gf_group->rf_level[frame_index] = GF_ARF_LOW;
+        gf_group->arf_src_offset[frame_index] = ext_arf_interval;
+        gf_group->arf_update_idx[frame_index] = which_arf;
+        gf_group->arf_ref_idx[frame_index] = 0;
+        ++frame_index;
+      }
+    }
+#endif
   }
 
   // Note:
   // We need to configure the frame at the end of the sequence + 1 that will be
   // the start frame for the next group. Otherwise prior to the call to
   // vp10_rc_get_second_pass_params() the data will be undefined.
+#if CONFIG_EXT_REFS
+  gf_group->arf_update_idx[frame_index] = 0;
+  gf_group->arf_ref_idx[frame_index] = 0;
+#else
   gf_group->arf_update_idx[frame_index] = arf_buffer_indices[0];
   gf_group->arf_ref_idx[frame_index] = arf_buffer_indices[0];
-
+#endif
   if (rc->source_alt_ref_pending) {
     gf_group->update_type[frame_index] = OVERLAY_UPDATE;
     gf_group->rf_level[frame_index] = INTER_NORMAL;
 
+#if CONFIG_EXT_REFS
+    if (cpi->num_extra_arfs) {
+      for (i = cpi->num_extra_arfs; i > 0; --i) {
+        int arf_pos_in_gf = (i == cpi->num_extra_arfs ? 2 : arf_pos[i + 1] + 1);
+        gf_group->bit_allocation[arf_pos_in_gf] =
+            gf_group->bit_allocation[arf_pos[i]];
+        gf_group->update_type[arf_pos[i]] = INTNL_OVERLAY_UPDATE;
+        gf_group->bit_allocation[arf_pos[i]] = 0;
+        gf_group->rf_level[arf_pos[i]] = INTER_LOW;
+      }
+    }
+#endif
+#if !CONFIG_EXT_REFS
     // Final setup for second arf and its overlay.
     if (cpi->multi_arf_enabled) {
       gf_group->bit_allocation[2] =
@@ -1785,6 +1892,7 @@ static void allocate_gf_group_bits(VP10_COMP *cpi, int64_t gf_group_bits,
       gf_group->update_type[mid_frame_idx] = OVERLAY_UPDATE;
       gf_group->bit_allocation[mid_frame_idx] = 0;
     }
+#endif
   } else {
     gf_group->update_type[frame_index] = GF_UPDATE;
     gf_group->rf_level[frame_index] = GF_ARF_STD;
@@ -1797,7 +1905,6 @@ static void allocate_gf_group_bits(VP10_COMP *cpi, int64_t gf_group_bits,
   // Note whether multi-arf was enabled this group for next time.
   cpi->multi_arf_last_grp_enabled = cpi->multi_arf_enabled;
 }
-
 // Analyse and define a gf/arf group.
 static void define_gf_group(VP10_COMP *cpi, FIRSTPASS_STATS *this_frame) {
   VP10_COMMON *const cm = &cpi->common;
@@ -2000,6 +2107,15 @@ static void define_gf_group(VP10_COMP *cpi, FIRSTPASS_STATS *this_frame) {
   // Set the interval until the next gf.
   rc->baseline_gf_interval = i - (is_key_frame || rc->source_alt_ref_pending);
 
+#if CONFIG_EXT_REFS
+  // Compute how many extra alt_refs we can have
+  cpi->num_extra_arfs =
+      get_number_of_extra_arfs(rc->baseline_gf_interval,
+                               rc->source_alt_ref_pending);
+  // Currently at maximum two extra ARFs' are allowed
+  assert(cpi->num_extra_arfs <= 2);
+#endif
+
   rc->frames_till_gf_update_due = rc->baseline_gf_interval;
 
 #if CONFIG_EXT_REFS
@@ -2445,24 +2561,31 @@ static void configure_buffer_updates(VP10_COMP *cpi) {
   cpi->rc.is_bwd_ref_frame = 0;
   cpi->rc.is_last_bipred_frame = 0;
   cpi->rc.is_bipred_frame = 0;
+  cpi->rc.is_src_frame_ext_arf = 0;
 #endif  // CONFIG_EXT_REFS
 
   switch (twopass->gf_group.update_type[twopass->gf_group.index]) {
-    case KF_UPDATE: cpi->refresh_last_frame = 1; cpi->refresh_golden_frame = 1;
+    case KF_UPDATE:
+      cpi->refresh_last_frame = 1;
+      cpi->refresh_golden_frame = 1;
 #if CONFIG_EXT_REFS
       cpi->refresh_bwd_ref_frame = 1;
 #endif  // CONFIG_EXT_REFS
       cpi->refresh_alt_ref_frame = 1;
       break;
 
-    case LF_UPDATE: cpi->refresh_last_frame = 1; cpi->refresh_golden_frame = 0;
+    case LF_UPDATE:
+      cpi->refresh_last_frame = 1;
+      cpi->refresh_golden_frame = 0;
 #if CONFIG_EXT_REFS
       cpi->refresh_bwd_ref_frame = 0;
 #endif  // CONFIG_EXT_REFS
       cpi->refresh_alt_ref_frame = 0;
       break;
 
-    case GF_UPDATE: cpi->refresh_last_frame = 1; cpi->refresh_golden_frame = 1;
+    case GF_UPDATE:
+      cpi->refresh_last_frame = 1;
+      cpi->refresh_golden_frame = 1;
 #if CONFIG_EXT_REFS
       cpi->refresh_bwd_ref_frame = 0;
 #endif  // CONFIG_EXT_REFS
@@ -2479,9 +2602,11 @@ static void configure_buffer_updates(VP10_COMP *cpi) {
       cpi->rc.is_src_frame_alt_ref = 1;
       break;
 
-    case ARF_UPDATE: cpi->refresh_last_frame = 0; cpi->refresh_golden_frame = 0;
+    case ARF_UPDATE:
+      cpi->refresh_last_frame = 0;
+      cpi->refresh_golden_frame = 0;
 #if CONFIG_EXT_REFS
-      cpi->refresh_bwd_ref_frame = 0;
+      cpi->refresh_bwd_ref_frame = 1;
 #endif  // CONFIG_EXT_REFS
       cpi->refresh_alt_ref_frame = 1;
       break;
@@ -2493,8 +2618,16 @@ static void configure_buffer_updates(VP10_COMP *cpi) {
       cpi->refresh_bwd_ref_frame = 1;
       cpi->refresh_alt_ref_frame = 0;
       cpi->rc.is_bwd_ref_frame = 1;
+      if (cpi->num_extra_arfs) {
+        // Allow BRF uses the farthest ALT_REF (ALT0) as BWD_REF by swapping
+        // the virtual indices.
+        // NOTE: The indices will be swapped back after this frame is encoded
+        //       (in vp10_update_reference_frames()).
+        int tmp = cpi->bwd_fb_idx;
+        cpi->bwd_fb_idx = cpi->arf_map[0];
+        cpi->arf_map[0] = tmp;
+      }
       break;
-
     case LAST_BIPRED_UPDATE:
       cpi->refresh_last_frame = 0;
       cpi->refresh_golden_frame = 0;
@@ -2510,6 +2643,15 @@ static void configure_buffer_updates(VP10_COMP *cpi) {
       cpi->refresh_alt_ref_frame = 0;
       cpi->rc.is_bipred_frame = 1;
       break;
+
+    case INTNL_OVERLAY_UPDATE:
+      cpi->refresh_last_frame = 1;
+      cpi->refresh_golden_frame = 0;
+      cpi->refresh_bwd_ref_frame = 0;
+      cpi->refresh_alt_ref_frame = 0;
+      cpi->rc.is_src_frame_alt_ref = 1;
+      cpi->rc.is_src_frame_ext_arf = 1;
+      break;
 #endif  // CONFIG_EXT_REFS
 
     default: assert(0); break;
diff --git a/vp10/encoder/firstpass.h b/vp10/encoder/firstpass.h
index 3642cfda68110ff5029ff778b370981d126b85fe..156fa2cc579d4ee48b222ccd1bddfe86ea90b6f9 100644
--- a/vp10/encoder/firstpass.h
+++ b/vp10/encoder/firstpass.h
@@ -43,7 +43,12 @@ typedef struct {
 // Length of the bi-predictive frame group (BFG)
 // NOTE: Currently each BFG contains one backward ref (BWF) frame plus a certain
 //       number of bi-predictive frames.
-#define BFG_INTERVAL 2
+#define BFG_INTERVAL          2
+// The maximum number of extra ALT_REF's
+// NOTE: This number cannot be greater than 2 or the reference frame buffer will
+//       overflow.
+#define MAX_EXT_ARFS          2
+#define MIN_EXT_ARF_INTERVAL  4
 #endif  // CONFIG_EXT_REFS
 
 #define VLOW_MOTION_THRESHOLD 950
@@ -80,10 +85,11 @@ typedef enum {
   ARF_UPDATE = 3,
   OVERLAY_UPDATE = 4,
 #if CONFIG_EXT_REFS
-  BRF_UPDATE = 5,          // Backward Reference Frame
-  LAST_BIPRED_UPDATE = 6,  // Last Bi-predictive Frame
-  BIPRED_UPDATE = 7,       // Bi-predictive Frame, but not the last one
-  FRAME_UPDATE_TYPES = 8
+  BRF_UPDATE = 5,            // Backward Reference Frame
+  LAST_BIPRED_UPDATE = 6,    // Last Bi-predictive Frame
+  BIPRED_UPDATE = 7,         // Bi-predictive Frame, but not the last one
+  INTNL_OVERLAY_UPDATE = 8,  // Internal Overlay Frame
+  FRAME_UPDATE_TYPES = 9
 #else
   FRAME_UPDATE_TYPES = 5
 #endif  // CONFIG_EXT_REFS
@@ -176,6 +182,16 @@ void vp10_init_subsampling(struct VP10_COMP *cpi);
 void vp10_calculate_coded_size(struct VP10_COMP *cpi, int *scaled_frame_width,
                                int *scaled_frame_height);
 
+#if CONFIG_EXT_REFS
+static inline int get_number_of_extra_arfs(int interval, int arf_pending) {
+  if (arf_pending && MAX_EXT_ARFS > 0)
+    return interval >= MIN_EXT_ARF_INTERVAL*(MAX_EXT_ARFS+1) ? MAX_EXT_ARFS :
+           interval >= MIN_EXT_ARF_INTERVAL*MAX_EXT_ARFS ? MAX_EXT_ARFS - 1 : 0;
+  else
+    return 0;
+}
+#endif
+
 #ifdef __cplusplus
 }  // extern "C"
 #endif
diff --git a/vp10/encoder/ratectrl.c b/vp10/encoder/ratectrl.c
index 6b077c7884684873ab567931a3afd90267713311..c7e4348727a8e31c3376faf909f155756b80381c 100644
--- a/vp10/encoder/ratectrl.c
+++ b/vp10/encoder/ratectrl.c
@@ -42,7 +42,6 @@
 #define MAX_BPB_FACTOR 50
 
 #define FRAME_OVERHEAD_BITS 200
-
 #if CONFIG_VP9_HIGHBITDEPTH
 #define ASSIGN_MINQ_TABLE(bit_depth, name)                   \
   do {                                                       \
@@ -917,10 +916,11 @@ int vp10_frame_type_qdelta(const VP10_COMP *cpi, int rf_level, int q) {
 #if CONFIG_EXT_REFS
     0.80,  // INTER_LOW
     1.50,  // INTER_HIGH
+    1.25,  // GF_ARF_LOW
 #else
     1.00,  // INTER_HIGH
-#endif     // CONFIG_EXT_REFS
     1.50,  // GF_ARF_LOW
+#endif  // CONFIG_EXT_REFS
     2.00,  // GF_ARF_STD
     2.00,  // KF_STD
   };
@@ -1185,16 +1185,20 @@ static void update_golden_frame_stats(VP10_COMP *cpi) {
 
 #if CONFIG_EXT_REFS
   // Update the Golden frame usage counts.
-  // Wei-Ting: If we use show_existing_frame for an OVERLAY frame, only the
-  //           virtual indices for the reference frame will be updated and
-  //           cpi->refresh_golden_frame will still be zero.
+  // NOTE(weitinglin): If we use show_existing_frame for an OVERLAY frame,
+  //                   only the virtual indices for the reference frame will be
+  //                   updated and cpi->refresh_golden_frame will still be zero.
   if (cpi->refresh_golden_frame || rc->is_src_frame_alt_ref) {
 #else
   // Update the Golden frame usage counts.
   if (cpi->refresh_golden_frame) {
 #endif
-    // this frame refreshes means next frames don't unless specified by user
-    rc->frames_since_golden = 0;
+#if CONFIG_EXT_REFS
+    // We will not use internal overlay frames to replace the golden frame
+    if (!rc->is_src_frame_ext_arf)
+#endif
+      // this frame refreshes means next frames don't unless specified by user
+      rc->frames_since_golden = 0;
 
     // If we are not using alt ref in the up and coming group clear the arf
     // active flag. In multi arf group case, if the index is not 0 then
diff --git a/vp10/encoder/ratectrl.h b/vp10/encoder/ratectrl.h
index ed9d6fbf98f9acea11351388267104d4344d946b..18965833676008ae1bed9db48599ee3dce71b6ad 100644
--- a/vp10/encoder/ratectrl.h
+++ b/vp10/encoder/ratectrl.h
@@ -110,6 +110,7 @@ typedef struct {
   int is_bwd_ref_frame;
   int is_last_bipred_frame;
   int is_bipred_frame;
+  int is_src_frame_ext_arf;
 #endif  // CONFIG_EXT_REFS
 
   int avg_frame_bandwidth;  // Average frame size target for clip
diff --git a/vp10/encoder/rd.c b/vp10/encoder/rd.c
index 54089480551c60b339a3476670d54939901d035b..12a1fbf8c25b2b3ad44f40434f733f41c4ffd99b 100644
--- a/vp10/encoder/rd.c
+++ b/vp10/encoder/rd.c
@@ -223,6 +223,9 @@ static const int rd_frame_type_factor[FRAME_UPDATE_TYPES] = {
 #if CONFIG_EXT_REFS
   // TODO(zoeliu): To adjust further following factor values.
   128, 128, 128
+  // TODO(weitinglin): We should investigate if the values should be the same
+  //                   as the value used by OVERLAY frame
+  , 144
 #endif  // CONFIG_EXT_REFS
 };
 
diff --git a/vp10/encoder/temporal_filter.c b/vp10/encoder/temporal_filter.c
index cc484a8ea6a6115ffa74917f2d0fab3824f5e589..691e1572d7bb06171c71f2757ccaa67b65d90649 100644
--- a/vp10/encoder/temporal_filter.c
+++ b/vp10/encoder/temporal_filter.c
@@ -625,15 +625,31 @@ void vp10_temporal_filter(VP10_COMP *cpi, int distance) {
   int frames_to_blur_forward;
   struct scale_factors sf;
   YV12_BUFFER_CONFIG *frames[MAX_LAG_BUFFERS] = { NULL };
+#if CONFIG_EXT_REFS
+  const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
+#endif
 
   // Apply context specific adjustments to the arnr filter parameters.
   adjust_arnr_filter(cpi, distance, rc->gfu_boost, &frames_to_blur, &strength);
+  // TODO(weitinglin): Currently, we enforce the filtering strength on
+  //                   extra ARFs' to be zeros. We should investigate in which
+  //                   case it is more beneficial to use non-zero strength
+  //                   filtering.
 #if CONFIG_EXT_REFS
-  if (strength == 0 && frames_to_blur == 1)
-    cpi->is_arf_filter_off = 1;
-  else
-    cpi->is_arf_filter_off = 0;
+  if (gf_group->rf_level[gf_group->index] == GF_ARF_LOW) {
+    strength = 0;
+    frames_to_blur = 1;
+  }
+#endif
+
+#if CONFIG_EXT_REFS
+  if (strength == 0 && frames_to_blur == 1) {
+    cpi->is_arf_filter_off[gf_group->arf_update_idx[gf_group->index]] = 1;
+  } else {
+    cpi->is_arf_filter_off[gf_group->arf_update_idx[gf_group->index]] = 0;
+  }
 #endif
+
   frames_to_blur_backward = (frames_to_blur / 2);
   frames_to_blur_forward = ((frames_to_blur - 1) / 2);
   start_frame = distance + frames_to_blur_forward;