mvref_common.c 84.1 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
23
24
25
26
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
53
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) {
#if CONFIG_TMV
  const int frame_mvs_stride = ROUND_POWER_OF_TWO(cm->mi_cols, 1);
  MV_REF *frame_mvs = cm->cur_frame->mvs +
                      ((mi_row & 0xfffe) >> 1) * frame_mvs_stride +
                      ((mi_col & 0xfffe) >> 1);
  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;
    }
  }
}

54
55
56
57
58
59
60
61
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
    int col, int weight
RogerZhou's avatar
RogerZhou committed
62
#if CONFIG_AMVR
63
64
    ,
    int is_integer
RogerZhou's avatar
RogerZhou committed
65
#endif
66
    ) {
Jingning Han's avatar
Jingning Han committed
67
68
  int index = 0, ref;
  int newmv_count = 0;
69
70
71
72
73
#if CONFIG_CB4X4
  const int unify_bsize = 1;
#else
  const int unify_bsize = 0;
#endif
74
  assert(weight % 2 == 0);
Jingning Han's avatar
Jingning Han committed
75

Emil Keyder's avatar
Emil Keyder committed
76
  if (rf[1] == NONE_FRAME) {
Jingning Han's avatar
Jingning Han committed
77
78
79
    // single reference frame
    for (ref = 0; ref < 2; ++ref) {
      if (candidate->ref_frame[ref] == rf[0]) {
80
81
82
83
84
85
86
        int_mv this_refmv;
#if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
        if (is_global_mv_block(candidate_mi, block, gm_params[rf[0]].wmtype))
          this_refmv = gm_mv_candidates[0];
        else
#endif  // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
          this_refmv = get_sub_block_mv(candidate_mi, ref, col, block);
RogerZhou's avatar
RogerZhou committed
87
88
89
#if CONFIG_AMVR
        lower_mv_precision(&this_refmv.as_mv, use_hp, is_integer);
#else
90
        lower_mv_precision(&this_refmv.as_mv, use_hp);
91
#endif  // CONFIG_AMVR
92

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

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

Jingning Han's avatar
Jingning Han committed
98
99
100
        // Add a new item to the list.
        if (index == *refmv_count) {
          ref_mv_stack[index].this_mv = this_refmv;
101
102
          ref_mv_stack[index].pred_diff[0] = av1_get_pred_diff_ctx(
              get_sub_block_pred_mv(candidate_mi, ref, col, block), this_refmv);
103
          ref_mv_stack[index].weight = weight * len;
Jingning Han's avatar
Jingning Han committed
104
          ++(*refmv_count);
105

106
          if (candidate->mode == NEWMV) ++newmv_count;
Jingning Han's avatar
Jingning Han committed
107
108
        }

109
110
        if (candidate_mi->mbmi.sb_type < BLOCK_8X8 && block >= 0 &&
            !unify_bsize) {
Jingning Han's avatar
Jingning Han committed
111
          int alt_block = 3 - block;
clang-format's avatar
clang-format committed
112
          this_refmv = get_sub_block_mv(candidate_mi, ref, col, alt_block);
RogerZhou's avatar
RogerZhou committed
113
114
115
#if CONFIG_AMVR
          lower_mv_precision(&this_refmv.as_mv, use_hp, is_integer);
#else
116
          lower_mv_precision(&this_refmv.as_mv, use_hp);
RogerZhou's avatar
RogerZhou committed
117
#endif
118
          for (index = 0; index < *refmv_count; ++index)
clang-format's avatar
clang-format committed
119
            if (ref_mv_stack[index].this_mv.as_int == this_refmv.as_int) break;
120

Yaowu Xu's avatar
Yaowu Xu committed
121
          if (index < *refmv_count) ref_mv_stack[index].weight += len;
122
123
124
125

          // Add a new item to the list.
          if (index == *refmv_count) {
            ref_mv_stack[index].this_mv = this_refmv;
126
127
128
            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
129
            ref_mv_stack[index].weight = len;
130
            ++(*refmv_count);
131

132
            if (candidate->mode == NEWMV) ++newmv_count;
133
134
135
          }
        }
      }
Jingning Han's avatar
Jingning Han committed
136
137
138
    }
  } else {
    // compound reference frame
clang-format's avatar
clang-format committed
139
    if (candidate->ref_frame[0] == rf[0] && candidate->ref_frame[1] == rf[1]) {
140
      int_mv this_refmv[2];
Jingning Han's avatar
Jingning Han committed
141

142
      for (ref = 0; ref < 2; ++ref) {
143
144
145
146
147
148
#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
149
150
151
#if CONFIG_AMVR
        lower_mv_precision(&this_refmv[ref].as_mv, use_hp, is_integer);
#else
152
        lower_mv_precision(&this_refmv[ref].as_mv, use_hp);
RogerZhou's avatar
RogerZhou committed
153
#endif
154
      }
155

Jingning Han's avatar
Jingning Han committed
156
157
158
159
160
      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;

161
      if (index < *refmv_count) ref_mv_stack[index].weight += weight * len;
Jingning Han's avatar
Jingning Han committed
162
163
164
165
166

      // 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];
167
168
169
170
        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]);
171
        ref_mv_stack[index].weight = weight * len;
Jingning Han's avatar
Jingning Han committed
172
173
        ++(*refmv_count);

174
        if (candidate->mode == NEW_NEWMV) ++newmv_count;
Jingning Han's avatar
Jingning Han committed
175
176
      }

