mvref_common.c 29.6 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"
Jingning Han's avatar
Jingning Han committed
13

14
#if CONFIG_REF_MV
15

clang-format's avatar
clang-format committed
16
17
18
19
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
20
21
22
23
24
25
26
  int index = 0, ref;
  int newmv_count = 0;

  if (rf[1] == NONE) {
    // single reference frame
    for (ref = 0; ref < 2; ++ref) {
      if (candidate->ref_frame[ref] == rf[0]) {
clang-format's avatar
clang-format committed
27
        int_mv this_refmv = get_sub_block_mv(candidate_mi, ref, col, block);
28
29
        lower_mv_precision(&this_refmv.as_mv, use_hp);

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

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

Jingning Han's avatar
Jingning Han committed
35
36
37
        // Add a new item to the list.
        if (index == *refmv_count) {
          ref_mv_stack[index].this_mv = this_refmv;
Yaowu Xu's avatar
Yaowu Xu committed
38
          ref_mv_stack[index].pred_mv[0] =
Jingning Han's avatar
Jingning Han committed
39
              get_sub_block_pred_mv(candidate_mi, ref, col, block);
Yaowu Xu's avatar
Yaowu Xu committed
40
          ref_mv_stack[index].weight = 2 * len;
Jingning Han's avatar
Jingning Han committed
41
          ++(*refmv_count);
42

43
44
45
#if CONFIG_EXT_INTER
          if (candidate->mode == NEWMV || candidate->mode == NEWFROMNEARMV)
#else
Jingning Han's avatar
Jingning Han committed
46
          if (candidate->mode == NEWMV)
47
#endif  // CONFIG_EXT_INTER
Jingning Han's avatar
Jingning Han committed
48
49
50
51
52
            ++newmv_count;
        }

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

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

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

          // Add a new item to the list.
          if (index == *refmv_count) {
            ref_mv_stack[index].this_mv = this_refmv;
Yaowu Xu's avatar
Yaowu Xu committed
64
            ref_mv_stack[index].pred_mv[0] =
Jingning Han's avatar
Jingning Han committed
65
                get_sub_block_pred_mv(candidate_mi, ref, col, alt_block);
Yaowu Xu's avatar
Yaowu Xu committed
66
            ref_mv_stack[index].weight = len;
67
            ++(*refmv_count);
68

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

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

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

      // 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];
Yaowu Xu's avatar
Yaowu Xu committed
100
101
102
103
        ref_mv_stack[index].pred_mv[0] =
            get_sub_block_pred_mv(candidate_mi, 0, col, block);
        ref_mv_stack[index].pred_mv[1] =
            get_sub_block_pred_mv(candidate_mi, 1, col, block);
Yaowu Xu's avatar
Yaowu Xu committed
104
        ref_mv_stack[index].weight = 2 * len;
Jingning Han's avatar
Jingning Han committed
105
106
        ++(*refmv_count);

107
108
109
#if CONFIG_EXT_INTER
        if (candidate->mode == NEW_NEWMV)
#else
Jingning Han's avatar
Jingning Han committed
110
        if (candidate->mode == NEWMV)
111
#endif  // CONFIG_EXT_INTER
Jingning Han's avatar
Jingning Han committed
112
113
114
115
116
117
118
119
          ++newmv_count;
      }

      if (candidate_mi->mbmi.sb_type < BLOCK_8X8 && block >= 0) {
        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);

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

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

        // 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];
Yaowu Xu's avatar
Yaowu Xu committed
134
135
136
137
          ref_mv_stack[index].pred_mv[0] =
              get_sub_block_pred_mv(candidate_mi, 0, col, block);
          ref_mv_stack[index].pred_mv[1] =
              get_sub_block_pred_mv(candidate_mi, 1, col, block);
Yaowu Xu's avatar
Yaowu Xu committed
138
          ref_mv_stack[index].weight = len;
Jingning Han's avatar
Jingning Han committed
139
140
          ++(*refmv_count);

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

Yaowu Xu's avatar
Yaowu Xu committed
154
static uint8_t scan_row_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
Jingning Han's avatar
Jingning Han committed
155
                             const int mi_row, const int mi_col, int block,
clang-format's avatar
clang-format committed
156
157
                             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
158
159
160
161
162
163
  const TileInfo *const tile = &xd->tile;
  int i;
  uint8_t newmv_count = 0;

  for (i = 0; i < xd->n8_w && *refmv_count < MAX_REF_MV_STACK_SIZE;) {
    POSITION mi_pos;
164
165
    const int use_step_16 = (xd->n8_w >= 8);

Jingning Han's avatar
Jingning Han committed
166
167
    mi_pos.row = row_offset;
    mi_pos.col = i;
Geza Lore's avatar
Geza Lore committed
168
    if (is_inside(tile, mi_col, mi_row, &mi_pos)) {
Jingning Han's avatar
Jingning Han committed
169
170
171
      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;
172
      int len =
Yaowu Xu's avatar
Yaowu Xu committed
173
          AOMMIN(xd->n8_w, num_8x8_blocks_wide_lookup[candidate->sb_type]);
174
      if (use_step_16) len = AOMMAX(2, len);
clang-format's avatar
clang-format committed
175
176
177
      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);
178
179
      i += len;
    } else {
180
181
182
183
      if (use_step_16)
        i += 2;
      else
        ++i;
184
185
    }
  }
186
187

  return newmv_count;
188
189
}

Yaowu Xu's avatar
Yaowu Xu committed
190
static uint8_t scan_col_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
191
                             const int mi_row, const int mi_col, int block,
clang-format's avatar
clang-format committed
192
193
                             const MV_REFERENCE_FRAME rf[2], int col_offset,
                             CANDIDATE_MV *ref_mv_stack, uint8_t *refmv_count) {
194
195
  const TileInfo *const tile = &xd->tile;
  int i;
196
  uint8_t newmv_count = 0;
197
198
199

  for (i = 0; i < xd->n8_h && *refmv_count < MAX_REF_MV_STACK_SIZE;) {
    POSITION mi_pos;
200
201
    const int use_step_16 = (xd->n8_h >= 8);

202
203
    mi_pos.row = i;
    mi_pos.col = col_offset;
Geza Lore's avatar
Geza Lore committed
204
    if (is_inside(tile, mi_col, mi_row, &mi_pos)) {
205
206
207
      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;
208
      int len =
Yaowu Xu's avatar
Yaowu Xu committed
209
          AOMMIN(xd->n8_h, num_8x8_blocks_high_lookup[candidate->sb_type]);
210
      if (use_step_16) len = AOMMAX(2, len);
clang-format's avatar
clang-format committed
211
212
213
      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);
214
215
      i += len;
    } else {
216
217
218
219
      if (use_step_16)
        i += 2;
      else
        ++i;
220
221
    }
  }
