Refactor setup_ref_mv_list

This patch eliminates the is_inside() checking for each neighouring
block in scan_row_mbmi() and scan_col_mbmi(). Instead, in
setup_ref_mv_list(), find maximum above row_offset and left col_offset
for current block, and use them to decide which above rows and left
columns to search on. This patch doesn't change bitstream. No
noticeable speedup is seen.

Change-Id: Ic4ae74412605d86e9e675f86d23de3a69c04e8f3
diff --git a/av1/common/mvref_common.c b/av1/common/mvref_common.c
index 40499cf..3793aa6 100644
--- a/av1/common/mvref_common.c
+++ b/av1/common/mvref_common.c
@@ -153,123 +153,81 @@
 }
 
 static uint8_t scan_row_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
-                             const int mi_row, const int mi_col, int block,
+                             const int mi_col, int block,
                              const MV_REFERENCE_FRAME rf[2], int row_offset,
                              CANDIDATE_MV *ref_mv_stack, uint8_t *refmv_count) {
-  const TileInfo *const tile = &xd->tile;
+  const int end_mi = AOMMIN(xd->n8_w, cm->mi_cols - mi_col);
   int i;
   uint8_t newmv_count = 0;
   int col_offset = 0;
 #if CONFIG_CB4X4
   const int bsize = xd->mi[0]->mbmi.sb_type;
   const int mi_width = mi_size_wide[bsize];
-  const int mi_col_offset =
-      ((abs(row_offset) > 1) || (mi_width < mi_size_wide[BLOCK_8X8]))
-          ? mi_size_wide[BLOCK_4X4]
-          : mi_size_wide[BLOCK_8X8];
   // TODO(jingning): Revisit this part after cb4x4 is stable.
   if (abs(row_offset) > 1) {
-    row_offset *= 2;
-    row_offset += 1;
-
     col_offset = 1;
-
-    if (mi_row & 0x01 && mi_size_high[bsize] < mi_size_high[BLOCK_8X8])
-      ++row_offset;
     if (mi_col & 0x01 && mi_width < mi_size_wide[BLOCK_8X8]) --col_offset;
   }
+  const int use_step_16 = (xd->n8_w >= 16);
 #else
-  const int mi_col_offset = mi_size_wide[BLOCK_8X8];
+  const int use_step_16 = (xd->n8_w >= 8);
 #endif
+  MODE_INFO **const candidate_mi0 = xd->mi + row_offset * xd->mi_stride;
+  const int n8_w_8 = mi_size_wide[BLOCK_8X8];
+  const int n8_w_16 = mi_size_wide[BLOCK_16X16];
 
-  for (i = 0; i < xd->n8_w && *refmv_count < MAX_REF_MV_STACK_SIZE;) {
-    POSITION mi_pos;
-#if CONFIG_CB4X4
-    const int use_step_16 = (xd->n8_w >= 16);
-#else
-    const int use_step_16 = (xd->n8_w >= 8);
-#endif
-
-    mi_pos.row = row_offset;
-    mi_pos.col = col_offset + i;
-    if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm, &mi_pos)) {
-      const MODE_INFO *const candidate_mi =
-          xd->mi[mi_pos.row * xd->mi_stride + mi_pos.col];
-      const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
-      int len = AOMMIN(xd->n8_w, mi_size_wide[candidate->sb_type]);
-      if (abs(row_offset) > 1) len = AOMMAX(len, mi_size_wide[BLOCK_8X8]);
-      if (use_step_16) len = AOMMAX(mi_size_wide[BLOCK_16X16], len);
-      newmv_count += add_ref_mv_candidate(
-          candidate_mi, candidate, rf, refmv_count, ref_mv_stack,
-          cm->allow_high_precision_mv, len, block, mi_pos.col);
-      i += len;
-    } else {
-      if (use_step_16)
-        i += (mi_col_offset << 1);
-      else
-        i += mi_col_offset;
-    }
+  for (i = 0; i < end_mi && *refmv_count < MAX_REF_MV_STACK_SIZE;) {
+    const MODE_INFO *const candidate_mi = candidate_mi0[col_offset + i];
+    const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
+    int len = AOMMIN(xd->n8_w, mi_size_wide[candidate->sb_type]);
+    if (use_step_16)
+      len = AOMMAX(n8_w_16, len);
+    else if (abs(row_offset) > 1)
+      len = AOMMAX(len, n8_w_8);
+    newmv_count += add_ref_mv_candidate(
+        candidate_mi, candidate, rf, refmv_count, ref_mv_stack,
+        cm->allow_high_precision_mv, len, block, col_offset + i);
+    i += len;
   }
 
   return newmv_count;
 }
 
 static uint8_t scan_col_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
