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

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

clang-format's avatar
clang-format committed
19
20
21
22
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, int col) {
Jingning Han's avatar
Jingning Han committed
23
24
  int index = 0, ref;
  int newmv_count = 0;
25
26
27
28
29
#if CONFIG_CB4X4
  const int unify_bsize = 1;
#else
  const int unify_bsize = 0;
#endif
Jingning Han's avatar
Jingning Han committed
30

Emil Keyder's avatar
Emil Keyder committed
31
  if (rf[1] == NONE_FRAME) {
Jingning Han's avatar
Jingning Han committed
32
33
34
    // single reference frame
    for (ref = 0; ref < 2; ++ref) {
      if (candidate->ref_frame[ref] == rf[0]) {
clang-format's avatar
clang-format committed
35
        int_mv this_refmv = get_sub_block_mv(candidate_mi, ref, col, block);
36
37
        lower_mv_precision(&this_refmv.as_mv, use_hp);

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

Yaowu Xu's avatar
Yaowu Xu committed
41
        if (index < *refmv_count) ref_mv_stack[index].weight += 2 * len;
42

Jingning Han's avatar
Jingning Han committed
43
44
45
        // Add a new item to the list.
        if (index == *refmv_count) {
          ref_mv_stack[index].this_mv = this_refmv;
46
47
          ref_mv_stack[index].pred_diff[0] = av1_get_pred_diff_ctx(
              get_sub_block_pred_mv(candidate_mi, ref, col, block), this_refmv);
Yaowu Xu's avatar
Yaowu Xu committed
48
          ref_mv_stack[index].weight = 2 * len;
Jingning Han's avatar
Jingning Han committed
49
          ++(*refmv_count);
50

51
52
53
#if CONFIG_EXT_INTER
          if (candidate->mode == NEWMV || candidate->mode == NEWFROMNEARMV)
#else
Jingning Han's avatar
Jingning Han committed
54
          if (candidate->mode == NEWMV)
55
#endif  // CONFIG_EXT_INTER
Jingning Han's avatar
Jingning Han committed
56
57
58
            ++newmv_count;
        }

59
60
        if (candidate_mi->mbmi.sb_type < BLOCK_8X8 && block >= 0 &&
            !unify_bsize) {
Jingning Han's avatar
Jingning Han committed
61
          int alt_block = 3 - block;
clang-format's avatar
clang-format committed
62
          this_refmv = get_sub_block_mv(candidate_mi, ref, col, alt_block);
63
64
          lower_mv_precision(&this_refmv.as_mv, use_hp);

65
          for (index = 0; index < *refmv_count; ++index)
clang-format's avatar
clang-format committed
66
            if (ref_mv_stack[index].this_mv.as_int == this_refmv.as_int) break;
67

Yaowu Xu's avatar
Yaowu Xu committed
68
          if (index < *refmv_count) ref_mv_stack[index].weight += len;
69
70
71
72

          // Add a new item to the list.
          if (index == *refmv_count) {
            ref_mv_stack[index].this_mv = this_refmv;
73
74
75
            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
76
            ref_mv_stack[index].weight = len;
77
            ++(*refmv_count);
78

79
#if CONFIG_EXT_INTER
clang-format's avatar
clang-format committed
80
            if (candidate->mode == NEWMV || candidate->mode == NEWFROMNEARMV)
81
#else
82
            if (candidate->mode == NEWMV)
83
#endif  // CONFIG_EXT_INTER
84
              ++newmv_count;
85
86
87
          }
        }
      }
Jingning Han's avatar
Jingning Han committed
88
89
90
    }
  } else {
    // compound reference frame
clang-format's avatar
clang-format committed
91
    if (candidate->ref_frame[0] == rf[0] && candidate->ref_frame[1] == rf[1]) {
92
      int_mv this_refmv[2];
Jingning Han's avatar
Jingning Han committed
93

94
95
      for (ref = 0; ref < 2; ++ref) {
        this_refmv[ref] = get_sub_block_mv(candidate_mi, ref, col, block);
96
        lower_mv_precision(&this_refmv[ref].as_mv, use_hp);
97
      }
98

Jingning Han's avatar
Jingning Han committed
99
100
101
102
103
      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
104
      if (index < *refmv_count) ref_mv_stack[index].weight += 2 * len;
Jingning Han's avatar
Jingning Han committed
105
106
107
108
109

      // 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];
110
111
112
113
        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]);
Yaowu Xu's avatar
Yaowu Xu committed
114
        ref_mv_stack[index].weight = 2 * len;
Jingning Han's avatar
Jingning Han committed
115
116
        ++(*refmv_count);

117
118
119
#if CONFIG_EXT_INTER
        if (candidate->mode == NEW_NEWMV)
#else
Jingning Han's avatar
Jingning Han committed
120
        if (candidate->mode == NEWMV)
121
#endif  // CONFIG_EXT_INTER
Jingning Han's avatar
Jingning Han committed
122
123
124
          ++newmv_count;
      }

125
126
      if (candidate_mi->mbmi.sb_type < BLOCK_8X8 && block >= 0 &&
          !unify_bsize) {
Jingning Han's avatar
Jingning Han committed
127
128
129
130
        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);