222
223

  return newmv_count;
224
225
}

Yaowu Xu's avatar
Yaowu Xu committed
226
static uint8_t scan_blk_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
227
                             const int mi_row, const int mi_col, int block,
clang-format's avatar
clang-format committed
228
229
                             const MV_REFERENCE_FRAME rf[2], int row_offset,
                             int col_offset, CANDIDATE_MV *ref_mv_stack,
230
                             uint8_t *refmv_count) {
231
232
  const TileInfo *const tile = &xd->tile;
  POSITION mi_pos;
233
  uint8_t newmv_count = 0;
234
235
236
237

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

Geza Lore's avatar
Geza Lore committed
238
  if (is_inside(tile, mi_col, mi_row, &mi_pos) &&
239
240
241
242
243
      *refmv_count < MAX_REF_MV_STACK_SIZE) {
    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;
    const int len = 1;
244

clang-format's avatar
clang-format committed
245
246
247
    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);
248
  }  // Analyze a single 8x8 block motion information.
Yaowu Xu's avatar
Yaowu Xu committed
249

250
  return newmv_count;
251
252
}

clang-format's avatar
clang-format committed
253
254
static int has_top_right(const MACROBLOCKD *xd, int mi_row, int mi_col,
                         int bs) {
255
  // In a split partition all apart from the bottom right has a top right
256
  int has_tr = !((mi_row & bs) && (mi_col & bs));
257

258
259
  // bs > 0 and bs is a power of 2
  assert(bs > 0 && !(bs & (bs - 1)));
260

261
262
263
  // 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
264
  while (bs < MAX_MIB_SIZE) {
265
266
    if (mi_col & bs) {
      if ((mi_col & (2 * bs)) && (mi_row & (2 * bs))) {
267
        has_tr = 0;
268
269
270
271
272
273
274
        break;
      }
    } else {
      break;
    }
    bs <<= 1;
  }
275

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

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

286
287
288
289
#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)
clang-format's avatar
clang-format committed
290
    if ((mi_row & bs) && !(mi_col & bs)) has_tr = 0;
291
292
#endif  // CONFIG_EXT_PARTITION_TYPES

293
294
295
  return has_tr;
}

