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