177
178
      if (candidate_mi->mbmi.sb_type < BLOCK_8X8 && block >= 0 &&
          !unify_bsize) {
Jingning Han's avatar
Jingning Han committed
179
180
181
182
        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
183
184
185
186
        for (ref = 0; ref < 2; ++ref) {
#if CONFIG_AMVR
          lower_mv_precision(&this_refmv[ref].as_mv, use_hp, is_integer);
#else
187
          lower_mv_precision(&this_refmv[ref].as_mv, use_hp);
RogerZhou's avatar
RogerZhou committed
188
189
#endif
        }
Jingning Han's avatar
Jingning Han committed
190
191
192
193
194
        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
195
        if (index < *refmv_count) ref_mv_stack[index].weight += len;
Jingning Han's avatar
Jingning Han committed
196
197
198
199
200

        // 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];
201
202
203
204
205
206
          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
207
          ref_mv_stack[index].weight = len;
Jingning Han's avatar
Jingning Han committed
208
209
          ++(*refmv_count);

210
          if (candidate->mode == NEW_NEWMV) ++newmv_count;
Jingning Han's avatar
Jingning Han committed
211
212
213
214
215
216
217
        }
      }
    }
  }
  return newmv_count;
}

Yaowu Xu's avatar
Yaowu Xu committed
218
static uint8_t scan_row_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
Yunqing Wang's avatar
Yunqing Wang committed
219
                             const int mi_col, int block,
clang-format's avatar
clang-format committed
220
                             const MV_REFERENCE_FRAME rf[2], int row_offset,
221
                             CANDIDATE_MV *ref_mv_stack, uint8_t *refmv_count,
222
223
224
#if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
                             int_mv *gm_mv_candidates,
