mvref_common.c 78.9 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 37 38 39 40 41 42 43
    for (w = 0; w < x_mis; w++) {
      mv->ref_frame[0] = mi->mbmi.ref_frame[0];
      mv->ref_frame[1] = mi->mbmi.ref_frame[1];
      mv->mv[0].as_int = mi->mbmi.mv[0].as_int;
      mv->mv[1].as_int = mi->mbmi.mv[1].as_int;
      // (TODO:yunqing) The following 2 lines won't be used and can be removed.
      mv->pred_mv[0].as_int = mi->mbmi.pred_mv[0].as_int;
      mv->pred_mv[1].as_int = mi->mbmi.pred_mv[1].as_int;
44
      mv++;
45
    }
46
    frame_mvs += frame_mvs_stride;
47 48 49
  }
}

50 51 52 53
static uint8_t add_ref_mv_candidate(
    const MODE_INFO *const candidate_mi, const MB_MODE_INFO *const candidate,
    const MV_REFERENCE_FRAME rf[2], uint8_t *refmv_count,
    CANDIDATE_MV *ref_mv_stack, const int use_hp, int len, int block,
54
#if USE_CUR_GM_REFMV
55
    int_mv *gm_mv_candidates, const WarpedMotionParams *gm_params,
56
#endif  // USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
57
    int col, int weight,
RogerZhou's avatar
RogerZhou committed
58
#if CONFIG_AMVR
Yunqing Wang's avatar
Yunqing Wang committed
59
    int is_integer,
RogerZhou's avatar
RogerZhou committed
60
#endif
Yunqing Wang's avatar
Yunqing Wang committed
61 62
    BLOCK_SIZE bsize, int mi_row, int mi_col, int subsampling_x,
    int subsampling_y) {
Jingning Han's avatar
Jingning Han committed
63 64
  int index = 0, ref;
  int newmv_count = 0;
65
  assert(weight % 2 == 0);
Yunqing Wang's avatar
Yunqing Wang committed
66 67 68 69 70 71 72
#if !CONFIG_EXT_WARPED_MOTION
  (void)bsize;
  (void)mi_row;
  (void)mi_col;
  (void)subsampling_x;
  (void)subsampling_y;
#endif  // CONFIG_EXT_WARPED_MOTION
Jingning Han's avatar
Jingning Han committed
73

Emil Keyder's avatar
Emil Keyder committed
74
  if (rf[1] == NONE_FRAME) {
Jingning Han's avatar
Jingning Han committed
75 76 77
    // single reference frame
    for (ref = 0; ref < 2; ++ref) {
      if (candidate->ref_frame[ref] == rf[0]) {
78
        int_mv this_refmv;
Yunqing Wang's avatar
Yunqing Wang committed
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
#if CONFIG_EXT_WARPED_MOTION
        if (candidate->motion_mode == WARPED_CAUSAL) {
          WarpedMotionParams wm = candidate->wm_params[0];
          const int bw = block_size_wide[bsize];
          const int bh = block_size_high[bsize];
          int global_offset_c = mi_col * MI_SIZE;
          int global_offset_r = mi_row * MI_SIZE;
          int cc_offset = bw / 2 - 1;
          int cr_offset = bh / 2 - 1;
          int xc0 = cc_offset + global_offset_c;
          int yc0 = cr_offset + global_offset_r;
          int xc1 = xc0 + 1;
          int yc1 = yc0 + 1;
          int in[4] = { xc0, yc0, xc1, yc1 };
          int out[4] = { 0, 0, 0, 0 };

          assert(ref == 0);
          // For WARPED_CAUSAL, wmtype is always AFFINE.
          assert(wm.wmtype == AFFINE);
          project_points_affine(wm.wmmat, in, out, 2, 2, 2, subsampling_x,
                                subsampling_y);

          // assert(x_scale == 1024 && y_scale == 1024);
          // out[]'s precision is 1/64, adjust xc, yc accordingly.
          out[0] -= (xc0 << (3 + SCALING_FCT));
          out[1] -= (yc0 << (3 + SCALING_FCT));
          out[2] -= (xc1 << (3 + SCALING_FCT));
          out[3] -= (yc1 << (3 + SCALING_FCT));

          this_refmv.as_mv.col =
              ROUND_POWER_OF_TWO_SIGNED(out[0] + out[2], SCALING_FCT + 1);
          this_refmv.as_mv.row =
              ROUND_POWER_OF_TWO_SIGNED(out[1] + out[3], SCALING_FCT + 1);
          lower_mv_precision(&this_refmv.as_mv, use_hp);
        } else {
#endif  // CONFIG_EXT_WARPED_MOTION
115
#if USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
116 117 118
          if (is_global_mv_block(candidate_mi, block, gm_params[rf[0]].wmtype))
            this_refmv = gm_mv_candidates[0];
          else
119
#endif  // USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
120
            this_refmv = get_sub_block_mv(candidate_mi, ref, col, block);
RogerZhou's avatar
RogerZhou committed
121
#if CONFIG_AMVR
Yunqing Wang's avatar
Yunqing Wang committed
122
          lower_mv_precision(&this_refmv.as_mv, use_hp, is_integer);
RogerZhou's avatar
RogerZhou committed
123
#else
124
        lower_mv_precision(&this_refmv.as_mv, use_hp);
125
#endif  // CONFIG_AMVR
Yunqing Wang's avatar
Yunqing Wang committed
126 127 128
#if CONFIG_EXT_WARPED_MOTION
        }
#endif  // CONFIG_EXT_WARPED_MOTION
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 139
          ref_mv_stack[index].pred_diff[0] = av1_get_pred_diff_ctx(
              get_sub_block_pred_mv(candidate_mi, ref, col, block), this_refmv);
140
          ref_mv_stack[index].weight = weight * len;
Jingning Han's avatar
Jingning Han committed
141
          ++(*refmv_count);
142

143
          if (candidate->mode == NEWMV) ++newmv_count;
Jingning Han's avatar
Jingning Han committed
144
        }
145
      }
Jingning Han's avatar
Jingning Han committed
146 147 148
    }
  } else {
    // compound reference frame
clang-format's avatar
clang-format committed
149
    if (candidate->ref_frame[0] == rf[0] && candidate->ref_frame[1] == rf[1]) {
150
      int_mv this_refmv[2];
Jingning Han's avatar
Jingning Han committed
151

152
      for (ref = 0; ref < 2; ++ref) {
153
#if USE_CUR_GM_REFMV
154 155 156
        if (is_global_mv_block(candidate_mi, block, gm_params[rf[ref]].wmtype))
          this_refmv[ref] = gm_mv_candidates[ref];
        else
157
#endif  // USE_CUR_GM_REFMV
158
          this_refmv[ref] = get_sub_block_mv(candidate_mi, ref, col, block);
RogerZhou's avatar
RogerZhou committed
159 160 161
#if CONFIG_AMVR
        lower_mv_precision(&this_refmv[ref].as_mv, use_hp, is_integer);
#else
162
        lower_mv_precision(&this_refmv[ref].as_mv, use_hp);
RogerZhou's avatar
RogerZhou committed
163
#endif
164
      }
165

Jingning Han's avatar
Jingning Han committed
166 167 168 169 170
      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;

171
      if (index < *refmv_count) ref_mv_stack[index].weight += weight * len;
Jingning Han's avatar
Jingning Han committed
172 173

      // Add a new item to the list.
174
      if (index == *refmv_count && *refmv_count < MAX_REF_MV_STACK_SIZE) {
Jingning Han's avatar
Jingning Han committed
175 176
        ref_mv_stack[index].this_mv = this_refmv[0];
        ref_mv_stack[index].comp_mv = this_refmv[1];
177 178 179 180
        ref_mv_stack[index].pred_diff[0] = av1_get_pred_diff_ctx(
            get_sub_block_pred_mv(candidate_mi, 0, col, block), this_refmv[0]);
        ref_mv_stack[index].pred_diff[1] = av1_get_pred_diff_ctx(
            get_sub_block_pred_mv(candidate_mi, 1, col, block), this_refmv[1]);
181
        ref_mv_stack[index].weight = weight * len;
Jingning Han's avatar
Jingning Han committed
182 183
        ++(*refmv_count);

184
        if (candidate->mode == NEW_NEWMV) ++newmv_count;
Jingning Han's avatar
Jingning Han committed
185 186 187 188 189 190
      }
    }
  }
  return newmv_count;
}

