Support two scanning passes for rd_pick_partition.

Reset xd->mi and x->mbmi_ext for the superblock after the first
scanning pass.

Change-Id: Iae9142ff2b1a2b576f54dc545b58fe37c97cecac
diff --git a/av1/decoder/decodemv.c b/av1/decoder/decodemv.c
index f69e32b..159e18c 100644
--- a/av1/decoder/decodemv.c
+++ b/av1/decoder/decodemv.c
@@ -33,7 +33,7 @@
 
 #define ACCT_STR __func__
 
-#define COMPOUND_SINGLEREF_DEBUG 0
+#define DEC_MISMATCH_DEBUG 0
 
 #if CONFIG_EXT_INTRA || CONFIG_FILTER_INTRA || CONFIG_PALETTE
 static INLINE int read_uniform(aom_reader *r, int n) {
@@ -1937,6 +1937,64 @@
                        mi_row << pbi->common.mib_size_log2);
 }
 
+#if DEC_MISMATCH_DEBUG
+static void dec_dump_logs(AV1_COMMON *cm, MODE_INFO *const mi,
+                          MACROBLOCKD *const xd, int mi_row, int mi_col) {
+  int_mv mv[2] = { { 0 } };
+  int ref;
+  MB_MODE_INFO *const mbmi = &mi->mbmi;
+  int16_t inter_mode_ctx[MODE_CTX_REF_FRAMES];
+  int16_t mode_ctx = 0;
+  for (ref = 0; ref < 1 + has_second_ref(mbmi); ++ref)
+    mv[ref].as_mv = mbmi->mv[ref].as_mv;
+
+  int interp_ctx[2] = { -1 };
+  int interp_filter[2] = { cm->interp_filter };
+  if (cm->interp_filter == SWITCHABLE) {
+    int dir;
+    for (dir = 0; dir < 2; ++dir) {
+      if (has_subpel_mv_component(xd->mi[0], xd, dir) ||
+          (mbmi->ref_frame[1] > INTRA_FRAME &&
+           has_subpel_mv_component(xd->mi[0], xd, dir + 2))) {
+        interp_ctx[dir] = av1_get_pred_context_switchable_interp(xd, dir);
+        interp_filter[dir] = mbmi->interp_filter[dir];
+      } else {
+        interp_filter[dir] = EIGHTTAP_REGULAR;
+      }
+    }
+  }
+
+  const int16_t newmv_ctx = mode_ctx & NEWMV_CTX_MASK;
+  int16_t zeromv_ctx = -1;
+  int16_t refmv_ctx = -1;
+  if (mbmi->mode != NEWMV) {
+    if (mode_ctx & (1 << ALL_ZERO_FLAG_OFFSET)) assert(mbmi->mode == ZEROMV);
+    zeromv_ctx = (mode_ctx >> ZEROMV_OFFSET) & ZEROMV_CTX_MASK;
+    if (mbmi->mode != ZEROMV) {
+      refmv_ctx = (mode_ctx >> REFMV_OFFSET) & REFMV_CTX_MASK;
+      if (mode_ctx & (1 << SKIP_NEARESTMV_OFFSET)) refmv_ctx = 6;
+      if (mode_ctx & (1 << SKIP_NEARMV_OFFSET)) refmv_ctx = 7;
+      if (mode_ctx & (1 << SKIP_NEARESTMV_SUB8X8_OFFSET)) refmv_ctx = 8;
+    }
+  }
+
+  int8_t ref_frame_type = av1_ref_frame_type(mbmi->ref_frame);
+  printf(
+      "=== DECODER ===: "
+      "Frame=%d, (mi_row,mi_col)=(%d,%d), mode=%d, bsize=%d, "
+      "show_frame=%d, mv[0]=(%d,%d), mv[1]=(%d,%d), ref[0]=%d, "
+      "ref[1]=%d, motion_mode=%d, inter_mode_ctx=%d, mode_ctx=%d, "
+      "interp_ctx=(%d,%d), interp_filter=(%d,%d), newmv_ctx=%d, "
+      "zeromv_ctx=%d, refmv_ctx=%d\n",
+      cm->current_video_frame, mi_row, mi_col, mbmi->mode, mbmi->sb_type,
+      cm->show_frame, mv[0].as_mv.row, mv[0].as_mv.col, mv[1].as_mv.row,
+      mv[1].as_mv.col, mbmi->ref_frame[0], mbmi->ref_frame[1],
+      mbmi->motion_mode, inter_mode_ctx[ref_frame_type], mode_ctx,
+      interp_ctx[0], interp_ctx[1], interp_filter[0], interp_filter[1],
+      newmv_ctx, zeromv_ctx, refmv_ctx);
+}
+#endif  // DEC_MISMATCH_DEBUG
+
 static void read_inter_block_mode_info(AV1Decoder *const pbi,
                                        MACROBLOCKD *const xd,
                                        MODE_INFO *const mi,
@@ -2482,38 +2540,10 @@
   read_mb_interp_filter(cm, xd, mbmi, r);
 #endif  // CONFIG_DUAL_FILTER || CONFIG_WARPED_MOTION
 
-#if CONFIG_EXT_INTER
-#if COMPOUND_SINGLEREF_DEBUG
-// NOTE(zoeliu): For debug
-#define FRAME_TO_CHECK 1
-  if (cm->current_video_frame == FRAME_TO_CHECK &&
-      ((cm->reference_mode != SINGLE_REFERENCE && cm->show_frame == 0) ||
-       cm->show_frame == 1)) {
-    const PREDICTION_MODE mode = mbmi->mode;
-
-    int_mv mv[2];
-#if CONFIG_COMPOUND_SINGLEREF
-    int is_comp_pred =
-        has_second_ref(mbmi) || is_inter_singleref_comp_mode(mbmi->mode);
-#else
-    int is_comp_pred = has_second_ref(mbmi);
-#endif  // CONFIG_COMPOUND_SINGLEREF
-
-    mv[0].as_int = mbmi->mv[0].as_int;
-    mv[1].as_int = is_comp_pred ? mbmi->mv[1].as_int : 0;
-
-    printf(
-        "=== DECODER ===: "
-        "Frame=%d, (mi_row,mi_col)=(%d,%d), mode=%d, bsize=%d, "
-        "show_frame=%d, mv[0]=(%d,%d), mv[1]=(%d,%d), ref[0]=%d, ref[1]=%d, "
-        "motion_mode=%d\n",
-        cm->current_video_frame, mi_row, mi_col, mode, bsize, cm->show_frame,
-        mv[0].as_mv.row, mv[0].as_mv.col, mv[1].as_mv.row, mv[1].as_mv.col,
-        mbmi->ref_frame[0], mbmi->ref_frame[1], mbmi->motion_mode);
-  }
-#endif  // COMPOUND_SINGLEREF_DEBUG
-#undef COMPOUND_SINGLEREF_DEBUG
-#endif  // CONFIG_EXT_INTER
+#if DEC_MISMATCH_DEBUG
+  // NOTE(zoeliu): For debug
+  dec_dump_logs(cm, mi, xd, mi_row, mi_col);
+#endif  // DEC_MISMATCH_DEBUG
 }
 
 static void read_inter_frame_mode_info(AV1Decoder *const pbi,
diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c
index 99fc32a..b449fab 100644
--- a/av1/encoder/bitstream.c
+++ b/av1/encoder/bitstream.c
@@ -61,7 +61,7 @@
 #include "av1/encoder/pvq_encoder.h"
 #endif
 
-#define COMPOUND_SINGLEREF_DEBUG 0
+#define ENC_MISMATCH_DEBUG 0
 
 static struct av1_token intra_mode_encodings[INTRA_MODES];
 static struct av1_token switchable_interp_encodings[SWITCHABLE_FILTERS];
@@ -2005,6 +2005,7 @@
       mode_ctx = mbmi_ext->compound_mode_context[mbmi->ref_frame[0]];
     else
 #endif  // CONFIG_EXT_INTER
+
       mode_ctx = av1_mode_context_analyzer(mbmi_ext->mode_context,
                                            mbmi->ref_frame, bsize, -1);
 
@@ -2448,6 +2449,93 @@
 }
 #endif
 
