mvref_common.c 83.8 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
#include "av1/common/mvref_common.h"
Yue Chen's avatar
Yue Chen committed
13
14
15
#if CONFIG_WARPED_MOTION
#include "av1/common/warped_motion.h"
#endif  // CONFIG_WARPED_MOTION
Jingning Han's avatar
Jingning Han committed
16

17
18
19
20
#if CONFIG_GLOBAL_MOTION
#define USE_CUR_GM_REFMV 1
#endif  // CONFIG_GLOBAL_MOTION

21
22
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) {
23
#if CONFIG_TMV || CONFIG_MFMV
24
  const int frame_mvs_stride = ROUND_POWER_OF_TWO(cm->mi_cols, 1);
25
26
  MV_REF *frame_mvs =
      cm->cur_frame->mvs + (mi_row >> 1) * frame_mvs_stride + (mi_col >> 1);
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
  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++) {
    MV_REF *const frame_mv = frame_mvs + h * frame_mvs_stride;
    for (w = 0; w < x_mis; w++) {
      MV_REF *const mv = frame_mv + w;
      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;
      // (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;
    }
  }
}

53
54
55
56
57
58
59
static uint8_t add_ref_mv_candidate(
    const MODE_INFO *const candidate_mi, const MB_MODE_INFO *const candidate,
    const MV_REFERENCE_FRAME rf[2], uint8_t *refmv_count,
    CANDIDATE_MV *ref_mv_stack, const int use_hp, int len, int block,
#if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
    int_mv *gm_mv_candidates, const WarpedMotionParams *gm_params,
#endif  // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
60
    int col, int weight,
RogerZhou's avatar
RogerZhou committed
61
#if CONFIG_AMVR
Yunqing Wang's avatar
Yunqing Wang committed
62
    int is_integer,
RogerZhou's avatar
RogerZhou committed
63
#endif
Yunqing Wang's avatar
Yunqing Wang committed
64
65
    BLOCK_SIZE bsize, int mi_row, int mi_col, int subsampling_x,
    int subsampling_y) {
Jingning Han's avatar
Jingning Han committed
66
67
  int index = 0, ref;
  int newmv_count = 0;
68
69
70
71
72
#if CONFIG_CB4X4
  const int unify_bsize = 1;
#else
  const int unify_bsize = 0;
#endif
73
  assert(weight % 2 == 0);
Yunqing Wang's avatar
Yunqing Wang committed
74
75
76
77
78
79
80
#if !CONFIG_EXT_WARPED_MOTION
  (void)bsize;
  (void)mi_row;
  (void)mi_col;
  (void)subsampling_x;
  (void)subsampling_y;
#endif  // CONFIG_EXT_WARPED_MOTION
Jingning Han's avatar
Jingning Han committed
81

Emil Keyder's avatar
Emil Keyder committed
82
  if (rf[1] == NONE_FRAME) {
Jingning Han's avatar
Jingning Han committed
83
84
85
    // single reference frame
    for (ref = 0; ref < 2; ++ref) {
      if (candidate->ref_frame[ref] == rf[0]) {
86
        int_mv this_refmv;
Yunqing Wang's avatar
Yunqing Wang committed
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#if CONFIG_EXT_WARPED_MOTION
        if (candidate->motion_mode == WARPED_CAUSAL) {
          WarpedMotionParams wm = candidate->wm_params[0];
          const int bw = block_size_wide[bsize];
          const int bh = block_size_high[bsize];
          int global_offset_c = mi_col * MI_SIZE;
          int global_offset_r = mi_row * MI_SIZE;
          int cc_offset = bw / 2 - 1;
          int cr_offset = bh / 2 - 1;
          int xc0 = cc_offset + global_offset_c;
          int yc0 = cr_offset + global_offset_r;
          int xc1 = xc0 + 1;
          int yc1 = yc0 + 1;
          int in[4] = { xc0, yc0, xc1, yc1 };
          int out[4] = { 0, 0, 0, 0 };

          assert(ref == 0);
          // For WARPED_CAUSAL, wmtype is always AFFINE.
          assert(wm.wmtype == AFFINE);
          project_points_affine(wm.wmmat, in, out, 2, 2, 2, subsampling_x,
                                subsampling_y);

          // assert(x_scale == 1024 && y_scale == 1024);
          // out[]'s precision is 1/64, adjust xc, yc accordingly.
          out[0] -= (xc0 << (3 + SCALING_FCT));
          out[1] -= (yc0 << (3 + SCALING_FCT));
          out[2] -= (xc1 << (3 + SCALING_FCT));
          out[3] -= (yc1 << (3 + SCALING_FCT));

          this_refmv.as_mv.col =
              ROUND_POWER_OF_TWO_SIGNED(out[0] + out[2], SCALING_FCT + 1);
          this_refmv.as_mv.row =
              ROUND_POWER_OF_TWO_SIGNED(out[1] + out[3], SCALING_FCT + 1);
          lower_mv_precision(&this_refmv.as_mv, use_hp);
        } else {
#endif  // CONFIG_EXT_WARPED_MOTION
123
#if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
124
125
126
          if (is_global_mv_block(candidate_mi, block, gm_params[rf[0]].wmtype))
            this_refmv = gm_mv_candidates[0];
          else
127
#endif  // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
128
            this_refmv = get_sub_block_mv(candidate_mi, ref, col, block);
RogerZhou's avatar
RogerZhou committed
129
#if CONFIG_AMVR
Yunqing Wang's avatar
Yunqing Wang committed
130
          lower_mv_precision(&this_refmv.as_mv, use_hp, is_integer);
RogerZhou's avatar
RogerZhou committed
131
#else
132
        lower_mv_precision(&this_refmv.as_mv, use_hp);
133
#endif  // CONFIG_AMVR
Yunqing Wang's avatar
Yunqing Wang committed
134
135
136
#if CONFIG_EXT_WARPED_MOTION
        }
#endif  // CONFIG_EXT_WARPED_MOTION
137

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

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

Jingning Han's avatar
Jingning Han committed
143
144
145
        // Add a new item to the list.
        if (index == *refmv_count) {
          ref_mv_stack[index].this_mv = this_refmv;
146
147
          ref_mv_stack[index].pred_diff[0] = av1_get_pred_diff_ctx(
              get_sub_block_pred_mv(candidate_mi, ref, col, block), this_refmv);
148
          ref_mv_stack[index].weight = weight * len;
Jingning Han's avatar
Jingning Han committed
149
          ++(*refmv_count);
150

151
          if (candidate->mode == NEWMV) ++newmv_count;
Jingning Han's avatar
Jingning Han committed
152
153
        }

154
155
        if (candidate_mi->mbmi.sb_type < BLOCK_8X8 && block >= 0 &&
            !unify_bsize) {
Jingning Han's avatar
Jingning Han committed
156
          int alt_block = 3 - block;
clang-format's avatar
clang-format committed
157
          this_refmv = get_sub_block_mv(candidate_mi, ref, col, alt_block);
RogerZhou's avatar
RogerZhou committed
158
159
160
#if CONFIG_AMVR
          lower_mv_precision(&this_refmv.as_mv, use_hp, is_integer);
#else
161
          lower_mv_precision(&this_refmv.as_mv, use_hp);
RogerZhou's avatar
RogerZhou committed
162
#endif
163
          for (index = 0; index < *refmv_count; ++index)
clang-format's avatar
clang-format committed
164
            if (ref_mv_stack[index].this_mv.as_int == this_refmv.as_int) break;
165

Yaowu Xu's avatar
Yaowu Xu committed
166
          if (index < *refmv_count) ref_mv_stack[index].weight += len;
167
168
169
170

          // Add a new item to the list.
          if (index == *refmv_count) {
            ref_mv_stack[index].this_mv = this_refmv;
171
172
173
            ref_mv_stack[index].pred_diff[0] = av1_get_pred_diff_ctx(
                get_sub_block_pred_mv(candidate_mi, ref, col, alt_block),
                this_refmv);
Yaowu Xu's avatar
Yaowu Xu committed
174
            ref_mv_stack[index].weight = len;
175
            ++(*refmv_count);
176

177
            if (candidate->mode == NEWMV) ++newmv_count;
178
179
180
          }
        }
      }
Jingning Han's avatar
Jingning Han committed
181
182
183
    }
  } else {
    // compound reference frame
clang-format's avatar
clang-format committed
184
    if (candidate->ref_frame[0] == rf[0] && candidate->ref_frame[1] == rf[1]) {
185
      int_mv this_refmv[2];
Jingning Han's avatar
Jingning Han committed
186

187
      for (ref = 0; ref < 2; ++ref) {
188
189
190
191
192
193
#if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
        if (is_global_mv_block(candidate_mi, block, gm_params[rf[ref]].wmtype))
          this_refmv[ref] = gm_mv_candidates[ref];
        else
#endif  // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
          this_refmv[ref] = get_sub_block_mv(candidate_mi, ref, col, block);
RogerZhou's avatar
RogerZhou committed
194
195
196
#if CONFIG_AMVR
        lower_mv_precision(&this_refmv[ref].as_mv, use_hp, is_integer);
#else
197
        lower_mv_precision(&this_refmv[ref].as_mv, use_hp);
RogerZhou's avatar
RogerZhou committed
198
#endif
199
      }
200

Jingning Han's avatar
Jingning Han committed
201
202
203
204
205
      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;

206
      if (index < *refmv_count) ref_mv_stack[index].weight += weight * len;
Jingning Han's avatar
Jingning Han committed
207
208
209
210
211

      // Add a new item to the list.
      if (index == *refmv_count) {
        ref_mv_stack[index].this_mv = this_refmv[0];
        ref_mv_stack[index].comp_mv = this_refmv[1];
212
213
214
215
        ref_mv_stack[index].pred_diff[0] = av1_get_pred_diff_ctx(
            get_sub_block_pred_mv(candidate_mi, 0, col, block), this_refmv[0]);
        ref_mv_stack[index].pred_diff[1] = av1_get_pred_diff_ctx(
            get_sub_block_pred_mv(candidate_mi, 1, col, block), this_refmv[1]);
216
        ref_mv_stack[index].weight = weight * len;
Jingning Han's avatar
Jingning Han committed
217
218
        ++(*refmv_count);

219
        if (candidate->mode == NEW_NEWMV) ++newmv_count;
Jingning Han's avatar
Jingning Han committed
220
221
      }

222
223
      if (candidate_mi->mbmi.sb_type < BLOCK_8X8 && block >= 0 &&
          !unify_bsize) {
Jingning Han's avatar
Jingning Han committed
224
225
226
227
        int alt_block = 3 - block;
        this_refmv[0] = get_sub_block_mv(candidate_mi, 0, col, alt_block);
        this_refmv[1] = get_sub_block_mv(candidate_mi, 1, col, alt_block);

RogerZhou's avatar
RogerZhou committed
228
229
230
231
        for (ref = 0; ref < 2; ++ref) {
#if CONFIG_AMVR
          lower_mv_precision(&this_refmv[ref].as_mv, use_hp, is_integer);
#else
232
          lower_mv_precision(&this_refmv[ref].as_mv, use_hp);
RogerZhou's avatar
RogerZhou committed
233
234
#endif
        }
Jingning Han's avatar
Jingning Han committed
235
236
237
238
239
        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;

Yaowu Xu's avatar
Yaowu Xu committed
240
        if (index < *refmv_count) ref_mv_stack[index].weight += len;
Jingning Han's avatar
Jingning Han committed
241
242
243
244
245

        // Add a new item to the list.
        if (index == *refmv_count) {
          ref_mv_stack[index].this_mv = this_refmv[0];
          ref_mv_stack[index].comp_mv = this_refmv[1];
246
247
248
249
250
251
          ref_mv_stack[index].pred_diff[0] = av1_get_pred_diff_ctx(
              get_sub_block_pred_mv(candidate_mi, 0, col, block),
              this_refmv[0]);
          ref_mv_stack[index].pred_diff[0] = av1_get_pred_diff_ctx(
              get_sub_block_pred_mv(candidate_mi, 1, col, block),
              this_refmv[1]);
Yaowu Xu's avatar
Yaowu Xu committed
252
          ref_mv_stack[index].weight = len;
Jingning Han's avatar
Jingning Han committed
253
254
          ++(*refmv_count);

255
          if (candidate->mode == NEW_NEWMV) ++newmv_count;
Jingning Han's avatar
Jingning Han committed
256
257
258
259
260
261
262
        }
      }
    }
  }
  return newmv_count;
}

