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

// TODO(jingning): Consider the use of lookup table for (num / den)
// altogether.
static void get_mv_projection(MV *output, MV ref, int num, int den) {
  output->row =
      (int16_t)(ROUND_POWER_OF_TWO_SIGNED(ref.row * num * div_mult[den], 14));
  output->col =
      (int16_t)(ROUND_POWER_OF_TWO_SIGNED(ref.col * num * div_mult[den], 14));
}
#endif  // CONFIG_MFMV

38
39
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) {
40
#if CONFIG_TMV || CONFIG_MFMV
41
  const int frame_mvs_stride = ROUND_POWER_OF_TWO(cm->mi_cols, 1);
42
43
  MV_REF *frame_mvs =
      cm->cur_frame->mvs + (mi_row >> 1) * frame_mvs_stride + (mi_col >> 1);
44
45
46
47
48
49
50
51
52
53
54
55
  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++) {
56
    MV_REF *mv = frame_mvs;
57
    for (w = 0; w < x_mis; w++) {
58
59
60
61
62
63
64
65
66
67
68
#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;
69
70
71
          if ((abs(mi->mbmi.mv[idx].as_mv.row) > REFMVS_LIMIT) ||
              (abs(mi->mbmi.mv[idx].as_mv.col) > REFMVS_LIMIT))
            continue;
72
73
74
75
76
          mv->ref_frame[ref_idx] = ref_frame;
          mv->mv[ref_idx].as_int = mi->mbmi.mv[idx].as_int;
        }
      }
#else
77
78
79
80
      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;
81
#endif
82
83
84
      // (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;
85
      mv++;
86
    }
87
    frame_mvs += frame_mvs_stride;
88
89
90
  }
}

91
92
93
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,
94
    uint8_t *ref_match_count, CANDIDATE_MV *ref_mv_stack, const int use_hp,
Luc Trudeau's avatar
Luc Trudeau committed
95
    int len,
96
#if USE_CUR_GM_REFMV
97
    int_mv *gm_mv_candidates, const WarpedMotionParams *gm_params,
98
#endif  // USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
99
    int col, int weight
RogerZhou's avatar
RogerZhou committed
100
#if CONFIG_AMVR
Yunqing Wang's avatar
Yunqing Wang committed
101
102
    ,
    int is_integer
