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

12
#include "av1/common/mvref_common.h"
Yue Chen's avatar
Yue Chen committed
13
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
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
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) {
#if CONFIG_TMV
  const int frame_mvs_stride = ROUND_POWER_OF_TWO(cm->mi_cols, 1);
  MV_REF *frame_mvs = cm->cur_frame->mvs +
                      ((mi_row & 0xfffe) >> 1) * frame_mvs_stride +
                      ((mi_col & 0xfffe) >> 1);
  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++) {
    MV_REF *const frame_mv = frame_mvs + h * frame_mvs_stride;
    for (w = 0; w < x_mis; w++) {
      MV_REF *const mv = frame_mv + 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;
    }
  }
}

50
51
52
53
54
55
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,
RogerZhou's avatar
RogerZhou committed
56
57
58
59
60
61
                                    int col, int weight
#if CONFIG_AMVR
                                    ,
                                    int is_integer
#endif
                                    ) {
Jingning Han's avatar
Jingning Han committed
62
63
  int index = 0, ref;
  int newmv_count = 0;
64
65
66
67
68
#if CONFIG_CB4X4
  const int unify_bsize = 1;
#else
  const int unify_bsize = 0;
#endif
69
  assert(weight % 2 == 0);
Jingning Han's avatar
Jingning Han committed
70

Emil Keyder's avatar
Emil Keyder committed
71
  if (rf[1] == NONE_FRAME) {
Jingning Han's avatar
Jingning Han committed
72
73
74
    // single reference frame
    for (ref = 0; ref < 2; ++ref) {
      if (candidate->ref_frame[ref] == rf[0]) {
clang-format's avatar
clang-format committed
75
        int_mv this_refmv = get_sub_block_mv(candidate_mi, ref, col, block);
RogerZhou's avatar
RogerZhou committed
76
77
78
#if CONFIG_AMVR
        lower_mv_precision(&this_refmv.as_mv, use_hp, is_integer);
#else
79
        lower_mv_precision(&this_refmv.as_mv, use_hp);
RogerZhou's avatar
RogerZhou committed
80
#endif
81

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

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

Jingning Han's avatar
Jingning Han committed
87
88
89
        // Add a new item to the list.
        if (index == *refmv_count) {
          ref_mv_stack[index].this_mv = this_refmv;
90
91
          ref_mv_stack[index].pred_diff[0] = av1_get_pred_diff_ctx(
              get_sub_block_pred_mv(candidate_mi, ref, col, block), this_refmv);
92
          ref_mv_stack[index].weight = weight * len;
Jingning Han's avatar
Jingning Han committed
93
          ++(*refmv_count);
94

95
          if (candidate->mode == NEWMV) ++newmv_count;
Jingning Han's avatar
Jingning Han committed
96
97
        }

98
99
        if (candidate_mi->mbmi.sb_type < BLOCK_8X8 && block >= 0 &&
            !unify_bsize) {
Jingning Han's avatar
Jingning Han committed
100
          int alt_block = 3 - block;
clang-format's avatar
clang-format committed
101
          this_refmv = get_sub_block_mv(candidate_mi, ref, col, alt_block);
RogerZhou's avatar
RogerZhou committed
102
103
104
#if CONFIG_AMVR
          lower_mv_precision(&this_refmv.as_mv, use_hp, is_integer);
#else
105
          lower_mv_precision(&this_refmv.as_mv, use_hp);
RogerZhou's avatar
RogerZhou committed
106
#endif
107
          for (index = 0; index < *refmv_count; ++index)
clang-format's avatar
clang-format committed
108
            if (ref_mv_stack[index].this_mv.as_int == this_refmv.as_int) break;
109

Yaowu Xu's avatar
Yaowu Xu committed
110
          if (index < *refmv_count) ref_mv_stack[index].weight += len;
111
112
113
114

          // Add a new item to the list.
          if (index == *refmv_count) {
            ref_mv_stack[index].this_mv = this_refmv;
115
116
117
            ref_mv_stack[index].pred_diff[0] = av1_get_pred_diff_ctx(
                get_sub_block_pred_mv(candidate_mi, ref, col, alt_block),
                this_refmv);
Yaowu Xu's avatar
Yaowu Xu committed
118
            ref_mv_stack[index].weight = len;
119
            ++(*refmv_count);
120

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

131
132
      for (ref = 0; ref < 2; ++ref) {
        this_refmv[ref] = get_sub_block_mv(candidate_mi, ref, col, block);
RogerZhou's avatar
RogerZhou committed
133
134
135
136

#if CONFIG_AMVR
        lower_mv_precision(&this_refmv[ref].as_mv, use_hp, is_integer);
#else
137
        lower_mv_precision(&this_refmv[ref].as_mv, use_hp);
RogerZhou's avatar
RogerZhou committed
138
#endif
139
      }
140

Jingning Han's avatar
Jingning Han committed
141
142
143
144
145
      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;

146
      if (index < *refmv_count) ref_mv_stack[index].weight += weight * len;
Jingning Han's avatar
Jingning Han committed
147
148
149
150
151

      // 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];
152
153
154
155
        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]);
156
        ref_mv_stack[index].weight = weight * len;
Jingning Han's avatar
Jingning Han committed
157
158
        ++(*refmv_count);

159
        if (candidate->mode == NEW_NEWMV) ++newmv_count;
Jingning Han's avatar
Jingning Han committed
160
161
      }

162
163
      if (candidate_mi->mbmi.sb_type < BLOCK_8X8 && block >= 0 &&
          !unify_bsize) {
Jingning Han's avatar
Jingning Han committed
164
165
166
167
        int alt_block = 3 - block;
        this_refmv[0] = get_sub_block_mv(candidate_mi, 0, col, alt_block);
        this_refmv[1] = get_sub_block_mv(candidate_mi, 1, col, alt_block);

RogerZhou's avatar
RogerZhou committed
168
169
170
171
        for (ref = 0; ref < 2; ++ref) {
#if CONFIG_AMVR
          lower_mv_precision(&this_refmv[ref].as_mv, use_hp, is_integer);
#else
172
          lower_mv_precision(&this_refmv[ref].as_mv, use_hp);
RogerZhou's avatar
RogerZhou committed
173
174
#endif
        }
Jingning Han's avatar
Jingning Han committed
175
176
177
178
179
        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;

Yaowu Xu's avatar
Yaowu Xu committed
180
        if (index < *refmv_count) ref_mv_stack[index].weight += len;
Jingning Han's avatar
Jingning Han committed
181
182
183
184
185

        // 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];
186
187
188
189
190
191
          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[0] = av1_get_pred_diff_ctx(
              get_sub_block_pred_mv(candidate_mi, 1, col, block),
              this_refmv[1]);
Yaowu Xu's avatar
Yaowu Xu committed
192
          ref_mv_stack[index].weight = len;
Jingning Han's avatar
Jingning Han committed
193
194
          ++(*refmv_count);

195
          if (candidate->mode == NEW_NEWMV) ++newmv_count;
Jingning Han's avatar
Jingning Han committed
196
197
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,
Yunqing Wang's avatar
Yunqing Wang committed
204
                             const int mi_col, int block,
clang-format's avatar
clang-format committed
205
                             const MV_REFERENCE_FRAME rf[2], int row_offset,
206
207
                             CANDIDATE_MV *ref_mv_stack, uint8_t *refmv_count,
                             int max_row_offset, int *processed_rows) {
Yunqing Wang's avatar
Yunqing Wang committed
208
  const int end_mi = AOMMIN(xd->n8_w, cm->mi_cols - mi_col);
209
210
  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
211
212
  int i;
  uint8_t newmv_count = 0;
213
  int col_offset = 0;
214
#if CONFIG_CB4X4
215
  const int shift = 0;
216
  // TODO(jingning): Revisit this part after cb4x4 is stable.
217
218
  if (abs(row_offset) > 1) {
    col_offset = 1;
219
    if (mi_col & 0x01 && xd->n8_w < n8_w_8) --col_offset;
220
  }
Yunqing Wang's avatar
Yunqing Wang committed
221
  const int use_step_16 = (xd->n8_w >= 16);
222
#else
223
  const int shift = 1;
Yunqing Wang's avatar
Yunqing Wang committed
224
  const int use_step_16 = (xd->n8_w >= 8);
225
#endif
Yunqing Wang's avatar
Yunqing Wang committed
226
  MODE_INFO **const candidate_mi0 = xd->mi + row_offset * xd->mi_stride;
Jingning Han's avatar
Jingning Han committed
227

Yunqing Wang's avatar
Yunqing Wang committed
228
229
230
  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;
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
251
252
253
254
#if CONFIG_AMVR
    newmv_count += add_ref_mv_candidate(
        candidate_mi, candidate, rf, refmv_count, ref_mv_stack,
        cm->allow_high_precision_mv, len, block, col_offset + i, weight,
        cm->cur_frame_mv_precision_level);
#else
Yunqing Wang's avatar
Yunqing Wang committed
255
256
    newmv_count += add_ref_mv_candidate(
        candidate_mi, candidate, rf, refmv_count, ref_mv_stack,
257
        cm->allow_high_precision_mv, len, block, col_offset + i, weight);
RogerZhou's avatar
RogerZhou committed
258
#endif
Yunqing Wang's avatar
Yunqing Wang committed
259
    i += len;
260
  }
261
262

  return newmv_count;
263
264
}

Yaowu Xu's avatar
Yaowu Xu committed
265
static uint8_t scan_col_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
Yunqing Wang's avatar
Yunqing Wang committed
266
                             const int mi_row, int block,
clang-format's avatar
clang-format committed
267
                             const MV_REFERENCE_FRAME rf[2], int col_offset,
268
269
                             CANDIDATE_MV *ref_mv_stack, uint8_t *refmv_count,
                             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
#if CONFIG_CB4X4
277
  const int shift = 0;
278
279
  if (abs(col_offset) > 1) {
    row_offset = 1;
280
    if (mi_row & 0x01 && xd->n8_h < n8_h_8) --row_offset;
281
  }
Yunqing Wang's avatar
Yunqing Wang committed
282
  const int use_step_16 = (xd->n8_h >= 16);
283
#else
284
  const int shift = 1;
Yunqing Wang's avatar
Yunqing Wang committed
285
  const int use_step_16 = (xd->n8_h >= 8);
286
#endif
287

Yunqing Wang's avatar
Yunqing Wang committed
288
289
290
291
  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;
292
293
294
    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
295
296
297
298
    if (use_step_16)
      len = AOMMAX(n8_h_16, len);
    else if (abs(col_offset) > 1)
      len = AOMMAX(len, n8_h_8);
299
300
301
302
303
304
305
306
307
308
309

    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
310
311
312
313
314
315
#if CONFIG_AMVR
    newmv_count += add_ref_mv_candidate(
        candidate_mi, candidate, rf, refmv_count, ref_mv_stack,
        cm->allow_high_precision_mv, len, block, col_offset, weight,
        cm->cur_frame_mv_precision_level);
#else
Yunqing Wang's avatar
Yunqing Wang committed
316
317
    newmv_count += add_ref_mv_candidate(
        candidate_mi, candidate, rf, refmv_count, ref_mv_stack,
318
        cm->allow_high_precision_mv, len, block, col_offset, weight);
RogerZhou's avatar
RogerZhou committed
319
#endif
Yunqing Wang's avatar
Yunqing Wang committed
320
    i += len;
321
  }
322
323

  return newmv_count;
324
325
}

