mvref_common.c 83.2 KB
Newer Older
Jingning Han's avatar
Jingning Han committed
1
/*
Yaowu Xu's avatar
Yaowu Xu committed
2
 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
Jingning Han's avatar
Jingning Han committed
3
 *
Yaowu Xu's avatar
Yaowu Xu committed
4 5 6 7 8 9
 * This source code is subject to the terms of the BSD 2 Clause License and
 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
 * was not distributed with this source code in the LICENSE file, you can
 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
 * Media Patent License 1.0 was not distributed with this source code in the
 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
Jingning Han's avatar
Jingning Han committed
10 11
 */

12 13
#include <stdlib.h>

14
#include "av1/common/mvref_common.h"
Yue Chen's avatar
Yue Chen committed
15
#include "av1/common/warped_motion.h"
Jingning Han's avatar
Jingning Han committed
16

17 18
#define USE_CUR_GM_REFMV 1

19 20 21 22 23 24 25 26 27 28 29 30 31 32
#if CONFIG_MFMV
// Although we assign 32 bit integers, all the values are strictly under 14
// bits.
static int div_mult[64] = {
  0,    16384, 8192, 5461, 4096, 3276, 2730, 2340, 2048, 1820, 1638, 1489, 1365,
  1260, 1170,  1092, 1024, 963,  910,  862,  819,  780,  744,  712,  682,  655,
  630,  606,   585,  564,  546,  528,  512,  496,  481,  468,  455,  442,  431,
  420,  409,   399,  390,  381,  372,  364,  356,  348,  341,  334,  327,  321,
  315,  309,   303,  297,  292,  287,  282,  277,  273,  268,  264,  260,
};

// TODO(jingning): Consider the use of lookup table for (num / den)
// altogether.
static void get_mv_projection(MV *output, MV ref, int num, int den) {
33 34 35
  den = AOMMIN(den, MAX_FRAME_DISTANCE);
  num = num > 0 ? AOMMIN(num, MAX_FRAME_DISTANCE)
                : AOMMAX(num, -MAX_FRAME_DISTANCE);
36 37 38 39 40 41 42
  output->row =
      (int16_t)(ROUND_POWER_OF_TWO_SIGNED(ref.row * num * div_mult[den], 14));
  output->col =
      (int16_t)(ROUND_POWER_OF_TWO_SIGNED(ref.col * num * div_mult[den], 14));
}
#endif  // CONFIG_MFMV

43 44
void av1_copy_frame_mvs(const AV1_COMMON *const cm, MODE_INFO *mi, int mi_row,
                        int mi_col, int x_mis, int y_mis) {
45
#if CONFIG_TMV || CONFIG_MFMV
46
  const int frame_mvs_stride = ROUND_POWER_OF_TWO(cm->mi_cols, 1);
47 48
  MV_REF *frame_mvs =
      cm->cur_frame->mvs + (mi_row >> 1) * frame_mvs_stride + (mi_col >> 1);
49 50 51 52 53 54 55 56 57 58 59 60
  x_mis = ROUND_POWER_OF_TWO(x_mis, 1);
  y_mis = ROUND_POWER_OF_TWO(y_mis, 1);
#else
  const int frame_mvs_stride = cm->mi_cols;
  MV_REF *frame_mvs = cm->cur_frame->mvs +
                      (mi_row & 0xfffe) * frame_mvs_stride + (mi_col & 0xfffe);
  x_mis = AOMMAX(x_mis, 2);
  y_mis = AOMMAX(y_mis, 2);
#endif  // CONFIG_TMV
  int w, h;

  for (h = 0; h < y_mis; h++) {
61
    MV_REF *mv = frame_mvs;
62
    for (w = 0; w < x_mis; w++) {
63 64 65 66 67 68 69 70 71 72 73
#if CONFIG_MFMV
      mv->ref_frame[0] = NONE_FRAME;
      mv->ref_frame[1] = NONE_FRAME;
      mv->mv[0].as_int = 0;
      mv->mv[1].as_int = 0;

      for (int idx = 0; idx < 2; ++idx) {
        MV_REFERENCE_FRAME ref_frame = mi->mbmi.ref_frame[idx];
        if (ref_frame > INTRA_FRAME) {
          int8_t ref_idx = cm->ref_frame_side[ref_frame];
          if (ref_idx < 0) continue;
74 75 76
          if ((abs(mi->mbmi.mv[idx].as_mv.row) > REFMVS_LIMIT) ||
              (abs(mi->mbmi.mv[idx].as_mv.col) > REFMVS_LIMIT))
            continue;
77 78 79 80 81
          mv->ref_frame[ref_idx] = ref_frame;
          mv->mv[ref_idx].as_int = mi->mbmi.mv[idx].as_int;
        }
      }
#else
82 83 84 85
      mv->ref_frame[0] = mi->mbmi.ref_frame[0];
      mv->ref_frame[1] = mi->mbmi.ref_frame[1];
      mv->mv[0].as_int = mi->mbmi.mv[0].as_int;
      mv->mv[1].as_int = mi->mbmi.mv[1].as_int;
86
#endif
87 88 89
      // (TODO:yunqing) The following 2 lines won't be used and can be removed.
      mv->pred_mv[0].as_int = mi->mbmi.pred_mv[0].as_int;
      mv->pred_mv[1].as_int = mi->mbmi.pred_mv[1].as_int;
90
      mv++;
91
    }
92
    frame_mvs += frame_mvs_stride;
93 94 95
  }
}

