Coverage Report

Created: 2025-07-23 08:18

/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
53.3k
                   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
53.3k
  if (av1_is_scaled(sf)) return 0;
41
42
51.4k
  if (final_warp_params != NULL) *final_warp_params = default_warp_params;
43
44
51.4k
  if (build_for_obmc) return 0;
45
46
51.4k
  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
51.4k
  } else if (warp_types->global_warp_allowed && !gm_params->invalid) {
51
382
    if (final_warp_params != NULL)
52
382
      memcpy(final_warp_params, gm_params, sizeof(*final_warp_params));
53
382
    return 1;
54
382
  }
55
56
51.0k
  return 0;
57
51.4k
}
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
181k
                           int_interpfilters interp_filters) {
66
181k
  inter_pred_params->block_width = block_width;
67
181k
  inter_pred_params->block_height = block_height;
68
181k
  inter_pred_params->pix_row = pix_row;
69
181k
  inter_pred_params->pix_col = pix_col;
70
181k
  inter_pred_params->subsampling_x = subsampling_x;
71
181k
  inter_pred_params->subsampling_y = subsampling_y;
72
181k
  inter_pred_params->bit_depth = bit_depth;
73
181k
  inter_pred_params->use_hbd_buf = use_hbd_buf;
74
181k
  inter_pred_params->is_intrabc = is_intrabc;
75
181k
  inter_pred_params->scale_factors = sf;
76
181k
  inter_pred_params->ref_frame_buf = *ref_buf;
77
181k
  inter_pred_params->mode = TRANSLATION_PRED;
78
181k
  inter_pred_params->comp_mode = UNIFORM_SINGLE;
79
80
181k
  if (is_intrabc) {
81
169k
    inter_pred_params->interp_filter_params[0] = &av1_intrabc_filter_params;
82
169k
    inter_pred_params->interp_filter_params[1] = &av1_intrabc_filter_params;
83
169k
  } else {
84
12.7k
    inter_pred_params->interp_filter_params[0] =
85
12.7k
        av1_get_interp_filter_params_with_block_size(
86
12.7k
            interp_filters.as_filters.x_filter, block_width);
87
12.7k
    inter_pred_params->interp_filter_params[1] =
88
12.7k
        av1_get_interp_filter_params_with_block_size(
89
12.7k
            interp_filters.as_filters.y_filter, block_height);
90
12.7k
  }
91
181k
}
92
93
3.35k
void av1_init_comp_mode(InterPredParams *inter_pred_params) {
94
3.35k
  inter_pred_params->comp_mode = UNIFORM_COMP;
95
3.35k
}
96
97
void av1_init_warp_params(InterPredParams *inter_pred_params,
98
                          const WarpTypesAllowed *warp_types, int ref,
99
181k
                          const MACROBLOCKD *xd, const MB_MODE_INFO *mi) {
100
181k
  if (inter_pred_params->block_height < 8 || inter_pred_params->block_width < 8)
101
96.3k
    return;
102
103
84.8k
  if (xd->cur_frame_force_integer_mv) return;
104
105
53.3k
  if (av1_allow_warp(mi, warp_types, &xd->global_motion[mi->ref_frame[ref]], 0,
106
53.3k
                     inter_pred_params->scale_factors,
107
53.3k
                     &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
382
    inter_pred_params->mode = WARP_PRED;
113
382
  }
114
53.3k
}
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
181k
                              const SubpelParams *subpel_params) {
120
181k
  assert(IMPLIES(inter_pred_params->conv_params.is_compound,
121
181k
                 inter_pred_params->conv_params.dst != NULL));
122
123
181k
  if (inter_pred_params->mode == TRANSLATION_PRED) {
124
181k
#if CONFIG_AV1_HIGHBITDEPTH
125
181k
    if (inter_pred_params->use_hbd_buf) {
126
75.3k
      highbd_inter_predictor(src, src_stride, dst, dst_stride, subpel_params,
127
75.3k
                             inter_pred_params->block_width,
128
75.3k
                             inter_pred_params->block_height,
129
75.3k
                             &inter_pred_params->conv_params,
130
75.3k
                             inter_pred_params->interp_filter_params,
131
75.3k
                             inter_pred_params->bit_depth);
132
106k
    } else {
133
106k
      inter_predictor(src, src_stride, dst, dst_stride, subpel_params,
134
106k
                      inter_pred_params->block_width,
135
106k
                      inter_pred_params->block_height,
136
106k
                      &inter_pred_params->conv_params,
137
106k
                      inter_pred_params->interp_filter_params);
138
106k
    }
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
181k
  }
147
382
#if !CONFIG_REALTIME_ONLY
148
  // TODO(jingning): av1_warp_plane() can be further cleaned up.
149
382
  else if (inter_pred_params->mode == WARP_PRED) {
150
382
    av1_warp_plane(
151
382
        &inter_pred_params->warp_params, inter_pred_params->use_hbd_buf,
152
382
        inter_pred_params->bit_depth, inter_pred_params->ref_frame_buf.buf0,
153
382
        inter_pred_params->ref_frame_buf.width,
154
382
        inter_pred_params->ref_frame_buf.height,
155
382
        inter_pred_params->ref_frame_buf.stride, dst,
156
382
        inter_pred_params->pix_col, inter_pred_params->pix_row,
157
382
        inter_pred_params->block_width, inter_pred_params->block_height,
158
382
        dst_stride, inter_pred_params->subsampling_x,
159
382
        inter_pred_params->subsampling_y, &inter_pred_params->conv_params);
160
382
  }
161
0
#endif
162
0
  else {
163
0
    assert(0 && "Unsupported inter_pred_params->mode");
164
0
  }
165
181k
}
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
210
                                                    INTERINTRA_MODE mode) {
579
210
  int i, j;
580
210
  const int bw = block_size_wide[plane_bsize];
581
210
  const int bh = block_size_high[plane_bsize];
582
210
  const int size_scale = ii_size_scales[plane_bsize];
583
584
210
  switch (mode) {
585
56
    case II_V_PRED:
586
756
      for (i = 0; i < bh; ++i) {
587
700
        memset(mask, ii_weights1d[i * size_scale], bw * sizeof(mask[0]));
588
700
        mask += stride;
589
700
      }
590
56
      break;
591
592
58
    case II_H_PRED:
593
798
      for (i = 0; i < bh; ++i) {
594
12.8k
        for (j = 0; j < bw; ++j) mask[j] = ii_weights1d[j * size_scale];
595
740
        mask += stride;
596
740
      }
597
58
      break;
598
599
48
    case II_SMOOTH_PRED:
600
700
      for (i = 0; i < bh; ++i) {
601
10.9k
        for (j = 0; j < bw; ++j)
602
10.3k
          mask[j] = ii_weights1d[(i < j ? i : j) * size_scale];
603
652
        mask += stride;
604
652
      }
605
48
      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
210
  }
615
210
}
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
181k
    int ref, uint8_t **mc_buf, CalcSubpelParamsFunc calc_subpel_params_func) {
707
181k
  SubpelParams subpel_params;
708
181k
  uint8_t *src;
709
181k
  int src_stride;
710
181k
  calc_subpel_params_func(src_mv, inter_pred_params, xd, mi_x, mi_y, ref,
711
181k
                          mc_buf, &src, &subpel_params, &src_stride);
712
713
181k
  if (inter_pred_params->comp_mode == UNIFORM_SINGLE ||
714
181k
      inter_pred_params->comp_mode == UNIFORM_COMP) {
715
181k
    av1_make_inter_predictor(src, src_stride, dst, dst_stride,
716
181k
                             inter_pred_params, &subpel_params);
717
181k
  } else {
718
189
    make_masked_inter_predictor(src, src_stride, dst, dst_stride,
719
189
                                inter_pred_params, &subpel_params);
720
189
  }
721
181k
}
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
181k
                                     int is_compound) {
728
181k
  assert(fwd_offset != NULL && bck_offset != NULL);
729
181k
  if (!is_compound || mbmi->compound_idx) {
730
180k
    *fwd_offset = 8;
731
180k
    *bck_offset = 8;
732
180k
    *use_dist_wtd_comp_avg = 0;
733
180k
    return;
734
180k
  }
735
736
1.38k
  *use_dist_wtd_comp_avg = 1;
737
1.38k
  const RefCntBuffer *const bck_buf = get_ref_frame_buf(cm, mbmi->ref_frame[0]);
738
1.38k
  const RefCntBuffer *const fwd_buf = get_ref_frame_buf(cm, mbmi->ref_frame[1]);
739
1.38k
  const int cur_frame_index = cm->cur_frame->order_hint;
740
1.38k
  int bck_frame_index = 0, fwd_frame_index = 0;
741
742
1.38k
  if (bck_buf != NULL) bck_frame_index = bck_buf->order_hint;
743
1.38k
  if (fwd_buf != NULL) fwd_frame_index = fwd_buf->order_hint;
744
745
1.38k
  int d0 = clamp(abs(get_relative_dist(&cm->seq_params->order_hint_info,
746
1.38k
                                       fwd_frame_index, cur_frame_index)),
747
1.38k
                 0, MAX_FRAME_DISTANCE);
748
1.38k
  int d1 = clamp(abs(get_relative_dist(&cm->seq_params->order_hint_info,
749
1.38k
                                       cur_frame_index, bck_frame_index)),
750
1.38k
                 0, MAX_FRAME_DISTANCE);
751
752
1.38k
  const int order = d0 <= d1;
753
754
1.38k
  if (d0 == 0 || d1 == 0) {
755
92
    *fwd_offset = quant_dist_lookup_table[3][order];
756
92
    *bck_offset = quant_dist_lookup_table[3][1 - order];
757
92
    return;
758
92
  }
759
760
1.29k
  int i;
761
1.38k
  for (i = 0; i < 3; ++i) {
762
1.36k
    int c0 = quant_dist_weight[i][order];
763
1.36k
    int c1 = quant_dist_weight[i][!order];
764
1.36k
    int d0_c0 = d0 * c0;
765
1.36k
    int d1_c1 = d1 * c1;
766
1.36k
    if ((d0 > d1 && d0_c0 < d1_c1) || (d0 <= d1 && d0_c0 > d1_c1)) break;
767
1.36k
  }
768
769
1.29k
  *fwd_offset = quant_dist_lookup_table[i][order];
770
1.29k
  *bck_offset = quant_dist_lookup_table[i][1 - order];
771
1.29k
}
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
179k
                            int is_intrabc, int build_for_obmc) {
780
179k
  if (is_intrabc || build_for_obmc) {
781
169k
    return false;
782
169k
  }
783
784
10.4k
  const struct macroblockd_plane *const pd = &xd->plane[plane];
785
10.4k
  const int ss_x = pd->subsampling_x;
786
10.4k
  const int ss_y = pd->subsampling_y;
787
10.4k
  const int is_sub4_x = (block_size_wide[bsize] == 4) && ss_x;
788
10.4k
  const int is_sub4_y = (block_size_high[bsize] == 4) && ss_y;
789
10.4k
  if (!is_sub4_x && !is_sub4_y) {
790
10.2k
    return false;
791
10.2k
  }
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
192
  const int row_start = is_sub4_y ? -1 : 0;
798
192
  const int col_start = is_sub4_x ? -1 : 0;
799
800
518
  for (int row = row_start; row <= 0; ++row) {
801
936
    for (int col = col_start; col <= 0; ++col) {
802
610
      const MB_MODE_INFO *this_mbmi = xd->mi[row * xd->mi_stride + col];
803
610
      if (!is_inter_block(this_mbmi)) return false;
804
590
      if (is_intrabc_block(this_mbmi)) return false;
805
590
    }
806
346
  }
807
172
  return true;
808
192
}
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
172
    CalcSubpelParamsFunc calc_subpel_params_func) {
814
172
  const BLOCK_SIZE bsize = mi->bsize;
815
172
  struct macroblockd_plane *const pd = &xd->plane[plane];
816
172
  const bool ss_x = pd->subsampling_x;
817
172
  const bool ss_y = pd->subsampling_y;
818
172
  const int b4_w = block_size_wide[bsize] >> ss_x;
819
172
  const int b4_h = block_size_high[bsize] >> ss_y;
820
172
  const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize, ss_x, ss_y);