-                             const int mi_row, const int mi_col, int block,
+                             const int mi_row, int block,
                              const MV_REFERENCE_FRAME rf[2], int col_offset,
                              CANDIDATE_MV *ref_mv_stack, uint8_t *refmv_count) {
-  const TileInfo *const tile = &xd->tile;
+  const int end_mi = AOMMIN(xd->n8_h, cm->mi_rows - mi_row);
   int i;
   uint8_t newmv_count = 0;
   int row_offset = 0;
 #if CONFIG_CB4X4
   const BLOCK_SIZE bsize = xd->mi[0]->mbmi.sb_type;
   const int mi_height = mi_size_high[bsize];
-  const int mi_row_offset =
-      ((abs(col_offset) > 1) || (mi_height < mi_size_high[BLOCK_8X8]))
-          ? mi_size_high[BLOCK_4X4]
-          : mi_size_high[BLOCK_8X8];
   if (abs(col_offset) > 1) {
-    col_offset *= 2;
-    col_offset += 1;
-
     row_offset = 1;
-
     if (mi_row & 0x01 && mi_height < mi_size_high[BLOCK_8X8]) --row_offset;
-    if (mi_col & 0x01 && mi_size_wide[bsize] < mi_size_wide[BLOCK_8X8])
-      ++col_offset;
   }
+  const int use_step_16 = (xd->n8_h >= 16);
 #else
-  const int mi_row_offset = mi_size_wide[BLOCK_8X8];
+  const int use_step_16 = (xd->n8_h >= 8);
 #endif
+  const int n8_h_8 = mi_size_high[BLOCK_8X8];
+  const int n8_h_16 = mi_size_high[BLOCK_16X16];
 
-  for (i = 0; i < xd->n8_h && *refmv_count < MAX_REF_MV_STACK_SIZE;) {
-    POSITION mi_pos;
-#if CONFIG_CB4X4
-    const int use_step_16 = (xd->n8_h >= 16);
-#else
-    const int use_step_16 = (xd->n8_h >= 8);
-#endif
-
-    mi_pos.row = row_offset + i;
-    mi_pos.col = col_offset;
-    if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm, &mi_pos)) {
-      const MODE_INFO *const candidate_mi =
-          xd->mi[mi_pos.row * xd->mi_stride + mi_pos.col];
-      const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
-      int len = AOMMIN(xd->n8_h, mi_size_high[candidate->sb_type]);
-      if (abs(col_offset) > 1) len = AOMMAX(len, mi_size_high[BLOCK_8X8]);
-      if (use_step_16) len = AOMMAX(mi_size_high[BLOCK_16X16], len);
-      newmv_count += add_ref_mv_candidate(
-          candidate_mi, candidate, rf, refmv_count, ref_mv_stack,
-          cm->allow_high_precision_mv, len, block, mi_pos.col);
-      i += len;
-    } else {
-      if (use_step_16)
-        i += (mi_row_offset << 1);
-      else
-        i += mi_row_offset;
-    }
+  for (i = 0; i < end_mi && *refmv_count < MAX_REF_MV_STACK_SIZE;) {
+    const MODE_INFO *const candidate_mi =
+        xd->mi[(row_offset + i) * xd->mi_stride + col_offset];
+    const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
+    int len = AOMMIN(xd->n8_h, mi_size_high[candidate->sb_type]);
+    if (use_step_16)
+      len = AOMMAX(n8_h_16, len);
+    else if (abs(col_offset) > 1)
+      len = AOMMAX(len, n8_h_8);
+    newmv_count += add_ref_mv_candidate(
+        candidate_mi, candidate, rf, refmv_count, ref_mv_stack,
+        cm->allow_high_precision_mv, len, block, col_offset);
+    i += len;
   }
 
   return newmv_count;
@@ -426,16 +384,42 @@
   const int has_tr = has_top_right(xd, mi_row, mi_col, bs);
   MV_REFERENCE_FRAME rf[2];
 
+  const TileInfo *const tile = &xd->tile;
+#if CONFIG_CB4X4
+  const int bsize = xd->mi[0]->mbmi.sb_type;
+  int max_row_offset = xd->up_available ? -(MVREF_ROWS << 1) : 0;
+  int max_col_offset = xd->left_available ? -(MVREF_COLS << 1) : 0;
+  const int row_adj =
+      (mi_size_high[bsize] < mi_size_high[BLOCK_8X8]) && (mi_row & 0x01);
+  const int col_adj =
+      (mi_size_wide[bsize] < mi_size_wide[BLOCK_8X8]) && (mi_col & 0x01);
+#else
+  int max_row_offset = xd->up_available ? -MVREF_ROWS : 0;
+  int max_col_offset = xd->left_available ? -MVREF_COLS : 0;
+#endif
+  int row_offset, col_offset;
+
   av1_set_ref_frame(rf, ref_frame);
   mode_context[ref_frame] = 0;
   *refmv_count = 0;
 
   // Scan the first above row mode info.