clang-format's avatar
clang-format committed
296
static void handle_sec_rect_block(const MB_MODE_INFO *const candidate,
297
                                  uint8_t refmv_count,
298
299
300
301
302
303
304
                                  CANDIDATE_MV *ref_mv_stack,
                                  MV_REFERENCE_FRAME ref_frame,
                                  int16_t *mode_context) {
  int rf, idx;

  for (rf = 0; rf < 2; ++rf) {
    if (candidate->ref_frame[rf] == ref_frame) {
Yaowu Xu's avatar
Yaowu Xu committed
305
      const int list_range = AOMMIN(refmv_count, MAX_MV_REF_CANDIDATES);
306
307
308

      const int_mv pred_mv = candidate->mv[rf];
      for (idx = 0; idx < list_range; ++idx)
clang-format's avatar
clang-format committed
309
        if (pred_mv.as_int == ref_mv_stack[idx].this_mv.as_int) break;
310
311

      if (idx < list_range) {
312
        if (idx == 0)
313
          mode_context[ref_frame] |= (1 << SKIP_NEARESTMV_OFFSET);
314
        else if (idx == 1)
315
316
317
318
319
320
          mode_context[ref_frame] |= (1 << SKIP_NEARMV_OFFSET);
      }
    }
  }
}

321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
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;

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

  if (!is_inside(&xd->tile, mi_col, mi_row, &mi_pos)) return coll_blk_count;

  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;

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

      if (idx == *refmv_count && *refmv_count < MAX_REF_MV_STACK_SIZE) {
        ref_mv_stack[idx].this_mv.as_int = this_refmv.as_int;
Yaowu Xu's avatar
Yaowu Xu committed
353
        ref_mv_stack[idx].pred_mv[0] = prev_frame_mvs->pred_mv[ref];
354
355
356
357
358
359
360
361
362
363
364
        ref_mv_stack[idx].weight = 2;
        ++(*refmv_count);
      }

      ++coll_blk_count;
    }
  }

  return coll_blk_count;
}

Yaowu Xu's avatar
Yaowu Xu committed
365
static void setup_ref_mv_list(const AV1_COMMON *cm, const MACROBLOCKD *xd,
366
                              MV_REFERENCE_FRAME ref_frame,
clang-format's avatar
clang-format committed
367
368
369
                              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) {
370
  int idx, nearest_refmv_count = 0;
371
  uint8_t newmv_count = 0;
372
373
374
  CANDIDATE_MV tmp_mv;
  int len, nr_len;

clang-format's avatar
clang-format committed
375
376
377
378
  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;
379

380
381
  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
382
383
  MV_REFERENCE_FRAME rf[2];

384
  av1_set_ref_frame(rf, ref_frame);
385
  mode_context[ref_frame] = 0;
386
  *refmv_count = 0;
387
388

  // Scan the first above row mode info.
389
390
  newmv_count += scan_row_mbmi(cm, xd, mi_row, mi_col, block, rf, -1,
                               ref_mv_stack, refmv_count);
391
  // Scan the first left column mode info.
clang-format's avatar
clang-format committed
392
393
  newmv_count += scan_col_mbmi(cm, xd, mi_row, mi_col, block, rf, -1,
                               ref_mv_stack, refmv_count);
394

395
396
  // Check top-right boundary
  if (has_tr)
clang-format's avatar
clang-format committed
397
398
    newmv_count += scan_blk_mbmi(cm, xd, mi_row, mi_col, block, rf, -1, 1,
                                 ref_mv_stack, refmv_count);
399

400
  nearest_refmv_count = *refmv_count;
401

402
  for (idx = 0; idx < nearest_refmv_count; ++idx)
403
404
    ref_mv_stack[idx].weight += REF_CAT_LEVEL;

clang-format's avatar
clang-format committed
405
406
  if (prev_frame_mvs_base && cm->show_frame && cm->last_show_frame &&
      rf[1] == NONE) {
407
    int blk_row, blk_col;
408
    int coll_blk_count = 0;
409

410
411
    for (blk_row = 0; blk_row < xd->n8_h; blk_row += 2) {
      for (blk_col = 0; blk_col < xd->n8_w; blk_col += 2) {
412
413
414
        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);
415
416
      }
    }
417
418
    if (coll_blk_count == 0) mode_context[ref_frame] |= (1 << ZEROMV_OFFSET);
  } else {
419
    mode_context[ref_frame] |= (1 << ZEROMV_OFFSET);
420
  }
