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

12
#include "av1/common/mvref_common.h"
Yue Chen's avatar
Yue Chen committed
13 14 15
#if CONFIG_WARPED_MOTION
#include "av1/common/warped_motion.h"
#endif  // CONFIG_WARPED_MOTION
Jingning Han's avatar
Jingning Han committed
16

17 18 19 20
#if CONFIG_GLOBAL_MOTION
#define USE_CUR_GM_REFMV 1
#endif  // CONFIG_GLOBAL_MOTION

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

54 55 56 57 58 59 60
static uint8_t add_ref_mv_candidate(
    const MODE_INFO *const candidate_mi, const MB_MODE_INFO *const candidate,
    const MV_REFERENCE_FRAME rf[2], uint8_t *refmv_count,
    CANDIDATE_MV *ref_mv_stack, const int use_hp, int len, int block,
#if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
    int_mv *gm_mv_candidates, const WarpedMotionParams *gm_params,
#endif  // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
61
    int col, int weight,
RogerZhou's avatar
RogerZhou committed
62
#if CONFIG_AMVR
Yunqing Wang's avatar
Yunqing Wang committed
63
    int is_integer,
RogerZhou's avatar
RogerZhou committed
64
#endif
Yunqing Wang's avatar
Yunqing Wang committed
65 66
    BLOCK_SIZE bsize, int mi_row, int mi_col, int subsampling_x,
    int subsampling_y) {
Jingning Han's avatar
Jingning Han committed
67 68
  int index = 0, ref;
  int newmv_count = 0;
69
  assert(weight % 2 == 0);
Yunqing Wang's avatar
Yunqing Wang committed
70 71 72 73 74 75 76
#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
77

Emil Keyder's avatar
Emil Keyder committed
78
  if (rf[1] == NONE_FRAME) {
Jingning Han's avatar
Jingning Han committed
79 80 81
    // single reference frame
    for (ref = 0; ref < 2; ++ref) {
      if (candidate->ref_frame[ref] == rf[0]) {
82
        int_mv this_refmv;
Yunqing Wang's avatar
Yunqing Wang committed
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 115 116 117 118
#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
119
#if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
120 121 122
          if (is_global_mv_block(candidate_mi, block, gm_params[rf[0]].wmtype))
            this_refmv = gm_mv_candidates[0];
          else
123
#endif  // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
124
            this_refmv = get_sub_block_mv(candidate_mi, ref, col, block);
RogerZhou's avatar
RogerZhou committed
125
#if CONFIG_AMVR
Yunqing Wang's avatar
Yunqing Wang committed
126
          lower_mv_precision(&this_refmv.as_mv, use_hp, is_integer);
RogerZhou's avatar
RogerZhou committed
127
#else
128
        lower_mv_precision(&this_refmv.as_mv, use_hp);
129
#endif  // CONFIG_AMVR
Yunqing Wang's avatar
Yunqing Wang committed
130 131 132
#if CONFIG_EXT_WARPED_MOTION
        }
#endif  // CONFIG_EXT_WARPED_MOTION
133

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

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

Jingning Han's avatar
Jingning Han committed
139 140 141
        // Add a new item to the list.
        if (index == *refmv_count) {
          ref_mv_stack[index].this_mv = this_refmv;
142 143
          ref_mv_stack[index].pred_diff[0] = av1_get_pred_diff_ctx(
              get_sub_block_pred_mv(candidate_mi, ref, col, block), this_refmv);
144
          ref_mv_stack[index].weight = weight * len;
Jingning Han's avatar
Jingning Han committed
145
          ++(*refmv_count);
146

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

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

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

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

      // Add a new item to the list.
      if (index == *refmv_count) {
        ref_mv_stack[index].this_mv = this_refmv[0];
        ref_mv_stack[index].comp_mv = this_refmv[1];
181 182 183 184
        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]);
185
        ref_mv_stack[index].weight = weight * len;
Jingning Han's avatar
Jingning Han committed
186 187
        ++(*refmv_count);

188
        if (candidate->mode == NEW_NEWMV) ++newmv_count;
Jingning Han's avatar
Jingning Han committed
189 190 191 192 193 194
      }
    }
  }
  return newmv_count;
}

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

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

    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