Yunqing Wang's avatar
Yunqing Wang committed
96
static void add_ref_mv_candidate(
97
    const MODE_INFO *const candidate_mi, const MB_MODE_INFO *const candidate,
98 99
    const MV_REFERENCE_FRAME rf[2], uint8_t refmv_counts[MODE_CTX_REF_FRAMES],
    uint8_t ref_match_counts[MODE_CTX_REF_FRAMES],
Yunqing Wang's avatar
Yunqing Wang committed
100
    uint8_t newmv_counts[MODE_CTX_REF_FRAMES],
101
    CANDIDATE_MV ref_mv_stacks[][MAX_REF_MV_STACK_SIZE], int len,
102
#if USE_CUR_GM_REFMV
103
    int_mv *gm_mv_candidates, const WarpedMotionParams *gm_params,
104
#endif  // USE_CUR_GM_REFMV
105
    int col, int weight) {
106
#if CONFIG_INTRABC
Yunqing Wang's avatar
Yunqing Wang committed
107
  if (!is_inter_block(candidate)) return;
108
#endif  // CONFIG_INTRABC
Jingning Han's avatar
Jingning Han committed
109
  int index = 0, ref;
110
  assert(weight % 2 == 0);
Jingning Han's avatar
Jingning Han committed
111

Emil Keyder's avatar
Emil Keyder committed
112
  if (rf[1] == NONE_FRAME) {
113 114
    uint8_t *refmv_count = &refmv_counts[rf[0]];
    uint8_t *ref_match_count = &ref_match_counts[rf[0]];
Yunqing Wang's avatar
Yunqing Wang committed
115
    uint8_t *newmv_count = &newmv_counts[rf[0]];
116 117 118
    CANDIDATE_MV *ref_mv_stack = ref_mv_stacks[rf[0]];
    (void)ref_match_count;

Jingning Han's avatar
Jingning Han committed
119 120 121
    // single reference frame
    for (ref = 0; ref < 2; ++ref) {
      if (candidate->ref_frame[ref] == rf[0]) {
122
        int_mv this_refmv;
123
#if USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
124 125 126
        if (is_global_mv_block(candidate_mi, gm_params[rf[0]].wmtype))
          this_refmv = gm_mv_candidates[0];
        else
127
#endif  // USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
128
          this_refmv = get_sub_block_mv(candidate_mi, ref, col);
129

Jingning Han's avatar
Jingning Han committed
130
        for (index = 0; index < *refmv_count; ++index)
clang-format's avatar
clang-format committed
131
          if (ref_mv_stack[index].this_mv.as_int == this_refmv.as_int) break;
132

133
        if (index < *refmv_count) ref_mv_stack[index].weight += weight * len;
134

Jingning Han's avatar
Jingning Han committed
135
        // Add a new item to the list.
136
        if (index == *refmv_count && *refmv_count < MAX_REF_MV_STACK_SIZE) {
Jingning Han's avatar
Jingning Han committed
137
          ref_mv_stack[index].this_mv = this_refmv;
138
          ref_mv_stack[index].pred_diff[0] = av1_get_pred_diff_ctx(
Luc Trudeau's avatar
Luc Trudeau committed
139
              get_sub_block_pred_mv(candidate_mi, ref, col), this_refmv);
140
          ref_mv_stack[index].weight = weight * len;
Jingning Han's avatar
Jingning Han committed
141
          ++(*refmv_count);
142

143
#if !CONFIG_OPT_REF_MV
Yunqing Wang's avatar
Yunqing Wang committed
144
          if (candidate->mode == NEWMV) ++*newmv_count;
145
#endif
Jingning Han's avatar
Jingning Han committed
146
        }
147
#if CONFIG_OPT_REF_MV
Yunqing Wang's avatar
Yunqing Wang committed
148
        if (have_newmv_in_inter_mode(candidate->mode)) ++*newmv_count;
149 150
        ++*ref_match_count;
#endif
151
      }
Jingning Han's avatar
Jingning Han committed
152 153
    }
  } else {
154 155 156
    MV_REFERENCE_FRAME ref_frame = av1_ref_frame_type(rf);
    uint8_t *refmv_count = &refmv_counts[ref_frame];
    uint8_t *ref_match_count = &ref_match_counts[ref_frame];
Yunqing Wang's avatar
Yunqing Wang committed
157
    uint8_t *newmv_count = &newmv_counts[ref_frame];
158 159 160
    CANDIDATE_MV *ref_mv_stack = ref_mv_stacks[ref_frame];
    (void)ref_match_count;

Jingning Han's avatar
Jingning Han committed
161
    // compound reference frame
clang-format's avatar
clang-format committed
162
    if (candidate->ref_frame[0] == rf[0] && candidate->ref_frame[1] == rf[1]) {
163
      int_mv this_refmv[2];
Jingning Han's avatar
Jingning Han committed
164

165
      for (ref = 0; ref < 2; ++ref) {
166
#if USE_CUR_GM_REFMV
Luc Trudeau's avatar
Luc Trudeau committed
167
        if (is_global_mv_block(candidate_mi, gm_params[rf[ref]].wmtype))
168 169
          this_refmv[ref] = gm_mv_candidates[ref];
        else
170
#endif  // USE_CUR_GM_REFMV
Luc Trudeau's avatar
Luc Trudeau committed
171
          this_refmv[ref] = get_sub_block_mv(candidate_mi, ref, col);
172
      }
173

Jingning Han's avatar
Jingning Han committed
174 175 176 177 178
      for (index = 0; index < *refmv_count; ++index)
        if ((ref_mv_stack[index].this_mv.as_int == this_refmv[0].as_int) &&
            (ref_mv_stack[index].comp_mv.as_int == this_refmv[1].as_int))
          break;

179
      if (index < *refmv_count) ref_mv_stack[index].weight += weight * len;
Jingning Han's avatar
Jingning Han committed
180 181

      // Add a new item to the list.
182
      if (index == *refmv_count && *refmv_count < MAX_REF_MV_STACK_SIZE) {
Jingning Han's avatar
Jingning Han committed
183 184
        ref_mv_stack[index].this_mv = this_refmv[0];
        ref_mv_stack[index].comp_mv = this_refmv[1];
185
        ref_mv_stack[index].pred_diff[0] = av1_get_pred_diff_ctx(
Luc Trudeau's avatar
Luc Trudeau committed
186
            get_sub_block_pred_mv(candidate_mi, 0, col), this_refmv[0]);
187
        ref_mv_stack[index].pred_diff[1] = av1_get_pred_diff_ctx(
Luc Trudeau's avatar
Luc Trudeau committed
188
            get_sub_block_pred_mv(candidate_mi, 1, col), this_refmv[1]);
189
        ref_mv_stack[index].weight = weight * len;
Jingning Han's avatar
Jingning Han committed
190 191
        ++(*refmv_count);

192
#if !CONFIG_OPT_REF_MV
Yunqing Wang's avatar
Yunqing Wang committed
193
        if (candidate->mode == NEW_NEWMV) ++*newmv_count;
194
#endif
Jingning Han's avatar
Jingning Han committed
195
      }
196
#if CONFIG_OPT_REF_MV
Yunqing Wang's avatar
Yunqing Wang committed
197
      if (have_newmv_in_inter_mode(candidate->mode)) ++*newmv_count;
198 199
      ++*ref_match_count;
#endif
Jingning Han's avatar
Jingning Han committed
200 201 202 203
    }
  }
}