#endif  // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
225
                             int max_row_offset, int *processed_rows) {
Yunqing Wang's avatar
Yunqing Wang committed
226
  const int end_mi = AOMMIN(xd->n8_w, cm->mi_cols - mi_col);
227
228
  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
229
230
  int i;
  uint8_t newmv_count = 0;
231
  int col_offset = 0;
232
#if CONFIG_CB4X4
233
  const int shift = 0;
234
  // TODO(jingning): Revisit this part after cb4x4 is stable.
235
236
  if (abs(row_offset) > 1) {
    col_offset = 1;
237
    if (mi_col & 0x01 && xd->n8_w < n8_w_8) --col_offset;
238
  }
Yunqing Wang's avatar
Yunqing Wang committed
239
  const int use_step_16 = (xd->n8_w >= 16);
240
#else
241
  const int shift = 1;
Yunqing Wang's avatar
Yunqing Wang committed
242
  const int use_step_16 = (xd->n8_w >= 8);
243
#endif
Yunqing Wang's avatar
Yunqing Wang committed
244
  MODE_INFO **const candidate_mi0 = xd->mi + row_offset * xd->mi_stride;
Jingning Han's avatar
Jingning Han committed
245

Yunqing Wang's avatar
Yunqing Wang committed
246
247
248
  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;
249
250
251
    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
252
253
254
255
    if (use_step_16)
      len = AOMMAX(n8_w_16, len);
    else if (abs(row_offset) > 1)
      len = AOMMAX(len, n8_w_8);
256
257
258
259
260
261
262
263
264
265
266

    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
267
268
269
#if CONFIG_AMVR
    newmv_count += add_ref_mv_candidate(
        candidate_mi, candidate, rf, refmv_count, ref_mv_stack,
270
271
272
273
274
        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
        col_offset + i, weight, cm->cur_frame_mv_precision_level);
RogerZhou's avatar
RogerZhou committed
275
#else
276
277
278
279
280
281
282
    newmv_count += add_ref_mv_candidate(candidate_mi, candidate, rf,
                                        refmv_count, ref_mv_stack,
                                        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
                                        col_offset + i, weight);
RogerZhou's avatar
RogerZhou committed
283
#endif
284

Yunqing Wang's avatar
Yunqing Wang committed
285
    i += len;
286
  }
287
288

  return newmv_count;
289
290
}

Yaowu Xu's avatar
Yaowu Xu committed
291
static uint8_t scan_col_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
Yunqing Wang's avatar
Yunqing Wang committed
292
                             const int mi_row, int block,
clang-format's avatar
clang-format committed
293
                             const MV_REFERENCE_FRAME rf[2], int col_offset,
294
                             CANDIDATE_MV *ref_mv_stack, uint8_t *refmv_count,
295
296
297
#if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
                             int_mv *gm_mv_candidates,
#endif  // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
298
                             int max_col_offset, int *processed_cols) {
Yunqing Wang's avatar
Yunqing Wang committed
299
  const int end_mi = AOMMIN(xd->n8_h, cm->mi_rows - mi_row);
300
301
  const int n8_h_8 = mi_size_high[BLOCK_8X8];
  const int n8_h_16 = mi_size_high[BLOCK_16X16];
302
  int i;
303
  uint8_t newmv_count = 0;
304
  int row_offset = 0;
305
#if CONFIG_CB4X4
306
  const int shift = 0;
307
308
  if (abs(col_offset) > 1) {
    row_offset = 1;
309
    if (mi_row & 0x01 && xd->n8_h < n8_h_8) --row_offset;
310
  }
Yunqing Wang's avatar
Yunqing Wang committed
311
  const int use_step_16 = (xd->n8_h >= 16);
312
#else
313
  const int shift = 1;
Yunqing Wang's avatar
Yunqing Wang committed
314
  const int use_step_16 = (xd->n8_h >= 8);
315
#endif
316

Yunqing Wang's avatar
Yunqing Wang committed
317
318
319
320
  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;
321
322
323
    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
324
325
326
327
    if (use_step_16)
      len = AOMMAX(n8_h_16, len);
    else if (abs(col_offset) > 1)
      len = AOMMAX(len, n8_h_8);
328
329
330
331
332
333
334
335
336
337
338

    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
339
340
341
#if CONFIG_AMVR
    newmv_count += add_ref_mv_candidate(
        candidate_mi, candidate, rf, refmv_count, ref_mv_stack,
342
343
344
345
346
        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
        col_offset, weight, cm->cur_frame_mv_precision_level);
RogerZhou's avatar
RogerZhou committed
347
#else
348
349
350
351
352
353
354
    newmv_count += add_ref_mv_candidate(candidate_mi, candidate, rf,
                                        refmv_count, ref_mv_stack,
                                        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
                                        col_offset, weight);
RogerZhou's avatar
RogerZhou committed
355
#endif
Yunqing Wang's avatar
Yunqing Wang committed
356
    i += len;
357
  }
358
359

  return newmv_count;
360
361
}

Yaowu Xu's avatar
Yaowu Xu committed
362
static uint8_t scan_blk_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
363
                             const int mi_row, const int mi_col, int block,
