Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 1 | /* |
Yaowu Xu | 2ab7ff0 | 2016-09-02 12:04:54 -0700 | [diff] [blame] | 2 | * Copyright (c) 2016, Alliance for Open Media. All rights reserved |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 3 | * |
Yaowu Xu | 2ab7ff0 | 2016-09-02 12:04:54 -0700 | [diff] [blame] | 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. |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 10 | */ |
| 11 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 12 | #ifndef AV1_COMMON_RECONINTER_H_ |
| 13 | #define AV1_COMMON_RECONINTER_H_ |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 14 | |
| 15 | #include "av1/common/filter.h" |
| 16 | #include "av1/common/onyxc_int.h" |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 17 | #include "av1/common/av1_convolve.h" |
| 18 | #include "aom/aom_integer.h" |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 19 | |
| 20 | #ifdef __cplusplus |
| 21 | extern "C" { |
| 22 | #endif |
| 23 | |
| 24 | static INLINE void inter_predictor(const uint8_t *src, int src_stride, |
| 25 | uint8_t *dst, int dst_stride, |
| 26 | const int subpel_x, const int subpel_y, |
| 27 | const struct scale_factors *sf, int w, int h, |
| 28 | int ref_idx, |
| 29 | #if CONFIG_DUAL_FILTER |
James Zern | 7b9407a | 2016-05-18 23:48:05 -0700 | [diff] [blame] | 30 | const InterpFilter *interp_filter, |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 31 | #else |
James Zern | 7b9407a | 2016-05-18 23:48:05 -0700 | [diff] [blame] | 32 | const InterpFilter interp_filter, |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 33 | #endif |
| 34 | int xs, int ys) { |
| 35 | #if CONFIG_DUAL_FILTER |
| 36 | InterpFilterParams interp_filter_params_x = |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 37 | av1_get_interp_filter_params(interp_filter[1 + 2 * ref_idx]); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 38 | InterpFilterParams interp_filter_params_y = |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 39 | av1_get_interp_filter_params(interp_filter[0 + 2 * ref_idx]); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 40 | #else |
| 41 | InterpFilterParams interp_filter_params = |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 42 | av1_get_interp_filter_params(interp_filter); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 43 | #endif |
| 44 | |
| 45 | #if CONFIG_DUAL_FILTER |
| 46 | if (interp_filter_params_x.taps == SUBPEL_TAPS && |
| 47 | interp_filter_params_y.taps == SUBPEL_TAPS && w > 2 && h > 2) { |
| 48 | const int16_t *kernel_x = |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 49 | av1_get_interp_filter_subpel_kernel(interp_filter_params_x, subpel_x); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 50 | const int16_t *kernel_y = |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 51 | av1_get_interp_filter_subpel_kernel(interp_filter_params_y, subpel_y); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 52 | #else |
Jingning Han | e29ea12 | 2016-06-21 17:47:30 -0700 | [diff] [blame] | 53 | if (interp_filter_params.taps == SUBPEL_TAPS && w > 2 && h > 2) { |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 54 | const int16_t *kernel_x = |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 55 | av1_get_interp_filter_subpel_kernel(interp_filter_params, subpel_x); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 56 | const int16_t *kernel_y = |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 57 | av1_get_interp_filter_subpel_kernel(interp_filter_params, subpel_y); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 58 | #endif |
| 59 | #if CONFIG_EXT_INTERP && SUPPORT_NONINTERPOLATING_FILTERS |
| 60 | if (IsInterpolatingFilter(interp_filter)) { |
| 61 | // Interpolating filter |
| 62 | sf->predict[subpel_x != 0][subpel_y != 0][ref]( |
| 63 | src, src_stride, dst, dst_stride, kernel_x, xs, kernel_y, ys, w, h); |
| 64 | } else { |
| 65 | sf->predict_ni[subpel_x != 0][subpel_y != 0][ref]( |
| 66 | src, src_stride, dst, dst_stride, kernel_x, xs, kernel_y, ys, w, h); |
| 67 | } |
| 68 | #else |
| 69 | sf->predict[subpel_x != 0][subpel_y != 0][ref_idx]( |
| 70 | src, src_stride, dst, dst_stride, kernel_x, xs, kernel_y, ys, w, h); |
| 71 | #endif // CONFIG_EXT_INTERP && SUPPORT_NONINTERPOLATING_FILTERS |
| 72 | } else { |
| 73 | // ref_idx > 0 means this is the second reference frame |
| 74 | // first reference frame's prediction result is already in dst |
| 75 | // therefore we need to average the first and second results |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 76 | av1_convolve(src, src_stride, dst, dst_stride, w, h, interp_filter, |
| 77 | subpel_x, xs, subpel_y, ys, ref_idx); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 78 | } |
| 79 | } |
| 80 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 81 | #if CONFIG_AOM_HIGHBITDEPTH |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 82 | static INLINE void highbd_inter_predictor(const uint8_t *src, int src_stride, |
| 83 | uint8_t *dst, int dst_stride, |
| 84 | const int subpel_x, |
| 85 | const int subpel_y, |
| 86 | const struct scale_factors *sf, int w, |
| 87 | int h, int ref, |
| 88 | #if CONFIG_DUAL_FILTER |
James Zern | 7b9407a | 2016-05-18 23:48:05 -0700 | [diff] [blame] | 89 | const InterpFilter *interp_filter, |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 90 | #else |
James Zern | 7b9407a | 2016-05-18 23:48:05 -0700 | [diff] [blame] | 91 | const InterpFilter interp_filter, |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 92 | #endif |
| 93 | int xs, int ys, int bd) { |
| 94 | #if CONFIG_DUAL_FILTER |
| 95 | InterpFilterParams interp_filter_params_x = |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 96 | av1_get_interp_filter_params(interp_filter[1 + 2 * ref]); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 97 | InterpFilterParams interp_filter_params_y = |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 98 | av1_get_interp_filter_params(interp_filter[0 + 2 * ref]); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 99 | #else |
| 100 | InterpFilterParams interp_filter_params = |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 101 | av1_get_interp_filter_params(interp_filter); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 102 | #endif |
| 103 | |
| 104 | #if CONFIG_DUAL_FILTER |
| 105 | if (interp_filter_params_x.taps == SUBPEL_TAPS && |
| 106 | interp_filter_params_y.taps == SUBPEL_TAPS && w > 2 && h > 2) { |
| 107 | const int16_t *kernel_x = |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 108 | av1_get_interp_filter_subpel_kernel(interp_filter_params_x, subpel_x); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 109 | const int16_t *kernel_y = |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 110 | av1_get_interp_filter_subpel_kernel(interp_filter_params_y, subpel_y); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 111 | #else |
Jingning Han | e29ea12 | 2016-06-21 17:47:30 -0700 | [diff] [blame] | 112 | if (interp_filter_params.taps == SUBPEL_TAPS && w > 2 && h > 2) { |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 113 | const int16_t *kernel_x = |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 114 | av1_get_interp_filter_subpel_kernel(interp_filter_params, subpel_x); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 115 | const int16_t *kernel_y = |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 116 | av1_get_interp_filter_subpel_kernel(interp_filter_params, subpel_y); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 117 | #endif // CONFIG_DUAL_FILTER |
| 118 | #if CONFIG_EXT_INTERP && SUPPORT_NONINTERPOLATING_FILTERS |
| 119 | if (IsInterpolatingFilter(interp_filter)) { |
| 120 | // Interpolating filter |
| 121 | sf->highbd_predict[subpel_x != 0][subpel_y != 0][ref]( |
| 122 | src, src_stride, dst, dst_stride, kernel_x, xs, kernel_y, ys, w, h, |
| 123 | bd); |
| 124 | } else { |
| 125 | sf->highbd_predict_ni[subpel_x != 0][subpel_y != 0][ref]( |
| 126 | src, src_stride, dst, dst_stride, kernel_x, xs, kernel_y, ys, w, h, |
| 127 | bd); |
| 128 | } |
| 129 | #else |
| 130 | sf->highbd_predict[subpel_x != 0][subpel_y != 0][ref]( |
| 131 | src, src_stride, dst, dst_stride, kernel_x, xs, kernel_y, ys, w, h, bd); |
| 132 | #endif // CONFIG_EXT_INTERP && SUPPORT_NONINTERPOLATING_FILTERS |
| 133 | } else { |
| 134 | // ref > 0 means this is the second reference frame |
| 135 | // first reference frame's prediction result is already in dst |
| 136 | // therefore we need to average the first and second results |
| 137 | int avg = ref > 0; |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 138 | av1_highbd_convolve(src, src_stride, dst, dst_stride, w, h, interp_filter, |
| 139 | subpel_x, xs, subpel_y, ys, avg, bd); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 140 | } |
| 141 | } |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 142 | #endif // CONFIG_AOM_HIGHBITDEPTH |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 143 | |
| 144 | #if CONFIG_EXT_INTER |
| 145 | // Set to one to use larger codebooks |
| 146 | #define USE_LARGE_WEDGE_CODEBOOK 0 |
| 147 | |
| 148 | #if USE_LARGE_WEDGE_CODEBOOK |
| 149 | #define MAX_WEDGE_TYPES (1 << 5) |
| 150 | #else |
| 151 | #define MAX_WEDGE_TYPES (1 << 4) |
| 152 | #endif |
| 153 | |
| 154 | #define MAX_WEDGE_SIZE_LOG2 5 // 32x32 |
| 155 | #define MAX_WEDGE_SIZE (1 << MAX_WEDGE_SIZE_LOG2) |
| 156 | #define MAX_WEDGE_SQUARE (MAX_WEDGE_SIZE * MAX_WEDGE_SIZE) |
| 157 | |
| 158 | #define WEDGE_WEIGHT_BITS 6 |
| 159 | |
| 160 | #define WEDGE_NONE -1 |
| 161 | |
| 162 | // Angles are with respect to horizontal anti-clockwise |
| 163 | typedef enum { |
| 164 | WEDGE_HORIZONTAL = 0, |
| 165 | WEDGE_VERTICAL = 1, |
| 166 | WEDGE_OBLIQUE27 = 2, |
| 167 | WEDGE_OBLIQUE63 = 3, |
| 168 | WEDGE_OBLIQUE117 = 4, |
| 169 | WEDGE_OBLIQUE153 = 5, |
| 170 | WEDGE_DIRECTIONS |
| 171 | } WedgeDirectionType; |
| 172 | |
| 173 | // 3-tuple: {direction, x_offset, y_offset} |
| 174 | typedef struct { |
| 175 | WedgeDirectionType direction; |
| 176 | int x_offset; |
| 177 | int y_offset; |
| 178 | } wedge_code_type; |
| 179 | |
| 180 | typedef uint8_t *wedge_masks_type[MAX_WEDGE_TYPES]; |
| 181 | |
| 182 | typedef struct { |
| 183 | int bits; |
| 184 | const wedge_code_type *codebook; |
| 185 | uint8_t *signflip; |
| 186 | int smoother; |
| 187 | wedge_masks_type *masks; |
| 188 | } wedge_params_type; |
| 189 | |
| 190 | extern const wedge_params_type wedge_params_lookup[BLOCK_SIZES]; |
| 191 | |
| 192 | static INLINE int get_wedge_bits_lookup(BLOCK_SIZE sb_type) { |
| 193 | return wedge_params_lookup[sb_type].bits; |
| 194 | } |
| 195 | |
| 196 | static INLINE int is_interinter_wedge_used(BLOCK_SIZE sb_type) { |
| 197 | (void)sb_type; |
| 198 | return wedge_params_lookup[sb_type].bits > 0; |
| 199 | } |
| 200 | |
| 201 | static INLINE int get_interinter_wedge_bits(BLOCK_SIZE sb_type) { |
| 202 | const int wbits = wedge_params_lookup[sb_type].bits; |
| 203 | return (wbits > 0) ? wbits + 1 : 0; |
| 204 | } |
| 205 | |
| 206 | static INLINE int is_interintra_wedge_used(BLOCK_SIZE sb_type) { |
| 207 | (void)sb_type; |
| 208 | return wedge_params_lookup[sb_type].bits > 0; |
| 209 | } |
| 210 | |
| 211 | static INLINE int get_interintra_wedge_bits(BLOCK_SIZE sb_type) { |
| 212 | return wedge_params_lookup[sb_type].bits; |
| 213 | } |
| 214 | #endif // CONFIG_EXT_INTER |
| 215 | |
| 216 | void build_inter_predictors(MACROBLOCKD *xd, int plane, |
Yue Chen | cb60b18 | 2016-10-13 15:18:22 -0700 | [diff] [blame] | 217 | #if CONFIG_MOTION_VAR |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 218 | int mi_col_offset, int mi_row_offset, |
Yue Chen | cb60b18 | 2016-10-13 15:18:22 -0700 | [diff] [blame] | 219 | #endif // CONFIG_MOTION_VAR |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 220 | int block, int bw, int bh, int x, int y, int w, |
| 221 | int h, |
| 222 | #if CONFIG_SUPERTX && CONFIG_EXT_INTER |
| 223 | int wedge_offset_x, int wedge_offset_y, |
| 224 | #endif // CONFIG_SUPERTX && CONFIG_EXT_INTER |
| 225 | int mi_x, int mi_y); |
| 226 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 227 | static INLINE void av1_make_inter_predictor( |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 228 | const uint8_t *src, int src_stride, uint8_t *dst, int dst_stride, |
| 229 | const int subpel_x, const int subpel_y, const struct scale_factors *sf, |
| 230 | int w, int h, int ref, |
| 231 | #if CONFIG_DUAL_FILTER |
James Zern | 7b9407a | 2016-05-18 23:48:05 -0700 | [diff] [blame] | 232 | const InterpFilter *interp_filter, |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 233 | #else |
James Zern | 7b9407a | 2016-05-18 23:48:05 -0700 | [diff] [blame] | 234 | const InterpFilter interp_filter, |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 235 | #endif |
| 236 | int xs, int ys, const MACROBLOCKD *xd) { |
| 237 | (void)xd; |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 238 | #if CONFIG_AOM_HIGHBITDEPTH |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 239 | if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) |
| 240 | highbd_inter_predictor(src, src_stride, dst, dst_stride, subpel_x, subpel_y, |
| 241 | sf, w, h, ref, interp_filter, xs, ys, xd->bd); |
| 242 | else |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 243 | #endif // CONFIG_AOM_HIGHBITDEPTH |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 244 | inter_predictor(src, src_stride, dst, dst_stride, subpel_x, subpel_y, sf, w, |
| 245 | h, ref, interp_filter, xs, ys); |
| 246 | } |
| 247 | |
| 248 | #if CONFIG_EXT_INTER |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 249 | void av1_make_masked_inter_predictor(const uint8_t *pre, int pre_stride, |
| 250 | uint8_t *dst, int dst_stride, |
| 251 | const int subpel_x, const int subpel_y, |
| 252 | const struct scale_factors *sf, int w, |
| 253 | int h, |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 254 | #if CONFIG_DUAL_FILTER |
James Zern | 7b9407a | 2016-05-18 23:48:05 -0700 | [diff] [blame] | 255 | const InterpFilter *interp_filter, |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 256 | #else |
James Zern | 7b9407a | 2016-05-18 23:48:05 -0700 | [diff] [blame] | 257 | const InterpFilter interp_filter, |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 258 | #endif |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 259 | int xs, int ys, |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 260 | #if CONFIG_SUPERTX |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 261 | int wedge_offset_x, int wedge_offset_y, |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 262 | #endif // CONFIG_SUPERTX |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 263 | const MACROBLOCKD *xd); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 264 | #endif // CONFIG_EXT_INTER |
| 265 | |
| 266 | static INLINE int round_mv_comp_q4(int value) { |
| 267 | return (value < 0 ? value - 2 : value + 2) / 4; |
| 268 | } |
| 269 | |
| 270 | static MV mi_mv_pred_q4(const MODE_INFO *mi, int idx) { |
| 271 | MV res = { |
| 272 | round_mv_comp_q4( |
| 273 | mi->bmi[0].as_mv[idx].as_mv.row + mi->bmi[1].as_mv[idx].as_mv.row + |
| 274 | mi->bmi[2].as_mv[idx].as_mv.row + mi->bmi[3].as_mv[idx].as_mv.row), |
| 275 | round_mv_comp_q4( |
| 276 | mi->bmi[0].as_mv[idx].as_mv.col + mi->bmi[1].as_mv[idx].as_mv.col + |
| 277 | mi->bmi[2].as_mv[idx].as_mv.col + mi->bmi[3].as_mv[idx].as_mv.col) |
| 278 | }; |
| 279 | return res; |
| 280 | } |
| 281 | |
| 282 | static INLINE int round_mv_comp_q2(int value) { |
| 283 | return (value < 0 ? value - 1 : value + 1) / 2; |
| 284 | } |
| 285 | |
| 286 | static MV mi_mv_pred_q2(const MODE_INFO *mi, int idx, int block0, int block1) { |
| 287 | MV res = { round_mv_comp_q2(mi->bmi[block0].as_mv[idx].as_mv.row + |
| 288 | mi->bmi[block1].as_mv[idx].as_mv.row), |
| 289 | round_mv_comp_q2(mi->bmi[block0].as_mv[idx].as_mv.col + |
| 290 | mi->bmi[block1].as_mv[idx].as_mv.col) }; |
| 291 | return res; |
| 292 | } |
| 293 | |
| 294 | // TODO(jkoleszar): yet another mv clamping function :-( |
| 295 | static INLINE MV clamp_mv_to_umv_border_sb(const MACROBLOCKD *xd, |
| 296 | const MV *src_mv, int bw, int bh, |
| 297 | int ss_x, int ss_y) { |
| 298 | // If the MV points so far into the UMV border that no visible pixels |
| 299 | // are used for reconstruction, the subpel part of the MV can be |
| 300 | // discarded and the MV limited to 16 pixels with equivalent results. |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 301 | const int spel_left = (AOM_INTERP_EXTEND + bw) << SUBPEL_BITS; |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 302 | const int spel_right = spel_left - SUBPEL_SHIFTS; |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 303 | const int spel_top = (AOM_INTERP_EXTEND + bh) << SUBPEL_BITS; |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 304 | const int spel_bottom = spel_top - SUBPEL_SHIFTS; |
| 305 | MV clamped_mv = { src_mv->row * (1 << (1 - ss_y)), |
| 306 | src_mv->col * (1 << (1 - ss_x)) }; |
| 307 | assert(ss_x <= 1); |
| 308 | assert(ss_y <= 1); |
| 309 | |
| 310 | clamp_mv(&clamped_mv, xd->mb_to_left_edge * (1 << (1 - ss_x)) - spel_left, |
| 311 | xd->mb_to_right_edge * (1 << (1 - ss_x)) + spel_right, |
| 312 | xd->mb_to_top_edge * (1 << (1 - ss_y)) - spel_top, |
| 313 | xd->mb_to_bottom_edge * (1 << (1 - ss_y)) + spel_bottom); |
| 314 | |
| 315 | return clamped_mv; |
| 316 | } |
| 317 | |
| 318 | static INLINE MV average_split_mvs(const struct macroblockd_plane *pd, |
| 319 | const MODE_INFO *mi, int ref, int block) { |
| 320 | const int ss_idx = ((pd->subsampling_x > 0) << 1) | (pd->subsampling_y > 0); |
| 321 | MV res = { 0, 0 }; |
| 322 | switch (ss_idx) { |
| 323 | case 0: res = mi->bmi[block].as_mv[ref].as_mv; break; |
| 324 | case 1: res = mi_mv_pred_q2(mi, ref, block, block + 2); break; |
| 325 | case 2: res = mi_mv_pred_q2(mi, ref, block, block + 1); break; |
| 326 | case 3: res = mi_mv_pred_q4(mi, ref); break; |
| 327 | default: assert(ss_idx <= 3 && ss_idx >= 0); |
| 328 | } |
| 329 | return res; |
| 330 | } |
| 331 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 332 | void av1_build_inter_predictor_sub8x8(MACROBLOCKD *xd, int plane, int i, int ir, |
| 333 | int ic, int mi_row, int mi_col); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 334 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 335 | void av1_build_inter_predictors_sby(MACROBLOCKD *xd, int mi_row, int mi_col, |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 336 | BLOCK_SIZE bsize); |
| 337 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 338 | void av1_build_inter_predictors_sbp(MACROBLOCKD *xd, int mi_row, int mi_col, |
| 339 | BLOCK_SIZE bsize, int plane); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 340 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 341 | void av1_build_inter_predictors_sbuv(MACROBLOCKD *xd, int mi_row, int mi_col, |
| 342 | BLOCK_SIZE bsize); |
| 343 | |
| 344 | void av1_build_inter_predictors_sb(MACROBLOCKD *xd, int mi_row, int mi_col, |
| 345 | BLOCK_SIZE bsize); |
| 346 | |
| 347 | #if CONFIG_SUPERTX |
| 348 | void av1_build_inter_predictors_sb_sub8x8_extend(MACROBLOCKD *xd, |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 349 | #if CONFIG_EXT_INTER |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 350 | int mi_row_ori, int mi_col_ori, |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 351 | #endif // CONFIG_EXT_INTER |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 352 | int mi_row, int mi_col, |
| 353 | BLOCK_SIZE bsize, int block); |
| 354 | |
| 355 | void av1_build_inter_predictors_sb_extend(MACROBLOCKD *xd, |
| 356 | #if CONFIG_EXT_INTER |
| 357 | int mi_row_ori, int mi_col_ori, |
| 358 | #endif // CONFIG_EXT_INTER |
| 359 | int mi_row, int mi_col, |
| 360 | BLOCK_SIZE bsize); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 361 | struct macroblockd_plane; |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 362 | void av1_build_masked_inter_predictor_complex( |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 363 | MACROBLOCKD *xd, uint8_t *dst, int dst_stride, const uint8_t *pre, |
| 364 | int pre_stride, int mi_row, int mi_col, int mi_row_ori, int mi_col_ori, |
| 365 | BLOCK_SIZE bsize, BLOCK_SIZE top_bsize, PARTITION_TYPE partition, |
| 366 | int plane); |
| 367 | #endif // CONFIG_SUPERTX |
| 368 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 369 | void av1_build_inter_predictor(const uint8_t *src, int src_stride, uint8_t *dst, |
| 370 | int dst_stride, const MV *mv_q3, |
| 371 | const struct scale_factors *sf, int w, int h, |
| 372 | int do_avg, |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 373 | #if CONFIG_DUAL_FILTER |
James Zern | 7b9407a | 2016-05-18 23:48:05 -0700 | [diff] [blame] | 374 | const InterpFilter *interp_filter, |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 375 | #else |
James Zern | 7b9407a | 2016-05-18 23:48:05 -0700 | [diff] [blame] | 376 | const InterpFilter interp_filter, |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 377 | #endif |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 378 | enum mv_precision precision, int x, int y); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 379 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 380 | #if CONFIG_AOM_HIGHBITDEPTH |
| 381 | void av1_highbd_build_inter_predictor( |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 382 | const uint8_t *src, int src_stride, uint8_t *dst, int dst_stride, |
| 383 | const MV *mv_q3, const struct scale_factors *sf, int w, int h, int do_avg, |
| 384 | #if CONFIG_DUAL_FILTER |
James Zern | 7b9407a | 2016-05-18 23:48:05 -0700 | [diff] [blame] | 385 | const InterpFilter *interp_filter, |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 386 | #else |
James Zern | 7b9407a | 2016-05-18 23:48:05 -0700 | [diff] [blame] | 387 | const InterpFilter interp_filter, |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 388 | #endif |
| 389 | enum mv_precision precision, int x, int y, int bd); |
| 390 | #endif |
| 391 | |
| 392 | static INLINE int scaled_buffer_offset(int x_offset, int y_offset, int stride, |
| 393 | const struct scale_factors *sf) { |
| 394 | const int x = sf ? sf->scale_value_x(x_offset, sf) : x_offset; |
| 395 | const int y = sf ? sf->scale_value_y(y_offset, sf) : y_offset; |
| 396 | return y * stride + x; |
| 397 | } |
| 398 | |
| 399 | static INLINE void setup_pred_plane(struct buf_2d *dst, uint8_t *src, int width, |
| 400 | int height, int stride, int mi_row, |
| 401 | int mi_col, |
| 402 | const struct scale_factors *scale, |
| 403 | int subsampling_x, int subsampling_y) { |
| 404 | const int x = (MI_SIZE * mi_col) >> subsampling_x; |
| 405 | const int y = (MI_SIZE * mi_row) >> subsampling_y; |
| 406 | dst->buf = src + scaled_buffer_offset(x, y, stride, scale); |
| 407 | dst->buf0 = src; |
| 408 | dst->width = width; |
| 409 | dst->height = height; |
| 410 | dst->stride = stride; |
| 411 | } |
| 412 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 413 | void av1_setup_dst_planes(struct macroblockd_plane planes[MAX_MB_PLANE], |
| 414 | const YV12_BUFFER_CONFIG *src, int mi_row, |
| 415 | int mi_col); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 416 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 417 | void av1_setup_pre_planes(MACROBLOCKD *xd, int idx, |
| 418 | const YV12_BUFFER_CONFIG *src, int mi_row, int mi_col, |
| 419 | const struct scale_factors *sf); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 420 | |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 421 | // Detect if the block have sub-pixel level motion vectors |
| 422 | // per component. |
| 423 | static INLINE int has_subpel_mv_component(const MODE_INFO *const mi, |
| 424 | const MACROBLOCKD *const xd, |
| 425 | int dir) { |
| 426 | const MB_MODE_INFO *const mbmi = &mi->mbmi; |
| 427 | const BLOCK_SIZE bsize = mbmi->sb_type; |
| 428 | int plane; |
| 429 | int ref = (dir >> 1); |
| 430 | |
| 431 | if (bsize >= BLOCK_8X8) { |
| 432 | if (dir & 0x01) { |
| 433 | if (mbmi->mv[ref].as_mv.col & SUBPEL_MASK) return 1; |
| 434 | } else { |
| 435 | if (mbmi->mv[ref].as_mv.row & SUBPEL_MASK) return 1; |
| 436 | } |
| 437 | } else { |
| 438 | for (plane = 0; plane < MAX_MB_PLANE; ++plane) { |
| 439 | const PARTITION_TYPE bp = BLOCK_8X8 - bsize; |
| 440 | const struct macroblockd_plane *const pd = &xd->plane[plane]; |
| 441 | const int have_vsplit = bp != PARTITION_HORZ; |
| 442 | const int have_hsplit = bp != PARTITION_VERT; |
| 443 | const int num_4x4_w = 2 >> ((!have_vsplit) | pd->subsampling_x); |
| 444 | const int num_4x4_h = 2 >> ((!have_hsplit) | pd->subsampling_y); |
| 445 | |
| 446 | int x, y; |
| 447 | for (y = 0; y < num_4x4_h; ++y) { |
| 448 | for (x = 0; x < num_4x4_w; ++x) { |
| 449 | const MV mv = average_split_mvs(pd, mi, ref, y * 2 + x); |
| 450 | if (dir & 0x01) { |
| 451 | if (mv.col & SUBPEL_MASK) return 1; |
| 452 | } else { |
| 453 | if (mv.row & SUBPEL_MASK) return 1; |
| 454 | } |
| 455 | } |
| 456 | } |
| 457 | } |
| 458 | } |
| 459 | |
| 460 | return 0; |
| 461 | } |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 462 | |
Angie Chiang | a69ce1b | 2016-10-07 10:57:45 -0700 | [diff] [blame] | 463 | #define CHECK_SUBPEL 0 |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 464 | static INLINE int av1_is_interp_needed(const MACROBLOCKD *const xd) { |
Angie Chiang | a69ce1b | 2016-10-07 10:57:45 -0700 | [diff] [blame] | 465 | #if CHECK_SUBPEL |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 466 | MODE_INFO *const mi = xd->mi[0]; |
Angie Chiang | b135deb | 2016-10-25 16:56:48 -0700 | [diff] [blame] | 467 | const int is_compound = has_second_ref(&mi->mbmi); |
| 468 | int ref; |
| 469 | for (ref = 0; ref < 1 + is_compound; ++ref) { |
| 470 | int row_col; |
| 471 | for (row_col = 0; row_col < 2; ++row_col) { |
| 472 | const int dir = (ref << 1) + row_col; |
| 473 | if (has_subpel_mv_component(mi, xd, dir)) { |
| 474 | return 1; |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 475 | } |
| 476 | } |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 477 | } |
Angie Chiang | b135deb | 2016-10-25 16:56:48 -0700 | [diff] [blame] | 478 | return 0; |
Angie Chiang | a69ce1b | 2016-10-07 10:57:45 -0700 | [diff] [blame] | 479 | #else |
| 480 | (void)xd; |
| 481 | return 1; |
| 482 | #endif |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 483 | } |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 484 | |
Yue Chen | cb60b18 | 2016-10-13 15:18:22 -0700 | [diff] [blame] | 485 | #if CONFIG_MOTION_VAR |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 486 | const uint8_t *av1_get_obmc_mask(int length); |
Urvang Joshi | 5264844 | 2016-10-13 17:27:51 -0700 | [diff] [blame] | 487 | void av1_build_obmc_inter_prediction(const AV1_COMMON *cm, MACROBLOCKD *xd, |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 488 | int mi_row, int mi_col, |
| 489 | uint8_t *above[MAX_MB_PLANE], |
| 490 | int above_stride[MAX_MB_PLANE], |
| 491 | uint8_t *left[MAX_MB_PLANE], |
| 492 | int left_stride[MAX_MB_PLANE]); |
Urvang Joshi | 5264844 | 2016-10-13 17:27:51 -0700 | [diff] [blame] | 493 | void av1_build_prediction_by_above_preds(const AV1_COMMON *cm, MACROBLOCKD *xd, |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 494 | int mi_row, int mi_col, |
| 495 | uint8_t *tmp_buf[MAX_MB_PLANE], |
| 496 | int tmp_width[MAX_MB_PLANE], |
| 497 | int tmp_height[MAX_MB_PLANE], |
| 498 | int tmp_stride[MAX_MB_PLANE]); |
Urvang Joshi | 5264844 | 2016-10-13 17:27:51 -0700 | [diff] [blame] | 499 | void av1_build_prediction_by_left_preds(const AV1_COMMON *cm, MACROBLOCKD *xd, |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 500 | int mi_row, int mi_col, |
| 501 | uint8_t *tmp_buf[MAX_MB_PLANE], |
| 502 | int tmp_width[MAX_MB_PLANE], |
| 503 | int tmp_height[MAX_MB_PLANE], |
| 504 | int tmp_stride[MAX_MB_PLANE]); |
Yue Chen | 894fcce | 2016-10-21 16:50:52 -0700 | [diff] [blame] | 505 | void av1_build_obmc_inter_predictors_sb(const AV1_COMMON *cm, MACROBLOCKD *xd, |
| 506 | int mi_row, int mi_col); |
Yue Chen | cb60b18 | 2016-10-13 15:18:22 -0700 | [diff] [blame] | 507 | #endif // CONFIG_MOTION_VAR |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 508 | |
| 509 | #if CONFIG_EXT_INTER |
| 510 | #define MASK_MASTER_SIZE (2 * MAX_SB_SIZE) |
| 511 | #define MASK_MASTER_STRIDE (2 * MAX_SB_SIZE) |
| 512 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 513 | void av1_init_wedge_masks(); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 514 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 515 | static INLINE const uint8_t *av1_get_contiguous_soft_mask(int wedge_index, |
| 516 | int wedge_sign, |
| 517 | BLOCK_SIZE sb_type) { |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 518 | return wedge_params_lookup[sb_type].masks[wedge_sign][wedge_index]; |
| 519 | } |
| 520 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 521 | const uint8_t *av1_get_soft_mask(int wedge_index, int wedge_sign, |
| 522 | BLOCK_SIZE sb_type, int wedge_offset_x, |
| 523 | int wedge_offset_y); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 524 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 525 | void av1_build_interintra_predictors(MACROBLOCKD *xd, uint8_t *ypred, |
| 526 | uint8_t *upred, uint8_t *vpred, |
| 527 | int ystride, int ustride, int vstride, |
| 528 | BLOCK_SIZE bsize); |
| 529 | void av1_build_interintra_predictors_sby(MACROBLOCKD *xd, uint8_t *ypred, |
| 530 | int ystride, BLOCK_SIZE bsize); |
| 531 | void av1_build_interintra_predictors_sbc(MACROBLOCKD *xd, uint8_t *upred, |
| 532 | int ustride, int plane, |
| 533 | BLOCK_SIZE bsize); |
| 534 | void av1_build_interintra_predictors_sbuv(MACROBLOCKD *xd, uint8_t *upred, |
| 535 | uint8_t *vpred, int ustride, |
| 536 | int vstride, BLOCK_SIZE bsize); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 537 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 538 | void av1_build_intra_predictors_for_interintra(MACROBLOCKD *xd, |
| 539 | BLOCK_SIZE bsize, int plane, |
| 540 | uint8_t *intra_pred, |
| 541 | int intra_stride); |
| 542 | void av1_combine_interintra(MACROBLOCKD *xd, BLOCK_SIZE bsize, int plane, |
| 543 | const uint8_t *inter_pred, int inter_stride, |
| 544 | const uint8_t *intra_pred, int intra_stride); |
| 545 | void av1_build_interintra_predictors_sbuv(MACROBLOCKD *xd, uint8_t *upred, |
| 546 | uint8_t *vpred, int ustride, |
| 547 | int vstride, BLOCK_SIZE bsize); |
| 548 | void av1_build_interintra_predictors_sby(MACROBLOCKD *xd, uint8_t *ypred, |
| 549 | int ystride, BLOCK_SIZE bsize); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 550 | |
| 551 | // Encoder only |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 552 | void av1_build_inter_predictors_for_planes_single_buf( |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 553 | MACROBLOCKD *xd, BLOCK_SIZE bsize, int plane_from, int plane_to, int mi_row, |
| 554 | int mi_col, int ref, uint8_t *ext_dst[3], int ext_dst_stride[3]); |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 555 | void av1_build_wedge_inter_predictor_from_buf(MACROBLOCKD *xd, BLOCK_SIZE bsize, |
| 556 | int plane_from, int plane_to, |
| 557 | uint8_t *ext_dst0[3], |
| 558 | int ext_dst_stride0[3], |
| 559 | uint8_t *ext_dst1[3], |
| 560 | int ext_dst_stride1[3]); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 561 | #endif // CONFIG_EXT_INTER |
| 562 | |
| 563 | #ifdef __cplusplus |
| 564 | } // extern "C" |
| 565 | #endif |
| 566 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 567 | #endif // AV1_COMMON_RECONINTER_H_ |