Yaowu Xu's avatar
Yaowu Xu committed
326
static uint8_t scan_blk_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
327
                             const int mi_row, const int mi_col, int block,
clang-format's avatar
clang-format committed
328
329
                             const MV_REFERENCE_FRAME rf[2], int row_offset,
                             int col_offset, CANDIDATE_MV *ref_mv_stack,
330
                             uint8_t *refmv_count) {
331
332
  const TileInfo *const tile = &xd->tile;
  POSITION mi_pos;
333
  uint8_t newmv_count = 0;
334
335
336
337

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

338
  if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm, &mi_pos) &&
339
      *refmv_count < MAX_REF_MV_STACK_SIZE) {
340
341
342
    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;
343
    const int len = mi_size_wide[BLOCK_8X8];
344

RogerZhou's avatar
RogerZhou committed
345
346
347
348
349
350
#if CONFIG_AMVR
    newmv_count += add_ref_mv_candidate(
        candidate_mi, candidate, rf, refmv_count, ref_mv_stack,
        cm->allow_high_precision_mv, len, block, mi_pos.col, 2,
        cm->cur_frame_mv_precision_level);
#else
clang-format's avatar
clang-format committed
351
352
    newmv_count += add_ref_mv_candidate(
        candidate_mi, candidate, rf, refmv_count, ref_mv_stack,
353
        cm->allow_high_precision_mv, len, block, mi_pos.col, 2);
RogerZhou's avatar
RogerZhou committed
354
#endif
355
  }  // Analyze a single 8x8 block motion information.