421
422

  // Scan the second outer area.
423
424
425
426
427
428
  for (idx = 2; idx <= 4; ++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);
  }
429

430
431
432
  switch (nearest_refmv_count) {
    case 0:
      mode_context[ref_frame] |= 0;
clang-format's avatar
clang-format committed
433
      if (*refmv_count >= 1) mode_context[ref_frame] |= 1;
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461

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

462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
  // 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;
  }

477
  len = *refmv_count;
478
479
480
481
482
483
484
485
486
487
488
489
490
  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;
  }

491
492
493
494
495
  // TODO(jingning): Clean-up needed.
  if (xd->is_sec_rect) {
    if (xd->n8_w < xd->n8_h) {
      const MODE_INFO *const candidate_mi = xd->mi[-1];
      const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
496
      handle_sec_rect_block(candidate, nearest_refmv_count, ref_mv_stack,
497
498
499
500
501
502
                            ref_frame, mode_context);
    }

    if (xd->n8_w > xd->n8_h) {
      const MODE_INFO *const candidate_mi = xd->mi[-xd->mi_stride];
      const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
503
      handle_sec_rect_block(candidate, nearest_refmv_count, ref_mv_stack,
504
505
506
507
                            ref_frame, mode_context);
    }
  }

508
509
  if (rf[1] > NONE) {
    for (idx = 0; idx < *refmv_count; ++idx) {
clang-format's avatar
clang-format committed
510
511
512
513
      clamp_mv_ref(&ref_mv_stack[idx].this_mv.as_mv, xd->n8_w << 3,
                   xd->n8_h << 3, xd);
      clamp_mv_ref(&ref_mv_stack[idx].comp_mv.as_mv, xd->n8_w << 3,
                   xd->n8_h << 3, xd);
514
515
    }
  } else {
Yaowu Xu's avatar
Yaowu Xu committed
516
    for (idx = 0; idx < AOMMIN(MAX_MV_REF_CANDIDATES, *refmv_count); ++idx) {
517
      mv_ref_list[idx].as_int = ref_mv_stack[idx].this_mv.as_int;
clang-format's avatar
clang-format committed
518
      clamp_mv_ref(&mv_ref_list[idx].as_mv, xd->n8_w << 3, xd->n8_h << 3, xd);
519
    }
520
521
522
523
  }
}
#endif

Jingning Han's avatar
Jingning Han committed
524
525
// This function searches the neighbourhood of a given MB/SB
// to try and find candidate reference vectors.
Yaowu Xu's avatar
Yaowu Xu committed
526
static void find_mv_refs_idx(const AV1_COMMON *cm, const MACROBLOCKD *xd,
Jingning Han's avatar
Jingning Han committed
527
                             MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame,
clang-format's avatar
clang-format committed
528
529
530
                             int_mv *mv_ref_list, int block, int mi_row,
                             int mi_col, find_mv_refs_sync sync,
                             void *const data, int16_t *mode_context) {
Jingning Han's avatar
Jingning Han committed
531
532
533
534
535
  const int *ref_sign_bias = cm->ref_frame_sign_bias;
  int i, refmv_count = 0;
  const POSITION *const mv_ref_search = mv_ref_blocks[mi->mbmi.sb_type];
  int different_ref_found = 0;
  int context_counter = 0;
clang-format's avatar
clang-format committed
536
537
538
539
  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
540
  const TileInfo *const tile = &xd->tile;
541
542
  const int bw = num_8x8_blocks_wide_lookup[mi->mbmi.sb_type] << 3;
  const int bh = num_8x8_blocks_high_lookup[mi->mbmi.sb_type] << 3;
Jingning Han's avatar
Jingning Han committed
543
544
545
546
547
548

  // 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];
Geza Lore's avatar
Geza Lore committed
549
    if (is_inside(tile, mi_col, mi_row, mv_ref)) {
clang-format's avatar
clang-format committed
550
551
      const MODE_INFO *const candidate_mi =
          xd->mi[mv_ref->col + mv_ref->row * xd->mi_stride];
Jingning Han's avatar
Jingning Han committed
552
553
554
555
556
557
558
      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),
559
                        refmv_count, mv_ref_list, bw, bh, xd, Done);