Yunqing Wang's avatar
Yunqing Wang committed
204 205 206 207 208 209 210
static void scan_row_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
                          int mi_row, int mi_col,
                          const MV_REFERENCE_FRAME rf[2], int row_offset,
                          CANDIDATE_MV ref_mv_stack[][MAX_REF_MV_STACK_SIZE],
                          uint8_t refmv_count[MODE_CTX_REF_FRAMES],
                          uint8_t ref_match_count[MODE_CTX_REF_FRAMES],
                          uint8_t newmv_count[MODE_CTX_REF_FRAMES],
211
#if USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
212
                          int_mv *gm_mv_candidates,
213
#endif  // USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
214
                          int max_row_offset, int *processed_rows) {
215 216
  int end_mi = AOMMIN(xd->n8_w, cm->mi_cols - mi_col);
  end_mi = AOMMIN(end_mi, mi_size_wide[BLOCK_64X64]);
217 218
  const int n8_w_8 = mi_size_wide[BLOCK_8X8];
  const int n8_w_16 = mi_size_wide[BLOCK_16X16];
Jingning Han's avatar
Jingning Han committed
219
  int i;
220
  int col_offset = 0;
221
  const int shift = 0;
222
  // TODO(jingning): Revisit this part after cb4x4 is stable.
223 224
  if (abs(row_offset) > 1) {
    col_offset = 1;
225
    if (mi_col & 0x01 && xd->n8_w < n8_w_8) --col_offset;
226
  }
Yunqing Wang's avatar
Yunqing Wang committed
227 228
  const int use_step_16 = (xd->n8_w >= 16);
  MODE_INFO **const candidate_mi0 = xd->mi + row_offset * xd->mi_stride;
Yunqing Wang's avatar
Yunqing Wang committed
229
  (void)mi_row;
Jingning Han's avatar
Jingning Han committed
230

231
  for (i = 0; i < end_mi;) {
Yunqing Wang's avatar
Yunqing Wang committed
232 233
    const MODE_INFO *const candidate_mi = candidate_mi0[col_offset + i];
    const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
234 235 236
    const int candidate_bsize = candidate->sb_type;
    const int n8_w = mi_size_wide[candidate_bsize];
    int len = AOMMIN(xd->n8_w, n8_w);
Yunqing Wang's avatar
Yunqing Wang committed
237 238 239 240
    if (use_step_16)
      len = AOMMAX(n8_w_16, len);
    else if (abs(row_offset) > 1)
      len = AOMMAX(len, n8_w_8);
241 242 243 244 245 246 247 248 249 250 251

    int weight = 2;
    if (xd->n8_w >= n8_w_8 && xd->n8_w <= n8_w) {
      int inc = AOMMIN(-max_row_offset + row_offset + 1,
                       mi_size_high[candidate_bsize]);
      // Obtain range used in weight calculation.
      weight = AOMMAX(weight, (inc << shift));
      // Update processed rows.
      *processed_rows = inc - row_offset - 1;
    }

Yunqing Wang's avatar
Yunqing Wang committed
252
    add_ref_mv_candidate(candidate_mi, candidate, rf, refmv_count,
253
                         ref_match_count, newmv_count, ref_mv_stack, len,
254
#if USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
255
                         gm_mv_candidates, cm->global_motion,
256
#endif  // USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
257
                         col_offset + i, weight);
258

Yunqing Wang's avatar
Yunqing Wang committed
259
    i += len;
260 261 262
  }
}

Yunqing Wang's avatar
Yunqing Wang committed
263 264 265 266 267 268 269
static void scan_col_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
                          int mi_row, int mi_col,
                          const MV_REFERENCE_FRAME rf[2], int col_offset,
                          CANDIDATE_MV ref_mv_stack[][MAX_REF_MV_STACK_SIZE],
                          uint8_t refmv_count[MODE_CTX_REF_FRAMES],
                          uint8_t ref_match_count[MODE_CTX_REF_FRAMES],
                          uint8_t newmv_count[MODE_CTX_REF_FRAMES],
270
#if USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
271
                          int_mv *gm_mv_candidates,
272
#endif  // USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
273
                          int max_col_offset, int *processed_cols) {
274 275
  int end_mi = AOMMIN(xd->n8_h, cm->mi_rows - mi_row);
  end_mi = AOMMIN(end_mi, mi_size_high[BLOCK_64X64]);
276 277
  const int n8_h_8 = mi_size_high[BLOCK_8X8];
  const int n8_h_16 = mi_size_high[BLOCK_16X16];
278
  int i;
279
  int row_offset = 0;
280
  const int shift = 0;
281 282
  if (abs(col_offset) > 1) {
    row_offset = 1;
283
    if (mi_row & 0x01 && xd->n8_h < n8_h_8) --row_offset;
284
  }
Yunqing Wang's avatar
Yunqing Wang committed
285
  const int use_step_16 = (xd->n8_h >= 16);
Yunqing Wang's avatar
Yunqing Wang committed
286
  (void)mi_col;
287

288
  for (i = 0; i < end_mi;) {
Yunqing Wang's avatar
Yunqing Wang committed
289 290 291
    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;
292 293 294
    const int candidate_bsize = candidate->sb_type;
    const int n8_h = mi_size_high[candidate_bsize];
    int len = AOMMIN(xd->n8_h, n8_h);
Yunqing Wang's avatar
Yunqing Wang committed
295 296 297 298
    if (use_step_16)
      len = AOMMAX(n8_h_16, len);
    else if (abs(col_offset) > 1)
      len = AOMMAX(len, n8_h_8);
299 300 301 302 303 304 305 306 307 308 309

    int weight = 2;
    if (xd->n8_h >= n8_h_8 && xd->n8_h <= n8_h) {
      int inc = AOMMIN(-max_col_offset + col_offset + 1,
                       mi_size_wide[candidate_bsize]);
      // Obtain range used in weight calculation.
      weight = AOMMAX(weight, (inc << shift));
      // Update processed cols.
      *processed_cols = inc - col_offset - 1;
    }

Yunqing Wang's avatar
Yunqing Wang committed
310
    add_ref_mv_candidate(candidate_mi, candidate, rf, refmv_count,
311
                         ref_match_count, newmv_count, ref_mv_stack, len,
312
#if USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
313
                         gm_mv_candidates, cm->global_motion,
314
#endif  // USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
315
                         col_offset, weight);
316

Yunqing Wang's avatar
Yunqing Wang committed
317
    i += len;
318 319 320
  }
}