Yaowu Xu's avatar
Yaowu Xu committed
356

357
  return newmv_count;
358
359
}

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

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

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

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

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

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

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

405
406
407
  return has_tr;
}

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

  return 1;
}

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

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

450
451
452
453
454
455
456
457
458
459
  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);

460
461
462
463
        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);
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495

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

496
497
498
499
500
501
        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);
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534

        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
535
536
static int add_col_ref_mv(const AV1_COMMON *cm,
                          const MV_REF *prev_frame_mvs_base,
537
538
539
                          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,
540
                          CANDIDATE_MV *ref_mv_stack, int16_t *mode_context) {
541
542
543
544
545
#if CONFIG_TMV
  const MV_REF *prev_frame_mvs = prev_frame_mvs_base +
                                 ((blk_row + 1) >> 1) * prev_frame_mvs_stride +
                                 ((blk_col + 1) >> 1);
#else
546
  const MV_REF *prev_frame_mvs =
547
548
      prev_frame_mvs_base + blk_row * prev_frame_mvs_stride + blk_col;
#endif
549
550
551
  POSITION mi_pos;
  int ref, idx;
  int coll_blk_count = 0;
552
  const int weight_unit = mi_size_wide[BLOCK_8X8];
553

554
555
556
557
#if CONFIG_TMV
  mi_pos.row = blk_row;
  mi_pos.col = blk_col;
#else
558
559
560
561
#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
562
563
  mi_pos.row = blk_row;
  mi_pos.col = blk_col;
564
#endif
565
#endif  // CONFIG_TMV
566

567
  if (!is_inside(&xd->tile, mi_col, mi_row, cm->mi_rows, cm, &mi_pos))
568
    return coll_blk_count;
569
570
571
  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
572
573
574
575
#if CONFIG_AMVR
      lower_mv_precision(&this_refmv.as_mv, cm->allow_high_precision_mv,
                         cm->cur_frame_mv_precision_level);
#else
576
      lower_mv_precision(&this_refmv.as_mv, cm->allow_high_precision_mv);
RogerZhou's avatar
RogerZhou committed
577
#endif
578
579
580
581
582
583
584
585

#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);
      }