821
172
  const int b8_w = block_size_wide[plane_bsize];
822
172
  const int b8_h = block_size_high[plane_bsize];
823
172
  const int is_compound = has_second_ref(mi);
824
172
  assert(!is_compound);
825
172
  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
172
  const int row_start = (block_size_high[bsize] == 4) && ss_y ? -1 : 0;
832
172
  const int col_start = (block_size_wide[bsize] == 4) && ss_x ? -1 : 0;
833
172
  const int pre_x = (mi_x + MI_SIZE * col_start) >> ss_x;
834
172
  const int pre_y = (mi_y + MI_SIZE * row_start) >> ss_y;
835
836
172
  int row = row_start;
837
490
  for (int y = 0; y < b8_h; y += b4_h) {
838
318
    int col = col_start;
839
890
    for (int x = 0; x < b8_w; x += b4_w) {
840
572
      MB_MODE_INFO *this_mbmi = xd->mi[row * xd->mi_stride + col];
841
572
      struct buf_2d *const dst_buf = &pd->dst;
842
572
      uint8_t *dst = dst_buf->buf + dst_buf->stride * y + x;
843
572
      int ref = 0;
844
572
      const RefCntBuffer *ref_buf =
845
572
          get_ref_frame_buf(cm, this_mbmi->ref_frame[ref]);
846
572
      const struct scale_factors *ref_scale_factors =
847
572
          get_ref_scale_factors_const(cm, this_mbmi->ref_frame[ref]);
848
572
      const struct scale_factors *const sf = ref_scale_factors;
849
572
      const struct buf_2d pre_buf = {
850
572
        NULL,
851
572
        (plane == 1) ? ref_buf->buf.u_buffer : ref_buf->buf.v_buffer,
852
572
        ref_buf->buf.uv_crop_width,
853
572
        ref_buf->buf.uv_crop_height,
854
572
        ref_buf->buf.uv_stride,
855
572
      };
856
857
572
      const MV mv = this_mbmi->mv[ref].as_mv;
858
859
572
      InterPredParams inter_pred_params;
860
572
      av1_init_inter_params(&inter_pred_params, b4_w, b4_h, pre_y + y,
861
572
                            pre_x + x, pd->subsampling_x, pd->subsampling_y,
862
572
                            xd->bd, is_cur_buf_hbd(xd), mi->use_intrabc, sf,
863
572
                            &pre_buf, this_mbmi->interp_filters);
864
572
      inter_pred_params.conv_params =
865
572
          get_conv_params_no_round(ref, plane, NULL, 0, is_compound, xd->bd);
866
867
572
      av1_build_one_inter_predictor(dst, dst_buf->stride, &mv,
868
572
                                    &inter_pred_params, xd, mi_x + x, mi_y + y,
869
572
                                    ref, mc_buf, calc_subpel_params_func);
870
871
572
      ++col;
872
572
    }
873
318
    ++row;
874
318
  }