Yunqing Wang's avatar
Yunqing Wang committed
321 322 323 324 325 326 327
static void scan_blk_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
                          const int mi_row, const int mi_col,
                          const MV_REFERENCE_FRAME rf[2], int row_offset,
                          int col_offset,
                          CANDIDATE_MV ref_mv_stack[][MAX_REF_MV_STACK_SIZE],
                          uint8_t ref_match_count[MODE_CTX_REF_FRAMES],
                          uint8_t newmv_count[MODE_CTX_REF_FRAMES],
328
#if USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
329
                          int_mv *gm_mv_candidates,
330
#endif  // USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
331
                          uint8_t refmv_count[MODE_CTX_REF_FRAMES]) {
332 333 334 335 336 337
  const TileInfo *const tile = &xd->tile;
  POSITION mi_pos;

  mi_pos.row = row_offset;
  mi_pos.col = col_offset;

338
  if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm, &mi_pos)) {
339 340 341
    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;
342
    const int len = mi_size_wide[BLOCK_8X8];
343

Yunqing Wang's avatar
Yunqing Wang committed
344
    add_ref_mv_candidate(candidate_mi, candidate, rf, refmv_count,
345
                         ref_match_count, newmv_count, ref_mv_stack, len,
346
#if USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
347
                         gm_mv_candidates, cm->global_motion,
348
#endif  // USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
349
                         mi_pos.col, 2);
350 351 352
  }  // Analyze a single 8x8 block motion information.
}

353 354
static int has_top_right(const AV1_COMMON *cm, const MACROBLOCKD *xd,
                         int mi_row, int mi_col, int bs) {
355
  const int sb_mi_size = mi_size_wide[cm->seq_params.sb_size];
356 357
  const int mask_row = mi_row & (sb_mi_size - 1);
  const int mask_col = mi_col & (sb_mi_size - 1);
358

359 360
  if (bs > mi_size_wide[BLOCK_64X64]) return 0;

361
  // In a split partition all apart from the bottom right has a top right
362
  int has_tr = !((mask_row & bs) && (mask_col & bs));
363

364 365
  // bs > 0 and bs is a power of 2
  assert(bs > 0 && !(bs & (bs - 1)));
366

367 368 369
  // For each 4x4 group of blocks, when the bottom right is decoded the blocks
  // to the right have not been decoded therefore the bottom right does
  // not have a top right
370
  while (bs < sb_mi_size) {
371 372
    if (mask_col & bs) {
      if ((mask_col & (2 * bs)) && (mask_row & (2 * bs))) {
373
        has_tr = 0;
374 375 376 377 378 379 380
        break;
      }
    } else {
      break;
    }
    bs <<= 1;
  }
381

382
  // The left hand of two vertical rectangles always has a top right (as the
383
  // block above will have been decoded)
384
  if (xd->n8_w < xd->n8_h)
clang-format's avatar
clang-format committed
385
    if (!xd->is_sec_rect) has_tr = 1;
386

387 388
  // The bottom of two horizontal rectangles never has a top right (as the block
  // to the right won't have been decoded)
389
  if (xd->n8_w > xd->n8_h)
clang-format's avatar
clang-format committed
390
    if (xd->is_sec_rect) has_tr = 0;
391

392
#if CONFIG_EXT_PARTITION_TYPES
393 394 395
  // The bottom left square of a Vertical A (in the old format) does
  // not have a top right as it is decoded before the right hand
  // rectangle of the partition
396
  if (xd->mi[0]->mbmi.partition == PARTITION_VERT_A) {
397 398
    if (xd->n8_w == xd->n8_h)
      if (mask_row & bs) has_tr = 0;
399
  }
400 401
#endif  // CONFIG_EXT_PARTITION_TYPES

402 403 404
  return has_tr;
}

405
#if CONFIG_MFMV
406 407 408
static int check_sb_border(const int mi_row, const int mi_col,
                           const int row_offset, const int col_offset) {
  const int sb_mi_size = mi_size_wide[BLOCK_64X64];
409 410 411 412 413
  const int row = mi_row & (sb_mi_size - 1);
  const int col = mi_col & (sb_mi_size - 1);

  if (row + row_offset < 0 || row + row_offset >= sb_mi_size ||
      col + col_offset < 0 || col + col_offset >= sb_mi_size)
414 415 416 417 418
    return 0;

  return 1;
}