RogerZhou's avatar
RogerZhou committed
103
#endif
Yunqing Wang's avatar
Yunqing Wang committed
104
    ) {
105
106
107
#if CONFIG_INTRABC
  if (!is_inter_block(candidate)) return 0;
#endif  // CONFIG_INTRABC
Jingning Han's avatar
Jingning Han committed
108
109
  int index = 0, ref;
  int newmv_count = 0;
110
  assert(weight % 2 == 0);
111
  (void)ref_match_count;
Jingning Han's avatar
Jingning Han committed
112

Emil Keyder's avatar
Emil Keyder committed
113
  if (rf[1] == NONE_FRAME) {
Jingning Han's avatar
Jingning Han committed
114
115
116
    // single reference frame
    for (ref = 0; ref < 2; ++ref) {
      if (candidate->ref_frame[ref] == rf[0]) {
117
        int_mv this_refmv;
118
#if USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
119
120
121
        if (is_global_mv_block(candidate_mi, gm_params[rf[0]].wmtype))
          this_refmv = gm_mv_candidates[0];
        else
122
#endif  // USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
123
          this_refmv = get_sub_block_mv(candidate_mi, ref, col);
RogerZhou's avatar
RogerZhou committed
124
#if CONFIG_AMVR
Yunqing Wang's avatar
Yunqing Wang committed
125
        lower_mv_precision(&this_refmv.as_mv, use_hp, is_integer);
RogerZhou's avatar
RogerZhou committed
126
#else
127
        lower_mv_precision(&this_refmv.as_mv, use_hp);
128
#endif  // CONFIG_AMVR
129

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

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

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

143
#if !CONFIG_OPT_REF_MV
144
          if (candidate->mode == NEWMV) ++newmv_count;
145
#endif
Jingning Han's avatar
Jingning Han committed
146
        }
147
148
149
150
#if CONFIG_OPT_REF_MV
        if (candidate->mode == NEWMV) ++newmv_count;
        ++*ref_match_count;
#endif
151
      }
Jingning Han's avatar
Jingning Han committed
152
153
154
    }
  } else {
    // compound reference frame
clang-format's avatar
clang-format committed
155
    if (candidate->ref_frame[0] == rf[0] && candidate->ref_frame[1] == rf[1]) {
156
      int_mv this_refmv[2];
Jingning Han's avatar
Jingning Han committed
157

158
      for (ref = 0; ref < 2; ++ref) {
159
#if USE_CUR_GM_REFMV
Luc Trudeau's avatar
Luc Trudeau committed
160
        if (is_global_mv_block(candidate_mi, gm_params[rf[ref]].wmtype))
161
162
          this_refmv[ref] = gm_mv_candidates[ref];
        else
163
#endif  // USE_CUR_GM_REFMV
Luc Trudeau's avatar
Luc Trudeau committed
164
          this_refmv[ref] = get_sub_block_mv(candidate_mi, ref, col);
RogerZhou's avatar
RogerZhou committed
165
166
167
#if CONFIG_AMVR
        lower_mv_precision(&this_refmv[ref].as_mv, use_hp, is_integer);
#else
168
        lower_mv_precision(&this_refmv[ref].as_mv, use_hp);
RogerZhou's avatar
RogerZhou committed
169
#endif
170
      }
171

Jingning Han's avatar
Jingning Han committed
172
173
174
175
176
      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;

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

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

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

Yaowu Xu's avatar
Yaowu Xu committed
203
static uint8_t scan_row_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
Luc Trudeau's avatar
Luc Trudeau committed
204
                             int mi_row, int mi_col,
clang-format's avatar
clang-format committed
205
                             const MV_REFERENCE_FRAME rf[2], int row_offset,
206
                             CANDIDATE_MV *ref_mv_stack, uint8_t *refmv_count,
207
                             uint8_t *ref_match_count,
208
#if USE_CUR_GM_REFMV
209
                             int_mv *gm_mv_candidates,
210
#endif  // USE_CUR_GM_REFMV
211
                             int max_row_offset, int *processed_rows) {
Yunqing Wang's avatar
Yunqing Wang committed
212
  const int end_mi = AOMMIN(xd->n8_w, cm->mi_cols - mi_col);
213
214
  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
215
216
  int i;
  uint8_t newmv_count = 0;
217
  int col_offset = 0;
218
  const int shift = 0;
219
  // TODO(jingning): Revisit this part after cb4x4 is stable.
220
221
  if (abs(row_offset) > 1) {
    col_offset = 1;
222
    if (mi_col & 0x01 && xd->n8_w < n8_w_8) --col_offset;
223
  }
Yunqing Wang's avatar
Yunqing Wang committed
224
225
  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
226
  (void)mi_row;
Jingning Han's avatar
Jingning Han committed
227

228
  for (i = 0; i < end_mi;) {
Yunqing Wang's avatar
Yunqing Wang committed
229
230
    const MODE_INFO *const candidate_mi = candidate_mi0[col_offset + i];
    const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
231
232
233
    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
234
235
236
237
    if (use_step_16)
      len = AOMMAX(n8_w_16, len);
    else if (abs(row_offset) > 1)
      len = AOMMAX(len, n8_w_8);
238
239
240
241
242
243
244
245
246
247
248

    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
249
250
#if CONFIG_AMVR
    newmv_count += add_ref_mv_candidate(
251
        candidate_mi, candidate, rf, refmv_count, ref_match_count, ref_mv_stack,
Luc Trudeau's avatar
Luc Trudeau committed
252
        cm->allow_high_precision_mv, len,
253
#if USE_CUR_GM_REFMV
254
        gm_mv_candidates, cm->global_motion,
255
#endif  // USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
256
        col_offset + i, weight, cm->cur_frame_force_integer_mv);
RogerZhou's avatar
RogerZhou committed
257
#else
Yunqing Wang's avatar
Yunqing Wang committed
258
    newmv_count += add_ref_mv_candidate(
259
        candidate_mi, candidate, rf, refmv_count, ref_match_count, ref_mv_stack,
Luc Trudeau's avatar
Luc Trudeau committed
260
        cm->allow_high_precision_mv, len,
261
#if USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
262
        gm_mv_candidates, cm->global_motion,
263
#endif  // USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
264
        col_offset + i, weight);
RogerZhou's avatar
RogerZhou committed
265
#endif
266

Yunqing Wang's avatar
Yunqing Wang committed
267
    i += len;
268
  }
269
270

  return newmv_count;
271
272
}

Yaowu Xu's avatar
Yaowu Xu committed
273
static uint8_t scan_col_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
Luc Trudeau's avatar
Luc Trudeau committed
274
                             int mi_row, int mi_col,
clang-format's avatar
clang-format committed
275
                             const MV_REFERENCE_FRAME rf[2], int col_offset,
276
                             CANDIDATE_MV *ref_mv_stack, uint8_t *refmv_count,
277
                             uint8_t *ref_match_count,
278
#if USE_CUR_GM_REFMV
279
                             int_mv *gm_mv_candidates,
280
#endif  // USE_CUR_GM_REFMV
281
                             int max_col_offset, int *processed_cols) {
Yunqing Wang's avatar
Yunqing Wang committed
282
  const int end_mi = AOMMIN(xd->n8_h, cm->mi_rows - mi_row);
283
284
  const int n8_h_8 = mi_size_high[BLOCK_8X8];
  const int n8_h_16 = mi_size_high[BLOCK_16X16];
285
  int i;
286
  uint8_t newmv_count = 0;
287
  int row_offset = 0;
288
  const int shift = 0;
289
290
  if (abs(col_offset) > 1) {
    row_offset = 1;
291
    if (mi_row & 0x01 && xd->n8_h < n8_h_8) --row_offset;
292
  }
Yunqing Wang's avatar
Yunqing Wang committed
293
  const int use_step_16 = (xd->n8_h >= 16);
Yunqing Wang's avatar
Yunqing Wang committed
294
  (void)mi_col;
295

296
  for (i = 0; i < end_mi;) {
Yunqing Wang's avatar
Yunqing Wang committed
297
298
299
    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;
300
301
302
    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
303
304
305
306
    if (use_step_16)
      len = AOMMAX(n8_h_16, len);
    else if (abs(col_offset) > 1)
      len = AOMMAX(len, n8_h_8);
307
308
309
310
311
312
313
314
315
316
317

    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
318
319
#if CONFIG_AMVR
    newmv_count += add_ref_mv_candidate(
320
        candidate_mi, candidate, rf, refmv_count, ref_match_count, ref_mv_stack,
Luc Trudeau's avatar
Luc Trudeau committed
321
        cm->allow_high_precision_mv, len,
322
#if USE_CUR_GM_REFMV
323
        gm_mv_candidates, cm->global_motion,
324
#endif  // USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
325
        col_offset, weight, cm->cur_frame_force_integer_mv);
RogerZhou's avatar
RogerZhou committed
326
#else
Yunqing Wang's avatar
Yunqing Wang committed
327
    newmv_count += add_ref_mv_candidate(
328
        candidate_mi, candidate, rf, refmv_count, ref_match_count, ref_mv_stack,
Luc Trudeau's avatar
Luc Trudeau committed
329
        cm->allow_high_precision_mv, len,
330
#if USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
331
        gm_mv_candidates, cm->global_motion,
332
#endif  // USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
333
        col_offset, weight);
RogerZhou's avatar
RogerZhou committed
334
#endif
Yunqing Wang's avatar
Yunqing Wang committed
335
    i += len;
336
  }
337
338

  return newmv_count;
339
340
}

