Coverage Report

Created: 2025-08-11 08:01

/src/aom/av1/common/reconinter.c
Line
Count
Source (jump to first uncovered line)
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 <assert.h>
13
#include <stdio.h>
14
#include <limits.h>
15
16
#include "config/aom_config.h"
17
#include "config/aom_dsp_rtcd.h"
18
#include "config/aom_scale_rtcd.h"
19
20
#include "aom/aom_integer.h"
21
#include "aom_dsp/blend.h"
22
23
#include "av1/common/av1_common_int.h"
24
#include "av1/common/blockd.h"
25
#include "av1/common/mvref_common.h"
26
#include "av1/common/obmc.h"
27
#include "av1/common/reconinter.h"
28
#include "av1/common/reconintra.h"
29
30
// This function will determine whether or not to create a warped
31
// prediction.
32
int av1_allow_warp(const MB_MODE_INFO *const mbmi,
33
                   const WarpTypesAllowed *const warp_types,
34
                   const WarpedMotionParams *const gm_params,
35
                   int build_for_obmc, const struct scale_factors *const sf,
36
51.9k
                   WarpedMotionParams *final_warp_params) {
37
  // Note: As per the spec, we must test the fixed point scales here, which are
38
  // at a higher precision (1 << 14) than the xs and ys in subpel_params (that
39
  // have 1 << 10 precision).
40
51.9k
  if (av1_is_scaled(sf)) return 0;
41
42
50.0k
  if (final_warp_params != NULL) *final_warp_params = default_warp_params;
43
44
50.0k
  if (build_for_obmc) return 0;
45
46
50.0k
  if (warp_types->local_warp_allowed && !mbmi->wm_params.invalid) {
47
0
    if (final_warp_params != NULL)
48
0
      memcpy(final_warp_params, &mbmi->wm_params, sizeof(*final_warp_params));
49
0
    return 1;
50
50.0k
  } else if (warp_types->global_warp_allowed && !gm_params->invalid) {
51
380
    if (final_warp_params != NULL)
52
380
      memcpy(final_warp_params, gm_params, sizeof(*final_warp_params));
53
380
    return 1;
54
380
  }
55
56
49.6k
  return 0;
57
50.0k
}
58
59
void av1_init_inter_params(InterPredParams *inter_pred_params, int block_width,
60
                           int block_height, int pix_row, int pix_col,
61
                           int subsampling_x, int subsampling_y, int bit_depth,
62
                           int use_hbd_buf, int is_intrabc,
63
                           const struct scale_factors *sf,
64
                           const struct buf_2d *ref_buf,
65
180k
                           int_interpfilters interp_filters) {
66
180k
  inter_pred_params->block_width = block_width;
67
180k
  inter_pred_params->block_height = block_height;
68
180k
  inter_pred_params->pix_row = pix_row;
69
180k
  inter_pred_params->pix_col = pix_col;
70
180k
  inter_pred_params->subsampling_x = subsampling_x;
71
180k
  inter_pred_params->subsampling_y = subsampling_y;
72
180k
  inter_pred_params->bit_depth = bit_depth;
73
180k
  inter_pred_params->use_hbd_buf = use_hbd_buf;
74
180k
  inter_pred_params->is_intrabc = is_intrabc;
75
180k
  inter_pred_params->scale_factors = sf;
76
180k
  inter_pred_params->ref_frame_buf = *ref_buf;
77
180k
  inter_pred_params->mode = TRANSLATION_PRED;
78
180k
  inter_pred_params->comp_mode = UNIFORM_SINGLE;
79
80
180k
  if (is_intrabc) {
81
167k
    inter_pred_params->interp_filter_params[0] = &av1_intrabc_filter_params;
82
167k
    inter_pred_params->interp_filter_params[1] = &av1_intrabc_filter_params;
83
167k
  } else {
84
13.1k
    inter_pred_params->interp_filter_params[0] =
85
13.1k
        av1_get_interp_filter_params_with_block_size(
86
13.1k
            interp_filters.as_filters.x_filter, block_width);
87
13.1k
    inter_pred_params->interp_filter_params[1] =
88
13.1k
        av1_get_interp_filter_params_with_block_size(
89
13.1k
            interp_filters.as_filters.y_filter, block_height);
90
13.1k
  }
91
180k
}
92
93
3.42k
void av1_init_comp_mode(InterPredParams *inter_pred_params) {
94
3.42k
  inter_pred_params->comp_mode = UNIFORM_COMP;
95
3.42k
}
96
97
void av1_init_warp_params(InterPredParams *inter_pred_params,
98
                          const WarpTypesAllowed *warp_types, int ref,
99
179k
                          const MACROBLOCKD *xd, const MB_MODE_INFO *mi) {
100
179k
  if (inter_pred_params->block_height < 8 || inter_pred_params->block_width < 8)
101
95.3k
    return;
102
103
84.3k
  if (xd->cur_frame_force_integer_mv) return;
104
105
51.9k
  if (av1_allow_warp(mi, warp_types, &xd->global_motion[mi->ref_frame[ref]], 0,
106
51.9k
                     inter_pred_params->scale_factors,
107
51.9k
                     &inter_pred_params->warp_params)) {
108
#if CONFIG_REALTIME_ONLY
109
    aom_internal_error(xd->error_info, AOM_CODEC_UNSUP_FEATURE,
110
                       "Warped motion is disabled in realtime only build.");
111
#endif
112
380
    inter_pred_params->mode = WARP_PRED;
113
380
  }
114
51.9k
}
115
116
void av1_make_inter_predictor(const uint8_t *src, int src_stride, uint8_t *dst,
117
                              int dst_stride,
118
                              InterPredParams *inter_pred_params,
119
180k
                              const SubpelParams *subpel_params) {
120
180k
  assert(IMPLIES(inter_pred_params->conv_params.is_compound,
121
180k
                 inter_pred_params->conv_params.dst != NULL));
122
123
180k
  if (inter_pred_params->mode == TRANSLATION_PRED) {
124
180k
#if CONFIG_AV1_HIGHBITDEPTH
125
180k
    if (inter_pred_params->use_hbd_buf) {
126
75.9k
      highbd_inter_predictor(src, src_stride, dst, dst_stride, subpel_params,
127
75.9k
                             inter_pred_params->block_width,
128
75.9k
                             inter_pred_params->block_height,
129
75.9k
                             &inter_pred_params->conv_params,
130
75.9k
                             inter_pred_params->interp_filter_params,
131
75.9k
                             inter_pred_params->bit_depth);
132
104k
    } else {
133
104k
      inter_predictor(src, src_stride, dst, dst_stride, subpel_params,
134
104k
                      inter_pred_params->block_width,
135
104k
                      inter_pred_params->block_height,
136
104k
                      &inter_pred_params->conv_params,
137
104k
                      inter_pred_params->interp_filter_params);
138
104k
    }
139
#else
140
    inter_predictor(src, src_stride, dst, dst_stride, subpel_params,
141
                    inter_pred_params->block_width,
142
                    inter_pred_params->block_height,
143
                    &inter_pred_params->conv_params,
144
                    inter_pred_params->interp_filter_params);
145
#endif
146
180k
  }
147
380
#if !CONFIG_REALTIME_ONLY
148
  // TODO(jingning): av1_warp_plane() can be further cleaned up.
149
380
  else if (inter_pred_params->mode == WARP_PRED) {
150
380
    av1_warp_plane(
151
380
        &inter_pred_params->warp_params, inter_pred_params->use_hbd_buf,
152
380
        inter_pred_params->bit_depth, inter_pred_params->ref_frame_buf.buf0,
153
380
        inter_pred_params->ref_frame_buf.width,
154
380
        inter_pred_params->ref_frame_buf.height,
155
380
        inter_pred_params->ref_frame_buf.stride, dst,
156
380
        inter_pred_params->pix_col, inter_pred_params->pix_row,
157
380
        inter_pred_params->block_width, inter_pred_params->block_height,
158
380
        dst_stride, inter_pred_params->subsampling_x,
159
380
        inter_pred_params->subsampling_y, &inter_pred_params->conv_params);
160
380
  }
161
0
#endif
162
0
  else {
163
0
    assert(0 && "Unsupported inter_pred_params->mode");
164
0
  }
165
180k
}
166
167
static const uint8_t wedge_master_oblique_odd[MASK_MASTER_SIZE] = {
168
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
169
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  2,  6,  18,
170
  37, 53, 60, 63, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
171
  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
172
};
173
static const uint8_t wedge_master_oblique_even[MASK_MASTER_SIZE] = {
174
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
175
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  4,  11, 27,
176
  46, 58, 62, 63, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
177
  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
178
};
179
static const uint8_t wedge_master_vertical[MASK_MASTER_SIZE] = {
180
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
181
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  2,  7,  21,
182
  43, 57, 62, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
183
  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
184
};
185
186
static AOM_INLINE void shift_copy(const uint8_t *src, uint8_t *dst, int shift,
187
192
                                  int width) {
188
192
  if (shift >= 0) {
189
99
    memcpy(dst + shift, src, width - shift);
190
99
    memset(dst, src[0], shift);
191
99
  } else {
192
93
    shift = -shift;
193
93
    memcpy(dst, src + shift, width - shift);
194
93
    memset(dst + width - shift, src[width - 1], shift);
195
93
  }
196
192
}
197
198
/* clang-format off */
199
DECLARE_ALIGNED(16, static uint8_t,
200
                wedge_signflip_lookup[BLOCK_SIZES_ALL][MAX_WEDGE_TYPES]) = {
201
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },  // not used
202
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },  // not used
203
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },  // not used
204
  { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, },
205
  { 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, },
206
  { 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, },
207
  { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, },
208
  { 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, },
209
  { 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, },
210
  { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, },
211
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },  // not used
212
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },  // not used
213
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },  // not used
214
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },  // not used
215
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },  // not used
216
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },  // not used
217
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },  // not used
218
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },  // not used
219
  { 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, },
220
  { 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, },
221
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },  // not used
222
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },  // not used
223
};
224
/* clang-format on */
225
226
// [negative][direction]
227
DECLARE_ALIGNED(
228
    16, static uint8_t,
229
    wedge_mask_obl[2][WEDGE_DIRECTIONS][MASK_MASTER_SIZE * MASK_MASTER_SIZE]);
230
231
// 4 * MAX_WEDGE_SQUARE is an easy to compute and fairly tight upper bound
232
// on the sum of all mask sizes up to an including MAX_WEDGE_SQUARE.
233
DECLARE_ALIGNED(16, static uint8_t,
234
                wedge_mask_buf[2 * MAX_WEDGE_TYPES * 4 * MAX_WEDGE_SQUARE]);