+#if ENC_MISMATCH_DEBUG
+static void enc_dump_logs(AV1_COMP *cpi, int mi_row, int mi_col) {
+  AV1_COMMON *const cm = &cpi->common;
+  MACROBLOCKD *const xd = &cpi->td.mb.e_mbd;
+  MODE_INFO *m;
+  xd->mi = cm->mi_grid_visible + (mi_row * cm->mi_stride + mi_col);
+  m = xd->mi[0];
+  if (is_inter_block(&m->mbmi)) {
+#define FRAME_TO_CHECK 1
+    if (cm->current_video_frame == FRAME_TO_CHECK && cm->show_frame == 0) {
+      const MB_MODE_INFO *const mbmi = &m->mbmi;
+      const BLOCK_SIZE bsize = mbmi->sb_type;
+
+      int_mv mv[2];
+      int is_comp_ref = has_second_ref(&m->mbmi);
+      int ref;
+
+      for (ref = 0; ref < 1 + is_comp_ref; ++ref)
+        mv[ref].as_mv = m->mbmi.mv[ref].as_mv;
+
+      if (!is_comp_ref) {
+#if CONFIG_COMPOUND_SINGLEREF
+        if (is_inter_singleref_comp_mode(m->mbmi.mode))
+          mv[1].as_mv = m->mbmi.mv[1].as_mv;
+        else
+#endif  // CONFIG_COMPOUND_SINGLEREF
+          mv[1].as_int = 0;
+      }
+      int interp_ctx[2] = { -1 };
+      int interp_filter[2] = { cm->interp_filter };
+      if (cm->interp_filter == SWITCHABLE) {
+        int dir;
+        for (dir = 0; dir < 2; ++dir) {
+          if (has_subpel_mv_component(xd->mi[0], xd, dir) ||
+              (mbmi->ref_frame[1] > INTRA_FRAME &&
+               has_subpel_mv_component(xd->mi[0], xd, dir + 2))) {
+            interp_ctx[dir] = av1_get_pred_context_switchable_interp(xd, dir);
+            interp_filter[dir] = mbmi->interp_filter[dir];
+          } else {
+            interp_filter[dir] = EIGHTTAP_REGULAR;
+          }
+        }
+      }
+
+#if CONFIG_DELTA_Q || CONFIG_EC_ADAPT
+      MACROBLOCK *const x = &cpi->td.mb;
+#else
+      const MACROBLOCK *x = &cpi->td.mb;
+#endif
+      const MB_MODE_INFO_EXT *const mbmi_ext = x->mbmi_ext;
+      const int16_t mode_ctx = av1_mode_context_analyzer(
+          mbmi_ext->mode_context, mbmi->ref_frame, bsize, -1);
+      const int16_t newmv_ctx = mode_ctx & NEWMV_CTX_MASK;
+      int16_t zeromv_ctx = -1;
+      int16_t refmv_ctx = -1;
+      if (mbmi->mode != NEWMV) {
+        zeromv_ctx = (mode_ctx >> ZEROMV_OFFSET) & ZEROMV_CTX_MASK;
+        if (mode_ctx & (1 << ALL_ZERO_FLAG_OFFSET)) {
+          assert(mbmi->mode == ZEROMV);
+        }
+        if (mbmi->mode != ZEROMV) {
+          refmv_ctx = (mode_ctx >> REFMV_OFFSET) & REFMV_CTX_MASK;
+          if (mode_ctx & (1 << SKIP_NEARESTMV_OFFSET)) refmv_ctx = 6;
+          if (mode_ctx & (1 << SKIP_NEARMV_OFFSET)) refmv_ctx = 7;
+          if (mode_ctx & (1 << SKIP_NEARESTMV_SUB8X8_OFFSET)) refmv_ctx = 8;
+        }
+      }
+
+      int8_t ref_frame_type = av1_ref_frame_type(mbmi->ref_frame);
+      printf(
+          "=== ENCODER ===: "
+          "Frame=%d, (mi_row,mi_col)=(%d,%d), mode=%d, bsize=%d, "
+          "show_frame=%d, mv[0]=(%d,%d), mv[1]=(%d,%d), ref[0]=%d, "
+          "ref[1]=%d, motion_mode=%d, inter_mode_ctx=%d, mode_ctx=%d, "
+          "interp_ctx=(%d,%d), interp_filter=(%d,%d), newmv_ctx=%d, "
+          "zeromv_ctx=%d, refmv_ctx=%d\n",
+          cm->current_video_frame, mi_row, mi_col, mbmi->mode, bsize,
+          cm->show_frame, mv[0].as_mv.row, mv[0].as_mv.col, mv[1].as_mv.row,
+          mv[1].as_mv.col, mbmi->ref_frame[0], mbmi->ref_frame[1],
+          mbmi->motion_mode, mbmi_ext->mode_context[ref_frame_type], mode_ctx,
+          interp_ctx[0], interp_ctx[1], interp_filter[0], interp_filter[1],
+          newmv_ctx, zeromv_ctx, refmv_ctx);
+    }
+  }
+}
+#endif  // ENC_MISMATCH_DEBUG
+
 static void write_mbmi_b(AV1_COMP *cpi, const TileInfo *const tile,
                          aom_writer *w,
 #if CONFIG_SUPERTX
@@ -2498,47 +2586,11 @@
 #endif  // CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
 #endif  // CONFIG_DUAL_FILTER
 
-#if CONFIG_EXT_INTER
-#if COMPOUND_SINGLEREF_DEBUG
+#if ENC_MISMATCH_DEBUG
     // NOTE(zoeliu): For debug
-    if (is_inter_block(&m->mbmi)) {
-#define FRAME_TO_CHECK 1
-      if (cm->current_video_frame == FRAME_TO_CHECK &&
-          ((cm->reference_mode != SINGLE_REFERENCE && cm->show_frame == 0) ||
-           cm->show_frame == 1)) {
-        const MB_MODE_INFO *const mbmi = &m->mbmi;
-        const BLOCK_SIZE bsize = mbmi->sb_type;
+    enc_dump_logs(cpi, mi_row, mi_col);
+#endif  // ENC_MISMATCH_DEBUG
 
-        int_mv mv[2];
-        int is_comp_ref = has_second_ref(&m->mbmi);
-        int ref;
-
-        for (ref = 0; ref < 1 + is_comp_ref; ++ref)
-          mv[ref].as_mv = m->mbmi.mv[ref].as_mv;
-
-        if (!is_comp_ref) {
-#if CONFIG_COMPOUND_SINGLEREF
-          if (is_inter_singleref_comp_mode(m->mbmi.mode))
-            mv[1].as_mv = m->mbmi.mv[1].as_mv;
-          else
-#endif  // CONFIG_COMPOUND_SINGLEREF
-            mv[1].as_int = 0;
-        }
-
-        printf(
-            "=== ENCODER ===: "
-            "Frame=%d, (mi_row,mi_col)=(%d,%d), mode=%d, bsize=%d, "
-            "show_frame=%d, mv[0]=(%d,%d), mv[1]=(%d,%d), ref[0]=%d, "
-            "ref[1]=%d, motion_mode=%d\n",
-            cm->current_video_frame, mi_row, mi_col, mbmi->mode, bsize,
-            cm->show_frame, mv[0].as_mv.row, mv[0].as_mv.col, mv[1].as_mv.row,
-            mv[1].as_mv.col, mbmi->ref_frame[0], mbmi->ref_frame[1],
-            mbmi->motion_mode);
-      }
-    }
-#endif  // COMPOUND_SINGLEREF_DEBUG
-#undef COMPOUND_SINGLEREF_DEBUG
-#endif  // CONFIG_EXT_INTER
     pack_inter_mode_mvs(cpi, mi_row, mi_col,
 #if CONFIG_SUPERTX
                         supertx_enabled,
diff --git a/av1/encoder/encodeframe.c b/av1/encoder/encodeframe.c
index 070cea2..ddecf49 100644
--- a/av1/encoder/encodeframe.c
+++ b/av1/encoder/encodeframe.c
@@ -648,7 +648,6 @@
 #if CONFIG_PALETTE
   for (i = 0; i < 2; ++i) pd[i].color_index_map = ctx->color_index_map[i];
 #endif  // CONFIG_PALETTE
-
   // Restore the coding context of the MB to that that was in place
   // when the mode was picked for it
   for (y = 0; y < mi_height; y++)
@@ -827,7 +826,6 @@
     }
     mi_addr->mbmi.segment_id_supertx = MAX_SEGMENTS;
   }