875
172
}
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
179k
    CalcSubpelParamsFunc calc_subpel_params_func) {
881
179k
  const int is_compound = has_second_ref(mi);
882
179k
  const int is_intrabc = is_intrabc_block(mi);
883
179k
  assert(IMPLIES(is_intrabc, !is_compound));
884
179k
  struct macroblockd_plane *const pd = &xd->plane[plane];
885
179k
  struct buf_2d *const dst_buf = &pd->dst;
886
179k
  uint8_t *const dst = dst_buf->buf;
887
888
179k
  int is_global[2] = { 0, 0 };
889
361k
  for (int ref = 0; ref < 1 + is_compound; ++ref) {
890
181k
    const WarpedMotionParams *const wm = &xd->global_motion[mi->ref_frame[ref]];
891
181k
    is_global[ref] = is_global_mv_block(mi, wm->wmtype);
892
181k
  }
893
894
179k
  const BLOCK_SIZE bsize = mi->bsize;
895
179k
  const int ss_x = pd->subsampling_x;
896
179k
  const int ss_y = pd->subsampling_y;
897
179k
  const int row_start =
898
179k
      (block_size_high[bsize] == 4) && ss_y && !build_for_obmc ? -1 : 0;
899
179k
  const int col_start =
900
179k
      (block_size_wide[bsize] == 4) && ss_x && !build_for_obmc ? -1 : 0;
901
179k
  const int pre_x = (mi_x + MI_SIZE * col_start) >> ss_x;
902
179k
  const int pre_y = (mi_y + MI_SIZE * row_start) >> ss_y;
903
904
361k
  for (int ref = 0; ref < 1 + is_compound; ++ref) {
905
181k
    const struct scale_factors *const sf =
906
181k
        is_intrabc ? &cm->sf_identity : xd->block_ref_scale_factors[ref];
907
181k
    struct buf_2d *const pre_buf = is_intrabc ? dst_buf : &pd->pre[ref];
908
181k
    const MV mv = mi->mv[ref].as_mv;
909
181k
    const WarpTypesAllowed warp_types = { is_global[ref],
910
181k
                                          mi->motion_mode == WARPED_CAUSAL };
911
912
181k
    InterPredParams inter_pred_params;
913
181k
    av1_init_inter_params(&inter_pred_params, bw, bh, pre_y, pre_x,
914
181k
                          pd->subsampling_x, pd->subsampling_y, xd->bd,
915
181k
                          is_cur_buf_hbd(xd), mi->use_intrabc, sf, pre_buf,
916
181k
                          mi->interp_filters);
917
181k
    if (is_compound) av1_init_comp_mode(&inter_pred_params);
918
181k
    inter_pred_params.conv_params = get_conv_params_no_round(
919
181k
        ref, plane, xd->tmp_conv_dst, MAX_SB_SIZE, is_compound, xd->bd);
920
921
181k
    av1_dist_wtd_comp_weight_assign(
922
181k
        cm, mi, &inter_pred_params.conv_params.fwd_offset,
923
181k
        &inter_pred_params.conv_params.bck_offset,
924
181k
        &inter_pred_params.conv_params.use_dist_wtd_comp_avg, is_compound);
925
926
181k
    if (!build_for_obmc)
927
181k
      av1_init_warp_params(&inter_pred_params, &warp_types, ref, xd, mi);
928
929
181k
    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
181k
    av1_build_one_inter_predictor(dst, dst_buf->stride, &mv, &inter_pred_params,
941
181k
                                  xd, mi_x, mi_y, ref, mc_buf,
942
181k
                                  calc_subpel_params_func);
943
181k
  }
944
179k
}
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
179k
                                CalcSubpelParamsFunc calc_subpel_params_func) {
951
179k
  if (is_sub8x8_inter(xd, plane, mi->bsize, is_intrabc_block(mi),
952
179k
                      build_for_obmc)) {
953
172
    assert(bw < 8 || bh < 8);
954
172
    build_inter_predictors_sub8x8(cm, xd, plane, mi, mi_x, mi_y, mc_buf,
955
172
                                  calc_subpel_params_func);
956
179k
  } else {
957
179k
    build_inter_predictors_8x8_and_bigger(cm, xd, plane, mi, build_for_obmc, bw,
958
179k
                                          bh, mi_x, mi_y, mc_buf,
959
179k
                                          calc_subpel_params_func);
960
179k
  }
961
179k
}
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.26M
                          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.7M
  for (int i = plane_start; i < AOMMIN(plane_end, MAX_MB_PLANE); ++i) {
968
24.5M
    struct macroblockd_plane *const pd = &planes[i];
969
24.5M
    const int is_uv = i > 0;
970
24.5M
    setup_pred_plane(&pd->dst, bsize, src->buffers[i], src->crop_widths[is_uv],
971
24.5M
                     src->crop_heights[is_uv], src->strides[is_uv], mi_row,
972
24.5M
                     mi_col, NULL, pd->subsampling_x, pd->subsampling_y);
973
24.5M
  }