clang-format's avatar
clang-format committed
364
365
                             const MV_REFERENCE_FRAME rf[2], int row_offset,
                             int col_offset, CANDIDATE_MV *ref_mv_stack,
366
367
368
#if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
                             int_mv *gm_mv_candidates,
#endif  // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
369
                             uint8_t *refmv_count) {
370
371
  const TileInfo *const tile = &xd->tile;
  POSITION mi_pos;
372
  uint8_t newmv_count = 0;
373
374
375
376

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

377
  if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm, &mi_pos) &&
378
      *refmv_count < MAX_REF_MV_STACK_SIZE) {
379
380
381
    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;
382
    const int len = mi_size_wide[BLOCK_8X8];
383

RogerZhou's avatar
RogerZhou committed
384
385
386
#if CONFIG_AMVR
    newmv_count += add_ref_mv_candidate(
        candidate_mi, candidate, rf, refmv_count, ref_mv_stack,
387
388
389
390
391
        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
        mi_pos.col, 2, cm->cur_frame_mv_precision_level);
RogerZhou's avatar
RogerZhou committed
392
#else
393
394
395
396
397
398
399
    newmv_count += add_ref_mv_candidate(candidate_mi, candidate, rf,
                                        refmv_count, ref_mv_stack,
                                        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
                                        mi_pos.col, 2);
RogerZhou's avatar
RogerZhou committed
400
#endif
401
  }  // Analyze a single 8x8 block motion information.
Yaowu Xu's avatar
Yaowu Xu committed
402

403
  return newmv_count;
404
405
}

406
407
408
409
410
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);
411

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

415
416
  // bs > 0 and bs is a power of 2
  assert(bs > 0 && !(bs & (bs - 1)));
417

418
419
420
  // 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
421
  while (bs < sb_mi_size) {
422
423
    if (mask_col & bs) {
      if ((mask_col & (2 * bs)) && (mask_row & (2 * bs))) {
424
        has_tr = 0;
425
426
427
428
429
430
431
        break;
      }
    } else {
      break;
    }
    bs <<= 1;
  }
432

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

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

443
444
445
446
#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
447
  if (xd->mi[0]->mbmi.partition == PARTITION_VERT_A)
448
    if ((mask_row & bs) && !(mask_col & bs)) has_tr = 0;
449
450
#endif  // CONFIG_EXT_PARTITION_TYPES

451
452
453
  return has_tr;
}

454
#if CONFIG_MFMV
455
456
457
458
459
460
461
462
463
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)
464
465
466
467
468
    return 0;

  return 1;
}

469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
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;

Jingning Han's avatar
Jingning Han committed
492
493
494
495
  const TPL_MV_REF *prev_frame_mvs = cm->cur_frame->tpl_mvs +
                                     (mi_row + mi_pos.row) * cm->mi_stride +
                                     (mi_col + mi_pos.col);

496
497
498
499
500
501
502
503
504
505
  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);

506
507
508
509
        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);
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541

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

542
543
544
545
546
547
        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);
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580

        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
581
582
static int add_col_ref_mv(const AV1_COMMON *cm,
                          const MV_REF *prev_frame_mvs_base,
583
584
585
                          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,
586
                          CANDIDATE_MV *ref_mv_stack, int16_t *mode_context) {
587
588
589
590
591
#if CONFIG_TMV
  const MV_REF *prev_frame_mvs = prev_frame_mvs_base +
                                 ((blk_row + 1) >> 1) * prev_frame_mvs_stride +
                                 ((blk_col + 1) >> 1);
#else
592
  const MV_REF *prev_frame_mvs =
593
594
      prev_frame_mvs_base + blk_row * prev_frame_mvs_stride + blk_col;
#endif
595
596
597
  POSITION mi_pos;
  int ref, idx;
  int coll_blk_count = 0;
598
  const int weight_unit = mi_size_wide[BLOCK_8X8];
599

600
601
602
603
#if CONFIG_TMV
  mi_pos.row = blk_row;
  mi_pos.col = blk_col;
#else
604
605
606
607
#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
608
609
  mi_pos.row = blk_row;
  mi_pos.col = blk_col;
610
#endif
611
#endif  // CONFIG_TMV
612

613
  if (!is_inside(&xd->tile, mi_col, mi_row, cm->mi_rows, cm, &mi_pos))
614
    return coll_blk_count;
615
616
617
  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
618
619
620
621
#if CONFIG_AMVR
      lower_mv_precision(&this_refmv.as_mv, cm->allow_high_precision_mv,
                         cm->cur_frame_mv_precision_level);
#else
622
      lower_mv_precision(&this_refmv.as_mv, cm->allow_high_precision_mv);
RogerZhou's avatar
RogerZhou committed
623
#endif
624
625
626
627
628
629
630
631

#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);
      }