-  newmv_count += scan_row_mbmi(cm, xd, mi_row, mi_col, block, rf, -1,
-                               ref_mv_stack, refmv_count);
+  if (max_row_offset) {
+    max_row_offset =
+        find_valid_row_offset(tile, mi_row, cm->mi_rows, cm, max_row_offset);
+    // row_offset = -1;
+    if (abs(max_row_offset) >= 1)
+      newmv_count += scan_row_mbmi(cm, xd, mi_col, block, rf, -1, ref_mv_stack,
+                                   refmv_count);
+  }
   // Scan the first left column mode info.
-  newmv_count += scan_col_mbmi(cm, xd, mi_row, mi_col, block, rf, -1,
-                               ref_mv_stack, refmv_count);
+  if (max_col_offset) {
+    max_col_offset = find_valid_col_offset(tile, mi_col, max_col_offset);
+    // col_offset = -1;
+    if (abs(max_col_offset) >= 1)
+      newmv_count += scan_col_mbmi(cm, xd, mi_row, block, rf, -1, ref_mv_stack,
+                                   refmv_count);
+  }
 
   // Check top-right boundary
   if (has_tr)
@@ -498,14 +482,40 @@
   // Scan the second outer area.
   scan_blk_mbmi(cm, xd, mi_row, mi_col, block, rf, -1, -1, ref_mv_stack,
                 refmv_count);
-  for (idx = 2; idx <= 3; ++idx) {
-    scan_row_mbmi(cm, xd, mi_row, mi_col, block, rf, -idx, ref_mv_stack,
-                  refmv_count);
-    scan_col_mbmi(cm, xd, mi_row, mi_col, block, rf, -idx, ref_mv_stack,
-                  refmv_count);
+  for (idx = 2; idx <= MVREF_ROWS; ++idx) {
+    if (max_row_offset) {
+#if CONFIG_CB4X4
+      row_offset = -(idx << 1) + 1 + row_adj;
+#else
+      row_offset = -idx;
+#endif
+      if (abs(row_offset) <= abs(max_row_offset))
+        scan_row_mbmi(cm, xd, mi_col, block, rf, row_offset, ref_mv_stack,
+                      refmv_count);
+    }
+
+    if (max_col_offset) {
+#if CONFIG_CB4X4
+      col_offset = -(idx << 1) + 1 + col_adj;
+#else
+      col_offset = -idx;
+#endif
+      if (abs(col_offset) <= abs(max_col_offset))
+        scan_col_mbmi(cm, xd, mi_row, block, rf, col_offset, ref_mv_stack,
+                      refmv_count);
+    }
   }
-  scan_col_mbmi(cm, xd, mi_row, mi_col, block, rf, -4, ref_mv_stack,
-                refmv_count);
+
+  if (max_col_offset) {
+#if CONFIG_CB4X4
+    col_offset = -(MVREF_COLS << 1) + 1 + col_adj;
+#else
+    col_offset = -MVREF_COLS;
+#endif
+    if (abs(col_offset) <= abs(max_col_offset))
+      scan_col_mbmi(cm, xd, mi_row, block, rf, col_offset, ref_mv_stack,
+                    refmv_count);
+  }
 
   switch (nearest_refmv_count) {
     case 0:
diff --git a/av1/common/mvref_common.h b/av1/common/mvref_common.h
index 906927d..4dc2350 100644
--- a/av1/common/mvref_common.h
+++ b/av1/common/mvref_common.h
@@ -19,6 +19,8 @@
 #endif
 
 #define MVREF_NEIGHBOURS 9
+#define MVREF_ROWS 3
+#define MVREF_COLS 4
 
 typedef struct position {
   int row;
@@ -207,6 +209,28 @@
   }
 }
 
+static INLINE int find_valid_row_offset(const TileInfo *const tile, int mi_row,
+                                        int mi_rows, const AV1_COMMON *cm,
+                                        int row_offset) {
+#if CONFIG_DEPENDENT_HORZTILES
+  const int dependent_horz_tile_flag = cm->dependent_horz_tiles;
+#else
+  const int dependent_horz_tile_flag = 0;
+  (void)cm;
+#endif
+  if (dependent_horz_tile_flag && !tile->tg_horz_boundary)
+    return clamp(row_offset, -mi_row, mi_rows - mi_row - 1);
+  else
+    return clamp(row_offset, tile->mi_row_start - mi_row,
+                 tile->mi_row_end - mi_row - 1);
+}
+
+static INLINE int find_valid_col_offset(const TileInfo *const tile, int mi_col,
+                                        int col_offset) {
+  return clamp(col_offset, tile->mi_col_start - mi_col,
+               tile->mi_col_end - mi_col - 1);
+}
+
 static INLINE void lower_mv_precision(MV *mv, int allow_hp) {
   if (!allow_hp) {
     if (mv->row & 1) mv->row += (mv->row > 0 ? -1 : 1);