mvref_common.c 70.3 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
#include "av1/common/warped_motion.h"
Jingning Han's avatar
Jingning Han committed
14

15
16
#define USE_CUR_GM_REFMV 1

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

      for (int idx = 0; idx < 2; ++idx) {
        MV_REFERENCE_FRAME ref_frame = mi->mbmi.ref_frame[idx];
        if (ref_frame > INTRA_FRAME) {
          int8_t ref_idx = cm->ref_frame_side[ref_frame];
          if (ref_idx < 0) continue;
          mv->ref_frame[ref_idx] = ref_frame;
          mv->mv[ref_idx].as_int = mi->mbmi.mv[idx].as_int;
        }
      }
#else
53
54
55
56
      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;
57
#endif
58
59
60
      // (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;
61
      mv++;
62
    }
63
    frame_mvs += frame_mvs_stride;
64
65
66
  }
}

67
68
69
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,
70
    uint8_t *ref_match_count, CANDIDATE_MV *ref_mv_stack, const int use_hp,
Luc Trudeau's avatar
Luc Trudeau committed
71
    int len,
72
#if USE_CUR_GM_REFMV
73
    int_mv *gm_mv_candidates, const WarpedMotionParams *gm_params,
74
#endif  // USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
75
    int col, int weight
RogerZhou's avatar
RogerZhou committed
76
#if CONFIG_AMVR
Yunqing Wang's avatar
Yunqing Wang committed
77
78
    ,
    int is_integer