239 240 241
#if CONFIG_AMVR
    newmv_count += add_ref_mv_candidate(
        candidate_mi, candidate, rf, refmv_count, ref_mv_stack,
242 243 244 245
        cm->allow_high_precision_mv, len, block,
#if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
        gm_mv_candidates, cm->global_motion,
#endif  // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
246 247 248
        col_offset + i, weight, cm->cur_frame_mv_precision_level,
        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
249
#else
Yunqing Wang's avatar
Yunqing Wang committed
250 251 252
    newmv_count += add_ref_mv_candidate(
        candidate_mi, candidate, rf, refmv_count, ref_mv_stack,
        cm->allow_high_precision_mv, len, block,
253
#if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
254
        gm_mv_candidates, cm->global_motion,
255
#endif  // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
256 257
        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
258
#endif
259

Yunqing Wang's avatar
Yunqing Wang committed
260
    i += len;
261
  }
262 263

  return newmv_count;
264 265
}

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

Yunqing Wang's avatar
Yunqing Wang committed
287 288 289 290
  for (i = 0; i < end_mi && *refmv_count < MAX_REF_MV_STACK_SIZE;) {
    const MODE_INFO *const candidate_mi =
        xd->mi[(row_offset + i) * xd->mi_stride + col_offset];
    const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
291 292 293
    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
294 295 296 297
    if (use_step_16)
      len = AOMMAX(n8_h_16, len);
    else if (abs(col_offset) > 1)
      len = AOMMAX(len, n8_h_8);
298 299 300 301 302 303 304 305 306 307 308

    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
309 310 311
#if CONFIG_AMVR
    newmv_count += add_ref_mv_candidate(
        candidate_mi, candidate, rf, refmv_count, ref_mv_stack,
312 313 314 315
        cm->allow_high_precision_mv, len, block,
#if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
        gm_mv_candidates, cm->global_motion,
#endif  // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
316 317 318
        col_offset, weight, cm->cur_frame_mv_precision_level,
        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
319
#else
Yunqing Wang's avatar
Yunqing Wang committed
320 321 322
    newmv_count += add_ref_mv_candidate(
        candidate_mi, candidate, rf, refmv_count, ref_mv_stack,
        cm->allow_high_precision_mv, len, block,
323
#if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
324
        gm_mv_candidates, cm->global_motion,
325
#endif  // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
326 327
        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
328
#endif
Yunqing Wang's avatar
Yunqing Wang committed
329
    i += len;
330
  }
331 332

  return newmv_count;
333 334
}

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

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

350
  if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm, &mi_pos) &&
351
      *refmv_count < MAX_REF_MV_STACK_SIZE) {
352 353 354
    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;
355
    const int len = mi_size_wide[BLOCK_8X8];
356

RogerZhou's avatar
RogerZhou committed
357 358 359
#if CONFIG_AMVR
    newmv_count += add_ref_mv_candidate(
        candidate_mi, candidate, rf, refmv_count, ref_mv_stack,
360 361 362 363
        cm->allow_high_precision_mv, len, block,
#if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
        gm_mv_candidates, cm->global_motion,
#endif  // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
364 365 366
        mi_pos.col, 2, cm->cur_frame_mv_precision_level,
        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
367
#else
Yunqing Wang's avatar
Yunqing Wang committed
368 369 370
    newmv_count += add_ref_mv_candidate(
        candidate_mi, candidate, rf, refmv_count, ref_mv_stack,
        cm->allow_high_precision_mv, len, block,
371
#if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
372
        gm_mv_candidates, cm->global_motion,
373
#endif  // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
Yunqing Wang's avatar
Yunqing Wang committed
374 375
        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
376
#endif
377
  }  // Analyze a single 8x8 block motion information.
Yaowu Xu's avatar
Yaowu Xu committed
378

379
  return newmv_count;
380 381
}

382 383 384 385 386
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);
387

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