Yaowu Xu's avatar
Yaowu Xu committed
263
static uint8_t scan_row_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
Yunqing Wang's avatar
Yunqing Wang committed
264
                             int mi_row, int mi_col, int block,
clang-format's avatar
clang-format committed
265
                             const MV_REFERENCE_FRAME rf[2], int row_offset,
266
                             CANDIDATE_MV *ref_mv_stack, uint8_t *refmv_count,
267
268
269
#if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
                             int_mv *gm_mv_candidates,
#endif  // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
270
                             int max_row_offset, int *processed_rows) {
Yunqing Wang's avatar
Yunqing Wang committed
271
  const int end_mi = AOMMIN(xd->n8_w, cm->mi_cols - mi_col);
272
273
  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
274
275
  int i;
  uint8_t newmv_count = 0;
276
  int col_offset = 0;
277
#if CONFIG_CB4X4
278
  const int shift = 0;
279
  // TODO(jingning): Revisit this part after cb4x4 is stable.
280
281
  if (abs(row_offset) > 1) {
    col_offset = 1;
282
    if (mi_col & 0x01 && xd->n8_w < n8_w_8) --col_offset;
283
  }
Yunqing Wang's avatar
Yunqing Wang committed
284
  const int use_step_16 = (xd->n8_w >= 16);
285
#else
286
  const int shift = 1;
Yunqing Wang's avatar
Yunqing Wang committed
287
  const int use_step_16 = (xd->n8_w >= 8);
288
#endif
Yunqing Wang's avatar
Yunqing Wang committed
289
  MODE_INFO **const candidate_mi0 = xd->mi + row_offset * xd->mi_stride;
Jingning Han's avatar
Jingning Han committed
290

Yunqing Wang's avatar
Yunqing Wang committed
291
292
293
  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;
294
295
296
    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
297
298
299
300
    if (use_step_16)
      len = AOMMAX(n8_w_16, len);
    else if (abs(row_offset) > 1)
      len = AOMMAX(len, n8_w_8);
301
302
303
304
305
306
307
308
309
310
311

    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;
    }