131
132
133
        for (ref = 0; ref < 2; ++ref)
          lower_mv_precision(&this_refmv[ref].as_mv, use_hp);

Jingning Han's avatar
Jingning Han committed
134
135
136
137
138
        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
139
        if (index < *refmv_count) ref_mv_stack[index].weight += len;
Jingning Han's avatar
Jingning Han committed
140
141
142
143
144

        // 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];
145
146
147
148
149
150
          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
151
          ref_mv_stack[index].weight = len;
Jingning Han's avatar
Jingning Han committed
152
153
          ++(*refmv_count);

154
155
156
#if CONFIG_EXT_INTER
          if (candidate->mode == NEW_NEWMV)
#else
Jingning Han's avatar
Jingning Han committed
157
          if (candidate->mode == NEWMV)
158
#endif  // CONFIG_EXT_INTER
Jingning Han's avatar
Jingning Han committed
159
160
161
162
163
164
165
166
            ++newmv_count;
        }
      }
    }
  }
  return newmv_count;
}

Yaowu Xu's avatar
Yaowu Xu committed
167
static uint8_t scan_row_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
Jingning Han's avatar
Jingning Han committed
168
                             const int mi_row, const int mi_col, int block,
clang-format's avatar
clang-format committed
169
170
                             const MV_REFERENCE_FRAME rf[2], int row_offset,
                             CANDIDATE_MV *ref_mv_stack, uint8_t *refmv_count) {
Jingning Han's avatar
Jingning Han committed
171
172
173
  const TileInfo *const tile = &xd->tile;
  int i;
  uint8_t newmv_count = 0;
174
#if CONFIG_CB4X4
175
176
177
  const int bsize = xd->mi[0]->mbmi.sb_type;
  const int mi_offset =
      bsize < BLOCK_8X8 ? mi_size_wide[BLOCK_4X4] : mi_size_wide[BLOCK_8X8];
178
  // TODO(jingning): Revisit this part after cb4x4 is stable.
179
180
181
  if (bsize >= BLOCK_8X8) row_offset *= 2;
#else
  const int mi_offset = mi_size_wide[BLOCK_8X8];
182
#endif
Jingning Han's avatar
Jingning Han committed
183
184
185

  for (i = 0; i < xd->n8_w && *refmv_count < MAX_REF_MV_STACK_SIZE;) {
    POSITION mi_pos;
186
187
188
#if CONFIG_CB4X4
    const int use_step_16 = (xd->n8_w >= 16);
#else
189
    const int use_step_16 = (xd->n8_w >= 8);
190
#endif
191

Jingning Han's avatar
Jingning Han committed
192
193
    mi_pos.row = row_offset;
    mi_pos.col = i;
194
195
196
197
#if CONFIG_DEPENDENT_HORZTILES
    if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm->dependent_horz_tiles,
                  &mi_pos)) {
#else
Geza Lore's avatar
Geza Lore committed
198
    if (is_inside(tile, mi_col, mi_row, &mi_pos)) {
199
#endif
Jingning Han's avatar
Jingning Han committed
200
201
202
      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;
203
      int len = AOMMIN(xd->n8_w, mi_size_wide[candidate->sb_type]);
204
      if (use_step_16) len = AOMMAX(mi_size_wide[BLOCK_16X16], len);
clang-format's avatar
clang-format committed
205
206
207
      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);
208
209
      i += len;
    } else {
210
      if (use_step_16)
211
        i += (mi_offset << 1);
212
      else
213
        i += mi_offset;
214
215
    }
  }
216
217

  return newmv_count;
218
219
}

Yaowu Xu's avatar
Yaowu Xu committed
220
static uint8_t scan_col_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
221
                             const int mi_row, const int mi_col, int block,
clang-format's avatar
clang-format committed
222
223
                             const MV_REFERENCE_FRAME rf[2], int col_offset,
                             CANDIDATE_MV *ref_mv_stack, uint8_t *refmv_count) {
224
225
  const TileInfo *const tile = &xd->tile;
  int i;
226
  uint8_t newmv_count = 0;
227
#if CONFIG_CB4X4
228
229
230
231
232
233
  const BLOCK_SIZE bsize = xd->mi[0]->mbmi.sb_type;
  const int mi_offset =
      (bsize < BLOCK_8X8) ? mi_size_high[BLOCK_4X4] : mi_size_high[BLOCK_8X8];
  if (bsize >= BLOCK_8X8) col_offset *= 2;
#else
  const int mi_offset = mi_size_wide[BLOCK_8X8];
234
#endif
235
236
237

  for (i = 0; i < xd->n8_h && *refmv_count < MAX_REF_MV_STACK_SIZE;) {
    POSITION mi_pos;
238
239
240
#if CONFIG_CB4X4
    const int use_step_16 = (xd->n8_h >= 16);
#else
241
    const int use_step_16 = (xd->n8_h >= 8);
242
#endif
243

244
245
    mi_pos.row = i;
    mi_pos.col = col_offset;
246
247
248
249
#if CONFIG_DEPENDENT_HORZTILES
    if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm->dependent_horz_tiles,
                  &mi_pos)) {
#else
Geza Lore's avatar
Geza Lore committed
250
    if (is_inside(tile, mi_col, mi_row, &mi_pos)) {
251
#endif
252
253
254
      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;
255
      int len = AOMMIN(xd->n8_h, mi_size_high[candidate->sb_type]);
256
      if (use_step_16) len = AOMMAX(mi_size_high[BLOCK_16X16], len);
clang-format's avatar
clang-format committed
257
258
259
      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);
260
261
      i += len;
    } else {
262
      if (use_step_16)
263
        i += (mi_offset << 1);
264
      else
265
        i += mi_offset;
266
267
    }
  }