632
633
634
635

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

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

      if (idx == *refmv_count && *refmv_count < MAX_REF_MV_STACK_SIZE) {
        ref_mv_stack[idx].this_mv.as_int = this_refmv.as_int;
640
641
        ref_mv_stack[idx].pred_diff[0] =
            av1_get_pred_diff_ctx(prev_frame_mvs->pred_mv[ref], this_refmv);
642
        ref_mv_stack[idx].weight = 2 * weight_unit;
643
644
645
646
647
648
649
650
651
        ++(*refmv_count);
      }

      ++coll_blk_count;
    }
  }

  return coll_blk_count;
}
652
#endif
653

Yaowu Xu's avatar
Yaowu Xu committed
654
static void setup_ref_mv_list(const AV1_COMMON *cm, const MACROBLOCKD *xd,
655
                              MV_REFERENCE_FRAME ref_frame,
clang-format's avatar
clang-format committed
656
                              uint8_t *refmv_count, CANDIDATE_MV *ref_mv_stack,
657
658
659
660
661
662
                              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) {
663
  int idx, nearest_refmv_count = 0;
664
  uint8_t newmv_count = 0;
665
666
667
  CANDIDATE_MV tmp_mv;
  int len, nr_len;

668
669
670
671
672
673
674
675
676
677
678
#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;
679
680
681
#if CONFIG_MV_COMPRESS
  const MV_REF *const prev_frame_mvs_base =
      cm->use_prev_frame_mvs
682
683
          ? cm->prev_frame->mvs +
                (((mi_row >> 1) << 1) + 1) * prev_frame_mvs_stride +
684
685
686
                ((mi_col >> 1) << 1) + 1
          : NULL;
#else
clang-format's avatar
clang-format committed
687
688
  const MV_REF *const prev_frame_mvs_base =
      cm->use_prev_frame_mvs
689
          ? cm->prev_frame->mvs + mi_row * prev_frame_mvs_stride + mi_col
clang-format's avatar
clang-format committed
690
          : NULL;
691
#endif
692
#endif  // CONFIG_TMV
693

694
  const int bs = AOMMAX(xd->n8_w, xd->n8_h);
695
  const int has_tr = has_top_right(cm, xd, mi_row, mi_col, bs);
Jingning Han's avatar
Jingning Han committed
696
697
  MV_REFERENCE_FRAME rf[2];

Yunqing Wang's avatar
Yunqing Wang committed
698
  const TileInfo *const tile = &xd->tile;
699
  int max_row_offset = 0, max_col_offset = 0;
Yunqing Wang's avatar
Yunqing Wang committed
700
#if CONFIG_CB4X4
701
702
  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
703
#endif
704
705
  int processed_rows = 0;
  int processed_cols = 0;
Yunqing Wang's avatar
Yunqing Wang committed
706
707
  int row_offset, col_offset;

708
  av1_set_ref_frame(rf, ref_frame);
709
  mode_context[ref_frame] = 0;
710
  *refmv_count = 0;
711

712
713
714
715
716
717
718
  // 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
719
720
721
    max_row_offset =
        find_valid_row_offset(tile, mi_row, cm->mi_rows, cm, max_row_offset);
  }
722
723
724
725
726
727
728

  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
729
730
    max_col_offset = find_valid_col_offset(tile, mi_col, max_col_offset);
  }
731

732
733
  // Scan the first above row mode info. row_offset = -1;
  if (abs(max_row_offset) >= 1)