RogerZhou's avatar
RogerZhou committed
312
313
314
#if CONFIG_AMVR
    newmv_count += add_ref_mv_candidate(
        candidate_mi, candidate, rf, refmv_count, ref_mv_stack,
315
316
317
318
        cm->allow_high_precision_mv, len, block,
#if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
        gm_mv_candidates, cm->global_motion,
#endif  // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
319
320
321
        col_offset + i, weight, cm->cur_frame_mv_precision_level,
        xd->mi[0]->mbmi.sb_type, mi_row, mi_col, xd->plane[0].subsampling_x,
        xd->plane[0].subsampling_y);
RogerZhou's avatar
RogerZhou committed
322
#else
Yunqing Wang's avatar
Yunqing Wang committed
323
324
325
    newmv_count += add_ref_mv_candidate(
        candidate_mi, candidate, rf, refmv_count, ref_mv_stack,
        cm->allow_high_precision_mv, len, block,
326
#if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
327
        gm_mv_candidates, cm->global_motion,
328
#endif  // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
329
330
        col_offset + i, weight, xd->mi[0]->mbmi.sb_type, mi_row, mi_col,
        xd->plane[0].subsampling_x, xd->plane[0].subsampling_y);
RogerZhou's avatar
RogerZhou committed
331
#endif
332

Yunqing Wang's avatar
Yunqing Wang committed
333
    i += len;
334
  }
335
336

  return newmv_count;
337
338
}

Yaowu Xu's avatar
Yaowu Xu committed
339
static uint8_t scan_col_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
Yunqing Wang's avatar
Yunqing Wang committed
340
                             int mi_row, int mi_col, int block,
clang-format's avatar
clang-format committed
341
                             const MV_REFERENCE_FRAME rf[2], int col_offset,
342
                             CANDIDATE_MV *ref_mv_stack, uint8_t *refmv_count,
343
344
345
#if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
                             int_mv *gm_mv_candidates,