268
269

  return newmv_count;
270
271
}

Yaowu Xu's avatar
Yaowu Xu committed
272
static uint8_t scan_blk_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
273
                             const int mi_row, const int mi_col, int block,
clang-format's avatar
clang-format committed
274
275
                             const MV_REFERENCE_FRAME rf[2], int row_offset,
                             int col_offset, CANDIDATE_MV *ref_mv_stack,
276
                             uint8_t *refmv_count) {
277
278
  const TileInfo *const tile = &xd->tile;
  POSITION mi_pos;
279
  uint8_t newmv_count = 0;
280
281
282
283

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

284
285
286
287
288
#if CONFIG_DEPENDENT_HORZTILES
  if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm->dependent_horz_tiles,
                &mi_pos) &&
      *refmv_count < MAX_REF_MV_STACK_SIZE) {
#else
Geza Lore's avatar
Geza Lore committed
289
  if (is_inside(tile, mi_col, mi_row, &mi_pos) &&
290
      *refmv_count < MAX_REF_MV_STACK_SIZE) {
291
#endif
292
293
294
    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;
295
    const int len = mi_size_wide[BLOCK_8X8];
296

clang-format's avatar
clang-format committed
297
298
299
    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);
300
  }  // Analyze a single 8x8 block motion information.
Yaowu Xu's avatar
Yaowu Xu committed
301

302
  return newmv_count;
303
304
}

clang-format's avatar
clang-format committed
305
306
static int has_top_right(const MACROBLOCKD *xd, int mi_row, int mi_col,
                         int bs) {
307
308
309
  const int mask_row = mi_row & MAX_MIB_MASK;
  const int mask_col = mi_col & MAX_MIB_MASK;

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

313
314
  // bs > 0 and bs is a power of 2
  assert(bs > 0 && !(bs & (bs - 1)));
315

316
317
318
  // 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
319
  while (bs < MAX_MIB_SIZE) {
320
321
    if (mask_col & bs) {
      if ((mask_col & (2 * bs)) && (mask_row & (2 * bs))) {
322
        has_tr = 0;
323
324
325
326
327
328
329
        break;
      }
    } else {
      break;
    }
    bs <<= 1;
  }
330

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

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

341
342
343
344
#if CONFIG_EXT_PARTITION_TYPES
  // The bottom left square of a Vertical A does not have a top right as it is
  // decoded before the right hand rectangle of the partition
  if (xd->mi[0]->mbmi.partition == PARTITION_VERT_A)
345
    if ((mask_row & bs) && !(mask_col & bs)) has_tr = 0;
346
347
#endif  // CONFIG_EXT_PARTITION_TYPES

348
349
350
  return has_tr;
}

351
352
353
354
355
356
357
358
359
360
361
static int add_col_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) {
  const MV_REF *prev_frame_mvs =
      prev_frame_mvs_base + blk_row * cm->mi_cols + blk_col;
  POSITION mi_pos;
  int ref, idx;
  int coll_blk_count = 0;
362
  const int weight_unit = mi_size_wide[BLOCK_8X8];
363
364
365
366

  mi_pos.row = blk_row;
  mi_pos.col = blk_col;

367
368
369
370
371
#if CONFIG_DEPENDENT_HORZTILES
  if (!is_inside(&xd->tile, mi_col, mi_row, cm->mi_rows,
                 cm->dependent_horz_tiles, &mi_pos))
    return coll_blk_count;
#else
372
  if (!is_inside(&xd->tile, mi_col, mi_row, &mi_pos)) return coll_blk_count;
373
#endif
374
375
376
377
378
379
380
381
382
383
384
385

  for (ref = 0; ref < 2; ++ref) {
    if (prev_frame_mvs->ref_frame[ref] == ref_frame) {
      int_mv this_refmv = prev_frame_mvs->mv[ref];
      lower_mv_precision(&this_refmv.as_mv, cm->allow_high_precision_mv);

      if (abs(this_refmv.as_mv.row) >= 16 || abs(this_refmv.as_mv.col) >= 16)
        mode_context[ref_frame] |= (1 << ZEROMV_OFFSET);

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

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

      if (idx == *refmv_count && *refmv_count < MAX_REF_MV_STACK_SIZE) {
        ref_mv_stack[idx].this_mv.as_int = this_refmv.as_int;
390
391
        ref_mv_stack[idx].pred_diff[0] =
            av1_get_pred_diff_ctx(prev_frame_mvs->pred_mv[ref], this_refmv);
392
        ref_mv_stack[idx].weight = 2 * weight_unit;
393
394
395
396
397
398
399
400
401
402
        ++(*refmv_count);
      }

      ++coll_blk_count;
    }
  }

  return coll_blk_count;
}