Jingning Han's avatar
Jingning Han committed
560
561
      else if (candidate->ref_frame[1] == ref_frame)
        ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 1, mv_ref->col, block),
562
                        refmv_count, mv_ref_list, bw, bh, xd, Done);
Jingning Han's avatar
Jingning Han committed
563
564
565
566
567
568
569
570
    }
  }

  // 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];
Geza Lore's avatar
Geza Lore committed
571
    if (is_inside(tile, mi_col, mi_row, mv_ref)) {
clang-format's avatar
clang-format committed
572
573
      const MB_MODE_INFO *const candidate =
          &xd->mi[mv_ref->col + mv_ref->row * xd->mi_stride]->mbmi;
Jingning Han's avatar
Jingning Han committed
574
575
576
      different_ref_found = 1;

      if (candidate->ref_frame[0] == ref_frame)
clang-format's avatar
clang-format committed
577
578
        ADD_MV_REF_LIST(candidate->mv[0], refmv_count, mv_ref_list, bw, bh, xd,
                        Done);
Jingning Han's avatar
Jingning Han committed
579
      else if (candidate->ref_frame[1] == ref_frame)
clang-format's avatar
clang-format committed
580
581
        ADD_MV_REF_LIST(candidate->mv[1], refmv_count, mv_ref_list, bw, bh, xd,
                        Done);
Jingning Han's avatar
Jingning Han committed
582
583
584
    }
  }

clang-format's avatar
clang-format committed
585
586
587
588
// 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
589
#if defined(_WIN32) && !HAVE_PTHREAD_H
clang-format's avatar
clang-format committed
590
591
592
  if (cm->frame_parallel_decode && sync != NULL) {
    sync(data, mi_row);
  }
Jingning Han's avatar
Jingning Han committed
593
594
595
596
597
598
599
600
601
602
#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
603
604
      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
605
    } else if (prev_frame_mvs->ref_frame[1] == ref_frame) {
clang-format's avatar
clang-format committed
606
607
      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
608
609
610
611
612
613
614
615
616
    }
  }

  // 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];
Geza Lore's avatar
Geza Lore committed
617
      if (is_inside(tile, mi_col, mi_row, mv_ref)) {
clang-format's avatar
clang-format committed
618
619
        const MB_MODE_INFO *const candidate =
            &xd->mi[mv_ref->col + mv_ref->row * xd->mi_stride]->mbmi;
Jingning Han's avatar
Jingning Han committed
620
621
622

        // 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,
623
                                 refmv_count, mv_ref_list, bw, bh, xd, Done);
Jingning Han's avatar
Jingning Han committed
624
625
626
627
628
629
630
631
632
633
634
635
636
637
      }
    }
  }

  // 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;
      }
638
      ADD_MV_REF_LIST(mv, refmv_count, mv_ref_list, bw, bh, xd, Done);
Jingning Han's avatar
Jingning Han committed
639
640
641
    }

    if (prev_frame_mvs->ref_frame[1] > INTRA_FRAME &&
642
        prev_frame_mvs->ref_frame[1] != ref_frame) {
Jingning Han's avatar
Jingning Han committed
643
644
645
646
647
648
      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;
      }
649
      ADD_MV_REF_LIST(mv, refmv_count, mv_ref_list, bw, bh, xd, Done);
Jingning Han's avatar
Jingning Han committed
650
651
652
    }
  }

653
654
655
Done:
  if (mode_context)
    mode_context[ref_frame] = counter_to_context[context_counter];
656
  for (i = refmv_count; i < MAX_MV_REF_CANDIDATES; ++i)
clang-format's avatar
clang-format committed
657
    mv_ref_list[i].as_int = 0;
Jingning Han's avatar
Jingning Han committed
658
659
}

Yue Chen's avatar
Yue Chen committed
660
661
#if CONFIG_EXT_INTER
// This function keeps a mode count for a given MB/SB
Yaowu Xu's avatar
Yaowu Xu committed
662
663
664
665
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
666
667
668
669
670
671
672
673
674
675
676
677
678
679
  int i, refmv_count = 0;
  const POSITION *const mv_ref_search = mv_ref_blocks[mi->mbmi.sb_type];
  int context_counter = 0;
  const int bw = num_8x8_blocks_wide_lookup[mi->mbmi.sb_type] << 3;
  const int bh = num_8x8_blocks_high_lookup[mi->mbmi.sb_type] << 3;
  const TileInfo *const tile = &xd->tile;

  // 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];