#endif  // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
346
                             int max_col_offset, int *processed_cols) {
Yunqing Wang's avatar
Yunqing Wang committed
347
  const int end_mi = AOMMIN(xd->n8_h, cm->mi_rows - mi_row);
348
349
  const int n8_h_8 = mi_size_high[BLOCK_8X8];
  const int n8_h_16 = mi_size_high[BLOCK_16X16];
350
  int i;
351
  uint8_t newmv_count = 0;
352
  int row_offset = 0;
353
#if CONFIG_CB4X4
354
  const int shift = 0;
355
356
  if (abs(col_offset) > 1) {
    row_offset = 1;
357
    if (mi_row & 0x01 && xd->n8_h < n8_h_8) --row_offset;
358
  }
Yunqing Wang's avatar
Yunqing Wang committed
359
  const int use_step_16 = (xd->n8_h >= 16);
360
#else
361
  const int shift = 1;
Yunqing Wang's avatar
Yunqing Wang committed
362
  const int use_step_16 = (xd->n8_h >= 8);
363
#endif
364

Yunqing Wang's avatar
Yunqing Wang committed
365
366
367
368
  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;
369
370
371
    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
372
373
374
375
    if (use_step_16)
      len = AOMMAX(n8_h_16, len);
    else if (abs(col_offset) > 1)
      len = AOMMAX(len, n8_h_8);
376
377
378
379
380
381
382
383
384
385
386

    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;
    }

RogerZhou's avatar
RogerZhou committed
387
388
389
#if CONFIG_AMVR
    newmv_count += add_ref_mv_candidate(
        candidate_mi, candidate, rf, refmv_count, ref_mv_stack,
390
391
392
393
        cm->allow_high_precision_mv, len, block,
#if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
        gm_mv_candidates, cm->global_motion,
#endif  // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
394
395
396
        col_offset, weight, cm->cur_frame_mv_precision_level,
        xd->mi[0]->mbmi.sb_type, mi_row, mi_col, xd->plane[0].subsampling_x,
        xd->plane[0].subsampling_y);
RogerZhou's avatar
RogerZhou committed
397
#else
Yunqing Wang's avatar
Yunqing Wang committed
398
399
400
    newmv_count += add_ref_mv_candidate(
        candidate_mi, candidate, rf, refmv_count, ref_mv_stack,
        cm->allow_high_precision_mv, len, block,
401
#if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
402
        gm_mv_candidates, cm->global_motion,
403
#endif  // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
404
405
        col_offset, weight, xd->mi[0]->mbmi.sb_type, mi_row, mi_col,
        xd->plane[0].subsampling_x, xd->plane[0].subsampling_y);
RogerZhou's avatar
RogerZhou committed
406
#endif
Yunqing Wang's avatar
Yunqing Wang committed
407
    i += len;
408
  }
409
410

  return newmv_count;
411
412
}

Yaowu Xu's avatar
Yaowu Xu committed
413
static uint8_t scan_blk_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
414
                             const int mi_row, const int mi_col, int block,
clang-format's avatar
clang-format committed
415
416
                             const MV_REFERENCE_FRAME rf[2], int row_offset,
                             int col_offset, CANDIDATE_MV *ref_mv_stack,
417
418
419
#if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
                             int_mv *gm_mv_candidates,
#endif  // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
420
                             uint8_t *refmv_count) {
421
422
  const TileInfo *const tile = &xd->tile;
  POSITION mi_pos;
423
  uint8_t newmv_count = 0;
424
425
426
427

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

428
  if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm, &mi_pos) &&
429
      *refmv_count < MAX_REF_MV_STACK_SIZE) {
430
431
432
    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;
433
    const int len = mi_size_wide[BLOCK_8X8];
434

RogerZhou's avatar
RogerZhou committed
435
436
437
#if CONFIG_AMVR
    newmv_count += add_ref_mv_candidate(
        candidate_mi, candidate, rf, refmv_count, ref_mv_stack,
438
439
440
441
        cm->allow_high_precision_mv, len, block,
#if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
        gm_mv_candidates, cm->global_motion,
#endif  // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
442
443
444
        mi_pos.col, 2, cm->cur_frame_mv_precision_level,
        xd->mi[0]->mbmi.sb_type, mi_row, mi_col, xd->plane[0].subsampling_x,
        xd->plane[0].subsampling_y);
RogerZhou's avatar
RogerZhou committed
445
#else
Yunqing Wang's avatar
Yunqing Wang committed
446
447
448
    newmv_count += add_ref_mv_candidate(
        candidate_mi, candidate, rf, refmv_count, ref_mv_stack,
        cm->allow_high_precision_mv, len, block,
449
#if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
450
        gm_mv_candidates, cm->global_motion,
451
#endif  // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
452
453
        mi_pos.col, 2, xd->mi[0]->mbmi.sb_type, mi_row, mi_col,
        xd->plane[0].subsampling_x, xd->plane[0].subsampling_y);
RogerZhou's avatar
RogerZhou committed
454
#endif
455
  }  // Analyze a single 8x8 block motion information.
Yaowu Xu's avatar
Yaowu Xu committed
456

457
  return newmv_count;
458
459
}