Yaowu Xu's avatar
Yaowu Xu committed
403
static void setup_ref_mv_list(const AV1_COMMON *cm, const MACROBLOCKD *xd,
404
                              MV_REFERENCE_FRAME ref_frame,
clang-format's avatar
clang-format committed
405
406
407
                              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) {
408
  int idx, nearest_refmv_count = 0;
409
  uint8_t newmv_count = 0;
410
411
412
  CANDIDATE_MV tmp_mv;
  int len, nr_len;

clang-format's avatar
clang-format committed
413
414
415
416
  const MV_REF *const prev_frame_mvs_base =
      cm->use_prev_frame_mvs
          ? cm->prev_frame->mvs + mi_row * cm->mi_cols + mi_col
          : NULL;
417

418
419
  const int bs = AOMMAX(xd->n8_w, xd->n8_h);
  const int has_tr = has_top_right(xd, mi_row, mi_col, bs);
Jingning Han's avatar
Jingning Han committed
420
421
  MV_REFERENCE_FRAME rf[2];

422
  av1_set_ref_frame(rf, ref_frame);
423
  mode_context[ref_frame] = 0;
424
  *refmv_count = 0;
425
426

  // Scan the first above row mode info.
427
428
  newmv_count += scan_row_mbmi(cm, xd, mi_row, mi_col, block, rf, -1,
                               ref_mv_stack, refmv_count);
429
  // Scan the first left column mode info.
clang-format's avatar
clang-format committed
430
431
  newmv_count += scan_col_mbmi(cm, xd, mi_row, mi_col, block, rf, -1,
                               ref_mv_stack, refmv_count);
432

433
434
  // Check top-right boundary
  if (has_tr)
435
436
    newmv_count += scan_blk_mbmi(cm, xd, mi_row, mi_col, block, rf, -1,
                                 xd->n8_w, ref_mv_stack, refmv_count);
437

438
  nearest_refmv_count = *refmv_count;
439

440
  for (idx = 0; idx < nearest_refmv_count; ++idx)
441
    ref_mv_stack[idx].weight += REF_CAT_LEVEL;
442
443
444
#if CONFIG_TEMPMV_SIGNALING
  if (cm->use_prev_frame_mvs && rf[1] == NONE_FRAME) {
#else
clang-format's avatar
clang-format committed
445
  if (prev_frame_mvs_base && cm->show_frame && cm->last_show_frame &&
Emil Keyder's avatar
Emil Keyder committed
446
      rf[1] == NONE_FRAME) {
447
#endif
448
    int blk_row, blk_col;
449
    int coll_blk_count = 0;
450
451
452
453
454
#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
455
    const int mi_step = mi_size_wide[BLOCK_16X16];
456
#endif
457
458
    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) {
459
460
461
        coll_blk_count += add_col_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);
462
463
      }
    }
464
465
    if (coll_blk_count == 0) mode_context[ref_frame] |= (1 << ZEROMV_OFFSET);
  } else {
466
    mode_context[ref_frame] |= (1 << ZEROMV_OFFSET);
467
  }
468

469
  // Scan the second outer area.
Deng's avatar
Deng committed
470
471
472
473
474
475
476
477
478
479
  scan_blk_mbmi(cm, xd, mi_row, mi_col, block, rf, -1, -1, ref_mv_stack,
                refmv_count);
  for (idx = 2; idx <= 3; ++idx) {
    scan_row_mbmi(cm, xd, mi_row, mi_col, block, rf, -idx, ref_mv_stack,
                  refmv_count);
    scan_col_mbmi(cm, xd, mi_row, mi_col, block, rf, -idx, ref_mv_stack,
                  refmv_count);
  }
  scan_col_mbmi(cm, xd, mi_row, mi_col, block, rf, -4, ref_mv_stack,
                refmv_count);
480

481
482
483
  switch (nearest_refmv_count) {
    case 0:
      mode_context[ref_frame] |= 0;
clang-format's avatar
clang-format committed
484
      if (*refmv_count >= 1) mode_context[ref_frame] |= 1;
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512

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

513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
  // 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;
  }

528
  len = *refmv_count;
529
530
531
532
533
534
535
536
537
538
539
540
541
  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
542
  if (rf[1] > NONE_FRAME) {
543
    for (idx = 0; idx < *refmv_count; ++idx) {
544
545
546
547
      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);
548
549
    }
  } else {
Yaowu Xu's avatar
Yaowu Xu committed
550
    for (idx = 0; idx < AOMMIN(MAX_MV_REF_CANDIDATES, *refmv_count); ++idx) {
551
      mv_ref_list[idx].as_int = ref_mv_stack[idx].this_mv.as_int;
552
553
      clamp_mv_ref(&mv_ref_list[idx].as_mv, xd->n8_w << MI_SIZE_LOG2,
                   xd->n8_h << MI_SIZE_LOG2, xd);
554
    }
555
556
557
558
  }
}
#endif