235
236
DECLARE_ALIGNED(16, static uint8_t,
237
                smooth_interintra_mask_buf[INTERINTRA_MODES][BLOCK_SIZES_ALL]
238
                                          [MAX_WEDGE_SQUARE]);
239
240
static wedge_masks_type wedge_masks[BLOCK_SIZES_ALL][2];
241
242
static const wedge_code_type wedge_codebook_16_hgtw[16] = {
243
  { WEDGE_OBLIQUE27, 4, 4 },  { WEDGE_OBLIQUE63, 4, 4 },
244
  { WEDGE_OBLIQUE117, 4, 4 }, { WEDGE_OBLIQUE153, 4, 4 },
245
  { WEDGE_HORIZONTAL, 4, 2 }, { WEDGE_HORIZONTAL, 4, 4 },
246
  { WEDGE_HORIZONTAL, 4, 6 }, { WEDGE_VERTICAL, 4, 4 },
247
  { WEDGE_OBLIQUE27, 4, 2 },  { WEDGE_OBLIQUE27, 4, 6 },
248
  { WEDGE_OBLIQUE153, 4, 2 }, { WEDGE_OBLIQUE153, 4, 6 },
249
  { WEDGE_OBLIQUE63, 2, 4 },  { WEDGE_OBLIQUE63, 6, 4 },
250
  { WEDGE_OBLIQUE117, 2, 4 }, { WEDGE_OBLIQUE117, 6, 4 },
251
};
252
253
static const wedge_code_type wedge_codebook_16_hltw[16] = {
254
  { WEDGE_OBLIQUE27, 4, 4 },  { WEDGE_OBLIQUE63, 4, 4 },
255
  { WEDGE_OBLIQUE117, 4, 4 }, { WEDGE_OBLIQUE153, 4, 4 },
256
  { WEDGE_VERTICAL, 2, 4 },   { WEDGE_VERTICAL, 4, 4 },
257
  { WEDGE_VERTICAL, 6, 4 },   { WEDGE_HORIZONTAL, 4, 4 },
258
  { WEDGE_OBLIQUE27, 4, 2 },  { WEDGE_OBLIQUE27, 4, 6 },
259
  { WEDGE_OBLIQUE153, 4, 2 }, { WEDGE_OBLIQUE153, 4, 6 },
260
  { WEDGE_OBLIQUE63, 2, 4 },  { WEDGE_OBLIQUE63, 6, 4 },
261
  { WEDGE_OBLIQUE117, 2, 4 }, { WEDGE_OBLIQUE117, 6, 4 },
262
};
263
264
static const wedge_code_type wedge_codebook_16_heqw[16] = {
265
  { WEDGE_OBLIQUE27, 4, 4 },  { WEDGE_OBLIQUE63, 4, 4 },
266
  { WEDGE_OBLIQUE117, 4, 4 }, { WEDGE_OBLIQUE153, 4, 4 },
267
  { WEDGE_HORIZONTAL, 4, 2 }, { WEDGE_HORIZONTAL, 4, 6 },
268
  { WEDGE_VERTICAL, 2, 4 },   { WEDGE_VERTICAL, 6, 4 },
269
  { WEDGE_OBLIQUE27, 4, 2 },  { WEDGE_OBLIQUE27, 4, 6 },
270
  { WEDGE_OBLIQUE153, 4, 2 }, { WEDGE_OBLIQUE153, 4, 6 },
271
  { WEDGE_OBLIQUE63, 2, 4 },  { WEDGE_OBLIQUE63, 6, 4 },
272
  { WEDGE_OBLIQUE117, 2, 4 }, { WEDGE_OBLIQUE117, 6, 4 },
273
};
274
275
const wedge_params_type av1_wedge_params_lookup[BLOCK_SIZES_ALL] = {
276
  { 0, NULL, NULL, NULL },
277
  { 0, NULL, NULL, NULL },
278
  { 0, NULL, NULL, NULL },
279
  { MAX_WEDGE_TYPES, wedge_codebook_16_heqw, wedge_signflip_lookup[BLOCK_8X8],
280
    wedge_masks[BLOCK_8X8] },
281
  { MAX_WEDGE_TYPES, wedge_codebook_16_hgtw, wedge_signflip_lookup[BLOCK_8X16],
282
    wedge_masks[BLOCK_8X16] },
283
  { MAX_WEDGE_TYPES, wedge_codebook_16_hltw, wedge_signflip_lookup[BLOCK_16X8],
284
    wedge_masks[BLOCK_16X8] },
285
  { MAX_WEDGE_TYPES, wedge_codebook_16_heqw, wedge_signflip_lookup[BLOCK_16X16],
286
    wedge_masks[BLOCK_16X16] },
287
  { MAX_WEDGE_TYPES, wedge_codebook_16_hgtw, wedge_signflip_lookup[BLOCK_16X32],
288
    wedge_masks[BLOCK_16X32] },
289
  { MAX_WEDGE_TYPES, wedge_codebook_16_hltw, wedge_signflip_lookup[BLOCK_32X16],
290
    wedge_masks[BLOCK_32X16] },
291
  { MAX_WEDGE_TYPES, wedge_codebook_16_heqw, wedge_signflip_lookup[BLOCK_32X32],
292
    wedge_masks[BLOCK_32X32] },
293
  { 0, NULL, NULL, NULL },
294
  { 0, NULL, NULL, NULL },
295
  { 0, NULL, NULL, NULL },
296
  { 0, NULL, NULL, NULL },
297
  { 0, NULL, NULL, NULL },
298
  { 0, NULL, NULL, NULL },
299
  { 0, NULL, NULL, NULL },
300
  { 0, NULL, NULL, NULL },
301
  { MAX_WEDGE_TYPES, wedge_codebook_16_hgtw, wedge_signflip_lookup[BLOCK_8X32],
302
    wedge_masks[BLOCK_8X32] },
303
  { MAX_WEDGE_TYPES, wedge_codebook_16_hltw, wedge_signflip_lookup[BLOCK_32X8],
304
    wedge_masks[BLOCK_32X8] },
305
  { 0, NULL, NULL, NULL },
306
  { 0, NULL, NULL, NULL },
307
};
308
309
static const uint8_t *get_wedge_mask_inplace(int wedge_index, int neg,
310
864
                                             BLOCK_SIZE sb_type) {
311
864
  const uint8_t *master;
312
864
  const int bh = block_size_high[sb_type];
313
864
  const int bw = block_size_wide[sb_type];
314
864
  const wedge_code_type *a =
315
864
      av1_wedge_params_lookup[sb_type].codebook + wedge_index;
316
864
  int woff, hoff;
317
864
  const uint8_t wsignflip =
318
864
      av1_wedge_params_lookup[sb_type].signflip[wedge_index];
319
320
864
  assert(wedge_index >= 0 && wedge_index < get_wedge_types_lookup(sb_type));
321
864
  woff = (a->x_offset * bw) >> 3;
322
864
  hoff = (a->y_offset * bh) >> 3;
323
864
  master = wedge_mask_obl[neg ^ wsignflip][a->direction] +
324
864
           MASK_MASTER_STRIDE * (MASK_MASTER_SIZE / 2 - hoff) +
325
864
           MASK_MASTER_SIZE / 2 - woff;
326
864
  return master;
327
864
}
328
329
const uint8_t *av1_get_compound_type_mask(
330
189
    const INTERINTER_COMPOUND_DATA *const comp_data, BLOCK_SIZE sb_type) {
331
189
  (void)sb_type;
332
189
  switch (comp_data->type) {
333
123
    case COMPOUND_WEDGE:
334
123
      return av1_get_contiguous_soft_mask(comp_data->wedge_index,
335
123
                                          comp_data->wedge_sign, sb_type);
336
66
    default: return comp_data->seg_mask;
337
189
  }
338
189
}
339
340
static AOM_INLINE void diffwtd_mask_d16(
341
    uint8_t *mask, int which_inverse, int mask_base, const CONV_BUF_TYPE *src0,
342
    int src0_stride, const CONV_BUF_TYPE *src1, int src1_stride, int h, int w,
343
30
    ConvolveParams *conv_params, int bd) {
344
30
  int round =
345
30
      2 * FILTER_BITS - conv_params->round_0 - conv_params->round_1 + (bd - 8);
346
30
  int i, j, m, diff;
347
286
  for (i = 0; i < h; ++i) {
348
3.13k
    for (j = 0; j < w; ++j) {
349
2.88k
      diff = abs(src0[i * src0_stride + j] - src1[i * src1_stride + j]);
350
2.88k
      diff = ROUND_POWER_OF_TWO(diff, round);
351
2.88k
      m = clamp(mask_base + (diff / DIFF_FACTOR), 0, AOM_BLEND_A64_MAX_ALPHA);
352
2.88k
      mask[i * w + j] = which_inverse ? AOM_BLEND_A64_MAX_ALPHA - m : m;
353
2.88k
    }
354
256
  }
355
30
}
356
357
void av1_build_compound_diffwtd_mask_d16_c(
358
    uint8_t *mask, DIFFWTD_MASK_TYPE mask_type, const CONV_BUF_TYPE *src0,
359
    int src0_stride, const CONV_BUF_TYPE *src1, int src1_stride, int h, int w,
360
30
    ConvolveParams *conv_params, int bd) {
361
30
  switch (mask_type) {
362
14
    case DIFFWTD_38:
363
14
      diffwtd_mask_d16(mask, 0, 38, src0, src0_stride, src1, src1_stride, h, w,
364
14
                       conv_params, bd);
365
14
      break;
366
16
    case DIFFWTD_38_INV:
367
16
      diffwtd_mask_d16(mask, 1, 38, src0, src0_stride, src1, src1_stride, h, w,
368
16
                       conv_params, bd);
369
16
      break;
370
0
    default: assert(0);
371
30
  }
372
30
}
373
374
static AOM_INLINE void diffwtd_mask(uint8_t *mask, int which_inverse,
375
                                    int mask_base, const uint8_t *src0,
376
                                    int src0_stride, const uint8_t *src1,
377
0
                                    int src1_stride, int h, int w) {
378
0
  int i, j, m, diff;
379
0
  for (i = 0; i < h; ++i) {
380
0
    for (j = 0; j < w; ++j) {
381
0
      diff =
382
0
          abs((int)src0[i * src0_stride + j] - (int)src1[i * src1_stride + j]);
383
0
      m = clamp(mask_base + (diff / DIFF_FACTOR), 0, AOM_BLEND_A64_MAX_ALPHA);
384
0
      mask[i * w + j] = which_inverse ? AOM_BLEND_A64_MAX_ALPHA - m : m;
385
0
    }
386
0
  }
387
0
}
388
389
void av1_build_compound_diffwtd_mask_c(uint8_t *mask,
390
                                       DIFFWTD_MASK_TYPE mask_type,
391
                                       const uint8_t *src0, int src0_stride,
392
                                       const uint8_t *src1, int src1_stride,
393
0
                                       int h, int w) {
394
0
  switch (mask_type) {
395
0
    case DIFFWTD_38:
396
0
      diffwtd_mask(mask, 0, 38, src0, src0_stride, src1, src1_stride, h, w);
397
0
      break;
398
0
    case DIFFWTD_38_INV:
399
0
      diffwtd_mask(mask, 1, 38, src0, src0_stride, src1, src1_stride, h, w);
400
0
      break;
401
0
    default: assert(0);
402
0
  }
403
0
}
404
405
static AOM_FORCE_INLINE void diffwtd_mask_highbd(
406
    uint8_t *mask, int which_inverse, int mask_base, const uint16_t *src0,
407
    int src0_stride, const uint16_t *src1, int src1_stride, int h, int w,
408
0
    const unsigned int bd) {
409
0
  assert(bd >= 8);
410
0
  if (bd == 8) {
411
0
    if (which_inverse) {
412
0
      for (int i = 0; i < h; ++i) {
413
0
        for (int j = 0; j < w; ++j) {
414
0
          int diff = abs((int)src0[j] - (int)src1[j]) / DIFF_FACTOR;
415
0
          unsigned int m = negative_to_zero(mask_base + diff);
416
0
          m = AOMMIN(m, AOM_BLEND_A64_MAX_ALPHA);
417
0
          mask[j] = AOM_BLEND_A64_MAX_ALPHA - m;
418
0
        }
419
0
        src0 += src0_stride;
420
0
        src1 += src1_stride;
421
0
        mask += w;
422
0
      }
423
0
    } else {
424
0
      for (int i = 0; i < h; ++i) {
425
0
        for (int j = 0; j < w; ++j) {
426
0
          int diff = abs((int)src0[j] - (int)src1[j]) / DIFF_FACTOR;
427
0
          unsigned int m = negative_to_zero(mask_base + diff);
428
0
          m = AOMMIN(m, AOM_BLEND_A64_MAX_ALPHA);
429
0
          mask[j] = m;
430
0
        }
431
0
        src0 += src0_stride;
432
0
        src1 += src1_stride;
433
0
        mask += w;
434
0
      }
435
0
    }
436
0
  } else {
437
0
    const unsigned int bd_shift = bd - 8;
438
0
    if (which_inverse) {
439
0
      for (int i = 0; i < h; ++i) {
440
0
        for (int j = 0; j < w; ++j) {
441
0
          int diff =
442
0
              (abs((int)src0[j] - (int)src1[j]) >> bd_shift) / DIFF_FACTOR;
443
0
          unsigned int m = negative_to_zero(mask_base + diff);
444
0
          m = AOMMIN(m, AOM_BLEND_A64_MAX_ALPHA);
445
0
          mask[j] = AOM_BLEND_A64_MAX_ALPHA - m;
446
0
        }
447
0
        src0 += src0_stride;
448
0
        src1 += src1_stride;
449
0
        mask += w;
450
0
      }
451
0
    } else {
452
0
      for (int i = 0; i < h; ++i) {
453
0
        for (int j = 0; j < w; ++j) {
454
0
          int diff =
455
0
              (abs((int)src0[j] - (int)src1[j]) >> bd_shift) / DIFF_FACTOR;
456
0
          unsigned int m = negative_to_zero(mask_base + diff);
457
0
          m = AOMMIN(m, AOM_BLEND_A64_MAX_ALPHA);
458
0
          mask[j] = m;
459
0
        }
460
0
        src0 += src0_stride;
461
0
        src1 += src1_stride;
462
0
        mask += w;
463
0
      }
464
0
    }
465
0
  }
466
0
}
467
468
void av1_build_compound_diffwtd_mask_highbd_c(
469
    uint8_t *mask, DIFFWTD_MASK_TYPE mask_type, const uint8_t *src0,
470
    int src0_stride, const uint8_t *src1, int src1_stride, int h, int w,
471
0
    int bd) {
472
0
  switch (mask_type) {
473
0
    case DIFFWTD_38:
474
0
      diffwtd_mask_highbd(mask, 0, 38, CONVERT_TO_SHORTPTR(src0), src0_stride,
475
0
                          CONVERT_TO_SHORTPTR(src1), src1_stride, h, w, bd);
476
0
      break;
477
0
    case DIFFWTD_38_INV:
478
0
      diffwtd_mask_highbd(mask, 1, 38, CONVERT_TO_SHORTPTR(src0), src0_stride,
479
0
                          CONVERT_TO_SHORTPTR(src1), src1_stride, h, w, bd);
480
0
      break;
481
0
    default: assert(0);
482
0
  }
483
0
}
484
485
3
static AOM_INLINE void init_wedge_master_masks() {
486
3
  int i, j;
487
3
  const int w = MASK_MASTER_SIZE;
488
3
  const int h = MASK_MASTER_SIZE;
489
3
  const int stride = MASK_MASTER_STRIDE;
490
  // Note: index [0] stores the masters, and [1] its complement.
491
  // Generate prototype by shifting the masters
492
3
  int shift = h / 4;
493
99
  for (i = 0; i < h; i += 2) {
494
96
    shift_copy(wedge_master_oblique_even,
495
96
               &wedge_mask_obl[0][WEDGE_OBLIQUE63][i * stride], shift,
496
96
               MASK_MASTER_SIZE);
497
96
    shift--;
498
96
    shift_copy(wedge_master_oblique_odd,
499
96
               &wedge_mask_obl[0][WEDGE_OBLIQUE63][(i + 1) * stride], shift,
500
96
               MASK_MASTER_SIZE);
501
96
    memcpy(&wedge_mask_obl[0][WEDGE_VERTICAL][i * stride],
502
96
           wedge_master_vertical,
503
96
           MASK_MASTER_SIZE * sizeof(wedge_master_vertical[0]));
504
96
    memcpy(&wedge_mask_obl[0][WEDGE_VERTICAL][(i + 1) * stride],
505
96
           wedge_master_vertical,
506
96
           MASK_MASTER_SIZE * sizeof(wedge_master_vertical[0]));
507
96
  }
508
509
195
  for (i = 0; i < h; ++i) {
510
12.4k
    for (j = 0; j < w; ++j) {
511
12.2k
      const int msk = wedge_mask_obl[0][WEDGE_OBLIQUE63][i * stride + j];
512
12.2k
      wedge_mask_obl[0][WEDGE_OBLIQUE27][j * stride + i] = msk;
513
12.2k
      wedge_mask_obl[0][WEDGE_OBLIQUE117][i * stride + w - 1 - j] =
514
12.2k
          wedge_mask_obl[0][WEDGE_OBLIQUE153][(w - 1 - j) * stride + i] =
515
12.2k
              (1 << WEDGE_WEIGHT_BITS) - msk;
516
12.2k
      wedge_mask_obl[1][WEDGE_OBLIQUE63][i * stride + j] =
517
12.2k
          wedge_mask_obl[1][WEDGE_OBLIQUE27][j * stride + i] =
518
12.2k
              (1 << WEDGE_WEIGHT_BITS) - msk;
519
12.2k
      wedge_mask_obl[1][WEDGE_OBLIQUE117][i * stride + w - 1 - j] =
520
12.2k
          wedge_mask_obl[1][WEDGE_OBLIQUE153][(w - 1 - j) * stride + i] = msk;
521
12.2k
      const int mskx = wedge_mask_obl[0][WEDGE_VERTICAL][i * stride + j];
522
12.2k
      wedge_mask_obl[0][WEDGE_HORIZONTAL][j * stride + i] = mskx;
523
12.2k
      wedge_mask_obl[1][WEDGE_VERTICAL][i * stride + j] =
524
12.2k
          wedge_mask_obl[1][WEDGE_HORIZONTAL][j * stride + i] =
525
12.2k
              (1 << WEDGE_WEIGHT_BITS) - mskx;
526
12.2k
    }
527
192
  }
528
3
}
529
530
3
static AOM_INLINE void init_wedge_masks() {
531
3
  uint8_t *dst = wedge_mask_buf;
532
3
  BLOCK_SIZE bsize;
533
3
  memset(wedge_masks, 0, sizeof(wedge_masks));
534
69
  for (bsize = BLOCK_4X4; bsize < BLOCK_SIZES_ALL; ++bsize) {
535
66
    const wedge_params_type *wedge_params = &av1_wedge_params_lookup[bsize];
536
66
    const int wtypes = wedge_params->wedge_types;
537
66
    if (wtypes == 0) continue;
538
27
    const uint8_t *mask;
539
27
    const int bw = block_size_wide[bsize];
540
27
    const int bh = block_size_high[bsize];
541
27
    int w;
542
459
    for (w = 0; w < wtypes; ++w) {
543
432
      mask = get_wedge_mask_inplace(w, 0, bsize);
544
432
      aom_convolve_copy(mask, MASK_MASTER_STRIDE, dst, bw /* dst_stride */, bw,
545
432
                        bh);
546
432
      wedge_params->masks[0][w] = dst;
547
432
      dst += bw * bh;
548
549
432
      mask = get_wedge_mask_inplace(w, 1, bsize);
550
432
      aom_convolve_copy(mask, MASK_MASTER_STRIDE, dst, bw /* dst_stride */, bw,
551
432
                        bh);
552
432
      wedge_params->masks[1][w] = dst;
553
432
      dst += bw * bh;
554
432
    }
555
27
    assert(sizeof(wedge_mask_buf) >= (size_t)(dst - wedge_mask_buf));
556
27
  }
557
3
}
558
559
/* clang-format off */
560
static const uint8_t ii_weights1d[MAX_SB_SIZE] = {
561
  60, 58, 56, 54, 52, 50, 48, 47, 45, 44, 42, 41, 39, 38, 37, 35, 34, 33, 32,
562
  31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 22, 21, 20, 19, 19, 18, 18, 17, 16,
563
  16, 15, 15, 14, 14, 13, 13, 12, 12, 12, 11, 11, 10, 10, 10,  9,  9,  9,  8,
564
  8,  8,  8,  7,  7,  7,  7,  6,  6,  6,  6,  6,  5,  5,  5,  5,  5,  4,  4,
565
  4,  4,  4,  4,  4,  4,  3,  3,  3,  3,  3,  3,  3,  3,  3,  2,  2,  2,  2,
566
  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  1,  1,  1,  1,  1,  1,  1,  1,
567
  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1
568
};
569
static uint8_t ii_size_scales[BLOCK_SIZES_ALL] = {
570
    32, 16, 16, 16, 8, 8, 8, 4,
571
    4,  4,  2,  2,  2, 1, 1, 1,
572
    8,  8,  4,  4,  2, 2
573
};
574
/* clang-format on */
575
576
static AOM_INLINE void build_smooth_interintra_mask(uint8_t *mask, int stride,
577
                                                    BLOCK_SIZE plane_bsize,
578
211
                                                    INTERINTRA_MODE mode) {
579
211
  int i, j;
580
211
  const int bw = block_size_wide[plane_bsize];
581
211
  const int bh = block_size_high[plane_bsize];
582
211
  const int size_scale = ii_size_scales[plane_bsize];
583
584
211
  switch (mode) {
585
55
    case II_V_PRED:
586
747
      for (i = 0; i < bh; ++i) {
587
692
        memset(mask, ii_weights1d[i * size_scale], bw * sizeof(mask[0]));
588
692
        mask += stride;
589
692
      }
590
55
      break;
591
592
57
    case II_H_PRED:
593
789
      for (i = 0; i < bh; ++i) {
594
12.7k
        for (j = 0; j < bw; ++j) mask[j] = ii_weights1d[j * size_scale];
595
732
        mask += stride;
596
732
      }
597
57
      break;
598
599
51
    case II_SMOOTH_PRED:
600
751
      for (i = 0; i < bh; ++i) {
601
12.5k
        for (j = 0; j < bw; ++j)
602
11.8k
          mask[j] = ii_weights1d[(i < j ? i : j) * size_scale];
603
700
        mask += stride;
604
700
      }
605
51
      break;
606
607
48
    case II_DC_PRED:
608
48
    default:
609
700
      for (i = 0; i < bh; ++i) {
610
652
        memset(mask, 32, bw * sizeof(mask[0]));
611
652
        mask += stride;
612
652
      }
613
48
      break;
614
211
  }
615
211
}
616
617
3
static AOM_INLINE void init_smooth_interintra_masks() {
618
15
  for (int m = 0; m < INTERINTRA_MODES; ++m) {
619
276
    for (int bs = 0; bs < BLOCK_SIZES_ALL; ++bs) {
620
264
      const int bw = block_size_wide[bs];
621
264
      const int bh = block_size_high[bs];
622
264
      if (bw > MAX_WEDGE_SIZE || bh > MAX_WEDGE_SIZE) continue;
623
168
      build_smooth_interintra_mask(smooth_interintra_mask_buf[m][bs], bw, bs,
624
168
                                   m);
625
168
    }
626
12
  }
627
3
}
628
629
// Equation of line: f(x, y) = a[0]*(x - a[2]*w/8) + a[1]*(y - a[3]*h/8) = 0
630
3
void av1_init_wedge_masks() {
631
3
  init_wedge_master_masks();
632
3
  init_wedge_masks();
633
3
  init_smooth_interintra_masks();
634
3
}
635
636
static AOM_INLINE void build_masked_compound_no_round(
637
    uint8_t *dst, int dst_stride, const CONV_BUF_TYPE *src0, int src0_stride,
638
    const CONV_BUF_TYPE *src1, int src1_stride,
639
    const INTERINTER_COMPOUND_DATA *const comp_data, BLOCK_SIZE sb_type, int h,
640
189
    int w, InterPredParams *inter_pred_params) {
641
189
  const int ssy = inter_pred_params->subsampling_y;
642
189
  const int ssx = inter_pred_params->subsampling_x;
643
189
  const uint8_t *mask = av1_get_compound_type_mask(comp_data, sb_type);
644
189
  const int mask_stride = block_size_wide[sb_type];
645
189
#if CONFIG_AV1_HIGHBITDEPTH
646
189
  if (inter_pred_params->use_hbd_buf) {
647
48
    aom_highbd_blend_a64_d16_mask(dst, dst_stride, src0, src0_stride, src1,
648
48
                                  src1_stride, mask, mask_stride, w, h, ssx,
649
48
                                  ssy, &inter_pred_params->conv_params,
650
48
                                  inter_pred_params->bit_depth);
651
141
  } else {
652
141
    aom_lowbd_blend_a64_d16_mask(dst, dst_stride, src0, src0_stride, src1,
653
141
                                 src1_stride, mask, mask_stride, w, h, ssx, ssy,
654
141
                                 &inter_pred_params->conv_params);
655
141
  }
656
#else
657
  aom_lowbd_blend_a64_d16_mask(dst, dst_stride, src0, src0_stride, src1,
658
                               src1_stride, mask, mask_stride, w, h, ssx, ssy,
659
                               &inter_pred_params->conv_params);
660
#endif
661
189
}
662
663
static void make_masked_inter_predictor(const uint8_t *pre, int pre_stride,
664
                                        uint8_t *dst, int dst_stride,
665
                                        InterPredParams *inter_pred_params,
666
189
                                        const SubpelParams *subpel_params) {
667
189
  const INTERINTER_COMPOUND_DATA *comp_data = &inter_pred_params->mask_comp;
668
189
  BLOCK_SIZE sb_type = inter_pred_params->sb_type;
669
670
  // We're going to call av1_make_inter_predictor to generate a prediction into
671
  // a temporary buffer, then will blend that temporary buffer with that from
672
  // the other reference.
673
189
  DECLARE_ALIGNED(32, uint8_t, tmp_buf[2 * MAX_SB_SQUARE]);
674
189
  uint8_t *tmp_dst =
675
189
      inter_pred_params->use_hbd_buf ? CONVERT_TO_BYTEPTR(tmp_buf) : tmp_buf;
676
677
189
  const int tmp_buf_stride = MAX_SB_SIZE;
678
189
  CONV_BUF_TYPE *org_dst = inter_pred_params->conv_params.dst;
679
189
  int org_dst_stride = inter_pred_params->conv_params.dst_stride;
680
189
  CONV_BUF_TYPE *tmp_buf16 = (CONV_BUF_TYPE *)tmp_buf;
681
189
  inter_pred_params->conv_params.dst = tmp_buf16;
682
189
  inter_pred_params->conv_params.dst_stride = tmp_buf_stride;
683
189
  assert(inter_pred_params->conv_params.do_average == 0);
684
685
  // This will generate a prediction in tmp_buf for the second reference
686
189
  av1_make_inter_predictor(pre, pre_stride, tmp_dst, MAX_SB_SIZE,
687
189
                           inter_pred_params, subpel_params);
688
689
189
  if (!inter_pred_params->conv_params.plane &&
690
189
      comp_data->type == COMPOUND_DIFFWTD) {
691
30
    av1_build_compound_diffwtd_mask_d16(
692
30
        comp_data->seg_mask, comp_data->mask_type, org_dst, org_dst_stride,
693
30
        tmp_buf16, tmp_buf_stride, inter_pred_params->block_height,
694
30
        inter_pred_params->block_width, &inter_pred_params->conv_params,
695
30
        inter_pred_params->bit_depth);
696
30
  }
697
189
  build_masked_compound_no_round(
698
189
      dst, dst_stride, org_dst, org_dst_stride, tmp_buf16, tmp_buf_stride,
699
189
      comp_data, sb_type, inter_pred_params->block_height,
700
189
      inter_pred_params->block_width, inter_pred_params);
701
189
}
702
703
void av1_build_one_inter_predictor(
704
    uint8_t *dst, int dst_stride, const MV *const src_mv,
705
    InterPredParams *inter_pred_params, MACROBLOCKD *xd, int mi_x, int mi_y,
706
180k
    int ref, uint8_t **mc_buf, CalcSubpelParamsFunc calc_subpel_params_func) {
707
180k
  SubpelParams subpel_params;
708
180k
  uint8_t *src;
709
180k
  int src_stride;
710
180k
  calc_subpel_params_func(src_mv, inter_pred_params, xd, mi_x, mi_y, ref,
711
180k
                          mc_buf, &src, &subpel_params, &src_stride);
712
713
180k
  if (inter_pred_params->comp_mode == UNIFORM_SINGLE ||
714
180k
      inter_pred_params->comp_mode == UNIFORM_COMP) {
715
180k
    av1_make_inter_predictor(src, src_stride, dst, dst_stride,
716
180k
                             inter_pred_params, &subpel_params);
717
180k
  } else {
718
189
    make_masked_inter_predictor(src, src_stride, dst, dst_stride,
719
189
                                inter_pred_params, &subpel_params);
720
189
  }
721
180k
}
722
723
void av1_dist_wtd_comp_weight_assign(const AV1_COMMON *cm,
724
                                     const MB_MODE_INFO *mbmi, int *fwd_offset,
725
                                     int *bck_offset,
726
                                     int *use_dist_wtd_comp_avg,
727
179k
                                     int is_compound) {
728
179k
  assert(fwd_offset != NULL && bck_offset != NULL);
729
179k
  if (!is_compound || mbmi->compound_idx) {
730
178k
    *fwd_offset = 8;
731
178k
    *bck_offset = 8;
732
178k
    *use_dist_wtd_comp_avg = 0;
733
178k
    return;
734
178k
  }
735
736
1.40k
  *use_dist_wtd_comp_avg = 1;
737
1.40k
  const RefCntBuffer *const bck_buf = get_ref_frame_buf(cm, mbmi->ref_frame[0]);
738
1.40k
  const RefCntBuffer *const fwd_buf = get_ref_frame_buf(cm, mbmi->ref_frame[1]);
739
1.40k
  const int cur_frame_index = cm->cur_frame->order_hint;
740
1.40k
  int bck_frame_index = 0, fwd_frame_index = 0;
741
742
1.40k
  if (bck_buf != NULL) bck_frame_index = bck_buf->order_hint;
743
1.40k
  if (fwd_buf != NULL) fwd_frame_index = fwd_buf->order_hint;
744
745
1.40k
  int d0 = clamp(abs(get_relative_dist(&cm->seq_params->order_hint_info,
746
1.40k
                                       fwd_frame_index, cur_frame_index)),
747
1.40k
                 0, MAX_FRAME_DISTANCE);
748
1.40k
  int d1 = clamp(abs(get_relative_dist(&cm->seq_params->order_hint_info,
749
1.40k
                                       cur_frame_index, bck_frame_index)),
750
1.40k
                 0, MAX_FRAME_DISTANCE);
751
752
1.40k
  const int order = d0 <= d1;
753
754
1.40k
  if (d0 == 0 || d1 == 0) {
755
94
    *fwd_offset = quant_dist_lookup_table[3][order];
756
94
    *bck_offset = quant_dist_lookup_table[3][1 - order];
757
94
    return;
758
94
  }
759
760
1.31k
  int i;
761
1.39k
  for (i = 0; i < 3; ++i) {
762
1.37k
    int c0 = quant_dist_weight[i][order];
763
1.37k
    int c1 = quant_dist_weight[i][!order];
764
1.37k
    int d0_c0 = d0 * c0;
765
1.37k
    int d1_c1 = d1 * c1;
766
1.37k
    if ((d0 > d1 && d0_c0 < d1_c1) || (d0 <= d1 && d0_c0 > d1_c1)) break;
767
1.37k
  }
768
769
1.31k
  *fwd_offset = quant_dist_lookup_table[i][order];
770
1.31k
  *bck_offset = quant_dist_lookup_table[i][1 - order];
771
1.31k
}
772
773
// True if the following hold:
774
//  1. Not intrabc and not build_for_obmc
775
//  2. At least one dimension is size 4 with subsampling
776
//  3. If sub-sampled, none of the previous blocks around the sub-sample
777
//     are intrabc or inter-blocks
778
static bool is_sub8x8_inter(const MACROBLOCKD *xd, int plane, BLOCK_SIZE bsize,
779
178k
                            int is_intrabc, int build_for_obmc) {
780
178k
  if (is_intrabc || build_for_obmc) {
781
167k
    return false;
782
167k
  }
783
784
10.7k
  const struct macroblockd_plane *const pd = &xd->plane[plane];
785
10.7k
  const int ss_x = pd->subsampling_x;
786
10.7k
  const int ss_y = pd->subsampling_y;
787
10.7k
  const int is_sub4_x = (block_size_wide[bsize] == 4) && ss_x;
788
10.7k
  const int is_sub4_y = (block_size_high[bsize] == 4) && ss_y;
789
10.7k
  if (!is_sub4_x && !is_sub4_y) {
790
10.5k
    return false;
791
10.5k
  }
792
793
  // For sub8x8 chroma blocks, we may be covering more than one luma block's
794
  // worth of pixels. Thus (mi_x, mi_y) may not be the correct coordinates for
795
  // the top-left corner of the prediction source - the correct top-left corner
796
  // is at (pre_x, pre_y).
797
226
  const int row_start = is_sub4_y ? -1 : 0;
798
226
  const int col_start = is_sub4_x ? -1 : 0;
799
800
610
  for (int row = row_start; row <= 0; ++row) {
801
1.10k
    for (int col = col_start; col <= 0; ++col) {
802
722
      const MB_MODE_INFO *this_mbmi = xd->mi[row * xd->mi_stride + col];
803
722
      if (!is_inter_block(this_mbmi)) return false;
804
698
      if (is_intrabc_block(this_mbmi)) return false;
805
698
    }
806
408
  }
807
202
  return true;
808
226
}
809
810
static void build_inter_predictors_sub8x8(
811
    const AV1_COMMON *cm, MACROBLOCKD *xd, int plane, const MB_MODE_INFO *mi,
812
    int mi_x, int mi_y, uint8_t **mc_buf,
813
202
    CalcSubpelParamsFunc calc_subpel_params_func) {
814
202
  const BLOCK_SIZE bsize = mi->bsize;
815
202
  struct macroblockd_plane *const pd = &xd->plane[plane];
816
202
  const bool ss_x = pd->subsampling_x;
817
202
  const bool ss_y = pd->subsampling_y;
818
202
  const int b4_w = block_size_wide[bsize] >> ss_x;
819
202
  const int b4_h = block_size_high[bsize] >> ss_y;
820
202
  const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize, ss_x, ss_y);