Yaowu Xu's avatar
Yaowu Xu committed
341
static uint8_t scan_blk_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
Luc Trudeau's avatar
Luc Trudeau committed
342
                             const int mi_row, const int mi_col,
clang-format's avatar
clang-format committed
343
344
                             const MV_REFERENCE_FRAME rf[2], int row_offset,
                             int col_offset, CANDIDATE_MV *ref_mv_stack,
345
                             uint8_t *ref_match_count,
346
#if USE_CUR_GM_REFMV
347
                             int_mv *gm_mv_candidates,
348
#endif  // USE_CUR_GM_REFMV
349
                             uint8_t *refmv_count) {
350
351
  const TileInfo *const tile = &xd->tile;
  POSITION mi_pos;
352
  uint8_t newmv_count = 0;
353
354
355
356

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

357
  if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm, &mi_pos)) {
358
359
360
    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;
361
    const int len = mi_size_wide[BLOCK_8X8];
362

RogerZhou's avatar
RogerZhou committed
363
364
#if CONFIG_AMVR
    newmv_count += add_ref_mv_candidate(
365
        candidate_mi, candidate, rf, refmv_count, ref_match_count, ref_mv_stack,
Luc Trudeau's avatar
Luc Trudeau committed
366
        cm->allow_high_precision_mv, len,
367
#if USE_CUR_GM_REFMV
368
        gm_mv_candidates, cm->global_motion,
369
#endif  // USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
370
        mi_pos.col, 2, cm->cur_frame_force_integer_mv);
RogerZhou's avatar
RogerZhou committed
371
#else
Yunqing Wang's avatar
Yunqing Wang committed
372
    newmv_count += add_ref_mv_candidate(
373
        candidate_mi, candidate, rf, refmv_count, ref_match_count, ref_mv_stack,
Luc Trudeau's avatar
Luc Trudeau committed
374
        cm->allow_high_precision_mv, len,
375
#if USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
376
        gm_mv_candidates, cm->global_motion,
377
#endif  // USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
378
        mi_pos.col, 2);
RogerZhou's avatar
RogerZhou committed
379
#endif
380
  }  // Analyze a single 8x8 block motion information.