460
461
462
463
464
static int has_top_right(const AV1_COMMON *cm, const MACROBLOCKD *xd,
                         int mi_row, int mi_col, int bs) {
  const int sb_mi_size = mi_size_wide[cm->sb_size];
  const int mask_row = mi_row & (sb_mi_size - 1);
  const int mask_col = mi_col & (sb_mi_size - 1);
465

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

469
470
  // bs > 0 and bs is a power of 2
  assert(bs > 0 && !(bs & (bs - 1)));
471

472
473
474
  // 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
475
  while (bs < sb_mi_size) {
476
477
    if (mask_col & bs) {
      if ((mask_col & (2 * bs)) && (mask_row & (2 * bs))) {
478
        has_tr = 0;
479
480
481
482
483
484
485
        break;
      }
    } else {
      break;
    }
    bs <<= 1;
  }
486

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

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

497
498
499
500
#if CONFIG_EXT_PARTITION_TYPES && !CONFIG_EXT_PARTITION_TYPES_AB
  // 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
501
  if (xd->mi[0]->mbmi.partition == PARTITION_VERT_A)
502
    if ((mask_row & bs) && !(mask_col & bs)) has_tr = 0;
503
504
#endif  // CONFIG_EXT_PARTITION_TYPES

505
506
507
  return has_tr;
}

508
#if CONFIG_MFMV
509
510
511
512
513
514
515
516
517
static int check_sb_border(const AV1_COMMON *cm, const int mi_row,
                           const int mi_col, const int row_offset,
                           const int col_offset) {
  const int sb_mi_size = mi_size_wide[cm->sb_size];
  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)
518
519
520
521
522
    return 0;

  return 1;
}

523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
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,
                          int blk_col, uint8_t *refmv_count,
                          CANDIDATE_MV *ref_mv_stack, int16_t *mode_context) {
  (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];

#if CONFIG_MV_COMPRESS
  mi_pos.row = (mi_row & 0x01) ? blk_row : blk_row + 1;
  mi_pos.col = (mi_col & 0x01) ? blk_col : blk_col + 1;
#else
  mi_pos.row = blk_row;
  mi_pos.col = blk_col;
#endif

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

546
  const TPL_MV_REF *prev_frame_mvs =
Jingning Han's avatar
Jingning Han committed
547
      cm->tpl_mvs + ((mi_row + mi_pos.row) >> 1) * (cm->mi_stride >> 1) +
548
      ((mi_col + mi_pos.col) >> 1);
Jingning Han's avatar
Jingning Han committed
549

550
551
552
553
554
555
556
557
558
559
  MV_REFERENCE_FRAME rf[2];
  av1_set_ref_frame(rf, ref_frame);

  if (rf[1] == NONE_FRAME) {
    for (int i = 0; i < MFMV_STACK_SIZE; ++i) {
      if (prev_frame_mvs->mfmv[ref_frame - LAST_FRAME][i].as_int !=
          INVALID_MV) {
        int_mv this_refmv = prev_frame_mvs->mfmv[ref_frame - LAST_FRAME][i];
        lower_mv_precision(&this_refmv.as_mv, cm->allow_high_precision_mv);

560
561
562
563
        if (blk_row == 0 && blk_col == 0)
          if (abs(this_refmv.as_mv.row) >= 16 ||
              abs(this_refmv.as_mv.col) >= 16)
            mode_context[ref_frame] |= (1 << ZEROMV_OFFSET);
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595

        for (idx = 0; idx < *refmv_count; ++idx)
          if (abs(this_refmv.as_mv.row - ref_mv_stack[idx].this_mv.as_mv.row) <
                  4 &&
              abs(this_refmv.as_mv.col - ref_mv_stack[idx].this_mv.as_mv.col) <
                  4)
            break;

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

        if (idx == *refmv_count && *refmv_count < MAX_REF_MV_STACK_SIZE) {
          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;
          ++(*refmv_count);
        }

        ++coll_blk_count;
      }
    }
  } else {
    // Process compound inter mode
    for (int i = 0; i < MFMV_STACK_SIZE; ++i) {
      if (prev_frame_mvs->mfmv[rf[0] - LAST_FRAME][i].as_int != INVALID_MV &&
          prev_frame_mvs->mfmv[rf[1] - LAST_FRAME][i].as_int != INVALID_MV) {
        int_mv this_refmv = prev_frame_mvs->mfmv[rf[0] - LAST_FRAME][i];
        int_mv comp_refmv = prev_frame_mvs->mfmv[rf[1] - LAST_FRAME][i];
        lower_mv_precision(&this_refmv.as_mv, cm->allow_high_precision_mv);
        lower_mv_precision(&comp_refmv.as_mv, cm->allow_high_precision_mv);

596
597
598
599
600
601
        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)
            mode_context[ref_frame] |= (1 << ZEROMV_OFFSET);
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634

        for (idx = 0; idx < *refmv_count; ++idx)
          if (abs(this_refmv.as_mv.row - ref_mv_stack[idx].this_mv.as_mv.row) <
                  4 &&
              abs(this_refmv.as_mv.col - ref_mv_stack[idx].this_mv.as_mv.col) <
                  4 &&
              abs(comp_refmv.as_mv.row - ref_mv_stack[idx].comp_mv.as_mv.row) <
                  4 &&
              abs(comp_refmv.as_mv.col - ref_mv_stack[idx].comp_mv.as_mv.col) <
                  4)
            break;

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

        if (idx == *refmv_count && *refmv_count < MAX_REF_MV_STACK_SIZE) {
          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;
          ++(*refmv_count);
        }

        ++coll_blk_count;
      }
    }
  }

  return coll_blk_count;
}
#else
635
636
static int add_col_ref_mv(const AV1_COMMON *cm,
                          const MV_REF *prev_frame_mvs_base,
637
638
639
                          int prev_frame_mvs_stride, const MACROBLOCKD *xd,
                          int mi_row, int mi_col, MV_REFERENCE_FRAME ref_frame,
                          int blk_row, int blk_col, uint8_t *refmv_count,
640
                          CANDIDATE_MV *ref_mv_stack, int16_t *mode_context) {
641
642
#if CONFIG_TMV
  const MV_REF *prev_frame_mvs = prev_frame_mvs_base +
Yunqing Wang's avatar
Yunqing Wang committed
643
644
                                 (blk_row >> 1) * prev_frame_mvs_stride +
                                 (blk_col >> 1);
645
#else
646
  const MV_REF *prev_frame_mvs =
647
648
      prev_frame_mvs_base + blk_row * prev_frame_mvs_stride + blk_col;
#endif
649
650
651
  POSITION mi_pos;
  int ref, idx;
  int coll_blk_count = 0;
652
  const int weight_unit = mi_size_wide[BLOCK_8X8];
653

654
655
656
657
#if CONFIG_TMV
  mi_pos.row = blk_row;
  mi_pos.col = blk_col;
#else
658
659
660
661
#if CONFIG_MV_COMPRESS
  mi_pos.row = (mi_row & 0x01) ? blk_row : blk_row + 1;
  mi_pos.col = (mi_col & 0x01) ? blk_col : blk_col + 1;
#else
662
663
  mi_pos.row = blk_row;
  mi_pos.col = blk_col;
664
#endif
665
#endif  // CONFIG_TMV
666

667
  if (!is_inside(&xd->tile, mi_col, mi_row, cm->mi_rows, cm, &mi_pos))
668
    return coll_blk_count;
669
670
671
  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
672
673
674
675
#if CONFIG_AMVR
      lower_mv_precision(&this_refmv.as_mv, cm->allow_high_precision_mv,
                         cm->cur_frame_mv_precision_level);
#else
676
      lower_mv_precision(&this_refmv.as_mv, cm->allow_high_precision_mv);
RogerZhou's avatar
RogerZhou committed
677
#endif
678
679
680
681
682
683
684
685

#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)
          mode_context[ref_frame] |= (1 << ZEROMV_OFFSET);
      }
