Home | History | Annotate | Download | only in encoder
      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/blockd.h"
     24 #include "av1/common/mvref_common.h"
     25 #include "av1/common/reconinter.h"
     26 #include "av1/common/reconintra.h"
     27 #include "av1/common/onyxc_int.h"
     28 #include "av1/common/obmc.h"
     29 #include "av1/encoder/reconinter_enc.h"
     30 
     31 static INLINE void calc_subpel_params(
     32     MACROBLOCKD *xd, const struct scale_factors *const sf, const MV mv,
     33     int plane, const int pre_x, const int pre_y, int x, int y,
     34     struct buf_2d *const pre_buf, uint8_t **pre, SubpelParams *subpel_params,
     35     int bw, int bh) {
     36   struct macroblockd_plane *const pd = &xd->plane[plane];
     37   const int is_scaled = av1_is_scaled(sf);
     38   if (is_scaled) {
     39     int ssx = pd->subsampling_x;
     40     int ssy = pd->subsampling_y;
     41     int orig_pos_y = (pre_y + y) << SUBPEL_BITS;
     42     orig_pos_y += mv.row * (1 << (1 - ssy));
     43     int orig_pos_x = (pre_x + x) << SUBPEL_BITS;
     44     orig_pos_x += mv.col * (1 << (1 - ssx));
     45     int pos_y = sf->scale_value_y(orig_pos_y, sf);
     46     int pos_x = sf->scale_value_x(orig_pos_x, sf);
     47     pos_x += SCALE_EXTRA_OFF;
     48     pos_y += SCALE_EXTRA_OFF;
     49 
     50     const int top = -AOM_LEFT_TOP_MARGIN_SCALED(ssy);
     51     const int left = -AOM_LEFT_TOP_MARGIN_SCALED(ssx);
     52     const int bottom = (pre_buf->height + AOM_INTERP_EXTEND)
     53                        << SCALE_SUBPEL_BITS;
     54     const int right = (pre_buf->width + AOM_INTERP_EXTEND) << SCALE_SUBPEL_BITS;
     55     pos_y = clamp(pos_y, top, bottom);
     56     pos_x = clamp(pos_x, left, right);
     57 
     58     *pre = pre_buf->buf0 + (pos_y >> SCALE_SUBPEL_BITS) * pre_buf->stride +
     59            (pos_x >> SCALE_SUBPEL_BITS);
     60     subpel_params->subpel_x = pos_x & SCALE_SUBPEL_MASK;
     61     subpel_params->subpel_y = pos_y & SCALE_SUBPEL_MASK;
     62     subpel_params->xs = sf->x_step_q4;
     63     subpel_params->ys = sf->y_step_q4;
     64   } else {
     65     const MV mv_q4 = clamp_mv_to_umv_border_sb(
     66         xd, &mv, bw, bh, pd->subsampling_x, pd->subsampling_y);
     67     subpel_params->xs = subpel_params->ys = SCALE_SUBPEL_SHIFTS;
     68     subpel_params->subpel_x = (mv_q4.col & SUBPEL_MASK) << SCALE_EXTRA_BITS;
     69     subpel_params->subpel_y = (mv_q4.row & SUBPEL_MASK) << SCALE_EXTRA_BITS;
     70     *pre = pre_buf->buf + (y + (mv_q4.row >> SUBPEL_BITS)) * pre_buf->stride +
     71            (x + (mv_q4.col >> SUBPEL_BITS));
     72   }
     73 }
     74 
     75 static INLINE void build_inter_predictors(const AV1_COMMON *cm, MACROBLOCKD *xd,
     76                                           int plane, const MB_MODE_INFO *mi,
     77                                           int build_for_obmc, int bw, int bh,
     78                                           int mi_x, int mi_y) {
     79   struct macroblockd_plane *const pd = &xd->plane[plane];
     80   int is_compound = has_second_ref(mi);
     81   int ref;
     82   const int is_intrabc = is_intrabc_block(mi);
     83   assert(IMPLIES(is_intrabc, !is_compound));
     84   int is_global[2] = { 0, 0 };
     85   for (ref = 0; ref < 1 + is_compound; ++ref) {
     86     const WarpedMotionParams *const wm = &xd->global_motion[mi->ref_frame[ref]];
     87     is_global[ref] = is_global_mv_block(mi, wm->wmtype);
     88   }
     89 
     90   const BLOCK_SIZE bsize = mi->sb_type;
     91   const int ss_x = pd->subsampling_x;
     92   const int ss_y = pd->subsampling_y;
     93   int sub8x8_inter = (block_size_wide[bsize] < 8 && ss_x) ||
     94                      (block_size_high[bsize] < 8 && ss_y);
     95 
     96   if (is_intrabc) sub8x8_inter = 0;
     97 
     98   // For sub8x8 chroma blocks, we may be covering more than one luma block's
     99   // worth of pixels. Thus (mi_x, mi_y) may not be the correct coordinates for
    100   // the top-left corner of the prediction source - the correct top-left corner
    101   // is at (pre_x, pre_y).
    102   const int row_start =
    103       (block_size_high[bsize] == 4) && ss_y && !build_for_obmc ? -1 : 0;
    104   const int col_start =
    105       (block_size_wide[bsize] == 4) && ss_x && !build_for_obmc ? -1 : 0;
    106   const int pre_x = (mi_x + MI_SIZE * col_start) >> ss_x;
    107   const int pre_y = (mi_y + MI_SIZE * row_start) >> ss_y;
    108 
    109   sub8x8_inter = sub8x8_inter && !build_for_obmc;
    110   if (sub8x8_inter) {
    111     for (int row = row_start; row <= 0 && sub8x8_inter; ++row) {
    112       for (int col = col_start; col <= 0; ++col) {
    113         const MB_MODE_INFO *this_mbmi = xd->mi[row * xd->mi_stride + col];
    114         if (!is_inter_block(this_mbmi)) sub8x8_inter = 0;
    115         if (is_intrabc_block(this_mbmi)) sub8x8_inter = 0;
    116       }
    117     }
    118   }
    119 
    120   if (sub8x8_inter) {
    121     // block size
    122     const int b4_w = block_size_wide[bsize] >> ss_x;
    123     const int b4_h = block_size_high[bsize] >> ss_y;
    124     const BLOCK_SIZE plane_bsize = scale_chroma_bsize(bsize, ss_x, ss_y);
    125     const int b8_w = block_size_wide[plane_bsize] >> ss_x;
    126     const int b8_h = block_size_high[plane_bsize] >> ss_y;
    127     assert(!is_compound);
    128 
    129     const struct buf_2d orig_pred_buf[2] = { pd->pre[0], pd->pre[1] };
    130 
    131     int row = row_start;
    132     for (int y = 0; y < b8_h; y += b4_h) {
    133       int col = col_start;
    134       for (int x = 0; x < b8_w; x += b4_w) {
    135         MB_MODE_INFO *this_mbmi = xd->mi[row * xd->mi_stride + col];
    136         is_compound = has_second_ref(this_mbmi);
    137         int tmp_dst_stride = 8;
    138         assert(bw < 8 || bh < 8);
    139         ConvolveParams conv_params = get_conv_params_no_round(
    140             0, plane, xd->tmp_conv_dst, tmp_dst_stride, is_compound, xd->bd);
    141         conv_params.use_dist_wtd_comp_avg = 0;
    142         struct buf_2d *const dst_buf = &pd->dst;
    143         uint8_t *dst = dst_buf->buf + dst_buf->stride * y + x;
    144 
    145         ref = 0;
    146         const RefCntBuffer *ref_buf =
    147             get_ref_frame_buf(cm, this_mbmi->ref_frame[ref]);
    148         const struct scale_factors *ref_scale_factors =
    149             get_ref_scale_factors_const(cm, this_mbmi->ref_frame[ref]);
    150 
    151         pd->pre[ref].buf0 =
    152             (plane == 1) ? ref_buf->buf.u_buffer : ref_buf->buf.v_buffer;
    153         pd->pre[ref].buf =
    154             pd->pre[ref].buf0 + scaled_buffer_offset(pre_x, pre_y,
    155                                                      ref_buf->buf.uv_stride,
    156                                                      ref_scale_factors);
    157         pd->pre[ref].width = ref_buf->buf.uv_crop_width;
    158         pd->pre[ref].height = ref_buf->buf.uv_crop_height;
    159         pd->pre[ref].stride = ref_buf->buf.uv_stride;
    160 
    161         const struct scale_factors *const sf =
    162             is_intrabc ? &cm->sf_identity : ref_scale_factors;
    163         struct buf_2d *const pre_buf = is_intrabc ? dst_buf : &pd->pre[ref];
    164 
    165         const MV mv = this_mbmi->mv[ref].as_mv;
    166 
    167         uint8_t *pre;
    168         SubpelParams subpel_params;
    169         WarpTypesAllowed warp_types;
    170         warp_types.global_warp_allowed = is_global[ref];
    171         warp_types.local_warp_allowed = this_mbmi->motion_mode == WARPED_CAUSAL;
    172 
    173         calc_subpel_params(xd, sf, mv, plane, pre_x, pre_y, x, y, pre_buf, &pre,
    174                            &subpel_params, bw, bh);
    175         conv_params.do_average = ref;
    176         if (is_masked_compound_type(mi->interinter_comp.type)) {
    177           // masked compound type has its own average mechanism
    178           conv_params.do_average = 0;
    179         }
    180 
    181         av1_make_inter_predictor(
    182             pre, pre_buf->stride, dst, dst_buf->stride, &subpel_params, sf,
    183             b4_w, b4_h, &conv_params, this_mbmi->interp_filters, &warp_types,
    184             (mi_x >> pd->subsampling_x) + x, (mi_y >> pd->subsampling_y) + y,
    185             plane, ref, mi, build_for_obmc, xd, cm->allow_warped_motion);
    186 
    187         ++col;
    188       }
    189       ++row;
    190     }
    191 
    192     for (ref = 0; ref < 2; ++ref) pd->pre[ref] = orig_pred_buf[ref];
    193     return;
    194   }
    195 
    196   {
    197     ConvolveParams conv_params = get_conv_params_no_round(
    198         0, plane, xd->tmp_conv_dst, MAX_SB_SIZE, is_compound, xd->bd);
    199     av1_dist_wtd_comp_weight_assign(
    200         cm, mi, 0, &conv_params.fwd_offset, &conv_params.bck_offset,
    201         &conv_params.use_dist_wtd_comp_avg, is_compound);
    202 
    203     struct buf_2d *const dst_buf = &pd->dst;
    204     uint8_t *const dst = dst_buf->buf;
    205     for (ref = 0; ref < 1 + is_compound; ++ref) {
    206       const struct scale_factors *const sf =
    207           is_intrabc ? &cm->sf_identity : xd->block_ref_scale_factors[ref];
    208       struct buf_2d *const pre_buf = is_intrabc ? dst_buf : &pd->pre[ref];
    209       const MV mv = mi->mv[ref].as_mv;
    210 
    211       uint8_t *pre;
    212       SubpelParams subpel_params;
    213       calc_subpel_params(xd, sf, mv, plane, pre_x, pre_y, 0, 0, pre_buf, &pre,
    214                          &subpel_params, bw, bh);
    215 
    216       WarpTypesAllowed warp_types;
    217       warp_types.global_warp_allowed = is_global[ref];
    218       warp_types.local_warp_allowed = mi->motion_mode == WARPED_CAUSAL;
    219 
    220       if (ref && is_masked_compound_type(mi->interinter_comp.type)) {
    221         // masked compound type has its own average mechanism
    222         conv_params.do_average = 0;
    223         av1_make_masked_inter_predictor(
    224             pre, pre_buf->stride, dst, dst_buf->stride, &subpel_params, sf, bw,
    225             bh, &conv_params, mi->interp_filters, plane, &warp_types,
    226             mi_x >> pd->subsampling_x, mi_y >> pd->subsampling_y, ref, xd,
    227             cm->allow_warped_motion);
    228       } else {
    229         conv_params.do_average = ref;
    230         av1_make_inter_predictor(
    231             pre, pre_buf->stride, dst, dst_buf->stride, &subpel_params, sf, bw,
    232             bh, &conv_params, mi->interp_filters, &warp_types,
    233             mi_x >> pd->subsampling_x, mi_y >> pd->subsampling_y, plane, ref,
    234             mi, build_for_obmc, xd, cm->allow_warped_motion);
    235       }
    236     }
    237   }
    238 }
    239 
    240 static void build_inter_predictors_for_plane(const AV1_COMMON *cm,
    241                                              MACROBLOCKD *xd, int mi_row,
    242                                              int mi_col, const BUFFER_SET *ctx,
    243                                              BLOCK_SIZE bsize, int plane_idx) {
    244   const struct macroblockd_plane *pd = &xd->plane[plane_idx];
    245   if (!is_chroma_reference(mi_row, mi_col, bsize, pd->subsampling_x,
    246                            pd->subsampling_y))
    247     return;
    248 
    249   const int mi_x = mi_col * MI_SIZE;
    250   const int mi_y = mi_row * MI_SIZE;
    251   build_inter_predictors(cm, xd, plane_idx, xd->mi[0], 0, pd->width, pd->height,
    252                          mi_x, mi_y);
    253 
    254   if (is_interintra_pred(xd->mi[0])) {
    255     BUFFER_SET default_ctx = { { NULL, NULL, NULL }, { 0, 0, 0 } };
    256     if (!ctx) {
    257       default_ctx.plane[plane_idx] = xd->plane[plane_idx].dst.buf;
    258       default_ctx.stride[plane_idx] = xd->plane[plane_idx].dst.stride;
    259       ctx = &default_ctx;
    260     }
    261     av1_build_interintra_predictors_sbp(cm, xd, xd->plane[plane_idx].dst.buf,
    262                                         xd->plane[plane_idx].dst.stride, ctx,
    263                                         plane_idx, bsize);
    264   }
    265 }
    266 
    267 void av1_enc_build_inter_predictor(const AV1_COMMON *cm, MACROBLOCKD *xd,
    268                                    int mi_row, int mi_col,
    269                                    const BUFFER_SET *ctx, BLOCK_SIZE bsize,
    270                                    int plane_from, int plane_to) {
    271   for (int plane_idx = plane_from; plane_idx <= plane_to; ++plane_idx) {
    272     build_inter_predictors_for_plane(cm, xd, mi_row, mi_col, ctx, bsize,
    273                                      plane_idx);
    274   }
    275 }
    276 
    277 // TODO(sarahparker):
    278 // av1_build_inter_predictor should be combined with
    279 // av1_make_inter_predictor
    280 void av1_build_inter_predictor(const uint8_t *src, int src_stride, uint8_t *dst,
    281                                int dst_stride, const MV *src_mv,
    282                                const struct scale_factors *sf, int w, int h,
    283                                ConvolveParams *conv_params,
    284                                InterpFilters interp_filters,
    285                                const WarpTypesAllowed *warp_types, int p_col,
    286                                int p_row, int plane, int ref,
    287                                mv_precision precision, int x, int y,
    288                                const MACROBLOCKD *xd, int can_use_previous) {
    289   const int is_q4 = precision == MV_PRECISION_Q4;
    290   const MV mv_q4 = { is_q4 ? src_mv->row : src_mv->row * 2,
    291                      is_q4 ? src_mv->col : src_mv->col * 2 };
    292   MV32 mv = av1_scale_mv(&mv_q4, x, y, sf);
    293   mv.col += SCALE_EXTRA_OFF;
    294   mv.row += SCALE_EXTRA_OFF;
    295 
    296   const SubpelParams subpel_params = { sf->x_step_q4, sf->y_step_q4,
    297                                        mv.col & SCALE_SUBPEL_MASK,
    298                                        mv.row & SCALE_SUBPEL_MASK };
    299   src += (mv.row >> SCALE_SUBPEL_BITS) * src_stride +
    300          (mv.col >> SCALE_SUBPEL_BITS);
    301 
    302   av1_make_inter_predictor(src, src_stride, dst, dst_stride, &subpel_params, sf,
    303                            w, h, conv_params, interp_filters, warp_types, p_col,
    304                            p_row, plane, ref, xd->mi[0], 0, xd,
    305                            can_use_previous);
    306 }
    307 
    308 static INLINE void build_prediction_by_above_pred(
    309     MACROBLOCKD *xd, int rel_mi_col, uint8_t above_mi_width,
    310     MB_MODE_INFO *above_mbmi, void *fun_ctxt, const int num_planes) {
    311   struct build_prediction_ctxt *ctxt = (struct build_prediction_ctxt *)fun_ctxt;
    312   const int above_mi_col = ctxt->mi_col + rel_mi_col;
    313   int mi_x, mi_y;
    314   MB_MODE_INFO backup_mbmi = *above_mbmi;
    315 
    316   av1_setup_build_prediction_by_above_pred(xd, rel_mi_col, above_mi_width,
    317                                            &backup_mbmi, ctxt, num_planes);
    318   mi_x = above_mi_col << MI_SIZE_LOG2;
    319   mi_y = ctxt->mi_row << MI_SIZE_LOG2;
    320 
    321   const BLOCK_SIZE bsize = xd->mi[0]->sb_type;
    322 
    323   for (int j = 0; j < num_planes; ++j) {
    324     const struct macroblockd_plane *pd = &xd->plane[j];
    325     int bw = (above_mi_width * MI_SIZE) >> pd->subsampling_x;
    326     int bh = clamp(block_size_high[bsize] >> (pd->subsampling_y + 1), 4,
    327                    block_size_high[BLOCK_64X64] >> (pd->subsampling_y + 1));
    328 
    329     if (av1_skip_u4x4_pred_in_obmc(bsize, pd, 0)) continue;
    330     build_inter_predictors(ctxt->cm, xd, j, &backup_mbmi, 1, bw, bh, mi_x,
    331                            mi_y);
    332   }
    333 }
    334 
    335 void av1_build_prediction_by_above_preds(const AV1_COMMON *cm, MACROBLOCKD *xd,
    336                                          int mi_row, int mi_col,
    337                                          uint8_t *tmp_buf[MAX_MB_PLANE],
    338                                          int tmp_width[MAX_MB_PLANE],
    339                                          int tmp_height[MAX_MB_PLANE],
    340                                          int tmp_stride[MAX_MB_PLANE]) {
    341   if (!xd->up_available) return;
    342 
    343   // Adjust mb_to_bottom_edge to have the correct value for the OBMC
    344   // prediction block. This is half the height of the original block,
    345   // except for 128-wide blocks, where we only use a height of 32.
    346   int this_height = xd->n4_h * MI_SIZE;
    347   int pred_height = AOMMIN(this_height / 2, 32);
    348   xd->mb_to_bottom_edge += (this_height - pred_height) * 8;
    349 
    350   struct build_prediction_ctxt ctxt = { cm,         mi_row,
    351                                         mi_col,     tmp_buf,
    352                                         tmp_width,  tmp_height,
    353                                         tmp_stride, xd->mb_to_right_edge };
    354   BLOCK_SIZE bsize = xd->mi[0]->sb_type;
    355   foreach_overlappable_nb_above(cm, xd, mi_col,
    356                                 max_neighbor_obmc[mi_size_wide_log2[bsize]],
    357                                 build_prediction_by_above_pred, &ctxt);
    358 
    359   xd->mb_to_left_edge = -((mi_col * MI_SIZE) * 8);
    360   xd->mb_to_right_edge = ctxt.mb_to_far_edge;
    361   xd->mb_to_bottom_edge -= (this_height - pred_height) * 8;
    362 }
    363 
    364 static INLINE void build_prediction_by_left_pred(
    365     MACROBLOCKD *xd, int rel_mi_row, uint8_t left_mi_height,
    366     MB_MODE_INFO *left_mbmi, void *fun_ctxt, const int num_planes) {
    367   struct build_prediction_ctxt *ctxt = (struct build_prediction_ctxt *)fun_ctxt;
    368   const int left_mi_row = ctxt->mi_row + rel_mi_row;
    369   int mi_x, mi_y;
    370   MB_MODE_INFO backup_mbmi = *left_mbmi;
    371 
    372   av1_setup_build_prediction_by_left_pred(xd, rel_mi_row, left_mi_height,
    373                                           &backup_mbmi, ctxt, num_planes);
    374   mi_x = ctxt->mi_col << MI_SIZE_LOG2;
    375   mi_y = left_mi_row << MI_SIZE_LOG2;
    376   const BLOCK_SIZE bsize = xd->mi[0]->sb_type;
    377 
    378   for (int j = 0; j < num_planes; ++j) {
    379     const struct macroblockd_plane *pd = &xd->plane[j];
    380     int bw = clamp(block_size_wide[bsize] >> (pd->subsampling_x + 1), 4,
    381                    block_size_wide[BLOCK_64X64] >> (pd->subsampling_x + 1));
    382     int bh = (left_mi_height << MI_SIZE_LOG2) >> pd->subsampling_y;
    383 
    384     if (av1_skip_u4x4_pred_in_obmc(bsize, pd, 1)) continue;
    385     build_inter_predictors(ctxt->cm, xd, j, &backup_mbmi, 1, bw, bh, mi_x,
    386                            mi_y);
    387   }
    388 }
    389 
    390 void av1_build_prediction_by_left_preds(const AV1_COMMON *cm, MACROBLOCKD *xd,
    391                                         int mi_row, int mi_col,
    392                                         uint8_t *tmp_buf[MAX_MB_PLANE],
    393                                         int tmp_width[MAX_MB_PLANE],
    394                                         int tmp_height[MAX_MB_PLANE],
    395                                         int tmp_stride[MAX_MB_PLANE]) {
    396   if (!xd->left_available) return;
    397 
    398   // Adjust mb_to_right_edge to have the correct value for the OBMC
    399   // prediction block. This is half the width of the original block,
    400   // except for 128-wide blocks, where we only use a width of 32.
    401   int this_width = xd->n4_w * MI_SIZE;
    402   int pred_width = AOMMIN(this_width / 2, 32);
    403   xd->mb_to_right_edge += (this_width - pred_width) * 8;
    404 
    405   struct build_prediction_ctxt ctxt = { cm,         mi_row,
    406                                         mi_col,     tmp_buf,
    407                                         tmp_width,  tmp_height,
    408                                         tmp_stride, xd->mb_to_bottom_edge };
    409   BLOCK_SIZE bsize = xd->mi[0]->sb_type;
    410   foreach_overlappable_nb_left(cm, xd, mi_row,
    411                                max_neighbor_obmc[mi_size_high_log2[bsize]],
    412                                build_prediction_by_left_pred, &ctxt);
    413 
    414   xd->mb_to_top_edge = -((mi_row * MI_SIZE) * 8);
    415   xd->mb_to_right_edge -= (this_width - pred_width) * 8;
    416   xd->mb_to_bottom_edge = ctxt.mb_to_far_edge;
    417 }
    418 
    419 void av1_build_obmc_inter_predictors_sb(const AV1_COMMON *cm, MACROBLOCKD *xd,
    420                                         int mi_row, int mi_col) {
    421   const int num_planes = av1_num_planes(cm);
    422   uint8_t *dst_buf1[MAX_MB_PLANE], *dst_buf2[MAX_MB_PLANE];
    423   int dst_stride1[MAX_MB_PLANE] = { MAX_SB_SIZE, MAX_SB_SIZE, MAX_SB_SIZE };
    424   int dst_stride2[MAX_MB_PLANE] = { MAX_SB_SIZE, MAX_SB_SIZE, MAX_SB_SIZE };
    425   int dst_width1[MAX_MB_PLANE] = { MAX_SB_SIZE, MAX_SB_SIZE, MAX_SB_SIZE };
    426   int dst_width2[MAX_MB_PLANE] = { MAX_SB_SIZE, MAX_SB_SIZE, MAX_SB_SIZE };
    427   int dst_height1[MAX_MB_PLANE] = { MAX_SB_SIZE, MAX_SB_SIZE, MAX_SB_SIZE };
    428   int dst_height2[MAX_MB_PLANE] = { MAX_SB_SIZE, MAX_SB_SIZE, MAX_SB_SIZE };
    429 
    430   if (is_cur_buf_hbd(xd)) {
    431     int len = sizeof(uint16_t);
    432     dst_buf1[0] = CONVERT_TO_BYTEPTR(xd->tmp_obmc_bufs[0]);
    433     dst_buf1[1] =
    434         CONVERT_TO_BYTEPTR(xd->tmp_obmc_bufs[0] + MAX_SB_SQUARE * len);
    435     dst_buf1[2] =
    436         CONVERT_TO_BYTEPTR(xd->tmp_obmc_bufs[0] + MAX_SB_SQUARE * 2 * len);
    437     dst_buf2[0] = CONVERT_TO_BYTEPTR(xd->tmp_obmc_bufs[1]);
    438     dst_buf2[1] =
    439         CONVERT_TO_BYTEPTR(xd->tmp_obmc_bufs[1] + MAX_SB_SQUARE * len);
    440     dst_buf2[2] =
    441         CONVERT_TO_BYTEPTR(xd->tmp_obmc_bufs[1] + MAX_SB_SQUARE * 2 * len);
    442   } else {
    443     dst_buf1[0] = xd->tmp_obmc_bufs[0];
    444     dst_buf1[1] = xd->tmp_obmc_bufs[0] + MAX_SB_SQUARE;
    445     dst_buf1[2] = xd->tmp_obmc_bufs[0] + MAX_SB_SQUARE * 2;
    446     dst_buf2[0] = xd->tmp_obmc_bufs[1];
    447     dst_buf2[1] = xd->tmp_obmc_bufs[1] + MAX_SB_SQUARE;
    448     dst_buf2[2] = xd->tmp_obmc_bufs[1] + MAX_SB_SQUARE * 2;
    449   }
    450   av1_build_prediction_by_above_preds(cm, xd, mi_row, mi_col, dst_buf1,
    451                                       dst_width1, dst_height1, dst_stride1);
    452   av1_build_prediction_by_left_preds(cm, xd, mi_row, mi_col, dst_buf2,
    453                                      dst_width2, dst_height2, dst_stride2);
    454   av1_setup_dst_planes(xd->plane, xd->mi[0]->sb_type, &cm->cur_frame->buf,
    455                        mi_row, mi_col, 0, num_planes);
    456   av1_build_obmc_inter_prediction(cm, xd, mi_row, mi_col, dst_buf1, dst_stride1,
    457                                   dst_buf2, dst_stride2);
    458 }
    459 
    460 // Builds the inter-predictor for the single ref case
    461 // for use in the encoder to search the wedges efficiently.
    462 static void build_inter_predictors_single_buf(MACROBLOCKD *xd, int plane,
    463                                               int bw, int bh, int x, int y,
    464                                               int w, int h, int mi_x, int mi_y,
    465                                               int ref, uint8_t *const ext_dst,
    466                                               int ext_dst_stride,
    467                                               int can_use_previous) {
    468   struct macroblockd_plane *const pd = &xd->plane[plane];
    469   const MB_MODE_INFO *mi = xd->mi[0];
    470 
    471   const struct scale_factors *const sf = xd->block_ref_scale_factors[ref];
    472   struct buf_2d *const pre_buf = &pd->pre[ref];
    473   uint8_t *const dst = get_buf_by_bd(xd, ext_dst) + ext_dst_stride * y + x;
    474   const MV mv = mi->mv[ref].as_mv;
    475 
    476   ConvolveParams conv_params = get_conv_params(0, plane, xd->bd);
    477   WarpTypesAllowed warp_types;
    478   const WarpedMotionParams *const wm = &xd->global_motion[mi->ref_frame[ref]];
    479   warp_types.global_warp_allowed = is_global_mv_block(mi, wm->wmtype);
    480   warp_types.local_warp_allowed = mi->motion_mode == WARPED_CAUSAL;
    481   const int pre_x = (mi_x) >> pd->subsampling_x;
    482   const int pre_y = (mi_y) >> pd->subsampling_y;
    483   uint8_t *pre;
    484   SubpelParams subpel_params;
    485   calc_subpel_params(xd, sf, mv, plane, pre_x, pre_y, x, y, pre_buf, &pre,
    486                      &subpel_params, bw, bh);
    487 
    488   av1_make_inter_predictor(pre, pre_buf->stride, dst, ext_dst_stride,
    489                            &subpel_params, sf, w, h, &conv_params,
    490                            mi->interp_filters, &warp_types, pre_x + x,
    491                            pre_y + y, plane, ref, mi, 0, xd, can_use_previous);
    492 }
    493 
    494 void av1_build_inter_predictors_for_planes_single_buf(
    495     MACROBLOCKD *xd, BLOCK_SIZE bsize, int plane_from, int plane_to, int mi_row,
    496     int mi_col, int ref, uint8_t *ext_dst[3], int ext_dst_stride[3],
    497     int can_use_previous) {
    498   int plane;
    499   const int mi_x = mi_col * MI_SIZE;
    500   const int mi_y = mi_row * MI_SIZE;
    501   for (plane = plane_from; plane <= plane_to; ++plane) {
    502     const BLOCK_SIZE plane_bsize = get_plane_block_size(
    503         bsize, xd->plane[plane].subsampling_x, xd->plane[plane].subsampling_y);
    504     const int bw = block_size_wide[plane_bsize];
    505     const int bh = block_size_high[plane_bsize];
    506     build_inter_predictors_single_buf(xd, plane, bw, bh, 0, 0, bw, bh, mi_x,
    507                                       mi_y, ref, ext_dst[plane],
    508                                       ext_dst_stride[plane], can_use_previous);
    509   }
    510 }
    511 
    512 static void build_masked_compound(
    513     uint8_t *dst, int dst_stride, const uint8_t *src0, int src0_stride,
    514     const uint8_t *src1, int src1_stride,
    515     const INTERINTER_COMPOUND_DATA *const comp_data, BLOCK_SIZE sb_type, int h,
    516     int w) {
    517   // Derive subsampling from h and w passed in. May be refactored to
    518   // pass in subsampling factors directly.
    519   const int subh = (2 << mi_size_high_log2[sb_type]) == h;
    520   const int subw = (2 << mi_size_wide_log2[sb_type]) == w;
    521   const uint8_t *mask = av1_get_compound_type_mask(comp_data, sb_type);
    522   aom_blend_a64_mask(dst, dst_stride, src0, src0_stride, src1, src1_stride,
    523                      mask, block_size_wide[sb_type], w, h, subw, subh);
    524 }
    525 
    526 static void build_masked_compound_highbd(
    527     uint8_t *dst_8, int dst_stride, const uint8_t *src0_8, int src0_stride,
    528     const uint8_t *src1_8, int src1_stride,
    529     const INTERINTER_COMPOUND_DATA *const comp_data, BLOCK_SIZE sb_type, int h,
    530     int w, int bd) {
    531   // Derive subsampling from h and w passed in. May be refactored to
    532   // pass in subsampling factors directly.
    533   const int subh = (2 << mi_size_high_log2[sb_type]) == h;
    534   const int subw = (2 << mi_size_wide_log2[sb_type]) == w;
    535   const uint8_t *mask = av1_get_compound_type_mask(comp_data, sb_type);
    536   // const uint8_t *mask =
    537   //     av1_get_contiguous_soft_mask(wedge_index, wedge_sign, sb_type);
    538   aom_highbd_blend_a64_mask(dst_8, dst_stride, src0_8, src0_stride, src1_8,
    539                             src1_stride, mask, block_size_wide[sb_type], w, h,
    540                             subw, subh, bd);
    541 }
    542 
    543 static void build_wedge_inter_predictor_from_buf(
    544     MACROBLOCKD *xd, int plane, int x, int y, int w, int h, uint8_t *ext_dst0,
    545     int ext_dst_stride0, uint8_t *ext_dst1, int ext_dst_stride1) {
    546   MB_MODE_INFO *const mbmi = xd->mi[0];
    547   const int is_compound = has_second_ref(mbmi);
    548   MACROBLOCKD_PLANE *const pd = &xd->plane[plane];
    549   struct buf_2d *const dst_buf = &pd->dst;
    550   uint8_t *const dst = dst_buf->buf + dst_buf->stride * y + x;
    551   mbmi->interinter_comp.seg_mask = xd->seg_mask;
    552   const INTERINTER_COMPOUND_DATA *comp_data = &mbmi->interinter_comp;
    553   const int is_hbd = is_cur_buf_hbd(xd);
    554 
    555   if (is_compound && is_masked_compound_type(comp_data->type)) {
    556     if (!plane && comp_data->type == COMPOUND_DIFFWTD) {
    557       if (is_hbd) {
    558         av1_build_compound_diffwtd_mask_highbd(
    559             comp_data->seg_mask, comp_data->mask_type,
    560             CONVERT_TO_BYTEPTR(ext_dst0), ext_dst_stride0,
    561             CONVERT_TO_BYTEPTR(ext_dst1), ext_dst_stride1, h, w, xd->bd);
    562       } else {
    563         av1_build_compound_diffwtd_mask(
    564             comp_data->seg_mask, comp_data->mask_type, ext_dst0,
    565             ext_dst_stride0, ext_dst1, ext_dst_stride1, h, w);
    566       }
    567     }
    568 
    569     if (is_hbd) {
    570       build_masked_compound_highbd(
    571           dst, dst_buf->stride, CONVERT_TO_BYTEPTR(ext_dst0), ext_dst_stride0,
    572           CONVERT_TO_BYTEPTR(ext_dst1), ext_dst_stride1, comp_data,
    573           mbmi->sb_type, h, w, xd->bd);
    574     } else {
    575       build_masked_compound(dst, dst_buf->stride, ext_dst0, ext_dst_stride0,
    576                             ext_dst1, ext_dst_stride1, comp_data, mbmi->sb_type,
    577                             h, w);
    578     }
    579   } else {
    580     if (is_hbd) {
    581       aom_highbd_convolve_copy(CONVERT_TO_BYTEPTR(ext_dst0), ext_dst_stride0,
    582                                dst, dst_buf->stride, NULL, 0, NULL, 0, w, h,
    583                                xd->bd);
    584     } else {
    585       aom_convolve_copy(ext_dst0, ext_dst_stride0, dst, dst_buf->stride, NULL,
    586                         0, NULL, 0, w, h);
    587     }
    588   }
    589 }
    590 
    591 void av1_build_wedge_inter_predictor_from_buf(MACROBLOCKD *xd, BLOCK_SIZE bsize,
    592                                               int plane_from, int plane_to,
    593                                               uint8_t *ext_dst0[3],
    594                                               int ext_dst_stride0[3],
    595                                               uint8_t *ext_dst1[3],
    596                                               int ext_dst_stride1[3]) {
    597   int plane;
    598   for (plane = plane_from; plane <= plane_to; ++plane) {
    599     const BLOCK_SIZE plane_bsize = get_plane_block_size(
    600         bsize, xd->plane[plane].subsampling_x, xd->plane[plane].subsampling_y);
    601     const int bw = block_size_wide[plane_bsize];
    602     const int bh = block_size_high[plane_bsize];
    603     build_wedge_inter_predictor_from_buf(
    604         xd, plane, 0, 0, bw, bh, ext_dst0[plane], ext_dst_stride0[plane],
    605         ext_dst1[plane], ext_dst_stride1[plane]);
    606   }
    607 }
    608