tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

reconinter_enc.c (29092B)


      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 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 
     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 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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
    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 
    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 
    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.
    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 
    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 
    518 void aom_comp_mask_upsampled_pred(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(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(comp_pred, pred, width, height, ref, ref_stride, mask,
    534                     mask_stride, invert_mask);
    535 }
    536 
    537 #if CONFIG_AV1_HIGHBITDEPTH
    538 void aom_highbd_upsampled_pred_c(MACROBLOCKD *xd,
    539                                 const struct AV1Common *const cm, int mi_row,
    540                                 int mi_col, const MV *const mv,
    541                                 uint8_t *comp_pred8, int width, int height,
    542                                 int subpel_x_q3, int subpel_y_q3,
    543                                 const uint8_t *ref8, int ref_stride, int bd,
    544                                 int subpel_search) {
    545  // expect xd == NULL only in tests
    546  if (xd != NULL) {
    547    const MB_MODE_INFO *mi = xd->mi[0];
    548    const int ref_num = 0;
    549    const int is_intrabc = is_intrabc_block(mi);
    550    const struct scale_factors *const sf =
    551        is_intrabc ? &cm->sf_identity : xd->block_ref_scale_factors[ref_num];
    552    const int is_scaled = av1_is_scaled(sf);
    553 
    554    if (is_scaled) {
    555      int plane = 0;
    556      const int mi_x = mi_col * MI_SIZE;
    557      const int mi_y = mi_row * MI_SIZE;
    558      const struct macroblockd_plane *const pd = &xd->plane[plane];
    559      const struct buf_2d *const dst_buf = &pd->dst;
    560      const struct buf_2d *const pre_buf =
    561          is_intrabc ? dst_buf : &pd->pre[ref_num];
    562 
    563      InterPredParams inter_pred_params;
    564      inter_pred_params.conv_params = get_conv_params(0, plane, xd->bd);
    565      const int_interpfilters filters =
    566          av1_broadcast_interp_filter(EIGHTTAP_REGULAR);
    567      av1_init_inter_params(
    568          &inter_pred_params, width, height, mi_y >> pd->subsampling_y,
    569          mi_x >> pd->subsampling_x, pd->subsampling_x, pd->subsampling_y,
    570          xd->bd, is_cur_buf_hbd(xd), is_intrabc, sf, pre_buf, filters);
    571      av1_enc_build_one_inter_predictor(comp_pred8, width, mv,
    572                                        &inter_pred_params);
    573      return;
    574    }
    575  }
    576 
    577  const InterpFilterParams *filter = av1_get_filter(subpel_search);
    578 
    579  if (!subpel_x_q3 && !subpel_y_q3) {
    580    const uint16_t *ref = CONVERT_TO_SHORTPTR(ref8);
    581    uint16_t *comp_pred = CONVERT_TO_SHORTPTR(comp_pred8);
    582    for (int i = 0; i < height; i++) {
    583      memcpy(comp_pred, ref, width * sizeof(*comp_pred));
    584      comp_pred += width;
    585      ref += ref_stride;
    586    }
    587  } else if (!subpel_y_q3) {
    588    const int16_t *const kernel =
    589        av1_get_interp_filter_subpel_kernel(filter, subpel_x_q3 << 1);
    590    aom_highbd_convolve8_horiz_c(ref8, ref_stride, comp_pred8, width, kernel,
    591                                 16, NULL, -1, width, height, bd);
    592  } else if (!subpel_x_q3) {
    593    const int16_t *const kernel =
    594        av1_get_interp_filter_subpel_kernel(filter, subpel_y_q3 << 1);
    595    aom_highbd_convolve8_vert_c(ref8, ref_stride, comp_pred8, width, NULL, -1,
    596                                kernel, 16, width, height, bd);
    597  } else {
    598    DECLARE_ALIGNED(16, uint16_t,
    599                    temp[((MAX_SB_SIZE + 16) + 16) * MAX_SB_SIZE]);
    600    const int16_t *const kernel_x =
    601        av1_get_interp_filter_subpel_kernel(filter, subpel_x_q3 << 1);
    602    const int16_t *const kernel_y =
    603        av1_get_interp_filter_subpel_kernel(filter, subpel_y_q3 << 1);
    604    const int intermediate_height =
    605        (((height - 1) * 8 + subpel_y_q3) >> 3) + filter->taps;
    606    assert(intermediate_height <= (MAX_SB_SIZE * 2 + 16) + 16);
    607    aom_highbd_convolve8_horiz_c(ref8 - ref_stride * ((filter->taps >> 1) - 1),
    608                                 ref_stride, CONVERT_TO_BYTEPTR(temp),
    609                                 MAX_SB_SIZE, kernel_x, 16, NULL, -1, width,
    610                                 intermediate_height, bd);
    611    aom_highbd_convolve8_vert_c(
    612        CONVERT_TO_BYTEPTR(temp + MAX_SB_SIZE * ((filter->taps >> 1) - 1)),
    613        MAX_SB_SIZE, comp_pred8, width, NULL, -1, kernel_y, 16, width, height,
    614        bd);
    615  }
    616 }
    617 
    618 void aom_highbd_comp_avg_upsampled_pred_c(
    619    MACROBLOCKD *xd, const struct AV1Common *const cm, int mi_row, int mi_col,
    620    const MV *const mv, uint8_t *comp_pred8, const uint8_t *pred8, int width,
    621    int height, int subpel_x_q3, int subpel_y_q3, const uint8_t *ref8,
    622    int ref_stride, int bd, int subpel_search) {
    623  int i, j;
    624 
    625  const uint16_t *pred = CONVERT_TO_SHORTPTR(pred8);
    626  uint16_t *comp_pred = CONVERT_TO_SHORTPTR(comp_pred8);
    627  aom_highbd_upsampled_pred(xd, cm, mi_row, mi_col, mv, comp_pred8, width,
    628                            height, subpel_x_q3, subpel_y_q3, ref8, ref_stride,
    629                            bd, subpel_search);
    630  for (i = 0; i < height; ++i) {
    631    for (j = 0; j < width; ++j) {
    632      comp_pred[j] = ROUND_POWER_OF_TWO(pred[j] + comp_pred[j], 1);
    633    }
    634    comp_pred += width;
    635    pred += width;
    636  }
    637 }
    638 
    639 void aom_highbd_comp_mask_upsampled_pred(
    640    MACROBLOCKD *xd, const struct AV1Common *const cm, int mi_row, int mi_col,
    641    const MV *const mv, uint8_t *comp_pred8, const uint8_t *pred8, int width,
    642    int height, int subpel_x_q3, int subpel_y_q3, const uint8_t *ref8,
    643    int ref_stride, const uint8_t *mask, int mask_stride, int invert_mask,
    644    int bd, int subpel_search) {
    645  aom_highbd_upsampled_pred(xd, cm, mi_row, mi_col, mv, comp_pred8, width,
    646                            height, subpel_x_q3, subpel_y_q3, ref8, ref_stride,
    647                            bd, subpel_search);
    648  aom_highbd_comp_mask_pred(comp_pred8, pred8, width, height, comp_pred8, width,
    649                            mask, mask_stride, invert_mask);
    650 }
    651 #endif  // CONFIG_AV1_HIGHBITDEPTH