Geza Lore's avatar
Geza Lore committed
680
    if (is_inside(tile, mi_col, mi_row, mv_ref)) {
Yue Chen's avatar
Yue Chen committed
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
      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
698
Done:
Yue Chen's avatar
Yue Chen committed
699
700
701
702
703
704

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

Yaowu Xu's avatar
Yaowu Xu committed
705
706
void av1_find_mv_refs(const AV1_COMMON *cm, const MACROBLOCKD *xd,
                      MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame,
707
#if CONFIG_REF_MV
Yaowu Xu's avatar
Yaowu Xu committed
708
                      uint8_t *ref_mv_count, CANDIDATE_MV *ref_mv_stack,
709
#if CONFIG_EXT_INTER
Yaowu Xu's avatar
Yaowu Xu committed
710
                      int16_t *compound_mode_context,
711
#endif  // CONFIG_EXT_INTER
712
#endif
Yaowu Xu's avatar
Yaowu Xu committed
713
714
715
                      int_mv *mv_ref_list, int mi_row, int mi_col,
                      find_mv_refs_sync sync, void *const data,
                      int16_t *mode_context) {
716
717
718
#if CONFIG_REF_MV
  int idx, all_zero = 1;
#endif
Yue Chen's avatar
Yue Chen committed
719
#if CONFIG_EXT_INTER
Yaowu Xu's avatar
Yaowu Xu committed
720
  av1_update_mv_context(xd, mi, ref_frame, mv_ref_list, -1, mi_row, mi_col,
721
#if CONFIG_REF_MV
Yaowu Xu's avatar
Yaowu Xu committed
722
                        compound_mode_context);
723
#else
Yaowu Xu's avatar
Yaowu Xu committed
724
                        mode_context);
725
#endif  // CONFIG_REF_MV
Yaowu Xu's avatar
Yaowu Xu committed
726
727
728
729
730
#endif  // CONFIG_EXT_INTER
#if CONFIG_REF_MV
  if (ref_frame <= ALTREF_FRAME)
    find_mv_refs_idx(cm, xd, mi, ref_frame, mv_ref_list, -1, mi_row, mi_col,
                     sync, data, mode_context);
Yue Chen's avatar
Yue Chen committed
731
#else
clang-format's avatar
clang-format committed
732
733
  find_mv_refs_idx(cm, xd, mi, ref_frame, mv_ref_list, -1, mi_row, mi_col, sync,
                   data, mode_context);
Yaowu Xu's avatar
Yaowu Xu committed
734
#endif  // CONFIG_REF_MV
735
736

#if CONFIG_REF_MV
clang-format's avatar
clang-format committed
737
738
  setup_ref_mv_list(cm, xd, ref_frame, ref_mv_count, ref_mv_stack, mv_ref_list,
                    -1, mi_row, mi_col, mode_context);
739

Yaowu Xu's avatar
Yaowu Xu committed
740
741
742
743
744
745
746
747
748
749
  if (*ref_mv_count >= 2) {
    for (idx = 0; idx < AOMMIN(3, *ref_mv_count); ++idx) {
      if (ref_mv_stack[idx].this_mv.as_int != 0) all_zero = 0;
      if (ref_frame > ALTREF_FRAME)
        if (ref_mv_stack[idx].comp_mv.as_int != 0) all_zero = 0;
    }
  } else if (ref_frame <= ALTREF_FRAME) {
    for (idx = 0; idx < MAX_MV_REF_CANDIDATES; ++idx)
      if (mv_ref_list[idx].as_int != 0) all_zero = 0;
  }
750

clang-format's avatar
clang-format committed
751
  if (all_zero) mode_context[ref_frame] |= (1 << ALL_ZERO_FLAG_OFFSET);
752
#endif
Jingning Han's avatar
Jingning Han committed
753
754
}

Yaowu Xu's avatar
Yaowu Xu committed
755
756
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
757
758
759
760
761
762
763
764
765
  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];
}

