mvref_common.c 47.1 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

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

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

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

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

Jingning Han's avatar
Jingning Han committed
41
42
43
        // Add a new item to the list.
        if (index == *refmv_count) {
          ref_mv_stack[index].this_mv = this_refmv;
44
45
          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
46
          ref_mv_stack[index].weight = 2 * len;
Jingning Han's avatar
Jingning Han committed
47
          ++(*refmv_count);
48

49
          if (candidate->mode == NEWMV) ++newmv_count;
Jingning Han's avatar
Jingning Han committed
50
51
        }

52
53
        if (candidate_mi->mbmi.sb_type < BLOCK_8X8 && block >= 0 &&
            !unify_bsize) {
Jingning Han's avatar
Jingning Han committed
54
          int alt_block = 3 - block;
clang-format's avatar
clang-format committed
55
          this_refmv = get_sub_block_mv(candidate_mi, ref, col, alt_block);
56
57
          lower_mv_precision(&this_refmv.as_mv, use_hp);

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

Yaowu Xu's avatar
Yaowu Xu committed
61
          if (index < *refmv_count) ref_mv_stack[index].weight += len;
62
63
64
65

          // Add a new item to the list.
          if (index == *refmv_count) {
            ref_mv_stack[index].this_mv = this_refmv;
66
67
68
            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
69
            ref_mv_stack[index].weight = len;
70
            ++(*refmv_count);
71

72
            if (candidate->mode == NEWMV) ++newmv_count;
73
74
75
          }
        }
      }
Jingning Han's avatar
Jingning Han committed
76
77
78
    }
  } else {
    // compound reference frame
clang-format's avatar
clang-format committed
79
    if (candidate->ref_frame[0] == rf[0] && candidate->ref_frame[1] == rf[1]) {
80
      int_mv this_refmv[2];
Jingning Han's avatar
Jingning Han committed
81

82
83
      for (ref = 0; ref < 2; ++ref) {
        this_refmv[ref] = get_sub_block_mv(candidate_mi, ref, col, block);
84
        lower_mv_precision(&this_refmv[ref].as_mv, use_hp);
85
      }
86

Jingning Han's avatar
Jingning Han committed
87
88
89
90
91
      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
92
      if (index < *refmv_count) ref_mv_stack[index].weight += 2 * len;
Jingning Han's avatar
Jingning Han committed
93
94
95
96
97

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

105
106
107
#if CONFIG_EXT_INTER
        if (candidate->mode == NEW_NEWMV)
#else
Jingning Han's avatar
Jingning Han committed
108
        if (candidate->mode == NEWMV)
109
#endif  // CONFIG_EXT_INTER
Jingning Han's avatar
Jingning Han committed
110
111
112
          ++newmv_count;
      }

113
114
      if (candidate_mi->mbmi.sb_type < BLOCK_8X8 && block >= 0 &&
          !unify_bsize) {
Jingning Han's avatar
Jingning Han committed
115
116
117
118
        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);

119
120
121
        for (ref = 0; ref < 2; ++ref)
          lower_mv_precision(&this_refmv[ref].as_mv, use_hp);

Jingning Han's avatar
Jingning Han committed
122
123
124
125
126
        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
127
        if (index < *refmv_count) ref_mv_stack[index].weight += len;
Jingning Han's avatar
Jingning Han committed
128
129
130
131
132

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

142
143
144
#if CONFIG_EXT_INTER
          if (candidate->mode == NEW_NEWMV)
#else
Jingning Han's avatar
Jingning Han committed
145
          if (candidate->mode == NEWMV)
146
#endif  // CONFIG_EXT_INTER
Jingning Han's avatar
Jingning Han committed
147
148
149
150
151
152
153
154
            ++newmv_count;
        }
      }
    }
  }
  return newmv_count;
}

Yaowu Xu's avatar
Yaowu Xu committed
155
static uint8_t scan_row_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
Jingning Han's avatar
Jingning Han committed
156
                             const int mi_row, const int mi_col, int block,
clang-format's avatar
clang-format committed
157
158
                             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
159
160
161
  const TileInfo *const tile = &xd->tile;
  int i;
  uint8_t newmv_count = 0;
162
  int col_offset = 0;
163
#if CONFIG_CB4X4
164
  const int bsize = xd->mi[0]->mbmi.sb_type;
