Line data Source code
1 : /*
2 : * Copyright (c) 2016, Alliance for Open Media. All rights reserved
3 : *
4 : * This source code is subject to the terms of the BSD 2 Clause License and
5 : * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6 : * was not distributed with this source code in the LICENSE file, you can
7 : * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8 : * Media Patent License 1.0 was not distributed with this source code in the
9 : * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10 : */
11 :
12 : #include "av1/common/mvref_common.h"
13 : #if CONFIG_WARPED_MOTION
14 : #include "av1/common/warped_motion.h"
15 : #endif // CONFIG_WARPED_MOTION
16 :
17 0 : static uint8_t add_ref_mv_candidate(
18 : const MODE_INFO *const candidate_mi, const MB_MODE_INFO *const candidate,
19 : const MV_REFERENCE_FRAME rf[2], uint8_t *refmv_count,
20 : CANDIDATE_MV *ref_mv_stack, const int use_hp, int len, int block, int col) {
21 0 : int index = 0, ref;
22 0 : int newmv_count = 0;
23 : #if CONFIG_CB4X4
24 0 : const int unify_bsize = 1;
25 : #else
26 : const int unify_bsize = 0;
27 : #endif
28 :
29 0 : if (rf[1] == NONE_FRAME) {
30 : // single reference frame
31 0 : for (ref = 0; ref < 2; ++ref) {
32 0 : if (candidate->ref_frame[ref] == rf[0]) {
33 0 : int_mv this_refmv = get_sub_block_mv(candidate_mi, ref, col, block);
34 0 : lower_mv_precision(&this_refmv.as_mv, use_hp);
35 :
36 0 : for (index = 0; index < *refmv_count; ++index)
37 0 : if (ref_mv_stack[index].this_mv.as_int == this_refmv.as_int) break;
38 :
39 0 : if (index < *refmv_count) ref_mv_stack[index].weight += 2 * len;
40 :
41 : // Add a new item to the list.
42 0 : if (index == *refmv_count) {
43 0 : ref_mv_stack[index].this_mv = this_refmv;
44 0 : ref_mv_stack[index].pred_diff[0] = av1_get_pred_diff_ctx(
45 : get_sub_block_pred_mv(candidate_mi, ref, col, block), this_refmv);
46 0 : ref_mv_stack[index].weight = 2 * len;
47 0 : ++(*refmv_count);
48 :
49 0 : if (candidate->mode == NEWMV) ++newmv_count;
50 : }
51 :
52 0 : if (candidate_mi->mbmi.sb_type < BLOCK_8X8 && block >= 0 &&
53 : !unify_bsize) {
54 0 : int alt_block = 3 - block;
55 0 : this_refmv = get_sub_block_mv(candidate_mi, ref, col, alt_block);
56 0 : lower_mv_precision(&this_refmv.as_mv, use_hp);
57 :
58 0 : for (index = 0; index < *refmv_count; ++index)
59 0 : if (ref_mv_stack[index].this_mv.as_int == this_refmv.as_int) break;
60 :
61 0 : if (index < *refmv_count) ref_mv_stack[index].weight += len;
62 :
63 : // Add a new item to the list.
64 0 : if (index == *refmv_count) {
65 0 : ref_mv_stack[index].this_mv = this_refmv;
66 0 : ref_mv_stack[index].pred_diff[0] = av1_get_pred_diff_ctx(
67 : get_sub_block_pred_mv(candidate_mi, ref, col, alt_block),
68 : this_refmv);
69 0 : ref_mv_stack[index].weight = len;
70 0 : ++(*refmv_count);
71 :
72 0 : if (candidate->mode == NEWMV) ++newmv_count;
73 : }
74 : }
75 : }
76 : }
77 : } else {
78 : // compound reference frame
79 0 : if (candidate->ref_frame[0] == rf[0] && candidate->ref_frame[1] == rf[1]) {
80 : int_mv this_refmv[2];
81 :
82 0 : for (ref = 0; ref < 2; ++ref) {
83 0 : this_refmv[ref] = get_sub_block_mv(candidate_mi, ref, col, block);
84 0 : lower_mv_precision(&this_refmv[ref].as_mv, use_hp);
85 : }
86 :
87 0 : for (index = 0; index < *refmv_count; ++index)
88 0 : if ((ref_mv_stack[index].this_mv.as_int == this_refmv[0].as_int) &&
89 0 : (ref_mv_stack[index].comp_mv.as_int == this_refmv[1].as_int))
90 0 : break;
91 :
92 0 : if (index < *refmv_count) ref_mv_stack[index].weight += 2 * len;
93 :
94 : // Add a new item to the list.
95 0 : if (index == *refmv_count) {
96 0 : ref_mv_stack[index].this_mv = this_refmv[0];
97 0 : ref_mv_stack[index].comp_mv = this_refmv[1];
98 0 : ref_mv_stack[index].pred_diff[0] = av1_get_pred_diff_ctx(
99 : get_sub_block_pred_mv(candidate_mi, 0, col, block), this_refmv[0]);
100 0 : ref_mv_stack[index].pred_diff[1] = av1_get_pred_diff_ctx(
101 : get_sub_block_pred_mv(candidate_mi, 1, col, block), this_refmv[1]);
102 0 : ref_mv_stack[index].weight = 2 * len;
103 0 : ++(*refmv_count);
104 :
105 : #if CONFIG_EXT_INTER
106 0 : if (candidate->mode == NEW_NEWMV)
107 : #else
108 : if (candidate->mode == NEWMV)
109 : #endif // CONFIG_EXT_INTER
110 0 : ++newmv_count;
111 : }
112 :
113 0 : if (candidate_mi->mbmi.sb_type < BLOCK_8X8 && block >= 0 &&
114 : !unify_bsize) {
115 0 : int alt_block = 3 - block;
116 0 : this_refmv[0] = get_sub_block_mv(candidate_mi, 0, col, alt_block);
117 0 : this_refmv[1] = get_sub_block_mv(candidate_mi, 1, col, alt_block);
118 :
119 0 : for (ref = 0; ref < 2; ++ref)
120 0 : lower_mv_precision(&this_refmv[ref].as_mv, use_hp);
121 :
122 0 : for (index = 0; index < *refmv_count; ++index)
123 0 : if (ref_mv_stack[index].this_mv.as_int == this_refmv[0].as_int &&
124 0 : ref_mv_stack[index].comp_mv.as_int == this_refmv[1].as_int)
125 0 : break;
126 :
127 0 : if (index < *refmv_count) ref_mv_stack[index].weight += len;
128 :
129 : // Add a new item to the list.
130 0 : if (index == *refmv_count) {
131 0 : ref_mv_stack[index].this_mv = this_refmv[0];
132 0 : ref_mv_stack[index].comp_mv = this_refmv[1];
133 0 : ref_mv_stack[index].pred_diff[0] = av1_get_pred_diff_ctx(
134 : get_sub_block_pred_mv(candidate_mi, 0, col, block),
135 : this_refmv[0]);
136 0 : ref_mv_stack[index].pred_diff[0] = av1_get_pred_diff_ctx(
137 : get_sub_block_pred_mv(candidate_mi, 1, col, block),
138 : this_refmv[1]);
139 0 : ref_mv_stack[index].weight = len;
140 0 : ++(*refmv_count);
141 :
142 : #if CONFIG_EXT_INTER
143 0 : if (candidate->mode == NEW_NEWMV)
144 : #else
145 : if (candidate->mode == NEWMV)
146 : #endif // CONFIG_EXT_INTER
147 0 : ++newmv_count;
148 : }
149 : }
150 : }
151 : }
152 0 : return newmv_count;
153 : }
154 :
155 0 : static uint8_t scan_row_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
156 : const int mi_row, const int mi_col, int block,
157 : const MV_REFERENCE_FRAME rf[2], int row_offset,
158 : CANDIDATE_MV *ref_mv_stack, uint8_t *refmv_count) {
159 0 : const TileInfo *const tile = &xd->tile;
160 : int i;
161 0 : uint8_t newmv_count = 0;
162 : #if CONFIG_CB4X4
163 0 : const int bsize = xd->mi[0]->mbmi.sb_type;
164 0 : const int mi_offset =
165 0 : bsize < BLOCK_8X8 ? mi_size_wide[BLOCK_4X4] : mi_size_wide[BLOCK_8X8];
166 : // TODO(jingning): Revisit this part after cb4x4 is stable.
167 0 : if (bsize >= BLOCK_8X8) row_offset *= 2;
168 : #else
169 : const int mi_offset = mi_size_wide[BLOCK_8X8];
170 : #endif
171 :
172 0 : for (i = 0; i < xd->n8_w && *refmv_count < MAX_REF_MV_STACK_SIZE;) {
173 : POSITION mi_pos;
174 : #if CONFIG_CB4X4
175 0 : const int use_step_16 = (xd->n8_w >= 16);
176 : #else
177 : const int use_step_16 = (xd->n8_w >= 8);
178 : #endif
179 :
180 0 : mi_pos.row = row_offset;
181 0 : mi_pos.col = i;
182 0 : if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm, &mi_pos)) {
183 0 : const MODE_INFO *const candidate_mi =
184 0 : xd->mi[mi_pos.row * xd->mi_stride + mi_pos.col];
185 0 : const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
186 0 : int len = AOMMIN(xd->n8_w, mi_size_wide[candidate->sb_type]);
187 0 : if (use_step_16) len = AOMMAX(mi_size_wide[BLOCK_16X16], len);
188 0 : newmv_count += add_ref_mv_candidate(
189 : candidate_mi, candidate, rf, refmv_count, ref_mv_stack,
190 : cm->allow_high_precision_mv, len, block, mi_pos.col);
191 0 : i += len;
192 : } else {
193 0 : if (use_step_16)
194 0 : i += (mi_offset << 1);
195 : else
196 0 : i += mi_offset;
197 : }
198 : }
199 :
200 0 : return newmv_count;
201 : }
202 :
203 0 : static uint8_t scan_col_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
204 : const int mi_row, const int mi_col, int block,
205 : const MV_REFERENCE_FRAME rf[2], int col_offset,
206 : CANDIDATE_MV *ref_mv_stack, uint8_t *refmv_count) {
207 0 : const TileInfo *const tile = &xd->tile;
208 : int i;
209 0 : uint8_t newmv_count = 0;
210 : #if CONFIG_CB4X4
211 0 : const BLOCK_SIZE bsize = xd->mi[0]->mbmi.sb_type;
212 0 : const int mi_offset =
213 0 : (bsize < BLOCK_8X8) ? mi_size_high[BLOCK_4X4] : mi_size_high[BLOCK_8X8];
214 0 : if (bsize >= BLOCK_8X8) col_offset *= 2;
215 : #else
216 : const int mi_offset = mi_size_wide[BLOCK_8X8];
217 : #endif
218 :
219 0 : for (i = 0; i < xd->n8_h && *refmv_count < MAX_REF_MV_STACK_SIZE;) {
220 : POSITION mi_pos;
221 : #if CONFIG_CB4X4
222 0 : const int use_step_16 = (xd->n8_h >= 16);
223 : #else
224 : const int use_step_16 = (xd->n8_h >= 8);
225 : #endif
226 :
227 0 : mi_pos.row = i;
228 0 : mi_pos.col = col_offset;
229 0 : if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm, &mi_pos)) {
230 0 : const MODE_INFO *const candidate_mi =
231 0 : xd->mi[mi_pos.row * xd->mi_stride + mi_pos.col];
232 0 : const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
233 0 : int len = AOMMIN(xd->n8_h, mi_size_high[candidate->sb_type]);
234 0 : if (use_step_16) len = AOMMAX(mi_size_high[BLOCK_16X16], len);
235 0 : newmv_count += add_ref_mv_candidate(
236 : candidate_mi, candidate, rf, refmv_count, ref_mv_stack,
237 : cm->allow_high_precision_mv, len, block, mi_pos.col);
238 0 : i += len;
239 : } else {
240 0 : if (use_step_16)
241 0 : i += (mi_offset << 1);
242 : else
243 0 : i += mi_offset;
244 : }
245 : }
246 :
247 0 : return newmv_count;
248 : }
249 :
250 0 : static uint8_t scan_blk_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
251 : const int mi_row, const int mi_col, int block,
252 : const MV_REFERENCE_FRAME rf[2], int row_offset,
253 : int col_offset, CANDIDATE_MV *ref_mv_stack,
254 : uint8_t *refmv_count) {
255 0 : const TileInfo *const tile = &xd->tile;
256 : POSITION mi_pos;
257 0 : uint8_t newmv_count = 0;
258 :
259 0 : mi_pos.row = row_offset;
260 0 : mi_pos.col = col_offset;
261 :
262 0 : if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm, &mi_pos) &&
263 0 : *refmv_count < MAX_REF_MV_STACK_SIZE) {
264 0 : const MODE_INFO *const candidate_mi =
265 0 : xd->mi[mi_pos.row * xd->mi_stride + mi_pos.col];
266 0 : const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
267 0 : const int len = mi_size_wide[BLOCK_8X8];
268 :
269 0 : newmv_count += add_ref_mv_candidate(
270 : candidate_mi, candidate, rf, refmv_count, ref_mv_stack,
271 : cm->allow_high_precision_mv, len, block, mi_pos.col);
272 : } // Analyze a single 8x8 block motion information.
273 :
274 0 : return newmv_count;
275 : }
276 :
277 0 : static int has_top_right(const MACROBLOCKD *xd, int mi_row, int mi_col,
278 : int bs) {
279 0 : const int mask_row = mi_row & MAX_MIB_MASK;
280 0 : const int mask_col = mi_col & MAX_MIB_MASK;
281 :
282 : // In a split partition all apart from the bottom right has a top right
283 0 : int has_tr = !((mask_row & bs) && (mask_col & bs));
284 :
285 : // bs > 0 and bs is a power of 2
286 0 : assert(bs > 0 && !(bs & (bs - 1)));
287 :
288 : // For each 4x4 group of blocks, when the bottom right is decoded the blocks
289 : // to the right have not been decoded therefore the bottom right does
290 : // not have a top right
291 0 : while (bs < MAX_MIB_SIZE) {
292 0 : if (mask_col & bs) {
293 0 : if ((mask_col & (2 * bs)) && (mask_row & (2 * bs))) {
294 0 : has_tr = 0;
295 0 : break;
296 : }
297 : } else {
298 0 : break;
299 : }
300 0 : bs <<= 1;
301 : }
302 :
303 : // The left hand of two vertical rectangles always has a top right (as the
304 : // block above will have been decoded)
305 0 : if (xd->n8_w < xd->n8_h)
306 0 : if (!xd->is_sec_rect) has_tr = 1;
307 :
308 : // The bottom of two horizontal rectangles never has a top right (as the block
309 : // to the right won't have been decoded)
310 0 : if (xd->n8_w > xd->n8_h)
311 0 : if (xd->is_sec_rect) has_tr = 0;
312 :
313 : #if CONFIG_EXT_PARTITION_TYPES
314 : // The bottom left square of a Vertical A does not have a top right as it is
315 : // decoded before the right hand rectangle of the partition
316 : if (xd->mi[0]->mbmi.partition == PARTITION_VERT_A)
317 : if ((mask_row & bs) && !(mask_col & bs)) has_tr = 0;
318 : #endif // CONFIG_EXT_PARTITION_TYPES
319 :
320 0 : return has_tr;
321 : }
322 :
323 0 : static int add_col_ref_mv(const AV1_COMMON *cm,
324 : const MV_REF *prev_frame_mvs_base,
325 : const MACROBLOCKD *xd, int mi_row, int mi_col,
326 : MV_REFERENCE_FRAME ref_frame, int blk_row,
327 : int blk_col, uint8_t *refmv_count,
328 : CANDIDATE_MV *ref_mv_stack, int16_t *mode_context) {
329 0 : const MV_REF *prev_frame_mvs =
330 0 : prev_frame_mvs_base + blk_row * cm->mi_cols + blk_col;
331 : POSITION mi_pos;
332 : int ref, idx;
333 0 : int coll_blk_count = 0;
334 0 : const int weight_unit = mi_size_wide[BLOCK_8X8];
335 :
336 : #if CONFIG_MV_COMPRESS
337 0 : mi_pos.row = (mi_row & 0x01) ? blk_row : blk_row + 1;
338 0 : mi_pos.col = (mi_col & 0x01) ? blk_col : blk_col + 1;
339 : #else
340 : mi_pos.row = blk_row;
341 : mi_pos.col = blk_col;
342 : #endif
343 :
344 0 : if (!is_inside(&xd->tile, mi_col, mi_row, cm->mi_rows, cm, &mi_pos))
345 0 : return coll_blk_count;
346 0 : for (ref = 0; ref < 2; ++ref) {
347 0 : if (prev_frame_mvs->ref_frame[ref] == ref_frame) {
348 0 : int_mv this_refmv = prev_frame_mvs->mv[ref];
349 0 : lower_mv_precision(&this_refmv.as_mv, cm->allow_high_precision_mv);
350 :
351 0 : if (abs(this_refmv.as_mv.row) >= 16 || abs(this_refmv.as_mv.col) >= 16)
352 0 : mode_context[ref_frame] |= (1 << ZEROMV_OFFSET);
353 :
354 0 : for (idx = 0; idx < *refmv_count; ++idx)
355 0 : if (this_refmv.as_int == ref_mv_stack[idx].this_mv.as_int) break;
356 :
357 0 : if (idx < *refmv_count) ref_mv_stack[idx].weight += 2 * weight_unit;
358 :
359 0 : if (idx == *refmv_count && *refmv_count < MAX_REF_MV_STACK_SIZE) {
360 0 : ref_mv_stack[idx].this_mv.as_int = this_refmv.as_int;
361 0 : ref_mv_stack[idx].pred_diff[0] =
362 0 : av1_get_pred_diff_ctx(prev_frame_mvs->pred_mv[ref], this_refmv);
363 0 : ref_mv_stack[idx].weight = 2 * weight_unit;
364 0 : ++(*refmv_count);
365 : }
366 :
367 0 : ++coll_blk_count;
368 : }
369 : }
370 :
371 0 : return coll_blk_count;
372 : }
373 :
374 0 : static void setup_ref_mv_list(const AV1_COMMON *cm, const MACROBLOCKD *xd,
375 : MV_REFERENCE_FRAME ref_frame,
376 : uint8_t *refmv_count, CANDIDATE_MV *ref_mv_stack,
377 : int_mv *mv_ref_list, int block, int mi_row,
378 : int mi_col, int16_t *mode_context) {
379 0 : int idx, nearest_refmv_count = 0;
380 0 : uint8_t newmv_count = 0;
381 : CANDIDATE_MV tmp_mv;
382 : int len, nr_len;
383 :
384 : #if CONFIG_MV_COMPRESS
385 0 : const MV_REF *const prev_frame_mvs_base =
386 0 : cm->use_prev_frame_mvs
387 0 : ? cm->prev_frame->mvs + (((mi_row >> 1) << 1) + 1) * cm->mi_cols +
388 0 : ((mi_col >> 1) << 1) + 1
389 0 : : NULL;
390 : #else
391 : const MV_REF *const prev_frame_mvs_base =
392 : cm->use_prev_frame_mvs
393 : ? cm->prev_frame->mvs + mi_row * cm->mi_cols + mi_col
394 : : NULL;
395 : #endif
396 :
397 0 : const int bs = AOMMAX(xd->n8_w, xd->n8_h);
398 0 : const int has_tr = has_top_right(xd, mi_row, mi_col, bs);
399 : MV_REFERENCE_FRAME rf[2];
400 :
401 0 : av1_set_ref_frame(rf, ref_frame);
402 0 : mode_context[ref_frame] = 0;
403 0 : *refmv_count = 0;
404 :
405 : // Scan the first above row mode info.
406 0 : newmv_count += scan_row_mbmi(cm, xd, mi_row, mi_col, block, rf, -1,
407 : ref_mv_stack, refmv_count);
408 : // Scan the first left column mode info.
409 0 : newmv_count += scan_col_mbmi(cm, xd, mi_row, mi_col, block, rf, -1,
410 : ref_mv_stack, refmv_count);
411 :
412 : // Check top-right boundary
413 0 : if (has_tr)
414 0 : newmv_count += scan_blk_mbmi(cm, xd, mi_row, mi_col, block, rf, -1,
415 0 : xd->n8_w, ref_mv_stack, refmv_count);
416 :
417 0 : nearest_refmv_count = *refmv_count;
418 :
419 0 : for (idx = 0; idx < nearest_refmv_count; ++idx)
420 0 : ref_mv_stack[idx].weight += REF_CAT_LEVEL;
421 : #if CONFIG_TEMPMV_SIGNALING
422 0 : if (cm->use_prev_frame_mvs && rf[1] == NONE_FRAME) {
423 : #else
424 : if (prev_frame_mvs_base && cm->show_frame && cm->last_show_frame &&
425 : rf[1] == NONE_FRAME) {
426 : #endif
427 : int blk_row, blk_col;
428 0 : int coll_blk_count = 0;
429 : #if CONFIG_CB4X4
430 0 : const int mi_step = (xd->n8_w == 1 || xd->n8_h == 1)
431 0 : ? mi_size_wide[BLOCK_8X8]
432 0 : : mi_size_wide[BLOCK_16X16];
433 : #else
434 : const int mi_step = mi_size_wide[BLOCK_16X16];
435 : #endif
436 :
437 : #if CONFIG_TPL_MV
438 : int tpl_sample_pos[5][2] = { { -1, xd->n8_w },
439 : { 0, xd->n8_w },
440 : { xd->n8_h, xd->n8_w },
441 : { xd->n8_h, 0 },
442 : { xd->n8_h, -1 } };
443 : int i;
444 : #endif
445 :
446 0 : for (blk_row = 0; blk_row < xd->n8_h; blk_row += mi_step) {
447 0 : for (blk_col = 0; blk_col < xd->n8_w; blk_col += mi_step) {
448 0 : coll_blk_count += add_col_ref_mv(
449 : cm, prev_frame_mvs_base, xd, mi_row, mi_col, ref_frame, blk_row,
450 : blk_col, refmv_count, ref_mv_stack, mode_context);
451 : }
452 : }
453 :
454 : #if CONFIG_TPL_MV
455 : for (i = 0; i < 5; ++i) {
456 : blk_row = tpl_sample_pos[i][0];
457 : blk_col = tpl_sample_pos[i][1];
458 : coll_blk_count += add_col_ref_mv(cm, prev_frame_mvs_base, xd, mi_row,
459 : mi_col, ref_frame, blk_row, blk_col,
460 : refmv_count, ref_mv_stack, mode_context);
461 : }
462 : #endif
463 :
464 0 : if (coll_blk_count == 0) mode_context[ref_frame] |= (1 << ZEROMV_OFFSET);
465 : } else {
466 0 : mode_context[ref_frame] |= (1 << ZEROMV_OFFSET);
467 : }
468 :
469 : // Scan the second outer area.
470 0 : scan_blk_mbmi(cm, xd, mi_row, mi_col, block, rf, -1, -1, ref_mv_stack,
471 : refmv_count);
472 0 : for (idx = 2; idx <= 3; ++idx) {
473 0 : scan_row_mbmi(cm, xd, mi_row, mi_col, block, rf, -idx, ref_mv_stack,
474 : refmv_count);
475 0 : scan_col_mbmi(cm, xd, mi_row, mi_col, block, rf, -idx, ref_mv_stack,
476 : refmv_count);
477 : }
478 0 : scan_col_mbmi(cm, xd, mi_row, mi_col, block, rf, -4, ref_mv_stack,
479 : refmv_count);
480 :
481 0 : switch (nearest_refmv_count) {
482 : case 0:
483 0 : mode_context[ref_frame] |= 0;
484 0 : if (*refmv_count >= 1) mode_context[ref_frame] |= 1;
485 :
486 0 : if (*refmv_count == 1)
487 0 : mode_context[ref_frame] |= (1 << REFMV_OFFSET);
488 0 : else if (*refmv_count >= 2)
489 0 : mode_context[ref_frame] |= (2 << REFMV_OFFSET);
490 0 : break;
491 : case 1:
492 0 : mode_context[ref_frame] |= (newmv_count > 0) ? 2 : 3;
493 :
494 0 : if (*refmv_count == 1)
495 0 : mode_context[ref_frame] |= (3 << REFMV_OFFSET);
496 0 : else if (*refmv_count >= 2)
497 0 : mode_context[ref_frame] |= (4 << REFMV_OFFSET);
498 0 : break;
499 :
500 : case 2:
501 : default:
502 0 : if (newmv_count >= 2)
503 0 : mode_context[ref_frame] |= 4;
504 0 : else if (newmv_count == 1)
505 0 : mode_context[ref_frame] |= 5;
506 : else
507 0 : mode_context[ref_frame] |= 6;
508 :
509 0 : mode_context[ref_frame] |= (5 << REFMV_OFFSET);
510 0 : break;
511 : }
512 :
513 : // Rank the likelihood and assign nearest and near mvs.
514 0 : len = nearest_refmv_count;
515 0 : while (len > 0) {
516 0 : nr_len = 0;
517 0 : for (idx = 1; idx < len; ++idx) {
518 0 : if (ref_mv_stack[idx - 1].weight < ref_mv_stack[idx].weight) {
519 0 : tmp_mv = ref_mv_stack[idx - 1];
520 0 : ref_mv_stack[idx - 1] = ref_mv_stack[idx];
521 0 : ref_mv_stack[idx] = tmp_mv;
522 0 : nr_len = idx;
523 : }
524 : }
525 0 : len = nr_len;
526 : }
527 :
528 0 : len = *refmv_count;
529 0 : while (len > nearest_refmv_count) {
530 0 : nr_len = nearest_refmv_count;
531 0 : for (idx = nearest_refmv_count + 1; idx < len; ++idx) {
532 0 : if (ref_mv_stack[idx - 1].weight < ref_mv_stack[idx].weight) {
533 0 : tmp_mv = ref_mv_stack[idx - 1];
534 0 : ref_mv_stack[idx - 1] = ref_mv_stack[idx];
535 0 : ref_mv_stack[idx] = tmp_mv;
536 0 : nr_len = idx;
537 : }
538 : }
539 0 : len = nr_len;
540 : }
541 :
542 0 : if (rf[1] > NONE_FRAME) {
543 0 : for (idx = 0; idx < *refmv_count; ++idx) {
544 0 : clamp_mv_ref(&ref_mv_stack[idx].this_mv.as_mv, xd->n8_w << MI_SIZE_LOG2,
545 0 : xd->n8_h << MI_SIZE_LOG2, xd);
546 0 : clamp_mv_ref(&ref_mv_stack[idx].comp_mv.as_mv, xd->n8_w << MI_SIZE_LOG2,
547 0 : xd->n8_h << MI_SIZE_LOG2, xd);
548 : }
549 : } else {
550 0 : for (idx = 0; idx < AOMMIN(MAX_MV_REF_CANDIDATES, *refmv_count); ++idx) {
551 0 : mv_ref_list[idx].as_int = ref_mv_stack[idx].this_mv.as_int;
552 0 : clamp_mv_ref(&mv_ref_list[idx].as_mv, xd->n8_w << MI_SIZE_LOG2,
553 0 : xd->n8_h << MI_SIZE_LOG2, xd);
554 : }
555 : }
556 0 : }
557 :
558 : // This function searches the neighbourhood of a given MB/SB
559 : // to try and find candidate reference vectors.
560 0 : static void find_mv_refs_idx(const AV1_COMMON *cm, const MACROBLOCKD *xd,
561 : MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame,
562 : int_mv *mv_ref_list, int block, int mi_row,
563 : int mi_col, find_mv_refs_sync sync,
564 : void *const data, int16_t *mode_context,
565 : int_mv zeromv) {
566 0 : const int *ref_sign_bias = cm->ref_frame_sign_bias;
567 0 : int i, refmv_count = 0;
568 0 : int different_ref_found = 0;
569 0 : int context_counter = 0;
570 : #if CONFIG_MV_COMPRESS
571 0 : const TileInfo *const tile_ = &xd->tile;
572 0 : int mi_row_end = tile_->mi_row_end;
573 0 : int mi_col_end = tile_->mi_col_end;
574 0 : const MV_REF *const prev_frame_mvs =
575 0 : cm->use_prev_frame_mvs
576 0 : ? cm->prev_frame->mvs +
577 0 : AOMMIN(((mi_row >> 1) << 1) + 1 + (((xd->n8_h - 1) >> 1) << 1),
578 0 : mi_row_end - 1) *
579 0 : cm->mi_cols +
580 0 : AOMMIN(((mi_col >> 1) << 1) + 1 + (((xd->n8_w - 1) >> 1) << 1),
581 : mi_col_end - 1)
582 0 : : NULL;
583 : #else
584 : const MV_REF *const prev_frame_mvs =
585 : cm->use_prev_frame_mvs
586 : ? cm->prev_frame->mvs + mi_row * cm->mi_cols + mi_col
587 : : NULL;
588 : #endif
589 : #if CONFIG_INTRABC
590 : assert(IMPLIES(ref_frame == INTRA_FRAME, cm->use_prev_frame_mvs == 0));
591 : #endif
592 0 : const TileInfo *const tile = &xd->tile;
593 0 : const BLOCK_SIZE bsize = mi->mbmi.sb_type;
594 0 : const int bw = block_size_wide[AOMMAX(bsize, BLOCK_8X8)];
595 0 : const int bh = block_size_high[AOMMAX(bsize, BLOCK_8X8)];
596 : POSITION mv_ref_search[MVREF_NEIGHBOURS];
597 0 : const int num_8x8_blocks_wide = num_8x8_blocks_wide_lookup[bsize];
598 0 : const int num_8x8_blocks_high = num_8x8_blocks_high_lookup[bsize];
599 0 : mv_ref_search[0].row = num_8x8_blocks_high - 1;
600 0 : mv_ref_search[0].col = -1;
601 0 : mv_ref_search[1].row = -1;
602 0 : mv_ref_search[1].col = num_8x8_blocks_wide - 1;
603 0 : mv_ref_search[2].row = -1;
604 0 : mv_ref_search[2].col = (num_8x8_blocks_wide - 1) >> 1;
605 0 : mv_ref_search[3].row = (num_8x8_blocks_high - 1) >> 1;
606 0 : mv_ref_search[3].col = -1;
607 0 : mv_ref_search[4].row = -1;
608 0 : mv_ref_search[4].col = -1;
609 : #if CONFIG_EXT_PARTITION_TYPES
610 : if (num_8x8_blocks_wide == num_8x8_blocks_high) {
611 : mv_ref_search[5].row = -1;
612 : mv_ref_search[5].col = 0;
613 : mv_ref_search[6].row = 0;
614 : mv_ref_search[6].col = -1;
615 : } else {
616 : mv_ref_search[5].row = -1;
617 : mv_ref_search[5].col = num_8x8_blocks_wide;
618 : mv_ref_search[6].row = num_8x8_blocks_high;
619 : mv_ref_search[6].col = -1;
620 : }
621 : #else
622 0 : mv_ref_search[5].row = -1;
623 0 : mv_ref_search[5].col = num_8x8_blocks_wide;
624 0 : mv_ref_search[6].row = num_8x8_blocks_high;
625 0 : mv_ref_search[6].col = -1;
626 : #endif // CONFIG_EXT_PARTITION_TYPES
627 0 : mv_ref_search[7].row = -1;
628 0 : mv_ref_search[7].col = -3;
629 0 : mv_ref_search[8].row = num_8x8_blocks_high - 1;
630 0 : mv_ref_search[8].col = -3;
631 :
632 : #if CONFIG_CB4X4
633 0 : for (i = 0; i < MVREF_NEIGHBOURS; ++i) {
634 0 : mv_ref_search[i].row *= 2;
635 0 : mv_ref_search[i].col *= 2;
636 : }
637 : #endif // CONFIG_CB4X4
638 :
639 : // The nearest 2 blocks are treated differently
640 : // if the size < 8x8 we get the mv from the bmi substructure,
641 : // and we also need to keep a mode count.
642 0 : for (i = 0; i < 2; ++i) {
643 0 : const POSITION *const mv_ref = &mv_ref_search[i];
644 0 : if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm, mv_ref)) {
645 0 : const MODE_INFO *const candidate_mi =
646 0 : xd->mi[mv_ref->col + mv_ref->row * xd->mi_stride];
647 0 : const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
648 : // Keep counts for entropy encoding.
649 0 : context_counter += mode_2_counter[candidate->mode];
650 0 : different_ref_found = 1;
651 :
652 0 : if (candidate->ref_frame[0] == ref_frame)
653 0 : ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 0, mv_ref->col, block),
654 : refmv_count, mv_ref_list, bw, bh, xd, Done);
655 0 : else if (candidate->ref_frame[1] == ref_frame)
656 0 : ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 1, mv_ref->col, block),
657 : refmv_count, mv_ref_list, bw, bh, xd, Done);
658 : }
659 : }
660 :
661 : // Check the rest of the neighbors in much the same way
662 : // as before except we don't need to keep track of sub blocks or
663 : // mode counts.
664 0 : for (; i < MVREF_NEIGHBOURS; ++i) {
665 0 : const POSITION *const mv_ref = &mv_ref_search[i];
666 0 : if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm, mv_ref)) {
667 0 : const MB_MODE_INFO *const candidate =
668 0 : !xd->mi[mv_ref->col + mv_ref->row * xd->mi_stride]
669 : ? NULL
670 0 : : &xd->mi[mv_ref->col + mv_ref->row * xd->mi_stride]->mbmi;
671 0 : if (candidate == NULL) continue;
672 0 : if ((mi_row % MAX_MIB_SIZE) + mv_ref->row >= MAX_MIB_SIZE ||
673 0 : (mi_col % MAX_MIB_SIZE) + mv_ref->col >= MAX_MIB_SIZE)
674 0 : continue;
675 0 : different_ref_found = 1;
676 :
677 0 : if (candidate->ref_frame[0] == ref_frame)
678 0 : ADD_MV_REF_LIST(candidate->mv[0], refmv_count, mv_ref_list, bw, bh, xd,
679 : Done);
680 0 : else if (candidate->ref_frame[1] == ref_frame)
681 0 : ADD_MV_REF_LIST(candidate->mv[1], refmv_count, mv_ref_list, bw, bh, xd,
682 : Done);
683 : }
684 : }
685 :
686 : // TODO(hkuang): Remove this sync after fixing pthread_cond_broadcast
687 : // on windows platform. The sync here is unncessary if use_perv_frame_mvs
688 : // is 0. But after removing it, there will be hang in the unit test on windows
689 : // due to several threads waiting for a thread's signal.
690 : #if defined(_WIN32) && !HAVE_PTHREAD_H
691 : if (cm->frame_parallel_decode && sync != NULL) {
692 : sync(data, mi_row);
693 : }
694 : #endif
695 :
696 : // Check the last frame's mode and mv info.
697 0 : if (cm->use_prev_frame_mvs) {
698 : // Synchronize here for frame parallel decode if sync function is provided.
699 0 : if (cm->frame_parallel_decode && sync != NULL) {
700 0 : sync(data, mi_row);
701 : }
702 :
703 0 : if (prev_frame_mvs->ref_frame[0] == ref_frame) {
704 0 : ADD_MV_REF_LIST(prev_frame_mvs->mv[0], refmv_count, mv_ref_list, bw, bh,
705 : xd, Done);
706 0 : } else if (prev_frame_mvs->ref_frame[1] == ref_frame) {
707 0 : ADD_MV_REF_LIST(prev_frame_mvs->mv[1], refmv_count, mv_ref_list, bw, bh,
708 : xd, Done);
709 : }
710 : }
711 :
712 : // Since we couldn't find 2 mvs from the same reference frame
713 : // go back through the neighbors and find motion vectors from
714 : // different reference frames.
715 0 : if (different_ref_found) {
716 0 : for (i = 0; i < MVREF_NEIGHBOURS; ++i) {
717 0 : const POSITION *mv_ref = &mv_ref_search[i];
718 0 : if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm, mv_ref)) {
719 0 : const MB_MODE_INFO *const candidate =
720 0 : !xd->mi[mv_ref->col + mv_ref->row * xd->mi_stride]
721 : ? NULL
722 0 : : &xd->mi[mv_ref->col + mv_ref->row * xd->mi_stride]->mbmi;
723 0 : if (candidate == NULL) continue;
724 0 : if ((mi_row % MAX_MIB_SIZE) + mv_ref->row >= MAX_MIB_SIZE ||
725 0 : (mi_col % MAX_MIB_SIZE) + mv_ref->col >= MAX_MIB_SIZE)
726 0 : continue;
727 :
728 : // If the candidate is INTRA we don't want to consider its mv.
729 0 : IF_DIFF_REF_FRAME_ADD_MV(candidate, ref_frame, ref_sign_bias,
730 : refmv_count, mv_ref_list, bw, bh, xd, Done);
731 : }
732 : }
733 : }
734 :
735 : // Since we still don't have a candidate we'll try the last frame.
736 0 : if (cm->use_prev_frame_mvs) {
737 0 : if (prev_frame_mvs->ref_frame[0] != ref_frame &&
738 0 : prev_frame_mvs->ref_frame[0] > INTRA_FRAME) {
739 0 : int_mv mv = prev_frame_mvs->mv[0];
740 0 : if (ref_sign_bias[prev_frame_mvs->ref_frame[0]] !=
741 0 : ref_sign_bias[ref_frame]) {
742 0 : mv.as_mv.row *= -1;
743 0 : mv.as_mv.col *= -1;
744 : }
745 0 : ADD_MV_REF_LIST(mv, refmv_count, mv_ref_list, bw, bh, xd, Done);
746 : }
747 :
748 0 : if (prev_frame_mvs->ref_frame[1] > INTRA_FRAME &&
749 0 : prev_frame_mvs->ref_frame[1] != ref_frame) {
750 0 : int_mv mv = prev_frame_mvs->mv[1];
751 0 : if (ref_sign_bias[prev_frame_mvs->ref_frame[1]] !=
752 0 : ref_sign_bias[ref_frame]) {
753 0 : mv.as_mv.row *= -1;
754 0 : mv.as_mv.col *= -1;
755 : }
756 0 : ADD_MV_REF_LIST(mv, refmv_count, mv_ref_list, bw, bh, xd, Done);
757 : }
758 : }
759 :
760 : Done:
761 0 : if (mode_context)
762 0 : mode_context[ref_frame] = counter_to_context[context_counter];
763 0 : for (i = refmv_count; i < MAX_MV_REF_CANDIDATES; ++i)
764 0 : mv_ref_list[i].as_int = zeromv.as_int;
765 0 : }
766 :
767 : #if CONFIG_EXT_INTER
768 : // This function keeps a mode count for a given MB/SB
769 0 : void av1_update_mv_context(const AV1_COMMON *cm, const MACROBLOCKD *xd,
770 : MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame,
771 : int_mv *mv_ref_list, int block, int mi_row,
772 : int mi_col, int16_t *mode_context) {
773 0 : int i, refmv_count = 0;
774 0 : int context_counter = 0;
775 0 : const int bw = block_size_wide[mi->mbmi.sb_type];
776 0 : const int bh = block_size_high[mi->mbmi.sb_type];
777 0 : const TileInfo *const tile = &xd->tile;
778 : POSITION mv_ref_search[2];
779 0 : const int num_8x8_blocks_wide = mi_size_wide[mi->mbmi.sb_type];
780 0 : const int num_8x8_blocks_high = mi_size_high[mi->mbmi.sb_type];
781 :
782 0 : mv_ref_search[0].row = num_8x8_blocks_high - 1;
783 0 : mv_ref_search[0].col = -1;
784 0 : mv_ref_search[1].row = -1;
785 0 : mv_ref_search[1].col = num_8x8_blocks_wide - 1;
786 :
787 : // Blank the reference vector list
788 0 : memset(mv_ref_list, 0, sizeof(*mv_ref_list) * MAX_MV_REF_CANDIDATES);
789 :
790 : // The nearest 2 blocks are examined only.
791 : // If the size < 8x8, we get the mv from the bmi substructure;
792 0 : for (i = 0; i < 2; ++i) {
793 0 : const POSITION *const mv_ref = &mv_ref_search[i];
794 0 : if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm, mv_ref)) {
795 0 : const MODE_INFO *const candidate_mi =
796 0 : xd->mi[mv_ref->col + mv_ref->row * xd->mi_stride];
797 0 : const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
798 :
799 : // Keep counts for entropy encoding.
800 0 : context_counter += mode_2_counter[candidate->mode];
801 :
802 0 : if (candidate->ref_frame[0] == ref_frame) {
803 0 : ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 0, mv_ref->col, block),
804 : refmv_count, mv_ref_list, bw, bh, xd, Done);
805 0 : } else if (candidate->ref_frame[1] == ref_frame) {
806 0 : ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 1, mv_ref->col, block),
807 : refmv_count, mv_ref_list, bw, bh, xd, Done);
808 : }
809 : }
810 : }
811 :
812 : Done:
813 :
814 0 : if (mode_context)
815 0 : mode_context[ref_frame] = counter_to_context[context_counter];
816 0 : }
817 : #endif // CONFIG_EXT_INTER
818 :
819 0 : void av1_find_mv_refs(const AV1_COMMON *cm, const MACROBLOCKD *xd,
820 : MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame,
821 : uint8_t *ref_mv_count, CANDIDATE_MV *ref_mv_stack,
822 : #if CONFIG_EXT_INTER
823 : int16_t *compound_mode_context,
824 : #endif // CONFIG_EXT_INTER
825 : int_mv *mv_ref_list, int mi_row, int mi_col,
826 : find_mv_refs_sync sync, void *const data,
827 : int16_t *mode_context) {
828 : int_mv zeromv[2];
829 : #if CONFIG_GLOBAL_MOTION
830 0 : BLOCK_SIZE bsize = mi->mbmi.sb_type;
831 : #endif // CONFIG_GLOBAL_MOTION
832 0 : int idx, all_zero = 1;
833 : #if CONFIG_GLOBAL_MOTION
834 : MV_REFERENCE_FRAME rf[2];
835 : #endif // CONFIG_GLOBAL_MOTION
836 :
837 : #if CONFIG_EXT_INTER
838 0 : av1_update_mv_context(cm, xd, mi, ref_frame, mv_ref_list, -1, mi_row, mi_col,
839 : compound_mode_context);
840 : #endif // CONFIG_EXT_INTER
841 :
842 : #if CONFIG_GLOBAL_MOTION
843 0 : av1_set_ref_frame(rf, ref_frame);
844 0 : zeromv[0].as_int = gm_get_motion_vector(&cm->global_motion[rf[0]],
845 : cm->allow_high_precision_mv, bsize,
846 : mi_col, mi_row, 0)
847 0 : .as_int;
848 0 : zeromv[1].as_int = (rf[1] != NONE_FRAME)
849 0 : ? gm_get_motion_vector(&cm->global_motion[rf[1]],
850 : cm->allow_high_precision_mv,
851 : bsize, mi_col, mi_row, 0)
852 : .as_int
853 0 : : 0;
854 : #else
855 : zeromv[0].as_int = zeromv[1].as_int = 0;
856 : #endif // CONFIG_GLOBAL_MOTION
857 :
858 0 : if (ref_frame <= ALTREF_FRAME)
859 0 : find_mv_refs_idx(cm, xd, mi, ref_frame, mv_ref_list, -1, mi_row, mi_col,
860 : sync, data, mode_context, zeromv[0]);
861 :
862 0 : setup_ref_mv_list(cm, xd, ref_frame, ref_mv_count, ref_mv_stack, mv_ref_list,
863 : -1, mi_row, mi_col, mode_context);
864 : /* Note: If global motion is enabled, then we want to set the ALL_ZERO flag
865 : iff all of the MVs we could generate with NEARMV/NEARESTMV are equivalent
866 : to the global motion vector.
867 : Note: For the following to work properly, the encoder can't throw away
868 : any global motion models after calling this function, even if they are
869 : unused. Instead we rely on the recode loop: If any non-IDENTITY model
870 : is unused, the whole frame will be re-encoded without it.
871 : The problem is that, otherwise, we can end up in the following situation:
872 : * Encoder has a global motion model with nonzero translational part,
873 : and all candidate MVs are zero. So the ALL_ZERO flag is unset.
874 : * Encoder throws away global motion because it is never used.
875 : * Decoder sees that there is no global motion and all candidate MVs are
876 : zero, so sets the ALL_ZERO flag.
877 : * This leads to an encode/decode mismatch.
878 : */
879 0 : if (*ref_mv_count >= 2) {
880 0 : for (idx = 0; idx < AOMMIN(3, *ref_mv_count); ++idx) {
881 0 : if (ref_mv_stack[idx].this_mv.as_int != zeromv[0].as_int) all_zero = 0;
882 0 : if (ref_frame > ALTREF_FRAME)
883 0 : if (ref_mv_stack[idx].comp_mv.as_int != zeromv[1].as_int) all_zero = 0;
884 : }
885 0 : } else if (ref_frame <= ALTREF_FRAME) {
886 0 : for (idx = 0; idx < MAX_MV_REF_CANDIDATES; ++idx)
887 0 : if (mv_ref_list[idx].as_int != zeromv[0].as_int) all_zero = 0;
888 : }
889 :
890 0 : if (all_zero) mode_context[ref_frame] |= (1 << ALL_ZERO_FLAG_OFFSET);
891 0 : }
892 :
893 0 : void av1_find_best_ref_mvs(int allow_hp, int_mv *mvlist, int_mv *nearest_mv,
894 : int_mv *near_mv) {
895 : int i;
896 : // Make sure all the candidates are properly clamped etc
897 0 : for (i = 0; i < MAX_MV_REF_CANDIDATES; ++i) {
898 0 : lower_mv_precision(&mvlist[i].as_mv, allow_hp);
899 : }
900 0 : *nearest_mv = mvlist[0];
901 0 : *near_mv = mvlist[1];
902 0 : }
903 :
904 0 : void av1_append_sub8x8_mvs_for_idx(const AV1_COMMON *cm, MACROBLOCKD *xd,
905 : int block, int ref, int mi_row, int mi_col,
906 : CANDIDATE_MV *ref_mv_stack,
907 : uint8_t *ref_mv_count,
908 : #if CONFIG_EXT_INTER
909 : int_mv *mv_list,
910 : #endif // CONFIG_EXT_INTER
911 : int_mv *nearest_mv, int_mv *near_mv) {
912 : #if !CONFIG_EXT_INTER
913 : int_mv mv_list[MAX_MV_REF_CANDIDATES];
914 : #endif // !CONFIG_EXT_INTER
915 0 : MODE_INFO *const mi = xd->mi[0];
916 0 : b_mode_info *bmi = mi->bmi;
917 : int n;
918 : int_mv zeromv;
919 : CANDIDATE_MV tmp_mv;
920 : uint8_t idx;
921 0 : uint8_t above_count = 0, left_count = 0;
922 0 : MV_REFERENCE_FRAME rf[2] = { mi->mbmi.ref_frame[ref], NONE_FRAME };
923 0 : *ref_mv_count = 0;
924 :
925 : assert(MAX_MV_REF_CANDIDATES == 2);
926 :
927 : #if CONFIG_GLOBAL_MOTION
928 0 : zeromv.as_int =
929 0 : gm_get_motion_vector(&cm->global_motion[ref], cm->allow_high_precision_mv,
930 0 : mi->mbmi.sb_type, mi_col, mi_row, block)
931 0 : .as_int;
932 : #else
933 : zeromv.as_int = 0;
934 : #endif
935 0 : find_mv_refs_idx(cm, xd, mi, mi->mbmi.ref_frame[ref], mv_list, block, mi_row,
936 : mi_col, NULL, NULL, NULL, zeromv);
937 :
938 0 : scan_blk_mbmi(cm, xd, mi_row, mi_col, block, rf, -1, 0, ref_mv_stack,
939 : ref_mv_count);
940 0 : above_count = *ref_mv_count;
941 :
942 0 : scan_blk_mbmi(cm, xd, mi_row, mi_col, block, rf, 0, -1, ref_mv_stack,
943 : ref_mv_count);
944 0 : left_count = *ref_mv_count - above_count;
945 :
946 0 : if (above_count > 1 && left_count > 0) {
947 0 : tmp_mv = ref_mv_stack[1];
948 0 : ref_mv_stack[1] = ref_mv_stack[above_count];
949 0 : ref_mv_stack[above_count] = tmp_mv;
950 : }
951 :
952 0 : for (idx = 0; idx < *ref_mv_count; ++idx)
953 0 : clamp_mv_ref(&ref_mv_stack[idx].this_mv.as_mv, xd->n8_w << MI_SIZE_LOG2,
954 0 : xd->n8_h << MI_SIZE_LOG2, xd);
955 :
956 0 : for (idx = 0; idx < AOMMIN(MAX_MV_REF_CANDIDATES, *ref_mv_count); ++idx)
957 0 : mv_list[idx].as_int = ref_mv_stack[idx].this_mv.as_int;
958 :
959 0 : near_mv->as_int = 0;
960 0 : switch (block) {
961 : case 0:
962 0 : nearest_mv->as_int = mv_list[0].as_int;
963 0 : near_mv->as_int = mv_list[1].as_int;
964 0 : break;
965 : case 1:
966 : case 2:
967 0 : nearest_mv->as_int = bmi[0].as_mv[ref].as_int;
968 0 : for (n = 0; n < MAX_MV_REF_CANDIDATES; ++n)
969 0 : if (nearest_mv->as_int != mv_list[n].as_int) {
970 0 : near_mv->as_int = mv_list[n].as_int;
971 0 : break;
972 : }
973 0 : break;
974 : case 3: {
975 : int_mv candidates[2 + MAX_MV_REF_CANDIDATES];
976 0 : candidates[0] = bmi[1].as_mv[ref];
977 0 : candidates[1] = bmi[0].as_mv[ref];
978 0 : candidates[2] = mv_list[0];
979 0 : candidates[3] = mv_list[1];
980 :
981 0 : nearest_mv->as_int = bmi[2].as_mv[ref].as_int;
982 0 : for (n = 0; n < 2 + MAX_MV_REF_CANDIDATES; ++n)
983 0 : if (nearest_mv->as_int != candidates[n].as_int) {
984 0 : near_mv->as_int = candidates[n].as_int;
985 0 : break;
986 : }
987 0 : break;
988 : }
989 0 : default: assert(0 && "Invalid block index.");
990 : }
991 0 : }
992 :
993 : #if CONFIG_WARPED_MOTION
994 0 : void calc_projection_samples(MB_MODE_INFO *const mbmi, int x, int y,
995 : int *pts_inref) {
996 0 : pts_inref[0] = (x * 8) + mbmi->mv[0].as_mv.col;
997 0 : pts_inref[1] = (y * 8) + mbmi->mv[0].as_mv.row;
998 0 : }
999 :
1000 : // Note: Samples returned are at 1/8-pel precision
1001 0 : int findSamples(const AV1_COMMON *cm, MACROBLOCKD *xd, int mi_row, int mi_col,
1002 : int *pts, int *pts_inref) {
1003 0 : MB_MODE_INFO *const mbmi0 = &(xd->mi[0]->mbmi);
1004 0 : int ref_frame = mbmi0->ref_frame[0];
1005 0 : int up_available = xd->up_available;
1006 0 : int left_available = xd->left_available;
1007 0 : int i, mi_step, np = 0;
1008 0 : int global_offset_c = mi_col * MI_SIZE;
1009 0 : int global_offset_r = mi_row * MI_SIZE;
1010 :
1011 : // scan the above row
1012 0 : if (up_available) {
1013 0 : for (i = 0; i < AOMMIN(xd->n8_w, cm->mi_cols - mi_col); i += mi_step) {
1014 0 : int mi_row_offset = -1;
1015 0 : int mi_col_offset = i;
1016 :
1017 0 : MODE_INFO *mi = xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride];
1018 0 : MB_MODE_INFO *mbmi = &mi->mbmi;
1019 :
1020 0 : mi_step = AOMMIN(xd->n8_w, mi_size_wide[mbmi->sb_type]);
1021 :
1022 0 : if (mbmi->ref_frame[0] == ref_frame && mbmi->ref_frame[1] == NONE_FRAME) {
1023 0 : int bw = block_size_wide[mbmi->sb_type];
1024 0 : int bh = block_size_high[mbmi->sb_type];
1025 0 : int cr_offset = -AOMMAX(bh, MI_SIZE) / 2 - 1;
1026 0 : int cc_offset = i * MI_SIZE + AOMMAX(bw, MI_SIZE) / 2 - 1;
1027 0 : int x = cc_offset + global_offset_c;
1028 0 : int y = cr_offset + global_offset_r;
1029 :
1030 0 : pts[0] = (x * 8);
1031 0 : pts[1] = (y * 8);
1032 0 : calc_projection_samples(mbmi, x, y, pts_inref);
1033 0 : pts += 2;
1034 0 : pts_inref += 2;
1035 0 : np++;
1036 0 : if (np >= LEAST_SQUARES_SAMPLES_MAX) return LEAST_SQUARES_SAMPLES_MAX;
1037 : }
1038 : }
1039 : }
1040 0 : assert(2 * np <= SAMPLES_ARRAY_SIZE);
1041 :
1042 : // scan the left column
1043 0 : if (left_available) {
1044 0 : for (i = 0; i < AOMMIN(xd->n8_h, cm->mi_rows - mi_row); i += mi_step) {
1045 0 : int mi_row_offset = i;
1046 0 : int mi_col_offset = -1;
1047 :
1048 0 : MODE_INFO *mi = xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride];
1049 0 : MB_MODE_INFO *mbmi = &mi->mbmi;
1050 :
1051 0 : mi_step = AOMMIN(xd->n8_h, mi_size_high[mbmi->sb_type]);
1052 :
1053 0 : if (mbmi->ref_frame[0] == ref_frame && mbmi->ref_frame[1] == NONE_FRAME) {
1054 0 : int bw = block_size_wide[mbmi->sb_type];
1055 0 : int bh = block_size_high[mbmi->sb_type];
1056 0 : int cr_offset = i * MI_SIZE + AOMMAX(bh, MI_SIZE) / 2 - 1;
1057 0 : int cc_offset = -AOMMAX(bw, MI_SIZE) / 2 - 1;
1058 0 : int x = cc_offset + global_offset_c;
1059 0 : int y = cr_offset + global_offset_r;
1060 :
1061 0 : pts[0] = (x * 8);
1062 0 : pts[1] = (y * 8);
1063 0 : calc_projection_samples(mbmi, x, y, pts_inref);
1064 0 : pts += 2;
1065 0 : pts_inref += 2;
1066 0 : np++;
1067 0 : if (np >= LEAST_SQUARES_SAMPLES_MAX) return LEAST_SQUARES_SAMPLES_MAX;
1068 : }
1069 : }
1070 : }
1071 0 : assert(2 * np <= SAMPLES_ARRAY_SIZE);
1072 :
1073 0 : if (left_available && up_available) {
1074 0 : int mi_row_offset = -1;
1075 0 : int mi_col_offset = -1;
1076 :
1077 0 : MODE_INFO *mi = xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride];
1078 0 : MB_MODE_INFO *mbmi = &mi->mbmi;
1079 :
1080 0 : if (mbmi->ref_frame[0] == ref_frame && mbmi->ref_frame[1] == NONE_FRAME) {
1081 0 : int bw = block_size_wide[mbmi->sb_type];
1082 0 : int bh = block_size_high[mbmi->sb_type];
1083 0 : int cr_offset = -AOMMAX(bh, MI_SIZE) / 2 - 1;
1084 0 : int cc_offset = -AOMMAX(bw, MI_SIZE) / 2 - 1;
1085 0 : int x = cc_offset + global_offset_c;
1086 0 : int y = cr_offset + global_offset_r;
1087 :
1088 0 : pts[0] = (x * 8);
1089 0 : pts[1] = (y * 8);
1090 0 : calc_projection_samples(mbmi, x, y, pts_inref);
1091 0 : np++;
1092 : }
1093 : }
1094 0 : assert(2 * np <= SAMPLES_ARRAY_SIZE);
1095 :
1096 0 : return np;
1097 : }
1098 : #endif // CONFIG_WARPED_MOTION
|