Add encoder support to ALTREF2

This CL adds the use of ALTREF2_FRAME to both single / comp reference
prediction at the encoder side. In particular, the encoder keeps the
distant altref as ALTREF, and uses the internal extra altrefs to
refresh ALTREF2.

Compared with the baseline (ext_tx and global_motion disabled simply
for speed concern):
(a) lowres: avg_psnr -0.395% ovr_psnr -0.393% ssim -0.329%
(b) midres: avg_psnr -0.419% ovr_psnr -0.431% ssim -0.444%
(c) AWCY High Latency:
   PSNR | PSNR Cb | PSNR Cr | PSNR HVS |    SSIM | MS SSIM | CIEDE 2000
-0.6661 | -0.5988 | -0.6669 |  -0.6993 | -0.6988 | -0.7303 | -0.6051
(d) AWCY Low Latency:
  PSNR | PSNR Cb | PSNR Cr | PSNR HVS |   SSIM | MS SSIM | CIEDE 2000
0.0720 | -0.0505 |  0.1501 |   0.0670 | 0.0842 |  0.0517 |     0.0158

TODO list:
(1) To have altref2 incorporated with ext-comp-refs;
(2) To have altref2 fully work with new-multisymbol;
(3) To re-collect the initial default probs/cdfs;
(4) To tune the encoder gf group structure design for altref2.

Change-Id: I6ad63fd65afa903d3bba20acdb68e3b67acf7fdf
diff --git a/av1/decoder/decodemv.c b/av1/decoder/decodemv.c
index 96ad365..7eb3de0 100644
--- a/av1/decoder/decodemv.c
+++ b/av1/decoder/decodemv.c
@@ -1590,12 +1590,22 @@
       const int ctx0 = av1_get_pred_context_single_ref_p1(xd);
 #if CONFIG_VAR_REFS
       int bit0;
+#if CONFIG_ALTREF2
+      // Test need to explicitly code (L,L2,L3,G) vs (BWD,ALT2,ALT) branch node
+      // in tree
+      if ((L_OR_L2(cm) || L3_OR_G(cm)) &&
+          (BWD_OR_ALT2(cm) || ALTREF_IS_VALID(cm)))
+        bit0 = READ_REF_BIT(single_ref_p1);
+      else
+        bit0 = (BWD_OR_ALT2(cm) || ALTREF_IS_VALID(cm));
+#else   // !CONFIG_ALTREF2
       // Test need to explicitly code (L,L2,L3,G) vs (BWD,ALT) branch node in
       // tree
       if ((L_OR_L2(cm) || L3_OR_G(cm)) && BWD_OR_ALT(cm))
         bit0 = READ_REF_BIT(single_ref_p1);
       else
         bit0 = BWD_OR_ALT(cm);
+#endif  // CONFIG_ALTREF2
 #else   // !CONFIG_VAR_REFS
       const int bit0 = READ_REF_BIT(single_ref_p1);
 #endif  // CONFIG_VAR_REFS
@@ -1605,10 +1615,11 @@
         const int ctx1 = av1_get_pred_context_single_ref_p2(xd);
 #if CONFIG_VAR_REFS
         int bit1;
-// Test need to explicitly code (BWD/ALT2) vs (ALT) branch node in tree
 #if CONFIG_ALTREF2
+        // Test need to explicitly code (BWD/ALT2) vs (ALT) branch node in tree
         const int bit1_uncertain = BWD_OR_ALT2(cm) && ALTREF_IS_VALID(cm);
 #else   // !CONFIG_ALTREF2
+        // Test need to explicitly code (BWD) vs (ALT) branch node in tree
         const int bit1_uncertain = BWD_AND_ALT(cm);
 #endif  // CONFIG_ALTREF2
         if (bit1_uncertain)
diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c
index 9d76628..568199c 100644
--- a/av1/encoder/bitstream.c
+++ b/av1/encoder/bitstream.c
@@ -1153,6 +1153,29 @@
 #endif  // CONFIG_VAR_REFS
       }
 
+#if CONFIG_ALTREF2
+
+#if CONFIG_VAR_REFS
+      // Test need to explicitly code (BWD,ALT2) vs (ALT) branch node in tree
+      if (BWD_OR_ALT2(cm) && ALTREF_IS_VALID(cm)) {
+#endif  // CONFIG_VAR_REFS
+        const int bit_bwd = mbmi->ref_frame[1] == ALTREF_FRAME;
+        WRITE_REF_BIT(bit_bwd, comp_bwdref_p);
+
+        if (!bit_bwd) {
+#if CONFIG_VAR_REFS
+          // Test need to explicitly code (BWD,ALT2) vs (ALT) branch node in
+          // tree
+          if (BWD_AND_ALT2(cm))
+#endif  // CONFIG_VAR_REFS
+            WRITE_REF_BIT(mbmi->ref_frame[1] == ALTREF2_FRAME, comp_bwdref_p1);
+        }
+#if CONFIG_VAR_REFS
+      }
+#endif  // CONFIG_VAR_REFS
+
+#else  // !CONFIG_ALTREF2
+
 #if CONFIG_VAR_REFS
       // Test need to explicitly code (BWD) vs (ALT) branch node in tree
       if (BWD_AND_ALT(cm)) {
@@ -1163,22 +1186,50 @@
       }
 #endif  // CONFIG_VAR_REFS
 
+#endif  // CONFIG_ALTREF2
+
 #else   // !CONFIG_EXT_REFS
       const int bit = mbmi->ref_frame[0] == GOLDEN_FRAME;
       WRITE_REF_BIT(bit, comp_ref_p);
 #endif  // CONFIG_EXT_REFS
     } else {
 #if CONFIG_EXT_REFS
-      const int bit0 = (mbmi->ref_frame[0] == ALTREF_FRAME ||
-                        mbmi->ref_frame[0] == BWDREF_FRAME);
+      const int bit0 = (mbmi->ref_frame[0] <= ALTREF_FRAME &&
+                        mbmi->ref_frame[0] >= BWDREF_FRAME);
 #if CONFIG_VAR_REFS
+#if CONFIG_ALTREF2
+      // Test need to explicitly code (L,L2,L3,G) vs (BWD,ALT2,ALT) branch node
+      // in tree
+      if ((L_OR_L2(cm) || L3_OR_G(cm)) &&
+          (BWD_OR_ALT2(cm) || ALTREF_IS_VALID(cm)))
+#else   // !CONFIG_ALTREF2
       // Test need to explicitly code (L,L2,L3,G) vs (BWD,ALT) branch node in
       // tree
       if ((L_OR_L2(cm) || L3_OR_G(cm)) && BWD_OR_ALT(cm))
+#endif  // CONFIG_ALTREF2
 #endif  // CONFIG_VAR_REFS
         WRITE_REF_BIT(bit0, single_ref_p1);
 
       if (bit0) {
+#if CONFIG_ALTREF2
+#if CONFIG_VAR_REFS
+        // Test need to explicitly code (BWD,ALT2) vs (ALT) branch node in tree
+        if (BWD_OR_ALT2(cm) && ALTREF_IS_VALID(cm)) {
+#endif  // CONFIG_VAR_REFS
+          const int bit1 = mbmi->ref_frame[0] == ALTREF_FRAME;
+          WRITE_REF_BIT(bit1, single_ref_p2);
+
+          if (!bit1) {
+#if CONFIG_VAR_REFS
+            // Test need to explicitly code (BWD) vs (ALT2) branch node in tree
+            if (BWD_AND_ALT2(cm))
+#endif  // CONFIG_VAR_REFS
+              WRITE_REF_BIT(mbmi->ref_frame[0] == ALTREF2_FRAME, single_ref_p6);
+          }
+#if CONFIG_VAR_REFS
+        }
+#endif  // CONFIG_VAR_REFS
+#else   // !CONFIG_ALTREF2
 #if CONFIG_VAR_REFS
         // Test need to explicitly code (BWD) vs (ALT) branch node in tree
         if (BWD_AND_ALT(cm)) {
@@ -1188,6 +1239,7 @@
 #if CONFIG_VAR_REFS
         }
 #endif  // CONFIG_VAR_REFS
+#endif  // CONFIG_ALTREF2
       } else {
         const int bit2 = (mbmi->ref_frame[0] == LAST3_FRAME ||
                           mbmi->ref_frame[0] == GOLDEN_FRAME);
@@ -3638,13 +3690,19 @@
   //     LAST3_FRAME.
   refresh_mask |=
       (cpi->refresh_last_frame << cpi->lst_fb_idxes[LAST_REF_FRAMES - 1]);
+
+#if CONFIG_ALTREF2
+  refresh_mask |= (cpi->refresh_bwd_ref_frame << cpi->bwd_fb_idx);
+  refresh_mask |= (cpi->refresh_alt2_ref_frame << cpi->alt2_fb_idx);
+#else   // !CONFIG_ALTREF2
   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
+#endif  // CONFIG_ALTREF2
+#else   // !CONFIG_EXT_REFS
   refresh_mask |= (cpi->refresh_last_frame << cpi->lst_fb_idx);
 #endif  // CONFIG_EXT_REFS
 
@@ -3662,9 +3720,13 @@
     return refresh_mask | (cpi->refresh_golden_frame << cpi->alt_fb_idx);
   } else {
 #if CONFIG_EXT_REFS
+#if CONFIG_ALTREF2
+    const int arf_idx = cpi->alt_fb_idx;
+#else   // !CONFIG_ALTREF2
     const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
-    int arf_idx = cpi->arf_map[gf_group->arf_update_idx[gf_group->index]];
-#else
+    const int arf_idx = cpi->arf_map[gf_group->arf_update_idx[gf_group->index]];
+#endif  // CONFIG_ALTREF2
+#else   // !CONFIG_EXT_REFS
     int arf_idx = cpi->alt_fb_idx;
     if ((cpi->oxcf.pass == 2) && cpi->multi_arf_allowed) {
       const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
diff --git a/av1/encoder/encodeframe.c b/av1/encoder/encodeframe.c
index a94d851..fc46f56 100644
--- a/av1/encoder/encodeframe.c
+++ b/av1/encoder/encodeframe.c
@@ -1491,6 +1491,9 @@
   if ((rd_cost->rate != INT_MAX) && (aq_mode == COMPLEXITY_AQ) &&
       (bsize >= BLOCK_16X16) &&
       (cm->frame_type == KEY_FRAME || cpi->refresh_alt_ref_frame ||
+#if CONFIG_EXT_REFS && CONFIG_ALTREF2
+       cpi->refresh_alt2_ref_frame ||
+#endif  // CONFIG_EXT_REFS && CONFIG_ALTREF2
        (cpi->refresh_golden_frame && !cpi->rc.is_src_frame_alt_ref))) {
     av1_caq_select_segment(cpi, x, bsize, mi_row, mi_col, rd_cost->rate);
   }
@@ -1664,6 +1667,11 @@
 
             counts->comp_bwdref[av1_get_pred_context_comp_bwdref_p(cm, xd)][0]
                                [ref1 == ALTREF_FRAME]++;
+#if CONFIG_ALTREF2
+            if (ref1 != ALTREF_FRAME)
+              counts->comp_bwdref[av1_get_pred_context_comp_bwdref_p1(cm, xd)]
+                                 [1][ref1 == ALTREF2_FRAME]++;
+#endif  // CONFIG_ALTREF2
 #else   // !CONFIG_EXT_REFS
           counts->comp_ref[av1_get_pred_context_comp_ref_p(cm, xd)][0]
                           [ref0 == GOLDEN_FRAME]++;
@@ -1673,12 +1681,18 @@
 #endif  // CONFIG_EXT_COMP_REFS
         } else {
 #if CONFIG_EXT_REFS
-          const int bit = (ref0 == ALTREF_FRAME || ref0 == BWDREF_FRAME);
+          const int bit = (ref0 >= BWDREF_FRAME);
 
           counts->single_ref[av1_get_pred_context_single_ref_p1(xd)][0][bit]++;
           if (bit) {
+            assert(ref0 <= ALTREF_FRAME);
             counts->single_ref[av1_get_pred_context_single_ref_p2(xd)][1]
-                              [ref0 != BWDREF_FRAME]++;
+                              [ref0 == ALTREF_FRAME]++;
+#if CONFIG_ALTREF2
+            if (ref0 != ALTREF_FRAME)
+              counts->single_ref[av1_get_pred_context_single_ref_p6(xd)][5]
+                                [ref0 == ALTREF2_FRAME]++;
+#endif  // CONFIG_ALTREF2
           } else {
             const int bit1 = !(ref0 == LAST2_FRAME || ref0 == LAST_FRAME);
             counts
@@ -4671,6 +4685,9 @@
 #if CONFIG_EXT_REFS
             !!(ref_flags & AOM_LAST2_FLAG) + !!(ref_flags & AOM_LAST3_FLAG) +
             !!(ref_flags & AOM_BWD_FLAG) +
+#if CONFIG_ALTREF2
+            !!(ref_flags & AOM_ALT2_FLAG) +
+#endif  // CONFIG_ALTREF2
 #endif  // CONFIG_EXT_REFS
             !!(ref_flags & AOM_ALT_FLAG)) >= 2;
   }
@@ -4702,7 +4719,11 @@
   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)
+  else if (cpi->refresh_golden_frame ||
+#if CONFIG_EXT_REFS && CONFIG_ALTREF2
+           cpi->refresh_alt2_ref_frame ||
+#endif  // CONFIG_EXT_REFS && CONFIG_ALTREF2
+           cpi->refresh_alt_ref_frame)
     return GOLDEN_FRAME;
   else
     // TODO(zoeliu): To investigate whether a frame_type other than
@@ -5389,8 +5410,13 @@
       cm->comp_fwd_ref[2] = LAST3_FRAME;
       cm->comp_fwd_ref[3] = GOLDEN_FRAME;
       cm->comp_bwd_ref[0] = BWDREF_FRAME;
+#if CONFIG_ALTREF2
+      cm->comp_bwd_ref[1] = ALTREF2_FRAME;
+      cm->comp_bwd_ref[2] = ALTREF_FRAME;
+#else   // !CONFIG_ALTREF2
       cm->comp_bwd_ref[1] = ALTREF_FRAME;
-#else
+#endif  // CONFIG_ALTREF2
+#else   // CONFIG_EXT_REFS
     cm->comp_fixed_ref = ALTREF_FRAME;
     cm->comp_var_ref[0] = LAST_FRAME;
     cm->comp_var_ref[1] = GOLDEN_FRAME;
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index e07e006..dac1f84 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -302,11 +302,15 @@
 #else
 #if CONFIG_EXT_REFS
     const GF_GROUP *gf_group = &cpi->twopass.gf_group;
+#if CONFIG_ALTREF2
+    if (gf_group->update_type[gf_group->index] == INTNL_ARF_UPDATE)
+#else  // !CONFIG_ALTREF2
     if (gf_group->rf_level[gf_group->index] == GF_ARF_LOW)
+#endif  // CONFIG_ALTREF2
       cm->frame_context_idx = EXT_ARF_FRAME;
     else if (cpi->refresh_alt_ref_frame)
       cm->frame_context_idx = ARF_FRAME;
-#else
+#else   // !CONFIG_EXT_REFS
     if (cpi->refresh_alt_ref_frame) cm->frame_context_idx = ARF_FRAME;
 #endif  // CONFIG_EXT_REFS
     else if (cpi->rc.is_src_frame_alt_ref)
@@ -985,10 +989,15 @@
     cpi->lst_fb_idxes[fb_idx] = fb_idx;
   cpi->gld_fb_idx = LAST_REF_FRAMES;
   cpi->bwd_fb_idx = LAST_REF_FRAMES + 1;
+#if CONFIG_ALTREF2
+  cpi->alt2_fb_idx = LAST_REF_FRAMES + 2;
+  cpi->alt_fb_idx = LAST_REF_FRAMES + 3;
+#else   // !CONFIG_ALTREF2
   cpi->alt_fb_idx = LAST_REF_FRAMES + 2;
+#endif  // CONFIG_ALTREF2
   for (fb_idx = 0; fb_idx < MAX_EXT_ARFS + 1; ++fb_idx)
     cpi->arf_map[fb_idx] = LAST_REF_FRAMES + 2 + fb_idx;
-#else
+#else   // !CONFIG_EXT_REFS
   cpi->lst_fb_idx = 0;
   cpi->gld_fb_idx = 1;
   cpi->alt_fb_idx = 2;
@@ -2208,6 +2217,9 @@
   cpi->refresh_golden_frame = 0;
 #if CONFIG_EXT_REFS
   cpi->refresh_bwd_ref_frame = 0;
+#if CONFIG_ALTREF2
+  cpi->refresh_alt2_ref_frame = 0;
+#endif  // CONFIG_ALTREF2
 #endif  // CONFIG_EXT_REFS
 
   cm->refresh_frame_context =
@@ -2948,6 +2960,10 @@
 #if CONFIG_EXT_REFS
   else if (ref_frame_flag == AOM_BWD_FLAG)
     ref_frame = BWDREF_FRAME;
+#if CONFIG_ALTREF2
+  else if (ref_frame_flag == AOM_ALT2_FLAG)
+    ref_frame = ALTREF2_FRAME;
+#endif  // CONFIG_ALTREF2
 #endif  // CONFIG_EXT_REFS
   else if (ref_frame_flag == AOM_ALT_FLAG)
     ref_frame = ALTREF_FRAME;
@@ -3039,7 +3055,13 @@
     // in av1_rc_get_second_pass_params(cpi)
     cm->show_existing_frame = 1;
     cpi->rc.is_src_frame_alt_ref = 1;
+#if CONFIG_ALTREF2
+    cpi->existing_fb_idx_to_show = (next_frame_update_type == OVERLAY_UPDATE)
+                                       ? cpi->alt_fb_idx
+                                       : cpi->alt2_fb_idx;
+#else   // !CONFIG_ALTREF2
     cpi->existing_fb_idx_to_show = cpi->alt_fb_idx;
+#endif  // CONFIG_ALTREF2
     cpi->is_arf_filter_off[which_arf] = 0;
   }
   cpi->rc.is_src_frame_ext_arf = 0;