Yaowu Xu's avatar
Yaowu Xu committed
766
767
void av1_append_sub8x8_mvs_for_idx(AV1_COMMON *cm, MACROBLOCKD *xd, int block,
                                   int ref, int mi_row, int mi_col,
768
#if CONFIG_REF_MV
Yaowu Xu's avatar
Yaowu Xu committed
769
770
                                   CANDIDATE_MV *ref_mv_stack,
                                   uint8_t *ref_mv_count,
771
#endif
Yue Chen's avatar
Yue Chen committed
772
#if CONFIG_EXT_INTER
Yaowu Xu's avatar
Yaowu Xu committed
773
                                   int_mv *mv_list,
Yue Chen's avatar
Yue Chen committed
774
#endif  // CONFIG_EXT_INTER
Yaowu Xu's avatar
Yaowu Xu committed
775
                                   int_mv *nearest_mv, int_mv *near_mv) {
Yue Chen's avatar
Yue Chen committed
776
#if !CONFIG_EXT_INTER
Jingning Han's avatar
Jingning Han committed
777
  int_mv mv_list[MAX_MV_REF_CANDIDATES];
Yue Chen's avatar
Yue Chen committed
778
#endif  // !CONFIG_EXT_INTER
Jingning Han's avatar
Jingning Han committed
779
780
781
  MODE_INFO *const mi = xd->mi[0];
  b_mode_info *bmi = mi->bmi;
  int n;
782
783
#if CONFIG_REF_MV
  CANDIDATE_MV tmp_mv;
784
  uint8_t idx;
785
  uint8_t above_count = 0, left_count = 0;
Jingning Han's avatar
Jingning Han committed
786
  MV_REFERENCE_FRAME rf[2] = { mi->mbmi.ref_frame[ref], NONE };
787
  *ref_mv_count = 0;
788
#endif
Jingning Han's avatar
Jingning Han committed
789
790
791

  assert(MAX_MV_REF_CANDIDATES == 2);

clang-format's avatar
clang-format committed
792
793
  find_mv_refs_idx(cm, xd, mi, mi->mbmi.ref_frame[ref], mv_list, block, mi_row,
                   mi_col, NULL, NULL, NULL);
Jingning Han's avatar
Jingning Han committed
794

795
#if CONFIG_REF_MV
clang-format's avatar
clang-format committed
796
797
  scan_blk_mbmi(cm, xd, mi_row, mi_col, block, rf, -1, 0, ref_mv_stack,
                ref_mv_count);
798
  above_count = *ref_mv_count;
799

clang-format's avatar
clang-format committed
800
801
  scan_blk_mbmi(cm, xd, mi_row, mi_col, block, rf, 0, -1, ref_mv_stack,
                ref_mv_count);
802
  left_count = *ref_mv_count - above_count;
803
804
805
806
807
808
809

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

810
  for (idx = 0; idx < *ref_mv_count; ++idx)
clang-format's avatar
clang-format committed
811
812
    clamp_mv_ref(&ref_mv_stack[idx].this_mv.as_mv, xd->n8_w << 3, xd->n8_h << 3,
                 xd);
813

Yaowu Xu's avatar
Yaowu Xu committed
814
  for (idx = 0; idx < AOMMIN(MAX_MV_REF_CANDIDATES, *ref_mv_count); ++idx)
815
    mv_list[idx].as_int = ref_mv_stack[idx].this_mv.as_int;
816
817
#endif

Jingning Han's avatar
Jingning Han committed
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
  near_mv->as_int = 0;
  switch (block) {
    case 0:
      nearest_mv->as_int = mv_list[0].as_int;
      near_mv->as_int = mv_list[1].as_int;
      break;
    case 1:
    case 2:
      nearest_mv->as_int = bmi[0].as_mv[ref].as_int;
      for (n = 0; n < MAX_MV_REF_CANDIDATES; ++n)
        if (nearest_mv->as_int != mv_list[n].as_int) {
          near_mv->as_int = mv_list[n].as_int;
          break;
        }
      break;
    case 3: {
      int_mv candidates[2 + MAX_MV_REF_CANDIDATES];
      candidates[0] = bmi[1].as_mv[ref];
      candidates[1] = bmi[0].as_mv[ref];
      candidates[2] = mv_list[0];
      candidates[3] = mv_list[1];

      nearest_mv->as_int = bmi[2].as_mv[ref].as_int;
      for (n = 0; n < 2 + MAX_MV_REF_CANDIDATES; ++n)
        if (nearest_mv->as_int != candidates[n].as_int) {
          near_mv->as_int = candidates[n].as_int;
          break;
        }
      break;
    }
clang-format's avatar
clang-format committed
848
    default: assert(0 && "Invalid block index.");
Jingning Han's avatar
Jingning Han committed
849
850
  }
}