RogerZhou's avatar
RogerZhou committed
79
#endif
Yunqing Wang's avatar
Yunqing Wang committed
80
    ) {
81
82
83
#if CONFIG_INTRABC
  if (!is_inter_block(candidate)) return 0;
#endif  // CONFIG_INTRABC
Jingning Han's avatar
Jingning Han committed
84
85
  int index = 0, ref;
  int newmv_count = 0;
86
  assert(weight % 2 == 0);
87
  (void)ref_match_count;
Jingning Han's avatar
Jingning Han committed
88

Emil Keyder's avatar
Emil Keyder committed
89
  if (rf[1] == NONE_FRAME) {
Jingning Han's avatar
Jingning Han committed
90
91
92
    // single reference frame
    for (ref = 0; ref < 2; ++ref) {
      if (candidate->ref_frame[ref] == rf[0]) {
93
        int_mv this_refmv;
94
#if USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
95
96
97
        if (is_global_mv_block(candidate_mi, gm_params[rf[0]].wmtype))
          this_refmv = gm_mv_candidates[0];
        else
98
#endif  // USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
99
          this_refmv = get_sub_block_mv(candidate_mi, ref, col);
RogerZhou's avatar
RogerZhou committed
100
#if CONFIG_AMVR
Yunqing Wang's avatar
Yunqing Wang committed
101
        lower_mv_precision(&this_refmv.as_mv, use_hp, is_integer);
RogerZhou's avatar
RogerZhou committed
102
#else
103
        lower_mv_precision(&this_refmv.as_mv, use_hp);
104
#endif  // CONFIG_AMVR
105

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

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

Jingning Han's avatar
Jingning Han committed
111
        // Add a new item to the list.
112
        if (index == *refmv_count && *refmv_count < MAX_REF_MV_STACK_SIZE) {
Jingning Han's avatar
Jingning Han committed
113
          ref_mv_stack[index].this_mv = this_refmv;
114
          ref_mv_stack[index].pred_diff[0] = av1_get_pred_diff_ctx(
Luc Trudeau's avatar
Luc Trudeau committed
115
              get_sub_block_pred_mv(candidate_mi, ref, col), this_refmv);
116
          ref_mv_stack[index].weight = weight * len;
Jingning Han's avatar
Jingning Han committed
117
          ++(*refmv_count);
118

119
#if !CONFIG_OPT_REF_MV
120
          if (candidate->mode == NEWMV) ++newmv_count;
121
#endif
Jingning Han's avatar
Jingning Han committed
122
        }
123
124
125
126
#if CONFIG_OPT_REF_MV
        if (candidate->mode == NEWMV) ++newmv_count;
        ++*ref_match_count;
#endif
127
      }
Jingning Han's avatar
Jingning Han committed
128
129
130
    }
  } else {
    // compound reference frame
clang-format's avatar
clang-format committed
131
    if (candidate->ref_frame[0] == rf[0] && candidate->ref_frame[1] == rf[1]) {
132
      int_mv this_refmv[2];
Jingning Han's avatar
Jingning Han committed
133

134
      for (ref = 0; ref < 2; ++ref) {
135
#if USE_CUR_GM_REFMV
Luc Trudeau's avatar
Luc Trudeau committed
136
        if (is_global_mv_block(candidate_mi, gm_params[rf[ref]].wmtype))
137
138
          this_refmv[ref] = gm_mv_candidates[ref];
        else
139
#endif  // USE_CUR_GM_REFMV
Luc Trudeau's avatar
Luc Trudeau committed
140
          this_refmv[ref] = get_sub_block_mv(candidate_mi, ref, col);
RogerZhou's avatar
RogerZhou committed
141
142
143
#if CONFIG_AMVR
        lower_mv_precision(&this_refmv[ref].as_mv, use_hp, is_integer);
#else
144
        lower_mv_precision(&this_refmv[ref].as_mv, use_hp);
RogerZhou's avatar
RogerZhou committed
145
#endif
146
      }
147

Jingning Han's avatar
Jingning Han committed
148
149
150
151
152
      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;

153
      if (index < *refmv_count) ref_mv_stack[index].weight += weight * len;
Jingning Han's avatar
Jingning Han committed
154
155

      // Add a new item to the list.
156
      if (index == *refmv_count && *refmv_count < MAX_REF_MV_STACK_SIZE) {
Jingning Han's avatar
Jingning Han committed
157
158
        ref_mv_stack[index].this_mv = this_refmv[0];
        ref_mv_stack[index].comp_mv = this_refmv[1];
159
        ref_mv_stack[index].pred_diff[0] = av1_get_pred_diff_ctx(
Luc Trudeau's avatar
Luc Trudeau committed
160
            get_sub_block_pred_mv(candidate_mi, 0, col), this_refmv[0]);
161
        ref_mv_stack[index].pred_diff[1] = av1_get_pred_diff_ctx(
Luc Trudeau's avatar
Luc Trudeau committed
162
            get_sub_block_pred_mv(candidate_mi, 1, col), this_refmv[1]);
163
        ref_mv_stack[index].weight = weight * len;
Jingning Han's avatar
Jingning Han committed
164
165
        ++(*refmv_count);

166
#if !CONFIG_OPT_REF_MV
167
        if (candidate->mode == NEW_NEWMV) ++newmv_count;
168
#endif
Jingning Han's avatar
Jingning Han committed
169
      }
170
171
172
173
#if CONFIG_OPT_REF_MV
      if (candidate->mode == NEW_NEWMV) ++newmv_count;
      ++*ref_match_count;
#endif
Jingning Han's avatar
Jingning Han committed
174
175
176
177
178
    }
  }
  return newmv_count;
}

Yaowu Xu's avatar
Yaowu Xu committed
179
static uint8_t scan_row_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
Luc Trudeau's avatar
Luc Trudeau committed
180
                             int mi_row, int mi_col,
clang-format's avatar
clang-format committed
181
                             const MV_REFERENCE_FRAME rf[2], int row_offset,
182
                             CANDIDATE_MV *ref_mv_stack, uint8_t *refmv_count,
183
                             uint8_t *ref_match_count,
184
#if USE_CUR_GM_REFMV
185
                             int_mv *gm_mv_candidates,
