mvref_common.c 68.8 KB
Newer Older
Jingning Han's avatar
Jingning Han committed
1
/*
Yaowu Xu's avatar
Yaowu Xu committed
2
 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
Jingning Han's avatar
Jingning Han committed
3
 *
Yaowu Xu's avatar
Yaowu Xu committed
4 5 6 7 8 9
 * This source code is subject to the terms of the BSD 2 Clause License and
 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
 * was not distributed with this source code in the LICENSE file, you can
 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
 * Media Patent License 1.0 was not distributed with this source code in the
 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
Jingning Han's avatar
Jingning Han committed
10 11
 */

12
#include "av1/common/mvref_common.h"
Yue Chen's avatar
Yue Chen committed
13
#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