Coverage Report

Created: 2022-08-24 06:15

/src/aom/av1/encoder/reconinter_enc.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
#include "av1/encoder/reconinter_enc.h"
30
31
static void enc_calc_subpel_params(const MV *const src_mv,
32
                                   InterPredParams *const inter_pred_params,
33
                                   MACROBLOCKD *xd, int mi_x, int mi_y, int ref,
34
                                   uint8_t **mc_buf, uint8_t **pre,
35
                                   SubpelParams *subpel_params,
36
0
                                   int *src_stride) {
37
  // These are part of the function signature to use this function through a
38
  // function pointer. See typedef of 'CalcSubpelParamsFunc'.
39
0
  (void)xd;
40
0
  (void)mi_x;
41
0
  (void)mi_y;
42
0
  (void)ref;
43
0
  (void)mc_buf;
44
45
0
  const struct scale_factors *sf = inter_pred_params->scale_factors;
46
47
0
  struct buf_2d *pre_buf = &inter_pred_params->ref_frame_buf;
48
0
  int ssx = inter_pred_params->subsampling_x;
49
0
  int ssy = inter_pred_params->subsampling_y;
50
0
  int orig_pos_y = inter_pred_params->pix_row << SUBPEL_BITS;
51
0
  orig_pos_y += src_mv->row * (1 << (1 - ssy));
52
0
  int orig_pos_x = inter_pred_params->pix_col << SUBPEL_BITS;
53
0
  orig_pos_x += src_mv->col * (1 << (1 - ssx));
54
0
  int pos_y = sf->scale_value_y(orig_pos_y, sf);
55
0
  int pos_x = sf->scale_value_x(orig_pos_x, sf);
56
0
  pos_x += SCALE_EXTRA_OFF;
57
0
  pos_y += SCALE_EXTRA_OFF;
58
59
0
  const int top = -AOM_LEFT_TOP_MARGIN_SCALED(ssy);
60
0
  const int left = -AOM_LEFT_TOP_MARGIN_SCALED(ssx);
61
0
  const int bottom = (pre_buf->height + AOM_INTERP_EXTEND) << SCALE_SUBPEL_BITS;
62
0
  const int right = (pre_buf->width + AOM_INTERP_EXTEND) << SCALE_SUBPEL_BITS;
63
0
  pos_y = clamp(pos_y, top, bottom);
64
0
  pos_x = clamp(pos_x, left, right);
65
66
0
  subpel_params->subpel_x = pos_x & SCALE_SUBPEL_MASK;
67
0
  subpel_params->subpel_y = pos_y & SCALE_SUBPEL_MASK;
68
0
  subpel_params->xs = sf->x_step_q4;
69
0
  subpel_params->ys = sf->y_step_q4;
70
0
  *pre = pre_buf->buf0 + (pos_y >> SCALE_SUBPEL_BITS) * pre_buf->stride +
71
0
         (pos_x >> SCALE_SUBPEL_BITS);
72
0
  *src_stride = pre_buf->stride;
73
0
}
74
75
void av1_enc_build_one_inter_predictor(uint8_t *dst, int dst_stride,
76
                                       const MV *src_mv,
77
0
                                       InterPredParams *inter_pred_params) {
78
0
  av1_build_one_inter_predictor(
79
0
      dst, dst_stride, src_mv, inter_pred_params, NULL /* xd */, 0 /* mi_x */,
80
0
      0 /* mi_y */, inter_pred_params->conv_params.do_average /* ref */,
81
0
      NULL /* mc_buf */, enc_calc_subpel_params);
82
0
}
83
84
static void enc_build_inter_predictors(const AV1_COMMON *cm, MACROBLOCKD *xd,
85
                                       int plane, const MB_MODE_INFO *mi,
86
0
                                       int bw, int bh, int mi_x, int mi_y) {
87
0
  av1_build_inter_predictors(cm, xd, plane, mi, 0 /* build_for_obmc */, bw, bh,
88
0
                             mi_x, mi_y, NULL /* mc_buf */,
89
0
                             enc_calc_subpel_params);
90
0
}
91
92
0
void av1_enc_build_inter_predictor_y(MACROBLOCKD *xd, int mi_row, int mi_col) {
93
0
  const int mi_x = mi_col * MI_SIZE;
94
0
  const int mi_y = mi_row * MI_SIZE;
95
0
  struct macroblockd_plane *const pd = &xd->plane[AOM_PLANE_Y];
96
0
  InterPredParams inter_pred_params;
97
98
0
  struct buf_2d *const dst_buf = &pd->dst;
99
0
  uint8_t *const dst = dst_buf->buf;
100
0
  const MV mv = xd->mi[0]->mv[0].as_mv;
101
0
  const struct scale_factors *const sf = xd->block_ref_scale_factors[0];
102
103
0
  av1_init_inter_params(&inter_pred_params, pd->width, pd->height, mi_y, mi_x,
104
0
                        pd->subsampling_x, pd->subsampling_y, xd->bd,
105
0
                        is_cur_buf_hbd(xd), false, sf, pd->pre,
106
0
                        xd->mi[0]->interp_filters);
107
108
0
  inter_pred_params.conv_params = get_conv_params_no_round(
109
0
      0, AOM_PLANE_Y, xd->tmp_conv_dst, MAX_SB_SIZE, false, xd->bd);
110
111
0
  inter_pred_params.conv_params.use_dist_wtd_comp_avg = 0;
112
0
  av1_enc_build_one_inter_predictor(dst, dst_buf->stride, &mv,
113
0
                                    &inter_pred_params);
114
0
}
115
116
void av1_enc_build_inter_predictor(const AV1_COMMON *cm, MACROBLOCKD *xd,
117
                                   int mi_row, int mi_col,
118
                                   const BUFFER_SET *ctx, BLOCK_SIZE bsize,
119
0
                                   int plane_from, int plane_to) {
120
0
  for (int plane = plane_from; plane <= plane_to; ++plane) {
121
0
    if (plane && !xd->is_chroma_ref) break;
122
0
    const int mi_x = mi_col * MI_SIZE;
123
0
    const int mi_y = mi_row * MI_SIZE;
124
0
    enc_build_inter_predictors(cm, xd, plane, xd->mi[0], xd->plane[plane].width,
125
0
                               xd->plane[plane].height, mi_x, mi_y);
126
127
0
    if (is_interintra_pred(xd->mi[0])) {
128
0
      BUFFER_SET default_ctx = {
129
0
        { xd->plane[0].dst.buf, xd->plane[1].dst.buf, xd->plane[2].dst.buf },
130
0
        { xd->plane[0].dst.stride, xd->plane[1].dst.stride,
131
0
          xd->plane[2].dst.stride }
132
0
      };
133
0
      if (!ctx) {
134
0
        ctx = &default_ctx;
135
0
      }
136
0
      av1_build_interintra_predictor(cm, xd, xd->plane[plane].dst.buf,
137
0
                                     xd->plane[plane].dst.stride, ctx, plane,
138
0
                                     bsize);
139
0
    }
140
0
  }
141
0
}
142
143
static void setup_address_for_obmc(MACROBLOCKD *xd, int mi_row_offset,
144
                                   int mi_col_offset, MB_MODE_INFO *ref_mbmi,
145
                                   struct build_prediction_ctxt *ctxt,
146
0
                                   const int num_planes) {
147
0
  const BLOCK_SIZE ref_bsize = AOMMAX(BLOCK_8X8, ref_mbmi->bsize);
148
0
  const int ref_mi_row = xd->mi_row + mi_row_offset;
149
0
  const int ref_mi_col = xd->mi_col + mi_col_offset;
150
151
0
  for (int plane = 0; plane < num_planes; ++plane) {
152
0
    struct macroblockd_plane *const pd = &xd->plane[plane];
153
0
    setup_pred_plane(&pd->dst, ref_bsize, ctxt->tmp_buf[plane],
154
0
                     ctxt->tmp_width[plane], ctxt->tmp_height[plane],
155
0
                     ctxt->tmp_stride[plane], mi_row_offset, mi_col_offset,
156
0
                     NULL, pd->subsampling_x, pd->subsampling_y);
157
0
  }
158
159
0
  const MV_REFERENCE_FRAME frame = ref_mbmi->ref_frame[0];
160
161
0
  const RefCntBuffer *const ref_buf = get_ref_frame_buf(ctxt->cm, frame);
162
0
  const struct scale_factors *const sf =
163
0
      get_ref_scale_factors_const(ctxt->cm, frame);
164
165
0
  xd->block_ref_scale_factors[0] = sf;
166
0
  if ((!av1_is_valid_scale(sf)))
167
0
    aom_internal_error(xd->error_info, AOM_CODEC_UNSUP_BITSTREAM,
168
0
                       "Reference frame has invalid dimensions");
169
170
0
  av1_setup_pre_planes(xd, 0, &ref_buf->buf, ref_mi_row, ref_mi_col, sf,
171
0
                       num_planes);
172
0
}
173
174
static INLINE void build_obmc_prediction(MACROBLOCKD *xd, int rel_mi_row,
175
                                         int rel_mi_col, uint8_t op_mi_size,
176
                                         int dir, MB_MODE_INFO *above_mbmi,
177
0
                                         void *fun_ctxt, const int num_planes) {
178
0
  struct build_prediction_ctxt *ctxt = (struct build_prediction_ctxt *)fun_ctxt;
179
0
  setup_address_for_obmc(xd, rel_mi_row, rel_mi_col, above_mbmi, ctxt,
180
0
                         num_planes);
181
182
0
  const int mi_x = (xd->mi_col + rel_mi_col) << MI_SIZE_LOG2;
183
0
  const int mi_y = (xd->mi_row + rel_mi_row) << MI_SIZE_LOG2;
184
185
0
  const BLOCK_SIZE bsize = xd->mi[0]->bsize;
186
187
0
  InterPredParams inter_pred_params;
188
189
0
  for (int j = 0; j < num_planes; ++j) {
190
0
    const struct macroblockd_plane *pd = &xd->plane[j];
191
0
    int bw = 0, bh = 0;
192
193
0
    if (dir) {
194
      // prepare left reference block size
195
0
      bw = clamp(block_size_wide[bsize] >> (pd->subsampling_x + 1), 4,
196
0
                 block_size_wide[BLOCK_64X64] >> (pd->subsampling_x + 1));
197
0
      bh = (op_mi_size << MI_SIZE_LOG2) >> pd->subsampling_y;
198
0
    } else {
199
      // prepare above reference block size
200
0
      bw = (op_mi_size * MI_SIZE) >> pd->subsampling_x;
201
0
      bh = clamp(block_size_high[bsize] >> (pd->subsampling_y + 1), 4,
202
0
                 block_size_high[BLOCK_64X64] >> (pd->subsampling_y + 1));
203
0
    }
204
205
0
    if (av1_skip_u4x4_pred_in_obmc(bsize, pd, dir)) continue;
206
207
0
    const struct buf_2d *const pre_buf = &pd->pre[0];
208
0
    const MV mv = above_mbmi->mv[0].as_mv;
209
210
0
    av1_init_inter_params(&inter_pred_params, bw, bh, mi_y >> pd->subsampling_y,
211
0
                          mi_x >> pd->subsampling_x, pd->subsampling_x,
212
0
                          pd->subsampling_y, xd->bd, is_cur_buf_hbd(xd), 0,
213
0
                          xd->block_ref_scale_factors[0], pre_buf,
214
0
                          above_mbmi->interp_filters);
215
0
    inter_pred_params.conv_params = get_conv_params(0, j, xd->bd);
216
217
0
    av1_enc_build_one_inter_predictor(pd->dst.buf, pd->dst.stride, &mv,
218
0
                                      &inter_pred_params);
219
0
  }
220
0
}
221
222
void av1_build_prediction_by_above_preds(const AV1_COMMON *cm, MACROBLOCKD *xd,
223
                                         uint8_t *tmp_buf[MAX_MB_PLANE],
224
                                         int tmp_width[MAX_MB_PLANE],
225
                                         int tmp_height[MAX_MB_PLANE],
226
0
                                         int tmp_stride[MAX_MB_PLANE]) {
227
0
  if (!xd->up_available) return;
228
0
  struct build_prediction_ctxt ctxt = {
229
0
    cm, tmp_buf, tmp_width, tmp_height, tmp_stride, xd->mb_to_right_edge, NULL
230
0
  };
231
0
  BLOCK_SIZE bsize = xd->mi[0]->bsize;
232
0
  foreach_overlappable_nb_above(cm, xd,
233
0
                                max_neighbor_obmc[mi_size_wide_log2[bsize]],
234
0
                                build_obmc_prediction, &ctxt);
235
0
}
236
237
void av1_build_prediction_by_left_preds(const AV1_COMMON *cm, MACROBLOCKD *xd,
238
                                        uint8_t *tmp_buf[MAX_MB_PLANE],
239
                                        int tmp_width[MAX_MB_PLANE],
240
                                        int tmp_height[MAX_MB_PLANE],
241
0
                                        int tmp_stride[MAX_MB_PLANE]) {
242
0
  if (!xd->left_available) return;
243
0
  struct build_prediction_ctxt ctxt = {
244
0
    cm, tmp_buf, tmp_width, tmp_height, tmp_stride, xd->mb_to_bottom_edge, NULL
245
0
  };
246
0
  BLOCK_SIZE bsize = xd->mi[0]->bsize;
247
0
  foreach_overlappable_nb_left(cm, xd,
248
0
                               max_neighbor_obmc[mi_size_high_log2[bsize]],
249
0
                               build_obmc_prediction, &ctxt);
250
0
}
251
252
0
void av1_build_obmc_inter_predictors_sb(const AV1_COMMON *cm, MACROBLOCKD *xd) {
253
0
  const int num_planes = av1_num_planes(cm);
254
0
  uint8_t *dst_buf1[MAX_MB_PLANE], *dst_buf2[MAX_MB_PLANE];
255
0
  int dst_stride1[MAX_MB_PLANE] = { MAX_SB_SIZE, MAX_SB_SIZE, MAX_SB_SIZE };
256
0
  int dst_stride2[MAX_MB_PLANE] = { MAX_SB_SIZE, MAX_SB_SIZE, MAX_SB_SIZE };
257
0
  int dst_width1[MAX_MB_PLANE] = { MAX_SB_SIZE, MAX_SB_SIZE, MAX_SB_SIZE };
258
0
  int dst_width2[MAX_MB_PLANE] = { MAX_SB_SIZE, MAX_SB_SIZE, MAX_SB_SIZE };
259
0
  int dst_height1[MAX_MB_PLANE] = { MAX_SB_SIZE, MAX_SB_SIZE, MAX_SB_SIZE };
260
0
  int dst_height2[MAX_MB_PLANE] = { MAX_SB_SIZE, MAX_SB_SIZE, MAX_SB_SIZE };
261
262
0
  av1_setup_obmc_dst_bufs(xd, dst_buf1, dst_buf2);
263
264
0
  const int mi_row = xd->mi_row;
265
0
  const int mi_col = xd->mi_col;
266
0
  av1_build_prediction_by_above_preds(cm, xd, dst_buf1, dst_width1, dst_height1,
267
0
                                      dst_stride1);
268
0
  av1_build_prediction_by_left_preds(cm, xd, dst_buf2, dst_width2, dst_height2,
269
0
                                     dst_stride2);
270
0
  av1_setup_dst_planes(xd->plane, xd->mi[0]->bsize, &cm->cur_frame->buf, mi_row,
271
0
                       mi_col, 0, num_planes);
272
0
  av1_build_obmc_inter_prediction(cm, xd, dst_buf1, dst_stride1, dst_buf2,
273
0
                                  dst_stride2);
274
0
}
275
276
void av1_build_inter_predictors_for_planes_single_buf(
277
    MACROBLOCKD *xd, BLOCK_SIZE bsize, int plane_from, int plane_to, int ref,
278
0
    uint8_t *ext_dst[], int ext_dst_stride[]) {
279
0
  assert(bsize < BLOCK_SIZES_ALL);
280
0
  const MB_MODE_INFO *mi = xd->mi[0];
281
0
  const int mi_row = xd->mi_row;
282
0
  const int mi_col = xd->mi_col;
283
0
  const int mi_x = mi_col * MI_SIZE;
284
0
  const int mi_y = mi_row * MI_SIZE;
285
0
  WarpTypesAllowed warp_types;
286
0
  const WarpedMotionParams *const wm = &xd->global_motion[mi->ref_frame[ref]];
287
0
  warp_types.global_warp_allowed = is_global_mv_block(mi, wm->wmtype);
288
0
  warp_types.local_warp_allowed = mi->motion_mode == WARPED_CAUSAL;
289
290
0
  for (int plane = plane_from; plane <= plane_to; ++plane) {
291
0
    const struct macroblockd_plane *pd = &xd->plane[plane];
292
0
    const BLOCK_SIZE plane_bsize =
293
0
        get_plane_block_size(bsize, pd->subsampling_x, pd->subsampling_y);
294
0
    const int bw = block_size_wide[plane_bsize];
295
0
    const int bh = block_size_high[plane_bsize];
296
297
0
    InterPredParams inter_pred_params;
298
299
0
    av1_init_inter_params(&inter_pred_params, bw, bh, mi_y >> pd->subsampling_y,
300
0
                          mi_x >> pd->subsampling_x, pd->subsampling_x,
301
0
                          pd->subsampling_y, xd->bd, is_cur_buf_hbd(xd), 0,
302
0
                          xd->block_ref_scale_factors[ref], &pd->pre[ref],
303
0
                          mi->interp_filters);
304
0
    inter_pred_params.conv_params = get_conv_params(0, plane, xd->bd);
305
0
    av1_init_warp_params(&inter_pred_params, &warp_types, ref, xd, mi);
306
307
0
    uint8_t *const dst = get_buf_by_bd(xd, ext_dst[plane]);
308
0
    const MV mv = mi->mv[ref].as_mv;
309
310
0
    av1_enc_build_one_inter_predictor(dst, ext_dst_stride[plane], &mv,
311
0
                                      &inter_pred_params);
312
0
  }
313
0
}
314
315
static void build_masked_compound(
316
    uint8_t *dst, int dst_stride, const uint8_t *src0, int src0_stride,
317
    const uint8_t *src1, int src1_stride,
318
    const INTERINTER_COMPOUND_DATA *const comp_data, BLOCK_SIZE sb_type, int h,
319
0
    int w) {
320
  // Derive subsampling from h and w passed in. May be refactored to
321
  // pass in subsampling factors directly.
322
0
  const int subh = (2 << mi_size_high_log2[sb_type]) == h;
323
0
  const int subw = (2 << mi_size_wide_log2[sb_type]) == w;
324
0
  const uint8_t *mask = av1_get_compound_type_mask(comp_data, sb_type);
325
0
  aom_blend_a64_mask(dst, dst_stride, src0, src0_stride, src1, src1_stride,
326
0
                     mask, block_size_wide[sb_type], w, h, subw, subh);
327
0
}
328
329
#if CONFIG_AV1_HIGHBITDEPTH
330
static void build_masked_compound_highbd(
331
    uint8_t *dst_8, int dst_stride, const uint8_t *src0_8, int src0_stride,
332
    const uint8_t *src1_8, int src1_stride,
333
    const INTERINTER_COMPOUND_DATA *const comp_data, BLOCK_SIZE sb_type, int h,
334
0
    int w, int bd) {
335
  // Derive subsampling from h and w passed in. May be refactored to
336
  // pass in subsampling factors directly.
337
0
  const int subh = (2 << mi_size_high_log2[sb_type]) == h;
338
0
  const int subw = (2 << mi_size_wide_log2[sb_type]) == w;
339
0
  const uint8_t *mask = av1_get_compound_type_mask(comp_data, sb_type);
340
  // const uint8_t *mask =
341
  //     av1_get_contiguous_soft_mask(wedge_index, wedge_sign, sb_type);
342
0
  aom_highbd_blend_a64_mask(dst_8, dst_stride, src0_8, src0_stride, src1_8,
343
0
                            src1_stride, mask, block_size_wide[sb_type], w, h,
344
0
                            subw, subh, bd);
345
0
}
346
#endif
347
348
static void build_wedge_inter_predictor_from_buf(
349
    MACROBLOCKD *xd, int plane, int x, int y, int w, int h, uint8_t *ext_dst0,
350
0
    int ext_dst_stride0, uint8_t *ext_dst1, int ext_dst_stride1) {
351
0
  MB_MODE_INFO *const mbmi = xd->mi[0];
352
0
  const int is_compound = has_second_ref(mbmi);
353
0
  MACROBLOCKD_PLANE *const pd = &xd->plane[plane];
354
0
  struct buf_2d *const dst_buf = &pd->dst;
355
0
  uint8_t *const dst = dst_buf->buf + dst_buf->stride * y + x;
356
0
  mbmi->interinter_comp.seg_mask = xd->seg_mask;
357
0
  const INTERINTER_COMPOUND_DATA *comp_data = &mbmi->interinter_comp;
358
0
  const int is_hbd = is_cur_buf_hbd(xd);
359
360
0
  if (is_compound && is_masked_compound_type(comp_data->type)) {
361
0
    if (!plane && comp_data->type == COMPOUND_DIFFWTD) {
362
0
#if CONFIG_AV1_HIGHBITDEPTH
363
0
      if (is_hbd) {
364
0
        av1_build_compound_diffwtd_mask_highbd(
365
0
            comp_data->seg_mask, comp_data->mask_type,
366
0
            CONVERT_TO_BYTEPTR(ext_dst0), ext_dst_stride0,
367
0
            CONVERT_TO_BYTEPTR(ext_dst1), ext_dst_stride1, h, w, xd->bd);
368
0
      } else {
369
0
        av1_build_compound_diffwtd_mask(
370
0
            comp_data->seg_mask, comp_data->mask_type, ext_dst0,
371
0
            ext_dst_stride0, ext_dst1, ext_dst_stride1, h, w);
372
0
      }
373
#else
374
      (void)is_hbd;
375
      av1_build_compound_diffwtd_mask(comp_data->seg_mask, comp_data->mask_type,
376
                                      ext_dst0, ext_dst_stride0, ext_dst1,
377
                                      ext_dst_stride1, h, w);
378
#endif  // CONFIG_AV1_HIGHBITDEPTH
379
0
    }
380
0
#if CONFIG_AV1_HIGHBITDEPTH
381
0
    if (is_hbd) {
382
0
      build_masked_compound_highbd(
383
0
          dst, dst_buf->stride, CONVERT_TO_BYTEPTR(ext_dst0), ext_dst_stride0,
384
0
          CONVERT_TO_BYTEPTR(ext_dst1), ext_dst_stride1, comp_data, mbmi->bsize,
385
0
          h, w, xd->bd);
386
0
    } else {
387
0
      build_masked_compound(dst, dst_buf->stride, ext_dst0, ext_dst_stride0,
388
0
                            ext_dst1, ext_dst_stride1, comp_data, mbmi->bsize,
389
0
                            h, w);
390
0
    }
391
#else
392
    build_masked_compound(dst, dst_buf->stride, ext_dst0, ext_dst_stride0,
393
                          ext_dst1, ext_dst_stride1, comp_data, mbmi->bsize, h,
394
                          w);
395
#endif
396
0
  } else {
397
0
#if CONFIG_AV1_HIGHBITDEPTH
398
0
    if (is_hbd) {
399
0
      aom_highbd_convolve_copy(CONVERT_TO_SHORTPTR(ext_dst0), ext_dst_stride0,
400
0
                               CONVERT_TO_SHORTPTR(dst), dst_buf->stride, w, h);
401
0
    } else {
402
0
      aom_convolve_copy(ext_dst0, ext_dst_stride0, dst, dst_buf->stride, w, h);
403
0
    }
404
#else
405
    aom_convolve_copy(ext_dst0, ext_dst_stride0, dst, dst_buf->stride, w, h);
406
#endif
407
0
  }
408
0
}
409
410
void av1_build_wedge_inter_predictor_from_buf(MACROBLOCKD *xd, BLOCK_SIZE bsize,
411
                                              int plane_from, int plane_to,
412
                                              uint8_t *ext_dst0[],
413
                                              int ext_dst_stride0[],
414
                                              uint8_t *ext_dst1[],
415
0
                                              int ext_dst_stride1[]) {
416
0
  int plane;
417
0
  assert(bsize < BLOCK_SIZES_ALL);
418
0
  for (plane = plane_from; plane <= plane_to; ++plane) {
419
0
    const BLOCK_SIZE plane_bsize = get_plane_block_size(
420
0
        bsize, xd->plane[plane].subsampling_x, xd->plane[plane].subsampling_y);
421
0
    const int bw = block_size_wide[plane_bsize];
422
0
    const int bh = block_size_high[plane_bsize];
423
0
    build_wedge_inter_predictor_from_buf(
424
0
        xd, plane, 0, 0, bw, bh, ext_dst0[plane], ext_dst_stride0[plane],
425
0
        ext_dst1[plane], ext_dst_stride1[plane]);
426
0
  }
427
0
}
428
429
// Get pred block from up-sampled reference.
430
void aom_upsampled_pred_c(MACROBLOCKD *xd, const AV1_COMMON *const cm,
431
                          int mi_row, int mi_col, const MV *const mv,
432
                          uint8_t *comp_pred, int width, int height,
433
                          int subpel_x_q3, int subpel_y_q3, const uint8_t *ref,
434
0
                          int ref_stride, int subpel_search) {
435
  // expect xd == NULL only in tests
436
0
  if (xd != NULL) {
437
0
    const MB_MODE_INFO *mi = xd->mi[0];
438
0
    const int ref_num = 0;
439
0
    const int is_intrabc = is_intrabc_block(mi);
440
0
    const struct scale_factors *const sf =
441
0
        is_intrabc ? &cm->sf_identity : xd->block_ref_scale_factors[ref_num];
442
0
    const int is_scaled = av1_is_scaled(sf);
443
444
0
    if (is_scaled) {
445
0
      int plane = 0;
446
0
      const int mi_x = mi_col * MI_SIZE;
447
0
      const int mi_y = mi_row * MI_SIZE;
448
0
      const struct macroblockd_plane *const pd = &xd->plane[plane];
449
0
      const struct buf_2d *const dst_buf = &pd->dst;
450
0
      const struct buf_2d *const pre_buf =
451
0
          is_intrabc ? dst_buf : &pd->pre[ref_num];
452
453
0
      InterPredParams inter_pred_params;
454
0
      inter_pred_params.conv_params = get_conv_params(0, plane, xd->bd);
455
0
      const int_interpfilters filters =
456
0
          av1_broadcast_interp_filter(EIGHTTAP_REGULAR);
457
0
      av1_init_inter_params(
458
0
          &inter_pred_params, width, height, mi_y >> pd->subsampling_y,
459
0
          mi_x >> pd->subsampling_x, pd->subsampling_x, pd->subsampling_y,
460
0
          xd->bd, is_cur_buf_hbd(xd), is_intrabc, sf, pre_buf, filters);
461
0
      av1_enc_build_one_inter_predictor(comp_pred, width, mv,
462
0
                                        &inter_pred_params);
463
0
      return;
464
0
    }
465
0
  }
466
467
0
  const InterpFilterParams *filter = av1_get_filter(subpel_search);
468
469
0
  if (!subpel_x_q3 && !subpel_y_q3) {
470
0
    for (int i = 0; i < height; i++) {
471
0
      memcpy(comp_pred, ref, width * sizeof(*comp_pred));
472
0
      comp_pred += width;
473
0
      ref += ref_stride;
474
0
    }
475
0
  } else if (!subpel_y_q3) {
476
0
    const int16_t *const kernel =
477
0
        av1_get_interp_filter_subpel_kernel(filter, subpel_x_q3 << 1);
478
0
    aom_convolve8_horiz_c(ref, ref_stride, comp_pred, width, kernel, 16, NULL,
479
0
                          -1, width, height);
480
0
  } else if (!subpel_x_q3) {
481
0
    const int16_t *const kernel =
482
0
        av1_get_interp_filter_subpel_kernel(filter, subpel_y_q3 << 1);
483
0
    aom_convolve8_vert_c(ref, ref_stride, comp_pred, width, NULL, -1, kernel,
484
0
                         16, width, height);
485
0
  } else {
486
0
    DECLARE_ALIGNED(16, uint8_t,
487
0
                    temp[((MAX_SB_SIZE * 2 + 16) + 16) * MAX_SB_SIZE]);
488
0
    const int16_t *const kernel_x =
489
0
        av1_get_interp_filter_subpel_kernel(filter, subpel_x_q3 << 1);
490
0
    const int16_t *const kernel_y =
491
0
        av1_get_interp_filter_subpel_kernel(filter, subpel_y_q3 << 1);
492
0
    const int intermediate_height =
493
0
        (((height - 1) * 8 + subpel_y_q3) >> 3) + filter->taps;
494
0
    assert(intermediate_height <= (MAX_SB_SIZE * 2 + 16) + 16);
495
0
    aom_convolve8_horiz_c(ref - ref_stride * ((filter->taps >> 1) - 1),
496
0
                          ref_stride, temp, MAX_SB_SIZE, kernel_x, 16, NULL, -1,
497
0
                          width, intermediate_height);
498
0
    aom_convolve8_vert_c(temp + MAX_SB_SIZE * ((filter->taps >> 1) - 1),
499
0
                         MAX_SB_SIZE, comp_pred, width, NULL, -1, kernel_y, 16,
500
0
                         width, height);
501
0
  }
502
0
}
503
504
void aom_comp_avg_upsampled_pred_c(MACROBLOCKD *xd, const AV1_COMMON *const cm,
505
                                   int mi_row, int mi_col, const MV *const mv,
506
                                   uint8_t *comp_pred, const uint8_t *pred,
507
                                   int width, int height, int subpel_x_q3,
508
                                   int subpel_y_q3, const uint8_t *ref,
509
0
                                   int ref_stride, int subpel_search) {
510
0
  int i, j;
511
512
0
  aom_upsampled_pred_c(xd, cm, mi_row, mi_col, mv, comp_pred, width, height,
513
0
                       subpel_x_q3, subpel_y_q3, ref, ref_stride,
514
0
                       subpel_search);
515
0
  for (i = 0; i < height; i++) {
516
0
    for (j = 0; j < width; j++) {
517
0
      comp_pred[j] = ROUND_POWER_OF_TWO(comp_pred[j] + pred[j], 1);
518
0
    }
519
0
    comp_pred += width;
520
0
    pred += width;
521
0
  }
522
0
}
523
524
void aom_comp_mask_upsampled_pred_c(MACROBLOCKD *xd, const AV1_COMMON *const cm,
525
                                    int mi_row, int mi_col, const MV *const mv,
526
                                    uint8_t *comp_pred, const uint8_t *pred,
527
                                    int width, int height, int subpel_x_q3,
528
                                    int subpel_y_q3, const uint8_t *ref,
529
                                    int ref_stride, const uint8_t *mask,
530
                                    int mask_stride, int invert_mask,
531
0
                                    int subpel_search) {
532
0
  if (subpel_x_q3 | subpel_y_q3) {
533
0
    aom_upsampled_pred_c(xd, cm, mi_row, mi_col, mv, comp_pred, width, height,
534
0
                         subpel_x_q3, subpel_y_q3, ref, ref_stride,
535
0
                         subpel_search);
536
0
    ref = comp_pred;
537
0
    ref_stride = width;
538
0
  }
539
0
  aom_comp_mask_pred_c(comp_pred, pred, width, height, ref, ref_stride, mask,
540
0
                       mask_stride, invert_mask);
541
0
}
542
543
void aom_dist_wtd_comp_avg_upsampled_pred_c(
544
    MACROBLOCKD *xd, const AV1_COMMON *const cm, int mi_row, int mi_col,
545
    const MV *const mv, uint8_t *comp_pred, const uint8_t *pred, int width,
546
    int height, int subpel_x_q3, int subpel_y_q3, const uint8_t *ref,
547
0
    int ref_stride, const DIST_WTD_COMP_PARAMS *jcp_param, int subpel_search) {
548
0
  int i, j;
549
0
  const int fwd_offset = jcp_param->fwd_offset;
550
0
  const int bck_offset = jcp_param->bck_offset;
551
552
0
  aom_upsampled_pred_c(xd, cm, mi_row, mi_col, mv, comp_pred, width, height,
553
0
                       subpel_x_q3, subpel_y_q3, ref, ref_stride,
554
0
                       subpel_search);
555
556
0
  for (i = 0; i < height; i++) {
557
0
    for (j = 0; j < width; j++) {
558
0
      int tmp = pred[j] * bck_offset + comp_pred[j] * fwd_offset;
559
0
      tmp = ROUND_POWER_OF_TWO(tmp, DIST_PRECISION_BITS);
560
0
      comp_pred[j] = (uint8_t)tmp;
561
0
    }
562
0
    comp_pred += width;
563
0
    pred += width;
564
0
  }
565
0
}
566
567
#if CONFIG_AV1_HIGHBITDEPTH
568
void aom_highbd_upsampled_pred_c(MACROBLOCKD *xd,
569
                                 const struct AV1Common *const cm, int mi_row,
570
                                 int mi_col, const MV *const mv,
571
                                 uint8_t *comp_pred8, int width, int height,
572
                                 int subpel_x_q3, int subpel_y_q3,
573
                                 const uint8_t *ref8, int ref_stride, int bd,
574
0
                                 int subpel_search) {
575
  // expect xd == NULL only in tests
576
0
  if (xd != NULL) {
577
0
    const MB_MODE_INFO *mi = xd->mi[0];
578
0
    const int ref_num = 0;
579
0
    const int is_intrabc = is_intrabc_block(mi);
580
0
    const struct scale_factors *const sf =
581
0
        is_intrabc ? &cm->sf_identity : xd->block_ref_scale_factors[ref_num];
582
0
    const int is_scaled = av1_is_scaled(sf);
583
584
0
    if (is_scaled) {
585
0
      int plane = 0;
586
0
      const int mi_x = mi_col * MI_SIZE;
587
0
      const int mi_y = mi_row * MI_SIZE;
588
0
      const struct macroblockd_plane *const pd = &xd->plane[plane];
589
0
      const struct buf_2d *const dst_buf = &pd->dst;
590
0
      const struct buf_2d *const pre_buf =
591
0
          is_intrabc ? dst_buf : &pd->pre[ref_num];
592
593
0
      InterPredParams inter_pred_params;
594
0
      inter_pred_params.conv_params = get_conv_params(0, plane, xd->bd);
595
0
      const int_interpfilters filters =
596
0
          av1_broadcast_interp_filter(EIGHTTAP_REGULAR);
597
0
      av1_init_inter_params(
598
0
          &inter_pred_params, width, height, mi_y >> pd->subsampling_y,
599
0
          mi_x >> pd->subsampling_x, pd->subsampling_x, pd->subsampling_y,
600
0
          xd->bd, is_cur_buf_hbd(xd), is_intrabc, sf, pre_buf, filters);
601
0
      av1_enc_build_one_inter_predictor(comp_pred8, width, mv,
602
0
                                        &inter_pred_params);
603
0
      return;
604
0
    }
605
0
  }
606
607
0
  const InterpFilterParams *filter = av1_get_filter(subpel_search);
608
609
0
  if (!subpel_x_q3 && !subpel_y_q3) {
610
0
    const uint16_t *ref = CONVERT_TO_SHORTPTR(ref8);
611
0
    uint16_t *comp_pred = CONVERT_TO_SHORTPTR(comp_pred8);
612
0
    for (int i = 0; i < height; i++) {
613
0
      memcpy(comp_pred, ref, width * sizeof(*comp_pred));
614
0
      comp_pred += width;
615
0
      ref += ref_stride;
616
0
    }
617
0
  } else if (!subpel_y_q3) {
618
0
    const int16_t *const kernel =
619
0
        av1_get_interp_filter_subpel_kernel(filter, subpel_x_q3 << 1);
620
0
    aom_highbd_convolve8_horiz_c(ref8, ref_stride, comp_pred8, width, kernel,
621
0
                                 16, NULL, -1, width, height, bd);
622
0
  } else if (!subpel_x_q3) {
623
0
    const int16_t *const kernel =
624
0
        av1_get_interp_filter_subpel_kernel(filter, subpel_y_q3 << 1);
625
0
    aom_highbd_convolve8_vert_c(ref8, ref_stride, comp_pred8, width, NULL, -1,
626
0
                                kernel, 16, width, height, bd);
627
0
  } else {
628
0
    DECLARE_ALIGNED(16, uint16_t,
629
0
                    temp[((MAX_SB_SIZE + 16) + 16) * MAX_SB_SIZE]);
630
0
    const int16_t *const kernel_x =
631
0
        av1_get_interp_filter_subpel_kernel(filter, subpel_x_q3 << 1);
632
0
    const int16_t *const kernel_y =
633
0
        av1_get_interp_filter_subpel_kernel(filter, subpel_y_q3 << 1);
634
0
    const int intermediate_height =
635
0
        (((height - 1) * 8 + subpel_y_q3) >> 3) + filter->taps;
636
0
    assert(intermediate_height <= (MAX_SB_SIZE * 2 + 16) + 16);
637
0
    aom_highbd_convolve8_horiz_c(ref8 - ref_stride * ((filter->taps >> 1) - 1),
638
0
                                 ref_stride, CONVERT_TO_BYTEPTR(temp),
639
0
                                 MAX_SB_SIZE, kernel_x, 16, NULL, -1, width,
640
0
                                 intermediate_height, bd);
641
0
    aom_highbd_convolve8_vert_c(
642
0
        CONVERT_TO_BYTEPTR(temp + MAX_SB_SIZE * ((filter->taps >> 1) - 1)),
643
0
        MAX_SB_SIZE, comp_pred8, width, NULL, -1, kernel_y, 16, width, height,
644
0
        bd);
645
0
  }
646
0
}
647
648
void aom_highbd_comp_avg_upsampled_pred_c(
649
    MACROBLOCKD *xd, const struct AV1Common *const cm, int mi_row, int mi_col,
650
    const MV *const mv, uint8_t *comp_pred8, const uint8_t *pred8, int width,
651
    int height, int subpel_x_q3, int subpel_y_q3, const uint8_t *ref8,
652
0
    int ref_stride, int bd, int subpel_search) {
653
0
  int i, j;
654
655
0
  const uint16_t *pred = CONVERT_TO_SHORTPTR(pred8);
656
0
  uint16_t *comp_pred = CONVERT_TO_SHORTPTR(comp_pred8);
657
0
  aom_highbd_upsampled_pred(xd, cm, mi_row, mi_col, mv, comp_pred8, width,
658
0
                            height, subpel_x_q3, subpel_y_q3, ref8, ref_stride,
659
0
                            bd, subpel_search);
660
0
  for (i = 0; i < height; ++i) {
661
0
    for (j = 0; j < width; ++j) {
662
0
      comp_pred[j] = ROUND_POWER_OF_TWO(pred[j] + comp_pred[j], 1);
663
0
    }
664
0
    comp_pred += width;
665
0
    pred += width;
666
0
  }
667
0
}
668
669
void aom_highbd_dist_wtd_comp_avg_upsampled_pred_c(
670
    MACROBLOCKD *xd, const struct AV1Common *const cm, int mi_row, int mi_col,
671
    const MV *const mv, uint8_t *comp_pred8, const uint8_t *pred8, int width,
672
    int height, int subpel_x_q3, int subpel_y_q3, const uint8_t *ref8,
673
    int ref_stride, int bd, const DIST_WTD_COMP_PARAMS *jcp_param,
674
0
    int subpel_search) {
675
0
  int i, j;
676
0
  const int fwd_offset = jcp_param->fwd_offset;
677
0
  const int bck_offset = jcp_param->bck_offset;
678
0
  const uint16_t *pred = CONVERT_TO_SHORTPTR(pred8);
679
0
  uint16_t *comp_pred = CONVERT_TO_SHORTPTR(comp_pred8);
680
0
  aom_highbd_upsampled_pred_c(xd, cm, mi_row, mi_col, mv, comp_pred8, width,
681
0
                              height, subpel_x_q3, subpel_y_q3, ref8,
682
0
                              ref_stride, bd, subpel_search);
683
684
0
  for (i = 0; i < height; i++) {
685
0
    for (j = 0; j < width; j++) {
686
0
      int tmp = pred[j] * bck_offset + comp_pred[j] * fwd_offset;
687
0
      tmp = ROUND_POWER_OF_TWO(tmp, DIST_PRECISION_BITS);
688
0
      comp_pred[j] = (uint16_t)tmp;
689
0
    }
690
0
    comp_pred += width;
691
0
    pred += width;
692
0
  }
693
0
}
694
695
void aom_highbd_comp_mask_upsampled_pred(
696
    MACROBLOCKD *xd, const struct AV1Common *const cm, int mi_row, int mi_col,
697
    const MV *const mv, uint8_t *comp_pred8, const uint8_t *pred8, int width,
698
    int height, int subpel_x_q3, int subpel_y_q3, const uint8_t *ref8,
699
    int ref_stride, const uint8_t *mask, int mask_stride, int invert_mask,
700
0
    int bd, int subpel_search) {
701
0
  aom_highbd_upsampled_pred(xd, cm, mi_row, mi_col, mv, comp_pred8, width,
702
0
                            height, subpel_x_q3, subpel_y_q3, ref8, ref_stride,
703
0
                            bd, subpel_search);
704
0
  aom_highbd_comp_mask_pred(comp_pred8, pred8, width, height, comp_pred8, width,
705
0
                            mask, mask_stride, invert_mask);
706
0
}
707
#endif  // CONFIG_AV1_HIGHBITDEPTH