821
202
  const int b8_w = block_size_wide[plane_bsize];
822
202
  const int b8_h = block_size_high[plane_bsize];
823
202
  const int is_compound = has_second_ref(mi);
824
202
  assert(!is_compound);
825
202
  assert(!is_intrabc_block(mi));
826
827
  // For sub8x8 chroma blocks, we may be covering more than one luma block's
828
  // worth of pixels. Thus (mi_x, mi_y) may not be the correct coordinates for
829
  // the top-left corner of the prediction source - the correct top-left corner
830
  // is at (pre_x, pre_y).
831
202
  const int row_start = (block_size_high[bsize] == 4) && ss_y ? -1 : 0;
832
202
  const int col_start = (block_size_wide[bsize] == 4) && ss_x ? -1 : 0;
833
202
  const int pre_x = (mi_x + MI_SIZE * col_start) >> ss_x;
834
202
  const int pre_y = (mi_y + MI_SIZE * row_start) >> ss_y;
835
836
202
  int row = row_start;
837
576
  for (int y = 0; y < b8_h; y += b4_h) {
838
374
    int col = col_start;
839
1.05k
    for (int x = 0; x < b8_w; x += b4_w) {
840
676
      MB_MODE_INFO *this_mbmi = xd->mi[row * xd->mi_stride + col];
841
676
      struct buf_2d *const dst_buf = &pd->dst;
842
676
      uint8_t *dst = dst_buf->buf + dst_buf->stride * y + x;
843
676
      int ref = 0;
844
676
      const RefCntBuffer *ref_buf =
845
676
          get_ref_frame_buf(cm, this_mbmi->ref_frame[ref]);
846
676
      const struct scale_factors *ref_scale_factors =
847
676
          get_ref_scale_factors_const(cm, this_mbmi->ref_frame[ref]);
848
676
      const struct scale_factors *const sf = ref_scale_factors;
849
676
      const struct buf_2d pre_buf = {
850
676
        NULL,
851
676
        (plane == 1) ? ref_buf->buf.u_buffer : ref_buf->buf.v_buffer,
852
676
        ref_buf->buf.uv_crop_width,
853
676
        ref_buf->buf.uv_crop_height,
854
676
        ref_buf->buf.uv_stride,
855
676
      };
856
857
676
      const MV mv = this_mbmi->mv[ref].as_mv;
858
859
676
      InterPredParams inter_pred_params;
860
676
      av1_init_inter_params(&inter_pred_params, b4_w, b4_h, pre_y + y,
861
676
                            pre_x + x, pd->subsampling_x, pd->subsampling_y,
862
676
                            xd->bd, is_cur_buf_hbd(xd), mi->use_intrabc, sf,
863
676
                            &pre_buf, this_mbmi->interp_filters);
864
676
      inter_pred_params.conv_params =
865
676
          get_conv_params_no_round(ref, plane, NULL, 0, is_compound, xd->bd);
866
867
676
      av1_build_one_inter_predictor(dst, dst_buf->stride, &mv,
868
676
                                    &inter_pred_params, xd, mi_x + x, mi_y + y,
869
676
                                    ref, mc_buf, calc_subpel_params_func);
870
871
676
      ++col;
872
676
    }
873
374
    ++row;
874
374
  }