586
587
588
589

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

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

      if (idx == *refmv_count && *refmv_count < MAX_REF_MV_STACK_SIZE) {
        ref_mv_stack[idx].this_mv.as_int = this_refmv.as_int;
594
595
        ref_mv_stack[idx].pred_diff[0] =
            av1_get_pred_diff_ctx(prev_frame_mvs->pred_mv[ref], this_refmv);
596
        ref_mv_stack[idx].weight = 2 * weight_unit;
597
598
599
600
601
602
603
604
605
        ++(*refmv_count);
      }

      ++coll_blk_count;
    }
  }

  return coll_blk_count;
}
606
#endif
607

Yaowu Xu's avatar
Yaowu Xu committed
608
static void setup_ref_mv_list(const AV1_COMMON *cm, const MACROBLOCKD *xd,
609
                              MV_REFERENCE_FRAME ref_frame,
clang-format's avatar
clang-format committed
610
611
612
                              uint8_t *refmv_count, CANDIDATE_MV *ref_mv_stack,
                              int_mv *mv_ref_list, int block, int mi_row,
                              int mi_col, int16_t *mode_context) {
613
  int idx, nearest_refmv_count = 0;
614
  uint8_t newmv_count = 0;
615
616
617
  CANDIDATE_MV tmp_mv;
  int len, nr_len;

618
619
620
621
622
623
624
625
626
627
628
#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;
629
630
631
#if CONFIG_MV_COMPRESS
  const MV_REF *const prev_frame_mvs_base =
      cm->use_prev_frame_mvs
632
633
          ? cm->prev_frame->mvs +
                (((mi_row >> 1) << 1) + 1) * prev_frame_mvs_stride +
634
635
636
                ((mi_col >> 1) << 1) + 1
          : NULL;
#else
clang-format's avatar
clang-format committed
637
638
  const MV_REF *const prev_frame_mvs_base =
      cm->use_prev_frame_mvs
639
          ? cm->prev_frame->mvs + mi_row * prev_frame_mvs_stride + mi_col
clang-format's avatar
clang-format committed
640
          : NULL;
641
#endif
642
#endif  // CONFIG_TMV
643

644
  const int bs = AOMMAX(xd->n8_w, xd->n8_h);
645
  const int has_tr = has_top_right(cm, xd, mi_row, mi_col, bs);
Jingning Han's avatar
Jingning Han committed
646
647
  MV_REFERENCE_FRAME rf[2];

Yunqing Wang's avatar
Yunqing Wang committed
648
  const TileInfo *const tile = &xd->tile;
649
  int max_row_offset = 0, max_col_offset = 0;
Yunqing Wang's avatar
Yunqing Wang committed
650
#if CONFIG_CB4X4
651
652
  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);
Yunqing Wang's avatar
Yunqing Wang committed
653
#endif
654
655
  int processed_rows = 0;
  int processed_cols = 0;
Yunqing Wang's avatar
Yunqing Wang committed
656
657
  int row_offset, col_offset;