419 420 421 422
static int add_tpl_ref_mv(const AV1_COMMON *cm,
                          const MV_REF *prev_frame_mvs_base,
                          const MACROBLOCKD *xd, int mi_row, int mi_col,
                          MV_REFERENCE_FRAME ref_frame, int blk_row,
423
                          int blk_col, int_mv *gm_mv_candidates,
424 425
                          uint8_t refmv_count[MODE_CTX_REF_FRAMES],
                          CANDIDATE_MV ref_mv_stacks[][MAX_REF_MV_STACK_SIZE],
426
                          int16_t *mode_context) {
427 428 429 430 431 432
  (void)prev_frame_mvs_base;
  POSITION mi_pos;
  int idx;
  int coll_blk_count = 0;
  const int weight_unit = 1;  // mi_size_wide[BLOCK_8X8];

433 434
  (void)gm_mv_candidates;

435 436 437 438 439 440
  mi_pos.row = (mi_row & 0x01) ? blk_row : blk_row + 1;
  mi_pos.col = (mi_col & 0x01) ? blk_col : blk_col + 1;

  if (!is_inside(&xd->tile, mi_col, mi_row, cm->mi_rows, cm, &mi_pos))
    return coll_blk_count;

441
  const TPL_MV_REF *prev_frame_mvs =
Jingning Han's avatar
Jingning Han committed
442
      cm->tpl_mvs + ((mi_row + mi_pos.row) >> 1) * (cm->mi_stride >> 1) +
443
      ((mi_col + mi_pos.col) >> 1);
Jingning Han's avatar
Jingning Han committed
444

445 446 447 448
  MV_REFERENCE_FRAME rf[2];
  av1_set_ref_frame(rf, ref_frame);

  if (rf[1] == NONE_FRAME) {
449 450
    int cur_frame_index = cm->cur_frame->cur_frame_offset;
    int buf_idx_0 = cm->frame_refs[FWD_RF_OFFSET(rf[0])].idx;
Yaowu Xu's avatar
Yaowu Xu committed
451 452
    int frame0_index = cm->buffer_pool->frame_bufs[buf_idx_0].cur_frame_offset;
    int cur_offset_0 = cur_frame_index - frame0_index;
453
    CANDIDATE_MV *ref_mv_stack = ref_mv_stacks[rf[0]];
454

455
    for (int i = 0; i < MFMV_STACK_SIZE; ++i) {
456 457 458 459 460
      if (prev_frame_mvs->mfmv0[i].as_int != INVALID_MV) {
        int_mv this_refmv;

        get_mv_projection(&this_refmv.as_mv, prev_frame_mvs->mfmv0[i].as_mv,
                          cur_offset_0, prev_frame_mvs->ref_frame_offset[i]);
RogerZhou's avatar
RogerZhou committed
461 462 463 464
#if CONFIG_AMVR
        lower_mv_precision(&this_refmv.as_mv, cm->allow_high_precision_mv,
                           cm->cur_frame_force_integer_mv);
#else
465
        lower_mv_precision(&this_refmv.as_mv, cm->allow_high_precision_mv);
RogerZhou's avatar
RogerZhou committed
466
#endif
467

468 469 470 471 472 473
#if CONFIG_OPT_REF_MV
        if (blk_row == 0 && blk_col == 0)
          if (abs(this_refmv.as_mv.row - gm_mv_candidates[0].as_mv.row) >= 16 ||
              abs(this_refmv.as_mv.col - gm_mv_candidates[0].as_mv.col) >= 16)
            mode_context[ref_frame] |= (1 << GLOBALMV_OFFSET);
#else
474 475 476
        if (blk_row == 0 && blk_col == 0)
          if (abs(this_refmv.as_mv.row) >= 16 ||
              abs(this_refmv.as_mv.col) >= 16)
Sarah Parker's avatar
Sarah Parker committed
477
            mode_context[ref_frame] |= (1 << GLOBALMV_OFFSET);
478
#endif
479

480
        for (idx = 0; idx < refmv_count[rf[0]]; ++idx)
481
          if (this_refmv.as_int == ref_mv_stack[idx].this_mv.as_int) break;
482

483 484
        if (idx < refmv_count[rf[0]])
          ref_mv_stack[idx].weight += 2 * weight_unit;
485

486 487
        if (idx == refmv_count[rf[0]] &&
            refmv_count[rf[0]] < MAX_REF_MV_STACK_SIZE) {
488 489 490 491 492
          ref_mv_stack[idx].this_mv.as_int = this_refmv.as_int;
          // TODO(jingning): Hard coded context number. Need to make it better
          // sense.
          ref_mv_stack[idx].pred_diff[0] = 1;
          ref_mv_stack[idx].weight = 2 * weight_unit;
493
          ++(refmv_count[rf[0]]);
494 495 496
        }

        ++coll_blk_count;
497
        return coll_blk_count;
498 499 500 501
      }
    }
  } else {
    // Process compound inter mode
502 503
    int cur_frame_index = cm->cur_frame->cur_frame_offset;
    int buf_idx_0 = cm->frame_refs[FWD_RF_OFFSET(rf[0])].idx;
Yaowu Xu's avatar
Yaowu Xu committed
504 505 506
    int frame0_index = cm->buffer_pool->frame_bufs[buf_idx_0].cur_frame_offset;

    int cur_offset_0 = cur_frame_index - frame0_index;
507
    int buf_idx_1 = cm->frame_refs[FWD_RF_OFFSET(rf[1])].idx;
Yaowu Xu's avatar
Yaowu Xu committed
508 509
    int frame1_index = cm->buffer_pool->frame_bufs[buf_idx_1].cur_frame_offset;
    int cur_offset_1 = cur_frame_index - frame1_index;
510
    CANDIDATE_MV *ref_mv_stack = ref_mv_stacks[ref_frame];
511

512
    for (int i = 0; i < MFMV_STACK_SIZE; ++i) {
513 514 515 516 517 518 519 520
      if (prev_frame_mvs->mfmv0[i].as_int != INVALID_MV) {
        int_mv this_refmv;
        int_mv comp_refmv;
        get_mv_projection(&this_refmv.as_mv, prev_frame_mvs->mfmv0[i].as_mv,
                          cur_offset_0, prev_frame_mvs->ref_frame_offset[i]);
        get_mv_projection(&comp_refmv.as_mv, prev_frame_mvs->mfmv0[i].as_mv,
                          cur_offset_1, prev_frame_mvs->ref_frame_offset[i]);

RogerZhou's avatar
RogerZhou committed
521 522 523 524 525 526
#if CONFIG_AMVR
        lower_mv_precision(&this_refmv.as_mv, cm->allow_high_precision_mv,
                           cm->cur_frame_force_integer_mv);
        lower_mv_precision(&comp_refmv.as_mv, cm->allow_high_precision_mv,
                           cm->cur_frame_force_integer_mv);
#else
527 528
        lower_mv_precision(&this_refmv.as_mv, cm->allow_high_precision_mv);
        lower_mv_precision(&comp_refmv.as_mv, cm->allow_high_precision_mv);
RogerZhou's avatar
RogerZhou committed
529
#endif
530 531 532 533 534 535 536 537 538

#if CONFIG_OPT_REF_MV
        if (blk_row == 0 && blk_col == 0)
          if (abs(this_refmv.as_mv.row - gm_mv_candidates[0].as_mv.row) >= 16 ||
              abs(this_refmv.as_mv.col - gm_mv_candidates[0].as_mv.col) >= 16 ||
              abs(comp_refmv.as_mv.row - gm_mv_candidates[1].as_mv.row) >= 16 ||
              abs(comp_refmv.as_mv.col - gm_mv_candidates[1].as_mv.col) >= 16)
            mode_context[ref_frame] |= (1 << GLOBALMV_OFFSET);
#else
539 540 541 542 543
        if (blk_row == 0 && blk_col == 0)
          if (abs(this_refmv.as_mv.row) >= 16 ||
              abs(this_refmv.as_mv.col) >= 16 ||
              abs(comp_refmv.as_mv.row) >= 16 ||
              abs(comp_refmv.as_mv.col) >= 16)
Sarah Parker's avatar
Sarah Parker committed
544
            mode_context[ref_frame] |= (1 << GLOBALMV_OFFSET);
545
#endif
546

547
        for (idx = 0; idx < refmv_count[ref_frame]; ++idx)
548 549
          if (this_refmv.as_int == ref_mv_stack[idx].this_mv.as_int &&
              comp_refmv.as_int == ref_mv_stack[idx].comp_mv.as_int)
550 551
            break;

552 553
        if (idx < refmv_count[ref_frame])
          ref_mv_stack[idx].weight += 2 * weight_unit;
554

555 556
        if (idx == refmv_count[ref_frame] &&
            refmv_count[ref_frame] < MAX_REF_MV_STACK_SIZE) {
557 558 559 560 561 562 563
          ref_mv_stack[idx].this_mv.as_int = this_refmv.as_int;
          ref_mv_stack[idx].comp_mv.as_int = comp_refmv.as_int;
          // TODO(jingning): Hard coded context number. Need to make it better
          // sense.
          ref_mv_stack[idx].pred_diff[0] = 1;
          ref_mv_stack[idx].pred_diff[1] = 1;
          ref_mv_stack[idx].weight = 2 * weight_unit;
564
          ++(refmv_count[ref_frame]);
565 566 567
        }

        ++coll_blk_count;
568
        return coll_blk_count;
569 570 571 572 573 574 575
      }
    }
  }

  return coll_blk_count;
}
#else
576 577
static int add_col_ref_mv(const AV1_COMMON *cm,
                          const MV_REF *prev_frame_mvs_base,
578 579
                          int prev_frame_mvs_stride, const MACROBLOCKD *xd,
                          int mi_row, int mi_col, MV_REFERENCE_FRAME ref_frame,
580 581 582 583
                          int blk_row, int blk_col,
                          uint8_t refmv_count[MODE_CTX_REF_FRAMES],
                          CANDIDATE_MV ref_mv_stacks[][MAX_REF_MV_STACK_SIZE],
                          int16_t *mode_context) {
584 585
#if CONFIG_TMV
  const MV_REF *prev_frame_mvs = prev_frame_mvs_base +
Yunqing Wang's avatar
Yunqing Wang committed
586 587
                                 (blk_row >> 1) * prev_frame_mvs_stride +
                                 (blk_col >> 1);
588
#else
589
  const MV_REF *prev_frame_mvs =
590 591
      prev_frame_mvs_base + blk_row * prev_frame_mvs_stride + blk_col;
#endif
592 593 594
  POSITION mi_pos;
  int ref, idx;
  int coll_blk_count = 0;
595
  const int weight_unit = mi_size_wide[BLOCK_8X8];
596
  CANDIDATE_MV *ref_mv_stack = ref_mv_stacks[ref_frame];
597

598 599 600 601
#if CONFIG_TMV
  mi_pos.row = blk_row;
  mi_pos.col = blk_col;
#else
602 603
  mi_pos.row = (mi_row & 0x01) ? blk_row : blk_row + 1;
  mi_pos.col = (mi_col & 0x01) ? blk_col : blk_col + 1;
604
#endif  // CONFIG_TMV
605

606
  if (!is_inside(&xd->tile, mi_col, mi_row, cm->mi_rows, cm, &mi_pos))
607
    return coll_blk_count;
608 609 610
  for (ref = 0; ref < 2; ++ref) {
    if (prev_frame_mvs->ref_frame[ref] == ref_frame) {
      int_mv this_refmv = prev_frame_mvs->mv[ref];
RogerZhou's avatar
RogerZhou committed
611 612
#if CONFIG_AMVR
      lower_mv_precision(&this_refmv.as_mv, cm->allow_high_precision_mv,
613
                         cm->cur_frame_force_integer_mv);
RogerZhou's avatar
RogerZhou committed
614
#else
615
      lower_mv_precision(&this_refmv.as_mv, cm->allow_high_precision_mv);
RogerZhou's avatar
RogerZhou committed
616
#endif
617 618 619 620 621 622

#if CONFIG_OPT_REF_MV
      if (blk_row == 0 && blk_col == 0)
#endif
      {
        if (abs(this_refmv.as_mv.row) >= 16 || abs(this_refmv.as_mv.col) >= 16)
Sarah Parker's avatar
Sarah Parker committed
623
          mode_context[ref_frame] |= (1 << GLOBALMV_OFFSET);
624
      }
625

626
      for (idx = 0; idx < refmv_count[ref_frame]; ++idx)
627 628
        if (this_refmv.as_int == ref_mv_stack[idx].this_mv.as_int) break;

629 630
      if (idx < refmv_count[ref_frame])
        ref_mv_stack[idx].weight += 2 * weight_unit;
631

632 633
      if (idx == refmv_count[ref_frame] &&
          refmv_count[ref_frame] < MAX_REF_MV_STACK_SIZE) {
634
        ref_mv_stack[idx].this_mv.as_int = this_refmv.as_int;
635 636
        ref_mv_stack[idx].pred_diff[0] =
            av1_get_pred_diff_ctx(prev_frame_mvs->pred_mv[ref], this_refmv);
637
        ref_mv_stack[idx].weight = 2 * weight_unit;
638
        ++(refmv_count[ref_frame]);
639 640 641 642 643 644 645 646
      }

      ++coll_blk_count;
    }
  }

  return coll_blk_count;
}
647
#endif  // CONFIG_MFMV
648