734
735
736
737
738
739
    newmv_count +=
        scan_row_mbmi(cm, xd, mi_col, block, rf, -1, ref_mv_stack, 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);
740
741
  // Scan the first left column mode info. col_offset = -1;
  if (abs(max_col_offset) >= 1)
742
743
744
745
746
747
    newmv_count +=
        scan_col_mbmi(cm, xd, mi_row, block, rf, -1, ref_mv_stack, 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);
748
749
  // Check top-right boundary
  if (has_tr)
750
    newmv_count += scan_blk_mbmi(cm, xd, mi_row, mi_col, block, rf, -1,
751
752
753
754
755
                                 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);
756

757
  nearest_refmv_count = *refmv_count;
758

759
  for (idx = 0; idx < nearest_refmv_count; ++idx)
760
    ref_mv_stack[idx].weight += REF_CAT_LEVEL;
761
762
763
764

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

  int tpl_sample_pos[9][2] = {
Jingning Han's avatar
Jingning Han committed
769
770
771
    { -2, hoffset }, { 0, hoffset },  { voffset, hoffset },
    { voffset, 0 },  { voffset, -2 }, { voffset, -4 },
    { -4, hoffset }, { voffset, 4 },  { 2, hoffset + 4 },
772
773
774
  };
  int i;

Jingning Han's avatar
Jingning Han committed
775
776
  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]) {
777
778
      // (TODO: yunqing) prev_frame_mvs_base is not used here, tpl_mvs is used.
      // Can be modified the same way.
779
780
781
782
      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;
783
784
785
786
787
788
789
790
    }
  }

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

792
    if (!check_sb_border(cm, mi_row, mi_col, blk_row, blk_col)) continue;
793
794
    // (TODO: yunqing) prev_frame_mvs_base is not used here, tpl_mvs is used.
    // Can be modified the same way.
795
796
797
798
799
    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
800
#if CONFIG_TEMPMV_SIGNALING
801
  if (cm->use_prev_frame_mvs && rf[1] == NONE_FRAME)
802
#else
clang-format's avatar
clang-format committed
803
  if (prev_frame_mvs_base && cm->show_frame && cm->last_show_frame &&
804
      rf[1] == NONE_FRAME)
805
#endif
806
  {
807
    int blk_row, blk_col;
808
    int coll_blk_count = 0;
809
810
811
812
813
#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
814
    const int mi_step = mi_size_wide[BLOCK_16X16];
815
#endif
816
817

#if CONFIG_TPL_MV
818
819
    // Modified sample positions to be consistent with frame_mvs
    // spatial resolution.
820
821
822
823
824
825
826
827
    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

828
829
    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) {
830
831
832
833
834
835
836
837
838
839
840
#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
841
842
843
844
845
#if CONFIG_OPT_REF_MV
        if (blk_row == 0 && blk_col == 0) coll_blk_count = is_available;
#else
        coll_blk_count += is_available;
#endif
846
847
      }
    }
848
849
850
851
852

#if CONFIG_TPL_MV
    for (i = 0; i < 5; ++i) {
      blk_row = tpl_sample_pos[i][0];
      blk_col = tpl_sample_pos[i][1];
853
854
855
856
857
858
859
860
861
#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
862
863
864
    }
#endif

865
866
    if (coll_blk_count == 0) mode_context[ref_frame] |= (1 << ZEROMV_OFFSET);
  } else {
867
    mode_context[ref_frame] |= (1 << ZEROMV_OFFSET);
868
  }
869
#endif
870

871
  // Scan the second outer area.
Deng's avatar
Deng committed
872
  scan_blk_mbmi(cm, xd, mi_row, mi_col, block, rf, -1, -1, ref_mv_stack,
873
874
875
#if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
                gm_mv_candidates,
#endif  // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
Deng's avatar
Deng committed
876
                refmv_count);