Yaowu Xu's avatar
Yaowu Xu committed
381

382
  return newmv_count;
383
384
}

385
386
387
388
389
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);
390

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

394
395
  // bs > 0 and bs is a power of 2
  assert(bs > 0 && !(bs & (bs - 1)));
396

397
398
399
  // 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
400
  while (bs < sb_mi_size) {
401
402
    if (mask_col & bs) {
      if ((mask_col & (2 * bs)) && (mask_row & (2 * bs))) {
403
        has_tr = 0;
404
405
406
407
408
409
410
        break;
      }
    } else {
      break;
    }
    bs <<= 1;
  }
411

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

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

422
#if CONFIG_EXT_PARTITION_TYPES
423
424
425
  // 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
426
  if (xd->mi[0]->mbmi.partition == PARTITION_VERT_A)
427
    if ((mask_row & bs) && !(mask_col & bs)) has_tr = 0;
428
429
#endif  // CONFIG_EXT_PARTITION_TYPES

430
431
432
  return has_tr;
}

433
#if CONFIG_MFMV
434
435
436
437
438
439
440
441
442
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)
443
444
445
446
447
    return 0;

  return 1;
}

448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
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;

471
  const TPL_MV_REF *prev_frame_mvs =
Jingning Han's avatar
Jingning Han committed
472
      cm->tpl_mvs + ((mi_row + mi_pos.row) >> 1) * (cm->mi_stride >> 1) +
473
      ((mi_col + mi_pos.col) >> 1);
Jingning Han's avatar
Jingning Han committed
474