649 650 651 652 653
static void setup_ref_mv_list(
    const AV1_COMMON *cm, const MACROBLOCKD *xd, MV_REFERENCE_FRAME ref_frame,
    uint8_t refmv_count[MODE_CTX_REF_FRAMES],
    CANDIDATE_MV ref_mv_stack[][MAX_REF_MV_STACK_SIZE],
    int_mv mv_ref_list[][MAX_MV_REF_CANDIDATES],
654
#if USE_CUR_GM_REFMV
655
    int_mv *gm_mv_candidates,
656
#endif  // USE_CUR_GM_REFMV
657
    int mi_row, int mi_col, int16_t *mode_context, int compound_search) {
658 659 660 661 662 663 664 665 666 667 668
#if CONFIG_TMV
  const int prev_frame_mvs_stride = ROUND_POWER_OF_TWO(cm->mi_cols, 1);
  const int tmi_row = mi_row & 0xfffe;
  const int tmi_col = mi_col & 0xfffe;
  const MV_REF *const prev_frame_mvs_base =
      cm->use_prev_frame_mvs
          ? cm->prev_frame->mvs + (tmi_row >> 1) * prev_frame_mvs_stride +
                (tmi_col >> 1)
          : NULL;
#else
  const int prev_frame_mvs_stride = cm->mi_cols;
669 670
  const MV_REF *const prev_frame_mvs_base =
      cm->use_prev_frame_mvs
671 672
          ? cm->prev_frame->mvs +
                (((mi_row >> 1) << 1) + 1) * prev_frame_mvs_stride +
673 674
                ((mi_col >> 1) << 1) + 1
          : NULL;
675
#endif  // CONFIG_TMV
676

677
  const int bs = AOMMAX(xd->n8_w, xd->n8_h);
678
  const int has_tr = has_top_right(cm, xd, mi_row, mi_col, bs);
Jingning Han's avatar
Jingning Han committed
679 680
  MV_REFERENCE_FRAME rf[2];

Yunqing Wang's avatar
Yunqing Wang committed
681
  const TileInfo *const tile = &xd->tile;
682 683 684 685 686
  int max_row_offset = 0, max_col_offset = 0;
  const int row_adj = (xd->n8_h < mi_size_high[BLOCK_8X8]) && (mi_row & 0x01);
  const int col_adj = (xd->n8_w < mi_size_wide[BLOCK_8X8]) && (mi_col & 0x01);
  int processed_rows = 0;
  int processed_cols = 0;
Yunqing Wang's avatar
Yunqing Wang committed
687

688
  av1_set_ref_frame(rf, ref_frame);
689
  mode_context[ref_frame] = 0;
Yunqing Wang's avatar
Yunqing Wang committed
690 691 692 693 694 695 696
  if (!compound_search) {
    refmv_count[ref_frame] = 0;
  } else {
    refmv_count[ref_frame] = 0;
    // refmv_count[rf[0]] = 0;
    // refmv_count[rf[1]] = 0;
  }
697

698 699 700
  // Find valid maximum row/col offset.
  if (xd->up_available) {
    max_row_offset = -(MVREF_ROWS << 1) + row_adj;
701 702 703 704
#if CONFIG_OPT_REF_MV
    if (xd->n8_h < mi_size_high[BLOCK_8X8])
      max_row_offset = -(2 << 1) + row_adj;
#endif
Yunqing Wang's avatar
Yunqing Wang committed
705 706 707
    max_row_offset =
        find_valid_row_offset(tile, mi_row, cm->mi_rows, cm, max_row_offset);
  }
708 709 710

  if (xd->left_available) {
    max_col_offset = -(MVREF_COLS << 1) + col_adj;
711 712 713 714
#if CONFIG_OPT_REF_MV
    if (xd->n8_w < mi_size_wide[BLOCK_8X8])
      max_col_offset = -(2 << 1) + col_adj;
#endif
Yunqing Wang's avatar
Yunqing Wang committed
715 716
    max_col_offset = find_valid_col_offset(tile, mi_col, max_col_offset);
  }
717

718
  uint8_t ref_match_count[MODE_CTX_REF_FRAMES] = { 0 };
Yunqing Wang's avatar
Yunqing Wang committed
719
  uint8_t newmv_count[MODE_CTX_REF_FRAMES] = { 0 };
720

721 722
  // Scan the first above row mode info. row_offset = -1;
  if (abs(max_row_offset) >= 1)
Yunqing Wang's avatar
Yunqing Wang committed
723 724
    scan_row_mbmi(cm, xd, mi_row, mi_col, rf, -1, ref_mv_stack, refmv_count,
                  ref_match_count, newmv_count,
725
#if USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
726
                  gm_mv_candidates,
727
#endif  // USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
728
                  max_row_offset, &processed_rows);
729 730
  // Scan the first left column mode info. col_offset = -1;
  if (abs(max_col_offset) >= 1)
Yunqing Wang's avatar
Yunqing Wang committed
731 732
    scan_col_mbmi(cm, xd, mi_row, mi_col, rf, -1, ref_mv_stack, refmv_count,
                  ref_match_count, newmv_count,
733
#if USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
734
                  gm_mv_candidates,
735
#endif  // USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
736
                  max_col_offset, &processed_cols);
737 738
  // Check top-right boundary
  if (has_tr)
Yunqing Wang's avatar
Yunqing Wang committed
739 740
    scan_blk_mbmi(cm, xd, mi_row, mi_col, rf, -1, xd->n8_w, ref_mv_stack,
                  ref_match_count, newmv_count,
741
#if USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
742
                  gm_mv_candidates,
743
#endif  // USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
744
                  refmv_count);
745

746 747 748 749 750
  uint8_t nearest_match[MODE_CTX_REF_FRAMES];
  uint8_t nearest_refmv_count[MODE_CTX_REF_FRAMES];

  nearest_match[ref_frame] = ref_match_count[ref_frame];
  nearest_refmv_count[ref_frame] = refmv_count[ref_frame];
751

752 753 754
  // TODO(yunqing): for comp_search, do it for all 3 cases.
  for (int idx = 0; idx < nearest_refmv_count[ref_frame]; ++idx)
    ref_mv_stack[ref_frame][idx].weight += REF_CAT_LEVEL;
755 756

#if CONFIG_MFMV
757
  if (cm->use_ref_frame_mvs) {
758
    int coll_blk_count[MODE_CTX_REF_FRAMES] = { 0 };
759 760
    const int voffset = AOMMAX(mi_size_high[BLOCK_8X8], xd->n8_h);
    const int hoffset = AOMMAX(mi_size_wide[BLOCK_8X8], xd->n8_w);
761 762
    const int blk_row_end = AOMMIN(xd->n8_h, mi_size_high[BLOCK_64X64]);
    const int blk_col_end = AOMMIN(xd->n8_w, mi_size_wide[BLOCK_64X64]);
763

Jingning Han's avatar
Jingning Han committed
764
    const int tpl_sample_pos[3][2] = {
765 766 767
      { voffset, -2 },
      { voffset, hoffset },
      { voffset - 2, hoffset },
768
    };
Jingning Han's avatar
Jingning Han committed
769
    const int allow_extension = (xd->n8_h >= mi_size_high[BLOCK_8X8]) &&
770 771 772
                                (xd->n8_h < mi_size_high[BLOCK_64X64]) &&
                                (xd->n8_w >= mi_size_wide[BLOCK_8X8]) &&
                                (xd->n8_w < mi_size_wide[BLOCK_64X64]);
773

774 775 776 777 778 779 780 781 782
    int step_h = (xd->n8_h >= mi_size_high[BLOCK_64X64])
                     ? mi_size_high[BLOCK_16X16]
                     : mi_size_high[BLOCK_8X8];
    int step_w = (xd->n8_w >= mi_size_wide[BLOCK_64X64])
                     ? mi_size_wide[BLOCK_16X16]
                     : mi_size_wide[BLOCK_8X8];

    for (int blk_row = 0; blk_row < blk_row_end; blk_row += step_h) {
      for (int blk_col = 0; blk_col < blk_col_end; blk_col += step_w) {
783 784 785 786 787
        // (TODO: yunqing) prev_frame_mvs_base is not used here, tpl_mvs is
        // used.
        // Can be modified the same way.
        int is_available = add_tpl_ref_mv(
            cm, prev_frame_mvs_base, xd, mi_row, mi_col, ref_frame, blk_row,
788
            blk_col, gm_mv_candidates, refmv_count, ref_mv_stack, mode_context);
789 790
        if (blk_row == 0 && blk_col == 0)
          coll_blk_count[ref_frame] = is_available;
791
      }
792 793
    }

794 795
    if (coll_blk_count[ref_frame] == 0)
      mode_context[ref_frame] |= (1 << GLOBALMV_OFFSET);
796

Jingning Han's avatar
Jingning Han committed
797
    for (int i = 0; i < 3 && allow_extension; ++i) {
798 799
      const int blk_row = tpl_sample_pos[i][0];
      const int blk_col = tpl_sample_pos[i][1];
800

801
      if (!check_sb_border(mi_row, mi_col, blk_row, blk_col)) continue;
802 803
      // (TODO: yunqing) prev_frame_mvs_base is not used here, tpl_mvs is used.
      // Can be modified the same way.
804
      coll_blk_count[ref_frame] += add_tpl_ref_mv(
805 806
          cm, prev_frame_mvs_base, xd, mi_row, mi_col, ref_frame, blk_row,
          blk_col, gm_mv_candidates, refmv_count, ref_mv_stack, mode_context);
807
    }
808 809
  }
#else
810
  if (cm->use_prev_frame_mvs && rf[1] == NONE_FRAME) {
811
    int coll_blk_count[MODE_CTX_REF_FRAMES] = { 0 };
812 813 814
    const int mi_step = (xd->n8_w == 1 || xd->n8_h == 1)
                            ? mi_size_wide[BLOCK_8X8]
                            : mi_size_wide[BLOCK_16X16];
815

816 817
    for (int blk_row = 0; blk_row < xd->n8_h; blk_row += mi_step) {
      for (int blk_col = 0; blk_col < xd->n8_w; blk_col += mi_step) {
818 819 820 821 822 823 824 825 826 827 828
#if CONFIG_TMV
        int is_available =
            add_col_ref_mv(cm, prev_frame_mvs_base, prev_frame_mvs_stride, xd,
                           tmi_row, tmi_col, ref_frame, blk_row, blk_col,
                           refmv_count, ref_mv_stack, mode_context);
#else
        int is_available =
            add_col_ref_mv(cm, prev_frame_mvs_base, prev_frame_mvs_stride, xd,
                           mi_row, mi_col, ref_frame, blk_row, blk_col,
                           refmv_count, ref_mv_stack, mode_context);
#endif  // CONFIG_TMV
829
#if CONFIG_OPT_REF_MV
830 831
        if (blk_row == 0 && blk_col == 0)
          coll_blk_count[ref_frame] = is_available;
832
#else
833
        coll_blk_count[ref_frame] += is_available;
834
#endif
835 836
      }
    }
837

838 839
    if (coll_blk_count[ref_frame] == 0)
      mode_context[ref_frame] |= (1 << GLOBALMV_OFFSET);
840
  } else {
Sarah Parker's avatar
Sarah Parker committed
841
    mode_context[ref_frame] |= (1 << GLOBALMV_OFFSET);
842
  }
843
#endif  // CONFIG_MFMV
844

Yunqing Wang's avatar
Yunqing Wang committed
845 846
  uint8_t dummy_newmv_count[MODE_CTX_REF_FRAMES] = { 0 };

847
  // Scan the second outer area.
Luc Trudeau's avatar
Luc Trudeau committed
848
  scan_blk_mbmi(cm, xd, mi_row, mi_col, rf, -1, -1, ref_mv_stack,
Yunqing Wang's avatar
Yunqing Wang committed
849
                ref_match_count, dummy_newmv_count,
850
#if USE_CUR_GM_REFMV
851
                gm_mv_candidates,
852
#endif  // USE_CUR_GM_REFMV
Deng's avatar
Deng committed
853
                refmv_count);
854

855 856 857
  for (int idx = 2; idx <= MVREF_ROWS; ++idx) {
    const int row_offset = -(idx << 1) + 1 + row_adj;
    const int col_offset = -(idx << 1) + 1 + col_adj;
Yunqing Wang's avatar
Yunqing Wang committed
858

859 860
    if (abs(row_offset) <= abs(max_row_offset) &&
        abs(row_offset) > processed_rows)
Luc Trudeau's avatar
Luc Trudeau committed
861
      scan_row_mbmi(cm, xd, mi_row, mi_col, rf, row_offset, ref_mv_stack,
Yunqing Wang's avatar
Yunqing Wang committed
862
                    refmv_count, ref_match_count, dummy_newmv_count,
863
#if USE_CUR_GM_REFMV
864
                    gm_mv_candidates,
865
#endif  // USE_CUR_GM_REFMV
866
                    max_row_offset, &processed_rows);
867 868 869

    if (abs(col_offset) <= abs(max_col_offset) &&
        abs(col_offset) > processed_cols)
Luc Trudeau's avatar
Luc Trudeau committed
870
      scan_col_mbmi(cm, xd, mi_row, mi_col, rf, col_offset, ref_mv_stack,
Yunqing Wang's avatar
Yunqing Wang committed
871
                    refmv_count, ref_match_count, dummy_newmv_count,
872
#if USE_CUR_GM_REFMV
873
                    gm_mv_candidates,
874
#endif  // USE_CUR_GM_REFMV
875
                    max_col_offset, &processed_cols);
Yunqing Wang's avatar
Yunqing Wang committed
876 877
  }

878
  const int col_offset = -(MVREF_COLS << 1) + 1 + col_adj;
879 880
  if (abs(col_offset) <= abs(max_col_offset) &&
      abs(col_offset) > processed_cols)
Luc Trudeau's avatar
Luc Trudeau committed
881
    scan_col_mbmi(cm, xd, mi_row, mi_col, rf, col_offset, ref_mv_stack,
Yunqing Wang's avatar
Yunqing Wang committed
882
                  refmv_count, ref_match_count, dummy_newmv_count,
883
#if USE_CUR_GM_REFMV
884
                  gm_mv_candidates,
885
#endif  // USE_CUR_GM_REFMV
886
                  max_col_offset, &processed_cols);
887