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 #if CONFIG_GLOBAL_MOTION
18 #define USE_CUR_GM_REFMV 1
19 #endif // CONFIG_GLOBAL_MOTION
20
av1_copy_frame_mvs(const AV1_COMMON * const cm,MODE_INFO * mi,int mi_row,int mi_col,int x_mis,int y_mis)21 void av1_copy_frame_mvs(const AV1_COMMON *const cm, MODE_INFO *mi, int mi_row,
22 int mi_col, int x_mis, int y_mis) {
23 #if CONFIG_TMV
24 const int frame_mvs_stride = ROUND_POWER_OF_TWO(cm->mi_cols, 1);
25 MV_REF *frame_mvs = cm->cur_frame->mvs +
26 ((mi_row & 0xfffe) >> 1) * frame_mvs_stride +
27 ((mi_col & 0xfffe) >> 1);
28 x_mis = ROUND_POWER_OF_TWO(x_mis, 1);
29 y_mis = ROUND_POWER_OF_TWO(y_mis, 1);
30 #else
31 const int frame_mvs_stride = cm->mi_cols;
32 MV_REF *frame_mvs = cm->cur_frame->mvs +
33 (mi_row & 0xfffe) * frame_mvs_stride + (mi_col & 0xfffe);
34 x_mis = AOMMAX(x_mis, 2);
35 y_mis = AOMMAX(y_mis, 2);
36 #endif // CONFIG_TMV
37 int w, h;
38
39 for (h = 0; h < y_mis; h++) {
40 MV_REF *const frame_mv = frame_mvs + h * frame_mvs_stride;
41 for (w = 0; w < x_mis; w++) {
42 MV_REF *const mv = frame_mv + w;
43 mv->ref_frame[0] = mi->mbmi.ref_frame[0];
44 mv->ref_frame[1] = mi->mbmi.ref_frame[1];
45 mv->mv[0].as_int = mi->mbmi.mv[0].as_int;
46 mv->mv[1].as_int = mi->mbmi.mv[1].as_int;
47 // (TODO:yunqing) The following 2 lines won't be used and can be removed.
48 mv->pred_mv[0].as_int = mi->mbmi.pred_mv[0].as_int;
49 mv->pred_mv[1].as_int = mi->mbmi.pred_mv[1].as_int;
50 }
51 }
52 }
53
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_mv * gm_mv_candidates,const WarpedMotionParams * gm_params,int col,int weight,int is_integer)54 static uint8_t add_ref_mv_candidate(
55 const MODE_INFO *const candidate_mi, const MB_MODE_INFO *const candidate,
56 const MV_REFERENCE_FRAME rf[2], uint8_t *refmv_count,
57 CANDIDATE_MV *ref_mv_stack, const int use_hp, int len, int block,
58 #if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
59 int_mv *gm_mv_candidates, const WarpedMotionParams *gm_params,
60 #endif // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
61 int col, int weight
62 #if CONFIG_AMVR
63 ,
64 int is_integer
65 #endif
66 ) {
67 int index = 0, ref;
68 int newmv_count = 0;
69 #if CONFIG_CB4X4
70 const int unify_bsize = 1;
71 #else
72 const int unify_bsize = 0;
73 #endif
74 assert(weight % 2 == 0);
75
76 if (rf[1] == NONE_FRAME) {
77 // single reference frame
78 for (ref = 0; ref < 2; ++ref) {
79 if (candidate->ref_frame[ref] == rf[0]) {
80 int_mv this_refmv;
81 #if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
82 if (is_global_mv_block(candidate_mi, block, gm_params[rf[0]].wmtype))
83 this_refmv = gm_mv_candidates[0];
84 else
85 #endif // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
86 this_refmv = get_sub_block_mv(candidate_mi, ref, col, block);
87 #if CONFIG_AMVR
88 lower_mv_precision(&this_refmv.as_mv, use_hp, is_integer);
89 #else
90 lower_mv_precision(&this_refmv.as_mv, use_hp);
91 #endif // CONFIG_AMVR
92
93 for (index = 0; index < *refmv_count; ++index)
94 if (ref_mv_stack[index].this_mv.as_int == this_refmv.as_int) break;
95
96 if (index < *refmv_count) ref_mv_stack[index].weight += weight * len;
97
98 // Add a new item to the list.
99 if (index == *refmv_count) {
100 ref_mv_stack[index].this_mv = this_refmv;
101 ref_mv_stack[index].pred_diff[0] = av1_get_pred_diff_ctx(
102 get_sub_block_pred_mv(candidate_mi, ref, col, block), this_refmv);
103 ref_mv_stack[index].weight = weight * len;
104 ++(*refmv_count);
105
106 if (candidate->mode == NEWMV) ++newmv_count;
107 }
108
109 if (candidate_mi->mbmi.sb_type < BLOCK_8X8 && block >= 0 &&
110 !unify_bsize) {
111 int alt_block = 3 - block;
112 this_refmv = get_sub_block_mv(candidate_mi, ref, col, alt_block);
113 #if CONFIG_AMVR
114 lower_mv_precision(&this_refmv.as_mv, use_hp, is_integer);
115 #else
116 lower_mv_precision(&this_refmv.as_mv, use_hp);
117 #endif
118 for (index = 0; index < *refmv_count; ++index)
119 if (ref_mv_stack[index].this_mv.as_int == this_refmv.as_int) break;
120
121 if (index < *refmv_count) ref_mv_stack[index].weight += len;
122
123 // Add a new item to the list.
124 if (index == *refmv_count) {
125 ref_mv_stack[index].this_mv = this_refmv;
126 ref_mv_stack[index].pred_diff[0] = av1_get_pred_diff_ctx(
127 get_sub_block_pred_mv(candidate_mi, ref, col, alt_block),
128 this_refmv);
129 ref_mv_stack[index].weight = len;
130 ++(*refmv_count);
131
132 if (candidate->mode == NEWMV) ++newmv_count;
133 }
134 }
135 }
136 }
137 } else {
138 // compound reference frame
139 if (candidate->ref_frame[0] == rf[0] && candidate->ref_frame[1] == rf[1]) {
140 int_mv this_refmv[2];
141
142 for (ref = 0; ref < 2; ++ref) {
143 #if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
144 if (is_global_mv_block(candidate_mi, block, gm_params[rf[ref]].wmtype))
145 this_refmv[ref] = gm_mv_candidates[ref];
146 else
147 #endif // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
148 this_refmv[ref] = get_sub_block_mv(candidate_mi, ref, col, block);
149 #if CONFIG_AMVR
150 lower_mv_precision(&this_refmv[ref].as_mv, use_hp, is_integer);
151 #else
152 lower_mv_precision(&this_refmv[ref].as_mv, use_hp);
153 #endif
154 }
155
156 for (index = 0; index < *refmv_count; ++index)
157 if ((ref_mv_stack[index].this_mv.as_int == this_refmv[0].as_int) &&
158 (ref_mv_stack[index].comp_mv.as_int == this_refmv[1].as_int))
159 break;
160
161 if (index < *refmv_count) ref_mv_stack[index].weight += weight * len;
162
163 // Add a new item to the list.
164 if (index == *refmv_count) {
165 ref_mv_stack[index].this_mv = this_refmv[0];
166 ref_mv_stack[index].comp_mv = this_refmv[1];
167 ref_mv_stack[index].pred_diff[0] = av1_get_pred_diff_ctx(
168 get_sub_block_pred_mv(candidate_mi, 0, col, block), this_refmv[0]);
169 ref_mv_stack[index].pred_diff[1] = av1_get_pred_diff_ctx(
170 get_sub_block_pred_mv(candidate_mi, 1, col, block), this_refmv[1]);
171 ref_mv_stack[index].weight = weight * len;
172 ++(*refmv_count);
173
174 if (candidate->mode == NEW_NEWMV) ++newmv_count;
175 }
176
177 if (candidate_mi->mbmi.sb_type < BLOCK_8X8 && block >= 0 &&
178 !unify_bsize) {
179 int alt_block = 3 - block;
180 this_refmv[0] = get_sub_block_mv(candidate_mi, 0, col, alt_block);
181 this_refmv[1] = get_sub_block_mv(candidate_mi, 1, col, alt_block);
182
183 for (ref = 0; ref < 2; ++ref) {
184 #if CONFIG_AMVR
185 lower_mv_precision(&this_refmv[ref].as_mv, use_hp, is_integer);
186 #else
187 lower_mv_precision(&this_refmv[ref].as_mv, use_hp);
188 #endif
189 }
190 for (index = 0; index < *refmv_count; ++index)
191 if (ref_mv_stack[index].this_mv.as_int == this_refmv[0].as_int &&
192 ref_mv_stack[index].comp_mv.as_int == this_refmv[1].as_int)
193 break;
194
195 if (index < *refmv_count) ref_mv_stack[index].weight += len;
196
197 // Add a new item to the list.
198 if (index == *refmv_count) {
199 ref_mv_stack[index].this_mv = this_refmv[0];
200 ref_mv_stack[index].comp_mv = this_refmv[1];
201 ref_mv_stack[index].pred_diff[0] = av1_get_pred_diff_ctx(
202 get_sub_block_pred_mv(candidate_mi, 0, col, block),
203 this_refmv[0]);
204 ref_mv_stack[index].pred_diff[0] = av1_get_pred_diff_ctx(
205 get_sub_block_pred_mv(candidate_mi, 1, col, block),
206 this_refmv[1]);
207 ref_mv_stack[index].weight = len;
208 ++(*refmv_count);
209
210 if (candidate->mode == NEW_NEWMV) ++newmv_count;
211 }
212 }
213 }
214 }
215 return newmv_count;
216 }
217
scan_row_mbmi(const AV1_COMMON * cm,const MACROBLOCKD * xd,const int mi_col,int block,const MV_REFERENCE_FRAME rf[2],int row_offset,CANDIDATE_MV * ref_mv_stack,uint8_t * refmv_count,int_mv * gm_mv_candidates,int max_row_offset,int * processed_rows)218 static uint8_t scan_row_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
219 const int mi_col, int block,
220 const MV_REFERENCE_FRAME rf[2], int row_offset,
221 CANDIDATE_MV *ref_mv_stack, uint8_t *refmv_count,
222 #if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
223 int_mv *gm_mv_candidates,
224 #endif // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
225 int max_row_offset, int *processed_rows) {
226 const int end_mi = AOMMIN(xd->n8_w, cm->mi_cols - mi_col);
227 const int n8_w_8 = mi_size_wide[BLOCK_8X8];
228 const int n8_w_16 = mi_size_wide[BLOCK_16X16];
229 int i;
230 uint8_t newmv_count = 0;
231 int col_offset = 0;
232 #if CONFIG_CB4X4
233 const int shift = 0;
234 // TODO(jingning): Revisit this part after cb4x4 is stable.
235 if (abs(row_offset) > 1) {
236 col_offset = 1;
237 if (mi_col & 0x01 && xd->n8_w < n8_w_8) --col_offset;
238 }
239 const int use_step_16 = (xd->n8_w >= 16);
240 #else
241 const int shift = 1;
242 const int use_step_16 = (xd->n8_w >= 8);
243 #endif
244 MODE_INFO **const candidate_mi0 = xd->mi + row_offset * xd->mi_stride;
245
246 for (i = 0; i < end_mi && *refmv_count < MAX_REF_MV_STACK_SIZE;) {
247 const MODE_INFO *const candidate_mi = candidate_mi0[col_offset + i];
248 const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
249 const int candidate_bsize = candidate->sb_type;
250 const int n8_w = mi_size_wide[candidate_bsize];
251 int len = AOMMIN(xd->n8_w, n8_w);
252 if (use_step_16)
253 len = AOMMAX(n8_w_16, len);
254 else if (abs(row_offset) > 1)
255 len = AOMMAX(len, n8_w_8);
256
257 int weight = 2;
258 if (xd->n8_w >= n8_w_8 && xd->n8_w <= n8_w) {
259 int inc = AOMMIN(-max_row_offset + row_offset + 1,
260 mi_size_high[candidate_bsize]);
261 // Obtain range used in weight calculation.
262 weight = AOMMAX(weight, (inc << shift));
263 // Update processed rows.
264 *processed_rows = inc - row_offset - 1;
265 }
266
267 #if CONFIG_AMVR
268 newmv_count += add_ref_mv_candidate(
269 candidate_mi, candidate, rf, refmv_count, ref_mv_stack,
270 cm->allow_high_precision_mv, len, block,
271 #if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
272 gm_mv_candidates, cm->global_motion,
273 #endif // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
274 col_offset + i, weight, cm->cur_frame_mv_precision_level);
275 #else
276 newmv_count += add_ref_mv_candidate(candidate_mi, candidate, rf,
277 refmv_count, ref_mv_stack,
278 cm->allow_high_precision_mv, len, block,
279 #if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
280 gm_mv_candidates, cm->global_motion,
281 #endif // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
282 col_offset + i, weight);
283 #endif
284
285 i += len;
286 }
287
288 return newmv_count;
289 }
290
scan_col_mbmi(const AV1_COMMON * cm,const MACROBLOCKD * xd,const int mi_row,int block,const MV_REFERENCE_FRAME rf[2],int col_offset,CANDIDATE_MV * ref_mv_stack,uint8_t * refmv_count,int_mv * gm_mv_candidates,int max_col_offset,int * processed_cols)291 static uint8_t scan_col_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
292 const int mi_row, int block,
293 const MV_REFERENCE_FRAME rf[2], int col_offset,
294 CANDIDATE_MV *ref_mv_stack, uint8_t *refmv_count,
295 #if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
296 int_mv *gm_mv_candidates,
297 #endif // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
298 int max_col_offset, int *processed_cols) {
299 const int end_mi = AOMMIN(xd->n8_h, cm->mi_rows - mi_row);
300 const int n8_h_8 = mi_size_high[BLOCK_8X8];
301 const int n8_h_16 = mi_size_high[BLOCK_16X16];
302 int i;
303 uint8_t newmv_count = 0;
304 int row_offset = 0;
305 #if CONFIG_CB4X4
306 const int shift = 0;
307 if (abs(col_offset) > 1) {
308 row_offset = 1;
309 if (mi_row & 0x01 && xd->n8_h < n8_h_8) --row_offset;
310 }
311 const int use_step_16 = (xd->n8_h >= 16);
312 #else
313 const int shift = 1;
314 const int use_step_16 = (xd->n8_h >= 8);
315 #endif
316
317 for (i = 0; i < end_mi && *refmv_count < MAX_REF_MV_STACK_SIZE;) {
318 const MODE_INFO *const candidate_mi =
319 xd->mi[(row_offset + i) * xd->mi_stride + col_offset];
320 const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
321 const int candidate_bsize = candidate->sb_type;
322 const int n8_h = mi_size_high[candidate_bsize];
323 int len = AOMMIN(xd->n8_h, n8_h);
324 if (use_step_16)
325 len = AOMMAX(n8_h_16, len);
326 else if (abs(col_offset) > 1)
327 len = AOMMAX(len, n8_h_8);
328
329 int weight = 2;
330 if (xd->n8_h >= n8_h_8 && xd->n8_h <= n8_h) {
331 int inc = AOMMIN(-max_col_offset + col_offset + 1,
332 mi_size_wide[candidate_bsize]);
333 // Obtain range used in weight calculation.
334 weight = AOMMAX(weight, (inc << shift));
335 // Update processed cols.
336 *processed_cols = inc - col_offset - 1;
337 }
338
339 #if CONFIG_AMVR
340 newmv_count += add_ref_mv_candidate(
341 candidate_mi, candidate, rf, refmv_count, ref_mv_stack,
342 cm->allow_high_precision_mv, len, block,
343 #if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
344 gm_mv_candidates, cm->global_motion,
345 #endif // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
346 col_offset, weight, cm->cur_frame_mv_precision_level);
347 #else
348 newmv_count += add_ref_mv_candidate(candidate_mi, candidate, rf,
349 refmv_count, ref_mv_stack,
350 cm->allow_high_precision_mv, len, block,
351 #if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
352 gm_mv_candidates, cm->global_motion,
353 #endif // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
354 col_offset, weight);
355 #endif
356 i += len;
357 }
358
359 return newmv_count;
360 }
361
scan_blk_mbmi(const AV1_COMMON * cm,const MACROBLOCKD * xd,const int mi_row,const int mi_col,int block,const MV_REFERENCE_FRAME rf[2],int row_offset,int col_offset,CANDIDATE_MV * ref_mv_stack,int_mv * gm_mv_candidates,uint8_t * refmv_count)362 static uint8_t scan_blk_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
363 const int mi_row, const int mi_col, int block,
364 const MV_REFERENCE_FRAME rf[2], int row_offset,
365 int col_offset, CANDIDATE_MV *ref_mv_stack,
366 #if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
367 int_mv *gm_mv_candidates,
368 #endif // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
369 uint8_t *refmv_count) {
370 const TileInfo *const tile = &xd->tile;
371 POSITION mi_pos;
372 uint8_t newmv_count = 0;
373
374 mi_pos.row = row_offset;
375 mi_pos.col = col_offset;
376
377 if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm, &mi_pos) &&
378 *refmv_count < MAX_REF_MV_STACK_SIZE) {
379 const MODE_INFO *const candidate_mi =
380 xd->mi[mi_pos.row * xd->mi_stride + mi_pos.col];
381 const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
382 const int len = mi_size_wide[BLOCK_8X8];
383
384 #if CONFIG_AMVR
385 newmv_count += add_ref_mv_candidate(
386 candidate_mi, candidate, rf, refmv_count, ref_mv_stack,
387 cm->allow_high_precision_mv, len, block,
388 #if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
389 gm_mv_candidates, cm->global_motion,
390 #endif // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
391 mi_pos.col, 2, cm->cur_frame_mv_precision_level);
392 #else
393 newmv_count += add_ref_mv_candidate(candidate_mi, candidate, rf,
394 refmv_count, ref_mv_stack,
395 cm->allow_high_precision_mv, len, block,
396 #if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
397 gm_mv_candidates, cm->global_motion,
398 #endif // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
399 mi_pos.col, 2);
400 #endif
401 } // Analyze a single 8x8 block motion information.
402
403 return newmv_count;
404 }
405
has_top_right(const AV1_COMMON * cm,const MACROBLOCKD * xd,int mi_row,int mi_col,int bs)406 static int has_top_right(const AV1_COMMON *cm, const MACROBLOCKD *xd,
407 int mi_row, int mi_col, int bs) {
408 const int sb_mi_size = mi_size_wide[cm->sb_size];
409 const int mask_row = mi_row & (sb_mi_size - 1);
410 const int mask_col = mi_col & (sb_mi_size - 1);
411
412 // In a split partition all apart from the bottom right has a top right
413 int has_tr = !((mask_row & bs) && (mask_col & bs));
414
415 // bs > 0 and bs is a power of 2
416 assert(bs > 0 && !(bs & (bs - 1)));
417
418 // For each 4x4 group of blocks, when the bottom right is decoded the blocks
419 // to the right have not been decoded therefore the bottom right does
420 // not have a top right
421 while (bs < sb_mi_size) {
422 if (mask_col & bs) {
423 if ((mask_col & (2 * bs)) && (mask_row & (2 * bs))) {
424 has_tr = 0;
425 break;
426 }
427 } else {
428 break;
429 }
430 bs <<= 1;
431 }
432
433 // The left hand of two vertical rectangles always has a top right (as the
434 // block above will have been decoded)
435 if (xd->n8_w < xd->n8_h)
436 if (!xd->is_sec_rect) has_tr = 1;
437
438 // The bottom of two horizontal rectangles never has a top right (as the block
439 // to the right won't have been decoded)
440 if (xd->n8_w > xd->n8_h)
441 if (xd->is_sec_rect) has_tr = 0;
442
443 #if CONFIG_EXT_PARTITION_TYPES && !CONFIG_EXT_PARTITION_TYPES_AB
444 // The bottom left square of a Vertical A (in the old format) does
445 // not have a top right as it is decoded before the right hand
446 // rectangle of the partition
447 if (xd->mi[0]->mbmi.partition == PARTITION_VERT_A)
448 if ((mask_row & bs) && !(mask_col & bs)) has_tr = 0;
449 #endif // CONFIG_EXT_PARTITION_TYPES
450
451 return has_tr;
452 }
453
454 #if CONFIG_MFMV
check_sb_border(const AV1_COMMON * cm,const int mi_row,const int mi_col,const int row_offset,const int col_offset)455 static int check_sb_border(const AV1_COMMON *cm, const int mi_row,
456 const int mi_col, const int row_offset,
457 const int col_offset) {
458 const int sb_mi_size = mi_size_wide[cm->sb_size];
459 const int row = mi_row & (sb_mi_size - 1);
460 const int col = mi_col & (sb_mi_size - 1);
461
462 if (row + row_offset < 0 || row + row_offset >= sb_mi_size ||
463 col + col_offset < 0 || col + col_offset >= sb_mi_size)
464 return 0;
465
466 return 1;
467 }
468
add_tpl_ref_mv(const AV1_COMMON * cm,const MV_REF * prev_frame_mvs_base,const MACROBLOCKD * xd,int mi_row,int mi_col,MV_REFERENCE_FRAME ref_frame,int blk_row,int blk_col,uint8_t * refmv_count,CANDIDATE_MV * ref_mv_stack,int16_t * mode_context)469 static int add_tpl_ref_mv(const AV1_COMMON *cm,
470 const MV_REF *prev_frame_mvs_base,
471 const MACROBLOCKD *xd, int mi_row, int mi_col,
472 MV_REFERENCE_FRAME ref_frame, int blk_row,
473 int blk_col, uint8_t *refmv_count,
474 CANDIDATE_MV *ref_mv_stack, int16_t *mode_context) {
475 (void)prev_frame_mvs_base;
476 POSITION mi_pos;
477 int idx;
478 int coll_blk_count = 0;
479 const int weight_unit = 1; // mi_size_wide[BLOCK_8X8];
480
481 #if CONFIG_MV_COMPRESS
482 mi_pos.row = (mi_row & 0x01) ? blk_row : blk_row + 1;
483 mi_pos.col = (mi_col & 0x01) ? blk_col : blk_col + 1;
484 #else
485 mi_pos.row = blk_row;
486 mi_pos.col = blk_col;
487 #endif
488
489 if (!is_inside(&xd->tile, mi_col, mi_row, cm->mi_rows, cm, &mi_pos))
490 return coll_blk_count;
491
492 const TPL_MV_REF *prev_frame_mvs = cm->cur_frame->tpl_mvs +
493 (mi_row + mi_pos.row) * cm->mi_stride +
494 (mi_col + mi_pos.col);
495
496 MV_REFERENCE_FRAME rf[2];
497 av1_set_ref_frame(rf, ref_frame);
498
499 if (rf[1] == NONE_FRAME) {
500 for (int i = 0; i < MFMV_STACK_SIZE; ++i) {
501 if (prev_frame_mvs->mfmv[ref_frame - LAST_FRAME][i].as_int !=
502 INVALID_MV) {
503 int_mv this_refmv = prev_frame_mvs->mfmv[ref_frame - LAST_FRAME][i];
504 lower_mv_precision(&this_refmv.as_mv, cm->allow_high_precision_mv);
505
506 if (blk_row == 0 && blk_col == 0)
507 if (abs(this_refmv.as_mv.row) >= 16 ||
508 abs(this_refmv.as_mv.col) >= 16)
509 mode_context[ref_frame] |= (1 << ZEROMV_OFFSET);
510
511 for (idx = 0; idx < *refmv_count; ++idx)
512 if (abs(this_refmv.as_mv.row - ref_mv_stack[idx].this_mv.as_mv.row) <
513 4 &&
514 abs(this_refmv.as_mv.col - ref_mv_stack[idx].this_mv.as_mv.col) <
515 4)
516 break;
517
518 if (idx < *refmv_count) ref_mv_stack[idx].weight += 2 * weight_unit;
519
520 if (idx == *refmv_count && *refmv_count < MAX_REF_MV_STACK_SIZE) {
521 ref_mv_stack[idx].this_mv.as_int = this_refmv.as_int;
522 // TODO(jingning): Hard coded context number. Need to make it better
523 // sense.
524 ref_mv_stack[idx].pred_diff[0] = 1;
525 ref_mv_stack[idx].weight = 2 * weight_unit;
526 ++(*refmv_count);
527 }
528
529 ++coll_blk_count;
530 }
531 }
532 } else {
533 // Process compound inter mode
534 for (int i = 0; i < MFMV_STACK_SIZE; ++i) {
535 if (prev_frame_mvs->mfmv[rf[0] - LAST_FRAME][i].as_int != INVALID_MV &&
536 prev_frame_mvs->mfmv[rf[1] - LAST_FRAME][i].as_int != INVALID_MV) {
537 int_mv this_refmv = prev_frame_mvs->mfmv[rf[0] - LAST_FRAME][i];
538 int_mv comp_refmv = prev_frame_mvs->mfmv[rf[1] - LAST_FRAME][i];
539 lower_mv_precision(&this_refmv.as_mv, cm->allow_high_precision_mv);
540 lower_mv_precision(&comp_refmv.as_mv, cm->allow_high_precision_mv);
541
542 if (blk_row == 0 && blk_col == 0)
543 if (abs(this_refmv.as_mv.row) >= 16 ||
544 abs(this_refmv.as_mv.col) >= 16 ||
545 abs(comp_refmv.as_mv.row) >= 16 ||
546 abs(comp_refmv.as_mv.col) >= 16)
547 mode_context[ref_frame] |= (1 << ZEROMV_OFFSET);
548
549 for (idx = 0; idx < *refmv_count; ++idx)
550 if (abs(this_refmv.as_mv.row - ref_mv_stack[idx].this_mv.as_mv.row) <
551 4 &&
552 abs(this_refmv.as_mv.col - ref_mv_stack[idx].this_mv.as_mv.col) <
553 4 &&
554 abs(comp_refmv.as_mv.row - ref_mv_stack[idx].comp_mv.as_mv.row) <
555 4 &&
556 abs(comp_refmv.as_mv.col - ref_mv_stack[idx].comp_mv.as_mv.col) <
557 4)
558 break;
559
560 if (idx < *refmv_count) ref_mv_stack[idx].weight += 2 * weight_unit;
561
562 if (idx == *refmv_count && *refmv_count < MAX_REF_MV_STACK_SIZE) {
563 ref_mv_stack[idx].this_mv.as_int = this_refmv.as_int;
564 ref_mv_stack[idx].comp_mv.as_int = comp_refmv.as_int;
565 // TODO(jingning): Hard coded context number. Need to make it better
566 // sense.
567 ref_mv_stack[idx].pred_diff[0] = 1;
568 ref_mv_stack[idx].pred_diff[1] = 1;
569 ref_mv_stack[idx].weight = 2 * weight_unit;
570 ++(*refmv_count);
571 }
572
573 ++coll_blk_count;
574 }
575 }
576 }
577
578 return coll_blk_count;
579 }
580 #else
add_col_ref_mv(const AV1_COMMON * cm,const MV_REF * prev_frame_mvs_base,int prev_frame_mvs_stride,const MACROBLOCKD * xd,int mi_row,int mi_col,MV_REFERENCE_FRAME ref_frame,int blk_row,int blk_col,uint8_t * refmv_count,CANDIDATE_MV * ref_mv_stack,int16_t * mode_context)581 static int add_col_ref_mv(const AV1_COMMON *cm,
582 const MV_REF *prev_frame_mvs_base,
583 int prev_frame_mvs_stride, const MACROBLOCKD *xd,
584 int mi_row, int mi_col, MV_REFERENCE_FRAME ref_frame,
585 int blk_row, int blk_col, uint8_t *refmv_count,
586 CANDIDATE_MV *ref_mv_stack, int16_t *mode_context) {
587 #if CONFIG_TMV
588 const MV_REF *prev_frame_mvs = prev_frame_mvs_base +
589 ((blk_row + 1) >> 1) * prev_frame_mvs_stride +
590 ((blk_col + 1) >> 1);
591 #else
592 const MV_REF *prev_frame_mvs =
593 prev_frame_mvs_base + blk_row * prev_frame_mvs_stride + blk_col;
594 #endif
595 POSITION mi_pos;
596 int ref, idx;
597 int coll_blk_count = 0;
598 const int weight_unit = mi_size_wide[BLOCK_8X8];
599
600 #if CONFIG_TMV
601 mi_pos.row = blk_row;
602 mi_pos.col = blk_col;
603 #else
604 #if CONFIG_MV_COMPRESS
605 mi_pos.row = (mi_row & 0x01) ? blk_row : blk_row + 1;
606 mi_pos.col = (mi_col & 0x01) ? blk_col : blk_col + 1;
607 #else
608 mi_pos.row = blk_row;
609 mi_pos.col = blk_col;
610 #endif
611 #endif // CONFIG_TMV
612
613 if (!is_inside(&xd->tile, mi_col, mi_row, cm->mi_rows, cm, &mi_pos))
614 return coll_blk_count;
615 for (ref = 0; ref < 2; ++ref) {
616 if (prev_frame_mvs->ref_frame[ref] == ref_frame) {
617 int_mv this_refmv = prev_frame_mvs->mv[ref];
618 #if CONFIG_AMVR
619 lower_mv_precision(&this_refmv.as_mv, cm->allow_high_precision_mv,
620 cm->cur_frame_mv_precision_level);
621 #else
622 lower_mv_precision(&this_refmv.as_mv, cm->allow_high_precision_mv);
623 #endif
624
625 #if CONFIG_OPT_REF_MV
626 if (blk_row == 0 && blk_col == 0)
627 #endif
628 {
629 if (abs(this_refmv.as_mv.row) >= 16 || abs(this_refmv.as_mv.col) >= 16)
630 mode_context[ref_frame] |= (1 << ZEROMV_OFFSET);
631 }
632
633 for (idx = 0; idx < *refmv_count; ++idx)
634 if (this_refmv.as_int == ref_mv_stack[idx].this_mv.as_int) break;
635
636 if (idx < *refmv_count) ref_mv_stack[idx].weight += 2 * weight_unit;
637
638 if (idx == *refmv_count && *refmv_count < MAX_REF_MV_STACK_SIZE) {
639 ref_mv_stack[idx].this_mv.as_int = this_refmv.as_int;
640 ref_mv_stack[idx].pred_diff[0] =
641 av1_get_pred_diff_ctx(prev_frame_mvs->pred_mv[ref], this_refmv);
642 ref_mv_stack[idx].weight = 2 * weight_unit;
643 ++(*refmv_count);
644 }
645
646 ++coll_blk_count;
647 }
648 }
649
650 return coll_blk_count;
651 }
652 #endif
653
setup_ref_mv_list(const AV1_COMMON * cm,const MACROBLOCKD * xd,MV_REFERENCE_FRAME ref_frame,uint8_t * refmv_count,CANDIDATE_MV * ref_mv_stack,int_mv * mv_ref_list,int_mv * gm_mv_candidates,int block,int mi_row,int mi_col,int16_t * mode_context)654 static void setup_ref_mv_list(const AV1_COMMON *cm, const MACROBLOCKD *xd,
655 MV_REFERENCE_FRAME ref_frame,
656 uint8_t *refmv_count, CANDIDATE_MV *ref_mv_stack,
657 int_mv *mv_ref_list,
658 #if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
659 int_mv *gm_mv_candidates,
660 #endif // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
661 int block, int mi_row, int mi_col,
662 int16_t *mode_context) {
663 int idx, nearest_refmv_count = 0;
664 uint8_t newmv_count = 0;
665 CANDIDATE_MV tmp_mv;
666 int len, nr_len;
667
668 #if CONFIG_TMV
669 const int prev_frame_mvs_stride = ROUND_POWER_OF_TWO(cm->mi_cols, 1);
670 const int tmi_row = mi_row & 0xfffe;
671 const int tmi_col = mi_col & 0xfffe;
672 const MV_REF *const prev_frame_mvs_base =
673 cm->use_prev_frame_mvs
674 ? cm->prev_frame->mvs + (tmi_row >> 1) * prev_frame_mvs_stride +
675 (tmi_col >> 1)
676 : NULL;
677 #else
678 const int prev_frame_mvs_stride = cm->mi_cols;
679 #if CONFIG_MV_COMPRESS
680 const MV_REF *const prev_frame_mvs_base =
681 cm->use_prev_frame_mvs
682 ? cm->prev_frame->mvs +
683 (((mi_row >> 1) << 1) + 1) * prev_frame_mvs_stride +
684 ((mi_col >> 1) << 1) + 1
685 : NULL;
686 #else
687 const MV_REF *const prev_frame_mvs_base =
688 cm->use_prev_frame_mvs
689 ? cm->prev_frame->mvs + mi_row * prev_frame_mvs_stride + mi_col
690 : NULL;
691 #endif
692 #endif // CONFIG_TMV
693
694 const int bs = AOMMAX(xd->n8_w, xd->n8_h);
695 const int has_tr = has_top_right(cm, xd, mi_row, mi_col, bs);
696 MV_REFERENCE_FRAME rf[2];
697
698 const TileInfo *const tile = &xd->tile;
699 int max_row_offset = 0, max_col_offset = 0;
700 #if CONFIG_CB4X4
701 const int row_adj = (xd->n8_h < mi_size_high[BLOCK_8X8]) && (mi_row & 0x01);
702 const int col_adj = (xd->n8_w < mi_size_wide[BLOCK_8X8]) && (mi_col & 0x01);
703 #endif
704 int processed_rows = 0;
705 int processed_cols = 0;
706 int row_offset, col_offset;
707
708 av1_set_ref_frame(rf, ref_frame);
709 mode_context[ref_frame] = 0;
710 *refmv_count = 0;
711
712 // Find valid maximum row/col offset.
713 if (xd->up_available) {
714 #if CONFIG_CB4X4
715 max_row_offset = -(MVREF_ROWS << 1) + row_adj;
716 #else
717 max_row_offset = -MVREF_ROWS;
718 #endif
719 max_row_offset =
720 find_valid_row_offset(tile, mi_row, cm->mi_rows, cm, max_row_offset);
721 }
722
723 if (xd->left_available) {
724 #if CONFIG_CB4X4
725 max_col_offset = -(MVREF_COLS << 1) + col_adj;
726 #else
727 max_col_offset = -MVREF_COLS;
728 #endif
729 max_col_offset = find_valid_col_offset(tile, mi_col, max_col_offset);
730 }
731
732 // Scan the first above row mode info. row_offset = -1;
733 if (abs(max_row_offset) >= 1)
734 newmv_count +=
735 scan_row_mbmi(cm, xd, mi_col, block, rf, -1, ref_mv_stack, refmv_count,
736 #if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
737 gm_mv_candidates,
738 #endif // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
739 max_row_offset, &processed_rows);
740 // Scan the first left column mode info. col_offset = -1;
741 if (abs(max_col_offset) >= 1)
742 newmv_count +=
743 scan_col_mbmi(cm, xd, mi_row, block, rf, -1, ref_mv_stack, refmv_count,
744 #if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
745 gm_mv_candidates,
746 #endif // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
747 max_col_offset, &processed_cols);
748 // Check top-right boundary
749 if (has_tr)
750 newmv_count += scan_blk_mbmi(cm, xd, mi_row, mi_col, block, rf, -1,
751 xd->n8_w, ref_mv_stack,
752 #if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
753 gm_mv_candidates,
754 #endif // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
755 refmv_count);
756
757 nearest_refmv_count = *refmv_count;
758
759 for (idx = 0; idx < nearest_refmv_count; ++idx)
760 ref_mv_stack[idx].weight += REF_CAT_LEVEL;
761
762 #if CONFIG_MFMV
763 int blk_row, blk_col;
764 int coll_blk_count = 0;
765 int voffset = AOMMAX(mi_size_high[BLOCK_8X8], xd->n8_h);
766 int hoffset = AOMMAX(mi_size_wide[BLOCK_8X8], xd->n8_w);
767
768 int tpl_sample_pos[9][2] = {
769 { -2, hoffset }, { 0, hoffset }, { voffset, hoffset },
770 { voffset, 0 }, { voffset, -2 }, { voffset, -4 },
771 { -4, hoffset }, { voffset, 4 }, { 2, hoffset + 4 },
772 };
773 int i;
774
775 for (blk_row = 0; blk_row < xd->n8_h; blk_row += mi_size_high[BLOCK_8X8]) {
776 for (blk_col = 0; blk_col < xd->n8_w; blk_col += mi_size_wide[BLOCK_8X8]) {
777 // (TODO: yunqing) prev_frame_mvs_base is not used here, tpl_mvs is used.
778 // Can be modified the same way.
779 int is_available = add_tpl_ref_mv(
780 cm, prev_frame_mvs_base, xd, mi_row, mi_col, ref_frame, blk_row,
781 blk_col, refmv_count, ref_mv_stack, mode_context);
782 if (blk_row == 0 && blk_col == 0) coll_blk_count = is_available;
783 }
784 }
785
786 if (coll_blk_count == 0) mode_context[ref_frame] |= (1 << ZEROMV_OFFSET);
787
788 for (i = 0; i < 9; ++i) {
789 blk_row = tpl_sample_pos[i][0];
790 blk_col = tpl_sample_pos[i][1];
791
792 if (!check_sb_border(cm, mi_row, mi_col, blk_row, blk_col)) continue;
793 // (TODO: yunqing) prev_frame_mvs_base is not used here, tpl_mvs is used.
794 // Can be modified the same way.
795 coll_blk_count += add_tpl_ref_mv(cm, prev_frame_mvs_base, xd, mi_row,
796 mi_col, ref_frame, blk_row, blk_col,
797 refmv_count, ref_mv_stack, mode_context);
798 }
799 #else
800 #if CONFIG_TEMPMV_SIGNALING
801 if (cm->use_prev_frame_mvs && rf[1] == NONE_FRAME)
802 #else
803 if (prev_frame_mvs_base && cm->show_frame && cm->last_show_frame &&
804 rf[1] == NONE_FRAME)
805 #endif
806 {
807 int blk_row, blk_col;
808 int coll_blk_count = 0;
809 #if CONFIG_CB4X4
810 const int mi_step = (xd->n8_w == 1 || xd->n8_h == 1)
811 ? mi_size_wide[BLOCK_8X8]
812 : mi_size_wide[BLOCK_16X16];
813 #else
814 const int mi_step = mi_size_wide[BLOCK_16X16];
815 #endif
816
817 #if CONFIG_TPL_MV
818 // Modified sample positions to be consistent with frame_mvs
819 // spatial resolution.
820 int tpl_sample_pos[5][2] = { { -1, xd->n8_w },
821 { 0, xd->n8_w },
822 { xd->n8_h, xd->n8_w },
823 { xd->n8_h, 0 },
824 { xd->n8_h, -1 } };
825 int i;
826 #endif
827
828 for (blk_row = 0; blk_row < xd->n8_h; blk_row += mi_step) {
829 for (blk_col = 0; blk_col < xd->n8_w; blk_col += mi_step) {
830 #if CONFIG_TMV
831 int is_available =
832 add_col_ref_mv(cm, prev_frame_mvs_base, prev_frame_mvs_stride, xd,
833 tmi_row, tmi_col, ref_frame, blk_row, blk_col,
834 refmv_count, ref_mv_stack, mode_context);
835 #else
836 int is_available =
837 add_col_ref_mv(cm, prev_frame_mvs_base, prev_frame_mvs_stride, xd,
838 mi_row, mi_col, ref_frame, blk_row, blk_col,
839 refmv_count, ref_mv_stack, mode_context);
840 #endif // CONFIG_TMV
841 #if CONFIG_OPT_REF_MV
842 if (blk_row == 0 && blk_col == 0) coll_blk_count = is_available;
843 #else
844 coll_blk_count += is_available;
845 #endif
846 }
847 }
848
849 #if CONFIG_TPL_MV
850 for (i = 0; i < 5; ++i) {
851 blk_row = tpl_sample_pos[i][0];
852 blk_col = tpl_sample_pos[i][1];
853 #if CONFIG_TMV
854 coll_blk_count += add_col_ref_mv(
855 cm, prev_frame_mvs_base, prev_frame_mvs_stride, xd, tmi_row, tmi_col,
856 ref_frame, blk_row, blk_col, refmv_count, ref_mv_stack, mode_context);
857 #else
858 coll_blk_count += add_col_ref_mv(
859 cm, prev_frame_mvs_base, prev_frame_mvs_stride, xd, mi_row, mi_col,
860 ref_frame, blk_row, blk_col, refmv_count, ref_mv_stack, mode_context);
861 #endif // CONFIG_TMV
862 }
863 #endif
864
865 if (coll_blk_count == 0) mode_context[ref_frame] |= (1 << ZEROMV_OFFSET);
866 } else {
867 mode_context[ref_frame] |= (1 << ZEROMV_OFFSET);
868 }
869 #endif
870
871 // Scan the second outer area.
872 scan_blk_mbmi(cm, xd, mi_row, mi_col, block, rf, -1, -1, ref_mv_stack,
873 #if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
874 gm_mv_candidates,
875 #endif // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
876 refmv_count);
877 for (idx = 2; idx <= MVREF_ROWS; ++idx) {
878 #if CONFIG_CB4X4
879 row_offset = -(idx << 1) + 1 + row_adj;
880 col_offset = -(idx << 1) + 1 + col_adj;
881 #else
882 row_offset = -idx;
883 col_offset = -idx;
884 #endif
885
886 if (abs(row_offset) <= abs(max_row_offset) &&
887 abs(row_offset) > processed_rows)
888 scan_row_mbmi(cm, xd, mi_col, block, rf, row_offset, ref_mv_stack,
889 refmv_count,
890 #if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
891 gm_mv_candidates,
892 #endif // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
893 max_row_offset, &processed_rows);
894
895 if (abs(col_offset) <= abs(max_col_offset) &&
896 abs(col_offset) > processed_cols)
897 scan_col_mbmi(cm, xd, mi_row, block, rf, col_offset, ref_mv_stack,
898 refmv_count,
899 #if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
900 gm_mv_candidates,
901 #endif // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
902 max_col_offset, &processed_cols);
903 }
904
905 #if CONFIG_CB4X4
906 col_offset = -(MVREF_COLS << 1) + 1 + col_adj;
907 #else
908 col_offset = -MVREF_COLS;
909 #endif
910 if (abs(col_offset) <= abs(max_col_offset) &&
911 abs(col_offset) > processed_cols)
912 scan_col_mbmi(cm, xd, mi_row, block, rf, col_offset, ref_mv_stack,
913 refmv_count,
914 #if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
915 gm_mv_candidates,
916 #endif // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
917 max_col_offset, &processed_cols);
918
919 switch (nearest_refmv_count) {
920 case 0: mode_context[ref_frame] |= 0;
921 #if !CONFIG_OPT_REF_MV
922 if (*refmv_count >= 1) mode_context[ref_frame] |= 1;
923 if (*refmv_count == 1)
924 mode_context[ref_frame] |= (1 << REFMV_OFFSET);
925 else if (*refmv_count >= 2)
926 mode_context[ref_frame] |= (2 << REFMV_OFFSET);
927 #endif
928 break;
929 case 1: mode_context[ref_frame] |= (newmv_count > 0) ? 2 : 3;
930 #if CONFIG_OPT_REF_MV
931 mode_context[ref_frame] |= (3 << REFMV_OFFSET);
932 #else
933 if (*refmv_count == 1)
934 mode_context[ref_frame] |= (3 << REFMV_OFFSET);
935 else if (*refmv_count >= 2)
936 mode_context[ref_frame] |= (4 << REFMV_OFFSET);
937 #endif
938 break;
939
940 case 2:
941 default:
942 if (newmv_count >= 2)
943 mode_context[ref_frame] |= 4;
944 else if (newmv_count == 1)
945 mode_context[ref_frame] |= 5;
946 else
947 mode_context[ref_frame] |= 6;
948
949 mode_context[ref_frame] |= (5 << REFMV_OFFSET);
950 break;
951 }
952
953 // Rank the likelihood and assign nearest and near mvs.
954 len = nearest_refmv_count;
955 while (len > 0) {
956 nr_len = 0;
957 for (idx = 1; idx < len; ++idx) {
958 if (ref_mv_stack[idx - 1].weight < ref_mv_stack[idx].weight) {
959 tmp_mv = ref_mv_stack[idx - 1];
960 ref_mv_stack[idx - 1] = ref_mv_stack[idx];
961 ref_mv_stack[idx] = tmp_mv;
962 nr_len = idx;
963 }
964 }
965 len = nr_len;
966 }
967
968 len = *refmv_count;
969 while (len > nearest_refmv_count) {
970 nr_len = nearest_refmv_count;
971 for (idx = nearest_refmv_count + 1; idx < len; ++idx) {
972 if (ref_mv_stack[idx - 1].weight < ref_mv_stack[idx].weight) {
973 tmp_mv = ref_mv_stack[idx - 1];
974 ref_mv_stack[idx - 1] = ref_mv_stack[idx];
975 ref_mv_stack[idx] = tmp_mv;
976 nr_len = idx;
977 }
978 }
979 len = nr_len;
980 }
981
982 if (rf[1] > NONE_FRAME) {
983 for (idx = 0; idx < *refmv_count; ++idx) {
984 clamp_mv_ref(&ref_mv_stack[idx].this_mv.as_mv, xd->n8_w << MI_SIZE_LOG2,
985 xd->n8_h << MI_SIZE_LOG2, xd);
986 clamp_mv_ref(&ref_mv_stack[idx].comp_mv.as_mv, xd->n8_w << MI_SIZE_LOG2,
987 xd->n8_h << MI_SIZE_LOG2, xd);
988 }
989 } else {
990 for (idx = 0; idx < AOMMIN(MAX_MV_REF_CANDIDATES, *refmv_count); ++idx) {
991 mv_ref_list[idx].as_int = ref_mv_stack[idx].this_mv.as_int;
992 clamp_mv_ref(&mv_ref_list[idx].as_mv, xd->n8_w << MI_SIZE_LOG2,
993 xd->n8_h << MI_SIZE_LOG2, xd);
994 }
995 }
996 }
997
998 // This function searches the neighbourhood of a given MB/SB
999 // to try and find candidate reference vectors.
find_mv_refs_idx(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,find_mv_refs_sync sync,void * const data,int16_t * mode_context,int_mv zeromv)1000 static void find_mv_refs_idx(const AV1_COMMON *cm, const MACROBLOCKD *xd,
1001 MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame,
1002 int_mv *mv_ref_list, int block, int mi_row,
1003 int mi_col, find_mv_refs_sync sync,
1004 void *const data, int16_t *mode_context,
1005 int_mv zeromv) {
1006 const int *ref_sign_bias = cm->ref_frame_sign_bias;
1007 const int sb_mi_size = mi_size_wide[cm->sb_size];
1008 int i, refmv_count = 0;
1009 int different_ref_found = 0;
1010 int context_counter = 0;
1011
1012 #if CONFIG_TMV
1013 int tmi_row = mi_row & 0xfffe;
1014 int tmi_col = mi_col & 0xfffe;
1015 POSITION mi_pos = { 0, 0 };
1016 int inside = is_inside(&xd->tile, tmi_col, tmi_row, cm->mi_rows, cm, &mi_pos);
1017 const MV_REF *const prev_frame_mvs =
1018 cm->use_prev_frame_mvs && inside
1019 ? cm->prev_frame->mvs + (tmi_row >> 1) * ((cm->mi_cols + 1) >> 1) +
1020 (tmi_col >> 1)
1021 : NULL;
1022 #else
1023 #if CONFIG_MV_COMPRESS
1024 const TileInfo *const tile_ = &xd->tile;
1025 int mi_row_end = tile_->mi_row_end;
1026 int mi_col_end = tile_->mi_col_end;
1027 const MV_REF *const prev_frame_mvs =
1028 cm->use_prev_frame_mvs
1029 ? cm->prev_frame->mvs +
1030 AOMMIN(((mi_row >> 1) << 1) + 1 + (((xd->n8_h - 1) >> 1) << 1),
1031 mi_row_end - 1) *
1032 cm->mi_cols +
1033 AOMMIN(((mi_col >> 1) << 1) + 1 + (((xd->n8_w - 1) >> 1) << 1),
1034 mi_col_end - 1)
1035 : NULL;
1036 #else
1037 const MV_REF *const prev_frame_mvs =
1038 cm->use_prev_frame_mvs
1039 ? cm->prev_frame->mvs + mi_row * cm->mi_cols + mi_col
1040 : NULL;
1041 #endif
1042 #endif // CONFIG_TMV
1043
1044 #if CONFIG_INTRABC
1045 assert(IMPLIES(ref_frame == INTRA_FRAME, cm->use_prev_frame_mvs == 0));
1046 #endif
1047 const TileInfo *const tile = &xd->tile;
1048 const BLOCK_SIZE bsize = mi->mbmi.sb_type;
1049 const int bw = block_size_wide[AOMMAX(bsize, BLOCK_8X8)];
1050 const int bh = block_size_high[AOMMAX(bsize, BLOCK_8X8)];
1051 POSITION mv_ref_search[MVREF_NEIGHBOURS];
1052 const int num_8x8_blocks_wide = num_8x8_blocks_wide_lookup[bsize];
1053 const int num_8x8_blocks_high = num_8x8_blocks_high_lookup[bsize];
1054 mv_ref_search[0].row = num_8x8_blocks_high - 1;
1055 mv_ref_search[0].col = -1;
1056 mv_ref_search[1].row = -1;
1057 mv_ref_search[1].col = num_8x8_blocks_wide - 1;
1058 mv_ref_search[2].row = -1;
1059 mv_ref_search[2].col = (num_8x8_blocks_wide - 1) >> 1;
1060 mv_ref_search[3].row = (num_8x8_blocks_high - 1) >> 1;
1061 mv_ref_search[3].col = -1;
1062 mv_ref_search[4].row = -1;
1063 mv_ref_search[4].col = -1;
1064 #if CONFIG_EXT_PARTITION_TYPES
1065 if (num_8x8_blocks_wide == num_8x8_blocks_high) {
1066 mv_ref_search[5].row = -1;
1067 mv_ref_search[5].col = 0;
1068 mv_ref_search[6].row = 0;
1069 mv_ref_search[6].col = -1;
1070 } else {
1071 mv_ref_search[5].row = -1;
1072 mv_ref_search[5].col = num_8x8_blocks_wide;
1073 mv_ref_search[6].row = num_8x8_blocks_high;
1074 mv_ref_search[6].col = -1;
1075 }
1076 #else
1077 mv_ref_search[5].row = -1;
1078 mv_ref_search[5].col = num_8x8_blocks_wide;
1079 mv_ref_search[6].row = num_8x8_blocks_high;
1080 mv_ref_search[6].col = -1;
1081 #endif // CONFIG_EXT_PARTITION_TYPES
1082 mv_ref_search[7].row = -1;
1083 mv_ref_search[7].col = -3;
1084 mv_ref_search[8].row = num_8x8_blocks_high - 1;
1085 mv_ref_search[8].col = -3;
1086
1087 #if CONFIG_CB4X4
1088 for (i = 0; i < MVREF_NEIGHBOURS; ++i) {
1089 mv_ref_search[i].row *= 2;
1090 mv_ref_search[i].col *= 2;
1091 }
1092 #endif // CONFIG_CB4X4
1093
1094 // The nearest 2 blocks are treated differently
1095 // if the size < 8x8 we get the mv from the bmi substructure,
1096 // and we also need to keep a mode count.
1097 for (i = 0; i < 2; ++i) {
1098 const POSITION *const mv_ref = &mv_ref_search[i];
1099 if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm, mv_ref)) {
1100 const MODE_INFO *const candidate_mi =
1101 xd->mi[mv_ref->col + mv_ref->row * xd->mi_stride];
1102 const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
1103 // Keep counts for entropy encoding.
1104 context_counter += mode_2_counter[candidate->mode];
1105 different_ref_found = 1;
1106
1107 if (candidate->ref_frame[0] == ref_frame)
1108 ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 0, mv_ref->col, block),
1109 refmv_count, mv_ref_list, bw, bh, xd, Done);
1110 else if (candidate->ref_frame[1] == ref_frame)
1111 ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 1, mv_ref->col, block),
1112 refmv_count, mv_ref_list, bw, bh, xd, Done);
1113 }
1114 }
1115
1116 // Check the rest of the neighbors in much the same way
1117 // as before except we don't need to keep track of sub blocks or
1118 // mode counts.
1119 for (; i < MVREF_NEIGHBOURS; ++i) {
1120 const POSITION *const mv_ref = &mv_ref_search[i];
1121 if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm, mv_ref)) {
1122 const MB_MODE_INFO *const candidate =
1123 !xd->mi[mv_ref->col + mv_ref->row * xd->mi_stride]
1124 ? NULL
1125 : &xd->mi[mv_ref->col + mv_ref->row * xd->mi_stride]->mbmi;
1126 if (candidate == NULL) continue;
1127 if ((mi_row & (sb_mi_size - 1)) + mv_ref->row >= sb_mi_size ||
1128 (mi_col & (sb_mi_size - 1)) + mv_ref->col >= sb_mi_size)
1129 continue;
1130 different_ref_found = 1;
1131
1132 if (candidate->ref_frame[0] == ref_frame)
1133 ADD_MV_REF_LIST(candidate->mv[0], refmv_count, mv_ref_list, bw, bh, xd,
1134 Done);
1135 else if (candidate->ref_frame[1] == ref_frame)
1136 ADD_MV_REF_LIST(candidate->mv[1], refmv_count, mv_ref_list, bw, bh, xd,
1137 Done);
1138 }
1139 }
1140
1141 // TODO(hkuang): Remove this sync after fixing pthread_cond_broadcast
1142 // on windows platform. The sync here is unncessary if use_perv_frame_mvs
1143 // is 0. But after removing it, there will be hang in the unit test on windows
1144 // due to several threads waiting for a thread's signal.
1145 #if defined(_WIN32) && !HAVE_PTHREAD_H
1146 if (cm->frame_parallel_decode && sync != NULL) {
1147 sync(data, mi_row);
1148 }
1149 #endif
1150
1151 // Check the last frame's mode and mv info.
1152 if (cm->use_prev_frame_mvs) {
1153 // Synchronize here for frame parallel decode if sync function is provided.
1154 if (cm->frame_parallel_decode && sync != NULL) {
1155 sync(data, mi_row);
1156 }
1157
1158 if (prev_frame_mvs->ref_frame[0] == ref_frame) {
1159 ADD_MV_REF_LIST(prev_frame_mvs->mv[0], refmv_count, mv_ref_list, bw, bh,
1160 xd, Done);
1161 } else if (prev_frame_mvs->ref_frame[1] == ref_frame) {
1162 ADD_MV_REF_LIST(prev_frame_mvs->mv[1], refmv_count, mv_ref_list, bw, bh,
1163 xd, Done);
1164 }
1165 }
1166
1167 // Since we couldn't find 2 mvs from the same reference frame
1168 // go back through the neighbors and find motion vectors from
1169 // different reference frames.
1170 if (different_ref_found) {
1171 for (i = 0; i < MVREF_NEIGHBOURS; ++i) {
1172 const POSITION *mv_ref = &mv_ref_search[i];
1173 if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm, mv_ref)) {
1174 const MB_MODE_INFO *const candidate =
1175 !xd->mi[mv_ref->col + mv_ref->row * xd->mi_stride]
1176 ? NULL
1177 : &xd->mi[mv_ref->col + mv_ref->row * xd->mi_stride]->mbmi;
1178 if (candidate == NULL) continue;
1179 if ((mi_row & (sb_mi_size - 1)) + mv_ref->row >= sb_mi_size ||
1180 (mi_col & (sb_mi_size - 1)) + mv_ref->col >= sb_mi_size)
1181 continue;
1182
1183 // If the candidate is INTRA we don't want to consider its mv.
1184 IF_DIFF_REF_FRAME_ADD_MV(candidate, ref_frame, ref_sign_bias,
1185 refmv_count, mv_ref_list, bw, bh, xd, Done);
1186 }
1187 }
1188 }
1189
1190 // Since we still don't have a candidate we'll try the last frame.
1191 if (cm->use_prev_frame_mvs) {
1192 if (prev_frame_mvs->ref_frame[0] != ref_frame &&
1193 prev_frame_mvs->ref_frame[0] > INTRA_FRAME) {
1194 int_mv mv = prev_frame_mvs->mv[0];
1195 if (ref_sign_bias[prev_frame_mvs->ref_frame[0]] !=
1196 ref_sign_bias[ref_frame]) {
1197 mv.as_mv.row *= -1;
1198 mv.as_mv.col *= -1;
1199 }
1200 ADD_MV_REF_LIST(mv, refmv_count, mv_ref_list, bw, bh, xd, Done);
1201 }
1202
1203 if (prev_frame_mvs->ref_frame[1] > INTRA_FRAME &&
1204 prev_frame_mvs->ref_frame[1] != ref_frame) {
1205 int_mv mv = prev_frame_mvs->mv[1];
1206 if (ref_sign_bias[prev_frame_mvs->ref_frame[1]] !=
1207 ref_sign_bias[ref_frame]) {
1208 mv.as_mv.row *= -1;
1209 mv.as_mv.col *= -1;
1210 }
1211 ADD_MV_REF_LIST(mv, refmv_count, mv_ref_list, bw, bh, xd, Done);
1212 }
1213 }
1214
1215 Done:
1216 if (mode_context)
1217 mode_context[ref_frame] = counter_to_context[context_counter];
1218 for (i = refmv_count; i < MAX_MV_REF_CANDIDATES; ++i)
1219 mv_ref_list[i].as_int = zeromv.as_int;
1220 }
1221
1222 // This function keeps a mode count for a given MB/SB
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)1223 void av1_update_mv_context(const AV1_COMMON *cm, const MACROBLOCKD *xd,
1224 MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame,
1225 int_mv *mv_ref_list, int block, int mi_row,
1226 int mi_col, int16_t *mode_context) {
1227 int i, refmv_count = 0;
1228 int context_counter = 0;
1229 const int bw = block_size_wide[mi->mbmi.sb_type];
1230 const int bh = block_size_high[mi->mbmi.sb_type];
1231 const TileInfo *const tile = &xd->tile;
1232 POSITION mv_ref_search[2];
1233 const int num_8x8_blocks_wide = mi_size_wide[mi->mbmi.sb_type];
1234 const int num_8x8_blocks_high = mi_size_high[mi->mbmi.sb_type];
1235
1236 mv_ref_search[0].row = num_8x8_blocks_high - 1;
1237 mv_ref_search[0].col = -1;
1238 mv_ref_search[1].row = -1;
1239 mv_ref_search[1].col = num_8x8_blocks_wide - 1;
1240
1241 // Blank the reference vector list
1242 memset(mv_ref_list, 0, sizeof(*mv_ref_list) * MAX_MV_REF_CANDIDATES);
1243
1244 // The nearest 2 blocks are examined only.
1245 // If the size < 8x8, we get the mv from the bmi substructure;
1246 for (i = 0; i < 2; ++i) {
1247 const POSITION *const mv_ref = &mv_ref_search[i];
1248 if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm, mv_ref)) {
1249 const MODE_INFO *const candidate_mi =
1250 xd->mi[mv_ref->col + mv_ref->row * xd->mi_stride];
1251 const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
1252
1253 // Keep counts for entropy encoding.
1254 context_counter += mode_2_counter[candidate->mode];
1255
1256 if (candidate->ref_frame[0] == ref_frame) {
1257 ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 0, mv_ref->col, block),
1258 refmv_count, mv_ref_list, bw, bh, xd, Done);
1259 } else if (candidate->ref_frame[1] == ref_frame) {
1260 ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 1, mv_ref->col, block),
1261 refmv_count, mv_ref_list, bw, bh, xd, Done);
1262 }
1263 }
1264 }
1265
1266 Done:
1267
1268 if (mode_context)
1269 mode_context[ref_frame] = counter_to_context[context_counter];
1270 }
1271
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,int16_t * compound_mode_context,int_mv * mv_ref_list,int mi_row,int mi_col,find_mv_refs_sync sync,void * const data,int16_t * mode_context)1272 void av1_find_mv_refs(const AV1_COMMON *cm, const MACROBLOCKD *xd,
1273 MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame,
1274 uint8_t *ref_mv_count, CANDIDATE_MV *ref_mv_stack,
1275 int16_t *compound_mode_context, int_mv *mv_ref_list,
1276 int mi_row, int mi_col, find_mv_refs_sync sync,
1277 void *const data, int16_t *mode_context) {
1278 int_mv zeromv[2];
1279 #if CONFIG_GLOBAL_MOTION
1280 BLOCK_SIZE bsize = mi->mbmi.sb_type;
1281 #endif // CONFIG_GLOBAL_MOTION
1282 int idx, all_zero = 1;
1283 #if CONFIG_GLOBAL_MOTION
1284 MV_REFERENCE_FRAME rf[2];
1285 #endif // CONFIG_GLOBAL_MOTION
1286
1287 av1_update_mv_context(cm, xd, mi, ref_frame, mv_ref_list, -1, mi_row, mi_col,
1288 compound_mode_context);
1289
1290 #if CONFIG_GLOBAL_MOTION
1291 if (!CONFIG_INTRABC || ref_frame != INTRA_FRAME) {
1292 av1_set_ref_frame(rf, ref_frame);
1293 zeromv[0].as_int = gm_get_motion_vector(&cm->global_motion[rf[0]],
1294 cm->allow_high_precision_mv, bsize,
1295 mi_col, mi_row, 0
1296 #if CONFIG_AMVR
1297 ,
1298 cm->cur_frame_mv_precision_level
1299 #endif
1300 )
1301 .as_int;
1302 zeromv[1].as_int =
1303 (rf[1] != NONE_FRAME)
1304 ? gm_get_motion_vector(&cm->global_motion[rf[1]],
1305 cm->allow_high_precision_mv, bsize, mi_col,
1306 mi_row, 0
1307 #if CONFIG_AMVR
1308 ,
1309 cm->cur_frame_mv_precision_level
1310 #endif
1311 )
1312 .as_int
1313 : 0;
1314 } else {
1315 zeromv[0].as_int = zeromv[1].as_int = 0;
1316 }
1317 #else
1318 zeromv[0].as_int = zeromv[1].as_int = 0;
1319 #endif // CONFIG_GLOBAL_MOTION
1320
1321 if (ref_frame <= ALTREF_FRAME)
1322 find_mv_refs_idx(cm, xd, mi, ref_frame, mv_ref_list, -1, mi_row, mi_col,
1323 sync, data, mode_context, zeromv[0]);
1324
1325 setup_ref_mv_list(cm, xd, ref_frame, ref_mv_count, ref_mv_stack, mv_ref_list,
1326 #if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
1327 zeromv,
1328 #endif // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
1329 -1, mi_row, mi_col, mode_context);
1330 /* Note: If global motion is enabled, then we want to set the ALL_ZERO flag
1331 iff all of the MVs we could generate with NEARMV/NEARESTMV are equivalent
1332 to the global motion vector.
1333 Note: For the following to work properly, the encoder can't throw away
1334 any global motion models after calling this function, even if they are
1335 unused. Instead we rely on the recode loop: If any non-IDENTITY model
1336 is unused, the whole frame will be re-encoded without it.
1337 The problem is that, otherwise, we can end up in the following situation:
1338 * Encoder has a global motion model with nonzero translational part,
1339 and all candidate MVs are zero. So the ALL_ZERO flag is unset.
1340 * Encoder throws away global motion because it is never used.
1341 * Decoder sees that there is no global motion and all candidate MVs are
1342 zero, so sets the ALL_ZERO flag.
1343 * This leads to an encode/decode mismatch.
1344 */
1345 for (idx = 0; idx < AOMMIN(3, *ref_mv_count); ++idx) {
1346 if (ref_mv_stack[idx].this_mv.as_int != zeromv[0].as_int) all_zero = 0;
1347 if (ref_frame > ALTREF_FRAME)
1348 if (ref_mv_stack[idx].comp_mv.as_int != zeromv[1].as_int) all_zero = 0;
1349 }
1350 if (*ref_mv_count < 2 && ref_frame <= ALTREF_FRAME) {
1351 for (idx = 0; idx < MAX_MV_REF_CANDIDATES; ++idx)
1352 if (mv_ref_list[idx].as_int != zeromv[0].as_int) all_zero = 0;
1353 }
1354
1355 #if !CONFIG_OPT_REF_MV
1356 if (all_zero) mode_context[ref_frame] |= (1 << ALL_ZERO_FLAG_OFFSET);
1357 #else
1358 (void)all_zero;
1359 #endif
1360 }
1361
av1_find_best_ref_mvs(int allow_hp,int_mv * mvlist,int_mv * nearest_mv,int_mv * near_mv,int is_integer)1362 void av1_find_best_ref_mvs(int allow_hp, int_mv *mvlist, int_mv *nearest_mv,
1363 int_mv *near_mv
1364 #if CONFIG_AMVR
1365 ,
1366 int is_integer
1367 #endif
1368 ) {
1369 int i;
1370 // Make sure all the candidates are properly clamped etc
1371 for (i = 0; i < MAX_MV_REF_CANDIDATES; ++i) {
1372 #if CONFIG_AMVR
1373 lower_mv_precision(&mvlist[i].as_mv, allow_hp, is_integer);
1374 #else
1375 lower_mv_precision(&mvlist[i].as_mv, allow_hp);
1376 #endif
1377 }
1378 *nearest_mv = mvlist[0];
1379 *near_mv = mvlist[1];
1380 }
1381
av1_append_sub8x8_mvs_for_idx(const AV1_COMMON * cm,MACROBLOCKD * xd,int block,int ref,int mi_row,int mi_col,CANDIDATE_MV * ref_mv_stack,uint8_t * ref_mv_count,int_mv * mv_list,int_mv * nearest_mv,int_mv * near_mv)1382 void av1_append_sub8x8_mvs_for_idx(const AV1_COMMON *cm, MACROBLOCKD *xd,
1383 int block, int ref, int mi_row, int mi_col,
1384 CANDIDATE_MV *ref_mv_stack,
1385 uint8_t *ref_mv_count, int_mv *mv_list,
1386 int_mv *nearest_mv, int_mv *near_mv) {
1387 MODE_INFO *const mi = xd->mi[0];
1388 b_mode_info *bmi = mi->bmi;
1389 int n;
1390 int_mv zeromv;
1391 CANDIDATE_MV tmp_mv;
1392 uint8_t idx;
1393 uint8_t above_count = 0, left_count = 0;
1394 MV_REFERENCE_FRAME rf[2] = { mi->mbmi.ref_frame[ref], NONE_FRAME };
1395 *ref_mv_count = 0;
1396
1397 assert(MAX_MV_REF_CANDIDATES == 2);
1398
1399 #if CONFIG_GLOBAL_MOTION
1400 zeromv.as_int = gm_get_motion_vector(&cm->global_motion[rf[0]],
1401 cm->allow_high_precision_mv,
1402 mi->mbmi.sb_type, mi_col, mi_row, block
1403 #if CONFIG_AMVR
1404 ,
1405 cm->cur_frame_mv_precision_level
1406 #endif
1407 )
1408 .as_int;
1409 #else
1410 zeromv.as_int = 0;
1411 #endif
1412 find_mv_refs_idx(cm, xd, mi, mi->mbmi.ref_frame[ref], mv_list, block, mi_row,
1413 mi_col, NULL, NULL, NULL, zeromv);
1414
1415 scan_blk_mbmi(cm, xd, mi_row, mi_col, block, rf, -1, 0, ref_mv_stack,
1416 #if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
1417 &zeromv,
1418 #endif // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
1419 ref_mv_count);
1420 above_count = *ref_mv_count;
1421
1422 scan_blk_mbmi(cm, xd, mi_row, mi_col, block, rf, 0, -1, ref_mv_stack,
1423 #if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
1424 &zeromv,
1425 #endif // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
1426 ref_mv_count);
1427 left_count = *ref_mv_count - above_count;
1428
1429 if (above_count > 1 && left_count > 0) {
1430 tmp_mv = ref_mv_stack[1];
1431 ref_mv_stack[1] = ref_mv_stack[above_count];
1432 ref_mv_stack[above_count] = tmp_mv;
1433 }
1434
1435 for (idx = 0; idx < *ref_mv_count; ++idx)
1436 clamp_mv_ref(&ref_mv_stack[idx].this_mv.as_mv, xd->n8_w << MI_SIZE_LOG2,
1437 xd->n8_h << MI_SIZE_LOG2, xd);
1438
1439 for (idx = 0; idx < AOMMIN(MAX_MV_REF_CANDIDATES, *ref_mv_count); ++idx)
1440 mv_list[idx].as_int = ref_mv_stack[idx].this_mv.as_int;
1441
1442 near_mv->as_int = 0;
1443 switch (block) {
1444 case 0:
1445 nearest_mv->as_int = mv_list[0].as_int;
1446 near_mv->as_int = mv_list[1].as_int;
1447 break;
1448 case 1:
1449 case 2:
1450 nearest_mv->as_int = bmi[0].as_mv[ref].as_int;
1451 for (n = 0; n < MAX_MV_REF_CANDIDATES; ++n)
1452 if (nearest_mv->as_int != mv_list[n].as_int) {
1453 near_mv->as_int = mv_list[n].as_int;
1454 break;
1455 }
1456 break;
1457 case 3: {
1458 int_mv candidates[2 + MAX_MV_REF_CANDIDATES];
1459 candidates[0] = bmi[1].as_mv[ref];
1460 candidates[1] = bmi[0].as_mv[ref];
1461 candidates[2] = mv_list[0];
1462 candidates[3] = mv_list[1];
1463
1464 nearest_mv->as_int = bmi[2].as_mv[ref].as_int;
1465 for (n = 0; n < 2 + MAX_MV_REF_CANDIDATES; ++n)
1466 if (nearest_mv->as_int != candidates[n].as_int) {
1467 near_mv->as_int = candidates[n].as_int;
1468 break;
1469 }
1470 break;
1471 }
1472 default: assert(0 && "Invalid block index.");
1473 }
1474 }
1475
1476 #if CONFIG_FRAME_MARKER
av1_setup_frame_buf_refs(AV1_COMMON * cm)1477 void av1_setup_frame_buf_refs(AV1_COMMON *cm) {
1478 cm->cur_frame->cur_frame_offset = cm->frame_offset;
1479 int alt_buf_idx = cm->frame_refs[ALTREF_FRAME - LAST_FRAME].idx;
1480 int lst_buf_idx = cm->frame_refs[LAST_FRAME - LAST_FRAME].idx;
1481 int gld_buf_idx = cm->frame_refs[GOLDEN_FRAME - LAST_FRAME].idx;
1482
1483 #if CONFIG_EXT_REFS
1484 int lst2_buf_idx = cm->frame_refs[LAST2_FRAME - LAST_FRAME].idx;
1485 int lst3_buf_idx = cm->frame_refs[LAST3_FRAME - LAST_FRAME].idx;
1486 int bwd_buf_idx = cm->frame_refs[BWDREF_FRAME - LAST_FRAME].idx;
1487 int alt2_buf_idx = cm->frame_refs[ALTREF2_FRAME - LAST_FRAME].idx;
1488 #endif
1489
1490 if (alt_buf_idx >= 0)
1491 cm->cur_frame->alt_frame_offset =
1492 cm->buffer_pool->frame_bufs[alt_buf_idx].cur_frame_offset;
1493
1494 if (lst_buf_idx >= 0)
1495 cm->cur_frame->lst_frame_offset =
1496 cm->buffer_pool->frame_bufs[lst_buf_idx].cur_frame_offset;
1497
1498 if (gld_buf_idx >= 0)
1499 cm->cur_frame->gld_frame_offset =
1500 cm->buffer_pool->frame_bufs[gld_buf_idx].cur_frame_offset;
1501
1502 #if CONFIG_EXT_REFS
1503 if (lst2_buf_idx >= 0)
1504 cm->cur_frame->lst2_frame_offset =
1505 cm->buffer_pool->frame_bufs[lst2_buf_idx].cur_frame_offset;
1506
1507 if (lst3_buf_idx >= 0)
1508 cm->cur_frame->lst3_frame_offset =
1509 cm->buffer_pool->frame_bufs[lst3_buf_idx].cur_frame_offset;
1510
1511 if (bwd_buf_idx >= 0)
1512 cm->cur_frame->bwd_frame_offset =
1513 cm->buffer_pool->frame_bufs[bwd_buf_idx].cur_frame_offset;
1514
1515 if (alt2_buf_idx >= 0)
1516 cm->cur_frame->alt2_frame_offset =
1517 cm->buffer_pool->frame_bufs[alt2_buf_idx].cur_frame_offset;
1518 #endif
1519 }
1520
1521 #if CONFIG_FRAME_SIGN_BIAS
av1_setup_frame_sign_bias(AV1_COMMON * cm)1522 void av1_setup_frame_sign_bias(AV1_COMMON *cm) {
1523 MV_REFERENCE_FRAME ref_frame;
1524 for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
1525 const int buf_idx = cm->frame_refs[ref_frame - LAST_FRAME].idx;
1526 if (buf_idx != INVALID_IDX) {
1527 const int ref_frame_offset =
1528 cm->buffer_pool->frame_bufs[buf_idx].cur_frame_offset;
1529 cm->ref_frame_sign_bias[ref_frame] =
1530 (ref_frame_offset <= (int)cm->frame_offset) ? 0 : 1;
1531 } else {
1532 cm->ref_frame_sign_bias[ref_frame] = 0;
1533 }
1534 }
1535 }
1536 #endif // CONFIG_FRAME_SIGN_BIAS
1537 #endif // CONFIG_FRAME_MARKER
1538
1539 #if CONFIG_MFMV
1540 // Although we assign 32 bit integers, all the values are strictly under 14
1541 // bits.
1542 static int div_mult[32] = {
1543 0, 16384, 8192, 5461, 4096, 3276, 2730, 2340, 2048, 1820, 1638,
1544 1489, 1365, 1260, 1170, 1092, 1024, 963, 910, 862, 819, 780,
1545 744, 712, 682, 655, 630, 606, 585, 564, 546, 528,
1546 };
1547
1548 // TODO(jingning): Consider the use of lookup table for (num / den)
1549 // altogether.
get_mv_projection(MV * output,MV ref,int num,int den)1550 static void get_mv_projection(MV *output, MV ref, int num, int den) {
1551 output->row =
1552 (int16_t)(ROUND_POWER_OF_TWO(ref.row * num * div_mult[den], 14));
1553 output->col =
1554 (int16_t)(ROUND_POWER_OF_TWO(ref.col * num * div_mult[den], 14));
1555 }
1556
1557 #define MAX_OFFSET_WIDTH 64
1558 #define MAX_OFFSET_HEIGHT 32
1559
get_block_position(AV1_COMMON * cm,int * mi_r,int * mi_c,int blk_row,int blk_col,MV mv,int sign_bias)1560 static int get_block_position(AV1_COMMON *cm, int *mi_r, int *mi_c, int blk_row,
1561 int blk_col, MV mv, int sign_bias) {
1562 if ((abs(mv.row) >> 3) > MAX_OFFSET_HEIGHT ||
1563 (abs(mv.col) >> 3) > MAX_OFFSET_WIDTH)
1564 return 0;
1565
1566 int row = (sign_bias == 1) ? blk_row - (mv.row >> (3 + MI_SIZE_LOG2))
1567 : blk_row + (mv.row >> (3 + MI_SIZE_LOG2));
1568 int col = (sign_bias == 1) ? blk_col - (mv.col >> (3 + MI_SIZE_LOG2))
1569 : blk_col + (mv.col >> (3 + MI_SIZE_LOG2));
1570
1571 if (row < 0 || row >= cm->mi_rows || col < 0 || col >= cm->mi_cols) return 0;
1572
1573 *mi_r = row;
1574 *mi_c = col;
1575
1576 return 1;
1577 }
1578
mv_sign_reverse(int_mv ref)1579 static uint32_t mv_sign_reverse(int_mv ref) {
1580 int_mv this_mv;
1581 this_mv.as_mv.row = -ref.as_mv.row;
1582 this_mv.as_mv.col = -ref.as_mv.col;
1583
1584 return this_mv.as_int;
1585 }
1586
av1_setup_motion_field(AV1_COMMON * cm)1587 void av1_setup_motion_field(AV1_COMMON *cm) {
1588 int cur_frame_index = cm->cur_frame->cur_frame_offset;
1589 int lst_frame_index = 0, alt_frame_index = 0, gld_frame_index = 0;
1590 #if CONFIG_EXT_REFS
1591 int lst2_frame_index = 0, lst3_frame_index = 0;
1592 int bwd_frame_index = 0, alt2_frame_index = 0;
1593 #endif
1594 TPL_MV_REF *tpl_mvs_base = cm->cur_frame->tpl_mvs;
1595
1596 for (int ref_frame = 0; ref_frame < INTER_REFS_PER_FRAME; ++ref_frame) {
1597 int size = (cm->mi_rows + 16) * cm->mi_stride;
1598 for (int idx = 0; idx < size; ++idx) {
1599 for (int i = 0; i < MFMV_STACK_SIZE; ++i)
1600 tpl_mvs_base[idx].mfmv[ref_frame][i].as_int = INVALID_MV;
1601 }
1602 }
1603
1604 int alt_buf_idx = cm->frame_refs[ALTREF_FRAME - LAST_FRAME].idx;
1605 int lst_buf_idx = cm->frame_refs[LAST_FRAME - LAST_FRAME].idx;
1606 int gld_buf_idx = cm->frame_refs[GOLDEN_FRAME - LAST_FRAME].idx;
1607 #if CONFIG_EXT_REFS
1608 int lst2_buf_idx = cm->frame_refs[LAST2_FRAME - LAST_FRAME].idx;
1609 int lst3_buf_idx = cm->frame_refs[LAST3_FRAME - LAST_FRAME].idx;
1610 int bwd_buf_idx = cm->frame_refs[BWDREF_FRAME - LAST_FRAME].idx;
1611 int alt2_buf_idx = cm->frame_refs[ALTREF2_FRAME - LAST_FRAME].idx;
1612 #endif
1613
1614 if (alt_buf_idx >= 0)
1615 alt_frame_index = cm->buffer_pool->frame_bufs[alt_buf_idx].cur_frame_offset;
1616
1617 if (lst_buf_idx >= 0)
1618 lst_frame_index = cm->buffer_pool->frame_bufs[lst_buf_idx].cur_frame_offset;
1619
1620 if (gld_buf_idx >= 0)
1621 gld_frame_index = cm->buffer_pool->frame_bufs[gld_buf_idx].cur_frame_offset;
1622
1623 #if CONFIG_EXT_REFS
1624 if (lst2_buf_idx >= 0)
1625 lst2_frame_index =
1626 cm->buffer_pool->frame_bufs[lst2_buf_idx].cur_frame_offset;
1627
1628 if (lst3_buf_idx >= 0)
1629 lst3_frame_index =
1630 cm->buffer_pool->frame_bufs[lst3_buf_idx].cur_frame_offset;
1631
1632 if (bwd_buf_idx >= 0)
1633 bwd_frame_index = cm->buffer_pool->frame_bufs[bwd_buf_idx].cur_frame_offset;
1634
1635 if (alt2_buf_idx >= 0)
1636 alt2_frame_index =
1637 cm->buffer_pool->frame_bufs[alt2_buf_idx].cur_frame_offset;
1638 #endif
1639
1640 if (alt_frame_index < cur_frame_index) return;
1641
1642 // ======================
1643 // Process last frame
1644 // ======================
1645 if (lst_buf_idx >= 0) {
1646 MV_REF *mv_ref_base = cm->buffer_pool->frame_bufs[lst_buf_idx].mvs;
1647 const int lst_frame_idx =
1648 cm->buffer_pool->frame_bufs[lst_buf_idx].lst_frame_offset;
1649 const int alt_frame_idx =
1650 cm->buffer_pool->frame_bufs[lst_buf_idx].alt_frame_offset;
1651 const int gld_frame_idx =
1652 cm->buffer_pool->frame_bufs[lst_buf_idx].gld_frame_offset;
1653 #if CONFIG_EXT_REFS
1654 const int lst2_frame_idx =
1655 cm->buffer_pool->frame_bufs[lst_buf_idx].lst2_frame_offset;
1656 const int lst3_frame_idx =
1657 cm->buffer_pool->frame_bufs[lst_buf_idx].lst3_frame_offset;
1658 const int bwd_frame_idx =
1659 cm->buffer_pool->frame_bufs[lst_buf_idx].bwd_frame_offset;
1660 const int alt2_frame_idx =
1661 cm->buffer_pool->frame_bufs[lst_buf_idx].alt2_frame_offset;
1662 #endif
1663
1664 int alt_offset = AOMMAX(1, alt_frame_idx - lst_frame_index);
1665 int lst_offset = AOMMAX(1, lst_frame_index - lst_frame_idx);
1666 int gld_offset = AOMMAX(1, lst_frame_index - gld_frame_idx);
1667 int cur_to_lst = cur_frame_index - lst_frame_index;
1668 int cur_to_alt = alt_frame_index - cur_frame_index;
1669 int cur_to_gld = cur_frame_index - gld_frame_index;
1670
1671 #if CONFIG_EXT_REFS
1672 int bwd_offset = AOMMAX(1, bwd_frame_idx - lst_frame_index);
1673 int alt2_offset = AOMMAX(1, alt2_frame_idx - lst_frame_index);
1674 int lst2_offset = AOMMAX(1, lst_frame_index - lst2_frame_idx);
1675 int lst3_offset = AOMMAX(1, lst_frame_index - lst3_frame_idx);
1676 int cur_to_lst2 = cur_frame_index - lst2_frame_index;
1677 int cur_to_lst3 = cur_frame_index - lst3_frame_index;
1678 int cur_to_bwd = bwd_frame_index - cur_frame_index;
1679 int cur_to_alt2 = alt2_frame_index - cur_frame_index;
1680 #endif
1681
1682 const int is_lst_overlay = (alt_frame_idx == gld_frame_index);
1683 // clang-format off
1684 const int ref_frame_offset_buffer[TOTAL_REFS_PER_FRAME] = {
1685 #if CONFIG_EXT_REFS
1686 0, lst_offset, lst2_offset, lst3_offset, gld_offset,
1687 bwd_offset, alt2_offset, alt_offset
1688 #else
1689 0, lst_offset, gld_offset, alt_offset
1690 #endif
1691 };
1692 // clang-format on
1693
1694 for (int blk_row = 0; blk_row < cm->mi_rows && !is_lst_overlay; ++blk_row) {
1695 for (int blk_col = 0; blk_col < cm->mi_cols; ++blk_col) {
1696 MV_REF *mv_ref = &mv_ref_base[blk_row * cm->mi_cols + blk_col];
1697 MV fwd_mv = mv_ref->mv[0].as_mv;
1698 MV_REFERENCE_FRAME ref_frame[2] = { mv_ref->ref_frame[0],
1699 mv_ref->ref_frame[1] };
1700
1701 // Derive motion vectors toward last reference frame.
1702 if (ref_frame[0] <= GOLDEN_FRAME && ref_frame[0] > INTRA_FRAME) {
1703 int_mv this_mv;
1704 int mi_r, mi_c;
1705
1706 const int ref_frame_offset = ref_frame_offset_buffer[ref_frame[0]];
1707
1708 get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_lst,
1709 ref_frame_offset);
1710 int pos_valid = get_block_position(cm, &mi_r, &mi_c, blk_row, blk_col,
1711 this_mv.as_mv, 1);
1712
1713 if (pos_valid) {
1714 int mi_offset = mi_r * cm->mi_stride + mi_c;
1715 tpl_mvs_base[mi_offset].mfmv[FWD_RF_OFFSET(LAST_FRAME)][0].as_int =
1716 this_mv.as_int;
1717
1718 #if CONFIG_EXT_REFS
1719 get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_lst2,
1720 ref_frame_offset);
1721 tpl_mvs_base[mi_offset].mfmv[FWD_RF_OFFSET(LAST2_FRAME)][0].as_int =
1722 this_mv.as_int;
1723
1724 get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_lst3,
1725 ref_frame_offset);
1726 tpl_mvs_base[mi_offset].mfmv[FWD_RF_OFFSET(LAST3_FRAME)][0].as_int =
1727 this_mv.as_int;
1728 #endif
1729 get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_gld,
1730 ref_frame_offset);
1731 tpl_mvs_base[mi_offset].mfmv[FWD_RF_OFFSET(GOLDEN_FRAME)]
1732 [0].as_int = this_mv.as_int;
1733 }
1734 }
1735
1736 for (int idx = 0; idx < 2; ++idx) {
1737 if (ref_frame[idx] <= GOLDEN_FRAME) continue;
1738
1739 int_mv this_mv;
1740 int mi_r, mi_c;
1741 fwd_mv = mv_ref->mv[idx].as_mv;
1742
1743 const int ref_frame_offset = ref_frame_offset_buffer[ref_frame[idx]];
1744
1745 get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_lst,
1746 ref_frame_offset);
1747 int pos_valid = get_block_position(cm, &mi_r, &mi_c, blk_row, blk_col,
1748 this_mv.as_mv, 0);
1749
1750 if (pos_valid) {
1751 int mi_offset = mi_r * cm->mi_stride + mi_c;
1752 get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_alt,
1753 ref_frame_offset);
1754 tpl_mvs_base[mi_offset].mfmv[FWD_RF_OFFSET(ALTREF_FRAME)]
1755 [0].as_int = this_mv.as_int;
1756
1757 #if CONFIG_EXT_REFS
1758 get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_bwd,
1759 ref_frame_offset);
1760 tpl_mvs_base[mi_offset].mfmv[FWD_RF_OFFSET(BWDREF_FRAME)]
1761 [0].as_int = this_mv.as_int;
1762 get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_alt2,
1763 ref_frame_offset);
1764 tpl_mvs_base[mi_offset].mfmv[FWD_RF_OFFSET(ALTREF2_FRAME)]
1765 [0].as_int = this_mv.as_int;
1766 #endif
1767 }
1768 }
1769 }
1770 }
1771 }
1772
1773 // =======================
1774 // Process ARF frame
1775 // =======================
1776 if (alt_buf_idx >= 0) {
1777 MV_REF *mv_ref_base = cm->buffer_pool->frame_bufs[alt_buf_idx].mvs;
1778 const int lst_frame_idx =
1779 cm->buffer_pool->frame_bufs[alt_buf_idx].lst_frame_offset;
1780 const int gld_frame_idx =
1781 cm->buffer_pool->frame_bufs[alt_buf_idx].gld_frame_offset;
1782 #if CONFIG_EXT_REFS
1783 const int lst2_frame_idx =
1784 cm->buffer_pool->frame_bufs[alt_buf_idx].lst2_frame_offset;
1785 const int lst3_frame_idx =
1786 cm->buffer_pool->frame_bufs[alt_buf_idx].lst3_frame_offset;
1787 const int bwd_frame_idx =
1788 cm->buffer_pool->frame_bufs[alt_buf_idx].bwd_frame_offset;
1789 const int alt2_frame_idx =
1790 cm->buffer_pool->frame_bufs[alt_buf_idx].alt2_frame_offset;
1791 #endif
1792
1793 int lst_offset = AOMMAX(1, alt_frame_index - lst_frame_idx);
1794 int gld_offset = AOMMAX(1, alt_frame_index - gld_frame_idx);
1795 int cur_to_alt = alt_frame_index - cur_frame_index;
1796 int cur_to_lst = cur_frame_index - lst_frame_index;
1797 int cur_to_gld = cur_frame_index - gld_frame_index;
1798 #if CONFIG_EXT_REFS
1799 int bwd_offset = AOMMAX(1, alt_frame_index - bwd_frame_idx);
1800 int alt2_offset = AOMMAX(1, alt_frame_index - alt2_frame_idx);
1801 int lst2_offset = AOMMAX(1, alt_frame_index - lst2_frame_idx);
1802 int lst3_offset = AOMMAX(1, alt_frame_index - lst3_frame_idx);
1803 int cur_to_lst2 = cur_frame_index - lst2_frame_index;
1804 int cur_to_lst3 = cur_frame_index - lst3_frame_index;
1805 int cur_to_bwd = bwd_frame_index - cur_frame_index;
1806 int cur_to_alt2 = alt2_frame_index - cur_frame_index;
1807 #endif
1808 const int ref_stamp = FWD_RF_OFFSET(ALTREF_FRAME);
1809 // clang-format off
1810 const int ref_frame_offset_buffer[TOTAL_REFS_PER_FRAME] = {
1811 #if CONFIG_EXT_REFS
1812 0, lst_offset, lst2_offset, lst3_offset, gld_offset,
1813 bwd_offset, alt2_offset, 0,
1814 #else
1815 0, lst_offset, gld_offset, 0,
1816 #endif
1817 };
1818 // clang-format on
1819
1820 for (int blk_row = 0; blk_row < cm->mi_rows; ++blk_row) {
1821 for (int blk_col = 0; blk_col < cm->mi_cols; ++blk_col) {
1822 MV_REF *mv_ref = &mv_ref_base[blk_row * cm->mi_cols + blk_col];
1823 MV fwd_mv = mv_ref->mv[0].as_mv;
1824 MV_REFERENCE_FRAME ref_frame[2] = { mv_ref->ref_frame[0],
1825 mv_ref->ref_frame[1] };
1826
1827 const int ref_frame_offset = ref_frame_offset_buffer[ref_frame[0]];
1828
1829 if (ref_frame[0] <= GOLDEN_FRAME && ref_frame[0] > INTRA_FRAME) {
1830 int_mv this_mv;
1831 int mi_r, mi_c;
1832
1833 get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_alt,
1834 ref_frame_offset);
1835 int pos_valid = get_block_position(cm, &mi_r, &mi_c, blk_row, blk_col,
1836 this_mv.as_mv, 0);
1837
1838 if (pos_valid) {
1839 int mi_offset = mi_r * cm->mi_stride + mi_c;
1840 tpl_mvs_base[mi_offset]
1841 .mfmv[FWD_RF_OFFSET(ALTREF_FRAME)][ref_stamp]
1842 .as_int = mv_sign_reverse(this_mv);
1843
1844 get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_lst,
1845 ref_frame_offset);
1846 tpl_mvs_base[mi_offset]
1847 .mfmv[FWD_RF_OFFSET(LAST_FRAME)][ref_stamp]
1848 .as_int = this_mv.as_int;
1849
1850 #if CONFIG_EXT_REFS
1851 get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_bwd,
1852 ref_frame_offset);
1853 tpl_mvs_base[mi_offset]
1854 .mfmv[FWD_RF_OFFSET(BWDREF_FRAME)][ref_stamp]
1855 .as_int = mv_sign_reverse(this_mv);
1856
1857 get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_alt2,
1858 ref_frame_offset);
1859 tpl_mvs_base[mi_offset]
1860 .mfmv[FWD_RF_OFFSET(ALTREF2_FRAME)][ref_stamp]
1861 .as_int = mv_sign_reverse(this_mv);
1862
1863 if (ref_frame[0] >= LAST2_FRAME) {
1864 get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_lst2,
1865 ref_frame_offset);
1866 tpl_mvs_base[mi_offset]
1867 .mfmv[FWD_RF_OFFSET(LAST2_FRAME)][ref_stamp]
1868 .as_int = this_mv.as_int;
1869 }
1870
1871 if (ref_frame[0] >= LAST3_FRAME) {
1872 get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_lst3,
1873 ref_frame_offset);
1874 tpl_mvs_base[mi_offset]
1875 .mfmv[FWD_RF_OFFSET(LAST3_FRAME)][ref_stamp]
1876 .as_int = this_mv.as_int;
1877 }
1878 #endif
1879 if (ref_frame[0] >= GOLDEN_FRAME) {
1880 get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_gld,
1881 ref_frame_offset);
1882 tpl_mvs_base[mi_offset]
1883 .mfmv[FWD_RF_OFFSET(GOLDEN_FRAME)][ref_stamp]
1884 .as_int = this_mv.as_int;
1885 }
1886 }
1887 }
1888 }
1889 }
1890 }
1891
1892 // ==========================================
1893 // Process BWD reference frame
1894 // ==========================================
1895 #if CONFIG_EXT_REFS
1896 if (bwd_buf_idx >= 0) {
1897 MV_REF *mv_ref_base = cm->buffer_pool->frame_bufs[bwd_buf_idx].mvs;
1898 const int lst_frame_idx =
1899 cm->buffer_pool->frame_bufs[bwd_buf_idx].lst_frame_offset;
1900 const int gld_frame_idx =
1901 cm->buffer_pool->frame_bufs[bwd_buf_idx].gld_frame_offset;
1902 const int lst2_frame_idx =
1903 cm->buffer_pool->frame_bufs[bwd_buf_idx].lst2_frame_offset;
1904 const int lst3_frame_idx =
1905 cm->buffer_pool->frame_bufs[bwd_buf_idx].lst3_frame_offset;
1906 const int bwd_frame_idx =
1907 cm->buffer_pool->frame_bufs[bwd_buf_idx].bwd_frame_offset;
1908 const int alt2_frame_idx =
1909 cm->buffer_pool->frame_bufs[bwd_buf_idx].alt2_frame_offset;
1910 const int alt_frame_idx =
1911 cm->buffer_pool->frame_bufs[bwd_buf_idx].alt_frame_offset;
1912
1913 int lst_offset = AOMMAX(1, bwd_frame_index - lst_frame_idx);
1914 int gld_offset = AOMMAX(1, bwd_frame_index - gld_frame_idx);
1915 int cur_to_lst = cur_frame_index - lst_frame_index;
1916
1917 int lst2_offset = AOMMAX(1, bwd_frame_index - lst2_frame_idx);
1918 int lst3_offset = AOMMAX(1, bwd_frame_index - lst3_frame_idx);
1919 int bwd_offset = AOMMAX(1, bwd_frame_idx - bwd_frame_index);
1920 int alt2_offset = AOMMAX(1, alt2_frame_idx - bwd_frame_index);
1921 int alt_offset = AOMMAX(1, alt_frame_idx - bwd_frame_index);
1922 int cur_to_lst2 = cur_frame_index - lst2_frame_index;
1923 int cur_to_lst3 = cur_frame_index - lst3_frame_index;
1924 int cur_to_gld = cur_frame_index - gld_frame_index;
1925 int cur_to_bwd = bwd_frame_index - cur_frame_index;
1926
1927 const int ref_stamp = FWD_RF_OFFSET(BWDREF_FRAME);
1928 const int ref_frame_offset_buffer[TOTAL_REFS_PER_FRAME] = {
1929 0, lst_offset, lst2_offset, lst3_offset,
1930 gld_offset, bwd_offset, alt2_offset, alt_offset,
1931 };
1932
1933 for (int blk_row = 0; blk_row < cm->mi_rows; ++blk_row) {
1934 for (int blk_col = 0; blk_col < cm->mi_cols; ++blk_col) {
1935 MV_REF *mv_ref = &mv_ref_base[blk_row * cm->mi_cols + blk_col];
1936 MV fwd_mv = mv_ref->mv[0].as_mv;
1937 MV_REFERENCE_FRAME ref_frame[2] = { mv_ref->ref_frame[0],
1938 mv_ref->ref_frame[1] };
1939
1940 if (ref_frame[0] <= GOLDEN_FRAME && ref_frame[0] > INTRA_FRAME) {
1941 const int ref_frame_offset = ref_frame_offset_buffer[ref_frame[0]];
1942 int_mv this_mv;
1943 int mi_r, mi_c;
1944
1945 get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_bwd,
1946 ref_frame_offset);
1947 int pos_valid = get_block_position(cm, &mi_r, &mi_c, blk_row, blk_col,
1948 this_mv.as_mv, 0);
1949
1950 if (pos_valid) {
1951 int mi_offset = mi_r * cm->mi_stride + mi_c;
1952
1953 tpl_mvs_base[mi_offset]
1954 .mfmv[FWD_RF_OFFSET(BWDREF_FRAME)][ref_stamp]
1955 .as_int = mv_sign_reverse(this_mv);
1956
1957 // Project the motion vector onto last reference frame
1958 get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_lst,
1959 ref_frame_offset);
1960 tpl_mvs_base[mi_offset]
1961 .mfmv[FWD_RF_OFFSET(LAST_FRAME)][ref_stamp]
1962 .as_int = this_mv.as_int;
1963
1964 if (ref_frame[0] >= LAST2_FRAME) {
1965 get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_lst2,
1966 ref_frame_offset);
1967 tpl_mvs_base[mi_offset]
1968 .mfmv[FWD_RF_OFFSET(LAST2_FRAME)][ref_stamp]
1969 .as_int = this_mv.as_int;
1970 }
1971
1972 if (ref_frame[0] >= LAST3_FRAME) {
1973 get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_lst3,
1974 ref_frame_offset);
1975 tpl_mvs_base[mi_offset]
1976 .mfmv[FWD_RF_OFFSET(LAST3_FRAME)][ref_stamp]
1977 .as_int = this_mv.as_int;
1978 }
1979
1980 if (ref_frame[0] >= GOLDEN_FRAME) {
1981 get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_gld,
1982 ref_frame_offset);
1983 tpl_mvs_base[mi_offset]
1984 .mfmv[FWD_RF_OFFSET(GOLDEN_FRAME)][ref_stamp]
1985 .as_int = this_mv.as_int;
1986 }
1987 }
1988 }
1989 }
1990 }
1991 }
1992 #endif
1993 }
1994 #endif // CONFIG_MFMV
1995
1996 #if CONFIG_WARPED_MOTION
1997 #if WARPED_MOTION_SORT_SAMPLES
record_samples(MB_MODE_INFO * mbmi,int * pts,int * pts_inref,int * pts_mv,int global_offset_r,int global_offset_c,int row_offset,int sign_r,int col_offset,int sign_c)1998 static INLINE void record_samples(MB_MODE_INFO *mbmi, int *pts, int *pts_inref,
1999 int *pts_mv, int global_offset_r,
2000 int global_offset_c, int row_offset,
2001 int sign_r, int col_offset, int sign_c) {
2002 int bw = block_size_wide[mbmi->sb_type];
2003 int bh = block_size_high[mbmi->sb_type];
2004 int cr_offset = row_offset * MI_SIZE + sign_r * AOMMAX(bh, MI_SIZE) / 2 - 1;
2005 int cc_offset = col_offset * MI_SIZE + sign_c * AOMMAX(bw, MI_SIZE) / 2 - 1;
2006 int x = cc_offset + global_offset_c;
2007 int y = cr_offset + global_offset_r;
2008
2009 pts[0] = (x * 8);
2010 pts[1] = (y * 8);
2011 pts_inref[0] = (x * 8) + mbmi->mv[0].as_mv.col;
2012 pts_inref[1] = (y * 8) + mbmi->mv[0].as_mv.row;
2013 pts_mv[0] = mbmi->mv[0].as_mv.col;
2014 pts_mv[1] = mbmi->mv[0].as_mv.row;
2015 }
2016
2017 // Only sort pts and pts_inref, and pts_mv is not sorted.
2018 #define TRIM_THR 16
sortSamples(int * pts_mv,MV * mv,int * pts,int * pts_inref,int len)2019 int sortSamples(int *pts_mv, MV *mv, int *pts, int *pts_inref, int len) {
2020 int pts_mvd[SAMPLES_ARRAY_SIZE] = { 0 };
2021 int i, j, k;
2022 int ret = len;
2023
2024 for (i = 0; i < len; ++i)
2025 pts_mvd[i] =
2026 abs(pts_mv[2 * i] - mv->col) + abs(pts_mv[2 * i + 1] - mv->row);
2027
2028 for (i = 1; i <= len - 1; ++i) {
2029 for (j = 0; j < i; ++j) {
2030 if (pts_mvd[j] > pts_mvd[i]) {
2031 int temp, tempi, tempj, ptempi, ptempj;
2032
2033 temp = pts_mvd[i];
2034 tempi = pts[2 * i];
2035 tempj = pts[2 * i + 1];
2036 ptempi = pts_inref[2 * i];
2037 ptempj = pts_inref[2 * i + 1];
2038
2039 for (k = i; k > j; k--) {
2040 pts_mvd[k] = pts_mvd[k - 1];
2041 pts[2 * k] = pts[2 * (k - 1)];
2042 pts[2 * k + 1] = pts[2 * (k - 1) + 1];
2043 pts_inref[2 * k] = pts_inref[2 * (k - 1)];
2044 pts_inref[2 * k + 1] = pts_inref[2 * (k - 1) + 1];
2045 }
2046
2047 pts_mvd[j] = temp;
2048 pts[2 * j] = tempi;
2049 pts[2 * j + 1] = tempj;
2050 pts_inref[2 * j] = ptempi;
2051 pts_inref[2 * j + 1] = ptempj;
2052 break;
2053 }
2054 }
2055 }
2056
2057 for (i = len - 1; i >= 1; i--) {
2058 int low = (i == 1) ? 1 : AOMMAX((pts_mvd[i - 1] - pts_mvd[0]) / (i - 1), 1);
2059
2060 if ((pts_mvd[i] - pts_mvd[i - 1]) >= TRIM_THR * low) ret = i;
2061 }
2062
2063 if (ret > LEAST_SQUARES_SAMPLES_MAX) ret = LEAST_SQUARES_SAMPLES_MAX;
2064 return ret;
2065 }
2066
2067 // Note: Samples returned are at 1/8-pel precision
findSamples(const AV1_COMMON * cm,MACROBLOCKD * xd,int mi_row,int mi_col,int * pts,int * pts_inref,int * pts_mv)2068 int findSamples(const AV1_COMMON *cm, MACROBLOCKD *xd, int mi_row, int mi_col,
2069 int *pts, int *pts_inref, int *pts_mv) {
2070 MB_MODE_INFO *const mbmi0 = &(xd->mi[0]->mbmi);
2071 int ref_frame = mbmi0->ref_frame[0];
2072 int up_available = xd->up_available;
2073 int left_available = xd->left_available;
2074 int i, mi_step = 1, np = 0;
2075 int global_offset_c = mi_col * MI_SIZE;
2076 int global_offset_r = mi_row * MI_SIZE;
2077
2078 const TileInfo *const tile = &xd->tile;
2079 int do_tl = 1;
2080 int do_tr = 1;
2081
2082 // scan the nearest above rows
2083 if (up_available) {
2084 int mi_row_offset = -1;
2085 MODE_INFO *mi = xd->mi[mi_row_offset * xd->mi_stride];
2086 MB_MODE_INFO *mbmi = &mi->mbmi;
2087 uint8_t n8_w = mi_size_wide[mbmi->sb_type];
2088
2089 if (xd->n8_w <= n8_w) {
2090 // Handle "current block width <= above block width" case.
2091 int col_offset = -mi_col % n8_w;
2092
2093 if (col_offset < 0) do_tl = 0;
2094 if (col_offset + n8_w > xd->n8_w) do_tr = 0;
2095
2096 if (mbmi->ref_frame[0] == ref_frame && mbmi->ref_frame[1] == NONE_FRAME) {
2097 record_samples(mbmi, pts, pts_inref, pts_mv, global_offset_r,
2098 global_offset_c, 0, -1, col_offset, 1);
2099 pts += 2;
2100 pts_inref += 2;
2101 pts_mv += 2;
2102 np++;
2103 }
2104 } else {
2105 // Handle "current block width > above block width" case.
2106 for (i = 0; i < AOMMIN(xd->n8_w, cm->mi_cols - mi_col); i += mi_step) {
2107 int mi_col_offset = i;
2108 mi = xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride];
2109 mbmi = &mi->mbmi;
2110 n8_w = mi_size_wide[mbmi->sb_type];
2111 mi_step = AOMMIN(xd->n8_w, n8_w);
2112
2113 if (mbmi->ref_frame[0] == ref_frame &&
2114 mbmi->ref_frame[1] == NONE_FRAME) {
2115 record_samples(mbmi, pts, pts_inref, pts_mv, global_offset_r,
2116 global_offset_c, 0, -1, i, 1);
2117 pts += 2;
2118 pts_inref += 2;
2119 pts_mv += 2;
2120 np++;
2121 }
2122 }
2123 }
2124 }
2125 assert(2 * np <= SAMPLES_ARRAY_SIZE);
2126
2127 // scan the nearest left columns
2128 if (left_available) {
2129 int mi_col_offset = -1;
2130
2131 MODE_INFO *mi = xd->mi[mi_col_offset];
2132 MB_MODE_INFO *mbmi = &mi->mbmi;
2133 uint8_t n8_h = mi_size_high[mbmi->sb_type];
2134
2135 if (xd->n8_h <= n8_h) {
2136 // Handle "current block height <= above block height" case.
2137 int row_offset = -mi_row % n8_h;
2138
2139 if (row_offset < 0) do_tl = 0;
2140
2141 if (mbmi->ref_frame[0] == ref_frame && mbmi->ref_frame[1] == NONE_FRAME) {
2142 record_samples(mbmi, pts, pts_inref, pts_mv, global_offset_r,
2143 global_offset_c, row_offset, 1, 0, -1);
2144 pts += 2;
2145 pts_inref += 2;
2146 pts_mv += 2;
2147 np++;
2148 }
2149 } else {
2150 // Handle "current block height > above block height" case.
2151 for (i = 0; i < AOMMIN(xd->n8_h, cm->mi_rows - mi_row); i += mi_step) {
2152 int mi_row_offset = i;
2153 mi = xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride];
2154 mbmi = &mi->mbmi;
2155 n8_h = mi_size_high[mbmi->sb_type];
2156 mi_step = AOMMIN(xd->n8_h, n8_h);
2157
2158 if (mbmi->ref_frame[0] == ref_frame &&
2159 mbmi->ref_frame[1] == NONE_FRAME) {
2160 record_samples(mbmi, pts, pts_inref, pts_mv, global_offset_r,
2161 global_offset_c, i, 1, 0, -1);
2162 pts += 2;
2163 pts_inref += 2;
2164 pts_mv += 2;
2165 np++;
2166 }
2167 }
2168 }
2169 }
2170 assert(2 * np <= SAMPLES_ARRAY_SIZE);
2171
2172 // Top-left block
2173 if (do_tl && left_available && up_available) {
2174 int mi_row_offset = -1;
2175 int mi_col_offset = -1;
2176
2177 MODE_INFO *mi = xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride];
2178 MB_MODE_INFO *mbmi = &mi->mbmi;
2179
2180 if (mbmi->ref_frame[0] == ref_frame && mbmi->ref_frame[1] == NONE_FRAME) {
2181 record_samples(mbmi, pts, pts_inref, pts_mv, global_offset_r,
2182 global_offset_c, 0, -1, 0, -1);
2183 pts += 2;
2184 pts_inref += 2;
2185 pts_mv += 2;
2186 np++;
2187 }
2188 }
2189 assert(2 * np <= SAMPLES_ARRAY_SIZE);
2190
2191 // Top-right block
2192 if (do_tr &&
2193 has_top_right(cm, xd, mi_row, mi_col, AOMMAX(xd->n8_w, xd->n8_h))) {
2194 POSITION trb_pos = { -1, xd->n8_w };
2195
2196 if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm, &trb_pos)) {
2197 int mi_row_offset = -1;
2198 int mi_col_offset = xd->n8_w;
2199
2200 MODE_INFO *mi = xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride];
2201 MB_MODE_INFO *mbmi = &mi->mbmi;
2202
2203 if (mbmi->ref_frame[0] == ref_frame && mbmi->ref_frame[1] == NONE_FRAME) {
2204 record_samples(mbmi, pts, pts_inref, pts_mv, global_offset_r,
2205 global_offset_c, 0, -1, xd->n8_w, 1);
2206 np++;
2207 }
2208 }
2209 }
2210 assert(2 * np <= SAMPLES_ARRAY_SIZE);
2211
2212 return np;
2213 }
2214 #else
calc_projection_samples(MB_MODE_INFO * const mbmi,int x,int y,int * pts_inref)2215 void calc_projection_samples(MB_MODE_INFO *const mbmi, int x, int y,
2216 int *pts_inref) {
2217 pts_inref[0] = (x * 8) + mbmi->mv[0].as_mv.col;
2218 pts_inref[1] = (y * 8) + mbmi->mv[0].as_mv.row;
2219 }
2220
2221 // Note: Samples returned are at 1/8-pel precision
findSamples(const AV1_COMMON * cm,MACROBLOCKD * xd,int mi_row,int mi_col,int * pts,int * pts_inref)2222 int findSamples(const AV1_COMMON *cm, MACROBLOCKD *xd, int mi_row, int mi_col,
2223 int *pts, int *pts_inref) {
2224 MB_MODE_INFO *const mbmi0 = &(xd->mi[0]->mbmi);
2225 int ref_frame = mbmi0->ref_frame[0];
2226 int up_available = xd->up_available;
2227 int left_available = xd->left_available;
2228 int i, mi_step, np = 0;
2229 int global_offset_c = mi_col * MI_SIZE;
2230 int global_offset_r = mi_row * MI_SIZE;
2231
2232 // scan the above row
2233 if (up_available) {
2234 for (i = 0; i < AOMMIN(xd->n8_w, cm->mi_cols - mi_col); i += mi_step) {
2235 int mi_row_offset = -1;
2236 int mi_col_offset = i;
2237
2238 MODE_INFO *mi = xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride];
2239 MB_MODE_INFO *mbmi = &mi->mbmi;
2240
2241 mi_step = AOMMIN(xd->n8_w, mi_size_wide[mbmi->sb_type]);
2242
2243 if (mbmi->ref_frame[0] == ref_frame && mbmi->ref_frame[1] == NONE_FRAME) {
2244 int bw = block_size_wide[mbmi->sb_type];
2245 int bh = block_size_high[mbmi->sb_type];
2246 int cr_offset = -AOMMAX(bh, MI_SIZE) / 2 - 1;
2247 int cc_offset = i * MI_SIZE + AOMMAX(bw, MI_SIZE) / 2 - 1;
2248 int x = cc_offset + global_offset_c;
2249 int y = cr_offset + global_offset_r;
2250
2251 pts[0] = (x * 8);
2252 pts[1] = (y * 8);
2253 calc_projection_samples(mbmi, x, y, pts_inref);
2254 pts += 2;
2255 pts_inref += 2;
2256 np++;
2257 if (np >= LEAST_SQUARES_SAMPLES_MAX) return LEAST_SQUARES_SAMPLES_MAX;
2258 }
2259 }
2260 }
2261 assert(2 * np <= SAMPLES_ARRAY_SIZE);
2262
2263 // scan the left column
2264 if (left_available) {
2265 for (i = 0; i < AOMMIN(xd->n8_h, cm->mi_rows - mi_row); i += mi_step) {
2266 int mi_row_offset = i;
2267 int mi_col_offset = -1;
2268
2269 MODE_INFO *mi = xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride];
2270 MB_MODE_INFO *mbmi = &mi->mbmi;
2271
2272 mi_step = AOMMIN(xd->n8_h, mi_size_high[mbmi->sb_type]);
2273
2274 if (mbmi->ref_frame[0] == ref_frame && mbmi->ref_frame[1] == NONE_FRAME) {
2275 int bw = block_size_wide[mbmi->sb_type];
2276 int bh = block_size_high[mbmi->sb_type];
2277 int cr_offset = i * MI_SIZE + AOMMAX(bh, MI_SIZE) / 2 - 1;
2278 int cc_offset = -AOMMAX(bw, MI_SIZE) / 2 - 1;
2279 int x = cc_offset + global_offset_c;
2280 int y = cr_offset + global_offset_r;
2281
2282 pts[0] = (x * 8);
2283 pts[1] = (y * 8);
2284 calc_projection_samples(mbmi, x, y, pts_inref);
2285 pts += 2;
2286 pts_inref += 2;
2287 np++;
2288 if (np >= LEAST_SQUARES_SAMPLES_MAX) return LEAST_SQUARES_SAMPLES_MAX;
2289 }
2290 }
2291 }
2292 assert(2 * np <= SAMPLES_ARRAY_SIZE);
2293
2294 if (left_available && up_available) {
2295 int mi_row_offset = -1;
2296 int mi_col_offset = -1;
2297
2298 MODE_INFO *mi = xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride];
2299 MB_MODE_INFO *mbmi = &mi->mbmi;
2300
2301 if (mbmi->ref_frame[0] == ref_frame && mbmi->ref_frame[1] == NONE_FRAME) {
2302 int bw = block_size_wide[mbmi->sb_type];
2303 int bh = block_size_high[mbmi->sb_type];
2304 int cr_offset = -AOMMAX(bh, MI_SIZE) / 2 - 1;
2305 int cc_offset = -AOMMAX(bw, MI_SIZE) / 2 - 1;
2306 int x = cc_offset + global_offset_c;
2307 int y = cr_offset + global_offset_r;
2308
2309 pts[0] = (x * 8);
2310 pts[1] = (y * 8);
2311 calc_projection_samples(mbmi, x, y, pts_inref);
2312 np++;
2313 }
2314 }
2315 assert(2 * np <= SAMPLES_ARRAY_SIZE);
2316
2317 return np;
2318 }
2319 #endif // WARPED_MOTION_SORT_SAMPLES
2320 #endif // CONFIG_WARPED_MOTION
2321