Jingning Han's avatar
Jingning Han committed
559
560
// This function searches the neighbourhood of a given MB/SB
// to try and find candidate reference vectors.
Yaowu Xu's avatar
Yaowu Xu committed
561
static void find_mv_refs_idx(const AV1_COMMON *cm, const MACROBLOCKD *xd,
Jingning Han's avatar
Jingning Han committed
562
                             MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame,
clang-format's avatar
clang-format committed
563
564
                             int_mv *mv_ref_list, int block, int mi_row,
                             int mi_col, find_mv_refs_sync sync,
565
566
                             void *const data, int16_t *mode_context,
                             int_mv zeromv) {
Jingning Han's avatar
Jingning Han committed
567
568
  const int *ref_sign_bias = cm->ref_frame_sign_bias;
  int i, refmv_count = 0;
Yaowu Xu's avatar
Yaowu Xu committed
569
#if !CONFIG_REF_MV
Jingning Han's avatar
Jingning Han committed
570
  const POSITION *const mv_ref_search = mv_ref_blocks[mi->mbmi.sb_type];
Deng's avatar
Deng committed
571
#endif
Jingning Han's avatar
Jingning Han committed
572
573
  int different_ref_found = 0;
  int context_counter = 0;
clang-format's avatar
clang-format committed
574
575
576
577
  const MV_REF *const prev_frame_mvs =
      cm->use_prev_frame_mvs
          ? cm->prev_frame->mvs + mi_row * cm->mi_cols + mi_col
          : NULL;
Jingning Han's avatar
Jingning Han committed
578
  const TileInfo *const tile = &xd->tile;
579
580
581
  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)];
Yaowu Xu's avatar
Yaowu Xu committed
582
#if CONFIG_REF_MV
Deng's avatar
Deng committed
583
  POSITION mv_ref_search[MVREF_NEIGHBOURS];
584
585
  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
586
587
588
589
590
591
592
593
594
595
  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;
596
597
598
599
600
601
602
603
604
605
606
607
608
#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
609
610
611
612
  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;
613
#endif  // CONFIG_EXT_PARTITION_TYPES
Deng's avatar
Deng committed
614
615
616
617
  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;
618
619
620
621
622
623
624
625

#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
#endif  // CONFIG_REF_MV
Jingning Han's avatar
Jingning Han committed
626
627
628
629
630
631

  // 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];
632
633
634
635
#if CONFIG_DEPENDENT_HORZTILES
    if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm->dependent_horz_tiles,
                  mv_ref)) {
#else
Geza Lore's avatar
Geza Lore committed
636
    if (is_inside(tile, mi_col, mi_row, mv_ref)) {
637
#endif
clang-format's avatar
clang-format committed
638
639
      const MODE_INFO *const candidate_mi =
          xd->mi[mv_ref->col + mv_ref->row * xd->mi_stride];
Jingning Han's avatar
Jingning Han committed
640
641
642
643
644
645
646
      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),
647
                        refmv_count, mv_ref_list, bw, bh, xd, Done);
Jingning Han's avatar
Jingning Han committed
648
649
      else if (candidate->ref_frame[1] == ref_frame)
        ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 1, mv_ref->col, block),
650
                        refmv_count, mv_ref_list, bw, bh, xd, Done);
Jingning Han's avatar
Jingning Han committed
651
652
653
654
655
656
657
658
    }
  }

  // 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];
659
660
661
662
#if CONFIG_DEPENDENT_HORZTILES
    if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm->dependent_horz_tiles,
                  mv_ref)) {
#else
Geza Lore's avatar
Geza Lore committed
663
    if (is_inside(tile, mi_col, mi_row, mv_ref)) {
664
#endif
clang-format's avatar
clang-format committed
665
      const MB_MODE_INFO *const candidate =
Yaowu Xu's avatar
Yaowu Xu committed
666
667
668
          !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
669
#if CONFIG_REF_MV
Yaowu Xu's avatar
Yaowu Xu committed
670
      if (candidate == NULL) continue;
671
672
      if ((mi_row % MAX_MIB_SIZE) + mv_ref->row >= MAX_MIB_SIZE ||
          (mi_col % MAX_MIB_SIZE) + mv_ref->col >= MAX_MIB_SIZE)
Deng's avatar
Deng committed
673
674
        continue;
#endif
Jingning Han's avatar
Jingning Han committed
675
676
677
      different_ref_found = 1;

      if (candidate->ref_frame[0] == ref_frame)
clang-format's avatar
clang-format committed
678
679
        ADD_MV_REF_LIST(candidate->mv[0], refmv_count, mv_ref_list, bw, bh, xd,
                        Done);
Jingning Han's avatar
Jingning Han committed
680
      else if (candidate->ref_frame[1] == ref_frame)
clang-format's avatar
clang-format committed
681
682
        ADD_MV_REF_LIST(candidate->mv[1], refmv_count, mv_ref_list, bw, bh, xd,
                        Done);
Jingning Han's avatar
Jingning Han committed
683
684
685
    }
  }

clang-format's avatar
clang-format committed
686
687
688
689
// 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
690
#if defined(_WIN32) && !HAVE_PTHREAD_H
clang-format's avatar
clang-format committed
691
692
693
  if (cm->frame_parallel_decode && sync != NULL) {
    sync(data, mi_row);
  }
