Coverage Report

Created: 2026-10-27 06:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/aom/av1/common/reconinter.c
Line
Count
Source
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
static int 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
217k
                      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
217k
  if (av1_is_scaled(sf)) return 0;
41
42
208k
  if (final_warp_params != NULL) *final_warp_params = default_warp_params;
43
44
208k
  if (build_for_obmc) return 0;
45
46
208k
  if (warp_types->local_warp_allowed && !mbmi->wm_params.invalid) {
47
6.81k
    if (final_warp_params != NULL) *final_warp_params = mbmi->wm_params;
48
6.81k
    return 1;
49
201k
  } else if (warp_types->global_warp_allowed && !gm_params->invalid) {
50
15.9k
    if (final_warp_params != NULL) *final_warp_params = *gm_params;
51
15.9k
    return 1;
52
15.9k
  }
53
54
185k
  return 0;
55
208k
}
56
57
void av1_init_warp_params(InterPredParams *inter_pred_params,
58
                          const WarpTypesAllowed *warp_types, int ref,
59
468k
                          const MACROBLOCKD *xd, const MB_MODE_INFO *mi) {
60
468k
  if (inter_pred_params->block_height < 8 || inter_pred_params->block_width < 8)
61
230k
    return;
62
63
237k
  if (xd->cur_frame_force_integer_mv) return;
64
65
217k
  if (allow_warp(mi, warp_types, &xd->global_motion[mi->ref_frame[ref]], 0,
66
217k
                 inter_pred_params->scale_factors,
67
217k
                 &inter_pred_params->warp_params)) {
68
#if CONFIG_REALTIME_ONLY && !CONFIG_AV1_DECODER
69
    aom_internal_error(xd->error_info, AOM_CODEC_UNSUP_FEATURE,
70
                       "Warped motion is disabled in realtime only build.");
71
#endif  // CONFIG_REALTIME_ONLY && !CONFIG_AV1_DECODER
72
22.7k
    inter_pred_params->mode = WARP_PRED;
73
22.7k
  }
74
217k
}
75
76
void av1_make_inter_predictor(const uint8_t *src, int src_stride, uint8_t *dst,
77
                              int dst_stride,
78
                              InterPredParams *inter_pred_params,
79
487k
                              const SubpelParams *subpel_params) {
80
487k
  assert(IMPLIES(inter_pred_params->conv_params.is_compound,
81
487k
                 inter_pred_params->conv_params.dst != NULL));
82
83
487k
  if (inter_pred_params->mode == TRANSLATION_PRED) {
84
465k
#if CONFIG_AV1_HIGHBITDEPTH
85
465k
    if (inter_pred_params->use_hbd_buf) {
86
204k
      highbd_inter_predictor(src, src_stride, dst, dst_stride, subpel_params,
87
204k
                             inter_pred_params->block_width,
88
204k
                             inter_pred_params->block_height,
89
204k
                             &inter_pred_params->conv_params,
90
204k
                             inter_pred_params->interp_filter_params,
91
204k
                             inter_pred_params->bit_depth);
92
261k
    } else {
93
261k
      inter_predictor(src, src_stride, dst, dst_stride, subpel_params,
94
261k
                      inter_pred_params->block_width,
95
261k
                      inter_pred_params->block_height,
96
261k
                      &inter_pred_params->conv_params,
97
261k
                      inter_pred_params->interp_filter_params);
98
261k
    }
99
#else
100
    inter_predictor(src, src_stride, dst, dst_stride, subpel_params,
101
                    inter_pred_params->block_width,
102
                    inter_pred_params->block_height,
103
                    &inter_pred_params->conv_params,
104
                    inter_pred_params->interp_filter_params);
105
#endif
106
465k
  }
107
22.7k
#if !CONFIG_REALTIME_ONLY || CONFIG_AV1_DECODER
108
  // TODO(jingning): av1_warp_plane() can be further cleaned up.
109
22.7k
  else if (inter_pred_params->mode == WARP_PRED) {
110
22.7k
    av1_warp_plane(
111
22.7k
        &inter_pred_params->warp_params, inter_pred_params->use_hbd_buf,
112
22.7k
        inter_pred_params->bit_depth, inter_pred_params->ref_frame_buf.buf0,
113
22.7k
        inter_pred_params->ref_frame_buf.width,
114
22.7k
        inter_pred_params->ref_frame_buf.height,
115
22.7k
        inter_pred_params->ref_frame_buf.stride, dst,
116
22.7k
        inter_pred_params->pix_col, inter_pred_params->pix_row,
117
22.7k
        inter_pred_params->block_width, inter_pred_params->block_height,
118
22.7k
        dst_stride, inter_pred_params->subsampling_x,
119
22.7k
        inter_pred_params->subsampling_y, &inter_pred_params->conv_params);
120
22.7k
  }
121
0
#endif  // !CONFIG_REALTIME_ONLY || CONFIG_AV1_DECODER
122
0
  else {
123
0
    assert(0 && "Unsupported inter_pred_params->mode");
124
0
  }
125
487k
}
126
127
/* clang-format off */
128
DECLARE_ALIGNED(16, static const uint8_t,
129
                wedge_signflip_lookup[BLOCK_SIZES_ALL][MAX_WEDGE_TYPES]) = {
130
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },  // not used
131
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },  // not used
132
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },  // not used
133
  { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, },
134
  { 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, },
135
  { 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, },
136
  { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, },
137
  { 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, },
138
  { 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, },
139
  { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, },
140
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },  // not used
141
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },  // not used
142
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },  // not used
143
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },  // not used
144
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },  // not used
145
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },  // not used
146
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },  // not used
147
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },  // not used
148
  { 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, },
149
  { 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, },