-
   // Restore the coding context of the MB to that that was in place
   // when the mode was picked for it
   for (y = 0; y < mi_height; y++)
@@ -4177,6 +4175,22 @@
   }
 }
 
+#if CONFIG_SPEED_REFS
+static void restore_mi(const AV1_COMP *const cpi, MACROBLOCK *const x,
+                       int mi_row, int mi_col) {
+  const AV1_COMMON *cm = &cpi->common;
+  MACROBLOCKD *const xd = &x->e_mbd;
+  set_mode_info_offsets(cpi, x, xd, mi_row, mi_col);
+  int x_idx, y;
+  for (y = 0; y < mi_size_high[cm->sb_size]; y++)
+    for (x_idx = 0; x_idx < mi_size_wide[cm->sb_size]; x_idx++)
+      if (mi_col + x_idx < cm->mi_cols && mi_row + y < cm->mi_rows) {
+        memset(xd->mi + y * cm->mi_stride + x_idx, 0, sizeof(*xd->mi));
+        memset(x->mbmi_ext + y * cm->mi_cols + x_idx, 0, sizeof(*x->mbmi_ext));
+      }
+}
+#endif  // CONFIG_SPEED_REFS
+
 static void encode_rd_sb_row(AV1_COMP *cpi, ThreadData *td,
                              TileDataEnc *tile_data, int mi_row,
                              TOKENEXTRA **tp) {
@@ -4326,8 +4340,11 @@
 #if CONFIG_SPEED_REFS
       // NOTE: Two scanning passes for the current superblock - the first pass
       //       is only targeted to collect stats.
+      int m_search_count_backup = *(x->m_search_count_ptr);
       for (int sb_pass_idx = 0; sb_pass_idx < 2; ++sb_pass_idx) {
         cpi->sb_scanning_pass_idx = sb_pass_idx;
+        if (frame_is_intra_only(cm) && sb_pass_idx == 0) continue;
+
         rd_pick_partition(cpi, td, tile_data, tp, mi_row, mi_col, cm->sb_size,
                           &dummy_rdc,
 #if CONFIG_SUPERTX
@@ -4337,6 +4354,8 @@
         if (sb_pass_idx == 0) {
           av1_zero(x->pred_mv);
           pc_root->index = 0;
+          restore_mi(cpi, x, mi_row, mi_col);
+          *(x->m_search_count_ptr) = m_search_count_backup;
         }
       }
 #else  // !CONFIG_SPEED_REFS