Jingning Han's avatar
Jingning Han committed
694
695
696
697
698
699
700
701
702
703
#endif

  // Check the last frame's mode and mv info.
  if (cm->use_prev_frame_mvs) {
    // Synchronize here for frame parallel decode if sync function is provided.
    if (cm->frame_parallel_decode && sync != NULL) {
      sync(data, mi_row);
    }

    if (prev_frame_mvs->ref_frame[0] == ref_frame) {
clang-format's avatar
clang-format committed
704
705
      ADD_MV_REF_LIST(prev_frame_mvs->mv[0], refmv_count, mv_ref_list, bw, bh,
                      xd, Done);
Jingning Han's avatar
Jingning Han committed
706
    } else if (prev_frame_mvs->ref_frame[1] == ref_frame) {
clang-format's avatar
clang-format committed
707
708
      ADD_MV_REF_LIST(prev_frame_mvs->mv[1], refmv_count, mv_ref_list, bw, bh,
                      xd, Done);
Jingning Han's avatar
Jingning Han committed
709
710
711
712
713
714
715
716
717
    }
  }

  // Since we couldn't find 2 mvs from the same reference frame
  // go back through the neighbors and find motion vectors from
  // different reference frames.
  if (different_ref_found) {
    for (i = 0; i < MVREF_NEIGHBOURS; ++i) {
      const POSITION *mv_ref = &mv_ref_search[i];
718
719
720
721
#if CONFIG_DEPENDENT_HORZTILES
      if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm->dependent_horz_tiles,
                    mv_ref)) {
#else
Geza Lore's avatar
Geza Lore committed
722
      if (is_inside(tile, mi_col, mi_row, mv_ref)) {
723
#endif
clang-format's avatar
clang-format committed
724
        const MB_MODE_INFO *const candidate =
Yaowu Xu's avatar
Yaowu Xu committed
725
726
727
            !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
728
#if CONFIG_REF_MV
Yaowu Xu's avatar
Yaowu Xu committed
729
        if (candidate == NULL) continue;
730
731
        if ((mi_row % MAX_MIB_SIZE) + mv_ref->row >= MAX_MIB_SIZE ||
            (mi_col % MAX_MIB_SIZE) + mv_ref->col >= MAX_MIB_SIZE)
Deng's avatar
Deng committed
732
733
          continue;
#endif
Jingning Han's avatar
Jingning Han committed
734
735
736

        // If the candidate is INTRA we don't want to consider its mv.
        IF_DIFF_REF_FRAME_ADD_MV(candidate, ref_frame, ref_sign_bias,
737
                                 refmv_count, mv_ref_list, bw, bh, xd, Done);
Jingning Han's avatar
Jingning Han committed
738
739
740
741
742
743
744
745
746
747
748
749
750
751
      }
    }
  }

  // Since we still don't have a candidate we'll try the last frame.
  if (cm->use_prev_frame_mvs) {
    if (prev_frame_mvs->ref_frame[0] != ref_frame &&
        prev_frame_mvs->ref_frame[0] > INTRA_FRAME) {
      int_mv mv = prev_frame_mvs->mv[0];
      if (ref_sign_bias[prev_frame_mvs->ref_frame[0]] !=
          ref_sign_bias[ref_frame]) {
        mv.as_mv.row *= -1;
        mv.as_mv.col *= -1;
      }
752
      ADD_MV_REF_LIST(mv, refmv_count, mv_ref_list, bw, bh, xd, Done);
Jingning Han's avatar
Jingning Han committed
753
754
755
    }

    if (prev_frame_mvs->ref_frame[1] > INTRA_FRAME &&
756
        prev_frame_mvs->ref_frame[1] != ref_frame) {
Jingning Han's avatar
Jingning Han committed
757
758
759
760
761
762
      int_mv mv = prev_frame_mvs->mv[1];
      if (ref_sign_bias[prev_frame_mvs->ref_frame[1]] !=
          ref_sign_bias[ref_frame]) {
        mv.as_mv.row *= -1;
        mv.as_mv.col *= -1;
      }
763
      ADD_MV_REF_LIST(mv, refmv_count, mv_ref_list, bw, bh, xd, Done);
Jingning Han's avatar
Jingning Han committed
764
765
766
    }
  }

767
768
769
Done:
  if (mode_context)
    mode_context[ref_frame] = counter_to_context[context_counter];
770
  for (i = refmv_count; i < MAX_MV_REF_CANDIDATES; ++i)
771
    mv_ref_list[i].as_int = zeromv.as_int;
Jingning Han's avatar
Jingning Han committed
772
773
}