Yunqing Wang's avatar
Yunqing Wang committed
877
878
  for (idx = 2; idx <= MVREF_ROWS; ++idx) {
#if CONFIG_CB4X4
879
880
    row_offset = -(idx << 1) + 1 + row_adj;
    col_offset = -(idx << 1) + 1 + col_adj;
Yunqing Wang's avatar
Yunqing Wang committed
881
#else
882
883
    row_offset = -idx;
    col_offset = -idx;
Yunqing Wang's avatar
Yunqing Wang committed
884
885
#endif

886
887
888
    if (abs(row_offset) <= abs(max_row_offset) &&
        abs(row_offset) > processed_rows)
      scan_row_mbmi(cm, xd, mi_col, block, rf, row_offset, ref_mv_stack,
889
890
891
892
893
                    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);
894
895
896
897

    if (abs(col_offset) <= abs(max_col_offset) &&
        abs(col_offset) > processed_cols)
      scan_col_mbmi(cm, xd, mi_row, block, rf, col_offset, ref_mv_stack,
898
899
900
901
902
                    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
903
904
905
  }

#if CONFIG_CB4X4
906
  col_offset = -(MVREF_COLS << 1) + 1 + col_adj;
Yunqing Wang's avatar
Yunqing Wang committed
907
#else
908
  col_offset = -MVREF_COLS;
Yunqing Wang's avatar
Yunqing Wang committed
909
#endif
910
911
912
  if (abs(col_offset) <= abs(max_col_offset) &&
      abs(col_offset) > processed_cols)
    scan_col_mbmi(cm, xd, mi_row, block, rf, col_offset, ref_mv_stack,
913
914
915
916
917
                  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);
918

919
  switch (nearest_refmv_count) {
920
921
    case 0: mode_context[ref_frame] |= 0;
#if !CONFIG_OPT_REF_MV
clang-format's avatar
clang-format committed
922
      if (*refmv_count >= 1) mode_context[ref_frame] |= 1;
923
924
925
926
      if (*refmv_count == 1)
        mode_context[ref_frame] |= (1 << REFMV_OFFSET);
      else if (*refmv_count >= 2)
        mode_context[ref_frame] |= (2 << REFMV_OFFSET);
927
#endif
928
      break;
929
930
931
932
    case 1: mode_context[ref_frame] |= (newmv_count > 0) ? 2 : 3;
#if CONFIG_OPT_REF_MV
      mode_context[ref_frame] |= (3 << REFMV_OFFSET);
#else
933
934
935
936
      if (*refmv_count == 1)
        mode_context[ref_frame] |= (3 << REFMV_OFFSET);
      else if (*refmv_count >= 2)
        mode_context[ref_frame] |= (4 << REFMV_OFFSET);
937
#endif
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
      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;
  }

953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
  // 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;
  }

968
  len = *refmv_count;
969
970
971
972
973
974
975
976
977
978
979
980
981
  while (len > nearest_refmv_count) {
    nr_len = nearest_refmv_count;
    for (idx = nearest_refmv_count + 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;
  }

Emil Keyder's avatar
Emil Keyder committed
982
  if (rf[1] > NONE_FRAME) {
983
    for (idx = 0; idx < *refmv_count; ++idx) {
984
985
986
987
      clamp_mv_ref(&ref_mv_stack[idx].this_mv.as_mv, xd->n8_w << MI_SIZE_LOG2,
                   xd->n8_h << MI_SIZE_LOG2, xd);
      clamp_mv_ref(&ref_mv_stack[idx].comp_mv.as_mv, xd->n8_w << MI_SIZE_LOG2,
                   xd->n8_h << MI_SIZE_LOG2, xd);
988
989
    }
  } else {
Yaowu Xu's avatar
Yaowu Xu committed
990
    for (idx = 0; idx < AOMMIN(MAX_MV_REF_CANDIDATES, *refmv_count); ++idx) {
991
      mv_ref_list[idx].as_int = ref_mv_stack[idx].this_mv.as_int;
992
993
      clamp_mv_ref(&mv_ref_list[idx].as_mv, xd->n8_w << MI_SIZE_LOG2,
                   xd->n8_h << MI_SIZE_LOG2, xd);
994
    }
995
996
997
  }
}