Yaowu Xu's avatar
Yaowu Xu committed
191
static uint8_t scan_row_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
Yunqing Wang's avatar
Yunqing Wang committed
192
                             int mi_row, int mi_col, int block,
clang-format's avatar
clang-format committed
193
                             const MV_REFERENCE_FRAME rf[2], int row_offset,
194
                             CANDIDATE_MV *ref_mv_stack, uint8_t *refmv_count,
195
#if USE_CUR_GM_REFMV
196
                             int_mv *gm_mv_candidates,
197
#endif  // USE_CUR_GM_REFMV
198
                             int max_row_offset, int *processed_rows) {
Yunqing Wang's avatar
Yunqing Wang committed
199
  const int end_mi = AOMMIN(xd->n8_w, cm->mi_cols - mi_col);
200 201
  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
202 203
  int i;
  uint8_t newmv_count = 0;
204
  int col_offset = 0;
205
  const int shift = 0;
206
  // TODO(jingning): Revisit this part after cb4x4 is stable.
207 208
  if (abs(row_offset) > 1) {
    col_offset = 1;
209
    if (mi_col & 0x01 && xd->n8_w < n8_w_8) --col_offset;
210
  }
Yunqing Wang's avatar
Yunqing Wang committed
211 212
  const int use_step_16 = (xd->n8_w >= 16);
  MODE_INFO **const candidate_mi0 = xd->mi + row_offset * xd->mi_stride;
Jingning Han's avatar
Jingning Han committed
213

214
  for (i = 0; i < end_mi;) {
Yunqing Wang's avatar
Yunqing Wang committed
215 216
    const MODE_INFO *const candidate_mi = candidate_mi0[col_offset + i];
    const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
217 218 219
    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
220 221 222 223
    if (use_step_16)
      len = AOMMAX(n8_w_16, len);
    else if (abs(row_offset) > 1)
      len = AOMMAX(len, n8_w_8);
224 225 226 227 228 229 230 231 232 233 234

    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
235 236 237
#if CONFIG_AMVR
    newmv_count += add_ref_mv_candidate(
        candidate_mi, candidate, rf, refmv_count, ref_mv_stack,
238
        cm->allow_high_precision_mv, len, block,
239
#if USE_CUR_GM_REFMV
240
        gm_mv_candidates, cm->global_motion,
241
#endif  // USE_CUR_GM_REFMV
242
        col_offset + i, weight, cm->cur_frame_force_integer_mv,
Yunqing Wang's avatar
Yunqing Wang committed
243 244
        xd->mi[0]->mbmi.sb_type, mi_row, mi_col, xd->plane[0].subsampling_x,
        xd->plane[0].subsampling_y);
RogerZhou's avatar
RogerZhou committed
245
#else
Yunqing Wang's avatar
Yunqing Wang committed
246 247 248
    newmv_count += add_ref_mv_candidate(
        candidate_mi, candidate, rf, refmv_count, ref_mv_stack,
        cm->allow_high_precision_mv, len, block,
249
#if USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
250
        gm_mv_candidates, cm->global_motion,
251
#endif  // USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
252 253
        col_offset + i, weight, xd->mi[0]->mbmi.sb_type, mi_row, mi_col,
        xd->plane[0].subsampling_x, xd->plane[0].subsampling_y);
RogerZhou's avatar
RogerZhou committed
254
#endif
255

Yunqing Wang's avatar
Yunqing Wang committed
256
    i += len;
257
  }
258 259

  return newmv_count;
260 261
}