165
166
167
  const int mi_offset = bsize < BLOCK_8X8 || abs(row_offset) > 1
                            ? mi_size_wide[BLOCK_4X4]
                            : mi_size_wide[BLOCK_8X8];
168
  // TODO(jingning): Revisit this part after cb4x4 is stable.
169
170
171
  if (abs(row_offset) > 1) {
    row_offset *= 2;
    row_offset += 1;
172

173
174
175
176
177
178
    col_offset = 1;

    if (bsize < BLOCK_8X8) {
      if (mi_row & 0x01) row_offset += 1;
      if (mi_col & 0x01) col_offset -= 1;
    }
179
  }
180
181
#else
  const int mi_offset = mi_size_wide[BLOCK_8X8];
182
#endif
Jingning Han's avatar
Jingning Han committed
183

184
  for (i = 0; i < xd->n8_w && *refmv_count < MAX_REF_MV_STACK_SIZE;) {
Jingning Han's avatar
Jingning Han committed
185
    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
    mi_pos.row = row_offset;
193
    mi_pos.col = col_offset + i;
194
    if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm, &mi_pos)) {
Jingning Han's avatar
Jingning Han committed
195
196
197
      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;
198
      int len = AOMMIN(xd->n8_w, mi_size_wide[candidate->sb_type]);
199
      if (abs(row_offset) > 1) len = AOMMAX(len, mi_size_wide[BLOCK_8X8]);
200
      if (use_step_16) len = AOMMAX(mi_size_wide[BLOCK_16X16], len);
clang-format's avatar
clang-format committed
201
202
203
      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);
204
205
      i += len;
    } else {
206
      if (use_step_16)
207
        i += (mi_offset << 1);
208
      else
209
        i += mi_offset;
210
211
    }
  }
212
213

  return newmv_count;
214
215
}

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

233
234
235
236
237
238
    row_offset = 1;

    if (bsize < BLOCK_8X8) {
      if (mi_row & 0x01) row_offset -= 1;
      if (mi_col & 0x01) col_offset += 1;
    }
239
  }
240
241
#else
  const int mi_offset = mi_size_wide[BLOCK_8X8];
242
#endif
243

244
  for (i = 0; i < xd->n8_h && *refmv_count < MAX_REF_MV_STACK_SIZE;) {
245
    POSITION mi_pos;
246
247
248
#if CONFIG_CB4X4
    const int use_step_16 = (xd->n8_h >= 16);
#else
249
    const int use_step_16 = (xd->n8_h >= 8);
250
#endif
251

252
    mi_pos.row = row_offset + i;
253
    mi_pos.col = col_offset;
254
    if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm, &mi_pos)) {
255
256
257
      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;
258
      int len = AOMMIN(xd->n8_h, mi_size_high[candidate->sb_type]);
259
      if (abs(col_offset) > 1) len = AOMMAX(len, mi_size_high[BLOCK_8X8]);
260
      if (use_step_16) len = AOMMAX(mi_size_high[BLOCK_16X16], len);
clang-format's avatar
clang-format committed
261
262
263
      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);
264
265
      i += len;
    } else {
266
      if (use_step_16)
267
        i += (mi_offset << 1);
268
      else
269
        i += mi_offset;
270
271
    }
  }
272
273

  return newmv_count;
274
275
}

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

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

288
  if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm, &mi_pos) &&
289
      *refmv_count < MAX_REF_MV_STACK_SIZE) {
290
291
292
    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;
293
    const int len = mi_size_wide[BLOCK_8X8];
294

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

300
  return newmv_count;
301
302
}

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

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

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

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

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

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

339
340
341
342
#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)
343
    if ((mask_row & bs) && !(mask_col & bs)) has_tr = 0;
344
345
#endif  // CONFIG_EXT_PARTITION_TYPES

346
347
348
  return has_tr;
}

349
350
351
352
353
354
355
356
357
358
359
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;
360
  const int weight_unit = mi_size_wide[BLOCK_8X8];
361

362
363
364
365
#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
366
367
  mi_pos.row = blk_row;
  mi_pos.col = blk_col;
368
#endif
369

370
  if (!is_inside(&xd->tile, mi_col, mi_row, cm->mi_rows, cm, &mi_pos))
371
    return coll_blk_count;
372
373
374
375
376
377
378
379
380
381
382
  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;

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

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

      ++coll_blk_count;
    }
  }

  return coll_blk_count;
}

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