875
202
}
876
877
static void build_inter_predictors_8x8_and_bigger(
878
    const AV1_COMMON *cm, MACROBLOCKD *xd, int plane, const MB_MODE_INFO *mi,
879
    int build_for_obmc, int bw, int bh, int mi_x, int mi_y, uint8_t **mc_buf,
880
178k
    CalcSubpelParamsFunc calc_subpel_params_func) {
881
178k
  const int is_compound = has_second_ref(mi);
882
178k
  const int is_intrabc = is_intrabc_block(mi);
883
178k
  assert(IMPLIES(is_intrabc, !is_compound));
884
178k
  struct macroblockd_plane *const pd = &xd->plane[plane];
885
178k
  struct buf_2d *const dst_buf = &pd->dst;
886
178k
  uint8_t *const dst = dst_buf->buf;
887
888
178k
  int is_global[2] = { 0, 0 };
889
358k
  for (int ref = 0; ref < 1 + is_compound; ++ref) {
890
179k
    const WarpedMotionParams *const wm = &xd->global_motion[mi->ref_frame[ref]];
891
179k
    is_global[ref] = is_global_mv_block(mi, wm->wmtype);
892
179k
  }
893
894
178k
  const BLOCK_SIZE bsize = mi->bsize;
895
178k
  const int ss_x = pd->subsampling_x;
896
178k
  const int ss_y = pd->subsampling_y;
897
178k
  const int row_start =
898
178k
      (block_size_high[bsize] == 4) && ss_y && !build_for_obmc ? -1 : 0;
899
178k
  const int col_start =
900
178k
      (block_size_wide[bsize] == 4) && ss_x && !build_for_obmc ? -1 : 0;
901
178k
  const int pre_x = (mi_x + MI_SIZE * col_start) >> ss_x;
902
178k
  const int pre_y = (mi_y + MI_SIZE * row_start) >> ss_y;
903
904
358k
  for (int ref = 0; ref < 1 + is_compound; ++ref) {
905
179k
    const struct scale_factors *const sf =
906
179k
        is_intrabc ? &cm->sf_identity : xd->block_ref_scale_factors[ref];
907
179k
    struct buf_2d *const pre_buf = is_intrabc ? dst_buf : &pd->pre[ref];
908
179k
    const MV mv = mi->mv[ref].as_mv;
909
179k
    const WarpTypesAllowed warp_types = { is_global[ref],
910
179k
                                          mi->motion_mode == WARPED_CAUSAL };
911
912
179k
    InterPredParams inter_pred_params;
913
179k
    av1_init_inter_params(&inter_pred_params, bw, bh, pre_y, pre_x,
914
179k
                          pd->subsampling_x, pd->subsampling_y, xd->bd,
915
179k
                          is_cur_buf_hbd(xd), mi->use_intrabc, sf, pre_buf,
916
179k
                          mi->interp_filters);
917
179k
    if (is_compound) av1_init_comp_mode(&inter_pred_params);
918
179k
    inter_pred_params.conv_params = get_conv_params_no_round(
919
179k
        ref, plane, xd->tmp_conv_dst, MAX_SB_SIZE, is_compound, xd->bd);
920
921
179k
    av1_dist_wtd_comp_weight_assign(
922
179k
        cm, mi, &inter_pred_params.conv_params.fwd_offset,
923
179k
        &inter_pred_params.conv_params.bck_offset,
924
179k
        &inter_pred_params.conv_params.use_dist_wtd_comp_avg, is_compound);
925
926
179k
    if (!build_for_obmc)
927
179k
      av1_init_warp_params(&inter_pred_params, &warp_types, ref, xd, mi);
928
929
179k
    if (is_masked_compound_type(mi->interinter_comp.type)) {
930
378
      inter_pred_params.sb_type = mi->bsize;
931
378
      inter_pred_params.mask_comp = mi->interinter_comp;
932
378
      if (ref == 1) {
933
189
        inter_pred_params.conv_params.do_average = 0;
934
189
        inter_pred_params.comp_mode = MASK_COMP;
935
189
      }
936
      // Assign physical buffer.
937
378
      inter_pred_params.mask_comp.seg_mask = xd->seg_mask;
938
378
    }
939
940
179k
    av1_build_one_inter_predictor(dst, dst_buf->stride, &mv, &inter_pred_params,
941
179k
                                  xd, mi_x, mi_y, ref, mc_buf,
942
179k
                                  calc_subpel_params_func);
943
179k
  }
944
178k
}
945
946
void av1_build_inter_predictors(const AV1_COMMON *cm, MACROBLOCKD *xd,
947
                                int plane, const MB_MODE_INFO *mi,
948
                                int build_for_obmc, int bw, int bh, int mi_x,
949
                                int mi_y, uint8_t **mc_buf,
950
178k
                                CalcSubpelParamsFunc calc_subpel_params_func) {
951
178k
  if (is_sub8x8_inter(xd, plane, mi->bsize, is_intrabc_block(mi),
952
178k
                      build_for_obmc)) {
953
202
    assert(bw < 8 || bh < 8);
954
202
    build_inter_predictors_sub8x8(cm, xd, plane, mi, mi_x, mi_y, mc_buf,
955
202
                                  calc_subpel_params_func);
956
178k
  } else {
957
178k
    build_inter_predictors_8x8_and_bigger(cm, xd, plane, mi, build_for_obmc, bw,
958
178k
                                          bh, mi_x, mi_y, mc_buf,
959
178k
                                          calc_subpel_params_func);
960
178k
  }
961
178k
}
962
void av1_setup_dst_planes(struct macroblockd_plane *planes, BLOCK_SIZE bsize,
963
                          const YV12_BUFFER_CONFIG *src, int mi_row, int mi_col,
964
8.20M
                          const int plane_start, const int plane_end) {
965
  // We use AOMMIN(num_planes, MAX_MB_PLANE) instead of num_planes to quiet
966
  // the static analysis warnings.
967
32.5M
  for (int i = plane_start; i < AOMMIN(plane_end, MAX_MB_PLANE); ++i) {
968
24.3M
    struct macroblockd_plane *const pd = &planes[i];
969
24.3M
    const int is_uv = i > 0;
970
24.3M
    setup_pred_plane(&pd->dst, bsize, src->buffers[i], src->crop_widths[is_uv],
971
24.3M
                     src->crop_heights[is_uv], src->strides[is_uv], mi_row,
972
24.3M
                     mi_col, NULL, pd->subsampling_x, pd->subsampling_y);
973
24.3M
  }
974
8.20M
}
975
976
void av1_setup_pre_planes(MACROBLOCKD *xd, int idx,
977
                          const YV12_BUFFER_CONFIG *src, int mi_row, int mi_col,
978
                          const struct scale_factors *sf,
979
8.60k
                          const int num_planes) {
980
8.60k
  if (src != NULL) {
981
    // We use AOMMIN(num_planes, MAX_MB_PLANE) instead of num_planes to quiet
982
    // the static analysis warnings.
983
21.8k
    for (int i = 0; i < AOMMIN(num_planes, MAX_MB_PLANE); ++i) {
984
13.2k
      struct macroblockd_plane *const pd = &xd->plane[i];
985
13.2k
      const int is_uv = i > 0;
986
13.2k
      setup_pred_plane(&pd->pre[idx], xd->mi[0]->bsize, src->buffers[i],
987
13.2k
                       src->crop_widths[is_uv], src->crop_heights[is_uv],
988
13.2k
                       src->strides[is_uv], mi_row, mi_col, sf,
989
13.2k
                       pd->subsampling_x, pd->subsampling_y);
990
13.2k
    }
991
8.60k
  }
992
8.60k
}
993
994
// obmc_mask_N[overlap_position]
995
static const uint8_t obmc_mask_1[1] = { 64 };
996
DECLARE_ALIGNED(2, static const uint8_t, obmc_mask_2[2]) = { 45, 64 };
997
998
DECLARE_ALIGNED(4, static const uint8_t, obmc_mask_4[4]) = { 39, 50, 59, 64 };
999
1000
static const uint8_t obmc_mask_8[8] = { 36, 42, 48, 53, 57, 61, 64, 64 };
1001
1002
static const uint8_t obmc_mask_16[16] = { 34, 37, 40, 43, 46, 49, 52, 54,
1003
                                          56, 58, 60, 61, 64, 64, 64, 64 };