686
687
688
689

      for (idx = 0; idx < *refmv_count; ++idx)
        if (this_refmv.as_int == ref_mv_stack[idx].this_mv.as_int) break;

690
      if (idx < *refmv_count) ref_mv_stack[idx].weight += 2 * weight_unit;
691
692
693

      if (idx == *refmv_count && *refmv_count < MAX_REF_MV_STACK_SIZE) {
        ref_mv_stack[idx].this_mv.as_int = this_refmv.as_int;
694
695
        ref_mv_stack[idx].pred_diff[0] =
            av1_get_pred_diff_ctx(prev_frame_mvs->pred_mv[ref], this_refmv);
696
        ref_mv_stack[idx].weight = 2 * weight_unit;
697
698
699
700
701
702
703
704
705
        ++(*refmv_count);
      }

      ++coll_blk_count;
    }
  }

  return coll_blk_count;
}
706
#endif
707

Yaowu Xu's avatar
Yaowu Xu committed
708
static void setup_ref_mv_list(const AV1_COMMON *cm, const MACROBLOCKD *xd,
709
                              MV_REFERENCE_FRAME ref_frame,
clang-format's avatar
clang-format committed
710
                              uint8_t *refmv_count, CANDIDATE_MV *ref_mv_stack,
711
712
713
714
715
716
                              int_mv *mv_ref_list,
#if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
                              int_mv *gm_mv_candidates,
#endif  // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
                              int block, int mi_row, int mi_col,
                              int16_t *mode_context) {
717
  int idx, nearest_refmv_count = 0;
718
  uint8_t newmv_count = 0;
719
720
721
  CANDIDATE_MV tmp_mv;
  int len, nr_len;

722
723
724
725
726
727
728
729
730
731
732
#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;
733
734
735
#if CONFIG_MV_COMPRESS
  const MV_REF *const prev_frame_mvs_base =
      cm->use_prev_frame_mvs
736
737
          ? cm->prev_frame->mvs +
                (((mi_row >> 1) << 1) + 1) * prev_frame_mvs_stride +
738
739
740
                ((mi_col >> 1) << 1) + 1
          : NULL;
#else
clang-format's avatar
clang-format committed
741
742
  const MV_REF *const prev_frame_mvs_base =
      cm->use_prev_frame_mvs
743
          ? cm->prev_frame->mvs + mi_row * prev_frame_mvs_stride + mi_col
clang-format's avatar
clang-format committed
744
          : NULL;
745
#endif
746
#endif  // CONFIG_TMV
747

748
  const int bs = AOMMAX(xd->n8_w, xd->n8_h);
749
  const int has_tr = has_top_right(cm, xd, mi_row, mi_col, bs);
Jingning Han's avatar
Jingning Han committed
750
751
  MV_REFERENCE_FRAME rf[2];

Yunqing Wang's avatar
Yunqing Wang committed
752
  const TileInfo *const tile = &xd->tile;
753
  int max_row_offset = 0, max_col_offset = 0;
Yunqing Wang's avatar
Yunqing Wang committed
754
#if CONFIG_CB4X4
755
756
  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);
Yunqing Wang's avatar
Yunqing Wang committed
757
#endif
758
759
  int processed_rows = 0;
  int processed_cols = 0;
Yunqing Wang's avatar
Yunqing Wang committed
760
761
  int row_offset, col_offset;

762
  av1_set_ref_frame(rf, ref_frame);
763
  mode_context[ref_frame] = 0;
764
  *refmv_count = 0;
765