410
411
412
413
414
415
416
#if CONFIG_MV_COMPRESS
  const MV_REF *const prev_frame_mvs_base =
      cm->use_prev_frame_mvs
          ? cm->prev_frame->mvs + (((mi_row >> 1) << 1) + 1) * cm->mi_cols +
                ((mi_col >> 1) << 1) + 1
          : NULL;
#else
clang-format's avatar
clang-format committed
417
418
419
420
  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;
421
#endif
422

423
424
  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
425
426
  MV_REFERENCE_FRAME rf[2];

427
  av1_set_ref_frame(rf, ref_frame);
428
  mode_context[ref_frame] = 0;
429
  *refmv_count = 0;
430
431

  // Scan the first above row mode info.
432
433
  newmv_count += scan_row_mbmi(cm, xd, mi_row, mi_col, block, rf, -1,
                               ref_mv_stack, refmv_count);
434
  // Scan the first left column mode info.
clang-format's avatar
clang-format committed
435
436
  newmv_count += scan_col_mbmi(cm, xd, mi_row, mi_col, block, rf, -1,
                               ref_mv_stack, refmv_count);
437

438
439
  // Check top-right boundary
  if (has_tr)
440
441
    newmv_count += scan_blk_mbmi(cm, xd, mi_row, mi_col, block, rf, -1,
                                 xd->n8_w, ref_mv_stack, refmv_count);
442

443
  nearest_refmv_count = *refmv_count;
444

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

#if CONFIG_TPL_MV
    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

473
474
    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) {
475
476
477
        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);
478
479
      }
    }
480
481
482
483
484
485
486
487
488
489
490

#if CONFIG_TPL_MV
    for (i = 0; i < 5; ++i) {
      blk_row = tpl_sample_pos[i][0];
      blk_col = tpl_sample_pos[i][1];
      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);
    }
#endif

491
492
    if (coll_blk_count == 0) mode_context[ref_frame] |= (1 << ZEROMV_OFFSET);
  } else {
493
    mode_context[ref_frame] |= (1 << ZEROMV_OFFSET);
494
  }
495

496
  // Scan the second outer area.
Deng's avatar
Deng committed
497
498
499
500
501
502
503
504
505
506
  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);
507

508
509
510
  switch (nearest_refmv_count) {
    case 0:
      mode_context[ref_frame] |= 0;
clang-format's avatar
clang-format committed
511
      if (*refmv_count >= 1) mode_context[ref_frame] |= 1;
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539

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

540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
  // 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;
  }

555
  len = *refmv_count;
556
557
558
559
560
561
562
563
564
565
566
567
568
  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
569
  if (rf[1] > NONE_FRAME) {
570
    for (idx = 0; idx < *refmv_count; ++idx) {
571
572
573
574
      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);
575
576
    }
  } else {
Yaowu Xu's avatar
Yaowu Xu committed
577
    for (idx = 0; idx < AOMMIN(MAX_MV_REF_CANDIDATES, *refmv_count); ++idx) {
578
      mv_ref_list[idx].as_int = ref_mv_stack[idx].this_mv.as_int;
579
580
      clamp_mv_ref(&mv_ref_list[idx].as_mv, xd->n8_w << MI_SIZE_LOG2,
                   xd->n8_h << MI_SIZE_LOG2, xd);
581
    }
582
583
584
  }
}