Jingning Han's avatar
Jingning Han committed
998
999
// This function searches the neighbourhood of a given MB/SB
// to try and find candidate reference vectors.
Yaowu Xu's avatar
Yaowu Xu committed
1000
static void find_mv_refs_idx(const AV1_COMMON *cm, const MACROBLOCKD *xd,
Jingning Han's avatar
Jingning Han committed
1001
                             MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame,
clang-format's avatar
clang-format committed
1002
1003
                             int_mv *mv_ref_list, int block, int mi_row,
                             int mi_col, find_mv_refs_sync sync,
1004
1005
                             void *const data, int16_t *mode_context,
                             int_mv zeromv) {
Jingning Han's avatar
Jingning Han committed
1006
  const int *ref_sign_bias = cm->ref_frame_sign_bias;
1007
  const int sb_mi_size = mi_size_wide[cm->sb_size];
Jingning Han's avatar
Jingning Han committed
1008
1009
1010
  int i, refmv_count = 0;
  int different_ref_found = 0;
  int context_counter = 0;
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022

#if CONFIG_TMV
  int tmi_row = mi_row & 0xfffe;
  int tmi_col = mi_col & 0xfffe;
  POSITION mi_pos = { 0, 0 };
  int inside = is_inside(&xd->tile, tmi_col, tmi_row, cm->mi_rows, cm, &mi_pos);
  const MV_REF *const prev_frame_mvs =
      cm->use_prev_frame_mvs && inside
          ? cm->prev_frame->mvs + (tmi_row >> 1) * ((cm->mi_cols + 1) >> 1) +
                (tmi_col >> 1)
          : NULL;
#else
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
#if CONFIG_MV_COMPRESS
  const TileInfo *const tile_ = &xd->tile;
  int mi_row_end = tile_->mi_row_end;
  int mi_col_end = tile_->mi_col_end;
  const MV_REF *const prev_frame_mvs =
      cm->use_prev_frame_mvs
          ? cm->prev_frame->mvs +
                AOMMIN(((mi_row >> 1) << 1) + 1 + (((xd->n8_h - 1) >> 1) << 1),
                       mi_row_end - 1) *
                    cm->mi_cols +
                AOMMIN(((mi_col >> 1) << 1) + 1 + (((xd->n8_w - 1) >> 1) << 1),
                       mi_col_end - 1)
          : NULL;
#else
clang-format's avatar
clang-format committed
1037
1038
1039
1040
  const MV_REF *const prev_frame_mvs =
      cm->use_prev_frame_mvs
          ? cm->prev_frame->mvs + mi_row * cm->mi_cols + mi_col
          : NULL;
1041
#endif
1042
1043
#endif  // CONFIG_TMV

1044
1045
#if CONFIG_INTRABC
  assert(IMPLIES(ref_frame == INTRA_FRAME, cm->use_prev_frame_mvs == 0));
1046
#endif
Jingning Han's avatar
Jingning Han committed
1047
  const TileInfo *const tile = &xd->tile;
1048
1049
1050
  const BLOCK_SIZE bsize = mi->mbmi.sb_type;
  const int bw = block_size_wide[AOMMAX(bsize, BLOCK_8X8)];
  const int bh = block_size_high[AOMMAX(bsize, BLOCK_8X8)];
Deng's avatar
Deng committed
1051
  POSITION mv_ref_search[MVREF_NEIGHBOURS];
1052
1053
  const int num_8x8_blocks_wide = num_8x8_blocks_wide_lookup[bsize];
  const int num_8x8_blocks_high = num_8x8_blocks_high_lookup[bsize];
Deng's avatar
Deng committed
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
  mv_ref_search[0].row = num_8x8_blocks_high - 1;
  mv_ref_search[0].col = -1;
  mv_ref_search[1].row = -1;
  mv_ref_search[1].col = num_8x8_blocks_wide - 1;
  mv_ref_search[2].row = -1;
  mv_ref_search[2].col = (num_8x8_blocks_wide - 1) >> 1;
  mv_ref_search[3].row = (num_8x8_blocks_high - 1) >> 1;
  mv_ref_search[3].col = -1;
  mv_ref_search[4].row = -1;
  mv_ref_search[4].col = -1;