150
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },  // not used
151
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },  // not used
152
};
153
/* clang-format on */
154
155
// The wedge / inter-intra mask buffers used to be writable .data populated
156
// by init_all_wedge_masks() at runtime, which gave every process its own
157
// private COW copy. They are now precomputed at codegen time (see
158
// tools/gen_wedge_masks_data.py) and included here as const data so they
159
// live in .rdata and are shared across processes.
160
//
161
// `wedge_masks` stores byte offsets into `wedge_mask_buf` (not pointers) to
162
// avoid loader relocations that would otherwise dirty the .rdata pages.
163
#include "av1/common/wedge_masks_data.inc"
164
165
static const wedge_code_type wedge_codebook_16_hgtw[16] = {
166
  { WEDGE_OBLIQUE27, 4, 4 },  { WEDGE_OBLIQUE63, 4, 4 },
167
  { WEDGE_OBLIQUE117, 4, 4 }, { WEDGE_OBLIQUE153, 4, 4 },
168
  { WEDGE_HORIZONTAL, 4, 2 }, { WEDGE_HORIZONTAL, 4, 4 },
169
  { WEDGE_HORIZONTAL, 4, 6 }, { WEDGE_VERTICAL, 4, 4 },
170
  { WEDGE_OBLIQUE27, 4, 2 },  { WEDGE_OBLIQUE27, 4, 6 },
171
  { WEDGE_OBLIQUE153, 4, 2 }, { WEDGE_OBLIQUE153, 4, 6 },
172
  { WEDGE_OBLIQUE63, 2, 4 },  { WEDGE_OBLIQUE63, 6, 4 },
173
  { WEDGE_OBLIQUE117, 2, 4 }, { WEDGE_OBLIQUE117, 6, 4 },
174
};
175
176
static const wedge_code_type wedge_codebook_16_hltw[16] = {
177
  { WEDGE_OBLIQUE27, 4, 4 },  { WEDGE_OBLIQUE63, 4, 4 },
178
  { WEDGE_OBLIQUE117, 4, 4 }, { WEDGE_OBLIQUE153, 4, 4 },
179
  { WEDGE_VERTICAL, 2, 4 },   { WEDGE_VERTICAL, 4, 4 },
180
  { WEDGE_VERTICAL, 6, 4 },   { WEDGE_HORIZONTAL, 4, 4 },
181
  { WEDGE_OBLIQUE27, 4, 2 },  { WEDGE_OBLIQUE27, 4, 6 },
182
  { WEDGE_OBLIQUE153, 4, 2 }, { WEDGE_OBLIQUE153, 4, 6 },
183
  { WEDGE_OBLIQUE63, 2, 4 },  { WEDGE_OBLIQUE63, 6, 4 },
184
  { WEDGE_OBLIQUE117, 2, 4 }, { WEDGE_OBLIQUE117, 6, 4 },
185
};
186
187
static const wedge_code_type wedge_codebook_16_heqw[16] = {
188
  { WEDGE_OBLIQUE27, 4, 4 },  { WEDGE_OBLIQUE63, 4, 4 },
189
  { WEDGE_OBLIQUE117, 4, 4 }, { WEDGE_OBLIQUE153, 4, 4 },
190
  { WEDGE_HORIZONTAL, 4, 2 }, { WEDGE_HORIZONTAL, 4, 6 },
191
  { WEDGE_VERTICAL, 2, 4 },   { WEDGE_VERTICAL, 6, 4 },
192
  { WEDGE_OBLIQUE27, 4, 2 },  { WEDGE_OBLIQUE27, 4, 6 },
193
  { WEDGE_OBLIQUE153, 4, 2 }, { WEDGE_OBLIQUE153, 4, 6 },
194
  { WEDGE_OBLIQUE63, 2, 4 },  { WEDGE_OBLIQUE63, 6, 4 },
195
  { WEDGE_OBLIQUE117, 2, 4 }, { WEDGE_OBLIQUE117, 6, 4 },
196
};
197
198
const wedge_params_type av1_wedge_params_lookup[BLOCK_SIZES_ALL] = {
199
  { 0, NULL, NULL, NULL },
200
  { 0, NULL, NULL, NULL },
201
  { 0, NULL, NULL, NULL },
202
  { MAX_WEDGE_TYPES, wedge_codebook_16_heqw, wedge_signflip_lookup[BLOCK_8X8],
203
    wedge_masks[BLOCK_8X8] },
204
  { MAX_WEDGE_TYPES, wedge_codebook_16_hgtw, wedge_signflip_lookup[BLOCK_8X16],
205
    wedge_masks[BLOCK_8X16] },
206
  { MAX_WEDGE_TYPES, wedge_codebook_16_hltw, wedge_signflip_lookup[BLOCK_16X8],
207
    wedge_masks[BLOCK_16X8] },
208
  { MAX_WEDGE_TYPES, wedge_codebook_16_heqw, wedge_signflip_lookup[BLOCK_16X16],
209
    wedge_masks[BLOCK_16X16] },
210
  { MAX_WEDGE_TYPES, wedge_codebook_16_hgtw, wedge_signflip_lookup[BLOCK_16X32],
211
    wedge_masks[BLOCK_16X32] },
212
  { MAX_WEDGE_TYPES, wedge_codebook_16_hltw, wedge_signflip_lookup[BLOCK_32X16],
213
    wedge_masks[BLOCK_32X16] },
214
  { MAX_WEDGE_TYPES, wedge_codebook_16_heqw, wedge_signflip_lookup[BLOCK_32X32],
215
    wedge_masks[BLOCK_32X32] },
216
  { 0, NULL, NULL, NULL },
217
  { 0, NULL, NULL, NULL },
218
  { 0, NULL, NULL, NULL },
219
  { 0, NULL, NULL, NULL },
220
  { 0, NULL, NULL, NULL },
221
  { 0, NULL, NULL, NULL },
222
  { 0, NULL, NULL, NULL },
223
  { 0, NULL, NULL, NULL },
224
  { MAX_WEDGE_TYPES, wedge_codebook_16_hgtw, wedge_signflip_lookup[BLOCK_8X32],
225
    wedge_masks[BLOCK_8X32] },
226
  { MAX_WEDGE_TYPES, wedge_codebook_16_hltw, wedge_signflip_lookup[BLOCK_32X8],
227
    wedge_masks[BLOCK_32X8] },
228
  { 0, NULL, NULL, NULL },
229
  { 0, NULL, NULL, NULL },
230
};
231
232
const uint8_t *av1_get_contiguous_soft_mask(int8_t wedge_index,
233
                                            int8_t wedge_sign,
234
5.03k
                                            BLOCK_SIZE sb_type) {
235
5.03k
  return wedge_mask_buf +
236
5.03k
         av1_wedge_params_lookup[sb_type].masks[wedge_sign][wedge_index];
237
5.03k
}
238
239
const uint8_t *av1_get_compound_type_mask(
240
3.94k
    const INTERINTER_COMPOUND_DATA *const comp_data, BLOCK_SIZE sb_type) {
241
3.94k
  (void)sb_type;
242
3.94k
  switch (comp_data->type) {
243
2.84k
    case COMPOUND_WEDGE:
244
2.84k
      return av1_get_contiguous_soft_mask(comp_data->wedge_index,
245
2.84k
                                          comp_data->wedge_sign, sb_type);
246
1.09k
    default: return comp_data->seg_mask;
247
3.94k
  }
248
3.94k
}
249
250
static inline void diffwtd_mask_d16(uint8_t *mask, int which_inverse,
251
                                    int mask_base, const CONV_BUF_TYPE *src0,
252
                                    int src0_stride, const CONV_BUF_TYPE *src1,
253
                                    int src1_stride, int h, int w,
254
371
                                    ConvolveParams *conv_params, int bd) {
255
371
  int round =
256
371
      2 * FILTER_BITS - conv_params->round_0 - conv_params->round_1 + (bd - 8);
257
371
  int i, j, m, diff;
258
5.25k
  for (i = 0; i < h; ++i) {
259
131k
    for (j = 0; j < w; ++j) {
260
126k
      diff = abs(src0[i * src0_stride + j] - src1[i * src1_stride + j]);
261
126k
      diff = ROUND_POWER_OF_TWO(diff, round);
262
126k
      m = clamp(mask_base + (diff / DIFF_FACTOR), 0, AOM_BLEND_A64_MAX_ALPHA);
263
126k
      mask[i * w + j] = which_inverse ? AOM_BLEND_A64_MAX_ALPHA - m : m;
264
126k
    }
265
4.88k
  }
266
371
}
267
268
void av1_build_compound_diffwtd_mask_d16_c(
269
    uint8_t *mask, DIFFWTD_MASK_TYPE mask_type, const CONV_BUF_TYPE *src0,
270
    int src0_stride, const CONV_BUF_TYPE *src1, int src1_stride, int h, int w,
271
371
    ConvolveParams *conv_params, int bd) {
272
371
  switch (mask_type) {
273
262
    case DIFFWTD_38:
274
262
      diffwtd_mask_d16(mask, 0, 38, src0, src0_stride, src1, src1_stride, h, w,
275
262
                       conv_params, bd);
276
262
      break;
277
109
    case DIFFWTD_38_INV:
278
109
      diffwtd_mask_d16(mask, 1, 38, src0, src0_stride, src1, src1_stride, h, w,
279
109
                       conv_params, bd);
280
109
      break;
281
0
    default: assert(0);
282
371
  }
283
371
}
284
285
static inline void diffwtd_mask(uint8_t *mask, int which_inverse, int mask_base,
286
                                const uint8_t *src0, int src0_stride,
287
                                const uint8_t *src1, int src1_stride, int h,
288
0
                                int w) {
289
0
  int i, j, m, diff;
290
0
  for (i = 0; i < h; ++i) {
291
0
    for (j = 0; j < w; ++j) {
292
0
      diff =
293
0
          abs((int)src0[i * src0_stride + j] - (int)src1[i * src1_stride + j]);
294
0
      m = clamp(mask_base + (diff / DIFF_FACTOR), 0, AOM_BLEND_A64_MAX_ALPHA);
295
0
      mask[i * w + j] = which_inverse ? AOM_BLEND_A64_MAX_ALPHA - m : m;
296
0
    }
297
0
  }
298
0
}
299
300
void av1_build_compound_diffwtd_mask_c(uint8_t *mask,
301
                                       DIFFWTD_MASK_TYPE mask_type,
302
                                       const uint8_t *src0, int src0_stride,
303
                                       const uint8_t *src1, int src1_stride,
304
0
                                       int h, int w) {
305
0
  switch (mask_type) {
306
0
    case DIFFWTD_38:
307
0
      diffwtd_mask(mask, 0, 38, src0, src0_stride, src1, src1_stride, h, w);
308
0
      break;
309
0
    case DIFFWTD_38_INV:
310
0
      diffwtd_mask(mask, 1, 38, src0, src0_stride, src1, src1_stride, h, w);
311
0
      break;
312
0
    default: assert(0);
313
0
  }
314
0
}
315
316
#if CONFIG_AV1_HIGHBITDEPTH
317
static AOM_FORCE_INLINE void diffwtd_mask_highbd(
318
    uint8_t *mask, int which_inverse, int mask_base, const uint16_t *src0,
319
    int src0_stride, const uint16_t *src1, int src1_stride, int h, int w,
320
0
    const unsigned int bd) {
321
0
  assert(bd >= 8);
322
0
  if (bd == 8) {
323
0
    if (which_inverse) {
324
0
      for (int i = 0; i < h; ++i) {
325
0
        for (int j = 0; j < w; ++j) {
326
0
          int diff = abs((int)src0[j] - (int)src1[j]) / DIFF_FACTOR;
327
0
          unsigned int m = negative_to_zero(mask_base + diff);
328
0
          m = AOMMIN(m, AOM_BLEND_A64_MAX_ALPHA);
329
0
          mask[j] = AOM_BLEND_A64_MAX_ALPHA - m;
330
0
        }
331
0
        src0 += src0_stride;
332
0
        src1 += src1_stride;
333
0
        mask += w;
334
0
      }
335
0
    } else {
336
0
      for (int i = 0; i < h; ++i) {
337
0
        for (int j = 0; j < w; ++j) {
338
0
          int diff = abs((int)src0[j] - (int)src1[j]) / DIFF_FACTOR;
339
0
          unsigned int m = negative_to_zero(mask_base + diff);
340
0
          m = AOMMIN(m, AOM_BLEND_A64_MAX_ALPHA);
341
0
          mask[j] = m;
342
0
        }
343
0
        src0 += src0_stride;
344
0
        src1 += src1_stride;
345
0
        mask += w;
346
0
      }
347
0
    }
348
0
  } else {
349
0
    const unsigned int bd_shift = bd - 8;
350
0
    if (which_inverse) {
351
0
      for (int i = 0; i < h; ++i) {
352
0
        for (int j = 0; j < w; ++j) {
353
0
          int diff =
354
0
              (abs((int)src0[j] - (int)src1[j]) >> bd_shift) / DIFF_FACTOR;
355
0
          unsigned int m = negative_to_zero(mask_base + diff);
356
0
          m = AOMMIN(m, AOM_BLEND_A64_MAX_ALPHA);
357
0
          mask[j] = AOM_BLEND_A64_MAX_ALPHA - m;
358
0
        }
359
0
        src0 += src0_stride;
360
0
        src1 += src1_stride;
361
0
        mask += w;
362
0
      }
363
0
    } else {
364
0
      for (int i = 0; i < h; ++i) {
365
0
        for (int j = 0; j < w; ++j) {
366
0
          int diff =
367
0
              (abs((int)src0[j] - (int)src1[j]) >> bd_shift) / DIFF_FACTOR;
368
0
          unsigned int m = negative_to_zero(mask_base + diff);
369
0
          m = AOMMIN(m, AOM_BLEND_A64_MAX_ALPHA);
370
0
          mask[j] = m;
371
0
        }
372
0
        src0 += src0_stride;
373
0
        src1 += src1_stride;
374
0
        mask += w;
375
0
      }
376
0
    }
377
0
  }
378
0
}
379
380
void av1_build_compound_diffwtd_mask_highbd_c(
381
    uint8_t *mask, DIFFWTD_MASK_TYPE mask_type, const uint8_t *src0,
382
    int src0_stride, const uint8_t *src1, int src1_stride, int h, int w,
383
0
    int bd) {
384
0
  switch (mask_type) {
385
0
    case DIFFWTD_38:
386
0
      diffwtd_mask_highbd(mask, 0, 38, CONVERT_TO_SHORTPTR(src0), src0_stride,
387
0
                          CONVERT_TO_SHORTPTR(src1), src1_stride, h, w, bd);
388
0
      break;
389
0
    case DIFFWTD_38_INV:
390
0
      diffwtd_mask_highbd(mask, 1, 38, CONVERT_TO_SHORTPTR(src0), src0_stride,
391
0
                          CONVERT_TO_SHORTPTR(src1), src1_stride, h, w, bd);
392
0
      break;
393
0
    default: assert(0);
394
0
  }
395
0
}
396
#endif  // CONFIG_AV1_HIGHBITDEPTH
397
398
/* clang-format off */
399
#if CONFIG_AV1_HIGHBITDEPTH
400
static const uint8_t ii_weights1d[MAX_SB_SIZE] = {
401
  60, 58, 56, 54, 52, 50, 48, 47, 45, 44, 42, 41, 39, 38, 37, 35, 34, 33, 32,
402
  31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 22, 21, 20, 19, 19, 18, 18, 17, 16,
403
  16, 15, 15, 14, 14, 13, 13, 12, 12, 12, 11, 11, 10, 10, 10,  9,  9,  9,  8,
404
  8,  8,  8,  7,  7,  7,  7,  6,  6,  6,  6,  6,  5,  5,  5,  5,  5,  4,  4,
405
  4,  4,  4,  4,  4,  4,  3,  3,  3,  3,  3,  3,  3,  3,  3,  2,  2,  2,  2,
406
  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  1,  1,  1,  1,  1,  1,  1,  1,
407
  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1
408
};
409
static const uint8_t ii_size_scales[BLOCK_SIZES_ALL] = {
410
    32, 16, 16, 16, 8, 8, 8, 4,
411
    4,  4,  2,  2,  2, 1, 1, 1,
412
    8,  8,  4,  4,  2, 2
413
};
414
#endif  // CONFIG_AV1_HIGHBITDEPTH
415
/* clang-format on */
416
417
#if CONFIG_AV1_HIGHBITDEPTH
418
// Used at runtime by combine_interintra_highbd() below for a per-call
419
// stack-allocated mask. The block-size-major precomputed
420
// `smooth_interintra_mask_buf` only covers block sizes with bw,bh <=
421
// MAX_WEDGE_SIZE; the highbd path may need larger sizes.
422
static inline void build_smooth_interintra_mask(uint8_t *mask, int stride,
423
                                                BLOCK_SIZE plane_bsize,
424
2.66k
                                                INTERINTRA_MODE mode) {
425
2.66k
  int i, j;
426
2.66k
  const int bw = block_size_wide[plane_bsize];
427
2.66k
  const int bh = block_size_high[plane_bsize];
428
2.66k
  const int size_scale = ii_size_scales[plane_bsize];
429
430
2.66k
  switch (mode) {
431
853
    case II_V_PRED:
432
9.46k
      for (i = 0; i < bh; ++i) {
433
8.61k
        memset(mask, ii_weights1d[i * size_scale], bw * sizeof(mask[0]));
434
8.61k
        mask += stride;
435
8.61k
      }
436
853
      break;
437
438
340
    case II_H_PRED:
439
4.88k
      for (i = 0; i < bh; ++i) {
440
64.5k
        for (j = 0; j < bw; ++j) mask[j] = ii_weights1d[j * size_scale];
441
4.54k
        mask += stride;
442
4.54k
      }
443
340
      break;
444
445
1.43k
    case II_SMOOTH_PRED:
446
12.9k
      for (i = 0; i < bh; ++i) {
447
74.0k
        for (j = 0; j < bw; ++j)
448
62.4k
          mask[j] = ii_weights1d[(i < j ? i : j) * size_scale];
449
11.5k
        mask += stride;
450
11.5k
      }
451
1.43k
      break;
452
453
36
    case II_DC_PRED:
454
36
    default:
455
764
      for (i = 0; i < bh; ++i) {
456
728
        memset(mask, 32, bw * sizeof(mask[0]));
457
728
        mask += stride;
458
728
      }
459
36
      break;
460
2.66k
  }
461
2.66k
}
462
#endif  // CONFIG_AV1_HIGHBITDEPTH
463
464
// No-op now that the wedge / inter-intra mask buffers are precomputed at
465
// codegen time and stored in `.rdata`. The symbol is kept exported because
466
// decoder.c, encoder.c, and unit tests still call it.
467
23.2k
void av1_init_wedge_masks(void) {}
468
469
static inline void build_masked_compound_no_round(
470
    uint8_t *dst, int dst_stride, const CONV_BUF_TYPE *src0, int src0_stride,
471
    const CONV_BUF_TYPE *src1, int src1_stride,
472
    const INTERINTER_COMPOUND_DATA *const comp_data, BLOCK_SIZE sb_type, int h,
473
3.94k
    int w, InterPredParams *inter_pred_params) {
474
3.94k
  const int ssy = inter_pred_params->subsampling_y;
475
3.94k
  const int ssx = inter_pred_params->subsampling_x;
476
3.94k
  const uint8_t *mask = av1_get_compound_type_mask(comp_data, sb_type);
477
3.94k
  const int mask_stride = block_size_wide[sb_type];
478
3.94k
#if CONFIG_AV1_HIGHBITDEPTH
479
3.94k
  if (inter_pred_params->use_hbd_buf) {
480
2.44k
    aom_highbd_blend_a64_d16_mask(dst, dst_stride, src0, src0_stride, src1,
481
2.44k
                                  src1_stride, mask, mask_stride, w, h, ssx,
482
2.44k
                                  ssy, &inter_pred_params->conv_params,
483
2.44k
                                  inter_pred_params->bit_depth);
484
2.44k
  } else {
485
1.49k
    aom_lowbd_blend_a64_d16_mask(dst, dst_stride, src0, src0_stride, src1,
486
1.49k
                                 src1_stride, mask, mask_stride, w, h, ssx, ssy,
487
1.49k
                                 &inter_pred_params->conv_params);
488
1.49k
  }
489
#else
490
  aom_lowbd_blend_a64_d16_mask(dst, dst_stride, src0, src0_stride, src1,
491
                               src1_stride, mask, mask_stride, w, h, ssx, ssy,
492
                               &inter_pred_params->conv_params);
493
#endif
494
3.94k
}
495
496
void av1_make_masked_inter_predictor(const uint8_t *pre, int pre_stride,
497
                                     uint8_t *dst, int dst_stride,
498
                                     InterPredParams *inter_pred_params,
499
3.94k
                                     const SubpelParams *subpel_params) {
500
3.94k
  const INTERINTER_COMPOUND_DATA *comp_data = &inter_pred_params->mask_comp;
501
3.94k
  BLOCK_SIZE sb_type = inter_pred_params->sb_type;
502
503
  // We're going to call av1_make_inter_predictor to generate a prediction into
504
  // a temporary buffer, then will blend that temporary buffer with that from
505
  // the other reference.
506
3.94k
  DECLARE_ALIGNED(32, uint8_t, tmp_buf[2 * MAX_SB_SQUARE]);
507
3.94k
  uint8_t *tmp_dst =
508
3.94k
      inter_pred_params->use_hbd_buf ? CONVERT_TO_BYTEPTR(tmp_buf) : tmp_buf;
509
510
3.94k
  const int tmp_buf_stride = MAX_SB_SIZE;
511
3.94k
  CONV_BUF_TYPE *org_dst = inter_pred_params->conv_params.dst;
512
3.94k
  int org_dst_stride = inter_pred_params->conv_params.dst_stride;
513
3.94k
  CONV_BUF_TYPE *tmp_buf16 = (CONV_BUF_TYPE *)tmp_buf;
514
3.94k
  inter_pred_params->conv_params.dst = tmp_buf16;
515
3.94k
  inter_pred_params->conv_params.dst_stride = tmp_buf_stride;
516
3.94k
  assert(inter_pred_params->conv_params.do_average == 0);
517
518
  // This will generate a prediction in tmp_buf for the second reference
519
3.94k
  av1_make_inter_predictor(pre, pre_stride, tmp_dst, MAX_SB_SIZE,
520
3.94k
                           inter_pred_params, subpel_params);
521
522
3.94k
  if (!inter_pred_params->conv_params.plane &&
523
1.32k
      comp_data->type == COMPOUND_DIFFWTD) {
524
371
    av1_build_compound_diffwtd_mask_d16(
525
371
        comp_data->seg_mask, comp_data->mask_type, org_dst, org_dst_stride,
526
371
        tmp_buf16, tmp_buf_stride, inter_pred_params->block_height,
527
371
        inter_pred_params->block_width, &inter_pred_params->conv_params,
528
371
        inter_pred_params->bit_depth);
529
371
  }
530
3.94k
  build_masked_compound_no_round(
531
3.94k
      dst, dst_stride, org_dst, org_dst_stride, tmp_buf16, tmp_buf_stride,
532
3.94k
      comp_data, sb_type, inter_pred_params->block_height,
533
3.94k
      inter_pred_params->block_width, inter_pred_params);
534
3.94k
}
535
536
void av1_dist_wtd_comp_weight_assign(const AV1_COMMON *cm,
537
                                     const MB_MODE_INFO *mbmi, int *fwd_offset,
538
                                     int *bck_offset,
539
                                     int *use_dist_wtd_comp_avg,
540
480k
                                     int is_compound) {
541
480k
  assert(fwd_offset != NULL && bck_offset != NULL);
542
480k
  if (!is_compound || mbmi->compound_idx) {
543
461k
    *fwd_offset = 8;
544
461k
    *bck_offset = 8;
545
461k
    *use_dist_wtd_comp_avg = 0;
546
461k
    return;
547
461k
  }
548
549
18.4k
  *use_dist_wtd_comp_avg = 1;
550
18.4k
  const RefCntBuffer *const bck_buf = get_ref_frame_buf(cm, mbmi->ref_frame[0]);
551
18.4k
  const RefCntBuffer *const fwd_buf = get_ref_frame_buf(cm, mbmi->ref_frame[1]);
552
18.4k
  const int cur_frame_index = cm->cur_frame->order_hint;
553
18.4k
  int bck_frame_index = 0, fwd_frame_index = 0;
554
555
18.4k
  if (bck_buf != NULL) bck_frame_index = bck_buf->order_hint;
556
18.4k
  if (fwd_buf != NULL) fwd_frame_index = fwd_buf->order_hint;
557
558
18.4k
  int d0 = clamp(abs(get_relative_dist(&cm->seq_params->order_hint_info,
559
18.4k
                                       fwd_frame_index, cur_frame_index)),
560
18.4k
                 0, MAX_FRAME_DISTANCE);
561
18.4k
  int d1 = clamp(abs(get_relative_dist(&cm->seq_params->order_hint_info,
562
18.4k
                                       cur_frame_index, bck_frame_index)),
563
18.4k
                 0, MAX_FRAME_DISTANCE);
564
565
18.4k
  const int order = d0 <= d1;
566
567
18.4k
  if (d0 == 0 || d1 == 0) {
568
2.56k
    *fwd_offset = quant_dist_lookup_table[3][order];
569
2.56k
    *bck_offset = quant_dist_lookup_table[3][1 - order];
570
2.56k
    return;
571
2.56k
  }
572
573
15.9k
  int i;
574
24.9k
  for (i = 0; i < 3; ++i) {
575
23.4k
    int c0 = quant_dist_weight[i][order];
576
23.4k
    int c1 = quant_dist_weight[i][!order];
577
23.4k
    int d0_c0 = d0 * c0;
578
23.4k
    int d1_c1 = d1 * c1;
579
23.4k
    if ((d0 > d1 && d0_c0 < d1_c1) || (d0 <= d1 && d0_c0 > d1_c1)) break;
580
23.4k
  }
581
582
15.9k
  *fwd_offset = quant_dist_lookup_table[i][order];
583
15.9k
  *bck_offset = quant_dist_lookup_table[i][1 - order];
584
15.9k
}
585
586
void av1_setup_dst_planes(struct macroblockd_plane *planes, BLOCK_SIZE bsize,
587
                          const YV12_BUFFER_CONFIG *src, int mi_row, int mi_col,
588
10.0M
                          const int plane_start, const int plane_end) {
589
  // We use AOMMIN(num_planes, MAX_MB_PLANE) instead of num_planes to quiet
590
  // the static analysis warnings.
591
39.0M
  for (int i = plane_start; i < AOMMIN(plane_end, MAX_MB_PLANE); ++i) {
592
28.9M
    struct macroblockd_plane *const pd = &planes[i];
593
28.9M
    const int is_uv = i > 0;
594
28.9M
    setup_pred_plane(&pd->dst, bsize, src->buffers[i], src->crop_widths[is_uv],
595
28.9M
                     src->crop_heights[is_uv], src->strides[is_uv], mi_row,
596
28.9M
                     mi_col, NULL, pd->subsampling_x, pd->subsampling_y);
597
28.9M
  }
598
10.0M
}
599
600
void av1_setup_pre_planes(MACROBLOCKD *xd, int idx,
601
                          const YV12_BUFFER_CONFIG *src, int mi_row, int mi_col,
602
                          const struct scale_factors *sf,
603
70.1k
                          const int num_planes) {
604
70.1k
  if (src != NULL) {
605
    // We use AOMMIN(num_planes, MAX_MB_PLANE) instead of num_planes to quiet
606
    // the static analysis warnings.
607
259k
    for (int i = 0; i < AOMMIN(num_planes, MAX_MB_PLANE); ++i) {
608
189k
      struct macroblockd_plane *const pd = &xd->plane[i];
609
189k
      const int is_uv = i > 0;
610
189k
      setup_pred_plane(&pd->pre[idx], xd->mi[0]->bsize, src->buffers[i],
611
189k
                       src->crop_widths[is_uv], src->crop_heights[is_uv],
612
189k
                       src->strides[is_uv], mi_row, mi_col, sf,
613
189k
                       pd->subsampling_x, pd->subsampling_y);
614
189k
    }
615
70.1k
  }
616
70.1k
}
617
618
// obmc_mask_N[overlap_position]
619
static const uint8_t obmc_mask_1[1] = { 64 };
620
DECLARE_ALIGNED(2, static const uint8_t, obmc_mask_2[2]) = { 45, 64 };
621
622
DECLARE_ALIGNED(4, static const uint8_t, obmc_mask_4[4]) = { 39, 50, 59, 64 };
623
624
static const uint8_t obmc_mask_8[8] = { 36, 42, 48, 53, 57, 61, 64, 64 };
625
626
static const uint8_t obmc_mask_16[16] = { 34, 37, 40, 43, 46, 49, 52, 54,
627
                                          56, 58, 60, 61, 64, 64, 64, 64 };
