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