658
  av1_set_ref_frame(rf, ref_frame);
659
  mode_context[ref_frame] = 0;
660
  *refmv_count = 0;
661

662
663
664
665
666
667
668
  // Find valid maximum row/col offset.
  if (xd->up_available) {
#if CONFIG_CB4X4
    max_row_offset = -(MVREF_ROWS << 1) + row_adj;
#else
    max_row_offset = -MVREF_ROWS;
#endif
Yunqing Wang's avatar
Yunqing Wang committed
669
670
671
    max_row_offset =
        find_valid_row_offset(tile, mi_row, cm->mi_rows, cm, max_row_offset);
  }
672
673
674
675
676
677
678

  if (xd->left_available) {
#if CONFIG_CB4X4
    max_col_offset = -(MVREF_COLS << 1) + col_adj;
#else
    max_col_offset = -MVREF_COLS;
#endif
Yunqing Wang's avatar
Yunqing Wang committed
679
680
    max_col_offset = find_valid_col_offset(tile, mi_col, max_col_offset);
  }
681

682
683
684
685
686
687
688
689
  // Scan the first above row mode info. row_offset = -1;
  if (abs(max_row_offset) >= 1)
    newmv_count += scan_row_mbmi(cm, xd, mi_col, block, rf, -1, ref_mv_stack,
                                 refmv_count, max_row_offset, &processed_rows);
  // Scan the first left column mode info. col_offset = -1;
  if (abs(max_col_offset) >= 1)
    newmv_count += scan_col_mbmi(cm, xd, mi_row, block, rf, -1, ref_mv_stack,
                                 refmv_count, max_col_offset, &processed_cols);
690
691
  // Check top-right boundary
  if (has_tr)
692
693
    newmv_count += scan_blk_mbmi(cm, xd, mi_row, mi_col, block, rf, -1,
                                 xd->n8_w, ref_mv_stack, refmv_count);
694

695
  nearest_refmv_count = *refmv_count;
696

697
  for (idx = 0; idx < nearest_refmv_count; ++idx)
698
    ref_mv_stack[idx].weight += REF_CAT_LEVEL;
699
700
701
702

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

  int tpl_sample_pos[9][2] = {
Jingning Han's avatar
Jingning Han committed
707
708
709
    { -2, hoffset }, { 0, hoffset },  { voffset, hoffset },
    { voffset, 0 },  { voffset, -2 }, { voffset, -4 },
    { -4, hoffset }, { voffset, 4 },  { 2, hoffset + 4 },
710
711
712
  };
  int i;

Jingning Han's avatar
Jingning Han committed
713
714
  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]) {
715
716
      // (TODO: yunqing) prev_frame_mvs_base is not used here, tpl_mvs is used.
      // Can be modified the same way.
717
718
719
720
      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;
721
722
723
724
725
726
727
728
    }
  }

  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];
729

730
    if (!check_sb_border(cm, mi_row, mi_col, blk_row, blk_col)) continue;
731
732
    // (TODO: yunqing) prev_frame_mvs_base is not used here, tpl_mvs is used.
    // Can be modified the same way.
733
734
735
736
737
    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
738
#if CONFIG_TEMPMV_SIGNALING
739
  if (cm->use_prev_frame_mvs && rf[1] == NONE_FRAME)
740
#else
clang-format's avatar
clang-format committed
741
  if (prev_frame_mvs_base && cm->show_frame && cm->last_show_frame &&
742
      rf[1] == NONE_FRAME)
743
#endif
744
  {
745
    int blk_row, blk_col;
746
    int coll_blk_count = 0;
747
748
749
750
751
#if CONFIG_CB4X4
    const int mi_step = (xd->n8_w == 1 || xd->n8_h == 1)
                            ? mi_size_wide[BLOCK_8X8]
                            : mi_size_wide[BLOCK_16X16];
#else
752
    const int mi_step = mi_size_wide[BLOCK_16X16];
753
#endif
754
755

#if CONFIG_TPL_MV
756
757
    // Modified sample positions to be consistent with frame_mvs
    // spatial resolution.
758
759
760
761
762
763
764
765
    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

766
767
    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) {
768
769
770
771
772
773
774
775
776
777
778
#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
779
780
781
782
783
#if CONFIG_OPT_REF_MV
        if (blk_row == 0 && blk_col == 0) coll_blk_count = is_available;
#else
        coll_blk_count += is_available;
#endif
784
785
      }
    }
786
787
788
789
790

#if CONFIG_TPL_MV
    for (i = 0; i < 5; ++i) {
      blk_row = tpl_sample_pos[i][0];
      blk_col = tpl_sample_pos[i][1];
791
792
793
794
795
796
797
798
799
#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
800
801
802
    }