475
476
477
478
  MV_REFERENCE_FRAME rf[2];
  av1_set_ref_frame(rf, ref_frame);

  if (rf[1] == NONE_FRAME) {
479
480
481
482
483
    int cur_frame_index = cm->cur_frame->cur_frame_offset;
    int buf_idx_0 = cm->frame_refs[FWD_RF_OFFSET(rf[0])].idx;
    int cur_offset_0 = cur_frame_index -
                       cm->buffer_pool->frame_bufs[buf_idx_0].cur_frame_offset;

484
    for (int i = 0; i < MFMV_STACK_SIZE; ++i) {
485
486
487
488
489
      if (prev_frame_mvs->mfmv0[i].as_int != INVALID_MV) {
        int_mv this_refmv;

        get_mv_projection(&this_refmv.as_mv, prev_frame_mvs->mfmv0[i].as_mv,
                          cur_offset_0, prev_frame_mvs->ref_frame_offset[i]);
RogerZhou's avatar
RogerZhou committed
490
491
492
493
#if CONFIG_AMVR
        lower_mv_precision(&this_refmv.as_mv, cm->allow_high_precision_mv,
                           cm->cur_frame_force_integer_mv);
#else
494
        lower_mv_precision(&this_refmv.as_mv, cm->allow_high_precision_mv);
RogerZhou's avatar
RogerZhou committed
495
#endif
496

497
498
499
        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
500
            mode_context[ref_frame] |= (1 << GLOBALMV_OFFSET);
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524

        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
525
526
527
528
529
530
531
532
    int cur_frame_index = cm->cur_frame->cur_frame_offset;
    int buf_idx_0 = cm->frame_refs[FWD_RF_OFFSET(rf[0])].idx;
    int cur_offset_0 = cur_frame_index -
                       cm->buffer_pool->frame_bufs[buf_idx_0].cur_frame_offset;
    int buf_idx_1 = cm->frame_refs[FWD_RF_OFFSET(rf[1])].idx;
    int cur_offset_1 = cur_frame_index -
                       cm->buffer_pool->frame_bufs[buf_idx_1].cur_frame_offset;

533
    for (int i = 0; i < MFMV_STACK_SIZE; ++i) {
534
535
536
537
538
539
540
541
      if (prev_frame_mvs->mfmv0[i].as_int != INVALID_MV) {
        int_mv this_refmv;
        int_mv comp_refmv;
        get_mv_projection(&this_refmv.as_mv, prev_frame_mvs->mfmv0[i].as_mv,
                          cur_offset_0, prev_frame_mvs->ref_frame_offset[i]);
        get_mv_projection(&comp_refmv.as_mv, prev_frame_mvs->mfmv0[i].as_mv,
                          cur_offset_1, prev_frame_mvs->ref_frame_offset[i]);

RogerZhou's avatar
RogerZhou committed
542
543
544
545
546
547
#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
548
549
        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
550
#endif
551
552
553
554
555
        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
556
            mode_context[ref_frame] |= (1 << GLOBALMV_OFFSET);
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589

        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
590
591
static int add_col_ref_mv(const AV1_COMMON *cm,
                          const MV_REF *prev_frame_mvs_base,
592
593
594
                          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,
595
                          CANDIDATE_MV *ref_mv_stack, int16_t *mode_context) {
596
597
#if CONFIG_TMV
  const MV_REF *prev_frame_mvs = prev_frame_mvs_base +
Yunqing Wang's avatar
Yunqing Wang committed
598
599
                                 (blk_row >> 1) * prev_frame_mvs_stride +
                                 (blk_col >> 1);
600
#else
601
  const MV_REF *prev_frame_mvs =
602
603
      prev_frame_mvs_base + blk_row * prev_frame_mvs_stride + blk_col;
#endif
604
605
606
  POSITION mi_pos;
  int ref, idx;
  int coll_blk_count = 0;
607
  const int weight_unit = mi_size_wide[BLOCK_8X8];
608

609
610
611
612
#if CONFIG_TMV
  mi_pos.row = blk_row;
  mi_pos.col = blk_col;
#else
613
614
615
616
#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
617
618
  mi_pos.row = blk_row;
  mi_pos.col = blk_col;
619
#endif
620
#endif  // CONFIG_TMV
621

622
  if (!is_inside(&xd->tile, mi_col, mi_row, cm->mi_rows, cm, &mi_pos))
623
    return coll_blk_count;
624
625
626
  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
627
628
#if CONFIG_AMVR
      lower_mv_precision(&this_refmv.as_mv, cm->allow_high_precision_mv,
629
                         cm->cur_frame_force_integer_mv);
RogerZhou's avatar
RogerZhou committed
630
#else
631
      lower_mv_precision(&this_refmv.as_mv, cm->allow_high_precision_mv);
RogerZhou's avatar
RogerZhou committed
632
#endif
633
634
635
636
637
638

#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
639
          mode_context[ref_frame] |= (1 << GLOBALMV_OFFSET);
640
      }
641
642
643
644

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

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

      if (idx == *refmv_count && *refmv_count < MAX_REF_MV_STACK_SIZE) {
        ref_mv_stack[idx].this_mv.as_int = this_refmv.as_int;
649
650
        ref_mv_stack[idx].pred_diff[0] =
            av1_get_pred_diff_ctx(prev_frame_mvs->pred_mv[ref], this_refmv);
651
        ref_mv_stack[idx].weight = 2 * weight_unit;
652
653
654
655
656
657
658
659
660
        ++(*refmv_count);
      }

      ++coll_blk_count;
    }
  }

  return coll_blk_count;
}
661
#endif  // CONFIG_MFMV
662

Yaowu Xu's avatar
Yaowu Xu committed
663
static void setup_ref_mv_list(const AV1_COMMON *cm, const MACROBLOCKD *xd,
664
                              MV_REFERENCE_FRAME ref_frame,
clang-format's avatar
clang-format committed
665
                              uint8_t *refmv_count, CANDIDATE_MV *ref_mv_stack,
666
                              int_mv *mv_ref_list,
667
#if USE_CUR_GM_REFMV
668
                              int_mv *gm_mv_candidates,
669
#endif  // USE_CUR_GM_REFMV
Luc Trudeau's avatar
Luc Trudeau committed
670
                              int mi_row, int mi_col, int16_t *mode_context) {
671
672
673
674
675
676
677
678
679
680
681
#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;
682
683
684
#if CONFIG_MV_COMPRESS
  const MV_REF *const prev_frame_mvs_base =
      cm->use_prev_frame_mvs
685
686
          ? cm->prev_frame->mvs +
                (((mi_row >> 1) << 1) + 1) * prev_frame_mvs_stride +
687
688
689
                ((mi_col >> 1) << 1) + 1
          : NULL;
#else
clang-format's avatar
clang-format committed
690
691
  const MV_REF *const prev_frame_mvs_base =
      cm->use_prev_frame_mvs
692
          ? cm->prev_frame->mvs + mi_row * prev_frame_mvs_stride + mi_col
clang-format's avatar
clang-format committed
693
          : NULL;
694
#endif
695
#endif  // CONFIG_TMV
696

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

Yunqing Wang's avatar
Yunqing Wang committed
701
  const TileInfo *const tile = &xd->tile;
702
703
704
705
706
  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
707

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

712
713
714
  // Find valid maximum row/col offset.
  if (xd->up_available) {
    max_row_offset = -(MVREF_ROWS << 1) + row_adj;
715
716
717
718
#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
719
720
721
    max_row_offset =
        find_valid_row_offset(tile, mi_row, cm->mi_rows, cm, max_row_offset);
  }
722
723
724

  if (xd->left_available) {
    max_col_offset = -(MVREF_COLS << 1) + col_adj;
725
726
727
728
#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
729
730
    max_col_offset = find_valid_col_offset(tile, mi_col, max_col_offset);
  }
731

732
733
734
  uint8_t ref_match_count = 0;
  uint8_t newmv_count = 0;

735
736
  // Scan the first above row mode info. row_offset = -1;
  if (abs(max_row_offset) >= 1)
Luc Trudeau's avatar
Luc Trudeau committed
737
738
    newmv_count += scan_row_mbmi(cm, xd, mi_row, mi_col, rf, -1, ref_mv_stack,
                                 refmv_count, &ref_match_count,
739
#if USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
740
                                 gm_mv_candidates,
741
#endif  // USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
742
                                 max_row_offset, &processed_rows);
743
744
  // Scan the first left column mode info. col_offset = -1;
  if (abs(max_col_offset) >= 1)
Luc Trudeau's avatar
Luc Trudeau committed
745
746
    newmv_count += scan_col_mbmi(cm, xd, mi_row, mi_col, rf, -1, ref_mv_stack,
                                 refmv_count, &ref_match_count,
747
#if USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
748
                                 gm_mv_candidates,
749
#endif  // USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
750
                                 max_col_offset, &processed_cols);
751
752
  // Check top-right boundary
  if (has_tr)
Luc Trudeau's avatar
Luc Trudeau committed
753
754
    newmv_count += scan_blk_mbmi(cm, xd, mi_row, mi_col, rf, -1, xd->n8_w,
                                 ref_mv_stack, &ref_match_count,
755
#if USE_CUR_GM_REFMV
756
                                 gm_mv_candidates,
757
#endif  // USE_CUR_GM_REFMV
758
                                 refmv_count);
759

760
761
  const int nearest_match = ref_match_count;
  const int nearest_refmv_count = *refmv_count;
762

763
  for (int idx = 0; idx < nearest_refmv_count; ++idx)
764
    ref_mv_stack[idx].weight += REF_CAT_LEVEL;
765
766

#if CONFIG_MFMV
767
  if (cm->use_ref_frame_mvs) {
768
    int coll_blk_count = 0;
769
770
    const int voffset = AOMMAX(mi_size_high[BLOCK_8X8], xd->n8_h);
    const int hoffset = AOMMAX(mi_size_wide[BLOCK_8X8], xd->n8_w);
771

Jingning Han's avatar
Jingning Han committed
772
773
    const int tpl_sample_pos[3][2] = {
      { voffset, -2 }, { voffset, hoffset }, { voffset - 2, hoffset },
774
    };
Jingning Han's avatar
Jingning Han committed
775
776
    const int allow_extension = (xd->n8_h >= mi_size_high[BLOCK_8X8]) &&
                                (xd->n8_w >= mi_size_wide[BLOCK_8X8]);
777

778
779
780
    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;
781
782
783
784
785
786
787
788
789
           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;
      }
790
791
    }

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

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

798
799
800
801
802
803
804
      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);
    }
805
806
  }
#else
807
#if CONFIG_TEMPMV_SIGNALING
808
  if (cm->use_prev_frame_mvs && rf[1] == NONE_FRAME)
809
#else
clang-format's avatar
clang-format committed
810
  if (prev_frame_mvs_base && cm->show_frame && cm->last_show_frame &&
811
      rf[1] == NONE_FRAME)
812
#endif
813
  {
814
    int coll_blk_count = 0;
815
816
817
    const int mi_step = (xd->n8_w == 1 || xd->n8_h == 1)
                            ? mi_size_wide[BLOCK_8X8]
                            : mi_size_wide[BLOCK_16X16];
818

819
820
    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) {
821
822
823
824
825
826
827
828
829
830
831
#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
832
833
834
835
836
#if CONFIG_OPT_REF_MV
        if (blk_row == 0 && blk_col == 0) coll_blk_count = is_available;
#else
        coll_blk_count += is_available;
#endif
837
838
      }
    }
839

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

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

854
855
856
  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;