391 392
  // bs > 0 and bs is a power of 2
  assert(bs > 0 && !(bs & (bs - 1)));
393

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

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

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

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

427 428 429
  return has_tr;
}

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

  return 1;
}

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

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

472 473 474 475 476 477 478 479 480 481
  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);

482 483 484 485
        if (blk_row == 0 && blk_col == 0)
          if (abs(this_refmv.as_mv.row) >= 16 ||
              abs(this_refmv.as_mv.col) >= 16)
            mode_context[ref_frame] |= (1 << ZEROMV_OFFSET);
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 512 513 514 515 516 517

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

518 519 520 521 522 523
        if (blk_row == 0 && blk_col == 0)
          if (abs(this_refmv.as_mv.row) >= 16 ||
              abs(this_refmv.as_mv.col) >= 16 ||
              abs(comp_refmv.as_mv.row) >= 16 ||
              abs(comp_refmv.as_mv.col) >= 16)
            mode_context[ref_frame] |= (1 << ZEROMV_OFFSET);
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 551 552 553 554 555 556

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

576 577 578 579
#if CONFIG_TMV
  mi_pos.row = blk_row;
  mi_pos.col = blk_col;
#else
580 581 582 583
#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
584 585
  mi_pos.row = blk_row;
  mi_pos.col = blk_col;
586
#endif
587
#endif  // CONFIG_TMV
588

589
  if (!is_inside(&xd->tile, mi_col, mi_row, cm->mi_rows, cm, &mi_pos))
590
    return coll_blk_count;
591 592 593
  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
594 595 596 597
#if CONFIG_AMVR
      lower_mv_precision(&this_refmv.as_mv, cm->allow_high_precision_mv,
                         cm->cur_frame_mv_precision_level);
#else
598
      lower_mv_precision(&this_refmv.as_mv, cm->allow_high_precision_mv);
RogerZhou's avatar
RogerZhou committed
599
#endif
600 601 602 603 604 605 606 607

#if CONFIG_OPT_REF_MV
      if (blk_row == 0 && blk_col == 0)
#endif
      {
        if (abs(this_refmv.as_mv.row) >= 16 || abs(this_refmv.as_mv.col) >= 16)
          mode_context[ref_frame] |= (1 << ZEROMV_OFFSET);
      }
608 609 610 611

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

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

      if (idx == *refmv_count && *refmv_count < MAX_REF_MV_STACK_SIZE) {
        ref_mv_stack[idx].this_mv.as_int = this_refmv.as_int;
616 617
        ref_mv_stack[idx].pred_diff[0] =
            av1_get_pred_diff_ctx(prev_frame_mvs->pred_mv[ref], this_refmv);
618
        ref_mv_stack[idx].weight = 2 * weight_unit;
619 620 621 622 623 624 625 626 627
        ++(*refmv_count);
      }

      ++coll_blk_count;
    }
  }

  return coll_blk_count;
}
628
#endif
629

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

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

670
  const int bs = AOMMAX(xd->n8_w, xd->n8_h);
671
  const int has_tr = has_top_right(cm, xd, mi_row, mi_col, bs);
Jingning Han's avatar
Jingning Han committed
672 673
  MV_REFERENCE_FRAME rf[2];

Yunqing Wang's avatar
Yunqing Wang committed
674
  const TileInfo *const tile = &xd->tile;
675 676 677 678 679
  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
680 681
  int row_offset, col_offset;

682
  av1_set_ref_frame(rf, ref_frame);
683
  mode_context[ref_frame] = 0;
684
  *refmv_count = 0;
685

686 687 688
  // 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
689 690 691
    max_row_offset =
        find_valid_row_offset(tile, mi_row, cm->mi_rows, cm, max_row_offset);
  }
692 693 694

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

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

723
  nearest_refmv_count = *refmv_count;
724

725
  for (idx = 0; idx < nearest_refmv_count; ++idx)
726
    ref_mv_stack[idx].weight += REF_CAT_LEVEL;