#endif

803
804
    if (coll_blk_count == 0) mode_context[ref_frame] |= (1 << ZEROMV_OFFSET);
  } else {
805
    mode_context[ref_frame] |= (1 << ZEROMV_OFFSET);
806
  }
807
#endif
808

809
  // Scan the second outer area.
Deng's avatar
Deng committed
810
811
  scan_blk_mbmi(cm, xd, mi_row, mi_col, block, rf, -1, -1, ref_mv_stack,
                refmv_count);
Yunqing Wang's avatar
Yunqing Wang committed
812
813
  for (idx = 2; idx <= MVREF_ROWS; ++idx) {
#if CONFIG_CB4X4
814
815
    row_offset = -(idx << 1) + 1 + row_adj;
    col_offset = -(idx << 1) + 1 + col_adj;
Yunqing Wang's avatar
Yunqing Wang committed
816
#else
817
818
    row_offset = -idx;
    col_offset = -idx;
Yunqing Wang's avatar
Yunqing Wang committed
819
820
#endif

821
822
823
824
825
826
827
828
829
    if (abs(row_offset) <= abs(max_row_offset) &&
        abs(row_offset) > processed_rows)
      scan_row_mbmi(cm, xd, mi_col, block, rf, row_offset, ref_mv_stack,
                    refmv_count, max_row_offset, &processed_rows);

    if (abs(col_offset) <= abs(max_col_offset) &&
        abs(col_offset) > processed_cols)
      scan_col_mbmi(cm, xd, mi_row, block, rf, col_offset, ref_mv_stack,
                    refmv_count, max_col_offset, &processed_cols);
Yunqing Wang's avatar
Yunqing Wang committed
830
831
832
  }

#if CONFIG_CB4X4
833
  col_offset = -(MVREF_COLS << 1) + 1 + col_adj;
Yunqing Wang's avatar
Yunqing Wang committed
834
#else
835
  col_offset = -MVREF_COLS;
Yunqing Wang's avatar
Yunqing Wang committed
836
#endif
837
838
839
840
  if (abs(col_offset) <= abs(max_col_offset) &&
      abs(col_offset) > processed_cols)
    scan_col_mbmi(cm, xd, mi_row, block, rf, col_offset, ref_mv_stack,
                  refmv_count, max_col_offset, &processed_cols);
841

842
843
844
  switch (nearest_refmv_count) {
    case 0:
      mode_context[ref_frame] |= 0;
clang-format's avatar
clang-format committed
845
      if (*refmv_count >= 1) mode_context[ref_frame] |= 1;
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873

      if (*refmv_count == 1)
        mode_context[ref_frame] |= (1 << REFMV_OFFSET);
      else if (*refmv_count >= 2)
        mode_context[ref_frame] |= (2 << REFMV_OFFSET);
      break;
    case 1:
      mode_context[ref_frame] |= (newmv_count > 0) ? 2 : 3;

      if (*refmv_count == 1)
        mode_context[ref_frame] |= (3 << REFMV_OFFSET);
      else if (*refmv_count >= 2)
        mode_context[ref_frame] |= (4 << REFMV_OFFSET);
      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;
  }

874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
  // 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;
  }

889
  len = *refmv_count;
890
891
892
893
894
895
896
897
898
899
900
901
902
  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
903
  if (rf[1] > NONE_FRAME) {
904
    for (idx = 0; idx < *refmv_count; ++idx) {
905
906
907
908
      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);
909
910
    }
  } else {
Yaowu Xu's avatar
Yaowu Xu committed
911
    for (idx = 0; idx < AOMMIN(MAX_MV_REF_CANDIDATES, *refmv_count); ++idx) {
912
      mv_ref_list[idx].as_int = ref_mv_stack[idx].this_mv.as_int;
913
914
      clamp_mv_ref(&mv_ref_list[idx].as_mv, xd->n8_w << MI_SIZE_LOG2,
                   xd->n8_h << MI_SIZE_LOG2, xd);
915
    }
916
917
918
  }
}