974
8.26M
}
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.43k
                          const int num_planes) {
980
8.43k
  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.2k
    for (int i = 0; i < AOMMIN(num_planes, MAX_MB_PLANE); ++i) {
984
12.8k
      struct macroblockd_plane *const pd = &xd->plane[i];
985
12.8k
      const int is_uv = i > 0;
986
12.8k
      setup_pred_plane(&pd->pre[idx], xd->mi[0]->bsize, src->buffers[i],
987
12.8k
                       src->crop_widths[is_uv], src->crop_heights[is_uv],
988
12.8k
                       src->strides[is_uv], mi_row, mi_col, sf,
989
12.8k
                       pd->subsampling_x, pd->subsampling_y);
990
12.8k
    }
991
8.43k
  }
992
8.43k
}
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.19k
void av1_count_overlappable_neighbors(const AV1_COMMON *cm, MACROBLOCKD *xd) {
1045
7.19k
  MB_MODE_INFO *mbmi = xd->mi[0];
1046
1047
7.19k
  mbmi->overlappable_neighbors = 0;
1048
1049
7.19k
  if (!is_motion_variation_allowed_bsize(mbmi->bsize)) return;
1050
1051
2.47k
  foreach_overlappable_nb_above(cm, xd, INT_MAX, increment_int_ptr,
1052
2.47k
                                &mbmi->overlappable_neighbors);
1053
2.47k
  if (mbmi->overlappable_neighbors) return;
1054
2.47k
  foreach_overlappable_nb_left(cm, xd, INT_MAX, increment_int_ptr,
1055
2.47k
                               &mbmi->overlappable_neighbors);
1056
2.47k
}
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
85
    int interstride, const uint8_t *intrapred, int intrastride) {
1305
85
  const int bw = block_size_wide[plane_bsize];
1306
85
  const int bh = block_size_high[plane_bsize];
1307
1308
85
  if (use_wedge_interintra) {
1309
54
    if (av1_is_wedge_used(bsize)) {
1310
54
      const uint8_t *mask =
1311
54
          av1_get_contiguous_soft_mask(wedge_index, wedge_sign, bsize);
1312
54
      const int subw = 2 * mi_size_wide[bsize] == bw;
1313
54
      const int subh = 2 * mi_size_high[bsize] == bh;
1314
54
      aom_blend_a64_mask(comppred, compstride, intrapred, intrastride,
1315
54
                         interpred, interstride, mask, block_size_wide[bsize],
1316
54
                         bw, bh, subw, subh);
1317
54
    }
1318
54
    return;
1319
54
  }
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
65
    int interstride, const uint8_t *intrapred8, int intrastride, int bd) {
1332
65
  const int bw = block_size_wide[plane_bsize];
1333
65
  const int bh = block_size_high[plane_bsize];
1334
1335
65
  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
42
  uint8_t mask[MAX_SB_SQUARE];
1349
42
  build_smooth_interintra_mask(mask, bw, plane_bsize, mode);
1350
42
  aom_highbd_blend_a64_mask(comppred8, compstride, intrapred8, intrastride,
1351
42
                            interpred8, interstride, mask, bw, bw, bh, 0, 0,
1352
42
                            bd);
1353
42
}
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
65
    combine_interintra_highbd(
1388
65
        xd->mi[0]->interintra_mode, xd->mi[0]->use_wedge_interintra,
1389
65
        xd->mi[0]->interintra_wedge_index, INTERINTRA_WEDGE_SIGN, bsize,
1390
65
        plane_bsize, xd->plane[plane].dst.buf, xd->plane[plane].dst.stride,
1391
65
        inter_pred, inter_stride, intra_pred, intra_stride, xd->bd);