@@ -3280,6 +3302,10 @@
 #if CONFIG_EXT_REFS
     ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[cpi->bwd_fb_idx],
                cm->new_fb_idx);
+#if CONFIG_ALTREF2
+    ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[cpi->alt2_fb_idx],
+               cm->new_fb_idx);
+#endif  // CONFIG_ALTREF2
 #endif  // CONFIG_EXT_REFS
     ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[cpi->alt_fb_idx],
                cm->new_fb_idx);
@@ -3303,7 +3329,7 @@
 #if CONFIG_EXT_REFS
     // We need to modify the mapping accordingly
     cpi->arf_map[0] = cpi->alt_fb_idx;
-#endif
+#endif  // CONFIG_EXT_REFS
 // TODO(zoeliu): Do we need to copy cpi->interp_filter_selected[0] over to
 // cpi->interp_filter_selected[GOLDEN_FRAME]?
 #if CONFIG_EXT_REFS
@@ -3312,31 +3338,46 @@
     // 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];
+    const int which_arf = gf_group->arf_ref_idx[gf_group->index];
+    assert(gf_group->update_type[gf_group->index] == INTNL_OVERLAY_UPDATE);
 
+    const int tmp = cpi->lst_fb_idxes[LAST_REF_FRAMES - 1];
     shift_last_ref_frames(cpi);
+
+#if CONFIG_ALTREF2
+    cpi->lst_fb_idxes[0] = cpi->alt2_fb_idx;
+    cpi->alt2_fb_idx = tmp;
+    // We need to modify the mapping accordingly
+    cpi->arf_map[which_arf] = cpi->alt2_fb_idx;
+
+    memcpy(cpi->interp_filter_selected[LAST_FRAME],
+           cpi->interp_filter_selected[ALTREF2_FRAME],
+           sizeof(cpi->interp_filter_selected[ALTREF2_FRAME]));
+#else      // !CONFIG_ALTREF2
     cpi->lst_fb_idxes[0] = cpi->alt_fb_idx;
     cpi->alt_fb_idx = tmp;
-
     // We need to modify the mapping accordingly
     cpi->arf_map[which_arf] = 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]));
+#endif     // CONFIG_ALTREF2
 #endif     // CONFIG_EXT_REFS
   } else { /* For non key/golden frames */
+    // === ALTREF_FRAME ===
     if (cpi->refresh_alt_ref_frame) {
       int arf_idx = cpi->alt_fb_idx;
       int which_arf = 0;
 #if CONFIG_EXT_REFS
+#if !CONFIG_ALTREF2
       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
+#endif  // !CONFIG_ALTREF2
+#else   // !CONFIG_EXT_REFS
       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];
@@ -3349,6 +3390,7 @@
              sizeof(cpi->interp_filter_selected[0]));
     }
 
+    // === GOLDEN_FRAME ===
     if (cpi->refresh_golden_frame) {
       ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[cpi->gld_fb_idx],
                  cm->new_fb_idx);
@@ -3362,7 +3404,9 @@
     }
 
 #if CONFIG_EXT_REFS
+    // === BWDREF_FRAME ===
     if (cpi->refresh_bwd_ref_frame) {
+#if !CONFIG_ALTREF2
       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.
@@ -3373,6 +3417,7 @@
         cpi->alt_fb_idx = cpi->bwd_fb_idx;
         cpi->bwd_fb_idx = tmp;
       }
+#endif  // !CONFIG_ALTREF2
 
       ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[cpi->bwd_fb_idx],
                  cm->new_fb_idx);
@@ -3381,6 +3426,18 @@
              cpi->interp_filter_selected[0],
              sizeof(cpi->interp_filter_selected[0]));
     }
+
+#if CONFIG_ALTREF2
+    // === ALTREF2_FRAME ===
+    if (cpi->refresh_alt2_ref_frame) {
+      ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[cpi->alt2_fb_idx],
+                 cm->new_fb_idx);
+
+      memcpy(cpi->interp_filter_selected[ALTREF2_FRAME],
+             cpi->interp_filter_selected[0],
+             sizeof(cpi->interp_filter_selected[0]));
+    }
+#endif  // CONFIG_ALTREF2
 #endif  // CONFIG_EXT_REFS
   }
 
@@ -3418,6 +3475,7 @@
     // lst_fb_idxes[2], lst_fb_idxes[0], lst_fb_idxes[1]
     int ref_frame;
 
+#if !CONFIG_ALTREF2
     if (cpi->rc.is_bwd_ref_frame && cpi->num_extra_arfs) {
       // We have swapped the virtual indices to use ALT0 as BWD_REF
       // and we need to swap them back.
@@ -3426,6 +3484,7 @@
       cpi->alt_fb_idx = cpi->bwd_fb_idx;
       cpi->bwd_fb_idx = tmp;
     }
+#endif  // !CONFIG_ALTREF2
 
     if (cm->frame_type == KEY_FRAME) {
       for (ref_frame = 0; ref_frame < LAST_REF_FRAMES; ++ref_frame) {
@@ -3470,7 +3529,7 @@
                sizeof(cpi->interp_filter_selected[BWDREF_FRAME]));
       }
     }
-#else
+#else   // !CONFIG_EXT_REFS
     ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[cpi->lst_fb_idx],
                cm->new_fb_idx);
     if (!cpi->rc.is_src_frame_alt_ref) {
@@ -3507,6 +3566,9 @@
     AOM_GOLD_FLAG,
 #if CONFIG_EXT_REFS
     AOM_BWD_FLAG,
+#if CONFIG_ALTREF2
+    AOM_ALT2_FLAG,
+#endif  // CONFIG_ALTREF2
 #endif  // CONFIG_EXT_REFS
     AOM_ALT_FLAG
   };
@@ -3597,8 +3659,13 @@
     refresh[1] = refresh[2] = 0;
     refresh[3] = (cpi->refresh_golden_frame) ? 1 : 0;
     refresh[4] = (cpi->refresh_bwd_ref_frame) ? 1 : 0;
+#if CONFIG_ALTREF2
+    refresh[5] = (cpi->refresh_alt2_ref_frame) ? 1 : 0;
+    refresh[6] = (cpi->refresh_alt_ref_frame) ? 1 : 0;
+#else  // !CONFIG_ALTREF2
     refresh[5] = (cpi->refresh_alt_ref_frame) ? 1 : 0;
-#else
+#endif  // CONFIG_ALTREF2
+#else   // !CONFIG_EXT_REFS
     refresh[1] = (cpi->refresh_golden_frame) ? 1 : 0;
     refresh[2] = (cpi->refresh_alt_ref_frame) ? 1 : 0;
 #endif  // CONFIG_EXT_REFS
@@ -4397,7 +4464,7 @@
       map[cpi->lst_fb_idxes[2]] == map[cpi->lst_fb_idxes[1]];
   const int gld_is_last2 = map[cpi->gld_fb_idx] == map[cpi->lst_fb_idxes[1]];
   const int gld_is_last3 = map[cpi->gld_fb_idx] == map[cpi->lst_fb_idxes[2]];
-#else  // !CONFIG_ONE_SIDED_COMPOUND
+#else   // !CONFIG_ONE_SIDED_COMPOUND
   const int bwd_is_last = map[cpi->bwd_fb_idx] == map[cpi->lst_fb_idxes[0]];
   const int alt_is_last = map[cpi->alt_fb_idx] == map[cpi->lst_fb_idxes[0]];
 
@@ -4410,12 +4477,23 @@
   const int bwd_is_last3 = map[cpi->bwd_fb_idx] == map[cpi->lst_fb_idxes[2]];
 
   const int bwd_is_gld = map[cpi->bwd_fb_idx] == map[cpi->gld_fb_idx];
-
 #endif  // CONFIG_ONE_SIDED_COMPOUND
+
+#if CONFIG_ALTREF2
+  const int alt2_is_last = map[cpi->alt2_fb_idx] == map[cpi->lst_fb_idxes[0]];
+  const int alt2_is_last2 = map[cpi->alt2_fb_idx] == map[cpi->lst_fb_idxes[1]];
+  const int alt2_is_last3 = map[cpi->alt2_fb_idx] == map[cpi->lst_fb_idxes[2]];
+  const int alt2_is_gld = map[cpi->alt2_fb_idx] == map[cpi->gld_fb_idx];
+  const int alt2_is_bwd = map[cpi->alt2_fb_idx] == map[cpi->bwd_fb_idx];
+#endif  // CONFIG_ALTREF2
+
   const int last2_is_alt = map[cpi->lst_fb_idxes[1]] == map[cpi->alt_fb_idx];
   const int last3_is_alt = map[cpi->lst_fb_idxes[2]] == map[cpi->alt_fb_idx];
   const int gld_is_alt = map[cpi->gld_fb_idx] == map[cpi->alt_fb_idx];
   const int bwd_is_alt = map[cpi->bwd_fb_idx] == map[cpi->alt_fb_idx];
+#if CONFIG_ALTREF2
+  const int alt2_is_alt = map[cpi->alt2_fb_idx] == map[cpi->alt_fb_idx];
+#endif  // CONFIG_ALTREF2
 #else   // !CONFIG_EXT_REFS
   const int gld_is_last = map[cpi->gld_fb_idx] == map[cpi->lst_fb_idx];
   const int gld_is_alt = map[cpi->gld_fb_idx] == map[cpi->alt_fb_idx];
@@ -4425,10 +4503,12 @@
   int flags = AOM_REFFRAME_ALL;
 
 #if CONFIG_EXT_REFS
+#if !CONFIG_ALTREF2
   // Disable the use of BWDREF_FRAME for non-bipredictive frames.
   if (!(cpi->rc.is_bipred_frame || cpi->rc.is_last_bipred_frame ||
         (cpi->rc.is_bwd_ref_frame && cpi->num_extra_arfs)))
     flags &= ~AOM_BWD_FLAG;