Jingning Han's avatar
Jingning Han committed
919
920
// This function searches the neighbourhood of a given MB/SB
// to try and find candidate reference vectors.
Yaowu Xu's avatar
Yaowu Xu committed
921
static void find_mv_refs_idx(const AV1_COMMON *cm, const MACROBLOCKD *xd,
Jingning Han's avatar
Jingning Han committed
922
                             MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame,
clang-format's avatar
clang-format committed
923
924
                             int_mv *mv_ref_list, int block, int mi_row,
                             int mi_col, find_mv_refs_sync sync,
925
926
                             void *const data, int16_t *mode_context,
                             int_mv zeromv) {
Jingning Han's avatar
Jingning Han committed
927
  const int *ref_sign_bias = cm->ref_frame_sign_bias;
928
  const int sb_mi_size = mi_size_wide[cm->sb_size];
Jingning Han's avatar
Jingning Han committed
929
930
931
  int i, refmv_count = 0;
  int different_ref_found = 0;
  int context_counter = 0;
932
933
934
935
936
937
938
939
940
941
942
943

#if CONFIG_TMV
  int tmi_row = mi_row & 0xfffe;
  int tmi_col = mi_col & 0xfffe;
  POSITION mi_pos = { 0, 0 };
  int inside = is_inside(&xd->tile, tmi_col, tmi_row, cm->mi_rows, cm, &mi_pos);
  const MV_REF *const prev_frame_mvs =
      cm->use_prev_frame_mvs && inside
          ? cm->prev_frame->mvs + (tmi_row >> 1) * ((cm->mi_cols + 1) >> 1) +
                (tmi_col >> 1)
          : NULL;
#else
944
945
946
947
948
949
950
951
952
953
954
955
956
957
#if CONFIG_MV_COMPRESS
  const TileInfo *const tile_ = &xd->tile;
  int mi_row_end = tile_->mi_row_end;
  int mi_col_end = tile_->mi_col_end;
  const MV_REF *const prev_frame_mvs =
      cm->use_prev_frame_mvs
          ? cm->prev_frame->mvs +
                AOMMIN(((mi_row >> 1) << 1) + 1 + (((xd->n8_h - 1) >> 1) << 1),
                       mi_row_end - 1) *
                    cm->mi_cols +
                AOMMIN(((mi_col >> 1) << 1) + 1 + (((xd->n8_w - 1) >> 1) << 1),
                       mi_col_end - 1)
          : NULL;
#else
clang-format's avatar
clang-format committed
958
959
960
961
  const MV_REF *const prev_frame_mvs =
      cm->use_prev_frame_mvs
          ? cm->prev_frame->mvs + mi_row * cm->mi_cols + mi_col
          : NULL;
962
#endif
963
964
#endif  // CONFIG_TMV

965
966
#if CONFIG_INTRABC
  assert(IMPLIES(ref_frame == INTRA_FRAME, cm->use_prev_frame_mvs == 0));
967
#endif
Jingning Han's avatar
Jingning Han committed
968
  const TileInfo *const tile = &xd->tile;
969
970
971
  const BLOCK_SIZE bsize = mi->mbmi.sb_type;
  const int bw = block_size_wide[AOMMAX(bsize, BLOCK_8X8)];
  const int bh = block_size_high[AOMMAX(bsize, BLOCK_8X8)];
Deng's avatar
Deng committed
972
  POSITION mv_ref_search[MVREF_NEIGHBOURS];
973
974
  const int num_8x8_blocks_wide = num_8x8_blocks_wide_lookup[bsize];
  const int num_8x8_blocks_high = num_8x8_blocks_high_lookup[bsize];
Deng's avatar
Deng committed
975
976
977
978
979
980
981
982
983
984
  mv_ref_search[0].row = num_8x8_blocks_high - 1;
  mv_ref_search[0].col = -1;
  mv_ref_search[1].row = -1;
  mv_ref_search[1].col = num_8x8_blocks_wide - 1;
  mv_ref_search[2].row = -1;
  mv_ref_search[2].col = (num_8x8_blocks_wide - 1) >> 1;
  mv_ref_search[3].row = (num_8x8_blocks_high - 1) >> 1;
  mv_ref_search[3].col = -1;
  mv_ref_search[4].row = -1;
  mv_ref_search[4].col = -1;
985
986
987
988
989
990
991
992
993
994
995
996
997
#if CONFIG_EXT_PARTITION_TYPES
  if (num_8x8_blocks_wide == num_8x8_blocks_high) {
    mv_ref_search[5].row = -1;
    mv_ref_search[5].col = 0;
    mv_ref_search[6].row = 0;
    mv_ref_search[6].col = -1;
  } else {
    mv_ref_search[5].row = -1;
    mv_ref_search[5].col = num_8x8_blocks_wide;
    mv_ref_search[6].row = num_8x8_blocks_high;
    mv_ref_search[6].col = -1;
  }
#else
Deng's avatar
Deng committed
998
999
1000
1001
  mv_ref_search[5].row = -1;
  mv_ref_search[5].col = num_8x8_blocks_wide;
  mv_ref_search[6].row = num_8x8_blocks_high;
  mv_ref_search[6].col = -1;
1002
#endif  // CONFIG_EXT_PARTITION_TYPES
Deng's avatar
Deng committed
1003
1004
1005
1006
  mv_ref_search[7].row = -1;
  mv_ref_search[7].col = -3;
  mv_ref_search[8].row = num_8x8_blocks_high - 1;
  mv_ref_search[8].col = -3;
1007
1008
1009
1010
1011
1012
1013

#if CONFIG_CB4X4
  for (i = 0; i < MVREF_NEIGHBOURS; ++i) {
    mv_ref_search[i].row *= 2;
    mv_ref_search[i].col *= 2;
  }
#endif  // CONFIG_CB4X4
Jingning Han's avatar
Jingning Han committed
1014
1015
1016
1017
1018
1019

  // The nearest 2 blocks are treated differently
  // if the size < 8x8 we get the mv from the bmi substructure,
  // and we also need to keep a mode count.
  for (i = 0; i < 2; ++i) {
    const POSITION *const mv_ref = &mv_ref_search[i];
1020
    if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm, mv_ref)) {
clang-format's avatar
clang-format committed
1021
1022
      const MODE_INFO *const candidate_mi =
          xd->mi[mv_ref->col + mv_ref->row * xd->mi_stride];
Jingning Han's avatar
Jingning Han committed
1023
1024
1025
1026
1027
1028
1029
      const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
      // Keep counts for entropy encoding.
      context_counter += mode_2_counter[candidate->mode];
      different_ref_found = 1;

      if (candidate->ref_frame[0] == ref_frame)
        ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 0, mv_ref->col, block),