727 728 729 730

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

  int tpl_sample_pos[9][2] = {
Jingning Han's avatar
Jingning Han committed
735 736 737
    { -2, hoffset }, { 0, hoffset },  { voffset, hoffset },
    { voffset, 0 },  { voffset, -2 }, { voffset, -4 },
    { -4, hoffset }, { voffset, 4 },  { 2, hoffset + 4 },
738 739 740
  };
  int i;

Jingning Han's avatar
Jingning Han committed
741 742
  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]) {
743 744
      // (TODO: yunqing) prev_frame_mvs_base is not used here, tpl_mvs is used.
      // Can be modified the same way.
745 746 747 748
      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;
749 750 751 752 753 754 755 756
    }
  }

  if (coll_blk_count == 0) mode_context[ref_frame] |= (1 << ZEROMV_OFFSET);

  for (i = 0; i < 9; ++i) {
    blk_row = tpl_sample_pos[i][0];
    blk_col = tpl_sample_pos[i][1];
757

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

#if CONFIG_TPL_MV
780 781
    // Modified sample positions to be consistent with frame_mvs
    // spatial resolution.
782 783 784 785 786 787 788 789
    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

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

#if CONFIG_TPL_MV
    for (i = 0; i < 5; ++i) {
      blk_row = tpl_sample_pos[i][0];
      blk_col = tpl_sample_pos[i][1];
815 816 817 818 819 820 821 822 823
#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
824 825 826
    }
#endif

827 828
    if (coll_blk_count == 0) mode_context[ref_frame] |= (1 << ZEROMV_OFFSET);
  } else {
829
    mode_context[ref_frame] |= (1 << ZEROMV_OFFSET);
830
  }
831
#endif
832

833
  // Scan the second outer area.
Deng's avatar
Deng committed
834
  scan_blk_mbmi(cm, xd, mi_row, mi_col, block, rf, -1, -1, ref_mv_stack,
835 836 837
#if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
                gm_mv_candidates,
#endif  // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
Deng's avatar
Deng committed
838
                refmv_count);
Yunqing Wang's avatar
Yunqing Wang committed
839
  for (idx = 2; idx <= MVREF_ROWS; ++idx) {
840 841
    row_offset = -(idx << 1) + 1 + row_adj;
    col_offset = -(idx << 1) + 1 + col_adj;
Yunqing Wang's avatar
Yunqing Wang committed
842

843 844
    if (abs(row_offset) <= abs(max_row_offset) &&
        abs(row_offset) > processed_rows)
Yunqing Wang's avatar
Yunqing Wang committed
845
      scan_row_mbmi(cm, xd, mi_row, mi_col, block, rf, row_offset, ref_mv_stack,
846 847 848 849 850
                    refmv_count,
#if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
                    gm_mv_candidates,
#endif  // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
                    max_row_offset, &processed_rows);
851 852 853

    if (abs(col_offset) <= abs(max_col_offset) &&
        abs(col_offset) > processed_cols)
Yunqing Wang's avatar
Yunqing Wang committed
854
      scan_col_mbmi(cm, xd, mi_row, mi_col, block, rf, col_offset, ref_mv_stack,
855 856 857 858 859
                    refmv_count,
#if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
                    gm_mv_candidates,
#endif  // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
                    max_col_offset, &processed_cols);
Yunqing Wang's avatar
Yunqing Wang committed
860 861
  }

862 863 864
  col_offset = -(MVREF_COLS << 1) + 1 + col_adj;
  if (abs(col_offset) <= abs(max_col_offset) &&
      abs(col_offset) > processed_cols)
Yunqing Wang's avatar
Yunqing Wang committed
865
    scan_col_mbmi(cm, xd, mi_row, mi_col, block, rf, col_offset, ref_mv_stack,
866 867 868 869 870
                  refmv_count,
#if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
                  gm_mv_candidates,
#endif  // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
                  max_col_offset, &processed_cols);
871