Yaowu Xu's avatar
Yaowu Xu committed
262
static uint8_t scan_col_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
Yunqing Wang's avatar
Yunqing Wang committed
263
                             int mi_row, int mi_col, int block,
clang-format's avatar
clang-format committed
264
                             const MV_REFERENCE_FRAME rf[2], int col_offset,
265
                             CANDIDATE_MV *ref_mv_stack, uint8_t *refmv_count,
266
#if USE_CUR_GM_REFMV
267
                             int_mv *gm_mv_candidates,
268
#endif  // USE_CUR_GM_REFMV
269
                             int max_col_offset, int *processed_cols) {
Yunqing Wang's avatar
Yunqing Wang committed
270
  const int end_mi = AOMMIN(xd->n8_h, cm->mi_rows - mi_row);
271 272
  const int n8_h_8 = mi_size_high[BLOCK_8X8];
  const int n8_h_16 = mi_size_high[BLOCK_16X16];
273
  int i;
274
  uint8_t newmv_count = 0;
275
  int row_offset = 0;
276
  const int shift = 0;
277 278
  if (abs(col_offset) > 1) {
    row_offset = 1;
279
    if (mi_row & 0x01 && xd->n8_h < n8_h_8) --row_offset;
280
  }
Yunqing Wang's avatar
Yunqing Wang committed
281
  const int use_step_16 = (xd->n8_h >= 16);
282

283
  for (i = 0; i < end_mi;) {
Yunqing Wang's avatar
Yunqing Wang committed
284 285 286
    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;
287 288 289
    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
290 291 292 293
    if (use_step_16)
      len = AOMMAX(n8_h_16, len);
    else if (abs(col_offset) > 1)
      len = AOMMAX(len, n8_h_8);
294 295 296 297 298 299 300 301 302 303 304

    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
305 306 307
#if CONFIG_AMVR
    newmv_count += add_ref_mv_candidate(
        candidate_mi, candidate, rf, refmv_count, ref_mv_stack,
308
        cm->allow_high_precision_mv, len, block,
309
#if USE_CUR_GM_REFMV
310
        gm_mv_candidates, cm->global_motion,
311
#endif  // USE_CUR_GM_REFMV
312
        col_offset, weight, cm->cur_frame_force_integer_mv,
Yunqing Wang's avatar
Yunqing Wang committed
313 314
        xd->mi[0]->mbmi.sb_type, mi_row, mi_col, xd->plane[0].subsampling_x,
        xd->plane[0].subsampling_y);
RogerZhou's avatar
RogerZhou committed
315
#else
Yunqing Wang's avatar
Yunqing Wang committed
316 317 318
    newmv_count += add_ref_mv_candidate(
        candidate_mi, candidate, rf, refmv_count, ref_mv_stack,
        cm->allow_high_precision_mv, len, block,
319
#if USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
320
        gm_mv_candidates, cm->global_motion,
321
#endif  // USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
322 323
        col_offset, weight, xd->mi[0]->mbmi.sb_type, mi_row, mi_col,
        xd->plane[0].subsampling_x, xd->plane[0].subsampling_y);
RogerZhou's avatar
RogerZhou committed
324
#endif
Yunqing Wang's avatar
Yunqing Wang committed
325
    i += len;
326
  }
327 328

  return newmv_count;
329 330
}