1030
                        refmv_count, mv_ref_list, bw, bh, xd, Done);
Jingning Han's avatar
Jingning Han committed
1031
1032
      else if (candidate->ref_frame[1] == ref_frame)
        ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 1, mv_ref->col, block),
1033
                        refmv_count, mv_ref_list, bw, bh, xd, Done);
Jingning Han's avatar
Jingning Han committed
1034
1035
1036
1037
1038
1039
1040
1041
    }
  }

  // Check the rest of the neighbors in much the same way
  // as before except we don't need to keep track of sub blocks or
  // mode counts.
  for (; i < MVREF_NEIGHBOURS; ++i) {
    const POSITION *const mv_ref = &mv_ref_search[i];
1042
    if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm, mv_ref)) {
clang-format's avatar
clang-format committed
1043
      const MB_MODE_INFO *const candidate =
Yaowu Xu's avatar
Yaowu Xu committed
1044
1045
1046
          !xd->mi[mv_ref->col + mv_ref->row * xd->mi_stride]
              ? NULL
              : &xd->mi[mv_ref->col + mv_ref->row * xd->mi_stride]->mbmi;
Yaowu Xu's avatar
Yaowu Xu committed
1047
      if (candidate == NULL) continue;
1048
1049
      if ((mi_row & (sb_mi_size - 1)) + mv_ref->row >= sb_mi_size ||
          (mi_col & (sb_mi_size - 1)) + mv_ref->col >= sb_mi_size)
Deng's avatar
Deng committed
1050
        continue;
Jingning Han's avatar
Jingning Han committed
1051
1052
1053
      different_ref_found = 1;

      if (candidate->ref_frame[0] == ref_frame)
clang-format's avatar
clang-format committed
1054
1055
        ADD_MV_REF_LIST(candidate->mv[0], refmv_count, mv_ref_list, bw, bh, xd,
                        Done);
Jingning Han's avatar
Jingning Han committed
1056
      else if (candidate->ref_frame[1] == ref_frame)
clang-format's avatar
clang-format committed
1057
1058
        ADD_MV_REF_LIST(candidate->mv[1], refmv_count, mv_ref_list, bw, bh, xd,
                        Done);
Jingning Han's avatar
Jingning Han committed
1059
1060
1061
    }
  }

clang-format's avatar
clang-format committed
1062
1063
1064
1065
// TODO(hkuang): Remove this sync after fixing pthread_cond_broadcast
// on windows platform. The sync here is unncessary if use_perv_frame_mvs
// is 0. But after removing it, there will be hang in the unit test on windows
// due to several threads waiting for a thread's signal.
Jingning Han's avatar
Jingning Han committed
1066
#if defined(_WIN32) && !HAVE_PTHREAD_H
clang-format's avatar
clang-format committed
1067
1068
1069
  if (cm->frame_parallel_decode && sync != NULL) {
    sync(data, mi_row);