+#endif  // !CONFIG_ALTREF2
 #endif  // CONFIG_EXT_REFS
 
   if (gld_is_last || gld_is_alt) flags &= ~AOM_GOLD_FLAG;
@@ -4447,12 +4527,19 @@
 #if CONFIG_ONE_SIDED_COMPOUND  // Changes LL & HL bitstream
   /* Allow biprediction between two identical frames (e.g. bwd_is_last = 1) */
   if (bwd_is_alt && (flags & AOM_BWD_FLAG)) flags &= ~AOM_BWD_FLAG;
-#else
+#else   // !CONFIG_ONE_SIDED_COMPOUND
   if ((bwd_is_last || bwd_is_last2 || bwd_is_last3 || bwd_is_gld ||
        bwd_is_alt) &&
       (flags & AOM_BWD_FLAG))
     flags &= ~AOM_BWD_FLAG;
-#endif
+#endif  // CONFIG_ONE_SIDED_COMPOUND
+
+#if CONFIG_ALTREF2
+  if ((alt2_is_last || alt2_is_last2 || alt2_is_last3 || alt2_is_gld ||
+       alt2_is_bwd || alt2_is_alt) &&
+      (flags & AOM_ALT2_FLAG))
+    flags &= ~AOM_ALT2_FLAG;
+#endif  // CONFIG_ALTREF2
 #endif  // CONFIG_EXT_REFS
 
   return flags;
@@ -4480,11 +4567,17 @@
   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'
+// The arf_sign_bias will be one for internal ARFs'
+#if CONFIG_ALTREF2
+  arf_sign_bias = cpi->rc.source_alt_ref_active &&
+                  (!cpi->refresh_alt_ref_frame ||
+                   gf_group->update_type[gf_group->index] == INTNL_ARF_UPDATE);
+#else   // !CONFIG_ALTREF2
   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
+#endif  // CONFIG_ALTREF2
+#else   // !CONFIG_EXT_REFS
   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 &&
@@ -4499,6 +4592,10 @@
   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];
+#if CONFIG_ALTREF2
+  cm->ref_frame_sign_bias[ALTREF2_FRAME] =
+      cm->ref_frame_sign_bias[ALTREF_FRAME];
+#endif  // CONFIG_ALTREF2
 #endif  // CONFIG_EXT_REFS
 }
 
@@ -4509,13 +4606,18 @@
   int mask = 0;
   int arf_idx = ALTREF_FRAME;
 
-#if CONFIG_EXT_REFS
+#if CONFIG_EXT_REFS && !CONFIG_ALTREF2
   // 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  // CONFIG_EXT_REFS
+#endif  // CONFIG_EXT_REFS && !CONFIG_ALTREF2
 
+#if CONFIG_ALTREF2
+  if (cpi->common.last_frame_type == KEY_FRAME || cpi->refresh_alt_ref_frame ||
+      cpi->refresh_alt2_ref_frame)
+#else   // !CONFIG_ALTREF2
   if (cpi->common.last_frame_type == KEY_FRAME || cpi->refresh_alt_ref_frame)
+#endif  // CONFIG_ALTREF2
     return mask;
 
 #if CONFIG_EXT_REFS
@@ -4523,9 +4625,11 @@
     for (ifilter = EIGHTTAP_REGULAR; ifilter < SWITCHABLE_FILTERS; ++ifilter)
       ref_total[ref] += cpi->interp_filter_selected[ref][ifilter];
 
+#if !CONFIG_ALTREF2
   for (ifilter = EIGHTTAP_REGULAR; ifilter < SWITCHABLE_FILTERS; ++ifilter)
     ref_total[ref] += cpi->interp_filter_selected[arf_idx][ifilter];
-#else
+#endif  // !CONFIG_ALTREF2
+#else   // !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];
@@ -4549,6 +4653,11 @@
         (ref_total[BWDREF_FRAME] == 0 ||
          cpi->interp_filter_selected[BWDREF_FRAME][ifilter] * 50 <
              ref_total[BWDREF_FRAME]) &&
+#if CONFIG_ALTREF2
+        (ref_total[ALTREF2_FRAME] == 0 ||
+         cpi->interp_filter_selected[ALTREF2_FRAME][ifilter] * 50 <
+             ref_total[ALTREF2_FRAME]) &&
+#endif  // CONFIG_ALTREF2
 #endif  // CONFIG_EXT_REFS
         (ref_total[ALTREF_FRAME] == 0 ||
          cpi->interp_filter_selected[arf_idx][ifilter] * 50 <
@@ -4596,6 +4705,19 @@
       cpi->refresh_alt_ref_frame,
       cpi->twopass.gf_group.rf_level[cpi->twopass.gf_group.index],
       recon_buf->y_stride, recon_buf->uv_stride, cm->width, cm->height);
+#if 0
+  int ref_frame;
+  printf("get_ref_frame_map_idx: [");
+  for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame)
+    printf(" %d", get_ref_frame_map_idx(cpi, ref_frame));
+  printf(" ]\n");
+  printf("cm->new_fb_idx = %d\n", cm->new_fb_idx);
+  printf("cm->ref_frame_map = [");
+  for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
+    printf(" %d", cm->ref_frame_map[ref_frame - LAST_FRAME]);
+  }
+  printf(" ]\n");
+#endif  // 0
 
   // --- Y ---
   for (h = 0; h < cm->height; ++h) {
@@ -4676,6 +4798,9 @@
     cpi->refresh_last_frame = 0;
     cpi->refresh_golden_frame = 0;
     cpi->refresh_bwd_ref_frame = 0;
+#if CONFIG_ALTREF2
+    cpi->refresh_alt2_ref_frame = 0;
+#endif  // CONFIG_ALTREF2
     cpi->refresh_alt_ref_frame = 0;
 
     cpi->rc.is_bwd_ref_frame = 0;
@@ -4694,6 +4819,15 @@
 #endif  // DUMP_RECON_FRAMES
 
     // Update the LAST_FRAME in the reference frame buffer.
+    // NOTE:
+    // (1) For BWDREF_FRAME as the show_existing_frame, the reference frame
+    //     update has been done previously when handling the LAST_BIPRED_FRAME
+    //     right before BWDREF_FRAME (in the display order);
+    // (2) For INTNL_OVERLAY as the show_existing_frame, the reference frame
+    //     update will be done when the following is called, which will exchange
+    //     the virtual indexes between LAST_FRAME and ALTREF2_FRAME, so that
+    //     LAST3 will get retired, LAST2 becomes LAST3, LAST becomes LAST2, and
+    //     ALTREF2_FRAME will serve as the new LAST_FRAME.
     av1_update_reference_frames(cpi);
 
     // Update frame flags
@@ -5192,6 +5326,9 @@
          cpi->refresh_golden_frame ||
 #if CONFIG_EXT_REFS
          cpi->refresh_bwd_ref_frame ||
+#if CONFIG_ALTREF2
+         cpi->refresh_alt2_ref_frame ||
+#endif  // CONFIG_ALTREF2
 #endif  // CONFIG_EXT_REFS
          cpi->refresh_alt_ref_frame || !cm->error_resilient_mode ||
          cm->lf.mode_ref_delta_update || cm->seg.update_map ||
@@ -5274,6 +5411,23 @@
 
   return brf_src_index;
 }
+
+#if CONFIG_ALTREF2
+// Returns 0 if this is not an alt ref else the offset of the source frame
+// used as the arf midpoint.
+static int get_arf2_src_index(AV1_COMP *cpi) {
+  int arf2_src_index = 0;
+  if (is_altref_enabled(cpi) && cpi->num_extra_arfs) {
+    if (cpi->oxcf.pass == 2) {
+      const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
+      if (gf_group->update_type[gf_group->index] == INTNL_ARF_UPDATE) {
+        arf2_src_index = gf_group->arf_src_offset[gf_group->index];
+      }
+    }
+  }
+  return arf2_src_index;
+}
+#endif  // CONFIG_ALTREF2
 #endif  // CONFIG_EXT_REFS
 
 static void check_src_altref(AV1_COMP *cpi,
@@ -5290,6 +5444,10 @@
         (gf_group->update_type[gf_group->index] == INTNL_OVERLAY_UPDATE) ||
 #endif  // CONFIG_EXT_REFS
         (gf_group->update_type[gf_group->index] == OVERLAY_UPDATE);
+#if CONFIG_EXT_REFS && CONFIG_ALTREF2
+    rc->is_src_frame_ext_arf =
+        gf_group->update_type[gf_group->index] == INTNL_OVERLAY_UPDATE;
+#endif  // CONFIG_EXT_REFS && CONFIG_ALTREF2
   } else {
     rc->is_src_frame_alt_ref =
         cpi->alt_ref_source && (source == cpi->alt_ref_source);
@@ -5299,9 +5457,20 @@
     // Current frame is an ARF overlay frame.
     cpi->alt_ref_source = NULL;
 
-    // Don't refresh the last buffer for an ARF overlay frame. It will
-    // become the GF so preserve last as an alternative prediction option.
-    cpi->refresh_last_frame = 0;
+#if CONFIG_EXT_REFS && CONFIG_ALTREF2
+    if (rc->is_src_frame_ext_arf && !cpi->common.show_existing_frame) {
+      // For INTNL_OVERLAY, when show_existing_frame == 0, they do need to
+      // refresh the LAST_FRAME, i.e. LAST3 gets retired, LAST2 becomes LAST3,
+      // LAST becomes LAST2, and INTNL_OVERLAY becomes LAST.
+      cpi->refresh_last_frame = 1;
+    } else {
+#endif  // CONFIG_EXT_REFS && CONFIG_ALTREF2
+      // Don't refresh the last buffer for an ARF overlay frame. It will
+      // become the GF so preserve last as an alternative prediction option.
+      cpi->refresh_last_frame = 0;
+#if CONFIG_EXT_REFS && CONFIG_ALTREF2
+    }
+#endif  // CONFIG_EXT_REFS && CONFIG_ALTREF2
   }
 }
 
@@ -5474,6 +5643,9 @@
   cpi->refresh_golden_frame = 0;
 #if CONFIG_EXT_REFS
   cpi->refresh_bwd_ref_frame = 0;
+#if CONFIG_ALTREF2
+  cpi->refresh_alt2_ref_frame = 0;
+#endif  // CONFIG_ALTREF2
 #endif  // CONFIG_EXT_REFS
   cpi->refresh_alt_ref_frame = 0;
 
@@ -5569,14 +5741,64 @@
       cm->show_frame = 0;
       cm->intra_only = 0;
       cpi->refresh_alt_ref_frame = 1;
-      cpi->refresh_golden_frame = 0;
       cpi->refresh_last_frame = 0;
+      cpi->refresh_golden_frame = 0;
+#if CONFIG_EXT_REFS
+      cpi->refresh_bwd_ref_frame = 0;
+#if CONFIG_ALTREF2
+      cpi->refresh_alt2_ref_frame = 0;
+#endif  // CONFIG_ALTREF2
+#endif  // CONFIG_EXT_REFS
       rc->is_src_frame_alt_ref = 0;
     }
     rc->source_alt_ref_pending = 0;
   }
 
 #if CONFIG_EXT_REFS