Yaowu Xu's avatar
Yaowu Xu committed
331
static uint8_t scan_blk_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
332
                             const int mi_row, const int mi_col, int block,
clang-format's avatar
clang-format committed
333 334
                             const MV_REFERENCE_FRAME rf[2], int row_offset,
                             int col_offset, CANDIDATE_MV *ref_mv_stack,
335
#if USE_CUR_GM_REFMV
336
                             int_mv *gm_mv_candidates,
337
#endif  // USE_CUR_GM_REFMV
338
                             uint8_t *refmv_count) {
339 340
  const TileInfo *const tile = &xd->tile;
  POSITION mi_pos;
341
  uint8_t newmv_count = 0;
342 343 344 345

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

346
  if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm, &mi_pos)) {
347 348 349
    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;
350
    const int len = mi_size_wide[BLOCK_8X8];
351

RogerZhou's avatar
RogerZhou committed
352 353 354
#if CONFIG_AMVR
    newmv_count += add_ref_mv_candidate(
        candidate_mi, candidate, rf, refmv_count, ref_mv_stack,
355
        cm->allow_high_precision_mv, len, block,
356
#if USE_CUR_GM_REFMV
357
        gm_mv_candidates, cm->global_motion,
358
#endif  // USE_CUR_GM_REFMV
359 360
        mi_pos.col, 2, cm->cur_frame_force_integer_mv, xd->mi[0]->mbmi.sb_type,
        mi_row, mi_col, xd->plane[0].subsampling_x, xd->plane[0].subsampling_y);
RogerZhou's avatar
RogerZhou committed
361
#else
Yunqing Wang's avatar
Yunqing Wang committed
362 363 364
    newmv_count += add_ref_mv_candidate(
        candidate_mi, candidate, rf, refmv_count, ref_mv_stack,
        cm->allow_high_precision_mv, len, block,
365
#if USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
366
        gm_mv_candidates, cm->global_motion,
367
#endif  // USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
368 369
        mi_pos.col, 2, xd->mi[0]->mbmi.sb_type, mi_row, mi_col,
        xd->plane[0].subsampling_x, xd->plane[0].subsampling_y);
RogerZhou's avatar
RogerZhou committed
370
#endif
371
  }  // Analyze a single 8x8 block motion information.
