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 : #ifndef AV1_COMMON_RECONINTER_H_
13 : #define AV1_COMMON_RECONINTER_H_
14 :
15 : #include "av1/common/filter.h"
16 : #include "av1/common/onyxc_int.h"
17 : #include "av1/common/convolve.h"
18 : #if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
19 : #include "av1/common/warped_motion.h"
20 : #endif // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
21 : #include "aom/aom_integer.h"
22 :
23 : #if CONFIG_MOTION_VAR && CONFIG_WARPED_MOTION
24 : #define WARP_WM_NEIGHBORS_WITH_OBMC 0
25 : #endif // CONFIG_MOTION_VAR && CONFIG_WARPED_MOTION
26 :
27 : #if CONFIG_MOTION_VAR && CONFIG_GLOBAL_MOTION
28 : #define WARP_GM_NEIGHBORS_WITH_OBMC 0
29 : #endif // CONFIG_MOTION_VAR && CONFIG_WARPED_MOTION
30 :
31 : #ifdef __cplusplus
32 : extern "C" {
33 : #endif
34 :
35 0 : static INLINE int has_scale(int xs, int ys) { return xs != 16 || ys != 16; }
36 :
37 0 : static INLINE void inter_predictor(const uint8_t *src, int src_stride,
38 : uint8_t *dst, int dst_stride, int subpel_x,
39 : int subpel_y, const struct scale_factors *sf,
40 : int w, int h, ConvolveParams *conv_params,
41 : #if CONFIG_DUAL_FILTER
42 : const InterpFilter *interp_filter,
43 : #else
44 : const InterpFilter interp_filter,
45 : #endif
46 : int xs, int ys) {
47 : #if CONFIG_DUAL_FILTER
48 0 : const InterpFilter filter_x = av1_get_plane_interp_filter(
49 0 : interp_filter[1 + 2 * conv_params->ref], conv_params->plane);
50 0 : const InterpFilter filter_y = av1_get_plane_interp_filter(
51 0 : interp_filter[0 + 2 * conv_params->ref], conv_params->plane);
52 0 : const InterpFilterParams interp_filter_params_x =
53 : av1_get_interp_filter_params(filter_x);
54 0 : const InterpFilterParams interp_filter_params_y =
55 : av1_get_interp_filter_params(filter_y);
56 : #else
57 : const InterpFilterParams interp_filter_params_x =
58 : av1_get_interp_filter_params(interp_filter);
59 : const InterpFilterParams interp_filter_params_y = interp_filter_params_x;
60 : #endif
61 :
62 0 : assert(sf);
63 0 : if (has_scale(xs, ys)) {
64 0 : av1_convolve_c(src, src_stride, dst, dst_stride, w, h, interp_filter,
65 : subpel_x, xs, subpel_y, ys, conv_params);
66 0 : } else if (conv_params->round == CONVOLVE_OPT_NO_ROUND) {
67 : #if CONFIG_CONVOLVE_ROUND
68 : av1_convolve_2d_facade(src, src_stride, dst, dst_stride, w, h,
69 : #if CONFIG_DUAL_FILTER
70 : interp_filter,
71 : #else // CONFIG_DUAL_FILTER
72 : &interp_filter,
73 : #endif // CONFIG_DUAL_FILTER
74 : subpel_x, xs, subpel_y, ys, conv_params);
75 : conv_params->do_post_rounding = 1;
76 : #else
77 0 : assert(0);
78 : #endif // CONFIG_CONVOLVE_ROUND
79 : } else {
80 0 : assert(conv_params->round == CONVOLVE_OPT_ROUND);
81 0 : if (w <= 2 || h <= 2) {
82 0 : av1_convolve_c(src, src_stride, dst, dst_stride, w, h, interp_filter,
83 : subpel_x, xs, subpel_y, ys, conv_params);
84 0 : } else if (interp_filter_params_x.taps == SUBPEL_TAPS &&
85 0 : interp_filter_params_y.taps == SUBPEL_TAPS) {
86 0 : const int16_t *kernel_x =
87 : av1_get_interp_filter_subpel_kernel(interp_filter_params_x, subpel_x);
88 0 : const int16_t *kernel_y =
89 : av1_get_interp_filter_subpel_kernel(interp_filter_params_y, subpel_y);
90 0 : sf->predict[subpel_x != 0][subpel_y != 0][conv_params->ref](
91 : src, src_stride, dst, dst_stride, kernel_x, xs, kernel_y, ys, w, h);
92 : } else {
93 0 : av1_convolve(src, src_stride, dst, dst_stride, w, h, interp_filter,
94 : subpel_x, xs, subpel_y, ys, conv_params);
95 : }
96 : }
97 0 : }
98 :
99 : #if CONFIG_HIGHBITDEPTH
100 0 : static INLINE void highbd_inter_predictor(const uint8_t *src, int src_stride,
101 : uint8_t *dst, int dst_stride,
102 : const int subpel_x,
103 : const int subpel_y,
104 : const struct scale_factors *sf, int w,
105 : int h, ConvolveParams *conv_params,
106 : #if CONFIG_DUAL_FILTER
107 : const InterpFilter *interp_filter,
108 : #else
109 : const InterpFilter interp_filter,
110 : #endif
111 : int xs, int ys, int bd) {
112 0 : const int ref = conv_params->ref;
113 : // ref > 0 means this is the second reference frame
114 : // first reference frame's prediction result is already in dst
115 : // therefore we need to average the first and second results
116 0 : const int avg = ref > 0;
117 : #if CONFIG_DUAL_FILTER
118 0 : const InterpFilterParams interp_filter_params_x =
119 0 : av1_get_interp_filter_params(interp_filter[1 + 2 * ref]);
120 0 : const InterpFilterParams interp_filter_params_y =
121 0 : av1_get_interp_filter_params(interp_filter[0 + 2 * ref]);
122 : #else
123 : const InterpFilterParams interp_filter_params_x =
124 : av1_get_interp_filter_params(interp_filter);
125 : const InterpFilterParams interp_filter_params_y = interp_filter_params_x;
126 : #endif
127 :
128 0 : if (has_scale(xs, ys)) {
129 0 : av1_highbd_convolve(src, src_stride, dst, dst_stride, w, h, interp_filter,
130 : subpel_x, xs, subpel_y, ys, avg, bd);
131 0 : } else if (conv_params->round == CONVOLVE_OPT_NO_ROUND) {
132 : #if CONFIG_CONVOLVE_ROUND
133 : av1_highbd_convolve_2d_facade(src, src_stride, dst, dst_stride, w, h,
134 : #if CONFIG_DUAL_FILTER
135 : interp_filter,
136 : #else // CONFIG_DUAL_FILTER
137 : &interp_filter,
138 : #endif // CONFIG_DUAL_FILTER
139 : subpel_x, xs, subpel_y, ys, conv_params, bd);
140 : conv_params->do_post_rounding = 1;
141 : #else
142 0 : assert(0);
143 : #endif // CONFIG_CONVOLVE_ROUND
144 : } else {
145 0 : if (interp_filter_params_x.taps == SUBPEL_TAPS &&
146 0 : interp_filter_params_y.taps == SUBPEL_TAPS && w > 2 && h > 2) {
147 0 : const int16_t *kernel_x =
148 : av1_get_interp_filter_subpel_kernel(interp_filter_params_x, subpel_x);
149 0 : const int16_t *kernel_y =
150 : av1_get_interp_filter_subpel_kernel(interp_filter_params_y, subpel_y);
151 0 : sf->highbd_predict[subpel_x != 0][subpel_y != 0][ref](
152 : src, src_stride, dst, dst_stride, kernel_x, xs, kernel_y, ys, w, h,
153 : bd);
154 : } else {
155 0 : av1_highbd_convolve(src, src_stride, dst, dst_stride, w, h, interp_filter,
156 : subpel_x, xs, subpel_y, ys, avg, bd);
157 : }
158 : }
159 0 : }
160 : #endif // CONFIG_HIGHBITDEPTH
161 :
162 : #if CONFIG_EXT_INTER
163 : // Set to (1 << 5) if the 32-ary codebooks are used for any bock size
164 : #define MAX_WEDGE_TYPES (1 << 4)
165 :
166 : #define MAX_WEDGE_SIZE_LOG2 5 // 32x32
167 : #define MAX_WEDGE_SIZE (1 << MAX_WEDGE_SIZE_LOG2)
168 : #define MAX_WEDGE_SQUARE (MAX_WEDGE_SIZE * MAX_WEDGE_SIZE)
169 :
170 : #define WEDGE_WEIGHT_BITS 6
171 :
172 : #define WEDGE_NONE -1
173 :
174 : // Angles are with respect to horizontal anti-clockwise
175 : typedef enum {
176 : WEDGE_HORIZONTAL = 0,
177 : WEDGE_VERTICAL = 1,
178 : WEDGE_OBLIQUE27 = 2,
179 : WEDGE_OBLIQUE63 = 3,
180 : WEDGE_OBLIQUE117 = 4,
181 : WEDGE_OBLIQUE153 = 5,
182 : WEDGE_DIRECTIONS
183 : } WedgeDirectionType;
184 :
185 : // 3-tuple: {direction, x_offset, y_offset}
186 : typedef struct {
187 : WedgeDirectionType direction;
188 : int x_offset;
189 : int y_offset;
190 : } wedge_code_type;
191 :
192 : typedef uint8_t *wedge_masks_type[MAX_WEDGE_TYPES];
193 :
194 : typedef struct {
195 : int bits;
196 : const wedge_code_type *codebook;
197 : uint8_t *signflip;
198 : int smoother;
199 : wedge_masks_type *masks;
200 : } wedge_params_type;
201 :
202 : extern const wedge_params_type wedge_params_lookup[BLOCK_SIZES];
203 :
204 0 : static INLINE int is_interinter_compound_used(COMPOUND_TYPE type,
205 : BLOCK_SIZE sb_type) {
206 : (void)sb_type;
207 0 : switch (type) {
208 0 : case COMPOUND_AVERAGE: return 1;
209 : #if CONFIG_WEDGE
210 0 : case COMPOUND_WEDGE: return wedge_params_lookup[sb_type].bits > 0;
211 : #endif // CONFIG_WEDGE
212 : #if CONFIG_COMPOUND_SEGMENT
213 0 : case COMPOUND_SEG: return sb_type >= BLOCK_8X8;
214 : #endif // CONFIG_COMPOUND_SEGMENT
215 0 : default: assert(0); return 0;
216 : }
217 : }
218 :
219 0 : static INLINE int is_any_masked_compound_used(BLOCK_SIZE sb_type) {
220 : COMPOUND_TYPE comp_type;
221 0 : for (comp_type = 0; comp_type < COMPOUND_TYPES; comp_type++) {
222 0 : if (is_masked_compound_type(comp_type) &&
223 0 : is_interinter_compound_used(comp_type, sb_type))
224 0 : return 1;
225 : }
226 0 : return 0;
227 : }
228 :
229 0 : static INLINE int get_wedge_bits_lookup(BLOCK_SIZE sb_type) {
230 0 : return wedge_params_lookup[sb_type].bits;
231 : }
232 :
233 0 : static INLINE int get_interinter_wedge_bits(BLOCK_SIZE sb_type) {
234 0 : const int wbits = wedge_params_lookup[sb_type].bits;
235 0 : return (wbits > 0) ? wbits + 1 : 0;
236 : }
237 :
238 0 : static INLINE int is_interintra_wedge_used(BLOCK_SIZE sb_type) {
239 : (void)sb_type;
240 0 : return wedge_params_lookup[sb_type].bits > 0;
241 : }
242 :
243 0 : static INLINE int get_interintra_wedge_bits(BLOCK_SIZE sb_type) {
244 0 : return wedge_params_lookup[sb_type].bits;
245 : }
246 :
247 : #if CONFIG_COMPOUND_SEGMENT
248 : void build_compound_seg_mask(uint8_t *mask, SEG_MASK_TYPE mask_type,
249 : const uint8_t *src0, int src0_stride,
250 : const uint8_t *src1, int src1_stride,
251 : BLOCK_SIZE sb_type, int h, int w);
252 : #if CONFIG_HIGHBITDEPTH
253 : void build_compound_seg_mask_highbd(uint8_t *mask, SEG_MASK_TYPE mask_type,
254 : const uint8_t *src0, int src0_stride,
255 : const uint8_t *src1, int src1_stride,
256 : BLOCK_SIZE sb_type, int h, int w, int bd);
257 : #endif // CONFIG_HIGHBITDEPTH
258 : #endif // CONFIG_COMPOUND_SEGMENT
259 : #endif // CONFIG_EXT_INTER
260 :
261 : void build_inter_predictors(const AV1_COMMON *cm, MACROBLOCKD *xd, int plane,
262 : #if CONFIG_MOTION_VAR
263 : int mi_col_offset, int mi_row_offset,
264 : #endif // CONFIG_MOTION_VAR
265 : int block, int bw, int bh, int x, int y, int w,
266 : int h,
267 : #if CONFIG_SUPERTX && CONFIG_EXT_INTER
268 : int wedge_offset_x, int wedge_offset_y,
269 : #endif // CONFIG_SUPERTX && CONFIG_EXT_INTER
270 : int mi_x, int mi_y);
271 :
272 : #if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
273 : // This function will determine whether or not to create a warped
274 : // prediction and return the appropriate motion model depending
275 : // on the configuration. Behavior will change with different
276 : // combinations of GLOBAL_MOTION, WARPED_MOTION and MOTION_VAR.
277 0 : static INLINE int allow_warp(const MODE_INFO *const mi,
278 : const WarpTypesAllowed *const warp_types,
279 : #if CONFIG_GLOBAL_MOTION
280 : const WarpedMotionParams *const gm_params,
281 : #endif // CONFIG_GLOBAL_MOTION
282 : #if CONFIG_MOTION_VAR
283 : int mi_col_offset, int mi_row_offset,
284 : #endif // CONFIG_MOTION_VAR
285 : WarpedMotionParams *final_warp_params) {
286 0 : const MB_MODE_INFO *const mbmi = &mi->mbmi;
287 0 : set_default_warp_params(final_warp_params);
288 :
289 : // Only global motion configured
290 : #if CONFIG_GLOBAL_MOTION && !CONFIG_WARPED_MOTION && !CONFIG_MOTION_VAR
291 : (void)mbmi;
292 : if (warp_types->global_warp_allowed) {
293 : memcpy(final_warp_params, gm_params, sizeof(*final_warp_params));
294 : return 1;
295 : }
296 : #endif // CONFIG_GLOBAL_MOTION && !CONFIG_WARPED_MOTION && !CONFIG_MOTION_VAR
297 :
298 : // Only warped motion configured
299 : #if CONFIG_WARPED_MOTION && !CONFIG_GLOBAL_MOTION && !CONFIG_MOTION_VAR
300 : if (warp_types->local_warp_allowed) {
301 : memcpy(final_warp_params, &mbmi->wm_params[0], sizeof(*final_warp_params));
302 : return 1;
303 : }
304 : #endif // CONFIG_WARPED_MOTION && !CONFIG_GLOBAL_MOTION && !CONFIG_MOTION_VAR
305 :
306 : // Warped and global motion configured
307 : #if CONFIG_GLOBAL_MOTION && CONFIG_WARPED_MOTION && !CONFIG_MOTION_VAR
308 : // When both are enabled, warped will take priority. The global parameters
309 : // will only be used to compute projection samples to find the warped model.
310 : // Note that, if SEPARATE_GLOBAL_MOTION is enabled and a block chooses
311 : // global, it will not be possible to select WARPED_CAUSAL.
312 : if (warp_types->local_warp_allowed) {
313 : memcpy(final_warp_params, &mbmi->wm_params[0], sizeof(*final_warp_params));
314 : return 1;
315 : } else if (warp_types->global_warp_allowed) {
316 : memcpy(final_warp_params, gm_params, sizeof(*final_warp_params));
317 : return 1;
318 : }
319 : #endif // CONFIG_GLOBAL_MOTION && CONFIG_WARPED_MOTION && !CONFIG_MOTION_VAR
320 :
321 : // Motion var and global motion configured
322 : #if CONFIG_GLOBAL_MOTION && CONFIG_MOTION_VAR && !CONFIG_WARPED_MOTION
323 : // We warp if either case is true:
324 : // 1.) We are predicting a block which uses global motion
325 : // 2.) We are predicting a neighboring block of a block using OBMC,
326 : // the neighboring block uses global motion, and we have enabled
327 : // WARP_GM_NEIGHBORS_WITH_OBMC
328 : const int build_for_obmc = !(mi_col_offset == 0 && mi_row_offset == 0);
329 : (void)mbmi;
330 : if (warp_types->global_warp_allowed &&
331 : (WARP_GM_NEIGHBORS_WITH_OBMC || !build_for_obmc)) {
332 : memcpy(final_warp_params, gm_params, sizeof(*final_warp_params));
333 : return 1;
334 : }
335 : #endif // CONFIG_GLOBAL_MOTION && CONFIG_MOTION_VAR && !CONFIG_WARPED_MOTION
336 :
337 : // Motion var and warped motion configured
338 : #if CONFIG_WARPED_MOTION && CONFIG_MOTION_VAR && !CONFIG_GLOBAL_MOTION
339 : // We warp if either case is true:
340 : // 1.) We are predicting a block with motion mode WARPED_CAUSAL
341 : // 2.) We are predicting a neighboring block of a block using OBMC,
342 : // the neighboring block has mode WARPED_CAUSAL, and we have enabled
343 : // WARP_WM_NEIGHBORS_WITH_OBMC
344 : const int build_for_obmc = !(mi_col_offset == 0 && mi_row_offset == 0);
345 : if (warp_types->local_warp_allowed) {
346 : if ((build_for_obmc && WARP_WM_NEIGHBORS_WITH_OBMC) || (!build_for_obmc)) {
347 : memcpy(final_warp_params, &mbmi->wm_params[0],
348 : sizeof(*final_warp_params));
349 : return 1;
350 : }
351 : }
352 : #endif // CONFIG_WARPED_MOTION && CONFIG_MOTION_VAR && !CONFIG_GLOBAL_MOTION
353 :
354 : // Motion var, warped motion and global motion all configured
355 : #if CONFIG_WARPED_MOTION && CONFIG_MOTION_VAR && CONFIG_GLOBAL_MOTION
356 0 : const int build_for_obmc = !(mi_col_offset == 0 && mi_row_offset == 0);
357 0 : if (warp_types->local_warp_allowed) {
358 0 : if ((build_for_obmc && WARP_WM_NEIGHBORS_WITH_OBMC) || (!build_for_obmc)) {
359 0 : memcpy(final_warp_params, &mbmi->wm_params[0],
360 : sizeof(*final_warp_params));
361 0 : return 1;
362 : }
363 0 : } else if (warp_types->global_warp_allowed &&
364 : (WARP_GM_NEIGHBORS_WITH_OBMC || !build_for_obmc)) {
365 0 : memcpy(final_warp_params, gm_params, sizeof(*final_warp_params));
366 0 : return 1;
367 : }
368 : #endif // CONFIG_WARPED_MOTION && CONFIG_MOTION_VAR && CONFIG_GLOBAL_MOTION
369 :
370 0 : return 0;
371 : }
372 : #endif // CONFIG_GLOBAL_MOTION ||CONFIG_WARPED_MOTION
373 :
374 0 : static INLINE void av1_make_inter_predictor(
375 : const uint8_t *src, int src_stride, uint8_t *dst, int dst_stride,
376 : const int subpel_x, const int subpel_y, const struct scale_factors *sf,
377 : int w, int h, ConvolveParams *conv_params,
378 : #if CONFIG_DUAL_FILTER
379 : const InterpFilter *interp_filter,
380 : #else
381 : const InterpFilter interp_filter,
382 : #endif
383 : #if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
384 : const WarpTypesAllowed *warp_types, int p_col, int p_row, int plane,
385 : int ref,
386 : #endif // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
387 : #if CONFIG_MOTION_VAR
388 : int mi_col_offset, int mi_row_offset,
389 : #endif
390 : int xs, int ys, const MACROBLOCKD *xd) {
391 : (void)xd;
392 :
393 : #if CONFIG_MOTION_VAR
394 0 : const MODE_INFO *mi = xd->mi[mi_col_offset + xd->mi_stride * mi_row_offset];
395 : #else
396 : const MODE_INFO *mi = xd->mi[0];
397 : (void)mi;
398 : #endif // CONFIG_MOTION_VAR
399 :
400 : // Make sure the selected motion mode is valid for this configuration
401 : #if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
402 0 : assert_motion_mode_valid(mi->mbmi.motion_mode,
403 : #if CONFIG_GLOBAL_MOTION && SEPARATE_GLOBAL_MOTION
404 0 : 0, xd->global_motion,
405 : #endif // CONFIG_GLOBAL_MOTION && SEPARATE_GLOBAL_MOTION
406 : mi);
407 : #endif // CONFIG MOTION_VAR || CONFIG_WARPED_MOTION
408 :
409 : #if CONFIG_WARPED_MOTION || CONFIG_GLOBAL_MOTION
410 : WarpedMotionParams final_warp_params;
411 0 : const int do_warp = allow_warp(mi, warp_types,
412 : #if CONFIG_GLOBAL_MOTION
413 0 : &xd->global_motion[mi->mbmi.ref_frame[ref]],
414 : #endif // CONFIG_GLOBAL_MOTION
415 : #if CONFIG_MOTION_VAR
416 : mi_col_offset, mi_row_offset,
417 : #endif // CONFIG_MOTION_VAR
418 : &final_warp_params);
419 0 : if (do_warp) {
420 0 : const struct macroblockd_plane *const pd = &xd->plane[plane];
421 0 : const struct buf_2d *const pre_buf = &pd->pre[ref];
422 : #if CONFIG_EXT_INTER
423 0 : int compute_avg =
424 0 : ref && mi->mbmi.interinter_compound_type == COMPOUND_AVERAGE;
425 : #else
426 : int compute_avg = ref;
427 : #endif // CONFIG_EXT_INTER
428 0 : av1_warp_plane(&final_warp_params,
429 : #if CONFIG_HIGHBITDEPTH
430 0 : xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH, xd->bd,
431 : #endif // CONFIG_HIGHBITDEPTH
432 0 : pre_buf->buf0, pre_buf->width, pre_buf->height,
433 : pre_buf->stride, dst, p_col, p_row, w, h, dst_stride,
434 : pd->subsampling_x, pd->subsampling_y, xs, ys, compute_avg);
435 0 : return;
436 : }
437 : #endif // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
438 : #if CONFIG_HIGHBITDEPTH
439 0 : if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
440 0 : highbd_inter_predictor(src, src_stride, dst, dst_stride, subpel_x, subpel_y,
441 : sf, w, h, conv_params, interp_filter, xs, ys,
442 : xd->bd);
443 0 : return;
444 : }
445 : #endif // CONFIG_HIGHBITDEPTH
446 0 : inter_predictor(src, src_stride, dst, dst_stride, subpel_x, subpel_y, sf, w,
447 : h, conv_params, interp_filter, xs, ys);
448 : }
449 :
450 : #if CONFIG_EXT_INTER
451 : void av1_make_masked_inter_predictor(const uint8_t *pre, int pre_stride,
452 : uint8_t *dst, int dst_stride,
453 : const int subpel_x, const int subpel_y,
454 : const struct scale_factors *sf, int w,
455 : int h,
456 : #if CONFIG_DUAL_FILTER
457 : const InterpFilter *interp_filter,
458 : #else
459 : const InterpFilter interp_filter,
460 : #endif
461 : int xs, int ys,
462 : #if CONFIG_SUPERTX
463 : int wedge_offset_x, int wedge_offset_y,
464 : #endif // CONFIG_SUPERTX
465 : int plane,
466 : #if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
467 : const WarpTypesAllowed *warp_types,
468 : int p_col, int p_row, int ref,
469 : #endif // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
470 : MACROBLOCKD *xd);
471 : #endif // CONFIG_EXT_INTER
472 :
473 0 : static INLINE int round_mv_comp_q4(int value) {
474 0 : return (value < 0 ? value - 2 : value + 2) / 4;
475 : }
476 :
477 0 : static MV mi_mv_pred_q4(const MODE_INFO *mi, int idx) {
478 0 : MV res = {
479 0 : round_mv_comp_q4(
480 0 : mi->bmi[0].as_mv[idx].as_mv.row + mi->bmi[1].as_mv[idx].as_mv.row +
481 0 : mi->bmi[2].as_mv[idx].as_mv.row + mi->bmi[3].as_mv[idx].as_mv.row),
482 0 : round_mv_comp_q4(
483 0 : mi->bmi[0].as_mv[idx].as_mv.col + mi->bmi[1].as_mv[idx].as_mv.col +
484 0 : mi->bmi[2].as_mv[idx].as_mv.col + mi->bmi[3].as_mv[idx].as_mv.col)
485 : };
486 0 : return res;
487 : }
488 :
489 0 : static INLINE int round_mv_comp_q2(int value) {
490 0 : return (value < 0 ? value - 1 : value + 1) / 2;
491 : }
492 :
493 0 : static MV mi_mv_pred_q2(const MODE_INFO *mi, int idx, int block0, int block1) {
494 0 : MV res = { round_mv_comp_q2(mi->bmi[block0].as_mv[idx].as_mv.row +
495 0 : mi->bmi[block1].as_mv[idx].as_mv.row),
496 0 : round_mv_comp_q2(mi->bmi[block0].as_mv[idx].as_mv.col +
497 0 : mi->bmi[block1].as_mv[idx].as_mv.col) };
498 0 : return res;
499 : }
500 :
501 : // TODO(jkoleszar): yet another mv clamping function :-(
502 0 : static INLINE MV clamp_mv_to_umv_border_sb(const MACROBLOCKD *xd,
503 : const MV *src_mv, int bw, int bh,
504 : int ss_x, int ss_y) {
505 : // If the MV points so far into the UMV border that no visible pixels
506 : // are used for reconstruction, the subpel part of the MV can be
507 : // discarded and the MV limited to 16 pixels with equivalent results.
508 0 : const int spel_left = (AOM_INTERP_EXTEND + bw) << SUBPEL_BITS;
509 0 : const int spel_right = spel_left - SUBPEL_SHIFTS;
510 0 : const int spel_top = (AOM_INTERP_EXTEND + bh) << SUBPEL_BITS;
511 0 : const int spel_bottom = spel_top - SUBPEL_SHIFTS;
512 0 : MV clamped_mv = { src_mv->row * (1 << (1 - ss_y)),
513 0 : src_mv->col * (1 << (1 - ss_x)) };
514 0 : assert(ss_x <= 1);
515 0 : assert(ss_y <= 1);
516 :
517 0 : clamp_mv(&clamped_mv, xd->mb_to_left_edge * (1 << (1 - ss_x)) - spel_left,
518 0 : xd->mb_to_right_edge * (1 << (1 - ss_x)) + spel_right,
519 0 : xd->mb_to_top_edge * (1 << (1 - ss_y)) - spel_top,
520 0 : xd->mb_to_bottom_edge * (1 << (1 - ss_y)) + spel_bottom);
521 :
522 0 : return clamped_mv;
523 : }
524 :
525 0 : static INLINE MV average_split_mvs(const struct macroblockd_plane *pd,
526 : const MODE_INFO *mi, int ref, int block) {
527 0 : const int ss_idx = ((pd->subsampling_x > 0) << 1) | (pd->subsampling_y > 0);
528 0 : MV res = { 0, 0 };
529 0 : switch (ss_idx) {
530 0 : case 0: res = mi->bmi[block].as_mv[ref].as_mv; break;
531 0 : case 1: res = mi_mv_pred_q2(mi, ref, block, block + 2); break;
532 0 : case 2: res = mi_mv_pred_q2(mi, ref, block, block + 1); break;
533 0 : case 3: res = mi_mv_pred_q4(mi, ref); break;
534 0 : default: assert(ss_idx <= 3 && ss_idx >= 0);
535 : }
536 0 : return res;
537 : }
538 :
539 : void av1_build_inter_predictor_sub8x8(const AV1_COMMON *cm, MACROBLOCKD *xd,
540 : int plane, int i, int ir, int ic,
541 : int mi_row, int mi_col);
542 :
543 : void av1_build_inter_predictors_sby(const AV1_COMMON *cm, MACROBLOCKD *xd,
544 : int mi_row, int mi_col, BUFFER_SET *ctx,
545 : BLOCK_SIZE bsize);
546 :
547 : void av1_build_inter_predictors_sbuv(const AV1_COMMON *cm, MACROBLOCKD *xd,
548 : int mi_row, int mi_col, BUFFER_SET *ctx,
549 : BLOCK_SIZE bsize);
550 :
551 : void av1_build_inter_predictors_sb(const AV1_COMMON *cm, MACROBLOCKD *xd,
552 : int mi_row, int mi_col, BUFFER_SET *ctx,
553 : BLOCK_SIZE bsize);
554 :
555 : #if CONFIG_SUPERTX
556 : void av1_build_inter_predictors_sb_sub8x8_extend(const AV1_COMMON *cm,
557 : MACROBLOCKD *xd,
558 : #if CONFIG_EXT_INTER
559 : int mi_row_ori, int mi_col_ori,
560 : #endif // CONFIG_EXT_INTER
561 : int mi_row, int mi_col,
562 : BLOCK_SIZE bsize, int block);
563 :
564 : void av1_build_inter_predictors_sb_extend(const AV1_COMMON *cm, MACROBLOCKD *xd,
565 : #if CONFIG_EXT_INTER
566 : int mi_row_ori, int mi_col_ori,
567 : #endif // CONFIG_EXT_INTER
568 : int mi_row, int mi_col,
569 : BLOCK_SIZE bsize);
570 : struct macroblockd_plane;
571 : void av1_build_masked_inter_predictor_complex(
572 : MACROBLOCKD *xd, uint8_t *dst, int dst_stride, const uint8_t *pre,
573 : int pre_stride, int mi_row, int mi_col, int mi_row_ori, int mi_col_ori,
574 : BLOCK_SIZE bsize, BLOCK_SIZE top_bsize, PARTITION_TYPE partition,
575 : int plane);
576 : #endif // CONFIG_SUPERTX
577 :
578 : void av1_build_inter_predictor(const uint8_t *src, int src_stride, uint8_t *dst,
579 : int dst_stride, const MV *src_mv,
580 : const struct scale_factors *sf, int w, int h,
581 : ConvolveParams *conv_params,
582 : #if CONFIG_DUAL_FILTER
583 : const InterpFilter *interp_filter,
584 : #else
585 : const InterpFilter interp_filter,
586 : #endif
587 : #if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
588 : const WarpTypesAllowed *warp_types, int p_col,
589 : int p_row, int plane, int ref,
590 : #endif // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
591 : enum mv_precision precision, int x, int y,
592 : const MACROBLOCKD *xd);
593 :
594 : #if CONFIG_HIGHBITDEPTH
595 : void av1_highbd_build_inter_predictor(
596 : const uint8_t *src, int src_stride, uint8_t *dst, int dst_stride,
597 : const MV *mv_q3, const struct scale_factors *sf, int w, int h, int do_avg,
598 : #if CONFIG_DUAL_FILTER
599 : const InterpFilter *interp_filter,
600 : #else
601 : const InterpFilter interp_filter,
602 : #endif
603 : #if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
604 : const WarpTypesAllowed *warp_types, int p_col, int p_row,
605 : #endif // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
606 : int plane, enum mv_precision precision, int x, int y,
607 : const MACROBLOCKD *xd);
608 : #endif
609 :
610 0 : static INLINE int scaled_buffer_offset(int x_offset, int y_offset, int stride,
611 : const struct scale_factors *sf) {
612 0 : const int x = sf ? sf->scale_value_x(x_offset, sf) : x_offset;
613 0 : const int y = sf ? sf->scale_value_y(y_offset, sf) : y_offset;
614 0 : return y * stride + x;
615 : }
616 :
617 0 : static INLINE void setup_pred_plane(struct buf_2d *dst, BLOCK_SIZE bsize,
618 : uint8_t *src, int width, int height,
619 : int stride, int mi_row, int mi_col,
620 : const struct scale_factors *scale,
621 : int subsampling_x, int subsampling_y) {
622 : #if CONFIG_CHROMA_SUB8X8
623 0 : if (bsize < BLOCK_8X8) {
624 : // Offset the buffer pointer
625 0 : if (subsampling_y && (mi_row & 0x01)) mi_row -= 1;
626 0 : if (subsampling_x && (mi_col & 0x01)) mi_col -= 1;
627 : }
628 : #else
629 : (void)bsize;
630 : #endif
631 :
632 0 : const int x = (MI_SIZE * mi_col) >> subsampling_x;
633 0 : const int y = (MI_SIZE * mi_row) >> subsampling_y;
634 0 : dst->buf = src + scaled_buffer_offset(x, y, stride, scale);
635 0 : dst->buf0 = src;
636 0 : dst->width = width;
637 0 : dst->height = height;
638 0 : dst->stride = stride;
639 0 : }
640 :
641 : void av1_setup_dst_planes(struct macroblockd_plane planes[MAX_MB_PLANE],
642 : BLOCK_SIZE bsize, const YV12_BUFFER_CONFIG *src,
643 : int mi_row, int mi_col);
644 :
645 : void av1_setup_pre_planes(MACROBLOCKD *xd, int idx,
646 : const YV12_BUFFER_CONFIG *src, int mi_row, int mi_col,
647 : const struct scale_factors *sf);
648 :
649 : // Detect if the block have sub-pixel level motion vectors
650 : // per component.
651 : #define CHECK_SUBPEL 0
652 0 : static INLINE int has_subpel_mv_component(const MODE_INFO *const mi,
653 : const MACROBLOCKD *const xd,
654 : int dir) {
655 : #if CHECK_SUBPEL
656 : const MB_MODE_INFO *const mbmi = &mi->mbmi;
657 : const BLOCK_SIZE bsize = mbmi->sb_type;
658 : int plane;
659 : int ref = (dir >> 1);
660 : #if CONFIG_CB4X4
661 : const int unify_bsize = 1;
662 : #else
663 : const int unify_bsize = 0;
664 : #endif
665 :
666 : if (bsize >= BLOCK_8X8 || unify_bsize) {
667 : if (dir & 0x01) {
668 : if (mbmi->mv[ref].as_mv.col & SUBPEL_MASK) return 1;
669 : } else {
670 : if (mbmi->mv[ref].as_mv.row & SUBPEL_MASK) return 1;
671 : }
672 : } else {
673 : for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
674 : const PARTITION_TYPE bp = BLOCK_8X8 - bsize;
675 : const struct macroblockd_plane *const pd = &xd->plane[plane];
676 : const int have_vsplit = bp != PARTITION_HORZ;
677 : const int have_hsplit = bp != PARTITION_VERT;
678 : const int num_4x4_w = 2 >> ((!have_vsplit) | pd->subsampling_x);
679 : const int num_4x4_h = 2 >> ((!have_hsplit) | pd->subsampling_y);
680 :
681 : int x, y;
682 : for (y = 0; y < num_4x4_h; ++y) {
683 : for (x = 0; x < num_4x4_w; ++x) {
684 : const MV mv = average_split_mvs(pd, mi, ref, y * 2 + x);
685 : if (dir & 0x01) {
686 : if (mv.col & SUBPEL_MASK) return 1;
687 : } else {
688 : if (mv.row & SUBPEL_MASK) return 1;
689 : }
690 : }
691 : }
692 : }
693 : }
694 :
695 : return 0;
696 : #else
697 : (void)mi;
698 : (void)xd;
699 : (void)dir;
700 0 : return 1;
701 : #endif
702 : }
703 :
704 0 : static INLINE void set_default_interp_filters(
705 : MB_MODE_INFO *const mbmi, InterpFilter frame_interp_filter) {
706 : #if CONFIG_DUAL_FILTER
707 : int dir;
708 0 : for (dir = 0; dir < 4; ++dir)
709 0 : mbmi->interp_filter[dir] = frame_interp_filter == SWITCHABLE
710 : ? EIGHTTAP_REGULAR
711 0 : : frame_interp_filter;
712 : #else
713 : mbmi->interp_filter = frame_interp_filter == SWITCHABLE ? EIGHTTAP_REGULAR
714 : : frame_interp_filter;
715 : #endif // CONFIG_DUAL_FILTER
716 0 : }
717 :
718 0 : static INLINE int av1_is_interp_needed(const MACROBLOCKD *const xd) {
719 : (void)xd;
720 : #if CONFIG_WARPED_MOTION
721 0 : const MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
722 0 : if (mbmi->motion_mode == WARPED_CAUSAL) return 0;
723 : #endif // CONFIG_WARPED_MOTION
724 : #if CONFIG_GLOBAL_MOTION
725 0 : if (is_nontrans_global_motion(xd)) return 0;
726 : #endif // CONFIG_GLOBAL_MOTION
727 0 : return 1;
728 : }
729 :
730 0 : static INLINE int av1_is_interp_search_needed(const MACROBLOCKD *const xd) {
731 0 : MODE_INFO *const mi = xd->mi[0];
732 0 : const int is_compound = has_second_ref(&mi->mbmi);
733 : int ref;
734 0 : for (ref = 0; ref < 1 + is_compound; ++ref) {
735 : int row_col;
736 0 : for (row_col = 0; row_col < 2; ++row_col) {
737 0 : const int dir = (ref << 1) + row_col;
738 0 : if (has_subpel_mv_component(mi, xd, dir)) {
739 0 : return 1;
740 : }
741 : }
742 : }
743 0 : return 0;
744 : }
745 :
746 : #if CONFIG_MOTION_VAR
747 : const uint8_t *av1_get_obmc_mask(int length);
748 : void av1_count_overlappable_neighbors(const AV1_COMMON *cm, MACROBLOCKD *xd,
749 : int mi_row, int mi_col);
750 : void av1_build_obmc_inter_prediction(const AV1_COMMON *cm, MACROBLOCKD *xd,
751 : int mi_row, int mi_col,
752 : uint8_t *above[MAX_MB_PLANE],
753 : int above_stride[MAX_MB_PLANE],
754 : uint8_t *left[MAX_MB_PLANE],
755 : int left_stride[MAX_MB_PLANE]);
756 : void av1_build_prediction_by_above_preds(const AV1_COMMON *cm, MACROBLOCKD *xd,
757 : int mi_row, int mi_col,
758 : uint8_t *tmp_buf[MAX_MB_PLANE],
759 : int tmp_width[MAX_MB_PLANE],
760 : int tmp_height[MAX_MB_PLANE],
761 : int tmp_stride[MAX_MB_PLANE]);
762 : void av1_build_prediction_by_left_preds(const AV1_COMMON *cm, MACROBLOCKD *xd,
763 : int mi_row, int mi_col,
764 : uint8_t *tmp_buf[MAX_MB_PLANE],
765 : int tmp_width[MAX_MB_PLANE],
766 : int tmp_height[MAX_MB_PLANE],
767 : int tmp_stride[MAX_MB_PLANE]);
768 : void av1_build_obmc_inter_predictors_sb(const AV1_COMMON *cm, MACROBLOCKD *xd,
769 : int mi_row, int mi_col);
770 : #if CONFIG_NCOBMC
771 : void av1_build_ncobmc_inter_predictors_sb(const AV1_COMMON *cm, MACROBLOCKD *xd,
772 : int mi_row, int mi_col);
773 : #endif
774 : #endif // CONFIG_MOTION_VAR
775 :
776 : #if CONFIG_EXT_INTER
777 : #define MASK_MASTER_SIZE ((MAX_WEDGE_SIZE) << 1)
778 : #define MASK_MASTER_STRIDE (MASK_MASTER_SIZE)
779 :
780 : void av1_init_wedge_masks();
781 :
782 0 : static INLINE const uint8_t *av1_get_contiguous_soft_mask(int wedge_index,
783 : int wedge_sign,
784 : BLOCK_SIZE sb_type) {
785 0 : return wedge_params_lookup[sb_type].masks[wedge_sign][wedge_index];
786 : }
787 :
788 : const uint8_t *av1_get_soft_mask(int wedge_index, int wedge_sign,
789 : BLOCK_SIZE sb_type, int wedge_offset_x,
790 : int wedge_offset_y);
791 :
792 : const uint8_t *av1_get_compound_type_mask_inverse(
793 : const INTERINTER_COMPOUND_DATA *const comp_data,
794 : #if CONFIG_COMPOUND_SEGMENT
795 : uint8_t *mask_buffer, int h, int w, int stride,
796 : #endif
797 : BLOCK_SIZE sb_type);
798 :
799 : const uint8_t *av1_get_compound_type_mask(
800 : const INTERINTER_COMPOUND_DATA *const comp_data, BLOCK_SIZE sb_type);
801 : #if CONFIG_INTERINTRA
802 : void av1_build_interintra_predictors(MACROBLOCKD *xd, uint8_t *ypred,
803 : uint8_t *upred, uint8_t *vpred,
804 : int ystride, int ustride, int vstride,
805 : BUFFER_SET *ctx, BLOCK_SIZE bsize);
806 : void av1_build_interintra_predictors_sby(MACROBLOCKD *xd, uint8_t *ypred,
807 : int ystride, BUFFER_SET *ctx,
808 : BLOCK_SIZE bsize);
809 : void av1_build_interintra_predictors_sbc(MACROBLOCKD *xd, uint8_t *upred,
810 : int ustride, BUFFER_SET *ctx,
811 : int plane, BLOCK_SIZE bsize);
812 : void av1_build_interintra_predictors_sbuv(MACROBLOCKD *xd, uint8_t *upred,
813 : uint8_t *vpred, int ustride,
814 : int vstride, BUFFER_SET *ctx,
815 : BLOCK_SIZE bsize);
816 :
817 : void av1_build_intra_predictors_for_interintra(MACROBLOCKD *xd,
818 : BLOCK_SIZE bsize, int plane,
819 : BUFFER_SET *ctx,
820 : uint8_t *intra_pred,
821 : int intra_stride);
822 : void av1_combine_interintra(MACROBLOCKD *xd, BLOCK_SIZE bsize, int plane,
823 : const uint8_t *inter_pred, int inter_stride,
824 : const uint8_t *intra_pred, int intra_stride);
825 : #endif // CONFIG_INTERINTRA
826 : // Encoder only
827 : void av1_build_inter_predictors_for_planes_single_buf(
828 : MACROBLOCKD *xd, BLOCK_SIZE bsize, int plane_from, int plane_to, int mi_row,
829 : int mi_col, int ref, uint8_t *ext_dst[3], int ext_dst_stride[3]);
830 : void av1_build_wedge_inter_predictor_from_buf(
831 : MACROBLOCKD *xd, BLOCK_SIZE bsize, int plane_from, int plane_to,
832 : #if CONFIG_SUPERTX
833 : int wedge_offset_x, int wedge_offset_y,
834 : #endif // CONFIG_SUPERTX
835 : uint8_t *ext_dst0[3], int ext_dst_stride0[3], uint8_t *ext_dst1[3],
836 : int ext_dst_stride1[3]);
837 : #endif // CONFIG_EXT_INTER
838 :
839 : #ifdef __cplusplus
840 : } // extern "C"
841 : #endif
842 :
843 : #endif // AV1_COMMON_RECONINTER_H_
|