186
#endif  // USE_CUR_GM_REFMV
187
                             int max_row_offset, int *processed_rows) {
Yunqing Wang's avatar
Yunqing Wang committed
188
  const int end_mi = AOMMIN(xd->n8_w, cm->mi_cols - mi_col);
189
190
  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
191
192
  int i;
  uint8_t newmv_count = 0;
193
  int col_offset = 0;
194
  const int shift = 0;
195
  // TODO(jingning): Revisit this part after cb4x4 is stable.
196
197
  if (abs(row_offset) > 1) {
    col_offset = 1;
198
    if (mi_col & 0x01 && xd->n8_w < n8_w_8) --col_offset;
199
  }
Yunqing Wang's avatar
Yunqing Wang committed
200
201
  const int use_step_16 = (xd->n8_w >= 16);
  MODE_INFO **const candidate_mi0 = xd->mi + row_offset * xd->mi_stride;
Yunqing Wang's avatar
Yunqing Wang committed
202
  (void)mi_row;
Jingning Han's avatar
Jingning Han committed
203

204
  for (i = 0; i < end_mi;) {
Yunqing Wang's avatar
Yunqing Wang committed
205
206
    const MODE_INFO *const candidate_mi = candidate_mi0[col_offset + i];
    const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
207
208
209
    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
210
211
212
213
    if (use_step_16)
      len = AOMMAX(n8_w_16, len);
    else if (abs(row_offset) > 1)
      len = AOMMAX(len, n8_w_8);
214
215
216
217
218
219
220
221
222
223
224

    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
225
226
#if CONFIG_AMVR
    newmv_count += add_ref_mv_candidate(
227
        candidate_mi, candidate, rf, refmv_count, ref_match_count, ref_mv_stack,
Luc Trudeau's avatar
Luc Trudeau committed
228
        cm->allow_high_precision_mv, len,
229
#if USE_CUR_GM_REFMV
230
        gm_mv_candidates, cm->global_motion,
231
#endif  // USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
232
        col_offset + i, weight, cm->cur_frame_force_integer_mv);
RogerZhou's avatar
RogerZhou committed
233
#else
Yunqing Wang's avatar
Yunqing Wang committed
234
    newmv_count += add_ref_mv_candidate(
235
        candidate_mi, candidate, rf, refmv_count, ref_match_count, ref_mv_stack,
Luc Trudeau's avatar
Luc Trudeau committed
236
        cm->allow_high_precision_mv, len,
237
#if USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
238
        gm_mv_candidates, cm->global_motion,
239
#endif  // USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
240
        col_offset + i, weight);
RogerZhou's avatar
RogerZhou committed
241
#endif
242

Yunqing Wang's avatar
Yunqing Wang committed
243
    i += len;
244
  }
245
246

  return newmv_count;
247
248
}

Yaowu Xu's avatar
Yaowu Xu committed
249
static uint8_t scan_col_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
Luc Trudeau's avatar
Luc Trudeau committed
250
                             int mi_row, int mi_col,
clang-format's avatar
clang-format committed
251
                             const MV_REFERENCE_FRAME rf[2], int col_offset,
252
                             CANDIDATE_MV *ref_mv_stack, uint8_t *refmv_count,
253
                             uint8_t *ref_match_count,
254
#if USE_CUR_GM_REFMV
255
                             int_mv *gm_mv_candidates,
256
#endif  // USE_CUR_GM_REFMV
257
                             int max_col_offset, int *processed_cols) {
Yunqing Wang's avatar
Yunqing Wang committed
258
  const int end_mi = AOMMIN(xd->n8_h, cm->mi_rows - mi_row);
259
260
  const int n8_h_8 = mi_size_high[BLOCK_8X8];
  const int n8_h_16 = mi_size_high[BLOCK_16X16];
261
  int i;
262
  uint8_t newmv_count = 0;
263
  int row_offset = 0;
264
  const int shift = 0;
265
266
  if (abs(col_offset) > 1) {
    row_offset = 1;
267
    if (mi_row & 0x01 && xd->n8_h < n8_h_8) --row_offset;
268
  }
Yunqing Wang's avatar
Yunqing Wang committed
269
  const int use_step_16 = (xd->n8_h >= 16);
Yunqing Wang's avatar
Yunqing Wang committed
270
  (void)mi_col;
271

272
  for (i = 0; i < end_mi;) {
Yunqing Wang's avatar
Yunqing Wang committed
273
274
275
    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;
276
277
278
    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
279
280
281
282
    if (use_step_16)
      len = AOMMAX(n8_h_16, len);
    else if (abs(col_offset) > 1)
      len = AOMMAX(len, n8_h_8);
283
284
285
286
287
288
289
290
291
292
293

    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
294
295
#if CONFIG_AMVR
    newmv_count += add_ref_mv_candidate(
296
        candidate_mi, candidate, rf, refmv_count, ref_match_count, ref_mv_stack,
Luc Trudeau's avatar
Luc Trudeau committed
297
        cm->allow_high_precision_mv, len,
298
#if USE_CUR_GM_REFMV
299
        gm_mv_candidates, cm->global_motion,
300
#endif  // USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
301
        col_offset, weight, cm->cur_frame_force_integer_mv);
RogerZhou's avatar
RogerZhou committed
302
#else
Yunqing Wang's avatar
Yunqing Wang committed
303
    newmv_count += add_ref_mv_candidate(
304
        candidate_mi, candidate, rf, refmv_count, ref_match_count, ref_mv_stack,
Luc Trudeau's avatar
Luc Trudeau committed
305
        cm->allow_high_precision_mv, len,
306
#if USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
307
        gm_mv_candidates, cm->global_motion,
308
#endif  // USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
309
        col_offset, weight);
RogerZhou's avatar
RogerZhou committed
310
#endif
Yunqing Wang's avatar
Yunqing Wang committed
311
    i += len;
312
  }
313
314

  return newmv_count;
315
316
}

