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