+#if CONFIG_ALTREF2
+  // Should we encode an arf2 frame.
+  arf_src_index = get_arf2_src_index(cpi);
+  if (arf_src_index) {
+    for (i = 0; i <= arf_src_index; ++i) {
+      struct lookahead_entry *e = av1_lookahead_peek(cpi->lookahead, i);
+      // Avoid creating an alt-ref if there's a forced keyframe pending.
+      if (e == NULL) {
+        break;
+      } else if (e->flags == AOM_EFLAG_FORCE_KF) {
+        arf_src_index = 0;
+        flush = 1;
+        break;
+      }
+    }
+  }
+
+  if (arf_src_index) {
+    assert(arf_src_index <= rc->frames_to_key);
+
+    if ((source = av1_lookahead_peek(cpi->lookahead, arf_src_index)) != NULL) {
+      cpi->alt_ref_source = source;
+
+      if (oxcf->arnr_max_frames > 0) {
+        // Produce the filtered ARF frame.
+        av1_temporal_filter(cpi, arf_src_index);
+        aom_extend_frame_borders(&cpi->alt_ref_buffer);
+        force_src_buffer = &cpi->alt_ref_buffer;
+      }
+
+      cm->show_frame = 0;
+      cm->intra_only = 0;
+      cpi->refresh_alt2_ref_frame = 1;
+      cpi->refresh_last_frame = 0;
+      cpi->refresh_golden_frame = 0;
+      cpi->refresh_bwd_ref_frame = 0;
+      cpi->refresh_alt_ref_frame = 0;
+      rc->is_src_frame_alt_ref = 0;
+      rc->is_src_frame_ext_arf = 0;
+    }
+    rc->source_alt_ref_pending = 0;
+  }
+#endif  // CONFIG_ALTREF2
+
   rc->is_bwd_ref_frame = 0;
   brf_src_index = get_brf_src_index(cpi);
   if (brf_src_index) {
@@ -5588,6 +5810,9 @@
       cpi->refresh_bwd_ref_frame = 1;
       cpi->refresh_last_frame = 0;
       cpi->refresh_golden_frame = 0;
+#if CONFIG_ALTREF2
+      cpi->refresh_alt2_ref_frame = 0;
+#endif  // CONFIG_ALTREF2
       cpi->refresh_alt_ref_frame = 0;
 
       rc->is_bwd_ref_frame = 1;
@@ -5658,11 +5883,13 @@
   cm->cur_frame = &pool->frame_bufs[cm->new_fb_idx];
 
 #if CONFIG_EXT_REFS
+#if !CONFIG_ALTREF2
   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
+#endif  // !CONFIG_ALTREF2
+#else   // !CONFIG_EXT_REFS
   if (cpi->multi_arf_allowed) {
     if (cm->frame_type == KEY_FRAME) {
       init_buffer_indices(cpi);
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h
index 8ed8e0a..66e509f 100644
--- a/av1/encoder/encoder.h
+++ b/av1/encoder/encoder.h
@@ -107,8 +107,11 @@
   FRAMEFLAGS_GOLDEN = 1 << 1,
 #if CONFIG_EXT_REFS
   FRAMEFLAGS_BWDREF = 1 << 2,
+#if CONFIG_ALTREF2
+// TODO(zoeliu): To determine whether a frame flag is needed for ALTREF2_FRAME
+#endif  // CONFIG_ALTREF2
   FRAMEFLAGS_ALTREF = 1 << 3,
-#else
+#else   // !CONFIG_EXT_REFS
   FRAMEFLAGS_ALTREF = 1 << 2,
 #endif  // CONFIG_EXT_REFS
 } FRAMETYPE_FLAGS;
@@ -407,8 +410,11 @@
 #endif  // CONFIG_EXT_REFS
   int gld_fb_idx;
 #if CONFIG_EXT_REFS
-  int bwd_fb_idx;  // BWD_REF_FRAME
-#endif             // CONFIG_EXT_REFS
+  int bwd_fb_idx;  // BWDREF_FRAME
+#if CONFIG_ALTREF2
+  int alt2_fb_idx;  // ALTREF2_FRAME
+#endif              // CONFIG_ALTREF2
+#endif              // CONFIG_EXT_REFS
   int alt_fb_idx;
 
   int last_show_frame_buf_idx;  // last show frame buffer index
@@ -417,6 +423,9 @@
   int refresh_golden_frame;
 #if CONFIG_EXT_REFS
   int refresh_bwd_ref_frame;
+#if CONFIG_ALTREF2
+  int refresh_alt2_ref_frame;
+#endif  // CONFIG_ALTREF2
 #endif  // CONFIG_EXT_REFS
   int refresh_alt_ref_frame;
 
@@ -667,6 +676,10 @@
 #if CONFIG_EXT_REFS
   else if (ref_frame == BWDREF_FRAME)
     return cpi->bwd_fb_idx;
+#if CONFIG_ALTREF2
+  else if (ref_frame == ALTREF2_FRAME)
+    return cpi->alt2_fb_idx;
+#endif  // CONFIG_ALTREF2
 #endif  // CONFIG_EXT_REFS
   else
     return cpi->alt_fb_idx;
diff --git a/av1/encoder/firstpass.c b/av1/encoder/firstpass.c
index e7d78d8..12d8799 100644
--- a/av1/encoder/firstpass.c
+++ b/av1/encoder/firstpass.c
@@ -1666,7 +1666,7 @@
   arf_buffer_indices[0] = ARF_SLOT1;
   arf_buffer_indices[1] = ARF_SLOT2;
 }
-#endif
+#endif  // !CONFIG_EXT_REFS
 
 static void allocate_gf_group_bits(AV1_COMP *cpi, int64_t gf_group_bits,
                                    double group_error, int gf_arf_bits) {
@@ -1726,6 +1726,7 @@
 
   // For key frames the frame target rate is already set and it
   // is also the golden frame.
+  // === [frame_index == 0] ===
   if (!key_frame) {
     if (rc->source_alt_ref_active) {
       gf_group->update_type[frame_index] = OVERLAY_UPDATE;
@@ -1763,6 +1764,7 @@
 #endif  // CONFIG_EXT_REFS
 
   // Store the bits to spend on the ARF if there is one.
+  // === [frame_index == 1] ===
   if (rc->source_alt_ref_pending) {
     gf_group->update_type[frame_index] = ARF_UPDATE;
     gf_group->rf_level[frame_index] = GF_ARF_STD;
@@ -1792,8 +1794,8 @@
     // 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;
+    arf_pos[0] = frame_index + cpi->num_extra_arfs +
+                 gf_group->arf_src_offset[frame_index] + 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);
@@ -1808,10 +1810,15 @@
 
 #if CONFIG_EXT_REFS
     // Insert an extra ARF
+    // === [frame_index == 2] ===
     if (cpi->num_extra_arfs) {
+#if CONFIG_ALTREF2
+      gf_group->update_type[frame_index] = INTNL_ARF_UPDATE;
+#else   // !CONFIG_ALTREF2
       gf_group->update_type[frame_index] = ARF_UPDATE;
-      // Note (weitinglin): GF_ARF_LOW is also used as an identifier
-      //                    for internal ALT_REF's:
+// Note (weitinglin): GF_ARF_LOW is also used as an identifier
+//                    for internal ALT_REF's:
+#endif  // CONFIG_ALTREF2
       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;
@@ -1819,7 +1826,7 @@
       ++frame_index;
     }
     accumulative_subgroup_interval += subgroup_interval[cpi->num_extra_arfs];
-#else
+#else   // !CONFIG_EXT_ARFS
     if (cpi->multi_arf_enabled) {
       // Set aside a slot for a level 1 arf.
       gf_group->update_type[frame_index] = ARF_UPDATE;
@@ -1875,8 +1882,11 @@
         clamp(target_frame_size, 0, AOMMIN(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 we are going to have ARFs, check whether we can have BWDREF in this
+    // subgroup, and further, whether we can have ARF subgroup which contains
+    // the BWDREF subgroup but contained within the GF group:
+    //
+    // GF group --> ARF subgroup --> BWDREF subgroup
     if (rc->source_alt_ref_pending) {
       is_sg_bipred_enabled =
           is_bipred_enabled &&
@@ -1953,16 +1963,20 @@
     ++frame_index;
 
 #if CONFIG_EXT_REFS
-    // Check if we need to update the ARF
+    // Check if we need to update the ARF.
     if (is_sg_bipred_enabled && cpi->num_extra_arfs && which_arf > 0 &&
         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;
+      // 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) {
+#if CONFIG_ALTREF2
+        gf_group->update_type[frame_index] = INTNL_ARF_UPDATE;
+#else  // !CONFIG_ALTREF2
         gf_group->update_type[frame_index] = ARF_UPDATE;
+#endif  // CONFIG_ALTREF2
         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;
@@ -1991,11 +2005,15 @@
 
 #if CONFIG_EXT_REFS
     if (cpi->num_extra_arfs) {
+      // Overwrite the update_type for internal ARF's:
+      //   Change from LF_UPDATE to INTNL_OVERLAY_UPDATE.
       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;
+        // Encoder's choice: Set show_existing_frame == 1 for both internal
+        // ARF's, and hence allocate zero bit for both internal OVERLAY frames.
         gf_group->bit_allocation[arf_pos[i]] = 0;
         gf_group->rf_level[arf_pos[i]] = INTER_NORMAL;
       }
@@ -2702,7 +2720,7 @@
 static void configure_buffer_updates(AV1_COMP *cpi) {
   TWO_PASS *const twopass = &cpi->twopass;
 
-  // Wei-Ting: Should we define another function to take care of
+  // NOTE(weitinglin): Should we define another function to take care of
   // cpi->rc.is_$Source_Type to make this function as it is in the comment?
 
   cpi->rc.is_src_frame_alt_ref = 0;
@@ -2714,19 +2732,29 @@
 #endif  // CONFIG_EXT_REFS
 
   switch (twopass->gf_group.update_type[twopass->gf_group.index]) {
-    case KF_UPDATE:
+    case KF_UPDATE: cpi->refresh_last_frame = 1; cpi->refresh_golden_frame = 1;
 #if CONFIG_EXT_REFS
       cpi->refresh_bwd_ref_frame = 1;
+#if CONFIG_ALTREF2
+      cpi->refresh_alt2_ref_frame = 1;
+#endif  // CONFIG_ALTREF2
 #endif  // CONFIG_EXT_REFS
-      cpi->refresh_last_frame = 1;
-      cpi->refresh_golden_frame = 1;
       cpi->refresh_alt_ref_frame = 1;
       break;
 
-    case LF_UPDATE:
+    case LF_UPDATE: cpi->refresh_last_frame = 1; cpi->refresh_golden_frame = 0;
 #if CONFIG_EXT_REFS
-      // If we have extra ALT_REFs, we can use the farthest ALT (ALT0) as
-      // the BWD_REF.
+      cpi->refresh_bwd_ref_frame = 0;
+#if CONFIG_ALTREF2
+      cpi->refresh_alt2_ref_frame = 0;
+#endif  // CONFIG_ALTREF2
+#endif  // CONFIG_EXT_REFS
+      cpi->refresh_alt_ref_frame = 0;
+
+#if CONFIG_EXT_REFS && !CONFIG_ALTREF2
+      // If we have extra ALT_REFs, we may use the farthest ALT (ALT0) as
+      // the BWDREF_FRAME, as LF_UPDATE frames do not have BWDREF_FRAME
+      // available as their reference.
       if (cpi->num_extra_arfs) {
         int tmp = cpi->bwd_fb_idx;
 
@@ -2735,21 +2763,21 @@
         cpi->arf_map[0] = tmp;
 
         cpi->rc.is_bwd_ref_frame = 1;
-      } else {
-        cpi->rc.is_bwd_ref_frame = 0;
       }
-#endif  // CONFIG_EXT_REFS
-      cpi->refresh_last_frame = 1;
-      cpi->refresh_golden_frame = 0;
-      cpi->refresh_alt_ref_frame = 0;
+#endif  // CONFIG_EXT_REFS && !CONFIG_ALTREF2
       break;
 
     case GF_UPDATE:
-#if CONFIG_EXT_REFS
-      cpi->refresh_bwd_ref_frame = 0;
-#endif  // CONFIG_EXT_REFS
+      // TODO(zoeliu): To further investigate whether 'refresh_last_frame' is
+      //               needed.
       cpi->refresh_last_frame = 1;
       cpi->refresh_golden_frame = 1;
+#if CONFIG_EXT_REFS
+      cpi->refresh_bwd_ref_frame = 0;
+#if CONFIG_ALTREF2
+      cpi->refresh_alt2_ref_frame = 0;
+#endif  // CONFIG_ALTREF2
+#endif  // CONFIG_EXT_REFS
       cpi->refresh_alt_ref_frame = 0;
       break;
 
@@ -2758,17 +2786,25 @@
       cpi->refresh_golden_frame = 1;
 #if CONFIG_EXT_REFS
       cpi->refresh_bwd_ref_frame = 0;
+#if CONFIG_ALTREF2
+      cpi->refresh_alt2_ref_frame = 0;
+#endif  // CONFIG_ALTREF2
 #endif  // CONFIG_EXT_REFS
       cpi->refresh_alt_ref_frame = 0;
+
       cpi->rc.is_src_frame_alt_ref = 1;
       break;
 
-    case ARF_UPDATE:
+    case ARF_UPDATE: cpi->refresh_last_frame = 0; cpi->refresh_golden_frame = 0;
 #if CONFIG_EXT_REFS
+#if CONFIG_ALTREF2
+      // NOTE: BWDREF does not get updated along with ALTREF_FRAME.
+      cpi->refresh_bwd_ref_frame = 0;
+      cpi->refresh_alt2_ref_frame = 0;
+#else   // !CONFIG_ALTREF2
       cpi->refresh_bwd_ref_frame = 1;
+#endif  // CONFIG_ALTREF2
 #endif  // CONFIG_EXT_REFS
-      cpi->refresh_last_frame = 0;
-      cpi->refresh_golden_frame = 0;
       cpi->refresh_alt_ref_frame = 1;
       break;
 
@@ -2777,8 +2813,12 @@
       cpi->refresh_last_frame = 0;
       cpi->refresh_golden_frame = 0;
       cpi->refresh_bwd_ref_frame = 1;
+#if CONFIG_ALTREF2
+      cpi->refresh_alt2_ref_frame = 0;
+#endif  // CONFIG_ALTREF2
       cpi->refresh_alt_ref_frame = 0;
-      cpi->rc.is_bwd_ref_frame = 1;
+
+#if !CONFIG_ALTREF2
       if (cpi->num_extra_arfs) {
         // Allow BRF use the farthest ALT_REF (ALT0) as BWD_REF by swapping
         // the virtual indices.
@@ -2790,13 +2830,19 @@
         cpi->alt_fb_idx = cpi->arf_map[0];
         cpi->arf_map[0] = tmp;
       }
+#endif  // !CONFIG_ALTREF2
+      cpi->rc.is_bwd_ref_frame = 1;
       break;
 
     case LAST_BIPRED_UPDATE:
       cpi->refresh_last_frame = 1;
       cpi->refresh_golden_frame = 0;
       cpi->refresh_bwd_ref_frame = 0;
+#if CONFIG_ALTREF2
+      cpi->refresh_alt2_ref_frame = 0;
+#endif  // CONFIG_ALTREF2
       cpi->refresh_alt_ref_frame = 0;
+
       cpi->rc.is_last_bipred_frame = 1;
       break;
 
@@ -2804,7 +2850,11 @@
       cpi->refresh_last_frame = 1;
       cpi->refresh_golden_frame = 0;
       cpi->refresh_bwd_ref_frame = 0;
+#if CONFIG_ALTREF2
+      cpi->refresh_alt2_ref_frame = 0;
+#endif  // CONFIG_ALTREF2
       cpi->refresh_alt_ref_frame = 0;
+
       cpi->rc.is_bipred_frame = 1;
       break;
 
@@ -2812,10 +2862,24 @@
       cpi->refresh_last_frame = 1;
       cpi->refresh_golden_frame = 0;
       cpi->refresh_bwd_ref_frame = 0;
+#if CONFIG_ALTREF2
+      cpi->refresh_alt2_ref_frame = 0;
+#endif  // CONFIG_ALTREF2
       cpi->refresh_alt_ref_frame = 0;
+
       cpi->rc.is_src_frame_alt_ref = 1;
       cpi->rc.is_src_frame_ext_arf = 1;
       break;
+
+#if CONFIG_ALTREF2
+    case INTNL_ARF_UPDATE:
+      cpi->refresh_last_frame = 0;
+      cpi->refresh_golden_frame = 0;
+      cpi->refresh_bwd_ref_frame = 0;
+      cpi->refresh_alt2_ref_frame = 1;
+      cpi->refresh_alt_ref_frame = 0;
+      break;
+#endif  // CONFIG_ALTREF2
 #endif  // CONFIG_EXT_REFS
 
     default: assert(0); break;
@@ -2857,7 +2921,11 @@
 
   // If this is an arf frame then we dont want to read the stats file or
   // advance the input pointer as we already have what we need.
-  if (gf_group->update_type[gf_group->index] == ARF_UPDATE) {
+  if (gf_group->update_type[gf_group->index] == ARF_UPDATE
+#if CONFIG_EXT_REFS && CONFIG_ALTREF2
+      || gf_group->update_type[gf_group->index] == INTNL_ARF_UPDATE
+#endif  // CONFIG_EXT_REFS && CONFIG_ALTREF2
+      ) {
     configure_buffer_updates(cpi);
     target_rate = gf_group->bit_allocation[gf_group->index];
     target_rate = av1_rc_clamp_pframe_target_size(cpi, target_rate);
diff --git a/av1/encoder/firstpass.h b/av1/encoder/firstpass.h
index 266766d..3b7c2b5 100644
--- a/av1/encoder/firstpass.h
+++ b/av1/encoder/firstpass.h
@@ -101,8 +101,13 @@
   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
+#if CONFIG_ALTREF2
+  INTNL_ARF_UPDATE = 9,  // Internal Altref Frame (candidate for ALTREF2)
+  FRAME_UPDATE_TYPES = 10
+#else   // !CONFIG_ALTREF2
   FRAME_UPDATE_TYPES = 9
-#else
+#endif  // CONFIG_ALTREF2
+#else   // !CONFIG_EXT_REFS
   FRAME_UPDATE_TYPES = 5
 #endif  // CONFIG_EXT_REFS
 } FRAME_UPDATE_TYPE;
diff --git a/av1/encoder/ratectrl.c b/av1/encoder/ratectrl.c
index b546fdf..a1f53b7 100644
--- a/av1/encoder/ratectrl.c
+++ b/av1/encoder/ratectrl.c
@@ -579,8 +579,11 @@
     active_worst_quality =
         curr_frame == 0 ? rc->worst_quality : rc->last_q[KEY_FRAME] * 2;
   } else {
-    if (!rc->is_src_frame_alt_ref &&
-        (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)) {
+    if (!rc->is_src_frame_alt_ref && (cpi->refresh_golden_frame ||
+#if CONFIG_EXT_REFS && CONFIG_ALTREF2
+                                      cpi->refresh_alt2_ref_frame ||
+#endif  // CONFIG_EXT_REFS && CONFIG_ALTREF2
+                                      cpi->refresh_alt_ref_frame)) {
       active_worst_quality = curr_frame == 1 ? rc->last_q[KEY_FRAME] * 5 / 4
                                              : rc->last_q[INTER_FRAME];
     } else {
@@ -1005,8 +1008,11 @@
       active_best_quality +=
           av1_compute_qdelta(rc, q_val, q_val * q_adj_factor, cm->bit_depth);
     }
-  } else if (!rc->is_src_frame_alt_ref &&
-             (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)) {
+  } else if (!rc->is_src_frame_alt_ref && (cpi->refresh_golden_frame ||
+#if CONFIG_EXT_REFS && CONFIG_ALTREF2
+                                           cpi->refresh_alt2_ref_frame ||
+#endif  // CONFIG_EXT_REFS && CONFIG_ALTREF2
+                                           cpi->refresh_alt_ref_frame)) {
     // Use the lower of active_worst_quality and recent
     // average Q as basis for GF/ARF best Q limit unless last frame was
     // a key frame.
@@ -1026,7 +1032,11 @@
       active_best_quality = active_best_quality * 15 / 16;
 
     } else if (oxcf->rc_mode == AOM_Q) {
+#if CONFIG_EXT_REFS && CONFIG_ALTREF2
+      if (!cpi->refresh_alt_ref_frame && !cpi->refresh_alt2_ref_frame) {
+#else
       if (!cpi->refresh_alt_ref_frame) {
+#endif  // CONFIG_EXT_REFS && CONFIG_ALTREF2
         active_best_quality = cq_level;
       } else {
         active_best_quality = get_gf_active_quality(rc, q, cm->bit_depth);
@@ -1058,8 +1068,11 @@
   if ((cpi->oxcf.rc_mode != AOM_Q) &&
       (cpi->twopass.gf_zeromotion_pct < VLOW_MOTION_THRESHOLD)) {
     if (frame_is_intra_only(cm) ||
-        (!rc->is_src_frame_alt_ref &&
-         (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame))) {
+        (!rc->is_src_frame_alt_ref && (cpi->refresh_golden_frame ||
+#if CONFIG_EXT_REFS && CONFIG_ALTREF2
+                                       cpi->refresh_alt2_ref_frame ||
+#endif  // CONFIG_EXT_REFS && CONFIG_ALTREF2
+                                       cpi->refresh_alt_ref_frame))) {
       active_best_quality -=
           (cpi->twopass.extend_minq + cpi->twopass.extend_minq_fast);
       active_worst_quality += (cpi->twopass.extend_maxq / 2);
@@ -1194,7 +1207,7 @@
   //                   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
+#else   // !CONFIG_EXT_REFS
   // Update the Golden frame usage counts.
   if (cpi->refresh_golden_frame) {
 #endif  // CONFIG_EXT_REFS
@@ -1219,7 +1232,11 @@
     // Decrement count down till next gf
     if (rc->frames_till_gf_update_due > 0) rc->frames_till_gf_update_due--;
 
+#if CONFIG_EXT_REFS && CONFIG_ALTREF2
+  } else if (!cpi->refresh_alt_ref_frame && !cpi->refresh_alt2_ref_frame) {
+#else
   } else if (!cpi->refresh_alt_ref_frame) {
+#endif  // CONFIG_EXT_REFS && CONFIG_ALTREF2
     // Decrement count down till next gf
     if (rc->frames_till_gf_update_due > 0) rc->frames_till_gf_update_due--;
 
@@ -1249,7 +1266,11 @@
         ROUND_POWER_OF_TWO(3 * rc->avg_frame_qindex[KEY_FRAME] + qindex, 2);
   } else {
     if (!rc->is_src_frame_alt_ref &&
-        !(cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)) {
+        !(cpi->refresh_golden_frame ||
+#if CONFIG_EXT_REFS && CONFIG_ALTREF2
+          cpi->refresh_alt2_ref_frame ||
+#endif  // CONFIG_EXT_REFS && CONFIG_ALTREF2
+          cpi->refresh_alt_ref_frame)) {
       rc->last_q[INTER_FRAME] = qindex;
       rc->avg_frame_qindex[INTER_FRAME] =
           ROUND_POWER_OF_TWO(3 * rc->avg_frame_qindex[INTER_FRAME] + qindex, 2);
@@ -1271,6 +1292,9 @@
   if ((qindex < rc->last_boosted_qindex) || (cm->frame_type == KEY_FRAME) ||
       (!rc->constrained_gf_group &&
        (cpi->refresh_alt_ref_frame ||
+#if CONFIG_EXT_REFS && CONFIG_ALTREF2
+        cpi->refresh_alt2_ref_frame ||
+#endif  // CONFIG_EXT_REFS && CONFIG_ALTREF2
         (cpi->refresh_golden_frame && !rc->is_src_frame_alt_ref)))) {
     rc->last_boosted_qindex = qindex;
   }
@@ -1294,6 +1318,8 @@
   // Actual bits spent
   rc->total_actual_bits += rc->projected_frame_size;
 #if CONFIG_EXT_REFS
+  // TODO(zoeliu): To investigate whether we should treat BWDREF_FRAME
+  //               differently here for rc->avg_frame_bandwidth.
   rc->total_target_bits +=
       (cm->show_frame || rc->is_bwd_ref_frame) ? rc->avg_frame_bandwidth : 0;
 #else
@@ -1313,6 +1339,8 @@
   if (cm->frame_type == KEY_FRAME) rc->frames_since_key = 0;
 
 #if CONFIG_EXT_REFS
+  // TODO(zoeliu): To investigate whether we should treat BWDREF_FRAME
+  //               differently here for rc->avg_frame_bandwidth.
   if (cm->show_frame || rc->is_bwd_ref_frame) {
 #else
   if (cm->show_frame) {
diff --git a/av1/encoder/rd.c b/av1/encoder/rd.c
index 9e1cf76..2c91a35 100644
--- a/av1/encoder/rd.c
+++ b/av1/encoder/rd.c
@@ -311,7 +311,11 @@
   // TODO(weitinglin): We should investigate if the values should be the same
   //                   as the value used by OVERLAY frame
   ,
-  144
+  144  // INTNL_OVERLAY_UPDATE
+#if CONFIG_ALTREF2
+  ,
+  128   // INTNL_ARF_UPDATE
+#endif  // CONFIG_ALTREF2
 #endif  // CONFIG_EXT_REFS
 };
 
@@ -959,6 +963,9 @@
     rd->thresh_mult[THR_NEARESTL2] = 300;
     rd->thresh_mult[THR_NEARESTL3] = 300;
     rd->thresh_mult[THR_NEARESTB] = 300;
+#if CONFIG_ALTREF2
+    rd->thresh_mult[THR_NEARESTA2] = 300;
+#endif  // CONFIG_ALTREF2
 #endif  // CONFIG_EXT_REFS
     rd->thresh_mult[THR_NEARESTA] = 300;
     rd->thresh_mult[THR_NEARESTG] = 300;
@@ -968,6 +975,9 @@
     rd->thresh_mult[THR_NEARESTL2] = 0;
     rd->thresh_mult[THR_NEARESTL3] = 0;
     rd->thresh_mult[THR_NEARESTB] = 0;
+#if CONFIG_ALTREF2
+    rd->thresh_mult[THR_NEARESTA2] = 0;
+#endif  // CONFIG_ALTREF2
 #endif  // CONFIG_EXT_REFS
     rd->thresh_mult[THR_NEARESTA] = 0;
     rd->thresh_mult[THR_NEARESTG] = 0;
@@ -980,6 +990,9 @@
   rd->thresh_mult[THR_NEWL2] += 1000;
   rd->thresh_mult[THR_NEWL3] += 1000;
   rd->thresh_mult[THR_NEWB] += 1000;
+#if CONFIG_ALTREF2
+  rd->thresh_mult[THR_NEWA2] = 1000;
+#endif  // CONFIG_ALTREF2
 #endif  // CONFIG_EXT_REFS
   rd->thresh_mult[THR_NEWA] += 1000;
   rd->thresh_mult[THR_NEWG] += 1000;
@@ -989,6 +1002,9 @@
   rd->thresh_mult[THR_NEARL2] += 1000;
   rd->thresh_mult[THR_NEARL3] += 1000;
   rd->thresh_mult[THR_NEARB] += 1000;
+#if CONFIG_ALTREF2
+  rd->thresh_mult[THR_NEARA2] = 1000;
+#endif  // CONFIG_ALTREF2
 #endif  // CONFIG_EXT_REFS
   rd->thresh_mult[THR_NEARA] += 1000;
   rd->thresh_mult[THR_NEARG] += 1000;
@@ -998,6 +1014,9 @@
   rd->thresh_mult[THR_ZEROL2] += 2000;
   rd->thresh_mult[THR_ZEROL3] += 2000;
   rd->thresh_mult[THR_ZEROB] += 2000;
+#if CONFIG_ALTREF2
+  rd->thresh_mult[THR_ZEROA2] = 2000;
+#endif  // CONFIG_ALTREF2
 #endif  // CONFIG_EXT_REFS
   rd->thresh_mult[THR_ZEROG] += 2000;
   rd->thresh_mult[THR_ZEROA] += 2000;
@@ -1065,6 +1084,12 @@
   rd->thresh_mult[THR_COMP_NEAREST_NEARESTL2B] += 1000;
   rd->thresh_mult[THR_COMP_NEAREST_NEARESTL3B] += 1000;
   rd->thresh_mult[THR_COMP_NEAREST_NEARESTGB] += 1000;
+#if CONFIG_ALTREF2
+  rd->thresh_mult[THR_COMP_NEAREST_NEARESTLA2] += 1000;
+  rd->thresh_mult[THR_COMP_NEAREST_NEARESTL2A2] += 1000;
+  rd->thresh_mult[THR_COMP_NEAREST_NEARESTL3A2] += 1000;
+  rd->thresh_mult[THR_COMP_NEAREST_NEARESTGA2] += 1000;
+#endif  // CONFIG_ALTREF2
 
 #if CONFIG_EXT_COMP_REFS
   rd->thresh_mult[THR_COMP_NEAREST_NEARESTLL2] += 1000;
@@ -1087,6 +1112,13 @@
   rd->thresh_mult[THR_COMP_NEARESTL2B] += 1000;
   rd->thresh_mult[THR_COMP_NEARESTL3B] += 1000;
   rd->thresh_mult[THR_COMP_NEARESTGB] += 1000;
+#if CONFIG_ALTREF2
+  rd->thresh_mult[THR_COMP_NEARESTLA2] += 1000;
+  rd->thresh_mult[THR_COMP_NEARESTL2A2] += 1000;
+  rd->thresh_mult[THR_COMP_NEARESTL3A2] += 1000;
+  rd->thresh_mult[THR_COMP_NEARESTGA2] += 1000;
+#endif  // CONFIG_ALTREF2
+
 #if CONFIG_EXT_COMP_REFS
   rd->thresh_mult[THR_COMP_NEARESTLL2] += 1000;
   rd->thresh_mult[THR_COMP_NEARESTLL3] += 1000;
@@ -1166,6 +1198,40 @@
   rd->thresh_mult[THR_COMP_NEW_NEWGB] += 2000;
   rd->thresh_mult[THR_COMP_ZERO_ZEROGB] += 2500;
 
+#if CONFIG_ALTREF2
+  rd->thresh_mult[THR_COMP_NEAR_NEARLA2] += 1200;
+  rd->thresh_mult[THR_COMP_NEAREST_NEWLA2] += 1500;
+  rd->thresh_mult[THR_COMP_NEW_NEARESTLA2] += 1500;
+  rd->thresh_mult[THR_COMP_NEAR_NEWLA2] += 1700;
+  rd->thresh_mult[THR_COMP_NEW_NEARLA2] += 1700;
+  rd->thresh_mult[THR_COMP_NEW_NEWLA2] += 2000;
+  rd->thresh_mult[THR_COMP_ZERO_ZEROLA2] += 2500;
+
+  rd->thresh_mult[THR_COMP_NEAR_NEARL2A2] += 1200;
+  rd->thresh_mult[THR_COMP_NEAREST_NEWL2A2] += 1500;
+  rd->thresh_mult[THR_COMP_NEW_NEARESTL2A2] += 1500;
+  rd->thresh_mult[THR_COMP_NEAR_NEWL2A2] += 1700;
+  rd->thresh_mult[THR_COMP_NEW_NEARL2A2] += 1700;
+  rd->thresh_mult[THR_COMP_NEW_NEWL2A2] += 2000;
+  rd->thresh_mult[THR_COMP_ZERO_ZEROL2A2] += 2500;
+
+  rd->thresh_mult[THR_COMP_NEAR_NEARL3A2] += 1200;
+  rd->thresh_mult[THR_COMP_NEAREST_NEWL3A2] += 1500;
+  rd->thresh_mult[THR_COMP_NEW_NEARESTL3A2] += 1500;
+  rd->thresh_mult[THR_COMP_NEAR_NEWL3A2] += 1700;
+  rd->thresh_mult[THR_COMP_NEW_NEARL3A2] += 1700;
+  rd->thresh_mult[THR_COMP_NEW_NEWL3A2] += 2000;
+  rd->thresh_mult[THR_COMP_ZERO_ZEROL3A2] += 2500;
+
+  rd->thresh_mult[THR_COMP_NEAR_NEARGA2] += 1200;
+  rd->thresh_mult[THR_COMP_NEAREST_NEWGA2] += 1500;
+  rd->thresh_mult[THR_COMP_NEW_NEARESTGA2] += 1500;
+  rd->thresh_mult[THR_COMP_NEAR_NEWGA2] += 1700;
+  rd->thresh_mult[THR_COMP_NEW_NEARGA2] += 1700;
+  rd->thresh_mult[THR_COMP_NEW_NEWGA2] += 2000;
+  rd->thresh_mult[THR_COMP_ZERO_ZEROGA2] += 2500;
+#endif  // CONFIG_ALTREF2
+
 #if CONFIG_EXT_COMP_REFS
   rd->thresh_mult[THR_COMP_NEAR_NEARLL2] += 1200;
   rd->thresh_mult[THR_COMP_NEAREST_NEWLL2] += 1500;
@@ -1224,6 +1290,17 @@
   rd->thresh_mult[THR_COMP_NEARGB] += 1500;
   rd->thresh_mult[THR_COMP_NEWGB] += 2000;
 
+#if CONFIG_ALTREF2
+  rd->thresh_mult[THR_COMP_NEARLA2] += 1500;
+  rd->thresh_mult[THR_COMP_NEWLA2] += 2000;
+  rd->thresh_mult[THR_COMP_NEARL2A2] += 1500;
+  rd->thresh_mult[THR_COMP_NEWL2A2] += 2000;
+  rd->thresh_mult[THR_COMP_NEARL3A2] += 1500;
+  rd->thresh_mult[THR_COMP_NEWL3A2] += 2000;
+  rd->thresh_mult[THR_COMP_NEARGA2] += 1500;
+  rd->thresh_mult[THR_COMP_NEWGA2] += 2000;
+#endif  // CONFIG_ALTREF2
+
 #if CONFIG_EXT_COMP_REFS
   rd->thresh_mult[THR_COMP_NEARLL2] += 1500;
   rd->thresh_mult[THR_COMP_NEWLL2] += 2000;
@@ -1249,6 +1326,13 @@
   rd->thresh_mult[THR_COMP_ZEROL3B] += 2500;
   rd->thresh_mult[THR_COMP_ZEROGB] += 2500;
 
+#if CONFIG_ALTREF2
+  rd->thresh_mult[THR_COMP_ZEROLA2] += 2500;
+  rd->thresh_mult[THR_COMP_ZEROL2A2] += 2500;
+  rd->thresh_mult[THR_COMP_ZEROL3A2] += 2500;
+  rd->thresh_mult[THR_COMP_ZEROGA2] += 2500;
+#endif  // CONFIG_ALTREF2
+
 #if CONFIG_EXT_COMP_REFS
   rd->thresh_mult[THR_COMP_ZEROLL2] += 2500;
   rd->thresh_mult[THR_COMP_ZEROLL3] += 2500;
@@ -1296,6 +1380,13 @@
   rd->thresh_mult[THR_COMP_INTERINTRA_NEARESTB] += 1500;
   rd->thresh_mult[THR_COMP_INTERINTRA_NEARB] += 1500;
   rd->thresh_mult[THR_COMP_INTERINTRA_NEWB] += 2000;
+
+#if CONFIG_ALTREF2
+  rd->thresh_mult[THR_COMP_INTERINTRA_ZEROA2] += 1500;
+  rd->thresh_mult[THR_COMP_INTERINTRA_NEARESTA2] += 1500;
+  rd->thresh_mult[THR_COMP_INTERINTRA_NEARA2] += 1500;
+  rd->thresh_mult[THR_COMP_INTERINTRA_NEWA2] += 2000;
+#endif  // CONFIG_ALTREF2
 #endif  // CONFIG_EXT_REFS
 
   rd->thresh_mult[THR_COMP_INTERINTRA_ZEROA] += 1500;
@@ -1312,6 +1403,9 @@
     2500,
     2500,
     2500,
+#if CONFIG_ALTREF2
+    2500,
+#endif  // CONFIG_ALTREF2
     2500,
     2500,
     4500,
@@ -1322,8 +1416,14 @@
     4500,
     4500,
     4500,
+#if CONFIG_ALTREF2
+    4500,
+    4500,
+    4500,
+    4500,
+#endif  // CONFIG_ALTREF2
     2500
-#else
+#else  // !CONFIG_EXT_REFS
     2500,
     2500,
     2500,
diff --git a/av1/encoder/rd.h b/av1/encoder/rd.h
index 07f0dfc..a6cb4ca 100644
--- a/av1/encoder/rd.h
+++ b/av1/encoder/rd.h
@@ -45,12 +45,6 @@
 
 #define INVALID_MV 0x80008000
 
-#if CONFIG_EXT_REFS
-#define MAX_REFS 15
-#else
-#define MAX_REFS 6
-#endif  // CONFIG_EXT_REFS
-
 #define RD_THRESH_MAX_FACT 64
 #define RD_THRESH_INC 1
 
@@ -62,6 +56,9 @@
   THR_NEARESTL2,
   THR_NEARESTL3,
   THR_NEARESTB,
+#if CONFIG_ALTREF2
+  THR_NEARESTA2,
+#endif  // CONFIG_ALTREF2
 #endif  // CONFIG_EXT_REFS
   THR_NEARESTA,
   THR_NEARESTG,
@@ -73,6 +70,9 @@
   THR_NEWL2,
   THR_NEWL3,
   THR_NEWB,
+#if CONFIG_ALTREF2
+  THR_NEWA2,
+#endif  // CONFIG_ALTREF2
 #endif  // CONFIG_EXT_REFS
   THR_NEWA,
   THR_NEWG,
@@ -82,6 +82,9 @@
   THR_NEARL2,
   THR_NEARL3,
   THR_NEARB,
+#if CONFIG_ALTREF2
+  THR_NEARA2,
+#endif  // CONFIG_ALTREF2
 #endif  // CONFIG_EXT_REFS
   THR_NEARA,
   THR_NEARG,
@@ -91,9 +94,12 @@
   THR_ZEROL2,
   THR_ZEROL3,
   THR_ZEROB,
+#if CONFIG_ALTREF2
+  THR_ZEROA2,
+#endif  // CONFIG_ALTREF2
 #endif  // CONFIG_EXT_REFS
-  THR_ZEROG,
   THR_ZEROA,
+  THR_ZEROG,
 
 #if CONFIG_EXT_INTER
 
@@ -156,6 +162,12 @@
   THR_COMP_NEAREST_NEARESTL2B,
   THR_COMP_NEAREST_NEARESTL3B,
   THR_COMP_NEAREST_NEARESTGB,
+#if CONFIG_ALTREF2
+  THR_COMP_NEAREST_NEARESTLA2,
+  THR_COMP_NEAREST_NEARESTL2A2,
+  THR_COMP_NEAREST_NEARESTL3A2,
+  THR_COMP_NEAREST_NEARESTGA2,
+#endif  // CONFIG_ALTREF2
 #if CONFIG_EXT_COMP_REFS
   THR_COMP_NEAREST_NEARESTLL2,
   THR_COMP_NEAREST_NEARESTLL3,
@@ -177,6 +189,12 @@
   THR_COMP_NEARESTL2B,
   THR_COMP_NEARESTL3B,
   THR_COMP_NEARESTGB,
+#if CONFIG_ALTREF2
+  THR_COMP_NEARESTLA2,
+  THR_COMP_NEARESTL2A2,
+  THR_COMP_NEARESTL3A2,
+  THR_COMP_NEARESTGA2,
+#endif  // CONFIG_ALTREF2
 #if CONFIG_EXT_COMP_REFS
   THR_COMP_NEARESTLL2,
   THR_COMP_NEARESTLL3,
@@ -266,6 +284,40 @@
   THR_COMP_NEW_NEWGB,
   THR_COMP_ZERO_ZEROGB,
 
+#if CONFIG_ALTREF2
+  THR_COMP_NEAR_NEARLA2,
+  THR_COMP_NEW_NEARESTLA2,
+  THR_COMP_NEAREST_NEWLA2,
+  THR_COMP_NEW_NEARLA2,
+  THR_COMP_NEAR_NEWLA2,
+  THR_COMP_NEW_NEWLA2,
+  THR_COMP_ZERO_ZEROLA2,
+
+  THR_COMP_NEAR_NEARL2A2,
+  THR_COMP_NEW_NEARESTL2A2,
+  THR_COMP_NEAREST_NEWL2A2,
+  THR_COMP_NEW_NEARL2A2,
+  THR_COMP_NEAR_NEWL2A2,
+  THR_COMP_NEW_NEWL2A2,
+  THR_COMP_ZERO_ZEROL2A2,
+
+  THR_COMP_NEAR_NEARL3A2,
+  THR_COMP_NEW_NEARESTL3A2,
+  THR_COMP_NEAREST_NEWL3A2,
+  THR_COMP_NEW_NEARL3A2,
+  THR_COMP_NEAR_NEWL3A2,
+  THR_COMP_NEW_NEWL3A2,
+  THR_COMP_ZERO_ZEROL3A2,
+
+  THR_COMP_NEAR_NEARGA2,
+  THR_COMP_NEW_NEARESTGA2,
+  THR_COMP_NEAREST_NEWGA2,
+  THR_COMP_NEW_NEARGA2,
+  THR_COMP_NEAR_NEWGA2,
+  THR_COMP_NEW_NEWGA2,
+  THR_COMP_ZERO_ZEROGA2,
+#endif  // CONFIG_ALTREF2
+
 #if CONFIG_EXT_COMP_REFS
   THR_COMP_NEAR_NEARLL2,
   THR_COMP_NEW_NEARESTLL2,
@@ -324,6 +376,17 @@
   THR_COMP_NEARGB,
   THR_COMP_NEWGB,
 
+#if CONFIG_ALTREF2
+  THR_COMP_NEARLA2,
+  THR_COMP_NEWLA2,
+  THR_COMP_NEARL2A2,
+  THR_COMP_NEWL2A2,
+  THR_COMP_NEARL3A2,
+  THR_COMP_NEWL3A2,
+  THR_COMP_NEARGA2,
+  THR_COMP_NEWGA2,
+#endif  // CONFIG_ALTREF2
+
 #if CONFIG_EXT_COMP_REFS
   THR_COMP_NEARLL2,
   THR_COMP_NEWLL2,
@@ -349,6 +412,13 @@
   THR_COMP_ZEROL3B,
   THR_COMP_ZEROGB,
 
+#if CONFIG_ALTREF2
+  THR_COMP_ZEROLA2,
+  THR_COMP_ZEROL2A2,
+  THR_COMP_ZEROL3A2,
+  THR_COMP_ZEROGA2,
+#endif  // CONFIG_ALTEF2
+
 #if CONFIG_EXT_COMP_REFS
   THR_COMP_ZEROLL2,
   THR_COMP_ZEROLL3,
@@ -396,6 +466,13 @@
   THR_COMP_INTERINTRA_NEARESTB,
   THR_COMP_INTERINTRA_NEARB,
   THR_COMP_INTERINTRA_NEWB,
+
+#if CONFIG_ALTREF2
+  THR_COMP_INTERINTRA_ZEROA2,
+  THR_COMP_INTERINTRA_NEARESTA2,
+  THR_COMP_INTERINTRA_NEARA2,
+  THR_COMP_INTERINTRA_NEWA2,
+#endif  // CONFIG_ALTREF2
 #endif  // CONFIG_EXT_REFS
 
   THR_COMP_INTERINTRA_ZEROA,
@@ -412,6 +489,9 @@
   THR_LAST2,
   THR_LAST3,
   THR_BWDR,
+#if CONFIG_ALTREF2
+  THR_ALTR2,
+#endif  // CONFIG_ALTREF2
 #endif  // CONFIG_EXT_REFS
   THR_GOLD,
   THR_ALTR,
@@ -428,9 +508,18 @@
   THR_COMP_L2B,
   THR_COMP_L3B,
   THR_COMP_GB,
+
+#if CONFIG_ALTREF2
+  THR_COMP_LA2,
+  THR_COMP_L2A2,
+  THR_COMP_L3A2,
+  THR_COMP_GA2,
+#endif  // CONFIG_ALTREF2
 #endif  // CONFIG_EXT_REFS
 
   THR_INTRA,
+
+  MAX_REFS
 } THR_MODES_SUB8X8;
 
 typedef struct RD_OPT {
diff --git a/av1/encoder/rdopt.c b/av1/encoder/rdopt.c
index 85ed073..89b4313 100644
--- a/av1/encoder/rdopt.c
+++ b/av1/encoder/rdopt.c
@@ -82,6 +82,39 @@
 
 #if CONFIG_EXT_REFS
 
+#if CONFIG_ALTREF2
+
+#define LAST_FRAME_MODE_MASK                                          \
+  ((1 << INTRA_FRAME) | (1 << LAST2_FRAME) | (1 << LAST3_FRAME) |     \
+   (1 << GOLDEN_FRAME) | (1 << BWDREF_FRAME) | (1 << ALTREF2_FRAME) | \
+   (1 << ALTREF_FRAME))
+#define LAST2_FRAME_MODE_MASK                                         \
+  ((1 << INTRA_FRAME) | (1 << LAST_FRAME) | (1 << LAST3_FRAME) |      \
+   (1 << GOLDEN_FRAME) | (1 << BWDREF_FRAME) | (1 << ALTREF2_FRAME) | \
+   (1 << ALTREF_FRAME))
+#define LAST3_FRAME_MODE_MASK                                         \
+  ((1 << INTRA_FRAME) | (1 << LAST_FRAME) | (1 << LAST2_FRAME) |      \
+   (1 << GOLDEN_FRAME) | (1 << BWDREF_FRAME) | (1 << ALTREF2_FRAME) | \
+   (1 << ALTREF_FRAME))
+#define GOLDEN_FRAME_MODE_MASK                                       \
+  ((1 << INTRA_FRAME) | (1 << LAST_FRAME) | (1 << LAST2_FRAME) |     \
+   (1 << LAST3_FRAME) | (1 << BWDREF_FRAME) | (1 << ALTREF2_FRAME) | \
+   (1 << ALTREF_FRAME))
+#define BWDREF_FRAME_MODE_MASK                                       \
+  ((1 << INTRA_FRAME) | (1 << LAST_FRAME) | (1 << LAST2_FRAME) |     \
+   (1 << LAST3_FRAME) | (1 << GOLDEN_FRAME) | (1 << ALTREF2_FRAME) | \
+   (1 << ALTREF_FRAME))
+#define ALTREF2_FRAME_MODE_MASK                                     \
+  ((1 << INTRA_FRAME) | (1 << LAST_FRAME) | (1 << LAST2_FRAME) |    \
+   (1 << LAST3_FRAME) | (1 << GOLDEN_FRAME) | (1 << BWDREF_FRAME) | \
+   (1 << ALTREF_FRAME))
+#define ALTREF_FRAME_MODE_MASK                                      \
+  ((1 << INTRA_FRAME) | (1 << LAST_FRAME) | (1 << LAST2_FRAME) |    \
+   (1 << LAST3_FRAME) | (1 << GOLDEN_FRAME) | (1 << BWDREF_FRAME) | \
+   (1 << ALTREF2_FRAME))
+
+#else  // CONFIG_ALTREF2
+
 #define LAST_FRAME_MODE_MASK                                      \
   ((1 << INTRA_FRAME) | (1 << LAST2_FRAME) | (1 << LAST3_FRAME) | \
    (1 << GOLDEN_FRAME) | (1 << BWDREF_FRAME) | (1 << ALTREF_FRAME))
@@ -101,7 +134,9 @@
   ((1 << INTRA_FRAME) | (1 << LAST_FRAME) | (1 << LAST2_FRAME) | \
    (1 << LAST3_FRAME) | (1 << GOLDEN_FRAME) | (1 << BWDREF_FRAME))
 
-#else
+#endif  // CONFIG_ALTREF2
+
+#else  // !CONFIG_EXT_REFS
 
 #define LAST_FRAME_MODE_MASK \
   ((1 << GOLDEN_FRAME) | (1 << ALTREF_FRAME) | (1 << INTRA_FRAME))
@@ -118,7 +153,12 @@
   ((1 << ALTREF_FRAME) | (1 << BWDREF_FRAME) | (1 << GOLDEN_FRAME) | \
    (1 << LAST2_FRAME) | 0x01)  // NOLINT
 #else                          // !CONFIG_EXT_COMP_REFS
+#if CONFIG_ALTREF2
+#define SECOND_REF_FRAME_MASK \
+  ((1 << ALTREF_FRAME) | (1 << ALTREF2_FRAME) | (1 << BWDREF_FRAME) | 0x01)
+#else  // !CONFIG_ALTREF2
 #define SECOND_REF_FRAME_MASK ((1 << ALTREF_FRAME) | (1 << BWDREF_FRAME) | 0x01)
+#endif  // CONFIG_ALTREF2
 #endif  // CONFIG_EXT_COMP_REFS
 #else   // !CONFIG_EXT_REFS
 #define SECOND_REF_FRAME_MASK ((1 << ALTREF_FRAME) | 0x01)
@@ -166,6 +206,9 @@
   { NEARESTMV, { LAST2_FRAME, NONE_FRAME } },
   { NEARESTMV, { LAST3_FRAME, NONE_FRAME } },
   { NEARESTMV, { BWDREF_FRAME, NONE_FRAME } },
+#if CONFIG_ALTREF2
+  { NEARESTMV, { ALTREF2_FRAME, NONE_FRAME } },
+#endif  // CONFIG_ALTREF2
 #endif  // CONFIG_EXT_REFS
   { NEARESTMV, { ALTREF_FRAME, NONE_FRAME } },
   { NEARESTMV, { GOLDEN_FRAME, NONE_FRAME } },
@@ -177,6 +220,9 @@
   { NEWMV, { LAST2_FRAME, NONE_FRAME } },
   { NEWMV, { LAST3_FRAME, NONE_FRAME } },
   { NEWMV, { BWDREF_FRAME, NONE_FRAME } },
+#if CONFIG_ALTREF2
+  { NEWMV, { ALTREF2_FRAME, NONE_FRAME } },
+#endif  // CONFIG_ALTREF2
 #endif  // CONFIG_EXT_REFS
   { NEWMV, { ALTREF_FRAME, NONE_FRAME } },
   { NEWMV, { GOLDEN_FRAME, NONE_FRAME } },
@@ -186,6 +232,9 @@
   { NEARMV, { LAST2_FRAME, NONE_FRAME } },
   { NEARMV, { LAST3_FRAME, NONE_FRAME } },
   { NEARMV, { BWDREF_FRAME, NONE_FRAME } },
+#if CONFIG_ALTREF2
+  { NEARMV, { ALTREF2_FRAME, NONE_FRAME } },
+#endif  // CONFIG_ALTREF2
 #endif  // CONFIG_EXT_REFS
   { NEARMV, { ALTREF_FRAME, NONE_FRAME } },
   { NEARMV, { GOLDEN_FRAME, NONE_FRAME } },
@@ -195,6 +244,9 @@
   { ZEROMV, { LAST2_FRAME, NONE_FRAME } },
   { ZEROMV, { LAST3_FRAME, NONE_FRAME } },
   { ZEROMV, { BWDREF_FRAME, NONE_FRAME } },
+#if CONFIG_ALTREF2
+  { ZEROMV, { ALTREF2_FRAME, NONE_FRAME } },
+#endif  // CONFIG_ALTREF2
 #endif  // CONFIG_EXT_REFS
   { ZEROMV, { GOLDEN_FRAME, NONE_FRAME } },
   { ZEROMV, { ALTREF_FRAME, NONE_FRAME } },
@@ -263,6 +315,12 @@
   { NEAREST_NEARESTMV, { LAST2_FRAME, BWDREF_FRAME } },
   { NEAREST_NEARESTMV, { LAST3_FRAME, BWDREF_FRAME } },
   { NEAREST_NEARESTMV, { GOLDEN_FRAME, BWDREF_FRAME } },
+#if CONFIG_ALTREF2
+  { NEAREST_NEARESTMV, { LAST_FRAME, ALTREF2_FRAME } },
+  { NEAREST_NEARESTMV, { LAST2_FRAME, ALTREF2_FRAME } },
+  { NEAREST_NEARESTMV, { LAST3_FRAME, ALTREF2_FRAME } },
+  { NEAREST_NEARESTMV, { GOLDEN_FRAME, ALTREF2_FRAME } },
+#endif  // CONFIG_ALTREF2
 
 #if CONFIG_EXT_COMP_REFS
   { NEAREST_NEARESTMV, { LAST_FRAME, LAST2_FRAME } },
@@ -285,6 +343,12 @@
   { NEARESTMV, { LAST2_FRAME, BWDREF_FRAME } },
   { NEARESTMV, { LAST3_FRAME, BWDREF_FRAME } },
   { NEARESTMV, { GOLDEN_FRAME, BWDREF_FRAME } },
+#if CONFIG_ALTREF2
+  { NEARESTMV, { LAST_FRAME, ALTREF2_FRAME } },
+  { NEARESTMV, { LAST2_FRAME, ALTREF2_FRAME } },
+  { NEARESTMV, { LAST3_FRAME, ALTREF2_FRAME } },
+  { NEARESTMV, { GOLDEN_FRAME, ALTREF2_FRAME } },
+#endif  // CONFIG_ALTREF2
 
 #if CONFIG_EXT_COMP_REFS
   { NEARESTMV, { LAST_FRAME, LAST2_FRAME } },
@@ -373,6 +437,40 @@
   { NEW_NEWMV, { GOLDEN_FRAME, BWDREF_FRAME } },
   { ZERO_ZEROMV, { GOLDEN_FRAME, BWDREF_FRAME } },
 
+#if CONFIG_ALTREF2
+  { NEAR_NEARMV, { LAST_FRAME, ALTREF2_FRAME } },
+  { NEW_NEARESTMV, { LAST_FRAME, ALTREF2_FRAME } },
+  { NEAREST_NEWMV, { LAST_FRAME, ALTREF2_FRAME } },
+  { NEW_NEARMV, { LAST_FRAME, ALTREF2_FRAME } },
+  { NEAR_NEWMV, { LAST_FRAME, ALTREF2_FRAME } },
+  { NEW_NEWMV, { LAST_FRAME, ALTREF2_FRAME } },
+  { ZERO_ZEROMV, { LAST_FRAME, ALTREF2_FRAME } },
+
+  { NEAR_NEARMV, { LAST2_FRAME, ALTREF2_FRAME } },
+  { NEW_NEARESTMV, { LAST2_FRAME, ALTREF2_FRAME } },
+  { NEAREST_NEWMV, { LAST2_FRAME, ALTREF2_FRAME } },
+  { NEW_NEARMV, { LAST2_FRAME, ALTREF2_FRAME } },
+  { NEAR_NEWMV, { LAST2_FRAME, ALTREF2_FRAME } },
+  { NEW_NEWMV, { LAST2_FRAME, ALTREF2_FRAME } },
+  { ZERO_ZEROMV, { LAST2_FRAME, ALTREF2_FRAME } },
+
+  { NEAR_NEARMV, { LAST3_FRAME, ALTREF2_FRAME } },
+  { NEW_NEARESTMV, { LAST3_FRAME, ALTREF2_FRAME } },
+  { NEAREST_NEWMV, { LAST3_FRAME, ALTREF2_FRAME } },
+  { NEW_NEARMV, { LAST3_FRAME, ALTREF2_FRAME } },
+  { NEAR_NEWMV, { LAST3_FRAME, ALTREF2_FRAME } },
+  { NEW_NEWMV, { LAST3_FRAME, ALTREF2_FRAME } },
+  { ZERO_ZEROMV, { LAST3_FRAME, ALTREF2_FRAME } },
+
+  { NEAR_NEARMV, { GOLDEN_FRAME, ALTREF2_FRAME } },
+  { NEW_NEARESTMV, { GOLDEN_FRAME, ALTREF2_FRAME } },
+  { NEAREST_NEWMV, { GOLDEN_FRAME, ALTREF2_FRAME } },
+  { NEW_NEARMV, { GOLDEN_FRAME, ALTREF2_FRAME } },
+  { NEAR_NEWMV, { GOLDEN_FRAME, ALTREF2_FRAME } },
+  { NEW_NEWMV, { GOLDEN_FRAME, ALTREF2_FRAME } },
+  { ZERO_ZEROMV, { GOLDEN_FRAME, ALTREF2_FRAME } },
+#endif  // CONFIG_ALTREF2
+
 #if CONFIG_EXT_COMP_REFS
   { NEAR_NEARMV, { LAST_FRAME, LAST2_FRAME } },
   { NEW_NEARESTMV, { LAST_FRAME, LAST2_FRAME } },
@@ -431,6 +529,17 @@
   { NEARMV, { GOLDEN_FRAME, BWDREF_FRAME } },
   { NEWMV, { GOLDEN_FRAME, BWDREF_FRAME } },
 
+#if CONFIG_ALTREF2
+  { NEARMV, { LAST_FRAME, ALTREF2_FRAME } },
+  { NEWMV, { LAST_FRAME, ALTREF2_FRAME } },
+  { NEARMV, { LAST2_FRAME, ALTREF2_FRAME } },
+  { NEWMV, { LAST2_FRAME, ALTREF2_FRAME } },
+  { NEARMV, { LAST3_FRAME, ALTREF2_FRAME } },
+  { NEWMV, { LAST3_FRAME, ALTREF2_FRAME } },
+  { NEARMV, { GOLDEN_FRAME, ALTREF2_FRAME } },
+  { NEWMV, { GOLDEN_FRAME, ALTREF2_FRAME } },
+#endif  // CONFIG_ALTREF2
+
 #if CONFIG_EXT_COMP_REFS
   { NEARMV, { LAST_FRAME, LAST2_FRAME } },
   { NEWMV, { LAST_FRAME, LAST2_FRAME } },
@@ -456,6 +565,13 @@
   { ZEROMV, { LAST3_FRAME, BWDREF_FRAME } },
   { ZEROMV, { GOLDEN_FRAME, BWDREF_FRAME } },
 
+#if CONFIG_ALTREF2
+  { ZEROMV, { LAST_FRAME, ALTREF2_FRAME } },
+  { ZEROMV, { LAST2_FRAME, ALTREF2_FRAME } },
+  { ZEROMV, { LAST3_FRAME, ALTREF2_FRAME } },
+  { ZEROMV, { GOLDEN_FRAME, ALTREF2_FRAME } },
+#endif  // CONFIG_ALTREF2
+
 #if CONFIG_EXT_COMP_REFS
   { ZEROMV, { LAST_FRAME, LAST2_FRAME } },
   { ZEROMV, { LAST_FRAME, LAST3_FRAME } },
@@ -503,6 +619,13 @@
   { NEARESTMV, { BWDREF_FRAME, INTRA_FRAME } },
   { NEARMV, { BWDREF_FRAME, INTRA_FRAME } },
   { NEWMV, { BWDREF_FRAME, INTRA_FRAME } },
+
+#if CONFIG_ALTREF2
+  { ZEROMV, { ALTREF2_FRAME, INTRA_FRAME } },
+  { NEARESTMV, { ALTREF2_FRAME, INTRA_FRAME } },
+  { NEARMV, { ALTREF2_FRAME, INTRA_FRAME } },
+  { NEWMV, { ALTREF2_FRAME, INTRA_FRAME } },
+#endif  // CONFIG_ALTREF2
 #endif  // CONFIG_EXT_REFS
 
   { ZEROMV, { ALTREF_FRAME, INTRA_FRAME } },
@@ -6555,6 +6678,9 @@
       aom_prob ref_single_p3 = av1_get_pred_prob_single_ref_p3(cm, xd);
       aom_prob ref_single_p4 = av1_get_pred_prob_single_ref_p4(cm, xd);
       aom_prob ref_single_p5 = av1_get_pred_prob_single_ref_p5(cm, xd);
+#if CONFIG_ALTREF2
+      aom_prob ref_single_p6 = av1_get_pred_prob_single_ref_p6(cm, xd);
+#endif  // CONFIG_ALTREF2
 #endif  // CONFIG_EXT_REFS
 
       unsigned int base_cost = av1_cost_bit(intra_inter_p, 1);
@@ -6563,9 +6689,12 @@
 #if CONFIG_EXT_REFS
           ref_costs_single[LAST2_FRAME] = ref_costs_single[LAST3_FRAME] =
               ref_costs_single[BWDREF_FRAME] =
+#if CONFIG_ALTREF2
+                  ref_costs_single[ALTREF2_FRAME] =
+#endif  // CONFIG_ALTREF2
 #endif  // CONFIG_EXT_REFS
-                  ref_costs_single[GOLDEN_FRAME] =
-                      ref_costs_single[ALTREF_FRAME] = base_cost;
+                      ref_costs_single[GOLDEN_FRAME] =
+                          ref_costs_single[ALTREF_FRAME] = base_cost;
 
 #if CONFIG_EXT_REFS
       ref_costs_single[LAST_FRAME] += av1_cost_bit(ref_single_p1, 0);
@@ -6573,6 +6702,9 @@
       ref_costs_single[LAST3_FRAME] += av1_cost_bit(ref_single_p1, 0);
       ref_costs_single[GOLDEN_FRAME] += av1_cost_bit(ref_single_p1, 0);
       ref_costs_single[BWDREF_FRAME] += av1_cost_bit(ref_single_p1, 1);
+#if CONFIG_ALTREF2
+      ref_costs_single[ALTREF2_FRAME] += av1_cost_bit(ref_single_p1, 1);
+#endif  // CONFIG_ALTREF2
       ref_costs_single[ALTREF_FRAME] += av1_cost_bit(ref_single_p1, 1);
 
       ref_costs_single[LAST_FRAME] += av1_cost_bit(ref_single_p3, 0);
@@ -6581,6 +6713,9 @@
       ref_costs_single[GOLDEN_FRAME] += av1_cost_bit(ref_single_p3, 1);
 
       ref_costs_single[BWDREF_FRAME] += av1_cost_bit(ref_single_p2, 0);
+#if CONFIG_ALTREF2
+      ref_costs_single[ALTREF2_FRAME] += av1_cost_bit(ref_single_p2, 0);
+#endif  // CONFIG_ALTREF2
       ref_costs_single[ALTREF_FRAME] += av1_cost_bit(ref_single_p2, 1);
 
       ref_costs_single[LAST_FRAME] += av1_cost_bit(ref_single_p4, 0);
@@ -6588,6 +6723,11 @@
 
       ref_costs_single[LAST3_FRAME] += av1_cost_bit(ref_single_p5, 0);
       ref_costs_single[GOLDEN_FRAME] += av1_cost_bit(ref_single_p5, 1);
+
+#if CONFIG_ALTREF2
+      ref_costs_single[BWDREF_FRAME] += av1_cost_bit(ref_single_p6, 0);
+      ref_costs_single[ALTREF2_FRAME] += av1_cost_bit(ref_single_p6, 1);
+#endif  // CONFIG_ALTREF2
 #else   // !CONFIG_EXT_REFS
       ref_costs_single[LAST_FRAME] += av1_cost_bit(ref_single_p1, 0);
       ref_costs_single[GOLDEN_FRAME] += av1_cost_bit(ref_single_p1, 1);
@@ -6602,6 +6742,9 @@
       ref_costs_single[LAST2_FRAME] = 512;
       ref_costs_single[LAST3_FRAME] = 512;
       ref_costs_single[BWDREF_FRAME] = 512;
+#if CONFIG_ALTREF2
+      ref_costs_single[ALTREF2_FRAME] = 512;
+#endif  // CONFIG_ALTREF2
 #endif  // CONFIG_EXT_REFS
       ref_costs_single[GOLDEN_FRAME] = 512;
       ref_costs_single[ALTREF_FRAME] = 512;
@@ -6613,6 +6756,9 @@
       aom_prob ref_comp_p1 = av1_get_pred_prob_comp_ref_p1(cm, xd);
       aom_prob ref_comp_p2 = av1_get_pred_prob_comp_ref_p2(cm, xd);
       aom_prob bwdref_comp_p = av1_get_pred_prob_comp_bwdref_p(cm, xd);
+#if CONFIG_ALTREF2
+      aom_prob bwdref_comp_p1 = av1_get_pred_prob_comp_bwdref_p1(cm, xd);
+#endif  // CONFIG_ALTREF2
 #endif  // CONFIG_EXT_REFS
 
       unsigned int base_cost = av1_cost_bit(intra_inter_p, 1);
@@ -6681,7 +6827,11 @@
               ref_costs_comp[GOLDEN_FRAME] = base_cost;
 
 #if CONFIG_EXT_REFS
-      ref_costs_comp[BWDREF_FRAME] = ref_costs_comp[ALTREF_FRAME] = 0;
+      ref_costs_comp[BWDREF_FRAME] =
+#if CONFIG_ALTREF2
+          ref_costs_comp[ALTREF2_FRAME] =
+#endif  // CONFIG_ALTREF2
+              ref_costs_comp[ALTREF_FRAME] = 0;
 #endif  // CONFIG_EXT_REFS
 
 #if CONFIG_EXT_REFS
@@ -6699,7 +6849,15 @@
       // NOTE(zoeliu): BWDREF and ALTREF each add an extra cost by coding 1
       //               more bit.
       ref_costs_comp[BWDREF_FRAME] += av1_cost_bit(bwdref_comp_p, 0);
+#if CONFIG_ALTREF2
+      ref_costs_comp[ALTREF2_FRAME] += av1_cost_bit(bwdref_comp_p, 0);
+#endif  // CONFIG_ALTREF2
       ref_costs_comp[ALTREF_FRAME] += av1_cost_bit(bwdref_comp_p, 1);
+
+#if CONFIG_ALTREF2
+      ref_costs_comp[BWDREF_FRAME] += av1_cost_bit(bwdref_comp_p1, 0);
+      ref_costs_comp[ALTREF2_FRAME] += av1_cost_bit(bwdref_comp_p1, 1);
+#endif  // CONFIG_ALTREF2
 #else   // !CONFIG_EXT_REFS
       ref_costs_comp[LAST_FRAME] += av1_cost_bit(ref_comp_p, 0);
       ref_costs_comp[GOLDEN_FRAME] += av1_cost_bit(ref_comp_p, 1);
@@ -6722,6 +6880,9 @@
       ref_costs_comp[LAST2_FRAME] = 512;
       ref_costs_comp[LAST3_FRAME] = 512;
       ref_costs_comp[BWDREF_FRAME] = 512;
+#if CONFIG_ALTREF2
+      ref_costs_comp[ALTREF2_FRAME] = 512;
+#endif  // CONFIG_ALTREF2
       ref_costs_comp[ALTREF_FRAME] = 512;
 #endif  // CONFIG_EXT_REFS
       ref_costs_comp[GOLDEN_FRAME] = 512;
@@ -10061,6 +10222,9 @@
     AOM_GOLD_FLAG,
 #if CONFIG_EXT_REFS
     AOM_BWD_FLAG,
+#if CONFIG_ALTREF2
+    AOM_ALT2_FLAG,
+#endif  // CONFIG_ALTREF2
 #endif  // CONFIG_EXT_REFS
     AOM_ALT_FLAG
   };
@@ -10295,25 +10459,11 @@
 
   for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
     if (!(cpi->ref_frame_flags & flag_list[ref_frame])) {
-// Skip checking missing references in both single and compound reference
-// modes. Note that a mode will be skipped iff both reference frames
-// are masked out.
-#if CONFIG_EXT_COMP_REFS
+      // Skip checking missing references in both single and compound reference
+      // modes. Note that a mode will be skipped iff both reference frames
+      // are masked out.
       ref_frame_skip_mask[0] |= (1 << ref_frame);
       ref_frame_skip_mask[1] |= SECOND_REF_FRAME_MASK;
-#else  // !CONFIG_EXT_COMP_REFS
-#if CONFIG_EXT_REFS
-      if (ref_frame == BWDREF_FRAME || ref_frame == ALTREF_FRAME) {
-        ref_frame_skip_mask[0] |= (1 << ref_frame);
-        ref_frame_skip_mask[1] |= ((1 << ref_frame) | 0x01);
-      } else {
-#endif  // CONFIG_EXT_REFS
-        ref_frame_skip_mask[0] |= (1 << ref_frame);
-        ref_frame_skip_mask[1] |= SECOND_REF_FRAME_MASK;
-#if CONFIG_EXT_REFS
-      }
-#endif  // CONFIG_EXT_REFS
-#endif  // CONFIG_EXT_COMP_REFS
     } else {
       for (i = LAST_FRAME; i <= ALTREF_FRAME; ++i) {
         // Skip fixed mv modes for poor references
@@ -10346,6 +10496,9 @@
 #if CONFIG_EXT_REFS
                                (1 << LAST2_FRAME) | (1 << LAST3_FRAME) |
                                (1 << BWDREF_FRAME) |
+#if CONFIG_ALTREF2
+                               (1 << ALTREF2_FRAME) |
+#endif  // CONFIG_ALTREF2
 #endif  // CONFIG_EXT_REFS
                                (1 << GOLDEN_FRAME);
       ref_frame_skip_mask[1] = SECOND_REF_FRAME_MASK;
@@ -10519,6 +10672,12 @@
           ref_frame_skip_mask[0] |= BWDREF_FRAME_MODE_MASK;
           ref_frame_skip_mask[1] |= SECOND_REF_FRAME_MASK;
           break;
+#if CONFIG_ALTREF2
+        case ALTREF2_FRAME:
+          ref_frame_skip_mask[0] |= ALTREF2_FRAME_MODE_MASK;
+          ref_frame_skip_mask[1] |= SECOND_REF_FRAME_MASK;
+          break;
+#endif  // CONFIG_ALTREF2
 #endif  // CONFIG_EXT_REFS
         case ALTREF_FRAME: ref_frame_skip_mask[0] |= ALTREF_FRAME_MODE_MASK;
 #if CONFIG_EXT_REFS
diff --git a/av1/encoder/temporal_filter.c b/av1/encoder/temporal_filter.c
index 6046479..560ddb4 100644
--- a/av1/encoder/temporal_filter.c
+++ b/av1/encoder/temporal_filter.c
@@ -618,7 +618,7 @@
   YV12_BUFFER_CONFIG *frames[MAX_LAG_BUFFERS] = { NULL };
 #if CONFIG_EXT_REFS
   const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
-#endif
+#endif  // CONFIG_EXT_REFS
 
   // Apply context specific adjustments to the arnr filter parameters.
   adjust_arnr_filter(cpi, distance, rc->gfu_boost, &frames_to_blur, &strength);
@@ -627,11 +627,18 @@
 //                   case it is more beneficial to use non-zero strength
 //                   filtering.
 #if CONFIG_EXT_REFS
+#if CONFIG_ALTREF2
+  if (gf_group->update_type[gf_group->index] == INTNL_ARF_UPDATE) {
+    strength = 0;
+    frames_to_blur = 1;
+  }
+#else   // !CONFIG_ALTREF2
   if (gf_group->rf_level[gf_group->index] == GF_ARF_LOW) {
     strength = 0;
     frames_to_blur = 1;
   }
-#endif
+#endif  // CONFIG_ALTREF2
+#endif  // CONFIG_EXT_REFS
 
 #if CONFIG_EXT_REFS
   if (strength == 0 && frames_to_blur == 1) {
@@ -639,7 +646,7 @@
   } else {
     cpi->is_arf_filter_off[gf_group->arf_update_idx[gf_group->index]] = 0;
   }
-#endif
+#endif  // CONFIG_EXT_REFS
 
   frames_to_blur_backward = (frames_to_blur / 2);
   frames_to_blur_forward = ((frames_to_blur - 1) / 2);