1004
1005
static const uint8_t obmc_mask_32[32] = { 33, 35, 36, 38, 40, 41, 43, 44,
1006
                                          45, 47, 48, 50, 51, 52, 53, 55,
1007
                                          56, 57, 58, 59, 60, 60, 61, 62,
1008
                                          64, 64, 64, 64, 64, 64, 64, 64 };
1009
1010
static const uint8_t obmc_mask_64[64] = {
1011
  33, 34, 35, 35, 36, 37, 38, 39, 40, 40, 41, 42, 43, 44, 44, 44,
1012
  45, 46, 47, 47, 48, 49, 50, 51, 51, 51, 52, 52, 53, 54, 55, 56,
1013
  56, 56, 57, 57, 58, 58, 59, 60, 60, 60, 60, 60, 61, 62, 62, 62,
1014
  62, 62, 63, 63, 63, 63, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
1015
};
1016
1017
198
const uint8_t *av1_get_obmc_mask(int length) {
1018
198
  switch (length) {
1019
0
    case 1: return obmc_mask_1;
1020
0
    case 2: return obmc_mask_2;
1021
177
    case 4: return obmc_mask_4;
1022
21
    case 8: return obmc_mask_8;
1023
0
    case 16: return obmc_mask_16;
1024
0
    case 32: return obmc_mask_32;
1025
0
    case 64: return obmc_mask_64;
1026
0
    default: assert(0); return NULL;
1027
198
  }
1028
198
}
1029
1030
static INLINE void increment_int_ptr(MACROBLOCKD *xd, int rel_mi_row,
1031
                                     int rel_mi_col, uint8_t op_mi_size,
1032
                                     int dir, MB_MODE_INFO *mi, void *fun_ctxt,
1033
269
                                     const int num_planes) {
1034
269
  (void)xd;
1035
269
  (void)rel_mi_row;
1036
269
  (void)rel_mi_col;
1037
269
  (void)op_mi_size;
1038
269
  (void)dir;
1039
269
  (void)mi;
1040
269
  ++*(int *)fun_ctxt;
1041
269
  (void)num_planes;
1042
269
}
1043
1044
7.33k
void av1_count_overlappable_neighbors(const AV1_COMMON *cm, MACROBLOCKD *xd) {
1045
7.33k
  MB_MODE_INFO *mbmi = xd->mi[0];
1046
1047
7.33k
  mbmi->overlappable_neighbors = 0;
1048
1049
7.33k
  if (!is_motion_variation_allowed_bsize(mbmi->bsize)) return;
1050
1051
2.50k
  foreach_overlappable_nb_above(cm, xd, INT_MAX, increment_int_ptr,
1052
2.50k
                                &mbmi->overlappable_neighbors);
1053
2.50k
  if (mbmi->overlappable_neighbors) return;
1054
2.50k
  foreach_overlappable_nb_left(cm, xd, INT_MAX, increment_int_ptr,
1055
2.50k
                               &mbmi->overlappable_neighbors);
1056
2.50k
}
1057
1058
// HW does not support < 4x4 prediction. To limit the bandwidth requirement, if
1059
// block-size of current plane is smaller than 8x8, always only blend with the
1060
// left neighbor(s) (skip blending with the above side).
1061
#define DISABLE_CHROMA_U8X8_OBMC 0  // 0: one-sided obmc; 1: disable
1062
1063
int av1_skip_u4x4_pred_in_obmc(BLOCK_SIZE bsize,
1064
396
                               const struct macroblockd_plane *pd, int dir) {
1065
396
  assert(is_motion_variation_allowed_bsize(bsize));
1066
1067
396
  const BLOCK_SIZE bsize_plane =
1068
396
      get_plane_block_size(bsize, pd->subsampling_x, pd->subsampling_y);
1069
396
  switch (bsize_plane) {
1070
#if DISABLE_CHROMA_U8X8_OBMC
1071
    case BLOCK_4X4:
1072
    case BLOCK_8X4:
1073
    case BLOCK_4X8: return 1; break;
1074
#else
1075
0
    case BLOCK_4X4:
1076
0
    case BLOCK_8X4:
1077
0
    case BLOCK_4X8: return dir == 0; break;
1078
0
#endif
1079
396
    default: return 0;
1080
396
  }
1081
396
}
1082
1083
66
void av1_modify_neighbor_predictor_for_obmc(MB_MODE_INFO *mbmi) {
1084
66
  mbmi->ref_frame[1] = NONE_FRAME;
1085
66
  mbmi->interinter_comp.type = COMPOUND_AVERAGE;
1086
1087
66
  return;
1088
66
}
1089
1090
struct obmc_inter_pred_ctxt {
1091
  uint8_t **adjacent;
1092
  int *adjacent_stride;
1093
};
1094
1095
static INLINE void build_obmc_inter_pred_above(
1096
    MACROBLOCKD *xd, int rel_mi_row, int rel_mi_col, uint8_t op_mi_size,
1097
0
    int dir, MB_MODE_INFO *above_mi, void *fun_ctxt, const int num_planes) {
1098
0
  (void)above_mi;
1099
0
  (void)rel_mi_row;
1100
0
  (void)dir;
1101
0
  struct obmc_inter_pred_ctxt *ctxt = (struct obmc_inter_pred_ctxt *)fun_ctxt;
1102
0
  const BLOCK_SIZE bsize = xd->mi[0]->bsize;
1103
0
  const int overlap =
1104
0
      AOMMIN(block_size_high[bsize], block_size_high[BLOCK_64X64]) >> 1;
1105
1106
0
  for (int plane = 0; plane < num_planes; ++plane) {
1107
0
    const struct macroblockd_plane *pd = &xd->plane[plane];
1108
0
    const int bw = (op_mi_size * MI_SIZE) >> pd->subsampling_x;
1109
0
    const int bh = overlap >> pd->subsampling_y;
1110
0
    const int plane_col = (rel_mi_col * MI_SIZE) >> pd->subsampling_x;
1111
1112
0
    if (av1_skip_u4x4_pred_in_obmc(bsize, pd, 0)) continue;
1113
1114
0
    const int dst_stride = pd->dst.stride;
1115
0
    uint8_t *const dst = &pd->dst.buf[plane_col];
1116
0
    const int tmp_stride = ctxt->adjacent_stride[plane];
1117
0
    const uint8_t *const tmp = &ctxt->adjacent[plane][plane_col];
1118
0
    const uint8_t *const mask = av1_get_obmc_mask(bh);
1119
0
#if CONFIG_AV1_HIGHBITDEPTH
1120
0
    const int is_hbd = is_cur_buf_hbd(xd);
1121
0
    if (is_hbd)
1122
0
      aom_highbd_blend_a64_vmask(dst, dst_stride, dst, dst_stride, tmp,
1123
0
                                 tmp_stride, mask, bw, bh, xd->bd);
1124
0
    else
1125
0
      aom_blend_a64_vmask(dst, dst_stride, dst, dst_stride, tmp, tmp_stride,
1126
0
                          mask, bw, bh);
1127
#else
1128
    aom_blend_a64_vmask(dst, dst_stride, dst, dst_stride, tmp, tmp_stride, mask,
1129
                        bw, bh);
1130
#endif
1131
0
  }
1132
0
}
1133
1134
static INLINE void build_obmc_inter_pred_left(
1135
    MACROBLOCKD *xd, int rel_mi_row, int rel_mi_col, uint8_t op_mi_size,
1136
66
    int dir, MB_MODE_INFO *left_mi, void *fun_ctxt, const int num_planes) {
1137
66
  (void)left_mi;
1138
66
  (void)rel_mi_col;
1139
66
  (void)dir;
1140
66
  struct obmc_inter_pred_ctxt *ctxt = (struct obmc_inter_pred_ctxt *)fun_ctxt;
1141
66
  const BLOCK_SIZE bsize = xd->mi[0]->bsize;
1142
66
  const int overlap =
1143
66
      AOMMIN(block_size_wide[bsize], block_size_wide[BLOCK_64X64]) >> 1;
1144
1145
264
  for (int plane = 0; plane < num_planes; ++plane) {
1146
198
    const struct macroblockd_plane *pd = &xd->plane[plane];
1147
198
    const int bw = overlap >> pd->subsampling_x;
1148
198
    const int bh = (op_mi_size * MI_SIZE) >> pd->subsampling_y;
1149
198
    const int plane_row = (rel_mi_row * MI_SIZE) >> pd->subsampling_y;
1150
1151
198
    if (av1_skip_u4x4_pred_in_obmc(bsize, pd, 1)) continue;
1152
1153
198
    const int dst_stride = pd->dst.stride;
1154
198
    uint8_t *const dst = &pd->dst.buf[plane_row * dst_stride];
1155
198
    const int tmp_stride = ctxt->adjacent_stride[plane];
1156
198
    const uint8_t *const tmp = &ctxt->adjacent[plane][plane_row * tmp_stride];
1157
198
    const uint8_t *const mask = av1_get_obmc_mask(bw);
1158
1159
198
#if CONFIG_AV1_HIGHBITDEPTH
1160
198
    const int is_hbd = is_cur_buf_hbd(xd);
1161
198
    if (is_hbd)
1162
42
      aom_highbd_blend_a64_hmask(dst, dst_stride, dst, dst_stride, tmp,
1163
42
                                 tmp_stride, mask, bw, bh, xd->bd);
1164
156
    else
1165
156
      aom_blend_a64_hmask(dst, dst_stride, dst, dst_stride, tmp, tmp_stride,
1166
156
                          mask, bw, bh);
1167
#else
1168
    aom_blend_a64_hmask(dst, dst_stride, dst, dst_stride, tmp, tmp_stride, mask,
1169
                        bw, bh);
1170
#endif
1171
198
  }
1172
66
}
1173
1174
// This function combines motion compensated predictions that are generated by
1175
// top/left neighboring blocks' inter predictors with the regular inter
1176
// prediction. We assume the original prediction (bmc) is stored in
1177
// xd->plane[].dst.buf
1178
void av1_build_obmc_inter_prediction(const AV1_COMMON *cm, MACROBLOCKD *xd,
1179
                                     uint8_t *above[MAX_MB_PLANE],
1180
                                     int above_stride[MAX_MB_PLANE],
1181
                                     uint8_t *left[MAX_MB_PLANE],
1182
66
                                     int left_stride[MAX_MB_PLANE]) {
1183
66
  const BLOCK_SIZE bsize = xd->mi[0]->bsize;
1184
1185
  // handle above row
1186
66
  struct obmc_inter_pred_ctxt ctxt_above = { above, above_stride };
1187
66
  foreach_overlappable_nb_above(cm, xd,
1188
66
                                max_neighbor_obmc[mi_size_wide_log2[bsize]],
1189
66
                                build_obmc_inter_pred_above, &ctxt_above);
1190
1191
  // handle left column
1192
66
  struct obmc_inter_pred_ctxt ctxt_left = { left, left_stride };
1193
66
  foreach_overlappable_nb_left(cm, xd,
1194
66
                               max_neighbor_obmc[mi_size_high_log2[bsize]],
1195
66
                               build_obmc_inter_pred_left, &ctxt_left);
1196
66
}
1197
1198
void av1_setup_obmc_dst_bufs(MACROBLOCKD *xd, uint8_t **dst_buf1,
1199
66
                             uint8_t **dst_buf2) {
1200
66
  if (is_cur_buf_hbd(xd)) {
1201
14
    int len = sizeof(uint16_t);
1202
14
    dst_buf1[0] = CONVERT_TO_BYTEPTR(xd->tmp_obmc_bufs[0]);
1203
14
    dst_buf1[1] =
1204
14
        CONVERT_TO_BYTEPTR(xd->tmp_obmc_bufs[0] + MAX_SB_SQUARE * len);
1205
14
    dst_buf1[2] =
1206
14
        CONVERT_TO_BYTEPTR(xd->tmp_obmc_bufs[0] + MAX_SB_SQUARE * 2 * len);
1207
14
    dst_buf2[0] = CONVERT_TO_BYTEPTR(xd->tmp_obmc_bufs[1]);
1208
14
    dst_buf2[1] =
1209
14
        CONVERT_TO_BYTEPTR(xd->tmp_obmc_bufs[1] + MAX_SB_SQUARE * len);
1210
14
    dst_buf2[2] =
1211
14
        CONVERT_TO_BYTEPTR(xd->tmp_obmc_bufs[1] + MAX_SB_SQUARE * 2 * len);
1212
52
  } else {
1213
52
    dst_buf1[0] = xd->tmp_obmc_bufs[0];
1214
52
    dst_buf1[1] = xd->tmp_obmc_bufs[0] + MAX_SB_SQUARE;
1215
52
    dst_buf1[2] = xd->tmp_obmc_bufs[0] + MAX_SB_SQUARE * 2;
1216
52
    dst_buf2[0] = xd->tmp_obmc_bufs[1];
1217
52
    dst_buf2[1] = xd->tmp_obmc_bufs[1] + MAX_SB_SQUARE;
1218
52
    dst_buf2[2] = xd->tmp_obmc_bufs[1] + MAX_SB_SQUARE * 2;
1219
52
  }
1220
66
}
1221
1222
void av1_setup_build_prediction_by_above_pred(
1223
    MACROBLOCKD *xd, int rel_mi_col, uint8_t above_mi_width,
1224
    MB_MODE_INFO *above_mbmi, struct build_prediction_ctxt *ctxt,
1225
0
    const int num_planes) {
1226
0
  const BLOCK_SIZE a_bsize = AOMMAX(BLOCK_8X8, above_mbmi->bsize);
1227
0
  const int above_mi_col = xd->mi_col + rel_mi_col;
1228
1229
0
  av1_modify_neighbor_predictor_for_obmc(above_mbmi);
1230
1231
0
  for (int j = 0; j < num_planes; ++j) {
1232
0
    struct macroblockd_plane *const pd = &xd->plane[j];
1233
0
    setup_pred_plane(&pd->dst, a_bsize, ctxt->tmp_buf[j], ctxt->tmp_width[j],
1234
0
                     ctxt->tmp_height[j], ctxt->tmp_stride[j], 0, rel_mi_col,
1235
0
                     NULL, pd->subsampling_x, pd->subsampling_y);
1236
0
  }
1237
1238
0
  const int num_refs = 1 + has_second_ref(above_mbmi);
1239
1240
0
  for (int ref = 0; ref < num_refs; ++ref) {
1241
0
    const MV_REFERENCE_FRAME frame = above_mbmi->ref_frame[ref];
1242
1243
0
    const RefCntBuffer *const ref_buf = get_ref_frame_buf(ctxt->cm, frame);
1244
0
    const struct scale_factors *const sf =
1245
0
        get_ref_scale_factors_const(ctxt->cm, frame);
1246
0
    xd->block_ref_scale_factors[ref] = sf;
1247
0
    if ((!av1_is_valid_scale(sf)))
1248
0
      aom_internal_error(xd->error_info, AOM_CODEC_UNSUP_BITSTREAM,
1249
0
                         "Reference frame has invalid dimensions");
1250
0
    av1_setup_pre_planes(xd, ref, &ref_buf->buf, xd->mi_row, above_mi_col, sf,
1251
0
                         num_planes);
1252
0
  }
1253
1254
0
  xd->mb_to_left_edge = 8 * MI_SIZE * (-above_mi_col);
1255
0
  xd->mb_to_right_edge =
1256
0
      ctxt->mb_to_far_edge +
1257
0
      (xd->width - rel_mi_col - above_mi_width) * MI_SIZE * 8;
1258
0
}
1259
1260
void av1_setup_build_prediction_by_left_pred(MACROBLOCKD *xd, int rel_mi_row,
1261
                                             uint8_t left_mi_height,
1262
                                             MB_MODE_INFO *left_mbmi,
1263
                                             struct build_prediction_ctxt *ctxt,
1264
66
                                             const int num_planes) {
1265
66
  const BLOCK_SIZE l_bsize = AOMMAX(BLOCK_8X8, left_mbmi->bsize);
1266
66
  const int left_mi_row = xd->mi_row + rel_mi_row;
1267
1268
66
  av1_modify_neighbor_predictor_for_obmc(left_mbmi);
1269
1270
264
  for (int j = 0; j < num_planes; ++j) {
1271
198
    struct macroblockd_plane *const pd = &xd->plane[j];
1272
198
    setup_pred_plane(&pd->dst, l_bsize, ctxt->tmp_buf[j], ctxt->tmp_width[j],
1273
198
                     ctxt->tmp_height[j], ctxt->tmp_stride[j], rel_mi_row, 0,
1274
198
                     NULL, pd->subsampling_x, pd->subsampling_y);
1275
198
  }
1276
1277
66
  const int num_refs = 1 + has_second_ref(left_mbmi);
1278
1279
132
  for (int ref = 0; ref < num_refs; ++ref) {
1280
66
    const MV_REFERENCE_FRAME frame = left_mbmi->ref_frame[ref];
1281
1282
66
    const RefCntBuffer *const ref_buf = get_ref_frame_buf(ctxt->cm, frame);
1283
66
    const struct scale_factors *const ref_scale_factors =
1284
66
        get_ref_scale_factors_const(ctxt->cm, frame);
1285
1286
66
    xd->block_ref_scale_factors[ref] = ref_scale_factors;
1287
66
    if ((!av1_is_valid_scale(ref_scale_factors)))
1288
0
      aom_internal_error(xd->error_info, AOM_CODEC_UNSUP_BITSTREAM,
1289
0
                         "Reference frame has invalid dimensions");
1290
66
    av1_setup_pre_planes(xd, ref, &ref_buf->buf, left_mi_row, xd->mi_col,
1291
66
                         ref_scale_factors, num_planes);
1292
66
  }
1293
1294
66
  xd->mb_to_top_edge = GET_MV_SUBPEL(MI_SIZE * (-left_mi_row));
1295
66
  xd->mb_to_bottom_edge =
1296
66
      ctxt->mb_to_far_edge +
1297
66
      GET_MV_SUBPEL((xd->height - rel_mi_row - left_mi_height) * MI_SIZE);
1298
66
}
1299
1300
static AOM_INLINE void combine_interintra(
1301
    INTERINTRA_MODE mode, int8_t use_wedge_interintra, int8_t wedge_index,
1302
    int8_t wedge_sign, BLOCK_SIZE bsize, BLOCK_SIZE plane_bsize,
1303
    uint8_t *comppred, int compstride, const uint8_t *interpred,
1304
84
    int interstride, const uint8_t *intrapred, int intrastride) {
1305
84
  const int bw = block_size_wide[plane_bsize];
1306
84
  const int bh = block_size_high[plane_bsize];
1307
1308
84
  if (use_wedge_interintra) {
1309
53
    if (av1_is_wedge_used(bsize)) {
1310
53
      const uint8_t *mask =
1311
53
          av1_get_contiguous_soft_mask(wedge_index, wedge_sign, bsize);
1312
53
      const int subw = 2 * mi_size_wide[bsize] == bw;
1313
53
      const int subh = 2 * mi_size_high[bsize] == bh;
1314
53
      aom_blend_a64_mask(comppred, compstride, intrapred, intrastride,
1315
53
                         interpred, interstride, mask, block_size_wide[bsize],
1316
53
                         bw, bh, subw, subh);
1317
53
    }
1318
53
    return;
1319
53
  }
1320
1321
31
  const uint8_t *mask = smooth_interintra_mask_buf[mode][plane_bsize];
1322
31
  aom_blend_a64_mask(comppred, compstride, intrapred, intrastride, interpred,
1323
31
                     interstride, mask, bw, bw, bh, 0, 0);
1324
31
}
1325
1326
#if CONFIG_AV1_HIGHBITDEPTH
1327
static AOM_INLINE void combine_interintra_highbd(
1328
    INTERINTRA_MODE mode, int8_t use_wedge_interintra, int8_t wedge_index,
1329
    int8_t wedge_sign, BLOCK_SIZE bsize, BLOCK_SIZE plane_bsize,
1330
    uint8_t *comppred8, int compstride, const uint8_t *interpred8,
1331
66
    int interstride, const uint8_t *intrapred8, int intrastride, int bd) {
1332
66
  const int bw = block_size_wide[plane_bsize];
1333
66
  const int bh = block_size_high[plane_bsize];
1334
1335
66
  if (use_wedge_interintra) {
1336
23
    if (av1_is_wedge_used(bsize)) {
1337
23
      const uint8_t *mask =
1338
23
          av1_get_contiguous_soft_mask(wedge_index, wedge_sign, bsize);
1339
23
      const int subh = 2 * mi_size_high[bsize] == bh;
1340
23
      const int subw = 2 * mi_size_wide[bsize] == bw;
1341
23
      aom_highbd_blend_a64_mask(comppred8, compstride, intrapred8, intrastride,
1342
23
                                interpred8, interstride, mask,
1343
23
                                block_size_wide[bsize], bw, bh, subw, subh, bd);
1344
23
    }
1345
23
    return;
1346
23
  }
1347
1348
43
  uint8_t mask[MAX_SB_SQUARE];
1349
43
  build_smooth_interintra_mask(mask, bw, plane_bsize, mode);
1350
43
  aom_highbd_blend_a64_mask(comppred8, compstride, intrapred8, intrastride,
1351
43
                            interpred8, interstride, mask, bw, bw, bh, 0, 0,
1352
43
                            bd);
1353
43
}
1354
#endif
1355
1356
void av1_build_intra_predictors_for_interintra(const AV1_COMMON *cm,
1357
                                               MACROBLOCKD *xd,
1358
                                               BLOCK_SIZE bsize, int plane,
1359
                                               const BUFFER_SET *ctx,
1360
150
                                               uint8_t *dst, int dst_stride) {
1361
150
  struct macroblockd_plane *const pd = &xd->plane[plane];
1362
150
  const int ssx = xd->plane[plane].subsampling_x;
1363
150
  const int ssy = xd->plane[plane].subsampling_y;
1364
150
  BLOCK_SIZE plane_bsize = get_plane_block_size(bsize, ssx, ssy);
1365
150
  PREDICTION_MODE mode = interintra_to_intra_mode[xd->mi[0]->interintra_mode];
1366
150
  assert(xd->mi[0]->angle_delta[PLANE_TYPE_Y] == 0);
1367
150
  assert(xd->mi[0]->angle_delta[PLANE_TYPE_UV] == 0);
1368
150
  assert(xd->mi[0]->filter_intra_mode_info.use_filter_intra == 0);
1369
150
  assert(xd->mi[0]->use_intrabc == 0);
1370
150
  const SequenceHeader *seq_params = cm->seq_params;
1371
1372
150
  av1_predict_intra_block(xd, seq_params->sb_size,
1373
150
                          seq_params->enable_intra_edge_filter, pd->width,
1374
150
                          pd->height, max_txsize_rect_lookup[plane_bsize], mode,
1375
150
                          0, 0, FILTER_INTRA_MODES, ctx->plane[plane],
1376
150
                          ctx->stride[plane], dst, dst_stride, 0, 0, plane);
1377
150
}
1378
1379
void av1_combine_interintra(MACROBLOCKD *xd, BLOCK_SIZE bsize, int plane,
1380
                            const uint8_t *inter_pred, int inter_stride,
1381
150
                            const uint8_t *intra_pred, int intra_stride) {
1382
150
  const int ssx = xd->plane[plane].subsampling_x;
1383
150
  const int ssy = xd->plane[plane].subsampling_y;
1384
150
  const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize, ssx, ssy);
