mvref_common.c 86.6 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
547
548
549
  const TPL_MV_REF *prev_frame_mvs =
      cm->cur_frame->tpl_mvs +
      ((mi_row + mi_pos.row) >> 1) * (cm->mi_stride >> 1) +
      ((mi_col + mi_pos.col) >> 1);
Jingning Han's avatar
Jingning Han committed
550

551
552
553
554
555
556
557
558
559
560
  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);

561
562
563
564
        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);
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
596

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

597
598
599
600
601
602
        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);
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
635

        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
636
637
static int add_col_ref_mv(const AV1_COMMON *cm,
                          const MV_REF *prev_frame_mvs_base,
638
639
640
                          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,
641
                          CANDIDATE_MV *ref_mv_stack, int16_t *mode_context) {
642
643
#if CONFIG_TMV
  const MV_REF *prev_frame_mvs = prev_frame_mvs_base +
Yunqing Wang's avatar
Yunqing Wang committed
644
645
                                 (blk_row >> 1) * prev_frame_mvs_stride +
                                 (blk_col >> 1);
646
#else
647
  const MV_REF *prev_frame_mvs =
648
649
      prev_frame_mvs_base + blk_row * prev_frame_mvs_stride + blk_col;
#endif
650
651
652
  POSITION mi_pos;
  int ref, idx;
  int coll_blk_count = 0;
653
  const int weight_unit = mi_size_wide[BLOCK_8X8];
654

655
656
657
658
#if CONFIG_TMV
  mi_pos.row = blk_row;
  mi_pos.col = blk_col;
#else
659
660
661
662
#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
663
664
  mi_pos.row = blk_row;
  mi_pos.col = blk_col;
665
#endif
666
#endif  // CONFIG_TMV
667

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

#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);
      }
687
688
689
690

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

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

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

      ++coll_blk_count;
    }
  }

  return coll_blk_count;
}
707
#endif
708

Yaowu Xu's avatar
Yaowu Xu committed
709
static void setup_ref_mv_list(const AV1_COMMON *cm, const MACROBLOCKD *xd,
710
                              MV_REFERENCE_FRAME ref_frame,
clang-format's avatar
clang-format committed
711
                              uint8_t *refmv_count, CANDIDATE_MV *ref_mv_stack,
712
713
714
715
716
717
                              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) {
718
  int idx, nearest_refmv_count = 0;
719
  uint8_t newmv_count = 0;
720
721
722
  CANDIDATE_MV tmp_mv;
  int len, nr_len;

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

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

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

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

767
768
769
770
771
772
773
  // 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
774
775
776
    max_row_offset =
        find_valid_row_offset(tile, mi_row, cm->mi_rows, cm, max_row_offset);
  }
777
778
779
780
781
782
783

  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
784
785
    max_col_offset = find_valid_col_offset(tile, mi_col, max_col_offset);
  }
786

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

812
  nearest_refmv_count = *refmv_count;
813

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

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

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

Jingning Han's avatar
Jingning Han committed
830
831
  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]) {
832
833
      // (TODO: yunqing) prev_frame_mvs_base is not used here, tpl_mvs is used.
      // Can be modified the same way.
834
835
836
837
      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;
838
839
840
841
842
843
844
845
    }
  }

  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];
846

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

#if CONFIG_TPL_MV
873
874
    // Modified sample positions to be consistent with frame_mvs
    // spatial resolution.
875
876
877
878
879
880
881
882
    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

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

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

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

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

941
942
    if (abs(row_offset) <= abs(max_row_offset) &&
        abs(row_offset) > processed_rows)
Yunqing Wang's avatar
Yunqing Wang committed
943
      scan_row_mbmi(cm, xd, mi_row, mi_col, block, rf, row_offset, ref_mv_stack,
944
945
946
947
948
                    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);
949
950
951

    if (abs(col_offset) <= abs(max_col_offset) &&
        abs(col_offset) > processed_cols)
Yunqing Wang's avatar
Yunqing Wang committed
952
      scan_col_mbmi(cm, xd, mi_row, mi_col, block, rf, col_offset, ref_mv_stack,
953
954
955
956
957
                    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
958
959
960
  }

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

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

1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
  // Rank the likelihood and assign nearest and near mvs.
  len = nearest_refmv_count;
  while (len > 0) {
    nr_len = 0;
    for (idx = 1; idx < len; ++idx) {
      if (ref_mv_stack[idx - 1].weight < ref_mv_stack[idx].weight) {
        tmp_mv = ref_mv_stack[idx - 1];
        ref_mv_stack[idx - 1] = ref_mv_stack[idx];
        ref_mv_stack[idx] = tmp_mv;
        nr_len = idx;
      }
    }
    len = nr_len;
  }