766
767
768
769
770
771
772
  // Find valid maximum row/col offset.
  if (xd->up_available) {
#if CONFIG_CB4X4
    max_row_offset = -(MVREF_ROWS << 1) + row_adj;
#else
    max_row_offset = -MVREF_ROWS;
#endif
Yunqing Wang's avatar
Yunqing Wang committed
773
774
775
    max_row_offset =
        find_valid_row_offset(tile, mi_row, cm->mi_rows, cm, max_row_offset);
  }
776
777
778
779
780
781
782

  if (xd->left_available) {
#if CONFIG_CB4X4
    max_col_offset = -(MVREF_COLS << 1) + col_adj;
#else
    max_col_offset = -MVREF_COLS;
#endif
Yunqing Wang's avatar
Yunqing Wang committed
783
784
    max_col_offset = find_valid_col_offset(tile, mi_col, max_col_offset);
  }
785

786
787
  // Scan the first above row mode info. row_offset = -1;
  if (abs(max_row_offset) >= 1)
Yunqing Wang's avatar
Yunqing Wang committed
788
789
    newmv_count += scan_row_mbmi(cm, xd, mi_row, mi_col, block, rf, -1,
                                 ref_mv_stack, refmv_count,
790
#if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
791
                                 gm_mv_candidates,
792
#endif  // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
793
                                 max_row_offset, &processed_rows);
794
795
  // Scan the first left column mode info. col_offset = -1;
  if (abs(max_col_offset) >= 1)
Yunqing Wang's avatar
Yunqing Wang committed
796
797
    newmv_count += scan_col_mbmi(cm, xd, mi_row, mi_col, block, rf, -1,
                                 ref_mv_stack, refmv_count,
798
#if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
799
                                 gm_mv_candidates,
800
#endif  // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
801
                                 max_col_offset, &processed_cols);
802
803
  // Check top-right boundary
  if (has_tr)
804
    newmv_count += scan_blk_mbmi(cm, xd, mi_row, mi_col, block, rf, -1,
805
806
807
808
809
                                 xd->n8_w, ref_mv_stack,
#if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
                                 gm_mv_candidates,
#endif  // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
                                 refmv_count);
810

811
  nearest_refmv_count = *refmv_count;
812

813
  for (idx = 0; idx < nearest_refmv_count; ++idx)
814
    ref_mv_stack[idx].weight += REF_CAT_LEVEL;
815
816
817
818

#if CONFIG_MFMV
  int blk_row, blk_col;
  int coll_blk_count = 0;
Jingning Han's avatar
Jingning Han committed
819
820
  int voffset = AOMMAX(mi_size_high[BLOCK_8X8], xd->n8_h);
  int hoffset = AOMMAX(mi_size_wide[BLOCK_8X8], xd->n8_w);
821
822

  int tpl_sample_pos[9][2] = {
Jingning Han's avatar
Jingning Han committed
823
824
825
    { -2, hoffset }, { 0, hoffset },  { voffset, hoffset },
    { voffset, 0 },  { voffset, -2 }, { voffset, -4 },
    { -4, hoffset }, { voffset, 4 },  { 2, hoffset + 4 },
826
827
828
  };
  int i;

Jingning Han's avatar
Jingning Han committed
829
830
  for (blk_row = 0; blk_row < xd->n8_h; blk_row += mi_size_high[BLOCK_8X8]) {
    for (blk_col = 0; blk_col < xd->n8_w; blk_col += mi_size_wide[BLOCK_8X8]) {
831
832
      // (TODO: yunqing) prev_frame_mvs_base is not used here, tpl_mvs is used.
      // Can be modified the same way.
833
834
835
836
      int is_available = add_tpl_ref_mv(
          cm, prev_frame_mvs_base, xd, mi_row, mi_col, ref_frame, blk_row,
          blk_col, refmv_count, ref_mv_stack, mode_context);
      if (blk_row == 0 && blk_col == 0) coll_blk_count = is_available;
837
838
839
840
841
842
843
844
    }
  }

  if (coll_blk_count == 0) mode_context[ref_frame] |= (1 << ZEROMV_OFFSET);

  for (i = 0; i < 9; ++i) {
    blk_row = tpl_sample_pos[i][0];
    blk_col = tpl_sample_pos[i][1];
845

846
    if (!check_sb_border(cm, mi_row, mi_col, blk_row, blk_col)) continue;
847
848
    // (TODO: yunqing) prev_frame_mvs_base is not used here, tpl_mvs is used.
    // Can be modified the same way.
849
850
851
852
853
    coll_blk_count += add_tpl_ref_mv(cm, prev_frame_mvs_base, xd, mi_row,
                                     mi_col, ref_frame, blk_row, blk_col,
                                     refmv_count, ref_mv_stack, mode_context);
  }
#else
854
#if CONFIG_TEMPMV_SIGNALING
855
  if (cm->use_prev_frame_mvs && rf[1] == NONE_FRAME)
856
#else
clang-format's avatar
clang-format committed
857
  if (prev_frame_mvs_base && cm->show_frame && cm->last_show_frame &&
858
      rf[1] == NONE_FRAME)