1385
150
#if CONFIG_AV1_HIGHBITDEPTH
1386
150
  if (is_cur_buf_hbd(xd)) {
1387
66
    combine_interintra_highbd(
1388
66
        xd->mi[0]->interintra_mode, xd->mi[0]->use_wedge_interintra,
1389
66
        xd->mi[0]->interintra_wedge_index, INTERINTRA_WEDGE_SIGN, bsize,
1390
66
        plane_bsize, xd->plane[plane].dst.buf, xd->plane[plane].dst.stride,
1391
66
        inter_pred, inter_stride, intra_pred, intra_stride, xd->bd);
1392
66
    return;
1393
66
  }
1394
84
#endif
1395
84
  combine_interintra(
1396
84
      xd->mi[0]->interintra_mode, xd->mi[0]->use_wedge_interintra,
1397
84
      xd->mi[0]->interintra_wedge_index, INTERINTRA_WEDGE_SIGN, bsize,
1398
84
      plane_bsize, xd->plane[plane].dst.buf, xd->plane[plane].dst.stride,
1399
84
      inter_pred, inter_stride, intra_pred, intra_stride);
1400
84
}
1401
1402
// build interintra_predictors for one plane
1403
void av1_build_interintra_predictor(const AV1_COMMON *cm, MACROBLOCKD *xd,
1404
                                    uint8_t *pred, int stride,
1405
                                    const BUFFER_SET *ctx, int plane,
1406
150
                                    BLOCK_SIZE bsize) {
1407
150
  assert(bsize < BLOCK_SIZES_ALL);
1408
150
  if (is_cur_buf_hbd(xd)) {
1409
66
    DECLARE_ALIGNED(16, uint16_t, intrapredictor[MAX_SB_SQUARE]);
1410
66
    av1_build_intra_predictors_for_interintra(
1411
66
        cm, xd, bsize, plane, ctx, CONVERT_TO_BYTEPTR(intrapredictor),
1412
66
        MAX_SB_SIZE);
1413
66
    av1_combine_interintra(xd, bsize, plane, pred, stride,
1414
66
                           CONVERT_TO_BYTEPTR(intrapredictor), MAX_SB_SIZE);
1415
84
  } else {
1416
84
    DECLARE_ALIGNED(16, uint8_t, intrapredictor[MAX_SB_SQUARE]);
1417
84
    av1_build_intra_predictors_for_interintra(cm, xd, bsize, plane, ctx,
1418
84
                                              intrapredictor, MAX_SB_SIZE);
1419
84
    av1_combine_interintra(xd, bsize, plane, pred, stride, intrapredictor,
1420
84
                           MAX_SB_SIZE);
1421
84
  }
1422
150
}