Jingning Han's avatar
Jingning Han committed
585
586
// This function searches the neighbourhood of a given MB/SB
// to try and find candidate reference vectors.
Yaowu Xu's avatar
Yaowu Xu committed
587
static void find_mv_refs_idx(const AV1_COMMON *cm, const MACROBLOCKD *xd,
Jingning Han's avatar
Jingning Han committed
588
                             MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame,
clang-format's avatar
clang-format committed
589
590
                             int_mv *mv_ref_list, int block, int mi_row,
                             int mi_col, find_mv_refs_sync sync,
591
592
                             void *const data, int16_t *mode_context,
                             int_mv zeromv) {
Jingning Han's avatar
Jingning Han committed
593
594
595
596
  const int *ref_sign_bias = cm->ref_frame_sign_bias;
  int i, refmv_count = 0;
  int different_ref_found = 0;
  int context_counter = 0;
597
598
599
600
601
602
603
604
605
606
607
608
609
610
#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
611
612
613
614
  const MV_REF *const prev_frame_mvs =
      cm->use_prev_frame_mvs
          ? cm->prev_frame->mvs + mi_row * cm->mi_cols + mi_col
          : NULL;
615
616
617
#endif
#if CONFIG_INTRABC
  assert(IMPLIES(ref_frame == INTRA_FRAME, cm->use_prev_frame_mvs == 0));
618
#endif
Jingning Han's avatar
Jingning Han committed
619
  const TileInfo *const tile = &xd->tile;
620
621
622
  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
623
  POSITION mv_ref_search[MVREF_NEIGHBOURS];
624
625
  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
626
627
628
629
630
631
632
633
634
635
  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;
636
637
638
639
640
641
642
643
644
645
646
647
648
#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
649
650
651
652
  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;
653
#endif  // CONFIG_EXT_PARTITION_TYPES
Deng's avatar
Deng committed
654
655
656
657
  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;
658
659
660
661
662
663
664

#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
665
666
667
668
669
670

  // 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];
671
    if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm, mv_ref)) {
clang-format's avatar
clang-format committed
672
673
      const MODE_INFO *const candidate_mi =
          xd->mi[mv_ref->col + mv_ref->row * xd->mi_stride];
Jingning Han's avatar
Jingning Han committed
674
675
676
677
678
679
680
      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),
681
                        refmv_count, mv_ref_list, bw, bh, xd, Done);
Jingning Han's avatar
Jingning Han committed
682
683
      else if (candidate->ref_frame[1] == ref_frame)
        ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 1, mv_ref->col, block),
684
                        refmv_count, mv_ref_list, bw, bh, xd, Done);
Jingning Han's avatar
Jingning Han committed
685
686
687
688
689
690
691
692
    }
  }

  // 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];
693
    if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm, mv_ref)) {
clang-format's avatar
clang-format committed
694
      const MB_MODE_INFO *const candidate =
Yaowu Xu's avatar
Yaowu Xu committed
695
696
697
          !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
698
      if (candidate == NULL) continue;
699
700
      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
701
        continue;
Jingning Han's avatar
Jingning Han committed
702
703
704
      different_ref_found = 1;

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

clang-format's avatar
clang-format committed
713
714
715
716
// 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
717
#if defined(_WIN32) && !HAVE_PTHREAD_H
clang-format's avatar
clang-format committed
718
719
720
  if (cm->frame_parallel_decode && sync != NULL) {
    sync(data, mi_row);
  }
Jingning Han's avatar
Jingning Han committed
721
722
723
724
725
726
727
728
729
730
#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
731
732
      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
733
    } else if (prev_frame_mvs->ref_frame[1] == ref_frame) {
clang-format's avatar
clang-format committed
734
735
      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
736
737
738
739
740
741
742
743
744
    }
  }

  // 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];
745
      if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm, mv_ref)) {
clang-format's avatar
clang-format committed
746
        const MB_MODE_INFO *const candidate =
Yaowu Xu's avatar
Yaowu Xu committed
747
748
749
            !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
750
        if (candidate == NULL) continue;
751
752
        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
753
          continue;
Jingning Han's avatar
Jingning Han committed
754
755
756

        // 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,
757
                                 refmv_count, mv_ref_list, bw, bh, xd, Done);
Jingning Han's avatar
Jingning Han committed
758
759
760
761
762
763
764
765
766
767
768
769
770
771
      }
    }
  }

  // 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;
      }
772
      ADD_MV_REF_LIST(mv, refmv_count, mv_ref_list, bw, bh, xd, Done);
Jingning Han's avatar
Jingning Han committed
773
774
775
    }

    if (prev_frame_mvs->ref_frame[1] > INTRA_FRAME &&
776
        prev_frame_mvs->ref_frame[1] != ref_frame) {
Jingning Han's avatar
Jingning Han committed
777
778
779
780
781
782
      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;
      }
783
      ADD_MV_REF_LIST(mv, refmv_count, mv_ref_list, bw, bh, xd, Done);
Jingning Han's avatar
Jingning Han committed
784
785
786
    }
  }

787
788
789
Done:
  if (mode_context)
    mode_context[ref_frame] = counter_to_context[context_counter];
790
  for (i = refmv_count; i < MAX_MV_REF_CANDIDATES; ++i)
791
    mv_ref_list[i].as_int = zeromv.as_int;