Yaowu Xu's avatar
Yaowu Xu committed
317
static uint8_t scan_blk_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
Luc Trudeau's avatar
Luc Trudeau committed
318
                             const int mi_row, const int mi_col,
clang-format's avatar
clang-format committed
319
320
                             const MV_REFERENCE_FRAME rf[2], int row_offset,
                             int col_offset, CANDIDATE_MV *ref_mv_stack,
321
                             uint8_t *ref_match_count,
322
#if USE_CUR_GM_REFMV
323
                             int_mv *gm_mv_candidates,
324
#endif  // USE_CUR_GM_REFMV
325
                             uint8_t *refmv_count) {
326
327
  const TileInfo *const tile = &xd->tile;
  POSITION mi_pos;
328
  uint8_t newmv_count = 0;
329
330
331
332

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

333
  if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm, &mi_pos)) {
334
335
336
    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;
337
    const int len = mi_size_wide[BLOCK_8X8];
338

RogerZhou's avatar
RogerZhou committed
339
340
#if CONFIG_AMVR
    newmv_count += add_ref_mv_candidate(
341
        candidate_mi, candidate, rf, refmv_count, ref_match_count, ref_mv_stack,
Luc Trudeau's avatar
Luc Trudeau committed
342
        cm->allow_high_precision_mv, len,
343
#if USE_CUR_GM_REFMV
344
        gm_mv_candidates, cm->global_motion,
345
#endif  // USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
346
        mi_pos.col, 2, cm->cur_frame_force_integer_mv);
RogerZhou's avatar
RogerZhou committed
347
#else
Yunqing Wang's avatar
Yunqing Wang committed
348
    newmv_count += add_ref_mv_candidate(
349
        candidate_mi, candidate, rf, refmv_count, ref_match_count, ref_mv_stack,
Luc Trudeau's avatar
Luc Trudeau committed
350
        cm->allow_high_precision_mv, len,
351
#if USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
352
        gm_mv_candidates, cm->global_motion,
353
#endif  // USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
354
        mi_pos.col, 2);
RogerZhou's avatar
RogerZhou committed
355
#endif
356
  }  // Analyze a single 8x8 block motion information.
Yaowu Xu's avatar
Yaowu Xu committed
357

358
  return newmv_count;
359
360
}

361
362
363
364
365
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);
366

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

370
371
  // bs > 0 and bs is a power of 2
  assert(bs > 0 && !(bs & (bs - 1)));
372

373
374
375
  // 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
376
  while (bs < sb_mi_size) {
377
378
    if (mask_col & bs) {
      if ((mask_col & (2 * bs)) && (mask_row & (2 * bs))) {
379
        has_tr = 0;
380
381
382
383
384
385
386
        break;
      }
    } else {
      break;
    }
    bs <<= 1;
  }
387

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

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

398
#if CONFIG_EXT_PARTITION_TYPES
399
400
401
  // 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