Yaowu Xu's avatar
Yaowu Xu committed
372

373
  return newmv_count;
374 375
}

376 377 378 379 380
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);
381

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

385 386
  // bs > 0 and bs is a power of 2
  assert(bs > 0 && !(bs & (bs - 1)));
387

388 389 390
  // 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
391
  while (bs < sb_mi_size) {
392 393
    if (mask_col & bs) {
      if ((mask_col & (2 * bs)) && (mask_row & (2 * bs))) {
394
        has_tr = 0;
395 396 397 398 399 400 401
        break;
      }
    } else {
      break;
    }
    bs <<= 1;
  }
402

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

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

413 414 415 416
#if CONFIG_EXT_PARTITION_TYPES && !CONFIG_EXT_PARTITION_TYPES_AB
  // The bottom left square of a Vertical A (in the old format) does
  // not have a top right as it is decoded before the right hand
  // rectangle of the partition
417
  if (xd->mi[0]->mbmi.partition == PARTITION_VERT_A)
418
    if ((mask_row & bs) && !(mask_col & bs)) has_tr = 0;
419 420
#endif  // CONFIG_EXT_PARTITION_TYPES

421 422 423
  return has_tr;
}

424
#if CONFIG_MFMV
425 426 427 428 429 430 431 432 433
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)
434 435 436 437 438
    return 0;

  return 1;
}

439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461
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;

462
  const TPL_MV_REF *prev_frame_mvs =
Jingning Han's avatar
Jingning Han committed
463
      cm->tpl_mvs + ((mi_row + mi_pos.row) >> 1) * (cm->mi_stride >> 1) +
464
      ((mi_col + mi_pos.col) >> 1);
Jingning Han's avatar
Jingning Han committed
465

466 467 468 469 470 471 472 473 474 475
  MV_REFERENCE_FRAME rf[2];
  av1_set_ref_frame(rf, ref_frame);

  if (rf[1] == NONE_FRAME) {
    for (int i = 0; i < MFMV_STACK_SIZE; ++i) {
      if (prev_frame_mvs->mfmv[ref_frame - LAST_FRAME][i].as_int !=
          INVALID_MV) {
        int_mv this_refmv = prev_frame_mvs->mfmv[ref_frame - LAST_FRAME][i];
        lower_mv_precision(&this_refmv.as_mv, cm->allow_high_precision_mv);

476 477 478
        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
479
            mode_context[ref_frame] |= (1 << GLOBALMV_OFFSET);
480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511

        for (idx = 0; idx < *refmv_count; ++idx)
          if (abs(this_refmv.as_mv.row - ref_mv_stack[idx].this_mv.as_mv.row) <
                  4 &&
              abs(this_refmv.as_mv.col - ref_mv_stack[idx].this_mv.as_mv.col) <
                  4)
            break;

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

        if (idx == *refmv_count && *refmv_count < MAX_REF_MV_STACK_SIZE) {
          ref_mv_stack[idx].this_mv.as_int = this_refmv.as_int;
          // TODO(jingning): Hard coded context number. Need to make it better
          // sense.
          ref_mv_stack[idx].pred_diff[0] = 1;
          ref_mv_stack[idx].weight = 2 * weight_unit;
          ++(*refmv_count);
        }

        ++coll_blk_count;
      }
    }
  } else {
    // Process compound inter mode
    for (int i = 0; i < MFMV_STACK_SIZE; ++i) {
      if (prev_frame_mvs->mfmv[rf[0] - LAST_FRAME][i].as_int != INVALID_MV &&
          prev_frame_mvs->mfmv[rf[1] - LAST_FRAME][i].as_int != INVALID_MV) {
        int_mv this_refmv = prev_frame_mvs->mfmv[rf[0] - LAST_FRAME][i];
        int_mv comp_refmv = prev_frame_mvs->mfmv[rf[1] - LAST_FRAME][i];
        lower_mv_precision(&this_refmv.as_mv, cm->allow_high_precision_mv);
        lower_mv_precision(&comp_refmv.as_mv, cm->allow_high_precision_mv);

512 513 514 515 516
        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
517
            mode_context[ref_frame] |= (1 << GLOBALMV_OFFSET);
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 547 548 549 550

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

570 571 572 573
#if CONFIG_TMV
  mi_pos.row = blk_row;
  mi_pos.col = blk_col;
#else
574 575 576 577
#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
578 579
  mi_pos.row = blk_row;
  mi_pos.col = blk_col;
580
#endif
581
#endif  // CONFIG_TMV
582

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

#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
600
          mode_context[ref_frame] |= (1 << GLOBALMV_OFFSET);
601
      }
602 603 604 605

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

606
      if (idx < *refmv_count) ref_mv_stack[idx].weight += 2 * weight_unit;
607 608 609

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

      ++coll_blk_count;
    }
  }

  return coll_blk_count;
}
622
#endif  // CONFIG_MFMV
623