859
#endif
860
  {
861
    int blk_row, blk_col;
862
    int coll_blk_count = 0;
863
864
865
866
867
#if CONFIG_CB4X4
    const int mi_step = (xd->n8_w == 1 || xd->n8_h == 1)
                            ? mi_size_wide[BLOCK_8X8]
                            : mi_size_wide[BLOCK_16X16];
#else
868
    const int mi_step = mi_size_wide[BLOCK_16X16];
869
#endif
870
871

#if CONFIG_TPL_MV
872
873
    // Modified sample positions to be consistent with frame_mvs
    // spatial resolution.
874
875
876
877
878
879
880
881
    int tpl_sample_pos[5][2] = { { -1, xd->n8_w },
                                 { 0, xd->n8_w },
                                 { xd->n8_h, xd->n8_w },
                                 { xd->n8_h, 0 },
                                 { xd->n8_h, -1 } };
    int i;
#endif

882
883
    for (blk_row = 0; blk_row < xd->n8_h; blk_row += mi_step) {
      for (blk_col = 0; blk_col < xd->n8_w; blk_col += mi_step) {
884
885
886
887
888
889
890
891
892
893
894
#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
895
896
897
898
899
#if CONFIG_OPT_REF_MV
        if (blk_row == 0 && blk_col == 0) coll_blk_count = is_available;
#else
        coll_blk_count += is_available;
#endif
900
901
      }
    }
902
903
904
905
906

#if CONFIG_TPL_MV
    for (i = 0; i < 5; ++i) {
      blk_row = tpl_sample_pos[i][0];
      blk_col = tpl_sample_pos[i][1];
907
908
909
910
911
912
913
914
915
#if CONFIG_TMV
      coll_blk_count += 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
      coll_blk_count += 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
916
917
918
    }
#endif

919
920
    if (coll_blk_count == 0) mode_context[ref_frame] |= (1 << ZEROMV_OFFSET);
  } else {
921
    mode_context[ref_frame] |= (1 << ZEROMV_OFFSET);
922
  }
923
#endif
924

925
  // Scan the second outer area.
Deng's avatar
Deng committed
926
  scan_blk_mbmi(cm, xd, mi_row, mi_col, block, rf, -1, -1, ref_mv_stack,
927
928
929
#if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
                gm_mv_candidates,
#endif  // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
Deng's avatar
Deng committed
930
                refmv_count);
Yunqing Wang's avatar
Yunqing Wang committed
931
932
  for (idx = 2; idx <= MVREF_ROWS; ++idx) {
#if CONFIG_CB4X4
933
934
    row_offset = -(idx << 1) + 1 + row_adj;
    col_offset = -(idx << 1) + 1 + col_adj;
Yunqing Wang's avatar
Yunqing Wang committed
935
#else
936
937
    row_offset = -idx;
    col_offset = -idx;
Yunqing Wang's avatar
Yunqing Wang committed
938
939
#endif

940
941
    if (abs(row_offset) <= abs(max_row_offset) &&
        abs(row_offset) > processed_rows)
Yunqing Wang's avatar
Yunqing Wang committed
942
      scan_row_mbmi(cm, xd, mi_row, mi_col, block, rf, row_offset, ref_mv_stack,
943
944
945
946
947
                    refmv_count,
#if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
                    gm_mv_candidates,
#endif  // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
                    max_row_offset, &processed_rows);
948
949
950

    if (abs(col_offset) <= abs(max_col_offset) &&
        abs(col_offset) > processed_cols)
Yunqing Wang's avatar
Yunqing Wang committed
951
      scan_col_mbmi(cm, xd, mi_row, mi_col, block, rf, col_offset, ref_mv_stack,
952
953
954
955
956
                    refmv_count,
#if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
                    gm_mv_candidates,
#endif  // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
                    max_col_offset, &processed_cols);
Yunqing Wang's avatar
Yunqing Wang committed
957
958
959
  }

#if CONFIG_CB4X4
960
  col_offset = -(MVREF_COLS << 1) + 1 + col_adj;
Yunqing Wang's avatar
Yunqing Wang committed
961
#else
962
  col_offset = -MVREF_COLS;
Yunqing Wang's avatar
Yunqing Wang committed
963
#endif
964
965
  if (abs(col_offset) <= abs(max_col_offset) &&
      abs(col_offset) > processed_cols)
Yunqing Wang's avatar
Yunqing Wang committed
966
    scan_col_mbmi(cm, xd, mi_row, mi_col, block, rf, col_offset, ref_mv_stack,
967
968
969
970
971
                  refmv_count,
#if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
                  gm_mv_candidates,
#endif  // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
                  max_col_offset, &processed_cols);
972

973
  switch (nearest_refmv_count) {
974
975
    case 0: mode_context[ref_frame] |= 0;
#if !CONFIG_OPT_REF_MV
clang-format's avatar
clang-format committed
976
      if (*refmv_count >= 1) mode_context[ref_frame] |= 1;
977
978
979
980
      if (*refmv_count == 1)
        mode_context[ref_frame] |= (1 << REFMV_OFFSET);
      else if (*refmv_count >= 2)
        mode_context[ref_frame] |= (2 << REFMV_OFFSET);
981
#endif
982
      break;
983
984
985
986
    case 1: mode_context[ref_frame] |= (newmv_count > 0) ? 2 : 3;
#if CONFIG_OPT_REF_MV
      mode_context[ref_frame] |= (3 << REFMV_OFFSET);
#else
987
988
989
990
      if (*refmv_count == 1)
        mode_context[ref_frame] |= (3 << REFMV_OFFSET);
      else if (*refmv_count >= 2)
        mode_context[ref_frame] |= (4 << REFMV_OFFSET);
991
#endif
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
      break;

    case 2:
    default:
      if (newmv_count >= 2)
        mode_context[ref_frame] |= 4;
      else if (newmv_count == 1)
        mode_context[ref_frame] |= 5;
      else
        mode_context[ref_frame] |= 6;

      mode_context[ref_frame] |= (5 << REFMV_OFFSET);
      break;
  }

1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
  // Rank the likelihood and assign nearest and near mvs.
  len = nearest_refmv_count;
  while (len > 0) {
    nr_len = 0;
    for (idx =