402
  if (xd->mi[0]->mbmi.partition == PARTITION_VERT_A)
403
    if ((mask_row & bs) && !(mask_col & bs)) has_tr = 0;
404
405
#endif  // CONFIG_EXT_PARTITION_TYPES

406
407
408
  return has_tr;
}

409
#if CONFIG_MFMV
410
411
412
413
414
415
416
417
418
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)
419
420
421
422
423
    return 0;

  return 1;
}

424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
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;

447
  const TPL_MV_REF *prev_frame_mvs =
Jingning Han's avatar
Jingning Han committed
448
      cm->tpl_mvs + ((mi_row + mi_pos.row) >> 1) * (cm->mi_stride >> 1) +
449
      ((mi_col + mi_pos.col) >> 1);
Jingning Han's avatar
Jingning Han committed
450

451
452
453
454
455
456
457
458
  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];
RogerZhou's avatar
RogerZhou committed
459
460
461
462
#if CONFIG_AMVR
        lower_mv_precision(&this_refmv.as_mv, cm->allow_high_precision_mv,
                           cm->cur_frame_force_integer_mv);
#else
463
        lower_mv_precision(&this_refmv.as_mv, cm->allow_high_precision_mv);
RogerZhou's avatar
RogerZhou committed
464
#endif
465

466
467
468
        if (blk_row == 0 && blk_col == 0)
          if (abs(this_refmv.as_mv.row) >= 16 ||
              abs(this_refmv.as_mv.col) >= 16)
Sarah Parker's avatar
Sarah Parker committed
469
            mode_context[ref_frame] |= (1 << GLOBALMV_OFFSET);
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498

        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];
RogerZhou's avatar
RogerZhou committed
499
500
501
502
503
504
#if CONFIG_AMVR
        lower_mv_precision(&this_refmv.as_mv, cm->allow_high_precision_mv,
                           cm->cur_frame_force_integer_mv);
        lower_mv_precision(&comp_refmv.as_mv, cm->allow_high_precision_mv,
                           cm->cur_frame_force_integer_mv);
#else
505
506
        lower_mv_precision(&this_refmv.as_mv, cm->allow_high_precision_mv);
        lower_mv_precision(&comp_refmv.as_mv, cm->allow_high_precision_mv);
RogerZhou's avatar
RogerZhou committed
507
#endif
508
509
510
511
512
        if (blk_row == 0 && blk_col == 0)
          if (abs(this_refmv.as_mv.row) >= 16 ||
              abs(this_refmv.as_mv.col) >= 16 ||
              abs(comp_refmv.as_mv.row) >= 16 ||
              abs(comp_refmv.as_mv.col) >= 16)
Sarah Parker's avatar
Sarah Parker committed
513
            mode_context[ref_frame] |= (1 << GLOBALMV_OFFSET);
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
542
543
544
545
546

        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
547
548
static int add_col_ref_mv(const AV1_COMMON *cm,
                          const MV_REF *prev_frame_mvs_base,
549
550
551
                          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,
552
                          CANDIDATE_MV *ref_mv_stack, int16_t *mode_context) {
553
554
#if CONFIG_TMV
  const MV_REF *prev_frame_mvs = prev_frame_mvs_base +
Yunqing Wang's avatar
Yunqing Wang committed
555
556
                                 (blk_row >> 1) * prev_frame_mvs_stride +
                                 (blk_col >> 1);
557
#else
558
  const MV_REF *prev_frame_mvs =
559
560
      prev_frame_mvs_base + blk_row * prev_frame_mvs_stride + blk_col;
#endif
561
562
563
  POSITION mi_pos;
  int ref, idx;
  int coll_blk_count = 0;
564
  const int weight_unit = mi_size_wide[BLOCK_8X8];
565

566
567
568
569
#if CONFIG_TMV
  mi_pos.row = blk_row;
  mi_pos.col = blk_col;
#else
570
571
572
573
#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
574
575
  mi_pos.row = blk_row;
  mi_pos.col = blk_col;
576
#endif
577
#endif  // CONFIG_TMV
578

579
  if (!is_inside(&xd->tile, mi_col, mi_row, cm->mi_rows, cm, &mi_pos))
580
    return coll_blk_count;
581
582
583
  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
584
585
#if CONFIG_AMVR
      lower_mv_precision(&this_refmv.as_mv, cm->allow_high_precision_mv,
586
                         cm->cur_frame_force_integer_mv);
RogerZhou's avatar
RogerZhou committed
587
#else
588
      lower_mv_precision(&this_refmv.as_mv, cm->allow_high_precision_mv);
RogerZhou's avatar
RogerZhou committed
589
#endif
590
591
592
593
594
595

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

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

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

      if (idx == *refmv_count && *refmv_count < MAX_REF_MV_STACK_SIZE) {
        ref_mv_stack[idx].this_mv.as_int = this_refmv.as_int;
606
607
        ref_mv_stack[idx].pred_diff[0] =
            av1_get_pred_diff_ctx(prev_frame_mvs->pred_mv[ref], this_refmv);
608
        ref_mv_stack[idx].weight = 2 * weight_unit;
609
610
611
612
613
614
615
616
617
        ++(*refmv_count);
      }

      ++coll_blk_count;
    }
  }

  return coll_blk_count;
}
618
#endif  // CONFIG_MFMV
619