Yaowu Xu's avatar
Yaowu Xu committed
624
static void setup_ref_mv_list(const AV1_COMMON *cm, const MACROBLOCKD *xd,
625
                              MV_REFERENCE_FRAME ref_frame,
clang-format's avatar
clang-format committed
626
                              uint8_t *refmv_count, CANDIDATE_MV *ref_mv_stack,
627
                              int_mv *mv_ref_list,
628
#if USE_CUR_GM_REFMV
629
                              int_mv *gm_mv_candidates,
630
#endif  // USE_CUR_GM_REFMV
631 632
                              int block, int mi_row, int mi_col,
                              int16_t *mode_context) {
633
  int idx, nearest_refmv_count = 0;
634
  uint8_t newmv_count = 0;
635 636 637
  CANDIDATE_MV tmp_mv;
  int len, nr_len;

638 639 640 641 642 643 644 645 646 647 648
#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;
649 650 651
#if CONFIG_MV_COMPRESS
  const MV_REF *const prev_frame_mvs_base =
      cm->use_prev_frame_mvs
652 653
          ? cm->prev_frame->mvs +
                (((mi_row >> 1) << 1) + 1) * prev_frame_mvs_stride +
654 655 656
                ((mi_col >> 1) << 1) + 1
          : NULL;
#else
clang-format's avatar
clang-format committed
657 658
  const MV_REF *const prev_frame_mvs_base =
      cm->use_prev_frame_mvs
659
          ? cm->prev_frame->mvs + mi_row * prev_frame_mvs_stride + mi_col
clang-format's avatar
clang-format committed
660
          : NULL;
661
#endif
662
#endif  // CONFIG_TMV
663

664
  const int bs = AOMMAX(xd->n8_w, xd->n8_h);
665
  const int has_tr = has_top_right(cm, xd, mi_row, mi_col, bs);
Jingning Han's avatar
Jingning Han committed
666 667
  MV_REFERENCE_FRAME rf[2];

Yunqing Wang's avatar
Yunqing Wang committed
668
  const TileInfo *const tile = &xd->tile;
669 670 671 672 673
  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
674 675
  int row_offset, col_offset;

676
  av1_set_ref_frame(rf, ref_frame);
677
  mode_context[ref_frame] = 0;
678
  *refmv_count = 0;
679

680 681 682
  // Find valid maximum row/col offset.
  if (xd->up_available) {
    max_row_offset = -(MVREF_ROWS << 1) + row_adj;
Yunqing Wang's avatar
Yunqing Wang committed
683 684 685
    max_row_offset =
        find_valid_row_offset(tile, mi_row, cm->mi_rows, cm, max_row_offset);
  }
686 687 688

  if (xd->left_available) {
    max_col_offset = -(MVREF_COLS << 1) + col_adj;
Yunqing Wang's avatar
Yunqing Wang committed
689 690
    max_col_offset = find_valid_col_offset(tile, mi_col, max_col_offset);
  }
691

692 693
  // Scan the first above row mode info. row_offset = -1;
  if (abs(max_row_offset) >= 1)
Yunqing Wang's avatar
Yunqing Wang committed
694 695
    newmv_count += scan_row_mbmi(cm, xd, mi_row, mi_col, block, rf, -1,
                                 ref_mv_stack, refmv_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)
Yunqing Wang's avatar
Yunqing Wang committed
702 703
    newmv_count += scan_col_mbmi(cm, xd, mi_row, mi_col, block, rf, -1,
                                 ref_mv_stack, refmv_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)
710
    newmv_count += scan_blk_mbmi(cm, xd, mi_row, mi_col, block, rf, -1,
711
                                 xd->n8_w, ref_mv_stack,
712
#if USE_CUR_GM_REFMV
713
                                 gm_mv_candidates,
714
#endif  // USE_CUR_GM_REFMV
715
                                 refmv_count);
716

717
  nearest_refmv_count = *refmv_count;
718

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

#if CONFIG_MFMV
723
  if (cm->use_ref_frame_mvs) {
724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746
    int blk_row, blk_col;
    int coll_blk_count = 0;
    int voffset = AOMMAX(mi_size_high[BLOCK_8X8], xd->n8_h);
    int hoffset = AOMMAX(mi_size_wide[BLOCK_8X8], xd->n8_w);

    int tpl_sample_pos[9][2] = {
      { -2, hoffset }, { 0, hoffset },  { voffset, hoffset },
      { voffset, 0 },  { voffset, -2 }, { voffset, -4 },
      { -4, hoffset }, { voffset, 4 },  { 2, hoffset + 4 },
    };
    int i;

    for (blk_row = 0; blk_row < xd->n8_h; blk_row += mi_size_high[BLOCK_8X8]) {
      for (blk_col = 0; blk_col < xd->n8_w;
           blk_col += mi_size_wide[BLOCK_8X8]) {
        // (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 (i = 0; i < 9; ++i) {
      blk_row = tpl_sample_pos[i][0];
      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 blk_row, blk_col;
772
    int coll_blk_count = 0;
773 774 775
    const int mi_step = (xd->n8_w == 1 || xd->n8_h == 1)
                            ? mi_size_wide[BLOCK_8X8]
                            : mi_size_wide[BLOCK_16X16];
776 777

#if CONFIG_TPL_MV
778 779
    // Modified sample positions to be consistent with frame_mvs
    // spatial resolution.
780 781 782 783 784 785 786 787
    int tpl_sample_pos[5][2] = { { -1, xd->n8_w },
                                 { 0, xd->n8_w },
                                 { xd->n8_h, xd->n8_w },
                                 { xd->n8_h, 0 },
                                 { xd->n8_h, -1 } };
    int i;
#endif

788 789
    for (blk_row = 0; blk_row < xd->n8_h; blk_row += mi_step) {
      for (blk_col = 0; blk_col < xd->n8_w; blk_col += mi_step) {
790 791 792 793 794 795 796 797 798 799 800
#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
801 802 803 804 805
#if CONFIG_OPT_REF_MV
        if (blk_row == 0 && blk_col == 0) coll_blk_count = is_available;
#else
        coll_blk_count += is_available;
#endif
806 807
      }
    }
808 809 810 811 812

#if CONFIG_TPL_MV
    for (i = 0; i < 5; ++i) {
      blk_row = tpl_sample_pos[i][0];
      blk_col = tpl_sample_pos[i][1];
813 814 815 816 817 818 819 820 821
#if CONFIG_TMV
      coll_blk_count += add_col_ref_mv(
          cm, prev_frame_mvs_base, prev_frame_mvs_stride, xd, tmi_row, tmi_col,
          ref_frame, blk_row, blk_col, refmv_count, ref_mv_stack, mode_context);
#else
      coll_blk_count += add_col_ref_mv(
          cm, prev_frame_mvs_base, prev_frame_mvs_stride, xd, mi_row, mi_col,
          ref_frame, blk_row, blk_col, refmv_count, ref_mv_stack, mode_context);
#endif  // CONFIG_TMV
822 823 824
    }
#endif