• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2022, 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#ifndef IS_DEC
13#error "IS_DEC must be defined for reconinter_template.inc."
14#endif
15
16#if IS_DEC
17static AOM_INLINE void build_one_inter_predictor(
18    uint8_t *dst, int dst_stride, const MV *src_mv,
19    InterPredParams *inter_pred_params, MACROBLOCKD *xd, int mi_x, int mi_y,
20    int ref, uint8_t **mc_buf) {
21#else
22static AOM_INLINE void build_one_inter_predictor(
23    uint8_t *dst, int dst_stride, const MV *src_mv,
24    InterPredParams *inter_pred_params) {
25#endif  // IS_DEC
26  SubpelParams subpel_params;
27  uint8_t *src;
28  int src_stride;
29#if IS_DEC
30  dec_calc_subpel_params_and_extend(src_mv, inter_pred_params, xd, mi_x, mi_y,
31                                    ref, mc_buf, &src, &subpel_params,
32                                    &src_stride);
33#else
34  enc_calc_subpel_params(src_mv, inter_pred_params, &src, &subpel_params,
35                         &src_stride);
36#endif  // IS_DEC
37  if (inter_pred_params->comp_mode == UNIFORM_SINGLE ||
38      inter_pred_params->comp_mode == UNIFORM_COMP) {
39    av1_make_inter_predictor(src, src_stride, dst, dst_stride,
40                             inter_pred_params, &subpel_params);
41  } else {
42    av1_make_masked_inter_predictor(src, src_stride, dst, dst_stride,
43                                    inter_pred_params, &subpel_params);
44  }
45}
46
47// True if the following hold:
48//  1. Not intrabc and not build_for_obmc
49//  2. At least one dimension is size 4 with subsampling
50//  3. If sub-sampled, none of the previous blocks around the sub-sample
51//     are intrabc or inter-blocks
52static bool is_sub8x8_inter(const MACROBLOCKD *xd, int plane, BLOCK_SIZE bsize,
53                            int is_intrabc, int build_for_obmc) {
54  if (is_intrabc || build_for_obmc) {
55    return false;
56  }
57
58  const struct macroblockd_plane *const pd = &xd->plane[plane];
59  const int ss_x = pd->subsampling_x;
60  const int ss_y = pd->subsampling_y;
61  const int is_sub4_x = (block_size_wide[bsize] == 4) && ss_x;
62  const int is_sub4_y = (block_size_high[bsize] == 4) && ss_y;
63  if (!is_sub4_x && !is_sub4_y) {
64    return false;
65  }
66
67  // For sub8x8 chroma blocks, we may be covering more than one luma block's
68  // worth of pixels. Thus (mi_x, mi_y) may not be the correct coordinates for
69  // the top-left corner of the prediction source - the correct top-left corner
70  // is at (pre_x, pre_y).
71  const int row_start = is_sub4_y ? -1 : 0;
72  const int col_start = is_sub4_x ? -1 : 0;
73
74  for (int row = row_start; row <= 0; ++row) {
75    for (int col = col_start; col <= 0; ++col) {
76      const MB_MODE_INFO *this_mbmi = xd->mi[row * xd->mi_stride + col];
77      if (!is_inter_block(this_mbmi)) return false;
78      if (is_intrabc_block(this_mbmi)) return false;
79    }
80  }
81  return true;
82}
83
84#if IS_DEC
85static AOM_INLINE void build_inter_predictors_sub8x8(const AV1_COMMON *cm,
86                                                     MACROBLOCKD *xd, int plane,
87                                                     const MB_MODE_INFO *mi,
88                                                     int mi_x, int mi_y,
89                                                     uint8_t **mc_buf) {
90#else
91static AOM_INLINE void build_inter_predictors_sub8x8(const AV1_COMMON *cm,
92                                                     MACROBLOCKD *xd, int plane,
93                                                     const MB_MODE_INFO *mi,
94                                                     int mi_x, int mi_y) {
95#endif  // IS_DEC
96  const BLOCK_SIZE bsize = mi->bsize;
97  struct macroblockd_plane *const pd = &xd->plane[plane];
98  const bool ss_x = pd->subsampling_x;
99  const bool ss_y = pd->subsampling_y;
100  const int b4_w = block_size_wide[bsize] >> ss_x;
101  const int b4_h = block_size_high[bsize] >> ss_y;
102  const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize, ss_x, ss_y);
103  const int b8_w = block_size_wide[plane_bsize];
104  const int b8_h = block_size_high[plane_bsize];
105  const int is_compound = has_second_ref(mi);
106  assert(!is_compound);
107  assert(!is_intrabc_block(mi));
108
109  // For sub8x8 chroma blocks, we may be covering more than one luma block's
110  // worth of pixels. Thus (mi_x, mi_y) may not be the correct coordinates for
111  // the top-left corner of the prediction source - the correct top-left corner
112  // is at (pre_x, pre_y).
113  const int row_start = (block_size_high[bsize] == 4) && ss_y ? -1 : 0;
114  const int col_start = (block_size_wide[bsize] == 4) && ss_x ? -1 : 0;
115  const int pre_x = (mi_x + MI_SIZE * col_start) >> ss_x;
116  const int pre_y = (mi_y + MI_SIZE * row_start) >> ss_y;
117
118  int row = row_start;
119  for (int y = 0; y < b8_h; y += b4_h) {
120    int col = col_start;
121    for (int x = 0; x < b8_w; x += b4_w) {
122      MB_MODE_INFO *this_mbmi = xd->mi[row * xd->mi_stride + col];
123      struct buf_2d *const dst_buf = &pd->dst;
124      uint8_t *dst = dst_buf->buf + dst_buf->stride * y + x;
125      int ref = 0;
126      const RefCntBuffer *ref_buf =
127          get_ref_frame_buf(cm, this_mbmi->ref_frame[ref]);
128      const struct scale_factors *ref_scale_factors =
129          get_ref_scale_factors_const(cm, this_mbmi->ref_frame[ref]);
130      const struct scale_factors *const sf = ref_scale_factors;
131      const struct buf_2d pre_buf = {
132        NULL,
133        (plane == 1) ? ref_buf->buf.u_buffer : ref_buf->buf.v_buffer,
134        ref_buf->buf.uv_crop_width,
135        ref_buf->buf.uv_crop_height,
136        ref_buf->buf.uv_stride,
137      };
138
139      const MV mv = this_mbmi->mv[ref].as_mv;
140
141      InterPredParams inter_pred_params;
142      av1_init_inter_params(&inter_pred_params, b4_w, b4_h, pre_y + y,
143                            pre_x + x, pd->subsampling_x, pd->subsampling_y,
144                            xd->bd, is_cur_buf_hbd(xd), mi->use_intrabc, sf,
145                            &pre_buf, this_mbmi->interp_filters);
146      inter_pred_params.conv_params =
147          get_conv_params_no_round(ref, plane, NULL, 0, is_compound, xd->bd);
148
149#if IS_DEC
150      build_one_inter_predictor(dst, dst_buf->stride, &mv, &inter_pred_params,
151                                xd, mi_x + x, mi_y + y, ref, mc_buf);
152#else
153      build_one_inter_predictor(dst, dst_buf->stride, &mv, &inter_pred_params);
154#endif  // IS_DEC
155
156      ++col;
157    }
158    ++row;
159  }
160}
161
162#if IS_DEC
163static AOM_INLINE void build_inter_predictors_8x8_and_bigger(
164    const AV1_COMMON *cm, MACROBLOCKD *xd, int plane, const MB_MODE_INFO *mi,
165    int build_for_obmc, int bw, int bh, int mi_x, int mi_y, uint8_t **mc_buf) {
166#else
167static AOM_INLINE void build_inter_predictors_8x8_and_bigger(
168    const AV1_COMMON *cm, MACROBLOCKD *xd, int plane, const MB_MODE_INFO *mi,
169    int build_for_obmc, int bw, int bh, int mi_x, int mi_y) {
170#endif  // IS_DEC
171  const int is_compound = has_second_ref(mi);
172  const int is_intrabc = is_intrabc_block(mi);
173  assert(IMPLIES(is_intrabc, !is_compound));
174  struct macroblockd_plane *const pd = &xd->plane[plane];
175  struct buf_2d *const dst_buf = &pd->dst;
176  uint8_t *const dst = dst_buf->buf;
177
178  int is_global[2] = { 0, 0 };
179  for (int ref = 0; ref < 1 + is_compound; ++ref) {
180    const WarpedMotionParams *const wm = &xd->global_motion[mi->ref_frame[ref]];
181    is_global[ref] = is_global_mv_block(mi, wm->wmtype);
182  }
183
184  const BLOCK_SIZE bsize = mi->bsize;
185  const int ss_x = pd->subsampling_x;
186  const int ss_y = pd->subsampling_y;
187  const int row_start =
188      (block_size_high[bsize] == 4) && ss_y && !build_for_obmc ? -1 : 0;
189  const int col_start =
190      (block_size_wide[bsize] == 4) && ss_x && !build_for_obmc ? -1 : 0;
191  const int pre_x = (mi_x + MI_SIZE * col_start) >> ss_x;
192  const int pre_y = (mi_y + MI_SIZE * row_start) >> ss_y;
193
194  for (int ref = 0; ref < 1 + is_compound; ++ref) {
195    const struct scale_factors *const sf =
196        is_intrabc ? &cm->sf_identity : xd->block_ref_scale_factors[ref];
197    struct buf_2d *const pre_buf = is_intrabc ? dst_buf : &pd->pre[ref];
198    const MV mv = mi->mv[ref].as_mv;
199    const WarpTypesAllowed warp_types = { is_global[ref],
200                                          mi->motion_mode == WARPED_CAUSAL };
201
202    InterPredParams inter_pred_params;
203    av1_init_inter_params(&inter_pred_params, bw, bh, pre_y, pre_x,
204                          pd->subsampling_x, pd->subsampling_y, xd->bd,
205                          is_cur_buf_hbd(xd), mi->use_intrabc, sf, pre_buf,
206                          mi->interp_filters);
207    if (is_compound) av1_init_comp_mode(&inter_pred_params);
208    inter_pred_params.conv_params = get_conv_params_no_round(
209        ref, plane, xd->tmp_conv_dst, MAX_SB_SIZE, is_compound, xd->bd);
210
211    av1_dist_wtd_comp_weight_assign(
212        cm, mi, &inter_pred_params.conv_params.fwd_offset,
213        &inter_pred_params.conv_params.bck_offset,
214        &inter_pred_params.conv_params.use_dist_wtd_comp_avg, is_compound);
215
216    if (!build_for_obmc)
217      av1_init_warp_params(&inter_pred_params, &warp_types, ref, xd, mi);
218
219    if (is_masked_compound_type(mi->interinter_comp.type)) {
220      inter_pred_params.sb_type = mi->bsize;
221      inter_pred_params.mask_comp = mi->interinter_comp;
222      if (ref == 1) {
223        inter_pred_params.conv_params.do_average = 0;
224        inter_pred_params.comp_mode = MASK_COMP;
225      }
226      // Assign physical buffer.
227      inter_pred_params.mask_comp.seg_mask = xd->seg_mask;
228    }
229
230#if IS_DEC
231    build_one_inter_predictor(dst, dst_buf->stride, &mv, &inter_pred_params, xd,
232                              mi_x, mi_y, ref, mc_buf);
233#else
234    build_one_inter_predictor(dst, dst_buf->stride, &mv, &inter_pred_params);
235#endif  // IS_DEC
236  }
237}
238
239#if IS_DEC
240static AOM_INLINE void build_inter_predictors(
241    const AV1_COMMON *cm, MACROBLOCKD *xd, int plane, const MB_MODE_INFO *mi,
242    int build_for_obmc, int bw, int bh, int mi_x, int mi_y, uint8_t **mc_buf) {
243  if (is_sub8x8_inter(xd, plane, mi->bsize, is_intrabc_block(mi),
244                      build_for_obmc)) {
245    assert(bw < 8 || bh < 8);
246    build_inter_predictors_sub8x8(cm, xd, plane, mi, mi_x, mi_y, mc_buf);
247  } else {
248    build_inter_predictors_8x8_and_bigger(cm, xd, plane, mi, build_for_obmc, bw,
249                                          bh, mi_x, mi_y, mc_buf);
250  }
251}
252#else
253static AOM_INLINE void build_inter_predictors(const AV1_COMMON *cm,
254                                              MACROBLOCKD *xd, int plane,
255                                              const MB_MODE_INFO *mi,
256                                              int build_for_obmc, int bw,
257                                              int bh, int mi_x, int mi_y) {
258  if (is_sub8x8_inter(xd, plane, mi->bsize, is_intrabc_block(mi),
259                      build_for_obmc)) {
260    assert(bw < 8 || bh < 8);
261    build_inter_predictors_sub8x8(cm, xd, plane, mi, mi_x, mi_y);
262  } else {
263    build_inter_predictors_8x8_and_bigger(cm, xd, plane, mi, build_for_obmc, bw,
264                                          bh, mi_x, mi_y);
265  }
266}
267#endif  // IS_DEC
268