Yaowu Xu's avatar
Yaowu Xu committed
620
static void setup_ref_mv_list(const AV1_COMMON *cm, const MACROBLOCKD *xd,
621
                              MV_REFERENCE_FRAME ref_frame,
clang-format's avatar
clang-format committed
622
                              uint8_t *refmv_count, CANDIDATE_MV *ref_mv_stack,
623
                              int_mv *mv_ref_list,
624
#if USE_CUR_GM_REFMV
625
                              int_mv *gm_mv_candidates,
626
#endif  // USE_CUR_GM_REFMV
Luc Trudeau's avatar
Luc Trudeau committed
627
                              int mi_row, int mi_col, int16_t *mode_context) {
628
629
630
631
632
633
634
635
636
637
638
#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;
639
640
641
#if CONFIG_MV_COMPRESS
  const MV_REF *const prev_frame_mvs_base =
      cm->use_prev_frame_mvs
642
643
          ? cm->prev_frame->mvs +
                (((mi_row >> 1) << 1) + 1) * prev_frame_mvs_stride +
644
645
646
                ((mi_col >> 1) << 1) + 1
          : NULL;
#else
clang-format's avatar
clang-format committed
647
648
  const MV_REF *const prev_frame_mvs_base =
      cm->use_prev_frame_mvs
649
          ? cm->prev_frame->mvs + mi_row * prev_frame_mvs_stride + mi_col
clang-format's avatar
clang-format committed
650
          : NULL;
651
#endif
652
#endif  // CONFIG_TMV
653

654
  const int bs = AOMMAX(xd->n8_w, xd->n8_h);
655
  const int has_tr = has_top_right(cm, xd, mi_row, mi_col, bs);
Jingning Han's avatar
Jingning Han committed
656
657
  MV_REFERENCE_FRAME rf[2];

Yunqing Wang's avatar
Yunqing Wang committed
658
  const TileInfo *const tile = &xd->tile;
659
660
661
662
663
  int max_row_offset = 0, max_col_offset = 0;
  const int row_adj = (xd->n8_h < mi_size_high[BLOCK_8X8]) && (mi_row & 0x01);
  const int col_adj = (xd->n8_w < mi_size_wide[BLOCK_8X8]) && (mi_col & 0x01);
  int processed_rows = 0;
  int processed_cols = 0;
Yunqing Wang's avatar
Yunqing Wang committed
664

665
  av1_set_ref_frame(rf, ref_frame);
666
  mode_context[ref_frame] = 0;
667
  *refmv_count = 0;
668

669
670
671
  // Find valid maximum row/col offset.
  if (xd->up_available) {
    max_row_offset = -(MVREF_ROWS << 1) + row_adj;
672
673
674
675
#if CONFIG_OPT_REF_MV
    if (xd->n8_h < mi_size_high[BLOCK_8X8])
      max_row_offset = -(2 << 1) + row_adj;
#endif
Yunqing Wang's avatar
Yunqing Wang committed
676
677
678
    max_row_offset =
        find_valid_row_offset(tile, mi_row, cm->mi_rows, cm, max_row_offset);
  }
679
680
681

  if (xd->left_available) {
    max_col_offset = -(MVREF_COLS << 1) + col_adj;
682
683
684
685
#if CONFIG_OPT_REF_MV
    if (xd->n8_w < mi_size_wide[BLOCK_8X8])
      max_col_offset = -(2 << 1) + col_adj;
#endif
Yunqing Wang's avatar
Yunqing Wang committed
686
687
    max_col_offset = find_valid_col_offset(tile, mi_col, max_col_offset);
  }
688

689
690
691
  uint8_t ref_match_count = 0;
  uint8_t newmv_count = 0;

692
693
  // Scan the first above row mode info. row_offset = -1;
  if (abs(max_row_offset) >= 1)
Luc Trudeau's avatar
Luc Trudeau committed
694
695
    newmv_count += scan_row_mbmi(cm, xd, mi_row, mi_col, rf, -1, ref_mv_stack,
                                 refmv_count, &ref_match_count,
696
#if USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
697
                                 gm_mv_candidates,
698
#endif  // USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
699
                                 max_row_offset, &processed_rows);
700
701
  // Scan the first left column mode info. col_offset = -1;
  if (abs(max_col_offset) >= 1)
Luc Trudeau's avatar
Luc Trudeau committed
702
703
    newmv_count += scan_col_mbmi(cm, xd, mi_row, mi_col, rf, -1, ref_mv_stack,
                                 refmv_count, &ref_match_count,
704
#if USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
705
                                 gm_mv_candidates,
706
#endif  // USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
707
                                 max_col_offset, &processed_cols);
708
709
  // Check top-right boundary
  if (has_tr)
Luc Trudeau's avatar
Luc Trudeau committed
710
711
    newmv_count += scan_blk_mbmi(cm, xd, mi_row, mi_col, rf, -1, xd->n8_w,
                                 ref_mv_stack, &ref_match_count,
712
#if USE_CUR_GM_REFMV
713
                                 gm_mv_candidates,
714
#endif  // USE_CUR_GM_REFMV
715
                                 refmv_count);
716

717
718
  const int nearest_match = ref_match_count;
  const int nearest_refmv_count = *refmv_count;
719

720
  for (int idx = 0; idx < nearest_refmv_count; ++idx)
721
    ref_mv_stack[idx].weight += REF_CAT_LEVEL;
722
723

#if CONFIG_MFMV
724
  if (cm->use_ref_frame_mvs) {
725
    int coll_blk_count = 0;
726
727
    const int voffset = AOMMAX(mi_size_high[BLOCK_8X8], xd->n8_h);
    const int hoffset = AOMMAX(mi_size_wide[BLOCK_8X8], xd->n8_w);
728

729
    const int tpl_sample_pos[9][2] = {
730
731
732
733
734
      { -2, hoffset }, { 0, hoffset },  { voffset, hoffset },
      { voffset, 0 },  { voffset, -2 }, { voffset, -4 },
      { -4, hoffset }, { voffset, 4 },  { 2, hoffset + 4 },
    };

735
736
737
    for (int blk_row = 0; blk_row < xd->n8_h;
         blk_row += mi_size_high[BLOCK_8X8]) {
      for (int blk_col = 0; blk_col < xd->n8_w;
738
739
740
741
742
743
744
745
746
           blk_col += mi_size_wide[BLOCK_8X8]) {
        // (TODO: yunqing) prev_frame_mvs_base is not used here, tpl_mvs is
        // used.
        // Can be modified the same way.
        int is_available = add_tpl_ref_mv(
            cm, prev_frame_mvs_base, xd, mi_row, mi_col, ref_frame, blk_row,
            blk_col, refmv_count, ref_mv_stack, mode_context);
        if (blk_row == 0 && blk_col == 0) coll_blk_count = is_available;
      }
747
748
    }

Sarah Parker's avatar
Sarah Parker committed
749
    if (coll_blk_count == 0) mode_context[ref_frame] |= (1 << GLOBALMV_OFFSET);
750

751
752
753
    for (int i = 0; i < 9; ++i) {
      const int blk_row = tpl_sample_pos[i][0];
      const int blk_col = tpl_sample_pos[i][1];
754

755
756
757
758
759
760
761
      if (!check_sb_border(cm, mi_row, mi_col, blk_row, blk_col)) continue;
      // (TODO: yunqing) prev_frame_mvs_base is not used here, tpl_mvs is used.
      // Can be modified the same way.
      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);
    }
762
763
  }