Jingning Han's avatar
Jingning Han committed
792
793
}

Yue Chen's avatar
Yue Chen committed
794
795
#if CONFIG_EXT_INTER
// This function keeps a mode count for a given MB/SB
796
797
798
799
void av1_update_mv_context(const AV1_COMMON *cm, 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
800
801
  int i, refmv_count = 0;
  int context_counter = 0;
802
803
  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
804
  const TileInfo *const tile = &xd->tile;
805
  POSITION mv_ref_search[2];
806
807
  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];
808

809
810
811
812
  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;
Yue Chen's avatar
Yue Chen committed
813
814
815
816
817
818
819
820

  // 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];
821
    if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm, mv_ref)) {
Yue Chen's avatar
Yue Chen committed
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
      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
839
Done:
Yue Chen's avatar
Yue Chen committed
840
841
842
843
844
845

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

Yaowu Xu's avatar
Yaowu Xu committed
846
847
848
void av1_find_mv_refs(const AV1_COMMON *cm, const MACROBLOCKD *xd,
                      MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame,
                      uint8_t *ref_mv_count, CANDIDATE_MV *ref_mv_stack,
849
#if CONFIG_EXT_INTER
Yaowu Xu's avatar
Yaowu Xu committed
850
                      int16_t *compound_mode_context,
851
#endif  // CONFIG_EXT_INTER
Yaowu Xu's avatar
Yaowu Xu committed
852
853
854
                      int_mv *mv_ref_list, int mi_row, int mi_col,
                      find_mv_refs_sync sync, void *const data,
                      int16_t *mode_context) {
855
  int_mv zeromv[2];
856
857
858
#if CONFIG_GLOBAL_MOTION
  BLOCK_SIZE bsize = mi->mbmi.sb_type;
#endif  // CONFIG_GLOBAL_MOTION
859
860
861
  int idx, all_zero = 1;
#if CONFIG_GLOBAL_MOTION
  MV_REFERENCE_FRAME rf[2];
862
#endif  // CONFIG_GLOBAL_MOTION
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
863

Yue Chen's avatar
Yue Chen committed
864
#if CONFIG_EXT_INTER
865
  av1_update_mv_context(cm, xd, mi, ref_frame, mv_ref_list, -1, mi_row, mi_col,
Yaowu Xu's avatar
Yaowu Xu committed
866
                        compound_mode_context);
Yaowu Xu's avatar
Yaowu Xu committed
867
#endif  // CONFIG_EXT_INTER
868
869

#if CONFIG_GLOBAL_MOTION
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
  if (!CONFIG_INTRABC || ref_frame != INTRA_FRAME) {
    av1_set_ref_frame(rf, ref_frame);
    zeromv[0].as_int = gm_get_motion_vector(&cm->global_motion[rf[0]],
                                            cm->allow_high_precision_mv, bsize,
                                            mi_col, mi_row, 0)
                           .as_int;
    zeromv[1].as_int = (rf[1] != NONE_FRAME)
                           ? gm_get_motion_vector(&cm->global_motion[rf[1]],
                                                  cm->allow_high_precision_mv,
                                                  bsize, mi_col, mi_row, 0)
                                 .as_int
                           : 0;
  } else {
    zeromv[0].as_int = zeromv[1].as_int = 0;
  }
885
886
#else
  zeromv[0].as_int = zeromv[1].as_int = 0;
887
#endif  // CONFIG_GLOBAL_MOTION
888

Yaowu Xu's avatar
Yaowu Xu committed
889
  if (ref_frame <= ALTREF_FRAME)
890
891
    find_mv_refs_idx(cm, xd, mi, ref_frame, mv_ref_list, -1, mi_row, mi_col,
                     sync, data, mode_context, zeromv[0]);
892

clang-format's avatar
clang-format committed
893
894
  setup_ref_mv_list(cm, xd, ref_frame, ref_mv_count, ref_mv_stack, mv_ref_list,
                    -1, mi_row, mi_col, mode_context);
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
  /* 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
910
911
  if (*ref_mv_count >= 2) {
    for (idx = 0; idx < AOMMIN(3, *ref_mv_count); ++idx) {
912
      if (ref_mv_stack[idx].this_mv.as_int != zeromv[0].as_int) all_zero = 0;
Yaowu Xu's avatar
Yaowu Xu committed
913
      if (ref_frame > ALTREF_FRAME)
914
        if (ref_mv_stack[idx].comp_mv.as_int != zeromv[1].as_int) all_zero = 0;
Yaowu Xu's avatar
Yaowu Xu committed
915
916
917
    }
  } else if (ref_frame <= ALTREF_FRAME) {
    for (idx = 0; idx < MAX_MV_REF_CANDIDATES; ++idx)
918
      if (mv_ref_list[idx].as_int != zeromv[0].as_int) all_zero = 0;
Yaowu Xu's avatar
Yaowu Xu committed
919
  }
920

clang-format's avatar
clang-format committed
921
  if (all_zero) mode_context[ref_frame] |= (1 << ALL_ZERO_FLAG_OFFSET);
Jingning Han's avatar
Jingning Han committed
922
923
}

Yaowu Xu's avatar
Yaowu Xu committed
924
925
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
926
927
928
929
930
931
932
933
934
  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];
}

935
936
void av1_append_sub8x8_mvs_for_idx(const AV1_COMMON *cm, MACROBLOCKD *xd,
                                   int block, int ref, int mi_row, int mi_col,
Yaowu Xu's avatar
Yaowu Xu committed
937
938
                                   CANDIDATE_MV *ref_mv_stack,
                                   uint8_t *ref_mv_count,
Yue Chen's avatar
Yue Chen committed
939
#if CONFIG_EXT_INTER
Yaowu Xu's avatar
Yaowu Xu committed
940
                                   int_mv *mv_list,
Yue Chen's avatar
Yue Chen committed
941
#endif  // CONFIG_EXT_INTER
Yaowu Xu's avatar
Yaowu Xu committed
942
                                   int_mv *nearest_mv, int_mv *near_mv) {
Yue Chen's avatar
Yue Chen committed
943
#if !CONFIG_EXT_INTER
Jingning Han's avatar
Jingning Han committed
944
  int_mv mv_list[MAX_MV_REF_CANDIDATES];
Yue Chen's avatar
Yue Chen committed
945
#endif  // !CONFIG_EXT_INTER
Jingning Han's avatar
Jingning Han committed
946
947
948
  MODE_INFO *const mi = xd->mi[0];
  b_mode_info *bmi = mi->bmi;
  int n;
949
  int_mv zeromv;
950
  CANDIDATE_MV tmp_mv;
951
  uint8_t idx;
952
  uint8_t above_count = 0, left_count = 0;
Emil Keyder's avatar
Emil Keyder committed
953
  MV_REFERENCE_FRAME rf[2] = { mi->mbmi.ref_frame[ref], NONE_FRAME };
954
  *ref_mv_count = 0;
Jingning Han's avatar
Jingning Han committed
955
956
957

  assert(MAX_MV_REF_CANDIDATES == 2);

958
#if CONFIG_GLOBAL_MOTION
David Barker's avatar
David Barker committed
959
960
961
962
  zeromv.as_int = gm_get_motion_vector(&cm->global_motion[rf[0]],
                                       cm->allow_high_precision_mv,
                                       mi->mbmi.sb_type, mi_col, mi_row, block)
                      .as_int;
963
964
965
#else
  zeromv.as_int = 0;
#endif
clang-format's avatar
clang-format committed
966
  find_mv_refs_idx(cm, xd, mi, mi->mbmi.ref_frame[ref], mv_list, block, mi_row,
967
                   mi_col, NULL, NULL, NULL, zeromv);
Jingning Han's avatar
Jingning Han committed
968

clang-format's avatar
clang-format committed
969
970
  scan_blk_mbmi(cm, xd, mi_row, mi_col, block, rf, -1, 0, ref_mv_stack,
                ref_mv_count);
971
  above_count = *ref_mv_count;
972

clang-format's avatar
clang-format committed
973
974
  scan_blk_mbmi(cm, xd, mi_row, mi_col, block, rf, 0, -1, ref_mv_stack,
                ref_mv_count);
975
  left_count = *ref_mv_count - above_count;
976
977
978
979
980
981
982

  if (above_count > 1 && left_count > 0) {
    tmp_mv = ref_mv_stack[1];
    ref_mv_stack[1] = ref_mv_stack[above_count];
    ref_mv_stack[above_count] = tmp_mv;
  }

983
  for (idx = 0; idx < *ref_mv_count; ++idx)