Yue Chen's avatar
Yue Chen committed
774
775
#if CONFIG_EXT_INTER
// This function keeps a mode count for a given MB/SB
Yaowu Xu's avatar
Yaowu Xu committed
776
777
778
779
void av1_update_mv_context(const MACROBLOCKD *xd, MODE_INFO *mi,
                           MV_REFERENCE_FRAME ref_frame, int_mv *mv_ref_list,
                           int block, int mi_row, int mi_col,
                           int16_t *mode_context) {
Yue Chen's avatar
Yue Chen committed
780
  int i, refmv_count = 0;
Yaowu Xu's avatar
Yaowu Xu committed
781
#if !CONFIG_REF_MV
Yue Chen's avatar
Yue Chen committed
782
  const POSITION *const mv_ref_search = mv_ref_blocks[mi->mbmi.sb_type];
783
#endif
Yue Chen's avatar
Yue Chen committed
784
  int context_counter = 0;
785
786
  const int bw = block_size_wide[mi->mbmi.sb_type];
  const int bh = block_size_high[mi->mbmi.sb_type];
Yue Chen's avatar
Yue Chen committed
787
  const TileInfo *const tile = &xd->tile;
Yaowu Xu's avatar
Yaowu Xu committed
788
#if CONFIG_REF_MV
789
  POSITION mv_ref_search[MVREF_NEIGHBOURS];
790
791
  const int num_8x8_blocks_wide = mi_size_wide[mi->mbmi.sb_type];
  const int num_8x8_blocks_high = mi_size_high[mi->mbmi.sb_type];
792
793
794
795
796
797
798
799
800
801
  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;
802
803
804
805
806
807
808
809
810
811
812
813
814
#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
815
816
817
818
  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;
819
#endif  // CONFIG_EXT_PARTITION_TYPES
820
821
822
823
824
  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;
#endif
Yue Chen's avatar
Yue Chen committed
825
826
827
828
829
830
831
832

  // Blank the reference vector list
  memset(mv_ref_list, 0, sizeof(*mv_ref_list) * MAX_MV_REF_CANDIDATES);

  // The nearest 2 blocks are examined only.
  // If the size < 8x8, we get the mv from the bmi substructure;
  for (i = 0; i < 2; ++i) {
    const POSITION *const mv_ref = &mv_ref_search[i];
833
834
835
836
#if CONFIG_DEPENDENT_HORZTILES
    if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm->dependent_horz_tiles,
                  mv_ref)) {
#else
Geza Lore's avatar
Geza Lore committed
837
    if (is_inside(tile, mi_col, mi_row, mv_ref)) {
838
#endif
Yue Chen's avatar
Yue Chen committed
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
      const MODE_INFO *const candidate_mi =
          xd->mi[mv_ref->col + mv_ref->row * xd->mi_stride];
      const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;

      // Keep counts for entropy encoding.
      context_counter += mode_2_counter[candidate->mode];

      if (candidate->ref_frame[0] == ref_frame) {
        ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 0, mv_ref->col, block),
                        refmv_count, mv_ref_list, bw, bh, xd, Done);
      } else if (candidate->ref_frame[1] == ref_frame) {
        ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 1, mv_ref->col, block),
                        refmv_count, mv_ref_list, bw, bh, xd, Done);
      }
    }
  }

clang-format's avatar
clang-format committed
856
Done:
Yue Chen's avatar
Yue Chen committed
857
858
859
860
861
862

  if (mode_context)
    mode_context[ref_frame] = counter_to_context[context_counter];
}
#endif  // CONFIG_EXT_INTER

Yaowu Xu's avatar
Yaowu Xu committed
863
864
void av1_find_mv_refs(const AV1_COMMON *cm, const MACROBLOCKD *xd,
                      MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame,
865
#if CONFIG_REF_MV
Yaowu Xu's avatar
Yaowu Xu committed
866
                      uint8_t *ref_mv_count, CANDIDATE_MV *ref_mv_stack,
867
#if CONFIG_EXT_INTER
Yaowu Xu's avatar
Yaowu Xu committed
868
                      int16_t *compound_mode_context,
869
#endif  // CONFIG_EXT_INTER
870
#endif
Yaowu Xu's avatar
Yaowu Xu committed
871
872
873
                      int_mv *mv_ref_list, int mi_row, int mi_col,
                      find_mv_refs_sync sync, void *const data,
                      int16_t *mode_context) {
874
  int_mv zeromv[2];
875
#if CONFIG_REF_MV
876
877
878
  int idx, all_zero = 1;
#if CONFIG_GLOBAL_MOTION
  MV_REFERENCE_FRAME rf[2];
879
#endif
880
#endif
Yue Chen's avatar
Yue Chen committed
881
#if CONFIG_EXT_INTER
Yaowu Xu's avatar
Yaowu Xu committed
882
  av1_update_mv_context(xd, mi, ref_frame, mv_ref_list, -1, mi_row, mi_col,
883
#if CONFIG_REF_MV
Yaowu Xu's avatar
Yaowu Xu committed
884
                        compound_mode_context);
885
#else
Yaowu Xu's avatar
Yaowu Xu committed
886
                        mode_context);
887
#endif  // CONFIG_REF_MV
Yaowu Xu's avatar
Yaowu Xu committed
888
#endif  // CONFIG_EXT_INTER
889
890

#if CONFIG_GLOBAL_MOTION
891
#if CONFIG_REF_MV
892
893
  av1_set_ref_frame(rf, ref_frame);
  zeromv[0].as_int = gm_get_motion_vector(&cm->global_motion[rf[0]],
David Barker's avatar
David Barker committed
894
895
896
                                          cm->allow_high_precision_mv,
                                          mi_col * MI_SIZE + MI_SIZE / 2,
                                          mi_row * MI_SIZE + MI_SIZE / 2)
897
                         .as_int;
Emil Keyder's avatar
Emil Keyder committed
898
  zeromv[1].as_int = (rf[1] != NONE_FRAME)
899
                         ? gm_get_motion_vector(&cm->global_motion[rf[1]],
David Barker's avatar
David Barker committed
900
901
902
                                                cm->allow_high_precision_mv,
                                                mi_col * MI_SIZE + MI_SIZE / 2,
                                                mi_row * MI_SIZE + MI_SIZE / 2)