1392
65
    return;
1393
65
  }
1394
85
#endif
1395
85
  combine_interintra(
1396
85
      xd->mi[0]->interintra_mode, xd->mi[0]->use_wedge_interintra,
1397
85
      xd->mi[0]->interintra_wedge_index, INTERINTRA_WEDGE_SIGN, bsize,
1398
85
      plane_bsize, xd->plane[plane].dst.buf, xd->plane[plane].dst.stride,
1399
85
      inter_pred, inter_stride, intra_pred, intra_stride);
1400
85
}
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
65
    DECLARE_ALIGNED(16, uint16_t, intrapredictor[MAX_SB_SQUARE]);
1410
65
    av1_build_intra_predictors_for_interintra(
1411
65
        cm, xd, bsize, plane, ctx, CONVERT_TO_BYTEPTR(intrapredictor),
1412
65
        MAX_SB_SIZE);
1413
65
    av1_combine_interintra(xd, bsize, plane, pred, stride,
1414
65
                           CONVERT_TO_BYTEPTR(intrapredictor), MAX_SB_SIZE);
1415
85
  } else {
1416
85
    DECLARE_ALIGNED(16, uint8_t, intrapredictor[MAX_SB_SQUARE]);
1417
85
    av1_build_intra_predictors_for_interintra(cm, xd, bsize, plane, ctx,
1418
85
                                              intrapredictor, MAX_SB_SIZE);
1419
85
    av1_combine_interintra(xd, bsize, plane, pred, stride, intrapredictor,
1420
85
                           MAX_SB_SIZE);
1421
85
  }
1422
150
}