872
  switch (nearest_refmv_count) {
873 874
    case 0: mode_context[ref_frame] |= 0;
#if !CONFIG_OPT_REF_MV
clang-format's avatar
clang-format committed
875
      if (*refmv_count >= 1) mode_context[ref_frame] |= 1;
876 877 878 879
      if (*refmv_count == 1)
        mode_context[ref_frame] |= (1 << REFMV_OFFSET);
      else if (*refmv_count >= 2)
        mode_context[ref_frame] |= (2 << REFMV_OFFSET);
880
#endif
881
      break;
882 883 884 885
    case 1: mode_context[ref_frame] |= (newmv_count > 0) ? 2 : 3;
#if CONFIG_OPT_REF_MV
      mode_context[ref_frame] |= (3 << REFMV_OFFSET);
#else
886 887 888 889
      if (*refmv_count == 1)
        mode_context[ref_frame] |= (3 << REFMV_OFFSET);
      else if (*refmv_count >= 2)
        mode_context[ref_frame] |= (4 << REFMV_OFFSET);
890
#endif
891 892 893 894 895 896 897 898 899 900 901 902 903 904 905
      break;

    case 2:
    default:
      if (newmv_count >= 2)
        mode_context[ref_frame] |= 4;
      else if (newmv_count == 1)
        mode_context[ref_frame] |= 5;
      else
        mode_context[ref_frame] |= 6;

      mode_context[ref_frame] |= (5 << REFMV_OFFSET);
      break;
  }

906 907 908 909 910 911 912 913 914 915 916 917 918 919 920
  // Rank the likelihood and assign nearest and near mvs.
  len = nearest_refmv_count;
  while (len > 0) {
    nr_len = 0;
    for (idx = 1; idx < len; ++idx) {
      if (ref_mv_stack[idx - 1].weight < ref_mv_stack[idx].weight) {
        tmp_mv = ref_mv_stack[idx - 1];
        ref_mv_stack[idx - 1] = ref_mv_stack[idx];
        ref_mv_stack[idx] = tmp_mv;
        nr_len = idx;
      }
    }
    len = nr_len;
  }

921
  len = *refmv_count;
922 923 924 925 926 927 928 929 930 931 932 933 934
  while (len > nearest_refmv_count) {
    nr_len = nearest_refmv_count;
    for (idx = nearest_refmv_count + 1; idx < len; ++idx) {
      if (ref_mv_stack[idx - 1].weight < ref_mv_stack[idx].weight) {
        tmp_mv = ref_mv_stack[idx - 1];
        ref_mv_stack[idx - 1] = ref_mv_stack[idx];
        ref_mv_stack[idx] = tmp_mv;
        nr_len = idx;
      }
    }
    len = nr_len;
  }

Emil Keyder's avatar
Emil Keyder committed
935
  if (rf[1] > NONE_FRAME) {
936
    for (idx = 0; idx < *refmv_count; ++idx) {
937 938 939 940
      clamp_mv_ref(&ref_mv_stack[idx].this_mv.as_mv, xd->n8_w << MI_SIZE_LOG2,
                   xd->n8_h << MI_SIZE_LOG2, xd);
      clamp_mv_ref(&ref_mv_stack[idx].comp_mv.as_mv, xd->n8_w << MI_SIZE_LOG2,
                   xd->n8_h << MI_SIZE_LOG2, xd);
941 942
    }
  } else {
Yaowu Xu's avatar
Yaowu Xu committed
943
    for (idx = 0; idx < AOMMIN(MAX_MV_REF_CANDIDATES, *refmv_count); ++idx) {
944
      mv_ref_list[idx].as_int = ref_mv_stack[idx].this_mv.as_int;
945 946
      clamp_mv_ref(&mv_ref_list[idx].as_mv, xd->n8_w << MI_SIZE_LOG2,
                   xd->n8_h << MI_SIZE_LOG2, xd);
947
    }
948 949 950
  }
}

Jingning Han's avatar
Jingning Han committed
951 952
// This function searches the neighbourhood of a given MB/SB
// to try and find candidate reference vectors.