628
629
static const uint8_t obmc_mask_32[32] = { 33, 35, 36, 38, 40, 41, 43, 44,
630
                                          45, 47, 48, 50, 51, 52, 53, 55,
631
                                          56, 57, 58, 59, 60, 60, 61, 62,
632
                                          64, 64, 64, 64, 64, 64, 64, 64 };
633
634
static const uint8_t obmc_mask_64[64] = {
635
  33, 34, 35, 35, 36, 37, 38, 39, 40, 40, 41, 42, 43, 44, 44, 44,
636
  45, 46, 47, 47, 48, 49, 50, 51, 51, 51, 52, 52, 53, 54, 55, 56,
637
  56, 56, 57, 57, 58, 58, 59, 60, 60, 60, 60, 60, 61, 62, 62, 62,
638
  62, 62, 63, 63, 63, 63, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
639
};
640
641
12.3k
const uint8_t *av1_get_obmc_mask(int length) {
642
12.3k
  switch (length) {
643
0
    case 1: return obmc_mask_1;
644
648
    case 2: return obmc_mask_2;
645
9.61k
    case 4: return obmc_mask_4;
646
2.00k
    case 8: return obmc_mask_8;
647
94
    case 16: return obmc_mask_16;
648
19
    case 32: return obmc_mask_32;
649
0
    case 64: return obmc_mask_64;
650
0
    default: assert(0); return NULL;
651
12.3k
  }
652
12.3k
}
653
654
static inline void increment_int_ptr(MACROBLOCKD *xd, int rel_mi_row,
655
                                     int rel_mi_col, uint8_t op_mi_size,
656
                                     int dir, MB_MODE_INFO *mi, void *fun_ctxt,
657
34.1k
                                     const int num_planes) {
658
34.1k
  (void)xd;
659
34.1k
  (void)rel_mi_row;
660
34.1k
  (void)rel_mi_col;
661
34.1k
  (void)op_mi_size;
662
34.1k
  (void)dir;
663
34.1k
  (void)mi;
664
34.1k
  ++*(uint8_t *)fun_ctxt;
665
34.1k
  (void)num_planes;
666
34.1k
}
667
668
91.0k
void av1_count_overlappable_neighbors(const AV1_COMMON *cm, MACROBLOCKD *xd) {
669
91.0k
  MB_MODE_INFO *mbmi = xd->mi[0];
670
671
91.0k
  mbmi->overlappable_neighbors = 0;
672
673
91.0k
  if (!is_motion_variation_allowed_bsize(mbmi->bsize)) return;
674
675
44.2k
  foreach_overlappable_nb_above(cm, xd, INT_MAX, increment_int_ptr,
676
44.2k
                                &mbmi->overlappable_neighbors);
677
44.2k
  if (mbmi->overlappable_neighbors) return;
678
26.3k
  foreach_overlappable_nb_left(cm, xd, INT_MAX, increment_int_ptr,
679
26.3k
                               &mbmi->overlappable_neighbors);
680
26.3k
}
681
682
// HW does not support < 4x4 prediction. To limit the bandwidth requirement, if
683
// block-size of current plane is smaller than 8x8, always only blend with the
684
// left neighbor(s) (skip blending with the above side).
685
#define DISABLE_CHROMA_U8X8_OBMC 0  // 0: one-sided obmc; 1: disable
686
687
int av1_skip_u4x4_pred_in_obmc(BLOCK_SIZE bsize,
688
25.7k
                               const struct macroblockd_plane *pd, int dir) {
689
25.7k
  assert(is_motion_variation_allowed_bsize(bsize));
690
691
25.7k
  const BLOCK_SIZE bsize_plane =
692
25.7k
      get_plane_block_size(bsize, pd->subsampling_x, pd->subsampling_y);
693
25.7k
  switch (bsize_plane) {
694
#if DISABLE_CHROMA_U8X8_OBMC
695
    case BLOCK_4X4:
696
    case BLOCK_8X4:
697
    case BLOCK_4X8: return 1;
698
#else
699
24
    case BLOCK_4X4:
700
24
    case BLOCK_8X4:
701
2.32k
    case BLOCK_4X8: return dir == 0;
702
0
#endif
703
23.4k
    default: return 0;
704
25.7k
  }
705
25.7k
}
706
707
#if CONFIG_AV1_DECODER
708
4.29k
static void modify_neighbor_predictor_for_obmc(MB_MODE_INFO *mbmi) {
709
4.29k
  mbmi->ref_frame[1] = NONE_FRAME;
710
4.29k
  mbmi->interinter_comp.type = COMPOUND_AVERAGE;
711
4.29k
}
712
#endif  // CONFIG_AV1_DECODER
713
714
struct obmc_inter_pred_ctxt {
715
  uint8_t **adjacent;
716
  int *adjacent_stride;
717
};
718
719
static inline void build_obmc_inter_pred_above(
720
    MACROBLOCKD *xd, int rel_mi_row, int rel_mi_col, uint8_t op_mi_size,
721
1.59k
    int dir, MB_MODE_INFO *above_mi, void *fun_ctxt, const int num_planes) {
722
1.59k
  (void)above_mi;
723
1.59k
  (void)rel_mi_row;
724
1.59k
  (void)dir;
725
1.59k
  struct obmc_inter_pred_ctxt *ctxt = (struct obmc_inter_pred_ctxt *)fun_ctxt;
726
1.59k
  const BLOCK_SIZE bsize = xd->mi[0]->bsize;
727
1.59k
  const int overlap =
728
1.59k
      AOMMIN(block_size_high[bsize], block_size_high[BLOCK_64X64]) >> 1;
729
730
6.37k
  for (int plane = 0; plane < num_planes; ++plane) {
731
4.77k
    const struct macroblockd_plane *pd = &xd->plane[plane];
732
4.77k
    const int bw = (op_mi_size * MI_SIZE) >> pd->subsampling_x;
733
4.77k
    const int bh = overlap >> pd->subsampling_y;
734
4.77k
    const int plane_col = (rel_mi_col * MI_SIZE) >> pd->subsampling_x;
735
736
4.77k
    if (av1_skip_u4x4_pred_in_obmc(bsize, pd, 0)) continue;
737
738
4.26k
    const int dst_stride = pd->dst.stride;
739
4.26k
    uint8_t *const dst = &pd->dst.buf[plane_col];
740
4.26k
    const int tmp_stride = ctxt->adjacent_stride[plane];
741
4.26k
    const uint8_t *const tmp = &ctxt->adjacent[plane][plane_col];
742
4.26k
    const uint8_t *const mask = av1_get_obmc_mask(bh);
743
4.26k
#if CONFIG_AV1_HIGHBITDEPTH
744
4.26k
    const int is_hbd = is_cur_buf_hbd(xd);
745
4.26k
    if (is_hbd)
746
2.84k
      aom_highbd_blend_a64_vmask(dst, dst_stride, dst, dst_stride, tmp,
747
2.84k
                                 tmp_stride, mask, bw, bh, xd->bd);
748
1.41k
    else
749
1.41k
      aom_blend_a64_vmask(dst, dst_stride, dst, dst_stride, tmp, tmp_stride,
750
1.41k
                          mask, bw, bh);
751
#else
752
    aom_blend_a64_vmask(dst, dst_stride, dst, dst_stride, tmp, tmp_stride, mask,
753
                        bw, bh);
754
#endif
755
4.26k
  }
756
1.59k
}
757
758
static inline void build_obmc_inter_pred_left(
759
    MACROBLOCKD *xd, int rel_mi_row, int rel_mi_col, uint8_t op_mi_size,
760
2.70k
    int dir, MB_MODE_INFO *left_mi, void *fun_ctxt, const int num_planes) {
761
2.70k
  (void)left_mi;
762
2.70k
  (void)rel_mi_col;
763
2.70k
  (void)dir;
764
2.70k
  struct obmc_inter_pred_ctxt *ctxt = (struct obmc_inter_pred_ctxt *)fun_ctxt;
765
2.70k
  const BLOCK_SIZE bsize = xd->mi[0]->bsize;
766
2.70k
  const int overlap =
767
2.70k
      AOMMIN(block_size_wide[bsize], block_size_wide[BLOCK_64X64]) >> 1;
768
769
10.8k
  for (int plane = 0; plane < num_planes; ++plane) {
770
8.11k
    const struct macroblockd_plane *pd = &xd->plane[plane];
771
8.11k
    const int bw = overlap >> pd->subsampling_x;
772
8.11k
    const int bh = (op_mi_size * MI_SIZE) >> pd->subsampling_y;
773
8.11k
    const int plane_row = (rel_mi_row * MI_SIZE) >> pd->subsampling_y;
774
775
8.11k
    if (av1_skip_u4x4_pred_in_obmc(bsize, pd, 1)) continue;
776
777
8.11k
    const int dst_stride = pd->dst.stride;
778
8.11k
    uint8_t *const dst = &pd->dst.buf[plane_row * dst_stride];
779
8.11k
    const int tmp_stride = ctxt->adjacent_stride[plane];
780
8.11k
    const uint8_t *const tmp = &ctxt->adjacent[plane][plane_row * tmp_stride];
781
8.11k
    const uint8_t *const mask = av1_get_obmc_mask(bw);
782
783
8.11k
#if CONFIG_AV1_HIGHBITDEPTH
784
8.11k
    const int is_hbd = is_cur_buf_hbd(xd);
785
8.11k
    if (is_hbd)
786
3.84k
      aom_highbd_blend_a64_hmask(dst, dst_stride, dst, dst_stride, tmp,
787
3.84k
                                 tmp_stride, mask, bw, bh, xd->bd);
788
4.26k
    else
789
4.26k
      aom_blend_a64_hmask(dst, dst_stride, dst, dst_stride, tmp, tmp_stride,
790
4.26k
                          mask, bw, bh);
791
#else
792
    aom_blend_a64_hmask(dst, dst_stride, dst, dst_stride, tmp, tmp_stride, mask,
793
                        bw, bh);
794
#endif
795
8.11k
  }
796
2.70k
}
797
798
// This function combines motion compensated predictions that are generated by
799
// top/left neighboring blocks' inter predictors with the regular inter
800
// prediction. We assume the original prediction (bmc) is stored in
801
// xd->plane[].dst.buf
802
void av1_build_obmc_inter_prediction(const AV1_COMMON *cm, MACROBLOCKD *xd,
803
                                     uint8_t *above[MAX_MB_PLANE],
804
                                     int above_stride[MAX_MB_PLANE],
805
                                     uint8_t *left[MAX_MB_PLANE],
806
3.69k
                                     int left_stride[MAX_MB_PLANE]) {
807
3.69k
  const BLOCK_SIZE bsize = xd->mi[0]->bsize;
808
809
  // handle above row
810
3.69k
  struct obmc_inter_pred_ctxt ctxt_above = { above, above_stride };
811
3.69k
  foreach_overlappable_nb_above(cm, xd,
812
3.69k
                                max_neighbor_obmc[mi_size_wide_log2[bsize]],
813
3.69k
                                build_obmc_inter_pred_above, &ctxt_above);
814
815
  // handle left column
816
3.69k
  struct obmc_inter_pred_ctxt ctxt_left = { left, left_stride };
817
3.69k
  foreach_overlappable_nb_left(cm, xd,
818
3.69k
                               max_neighbor_obmc[mi_size_high_log2[bsize]],
819
3.69k
                               build_obmc_inter_pred_left, &ctxt_left);
820
3.69k
}
821
822
void av1_setup_obmc_dst_bufs(MACROBLOCKD *xd, uint8_t **dst_buf1,
823
3.69k
                             uint8_t **dst_buf2) {
824
3.69k
  if (is_cur_buf_hbd(xd)) {
825
1.95k
    int len = sizeof(uint16_t);
826
1.95k
    dst_buf1[0] = CONVERT_TO_BYTEPTR(xd->tmp_obmc_bufs[0]);
827
1.95k
    dst_buf1[1] =
828
1.95k
        CONVERT_TO_BYTEPTR(xd->tmp_obmc_bufs[0] + MAX_SB_SQUARE * len);
829
1.95k
    dst_buf1[2] =
830
1.95k
        CONVERT_TO_BYTEPTR(xd->tmp_obmc_bufs[0] + MAX_SB_SQUARE * 2 * len);
831
1.95k
    dst_buf2[0] = CONVERT_TO_BYTEPTR(xd->tmp_obmc_bufs[1]);
832
1.95k
    dst_buf2[1] =
833
1.95k
        CONVERT_TO_BYTEPTR(xd->tmp_obmc_bufs[1] + MAX_SB_SQUARE * len);
834
1.95k
    dst_buf2[2] =
835
1.95k
        CONVERT_TO_BYTEPTR(xd->tmp_obmc_bufs[1] + MAX_SB_SQUARE * 2 * len);
836
1.95k
  } else {
837
1.74k
    dst_buf1[0] = xd->tmp_obmc_bufs[0];
838
1.74k
    dst_buf1[1] = xd->tmp_obmc_bufs[0] + MAX_SB_SQUARE;
839
1.74k
    dst_buf1[2] = xd->tmp_obmc_bufs[0] + MAX_SB_SQUARE * 2;
840
1.74k
    dst_buf2[0] = xd->tmp_obmc_bufs[1];
841
1.74k
    dst_buf2[1] = xd->tmp_obmc_bufs[1] + MAX_SB_SQUARE;
842
1.74k
    dst_buf2[2] = xd->tmp_obmc_bufs[1] + MAX_SB_SQUARE * 2;
843
1.74k
  }
844
3.69k
}
845
846
#if CONFIG_AV1_DECODER
847
void av1_setup_build_prediction_by_above_pred(
848
    MACROBLOCKD *xd, int rel_mi_col, uint8_t above_mi_width,
849
    MB_MODE_INFO *above_mbmi, struct build_prediction_ctxt *ctxt,
850
1.59k
    const int num_planes) {
851
1.59k
  const BLOCK_SIZE a_bsize = AOMMAX(BLOCK_8X8, above_mbmi->bsize);
852
1.59k
  const int above_mi_col = xd->mi_col + rel_mi_col;
853
854
1.59k
  modify_neighbor_predictor_for_obmc(above_mbmi);
855
856
6.37k
  for (int j = 0; j < num_planes; ++j) {
857
4.77k
    struct macroblockd_plane *const pd = &xd->plane[j];
858
4.77k
    setup_pred_plane(&pd->dst, a_bsize, ctxt->tmp_buf[j], ctxt->tmp_width[j],
859
4.77k
                     ctxt->tmp_height[j], ctxt->tmp_stride[j], 0, rel_mi_col,
860
4.77k
                     NULL, pd->subsampling_x, pd->subsampling_y);
861
4.77k
  }
862
863
1.59k
  const int num_refs = 1 + has_second_ref(above_mbmi);
864
865
3.18k
  for (int ref = 0; ref < num_refs; ++ref) {
866
1.59k
    const MV_REFERENCE_FRAME frame = above_mbmi->ref_frame[ref];
867
868
1.59k
    const RefCntBuffer *const ref_buf = get_ref_frame_buf(ctxt->cm, frame);
869
1.59k
    const struct scale_factors *const sf =
870
1.59k
        get_ref_scale_factors_const(ctxt->cm, frame);
871
1.59k
    xd->block_ref_scale_factors[ref] = sf;
872
1.59k
    if ((!av1_is_valid_scale(sf)))
873
0
      aom_internal_error(xd->error_info, AOM_CODEC_UNSUP_BITSTREAM,
874
0
                         "Reference frame has invalid dimensions");
875
1.59k
    av1_setup_pre_planes(xd, ref, &ref_buf->buf, xd->mi_row, above_mi_col, sf,
876
1.59k
                         num_planes);
877
1.59k
  }
878
879
1.59k
  xd->mb_to_left_edge = 8 * MI_SIZE * (-above_mi_col);
880
1.59k
  xd->mb_to_right_edge =
881
1.59k
      ctxt->mb_to_far_edge +
882
1.59k
      (xd->width - rel_mi_col - above_mi_width) * MI_SIZE * 8;
883
1.59k
}
884
885
void av1_setup_build_prediction_by_left_pred(MACROBLOCKD *xd, int rel_mi_row,
886
                                             uint8_t left_mi_height,
887
                                             MB_MODE_INFO *left_mbmi,
888
                                             struct build_prediction_ctxt *ctxt,
889
2.70k
                                             const int num_planes) {
890
2.70k
  const BLOCK_SIZE l_bsize = AOMMAX(BLOCK_8X8, left_mbmi->bsize);
891
2.70k
  const int left_mi_row = xd->mi_row + rel_mi_row;
892
893
2.70k
  modify_neighbor_predictor_for_obmc(left_mbmi);
894
895
10.8k
  for (int j = 0; j < num_planes; ++j) {
896
8.11k
    struct macroblockd_plane *const pd = &xd->plane[j];
897
8.11k
    setup_pred_plane(&pd->dst, l_bsize, ctxt->tmp_buf[j], ctxt->tmp_width[j],
898
8.11k
                     ctxt->tmp_height[j], ctxt->tmp_stride[j], rel_mi_row, 0,
899
8.11k
                     NULL, pd->subsampling_x, pd->subsampling_y);
900
8.11k
  }
901
902
2.70k
  const int num_refs = 1 + has_second_ref(left_mbmi);
903
904
5.41k
  for (int ref = 0; ref < num_refs; ++ref) {
905
2.70k
    const MV_REFERENCE_FRAME frame = left_mbmi->ref_frame[ref];
906
907
2.70k
    const RefCntBuffer *const ref_buf = get_ref_frame_buf(ctxt->cm, frame);
908
2.70k
    const struct scale_factors *const ref_scale_factors =
909
2.70k
        get_ref_scale_factors_const(ctxt->cm, frame);
910
911
2.70k
    xd->block_ref_scale_factors[ref] = ref_scale_factors;
912
2.70k
    if ((!av1_is_valid_scale(ref_scale_factors)))
913
0
      aom_internal_error(xd->error_info, AOM_CODEC_UNSUP_BITSTREAM,
914
0
                         "Reference frame has invalid dimensions");
915
2.70k
    av1_setup_pre_planes(xd, ref, &ref_buf->buf, left_mi_row, xd->mi_col,
916
2.70k
                         ref_scale_factors, num_planes);
917
2.70k
  }
918
919
2.70k
  xd->mb_to_top_edge = GET_MV_SUBPEL(MI_SIZE * (-left_mi_row));
920
2.70k
  xd->mb_to_bottom_edge =
921
2.70k
      ctxt->mb_to_far_edge +
922
2.70k
      GET_MV_SUBPEL((xd->height - rel_mi_row - left_mi_height) * MI_SIZE);
923
2.70k
}
924
#endif  // CONFIG_AV1_DECODER
925
926
static inline void combine_interintra(
927
    INTERINTRA_MODE mode, int8_t use_wedge_interintra, int8_t wedge_index,
928
    int8_t wedge_sign, BLOCK_SIZE bsize, BLOCK_SIZE plane_bsize,
929
    uint8_t *comppred, int compstride, const uint8_t *interpred,
930
1.23k
    int interstride, const uint8_t *intrapred, int intrastride) {
931
1.23k
  const int bw = block_size_wide[plane_bsize];
932
1.23k
  const int bh = block_size_high[plane_bsize];
933
934
1.23k
  if (use_wedge_interintra) {
935
602
    if (av1_is_wedge_used(bsize)) {
936
602
      const uint8_t *mask =
937
602
          av1_get_contiguous_soft_mask(wedge_index, wedge_sign, bsize);
938
602
      const int subw = 2 * mi_size_wide[bsize] == bw;
939
602
      const int subh = 2 * mi_size_high[bsize] == bh;
940
602
      aom_blend_a64_mask(comppred, compstride, intrapred, intrastride,
941
602
                         interpred, interstride, mask, block_size_wide[bsize],
942
602
                         bw, bh, subw, subh);
943
602
    }
944
602
    return;
945
602
  }
946
947
631
  const uint8_t *mask = smooth_interintra_mask_buf[mode][plane_bsize];
948
631
  aom_blend_a64_mask(comppred, compstride, intrapred, intrastride, interpred,
949
631
                     interstride, mask, bw, bw, bh, 0, 0);
950
631
}
951
952
#if CONFIG_AV1_HIGHBITDEPTH
953
static inline void combine_interintra_highbd(
954
    INTERINTRA_MODE mode, int8_t use_wedge_interintra, int8_t wedge_index,
955
    int8_t wedge_sign, BLOCK_SIZE bsize, BLOCK_SIZE plane_bsize,
956
    uint8_t *comppred8, int compstride, const uint8_t *interpred8,
957
4.26k
    int interstride, const uint8_t *intrapred8, int intrastride, int bd) {
958
4.26k
  const int bw = block_size_wide[plane_bsize];
959
4.26k
  const int bh = block_size_high[plane_bsize];
960
961
4.26k
  if (use_wedge_interintra) {
962
1.59k
    if (av1_is_wedge_used(bsize)) {
963
1.59k
      const uint8_t *mask =
964
1.59k
          av1_get_contiguous_soft_mask(wedge_index, wedge_sign, bsize);
965
1.59k
      const int subh = 2 * mi_size_high[bsize] == bh;
966
1.59k
      const int subw = 2 * mi_size_wide[bsize] == bw;
967
1.59k
      aom_highbd_blend_a64_mask(comppred8, compstride, intrapred8, intrastride,
968
1.59k
                                interpred8, interstride, mask,
969
1.59k
                                block_size_wide[bsize], bw, bh, subw, subh, bd);
970
1.59k
    }
971
1.59k
    return;
972
1.59k
  }
973
974
2.66k
  uint8_t mask[MAX_SB_SQUARE];
975
2.66k
  build_smooth_interintra_mask(mask, bw, plane_bsize, mode);
976
2.66k
  aom_highbd_blend_a64_mask(comppred8, compstride, intrapred8, intrastride,
977
2.66k
                            interpred8, interstride, mask, bw, bw, bh, 0, 0,
978
2.66k
                            bd);
979
2.66k
}
980
#endif
981
982
void av1_build_intra_predictors_for_interintra(const AV1_COMMON *cm,
983
                                               MACROBLOCKD *xd,
984
                                               BLOCK_SIZE bsize, int plane,
985
                                               const BUFFER_SET *ctx,
986
5.49k
                                               uint8_t *dst, int dst_stride) {
987
5.49k
  struct macroblockd_plane *const pd = &xd->plane[plane];
988
5.49k
  const int ssx = xd->plane[plane].subsampling_x;
989
5.49k
  const int ssy = xd->plane[plane].subsampling_y;
990
5.49k
  BLOCK_SIZE plane_bsize = get_plane_block_size(bsize, ssx, ssy);
991
5.49k
  PREDICTION_MODE mode = interintra_to_intra_mode[xd->mi[0]->interintra_mode];
992
5.49k
  assert(xd->mi[0]->angle_delta[PLANE_TYPE_Y] == 0);
993
5.49k
  assert(xd->mi[0]->angle_delta[PLANE_TYPE_UV] == 0);
994
5.49k
  assert(xd->mi[0]->filter_intra_mode_info.use_filter_intra == 0);
995
5.49k
  assert(xd->mi[0]->use_intrabc == 0);
996
5.49k
  const SequenceHeader *seq_params = cm->seq_params;
997
998
5.49k
  av1_predict_intra_block(xd, seq_params->sb_size,
999
5.49k
                          seq_params->enable_intra_edge_filter, pd->width,
1000
5.49k
                          pd->height, max_txsize_rect_lookup[plane_bsize], mode,
1001
5.49k
                          0, 0, FILTER_INTRA_MODES, ctx->plane[plane],
1002
5.49k
                          ctx->stride[plane], dst, dst_stride, 0, 0, plane);
1003
5.49k
}
1004
1005
void av1_combine_interintra(MACROBLOCKD *xd, BLOCK_SIZE bsize, int plane,
1006
                            const uint8_t *inter_pred, int inter_stride,
1007
5.49k
                            const uint8_t *intra_pred, int intra_stride) {
1008
5.49k
  const int ssx = xd->plane[plane].subsampling_x;
1009
5.49k
  const int ssy = xd->plane[plane].subsampling_y;
1010
5.49k
  const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize, ssx, ssy);