903
904
                               .as_int
                         : 0;
905
906
#else
  zeromv[0].as_int = gm_get_motion_vector(&cm->global_motion[ref_frame],
David Barker's avatar
David Barker committed
907
908
909
                                          cm->allow_high_precision_mv,
                                          mi_col * MI_SIZE + MI_SIZE / 2,
                                          mi_row * MI_SIZE + MI_SIZE / 2)
910
911
912
                         .as_int;
  zeromv[1].as_int = 0;
#endif  // CONFIG_REF_MV
913
914
#else
  zeromv[0].as_int = zeromv[1].as_int = 0;
915
#endif  // CONFIG_GLOBAL_MOTION
916

Yaowu Xu's avatar
Yaowu Xu committed
917
918
#if CONFIG_REF_MV
  if (ref_frame <= ALTREF_FRAME)
919
#endif  // CONFIG_REF_MV
920
921
    find_mv_refs_idx(cm, xd, mi, ref_frame, mv_ref_list, -1, mi_row, mi_col,
                     sync, data, mode_context, zeromv[0]);
922
923

#if CONFIG_REF_MV
clang-format's avatar
clang-format committed
924
925
  setup_ref_mv_list(cm, xd, ref_frame, ref_mv_count, ref_mv_stack, mv_ref_list,
                    -1, mi_row, mi_col, mode_context);
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
  /* Note: If global motion is enabled, then we want to set the ALL_ZERO flag
     iff all of the MVs we could generate with NEARMV/NEARESTMV are equivalent
     to the global motion vector.
     Note: For the following to work properly, the encoder can't throw away
     any global motion models after calling this function, even if they are
     unused. Instead we rely on the recode loop: If any non-IDENTITY model
     is unused, the whole frame will be re-encoded without it.
     The problem is that, otherwise, we can end up in the following situation:
     * Encoder has a global motion model with nonzero translational part,
       and all candidate MVs are zero. So the ALL_ZERO flag is unset.
     * Encoder throws away global motion because it is never used.
     * Decoder sees that there is no global motion and all candidate MVs are
       zero, so sets the ALL_ZERO flag.
     * This leads to an encode/decode mismatch.
  */
Yaowu Xu's avatar
Yaowu Xu committed
941
942
  if (*ref_mv_count >= 2) {
    for (idx = 0; idx < AOMMIN(3, *ref_mv_count); ++idx) {
943
      if (ref_mv_stack[idx].this_mv.as_int != zeromv[0].as_int) all_zero = 0;
Yaowu Xu's avatar
Yaowu Xu committed
944
      if (ref_frame > ALTREF_FRAME)
945
        if (ref_mv_stack[idx].comp_mv.as_int != zeromv[1].as_int) all_zero = 0;
Yaowu Xu's avatar
Yaowu Xu committed
946
947
948
    }
  } else if (ref_frame <= ALTREF_FRAME) {
    for (idx = 0; idx < MAX_MV_REF_CANDIDATES; ++idx)
949
      if (mv_ref_list[idx].as_int != zeromv[0].as_int) all_zero = 0;
Yaowu Xu's avatar
Yaowu Xu committed
950
  }
951

clang-format's avatar
clang-format committed
952
  if (all_zero) mode_context[ref_frame] |= (1 << ALL_ZERO_FLAG_OFFSET);
953
#endif
Jingning Han's avatar
Jingning Han committed
954
955
}

Yaowu Xu's avatar
Yaowu Xu committed
956
957
void av1_find_best_ref_mvs(int allow_hp, int_mv *mvlist, int_mv *nearest_mv,
                           int_mv *near_mv) {
Jingning Han's avatar
Jingning Han committed
958
959
960
961
962
963
964
965
966
  int i;
  // Make sure all the candidates are properly clamped etc
  for (i = 0; i < MAX_MV_REF_CANDIDATES; ++i) {
    lower_mv_precision(&mvlist[i].as_mv, allow_hp);
  }
  *nearest_mv = mvlist[0];
  *near_mv = mvlist[1];
}

967
968
void av1_append_sub8x8_mvs_for_idx(const AV1_COMMON *cm, MACROBLOCKD *xd,
                                   int block, int ref, int mi_row, int mi_col,
969
#if CONFIG_REF_MV
Yaowu Xu's avatar
Yaowu Xu committed
970
971
                                   CANDIDATE_MV *ref_mv_stack,
                                   uint8_t *ref_mv_count,
972
#endif
Yue Chen's avatar
Yue Chen committed
973
#if CONFIG_EXT_INTER
Yaowu Xu's avatar
Yaowu Xu committed
974
                                   int_mv *mv_list,
Yue Chen's avatar
Yue Chen committed
975
#endif  // CONFIG_EXT_INTER
Yaowu Xu's avatar
Yaowu Xu committed
976
                                   int_mv *nearest_mv, int_mv *near_mv) {
Yue Chen's avatar
Yue Chen committed
977
#if !CONFIG_EXT_INTER
Jingning Han's avatar
Jingning Han committed
978
  int_mv mv_list[MAX_MV_REF_CANDIDATES];
Yue Chen's avatar
Yue Chen committed
979
#endif  // !CONFIG_EXT_INTER