#else
764
#if CONFIG_TEMPMV_SIGNALING
765
  if (cm->use_prev_frame_mvs && rf[1] == NONE_FRAME)
766
#else
clang-format's avatar
clang-format committed
767
  if (prev_frame_mvs_base && cm->show_frame && cm->last_show_frame &&
768
      rf[1] == NONE_FRAME)
769
#endif
770
  {
771
    int coll_blk_count = 0;
772
773
774
    const int mi_step = (xd->n8_w == 1 || xd->n8_h == 1)
                            ? mi_size_wide[BLOCK_8X8]
                            : mi_size_wide[BLOCK_16X16];
775

776
777
    for (int blk_row = 0; blk_row < xd->n8_h; blk_row += mi_step) {
      for (int blk_col = 0; blk_col < xd->n8_w; blk_col += mi_step) {
778
779
780
781
782
783
784
785
786
787
788
#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
789
790
791
792
793
#if CONFIG_OPT_REF_MV
        if (blk_row == 0 && blk_col == 0) coll_blk_count = is_available;
#else
        coll_blk_count += is_available;
#endif
794
795
      }
    }
796

Sarah Parker's avatar
Sarah Parker committed
797
    if (coll_blk_count == 0) mode_context[ref_frame] |= (1 << GLOBALMV_OFFSET);
798
  } else {
Sarah Parker's avatar
Sarah Parker committed
799
    mode_context[ref_frame] |= (1 << GLOBALMV_OFFSET);
800
  }