1011
5.49k
#if CONFIG_AV1_HIGHBITDEPTH
1012
5.49k
  if (is_cur_buf_hbd(xd)) {
1013
4.26k
    combine_interintra_highbd(
1014
4.26k
        xd->mi[0]->interintra_mode, xd->mi[0]->use_wedge_interintra,
1015
4.26k
        xd->mi[0]->interintra_wedge_index, INTERINTRA_WEDGE_SIGN, bsize,
1016
4.26k
        plane_bsize, xd->plane[plane].dst.buf, xd->plane[plane].dst.stride,
1017
4.26k
        inter_pred, inter_stride, intra_pred, intra_stride, xd->bd);
1018
4.26k
    return;
1019
4.26k
  }
1020
1.23k
#endif
1021
1.23k
  combine_interintra(
1022
1.23k
      xd->mi[0]->interintra_mode, xd->mi[0]->use_wedge_interintra,
1023
1.23k
      xd->mi[0]->interintra_wedge_index, INTERINTRA_WEDGE_SIGN, bsize,
1024
1.23k
      plane_bsize, xd->plane[plane].dst.buf, xd->plane[plane].dst.stride,
1025
1.23k
      inter_pred, inter_stride, intra_pred, intra_stride);
1026
1.23k
}
1027
1028
// build interintra_predictors for one plane
1029
void av1_build_interintra_predictor(const AV1_COMMON *cm, MACROBLOCKD *xd,
1030
                                    uint8_t *pred, int stride,
1031
                                    const BUFFER_SET *ctx, int plane,
1032
5.49k
                                    BLOCK_SIZE bsize) {
1033
5.49k
  assert(bsize < BLOCK_SIZES_ALL);
1034
5.49k
  if (is_cur_buf_hbd(xd)) {
1035
4.26k
    DECLARE_ALIGNED(16, uint16_t, intrapredictor[MAX_SB_SQUARE]);
1036
4.26k
    av1_build_intra_predictors_for_interintra(
1037
4.26k
        cm, xd, bsize, plane, ctx, CONVERT_TO_BYTEPTR(intrapredictor),
1038
4.26k
        MAX_SB_SIZE);
1039
4.26k
    av1_combine_interintra(xd, bsize, plane, pred, stride,
1040
4.26k
                           CONVERT_TO_BYTEPTR(intrapredictor), MAX_SB_SIZE);
1041
4.26k
  } else {
1042
1.23k
    DECLARE_ALIGNED(16, uint8_t, intrapredictor[MAX_SB_SQUARE]);
1043
1.23k
    av1_build_intra_predictors_for_interintra(cm, xd, bsize, plane, ctx,
1044
1.23k
                                              intrapredictor, MAX_SB_SIZE);
1045
1.23k
    av1_combine_interintra(xd, bsize, plane, pred, stride, intrapredictor,
1046
1.23k
                           MAX_SB_SIZE);
1047
1.23k
  }
1048
5.49k
}