801
#endif  // CONFIG_MFMV
802

803
  // Scan the second outer area.
Luc Trudeau's avatar
Luc Trudeau committed
804
  scan_blk_mbmi(cm, xd, mi_row, mi_col, rf, -1, -1, ref_mv_stack,
805
                &ref_match_count,
806
#if USE_CUR_GM_REFMV
807
                gm_mv_candidates,
808
#endif  // USE_CUR_GM_REFMV
Deng's avatar
Deng committed
809
                refmv_count);
810

811
812
813
  for (int idx = 2; idx <= MVREF_ROWS; ++idx) {
    const int row_offset = -(idx << 1) + 1 + row_adj;
    const int col_offset = -(idx << 1) + 1 + col_adj;
Yunqing Wang's avatar
Yunqing Wang committed
814

815
816
    if (abs(row_offset) <= abs(max_row_offset) &&
        abs(row_offset) > processed_rows)
Luc Trudeau's avatar
Luc Trudeau committed
817
      scan_row_mbmi(cm, xd, mi_row, mi_col, rf, row_offset, ref_mv_stack,
818
                    refmv_count, &ref_match_count,
819
#if USE_CUR_GM_REFMV
820
                    gm_mv_candidates,
821
#endif  // USE_CUR_GM_REFMV
822
                    max_row_offset, &processed_rows);
823
824
825

    if (abs(col_offset) <= abs(max_col_offset) &&
        abs(col_offset) > processed_cols)
Luc Trudeau's avatar
Luc Trudeau committed
826
      scan_col_mbmi(cm, xd, mi_row, mi_col, rf, col_offset, ref_mv_stack,
827
                    refmv_count, &ref_match_count,
828
#if USE_CUR_GM_REFMV
829
                    gm_mv_candidates,
830
#endif  // USE_CUR_GM_REFMV
831
                    max_col_offset, &processed_cols);
Yunqing Wang's avatar
Yunqing Wang committed
832
833
  }

834
  const int col_offset = -(MVREF_COLS << 1) + 1 + col_adj;
835
836
  if (abs(col_offset) <= abs(max_col_offset) &&
      abs(col_offset) > processed_cols)