ncobmc-adapt-weight: add recon functions Change-Id: Iebc527697548355ea2e92e2fbc2faa46f16ef0db
diff --git a/av1/common/reconinter.c b/av1/common/reconinter.c index 5eae3be..3cfa5d2 100644 --- a/av1/common/reconinter.c +++ b/av1/common/reconinter.c
@@ -10,6 +10,7 @@ */ #include <assert.h> +#include <stdio.h> #include "./aom_scale_rtcd.h" #include "./aom_dsp_rtcd.h" @@ -2442,7 +2443,9 @@ int tmp_height[MAX_MB_PLANE], int tmp_stride[MAX_MB_PLANE]) { const TileInfo *const tile = &xd->tile; +#if CONFIG_DEBUG BLOCK_SIZE bsize = xd->mi[0]->mbmi.sb_type; +#endif int i, j, mi_step, ref; const int ilimit = AOMMIN(xd->n8_w, cm->mi_cols - mi_col); int mb_to_right_edge_base = xd->mb_to_right_edge; @@ -2495,12 +2498,12 @@ xd->mb_to_right_edge = mb_to_right_edge_base + (xd->n8_w - i - mi_step) * 64; mi_x = (mi_col + i) << MI_SIZE_LOG2; - mi_y = (mi_row << MI_SIZE_LOG2) + xd->n8_h * 4; + mi_y = (mi_row << MI_SIZE_LOG2) + xd->n8_h * (MI_SIZE >> 1); for (j = 0; j < MAX_MB_PLANE; ++j) { const struct macroblockd_plane *pd = &xd->plane[j]; bw = (mi_step << MI_SIZE_LOG2) >> pd->subsampling_x; - bh = (num_4x4_blocks_high_lookup[bsize] << 1) >> pd->subsampling_y; + bh = (xd->n8_h << (MI_SIZE_LOG2 - 1)) >> pd->subsampling_y; if (mbmi->sb_type < BLOCK_8X8 && !CONFIG_CB4X4) { const PARTITION_TYPE bp = BLOCK_8X8 - mbmi->sb_type; @@ -2551,7 +2554,9 @@ int tmp_height[MAX_MB_PLANE], const int tmp_stride[MAX_MB_PLANE]) { const TileInfo *const tile = &xd->tile; +#if CONFIG_DEBUG BLOCK_SIZE bsize = xd->mi[0]->mbmi.sb_type; +#endif int i, j, mi_step, ref; const int ilimit = AOMMIN(xd->n8_h, cm->mi_rows - mi_row); int mb_to_bottom_edge_base = xd->mb_to_bottom_edge; @@ -2560,6 +2565,8 @@ (mi_col + xd->n8_w) % MI_SIZE == 0 || (mi_col + xd->n8_w) >= cm->mi_cols) return; + assert(bsize >= BLOCK_8X8); + xd->mb_to_left_edge -= xd->n8_w * 32; for (i = 0; i < ilimit; i += mi_step) { int mi_row_offset = i; @@ -2602,12 +2609,12 @@ xd->mb_to_top_edge = -(((mi_row + i) * MI_SIZE) * 8); xd->mb_to_bottom_edge = mb_to_bottom_edge_base + (xd->n8_h - i - mi_step) * 64; - mi_x = (mi_col << MI_SIZE_LOG2) + xd->n8_w * 4; + mi_x = (mi_col << MI_SIZE_LOG2) + xd->n8_w * (MI_SIZE >> 1); mi_y = (mi_row + i) << MI_SIZE_LOG2; for (j = 0; j < MAX_MB_PLANE; ++j) { const struct macroblockd_plane *pd = &xd->plane[j]; - bw = (num_4x4_blocks_wide_lookup[bsize] << 1) >> pd->subsampling_x; + bw = (xd->n8_w << (MI_SIZE_LOG2 - 1)) >> pd->subsampling_x; bh = (mi_step << MI_SIZE_LOG2) >> pd->subsampling_y; if (mbmi->sb_type < BLOCK_8X8 && !CONFIG_CB4X4) { @@ -2818,6 +2825,31 @@ mi_col); } #endif // CONFIG_NCOBMC + +#if CONFIG_NCOBMC_ADAPT_WEIGHT +void reset_xd_boundary(MACROBLOCKD *xd, int mi_row, int bh, int mi_col, int bw, + int mi_rows, int mi_cols) { + xd->mb_to_top_edge = -((mi_row * MI_SIZE) * 8); + xd->mb_to_bottom_edge = ((mi_rows - bh - mi_row) * MI_SIZE) * 8; + xd->mb_to_left_edge = -((mi_col * MI_SIZE) * 8); + xd->mb_to_right_edge = ((mi_cols - bw - mi_col) * MI_SIZE) * 8; +} +void set_sb_mi_boundaries(const AV1_COMMON *const cm, MACROBLOCKD *const xd, + const int mi_row, const int mi_col) { + const BLOCK_SIZE sb = cm->sb_size; + const int num_mi_w = mi_size_wide[sb]; + const int num_mi_h = mi_size_high[sb]; + + xd->sb_mi_bd.mi_col_begin = mi_col; + xd->sb_mi_bd.mi_row_begin = mi_row; + // points to the last mi + xd->sb_mi_bd.mi_col_end = + mi_col + num_mi_w > cm->mi_cols ? cm->mi_cols - 1 : mi_col + num_mi_w - 1; + xd->sb_mi_bd.mi_row_end = + mi_row + num_mi_h > cm->mi_rows ? cm->mi_rows - 1 : mi_row + num_mi_h - 1; +} +#endif + #endif // CONFIG_MOTION_VAR #if CONFIG_EXT_INTER @@ -3370,3 +3402,715 @@ } } #endif // CONFIG_EXT_INTER +#if CONFIG_NCOBMC_ADAPT_WEIGHT + +void alloc_ncobmc_pred_buffer(MACROBLOCKD *const xd) { + int i; + // allocate interpolated prediction buffer + for (i = 0; i < MAX_MB_PLANE; ++i) { + xd->ncobmc_pred_buf[i] = (uint8_t *)malloc(sizeof(uint8_t) * MAX_SB_SQUARE); + av1_zero_array(xd->ncobmc_pred_buf[i], MAX_SB_SQUARE); + xd->ncobmc_pred_buf_stride[i] = MAX_SB_SIZE; + } +} + +void free_ncobmc_pred_buffer(MACROBLOCKD *const xd) { + for (int i = 0; i < MAX_MB_PLANE; ++i) free(xd->ncobmc_pred_buf[i]); +} + +void get_pred_from_intrpl_buf(MACROBLOCKD *xd, int mi_row, int mi_col, + BLOCK_SIZE bsize, int plane) { + uint8_t *dst = xd->plane[plane].dst.buf; + int ds = xd->plane[plane].dst.stride; + int ss_x = xd->plane[plane].subsampling_x; + int ss_y = xd->plane[plane].subsampling_y; + + const int ip_wide = mi_size_wide[bsize] * MI_SIZE >> ss_x; + const int ip_high = mi_size_high[bsize] * MI_SIZE >> ss_y; + // relative coordinates of this MI in the superblock + int row_rlt = (mi_row - xd->sb_mi_bd.mi_row_begin) * MI_SIZE >> ss_y; + int col_rlt = (mi_col - xd->sb_mi_bd.mi_col_begin) * MI_SIZE >> ss_x; + int s = xd->ncobmc_pred_buf_stride[plane]; + int r, c; + + for (r = 0; r < ip_high; ++r) { + for (c = 0; c < ip_wide; ++c) { + dst[r * ds + c] = + xd->ncobmc_pred_buf[plane][(r + row_rlt) * s + c + col_rlt]; + } + } +} +// scaling factors for ncobmc kernels +#define KERNEL_SCALE_LOG 14 + +void build_ncobmc_intrpl_pred(const AV1_COMMON *const cm, MACROBLOCKD *xd, + int plane, int pxl_row, int pxl_col, + BLOCK_SIZE bsize, uint8_t *preds[][MAX_MB_PLANE], + int stride[MAX_MB_PLANE], // pred buffer strides + int mode) { + const ADAPT_OVERLAP_BLOCK ao_block = adapt_overlap_block_lookup[bsize]; + const NCOBMC_KERNELS *const knls = &cm->ncobmc_kernels[ao_block][mode]; + const int wide = mi_size_wide[bsize] * MI_SIZE; + const int high = mi_size_high[bsize] * MI_SIZE; + const int s = stride[plane]; + const int ss_x = xd->plane[plane].subsampling_x; + const int ss_y = xd->plane[plane].subsampling_y; + int row_offset = (pxl_row - xd->sb_mi_bd.mi_row_begin * MI_SIZE) >> ss_y; + int col_offset = (pxl_col - xd->sb_mi_bd.mi_col_begin * MI_SIZE) >> ss_x; + int dst_stride = xd->ncobmc_pred_buf_stride[plane]; + int dst_offset = row_offset * dst_stride + col_offset; + +#if CONFIG_HIGHBITDEPTH + const int is_hbd = (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) ? 1 : 0; +#else + const int is_hbd = 0; +#endif // CONFIG_HIGHBITDEPTH + + int r, c, k_r, k_c; + int64_t tmp; + + for (r = 0; r < (high >> ss_x); ++r) { + for (c = 0; c < (wide >> ss_y); ++c) { + int pos = r * s + c; + int q_tmp; + uint8_t val; + + // TODO(weitinglin): find out the optimal sub-sampling patterns for + // chroma + k_r = (r << ss_y) + ss_y; + k_c = (c << ss_x) + ss_x; + if (ss_y && k_r >= high) k_r -= 1; + if (ss_x && k_c >= wide) k_c -= 1; + + if (!is_hbd) { + uint8_t *tmp_p[4]; + int i; + for (i = 0; i < 4; ++i) tmp_p[i] = preds[i][plane]; + + tmp = (int64_t)knls->KERNEL_TL[k_r][k_c] * tmp_p[0][pos] + + (int64_t)knls->KERNEL_TR[k_r][k_c] * tmp_p[1][pos] + + (int64_t)knls->KERNEL_BL[k_r][k_c] * tmp_p[2][pos] + + (int64_t)knls->KERNEL_BR[k_r][k_c] * tmp_p[3][pos]; + } else { + uint16_t *tmp_p[4]; + int i; + for (i = 0; i < 4; ++i) tmp_p[i] = CONVERT_TO_SHORTPTR(preds[i][plane]); + + tmp = (int64_t)knls->KERNEL_TL[k_r][k_c] * tmp_p[0][pos] + + (int64_t)knls->KERNEL_TR[k_r][k_c] * tmp_p[1][pos] + + (int64_t)knls->KERNEL_BL[k_r][k_c] * tmp_p[2][pos] + + (int64_t)knls->KERNEL_BR[k_r][k_c] * tmp_p[3][pos]; + } + + q_tmp = (tmp <= 0) ? 0 : ROUND_POWER_OF_TWO(tmp, KERNEL_SCALE_LOG); + val = clip_pixel(q_tmp); + + xd->ncobmc_pred_buf[plane][r * dst_stride + c + dst_offset] = val; + + assert(r * dst_stride + c + dst_offset < MAX_SB_SQUARE); + } + } +} + +void get_pred_by_horz_neighbor(const AV1_COMMON *cm, MACROBLOCKD *xd, int bsize, + int mi_row, int mi_col, + uint8_t *dst_buf[MAX_MB_PLANE], + int dst_stride[MAX_MB_PLANE]) { + const TileInfo *const tile = &xd->tile; + const int mb_to_bottom_edge_base = xd->mb_to_bottom_edge; + const int mb_to_top_edge_base = xd->mb_to_top_edge; + const int mb_to_left_edge_base = xd->mb_to_left_edge; + const int mb_to_right_edge_base = xd->mb_to_right_edge; + int overlappable_offset = -1; + const int mi_nums = AOMMIN(mi_size_high[bsize], cm->mi_rows - mi_row); + + int i, j, mi_step, ref; + + xd->mb_to_right_edge += mi_size_wide[bsize] * MI_SIZE * 4; + + // build from left neighbors + for (i = 0; i < mi_nums; i += mi_step) { + int mi_row_offset = i; + int mi_col_offset = -1; + int mi_x, mi_y, bw, bh; + MODE_INFO *left_mi; + MB_MODE_INFO *left_mbmi, backup_mbmi; + BLOCK_SIZE l_bsize; + + // create the original prediction if offset exceeds the boundary + if (mi_col == 0 || (mi_col - 1 < tile->mi_col_start)) mi_col_offset = 0; + + left_mi = xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride]; + left_mbmi = &left_mi->mbmi; + l_bsize = AOMMAX(left_mbmi->sb_type, BLOCK_8X8); + + mi_step = AOMMIN(xd->n8_h, mi_size_high[l_bsize]); + + // reset the mi if it is not overlappble + if (!is_neighbor_overlappable(left_mbmi)) { + // use left_mbmi->sb_type instead of l_bsize to handle + // sub8x8 cases + int search_mi_step = mi_size_high[left_mbmi->sb_type]; + while (!is_neighbor_overlappable(left_mbmi)) { + mi_row_offset += search_mi_step; + if (mi_row_offset < mi_nums) { + left_mi = xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride]; + left_mbmi = &left_mi->mbmi; + search_mi_step = mi_size_high[left_mbmi->sb_type]; + } else { + if (overlappable_offset >= 0) { + mi_row_offset = overlappable_offset; + } else { + mi_row_offset = 0; + mi_col_offset = 0; + } + left_mi = xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride]; + left_mbmi = &left_mi->mbmi; + break; + } + } + } else { + // update the available overlappable mi + overlappable_offset = mi_row_offset; + } + + backup_mbmi = *left_mbmi; + modify_neighbor_predictor_for_obmc(left_mbmi); + + for (j = 0; j < MAX_MB_PLANE; ++j) { + struct macroblockd_plane *const pd = &xd->plane[j]; + setup_pred_plane(&pd->dst, l_bsize, dst_buf[j], MAX_SB_SIZE, MAX_SB_SIZE, + dst_stride[j], i, 0, NULL, pd->subsampling_x, + pd->subsampling_y); + } +#if CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF + for (ref = 0; ref < 1 + (is_inter_anyref_comp_mode(left_mbmi->mode)); + ++ref) { + const MV_REFERENCE_FRAME frame = has_second_ref(left_mbmi) + ? left_mbmi->ref_frame[ref] + : left_mbmi->ref_frame[0]; +#else // !(CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF) + for (ref = 0; ref < 1 + has_second_ref(left_mbmi); ++ref) { + const MV_REFERENCE_FRAME frame = left_mbmi->ref_frame[ref]; +#endif // CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF + const RefBuffer *const ref_buf = &cm->frame_refs[frame - LAST_FRAME]; + + xd->block_refs[ref] = ref_buf; + if ((!av1_is_valid_scale(&ref_buf->sf))) + aom_internal_error(xd->error_info, AOM_CODEC_UNSUP_BITSTREAM, + "Reference frame has invalid dimensions"); + av1_setup_pre_planes(xd, ref, ref_buf->buf, mi_row + i, mi_col, + &ref_buf->sf); + } + xd->mb_to_top_edge = -((mi_row + i) * MI_SIZE * 8); + xd->mb_to_bottom_edge = + mb_to_bottom_edge_base + (mi_nums - i - mi_step) * MI_SIZE * 8; + mi_x = mi_col << MI_SIZE_LOG2; + mi_y = (mi_row + i) << MI_SIZE_LOG2; + + for (j = 0; j < MAX_MB_PLANE; ++j) { + const struct macroblockd_plane *pd = &xd->plane[j]; + bw = mi_size_wide[bsize] << (MI_SIZE_LOG2 - 1) >> pd->subsampling_x; + bh = (mi_step << MI_SIZE_LOG2) >> pd->subsampling_y; + + build_inter_predictors(cm, xd, j, mi_col_offset, mi_row_offset, 0, bw, bh, + 0, 0, bw, bh, +#if CONFIG_SUPERTX && CONFIG_EXT_INTER + 0, 0, +#endif // CONFIG_SUPERTX && CONFIG_EXT_INTER + mi_x, mi_y); + } + *left_mbmi = backup_mbmi; + } + + // build from right neighbors + xd->mb_to_right_edge = mb_to_right_edge_base; + xd->mb_to_left_edge -= mi_size_wide[bsize] * MI_SIZE * 4; + + overlappable_offset = -1; + + for (i = 0; i < mi_nums; i += mi_step) { + int mi_row_offset = i; + int mi_col_offset = mi_size_wide[bsize]; + int mi_x, mi_y, bw, bh; + int mi_col_shift = mi_size_wide[bsize] >> 1; + MODE_INFO *right_mi; + MB_MODE_INFO *right_mbmi, backup_mbmi; + BLOCK_SIZE r_bsize; + + // create the original prediction if offset exceeds the boundary + if (mi_col + mi_col_offset > xd->sb_mi_bd.mi_col_end) mi_col_offset = 0; + + right_mi = xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride]; + right_mbmi = &right_mi->mbmi; + r_bsize = AOMMAX(right_mbmi->sb_type, BLOCK_8X8); + + mi_step = AOMMIN(mi_nums, mi_size_high[r_bsize]); + + if (!is_neighbor_overlappable(right_mbmi)) { + int search_mi_step = mi_size_high[right_mbmi->sb_type]; + while (!is_neighbor_overlappable(right_mbmi)) { + mi_row_offset += search_mi_step; + if (mi_row_offset < mi_nums) { + right_mi = xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride]; + right_mbmi = &right_mi->mbmi; + search_mi_step = mi_size_high[right_mbmi->sb_type]; + } else { + if (overlappable_offset >= 0) { + mi_row_offset = overlappable_offset; + } else { + mi_row_offset = 0; + mi_col_offset = 0; + } + right_mi = xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride]; + right_mbmi = &right_mi->mbmi; + break; + } + } + } else { + overlappable_offset = mi_row_offset; + } + + backup_mbmi = *right_mbmi; + modify_neighbor_predictor_for_obmc(right_mbmi); + + for (j = 0; j < MAX_MB_PLANE; ++j) { + struct macroblockd_plane *const pd = &xd->plane[j]; + setup_pred_plane(&pd->dst, r_bsize, dst_buf[j], MAX_SB_SIZE, MAX_SB_SIZE, + dst_stride[j], i, mi_col_shift, NULL, pd->subsampling_x, + pd->subsampling_y); + } +#if CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF + for (ref = 0; ref < 1 + (is_inter_anyref_comp_mode(right_mbmi->mode)); + ++ref) { + const MV_REFERENCE_FRAME frame = has_second_ref(right_mbmi) + ? right_mbmi->ref_frame[ref] + : right_mbmi->ref_frame[0]; +#else // !(CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF) + for (ref = 0; ref < 1 + has_second_ref(right_mbmi); ++ref) { + const MV_REFERENCE_FRAME frame = right_mbmi->ref_frame[ref]; +#endif // CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF + const RefBuffer *const ref_buf = &cm->frame_refs[frame - LAST_FRAME]; + xd->block_refs[ref] = ref_buf; + if ((!av1_is_valid_scale(&ref_buf->sf))) + aom_internal_error(xd->error_info, AOM_CODEC_UNSUP_BITSTREAM, + "Reference frame has invalid dimensions"); + av1_setup_pre_planes(xd, ref, ref_buf->buf, mi_row + i, + mi_col + mi_col_shift, &ref_buf->sf); + } + xd->mb_to_top_edge = -((mi_row + i) * MI_SIZE * 8); + xd->mb_to_bottom_edge = + mb_to_bottom_edge_base + (mi_nums - i - mi_step) * MI_SIZE * 8; + mi_x = (mi_col + mi_col_shift) << MI_SIZE_LOG2; + mi_y = (mi_row + i) << MI_SIZE_LOG2; + + for (j = 0; j < MAX_MB_PLANE; ++j) { + const struct macroblockd_plane *pd = &xd->plane[j]; + bw = mi_size_wide[bsize] << (MI_SIZE_LOG2 - 1) >> pd->subsampling_x; + bh = (mi_step << MI_SIZE_LOG2) >> pd->subsampling_y; + + build_inter_predictors(cm, xd, j, mi_col_offset, mi_row_offset, 0, bw, bh, + 0, 0, bw, bh, +#if CONFIG_SUPERTX && CONFIG_EXT_INTER + 0, 0, +#endif // CONFIG_SUPERTX && CONFIG_EXT_INTER + mi_x, mi_y); + } + + *right_mbmi = backup_mbmi; + } + + // restore the boundaries + xd->mb_to_top_edge = mb_to_top_edge_base; + xd->mb_to_bottom_edge = mb_to_bottom_edge_base; + xd->mb_to_left_edge = mb_to_left_edge_base; + xd->mb_to_right_edge = mb_to_right_edge_base; +} + +void get_pred_by_vert_neighbor(const AV1_COMMON *cm, MACROBLOCKD *xd, int bsize, + int mi_row, int mi_col, + uint8_t *dst_buf[MAX_MB_PLANE], + int dst_stride[MAX_MB_PLANE]) { + const TileInfo *const tile = &xd->tile; + const int mb_to_bottom_edge_base = xd->mb_to_bottom_edge; + const int mb_to_top_edge_base = xd->mb_to_top_edge; + const int mb_to_left_edge_base = xd->mb_to_left_edge; + const int mb_to_right_edge_base = xd->mb_to_right_edge; + int overlappable_offset = -1; + const int mi_nums = AOMMIN(mi_size_wide[bsize], cm->mi_cols - mi_col); + + int i, j, mi_step, ref; + + xd->mb_to_bottom_edge += mi_nums * MI_SIZE * 4; + + // build from above neighbors + for (i = 0; i < mi_nums; i += mi_step) { + int mi_row_offset = -1; + int mi_col_offset = i; + int mi_x, mi_y, bw, bh; + MODE_INFO *above_mi; + MB_MODE_INFO *above_mbmi, backup_mbmi; + BLOCK_SIZE a_bsize; + + // create the original prediction if offset exceeds the boundary + if (mi_row <= tile->mi_row_start) mi_row_offset = 0; + + above_mi = xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride]; + above_mbmi = &above_mi->mbmi; + a_bsize = AOMMAX(above_mbmi->sb_type, BLOCK_8X8); + + mi_step = AOMMIN(mi_nums, mi_size_high[a_bsize]); + + // reset the mi if it is not overlappble + if (!is_neighbor_overlappable(above_mbmi)) { + int search_mi_step = mi_size_high[above_mbmi->sb_type]; + // backward search + while (!is_neighbor_overlappable(above_mbmi)) { + mi_col_offset += search_mi_step; + if (mi_col_offset < mi_nums) { + above_mi = xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride]; + above_mbmi = &above_mi->mbmi; + search_mi_step = mi_size_high[above_mbmi->sb_type]; + } else { + if (overlappable_offset >= 0) { + mi_col_offset = overlappable_offset; + } else { + mi_row_offset = 0; + mi_col_offset = 0; + } + above_mi = xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride]; + above_mbmi = &above_mi->mbmi; + break; + } + } + } else { + // update the available overlappable mi + overlappable_offset = mi_col_offset; + } + + backup_mbmi = *above_mbmi; + modify_neighbor_predictor_for_obmc(above_mbmi); + + for (j = 0; j < MAX_MB_PLANE; ++j) { + struct macroblockd_plane *const pd = &xd->plane[j]; + setup_pred_plane(&pd->dst, a_bsize, dst_buf[j], MAX_SB_SIZE, MAX_SB_SIZE, + dst_stride[j], 0, i, NULL, pd->subsampling_x, + pd->subsampling_y); + } +#if CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF + for (ref = 0; ref < 1 + (is_inter_anyref_comp_mode(above_mbmi->mode)); + ++ref) { + const MV_REFERENCE_FRAME frame = has_second_ref(above_mbmi) + ? above_mbmi->ref_frame[ref] + : above_mbmi->ref_frame[0]; +#else // !(CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF) + for (ref = 0; ref < 1 + has_second_ref(above_mbmi); ++ref) { + const MV_REFERENCE_FRAME frame = above_mbmi->ref_frame[ref]; +#endif // CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF + const RefBuffer *const ref_buf = &cm->frame_refs[frame - LAST_FRAME]; + + xd->block_refs[ref] = ref_buf; + if ((!av1_is_valid_scale(&ref_buf->sf))) + aom_internal_error(xd->error_info, AOM_CODEC_UNSUP_BITSTREAM, + "Reference frame has invalid dimensions"); + av1_setup_pre_planes(xd, ref, ref_buf->buf, mi_row, mi_col + i, + &ref_buf->sf); + } + + xd->mb_to_left_edge = -(((mi_col + i) * MI_SIZE) * 8); + xd->mb_to_right_edge = + mb_to_right_edge_base + (mi_nums - i - mi_step) * MI_SIZE * 8; + mi_x = (mi_col + i) << MI_SIZE_LOG2; + mi_y = mi_row << MI_SIZE_LOG2; + + for (j = 0; j < MAX_MB_PLANE; ++j) { + const struct macroblockd_plane *pd = &xd->plane[j]; + + bh = mi_size_high[bsize] << (MI_SIZE_LOG2 - 1) >> pd->subsampling_x; + bw = (mi_step << MI_SIZE_LOG2) >> pd->subsampling_y; + + build_inter_predictors(cm, xd, j, mi_col_offset, mi_row_offset, 0, bw, bh, + 0, 0, bw, bh, +#if CONFIG_SUPERTX && CONFIG_EXT_INTER + 0, 0, +#endif // CONFIG_SUPERTX && CONFIG_EXT_INTER + mi_x, mi_y); + } + + *above_mbmi = backup_mbmi; + } + + // build from bottom neighbors + xd->mb_to_bottom_edge = mb_to_bottom_edge_base; + xd->mb_to_top_edge -= mi_size_high[bsize] * MI_SIZE * 4; + + overlappable_offset = -1; + + for (i = 0; i < mi_nums; i += mi_step) { + int mi_row_offset = mi_size_high[bsize]; + int mi_col_offset = i; + int mi_x, mi_y, bw, bh; + int mi_row_shift = mi_size_high[bsize] >> 1; + MODE_INFO *bottom_mi; + MB_MODE_INFO *bottom_mbmi, backup_mbmi; + BLOCK_SIZE b_bsize; + + // create the original prediction if offset exceeds the boundary + if (mi_row + mi_row_offset > xd->sb_mi_bd.mi_row_end) mi_row_offset = 0; + + bottom_mi = xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride]; + bottom_mbmi = &bottom_mi->mbmi; + b_bsize = AOMMAX(bottom_mbmi->sb_type, BLOCK_8X8); + + mi_step = AOMMIN(mi_nums, mi_size_high[b_bsize]); + + // reset the mi if it is not overlappble + if (!is_neighbor_overlappable(bottom_mbmi)) { + int search_mi_step = mi_size_high[bottom_mbmi->sb_type]; + while (!is_neighbor_overlappable(bottom_mbmi)) { + mi_col_offset += search_mi_step; + if (mi_col_offset < mi_nums) { + bottom_mi = xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride]; + bottom_mbmi = &bottom_mi->mbmi; + search_mi_step = mi_size_high[bottom_mbmi->sb_type]; + } else { + if (overlappable_offset >= 0) { + mi_col_offset = overlappable_offset; + } else { + mi_col_offset = 0; + mi_row_offset = 0; + } + bottom_mi = xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride]; + bottom_mbmi = &bottom_mi->mbmi; + break; + } + } + } else { + // update the available overlappable mi + overlappable_offset = mi_col_offset; + } + + backup_mbmi = *bottom_mbmi; + modify_neighbor_predictor_for_obmc(bottom_mbmi); + + for (j = 0; j < MAX_MB_PLANE; ++j) { + struct macroblockd_plane *const pd = &xd->plane[j]; + setup_pred_plane(&pd->dst, b_bsize, dst_buf[j], MAX_SB_SIZE, MAX_SB_SIZE, + dst_stride[j], mi_row_shift, i, NULL, pd->subsampling_x, + pd->subsampling_y); + } +#if CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF + for (ref = 0; ref < 1 + (is_inter_anyref_comp_mode(bottom_mbmi->mode)); + ++ref) { + const MV_REFERENCE_FRAME frame = has_second_ref(bottom_mbmi) + ? bottom_mbmi->ref_frame[ref] + : bottom_mbmi->ref_frame[0]; +#else // !(CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF) + for (ref = 0; ref < 1 + has_second_ref(bottom_mbmi); ++ref) { + const MV_REFERENCE_FRAME frame = bottom_mbmi->ref_frame[ref]; +#endif // CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF + const RefBuffer *const ref_buf = &cm->frame_refs[frame - LAST_FRAME]; + xd->block_refs[ref] = ref_buf; + if ((!av1_is_valid_scale(&ref_buf->sf))) + aom_internal_error(xd->error_info, AOM_CODEC_UNSUP_BITSTREAM, + "Reference frame has invalid dimensions"); + av1_setup_pre_planes(xd, ref, ref_buf->buf, mi_row + mi_row_shift, + mi_col + i, &ref_buf->sf); + } + + xd->mb_to_left_edge = -(((mi_col + i) * MI_SIZE) * 8); + xd->mb_to_right_edge = + mb_to_right_edge_base + (mi_nums - i - mi_step) * MI_SIZE * 8; + mi_x = (mi_col + i) << MI_SIZE_LOG2; + mi_y = (mi_row + mi_row_shift) << MI_SIZE_LOG2; + + for (j = 0; j < MAX_MB_PLANE; ++j) { + const struct macroblockd_plane *pd = &xd->plane[j]; + + bh = mi_size_high[bsize] << (MI_SIZE_LOG2 - 1) >> pd->subsampling_x; + bw = (mi_step << MI_SIZE_LOG2) >> pd->subsampling_y; + + build_inter_predictors(cm, xd, j, mi_col_offset, mi_row_offset, 0, bw, bh, + 0, 0, bw, bh, +#if CONFIG_SUPERTX && CONFIG_EXT_INTER + 0, 0, +#endif // CONFIG_SUPERTX && CONFIG_EXT_INTER + mi_x, mi_y); + } + + *bottom_mbmi = backup_mbmi; + } + // restore the boundaries + xd->mb_to_top_edge = mb_to_top_edge_base; + xd->mb_to_bottom_edge = mb_to_bottom_edge_base; + xd->mb_to_left_edge = mb_to_left_edge_base; + xd->mb_to_right_edge = mb_to_right_edge_base; +} + +void get_pred_by_corner_neighbor(const AV1_COMMON *cm, MACROBLOCKD *xd, + int bsize, int mi_row, int mi_col, + uint8_t *dst_buf[MAX_MB_PLANE], + int dst_stride[MAX_MB_PLANE]) { + const TileInfo *const tile = &xd->tile; + const int mb_to_bottom_edge_base = xd->mb_to_bottom_edge; + const int mb_to_top_edge_base = xd->mb_to_top_edge; + const int mb_to_left_edge_base = xd->mb_to_left_edge; + const int mb_to_right_edge_base = xd->mb_to_right_edge; + const int mi_wide = mi_size_wide[bsize]; + const int mi_high = mi_size_high[bsize]; + + // location of four mi sources + const int mi_row_offsets[4] = { -1, -1, mi_high, mi_high }; + const int mi_col_offsets[4] = { -1, mi_wide, -1, mi_wide }; + + MB_MODE_INFO backup_mbmi; + int mi_x, mi_y, bh, bw; + int i, j, ref; + + assert(bsize >= BLOCK_8X8); + + for (i = 0; i < 4; ++i) { + int mi_row_offset = mi_row_offsets[i]; + int mi_col_offset = mi_col_offsets[i]; + MODE_INFO *corner_mi; + MB_MODE_INFO *corner_mbmi; + + if (mi_col + mi_col_offset < tile->mi_col_start || + mi_col + mi_col_offset > xd->sb_mi_bd.mi_col_end) + mi_col_offset = 0; + + if (mi_row + mi_row_offset < tile->mi_row_start || + mi_row + mi_row_offset > xd->sb_mi_bd.mi_row_end) + mi_row_offset = 0; + + corner_mi = xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride]; + corner_mbmi = &corner_mi->mbmi; + + // reset the mi if it is not overlappble + if (!is_neighbor_overlappable(corner_mbmi)) { + mi_row_offset = 0; + mi_col_offset = 0; + corner_mi = xd->mi[0]; + corner_mbmi = &corner_mi->mbmi; + } + + backup_mbmi = *corner_mbmi; + modify_neighbor_predictor_for_obmc(corner_mbmi); + + for (j = 0; j < MAX_MB_PLANE; ++j) { + struct macroblockd_plane *const pd = &xd->plane[j]; + setup_pred_plane(&pd->dst, BLOCK_8X8, dst_buf[j], MAX_SB_SIZE, + MAX_SB_SIZE, dst_stride[j], (i / 2) * (mi_high >> 1), + (i % 2) * (mi_wide >> 1), NULL, pd->subsampling_x, + pd->subsampling_y); + } + +#if CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF + for (ref = 0; ref < 1 + (is_inter_anyref_comp_mode(corner_mbmi->mode)); + ++ref) { + const MV_REFERENCE_FRAME frame = has_second_ref(corner_mbmi) + ? corner_mbmi->ref_frame[ref] + : corner_mbmi->ref_frame[0]; +#else + for (ref = 0; ref < 1 + has_second_ref(corner_mbmi); ++ref) { + const MV_REFERENCE_FRAME frame = corner_mbmi->ref_frame[ref]; +#endif + const RefBuffer *const ref_buf = &cm->frame_refs[frame - LAST_FRAME]; + xd->block_refs[ref] = ref_buf; + + if ((!av1_is_valid_scale(&ref_buf->sf))) + aom_internal_error(xd->error_info, AOM_CODEC_UNSUP_BITSTREAM, + "Reference frame has invalid dimensions"); + av1_setup_pre_planes(xd, ref, ref_buf->buf, + mi_row + (i / 2) * (mi_high >> 1), + mi_col + (i % 2) * (mi_wide >> 1), &ref_buf->sf); + } + // adjust mi boundaries of this block + xd->mb_to_bottom_edge = + mb_to_bottom_edge_base + (1 - (i / 2)) * mi_high * MI_SIZE * 4; + xd->mb_to_top_edge = mb_to_top_edge_base - (i / 2) * mi_high * MI_SIZE * 4; + xd->mb_to_right_edge = + mb_to_right_edge_base + (1 - (i % 2)) * mi_wide * MI_SIZE * 4; + xd->mb_to_left_edge = + mb_to_left_edge_base - (i % 2) * mi_wide * MI_SIZE * 4; + + mi_x = (mi_col + (i % 2) * mi_wide / 2) << MI_SIZE_LOG2; + mi_y = (mi_row + (i / 2) * mi_high / 2) << MI_SIZE_LOG2; + + for (j = 0; j < MAX_MB_PLANE; ++j) { + const struct macroblockd_plane *pd = &xd->plane[j]; + bh = mi_high << MI_SIZE_LOG2 >> (pd->subsampling_x + 1); + bw = mi_wide << MI_SIZE_LOG2 >> (pd->subsampling_y + 1); + build_inter_predictors(cm, xd, j, mi_col_offset, mi_row_offset, 0, bw, bh, + 0, 0, bw, bh, +#if CONFIG_SUPERTX && CONFIG_EXT_INTER + 0, 0, +#endif // CONFIG_SUPERTX && CONFIG_EXT_INTER + mi_x, mi_y); + } + *corner_mbmi = backup_mbmi; + } + // restore the boundaries + xd->mb_to_bottom_edge = mb_to_bottom_edge_base; + xd->mb_to_top_edge = mb_to_top_edge_base; + xd->mb_to_right_edge = mb_to_right_edge_base; + xd->mb_to_left_edge = mb_to_left_edge_base; +} + +// get the stitched extra prediction for this block +void av1_get_ext_blk_preds(const AV1_COMMON *cm, MACROBLOCKD *xd, int bsize, + int mi_row, int mi_col, + uint8_t *dst_buf[][MAX_MB_PLANE], + int dst_stride[MAX_MB_PLANE]) { + get_pred_by_corner_neighbor(cm, xd, bsize, mi_row, mi_col, dst_buf[0], + dst_stride); + get_pred_by_vert_neighbor(cm, xd, bsize, mi_row, mi_col, dst_buf[1], + dst_stride); + get_pred_by_horz_neighbor(cm, xd, bsize, mi_row, mi_col, dst_buf[2], + dst_stride); +} + +void av1_get_ori_blk_pred(const AV1_COMMON *cm, MACROBLOCKD *xd, int bsize, + int mi_row, int mi_col, + uint8_t *dst_buf[MAX_MB_PLANE], + int dst_stride[MAX_MB_PLANE]) { + MODE_INFO *const mi = xd->mi[0]; + MB_MODE_INFO *const mbmi = &mi->mbmi; + int mi_x = mi_col << MI_SIZE_LOG2; + int mi_y = mi_row << MI_SIZE_LOG2; + int bw = block_size_wide[bsize]; + int bh = block_size_high[bsize]; + int i, ref; + + for (i = 0; i < MAX_MB_PLANE; ++i) { + struct macroblockd_plane *const pd = &xd->plane[i]; + setup_pred_plane(&pd->dst, BLOCK_8X8, dst_buf[i], MAX_SB_SIZE, MAX_SB_SIZE, + dst_stride[i], 0, 0, NULL, pd->subsampling_x, + pd->subsampling_y); + } + + for (ref = 0; ref < 1 + has_second_ref(mbmi); ++ref) { + const MV_REFERENCE_FRAME frame = mbmi->ref_frame[ref]; + const RefBuffer *const ref_buf = &cm->frame_refs[frame - LAST_FRAME]; + xd->block_refs[ref] = ref_buf; + + if (!av1_is_valid_scale(&ref_buf->sf)) + aom_internal_error(xd->error_info, AOM_CODEC_UNSUP_BITSTREAM, + "Reference frame has invalid dimensions"); + + av1_setup_pre_planes(xd, ref, ref_buf->buf, mi_row, mi_col, &ref_buf->sf); + } + + for (i = 0; i < MAX_MB_PLANE; ++i) { + const struct macroblockd_plane *pd = &xd->plane[i]; + build_inter_predictors(cm, xd, i, 0, 0, 0, bw >> pd->subsampling_x, + bh >> pd->subsampling_y, 0, 0, + bw >> pd->subsampling_x, bh >> pd->subsampling_y, +#if CONFIG_SUPERTX && CONFIG_EXT_INTER + 0, 0, +#endif // CONFIG_SUPERTX && CONFIG_EXT_INTER + mi_x, mi_y); + } +} + +#endif
diff --git a/av1/common/reconinter.h b/av1/common/reconinter.h index 2296460..7d6badb 100644 --- a/av1/common/reconinter.h +++ b/av1/common/reconinter.h
@@ -873,6 +873,45 @@ int ext_dst_stride1[3]); #endif // CONFIG_EXT_INTER +#if CONFIG_NCOBMC_ADAPT_WEIGHT +#define ASSIGN_ALIGNED_PTRS(p, a, s) \ + p[0] = a; \ + p[1] = a + s; \ + p[2] = a + 2 * s; + +#define ASSIGN_ALIGNED_PTRS_HBD(p, a, s, l) \ + p[0] = CONVERT_TO_BYTEPTR(a); \ + p[1] = CONVERT_TO_BYTEPTR(a + s * l); \ + p[2] = CONVERT_TO_BYTEPTR(a + 2 * s * l); + +void alloc_ncobmc_pred_buffer(MACROBLOCKD *const xd); +void free_ncobmc_pred_buffer(MACROBLOCKD *const xd); +void set_sb_mi_boundaries(const AV1_COMMON *const cm, MACROBLOCKD *const xd, + const int mi_row, const int mi_col); + +void reset_xd_boundary(MACROBLOCKD *xd, int mi_row, int bh, int mi_col, int bw, + int mi_rows, int mi_cols); + +void get_pred_from_intrpl_buf(MACROBLOCKD *xd, int mi_row, int mi_col, + BLOCK_SIZE bsize, int plane); + +void build_ncobmc_intrpl_pred(const AV1_COMMON *const cm, MACROBLOCKD *xd, + int plane, int pxl_row, int pxl_col, + BLOCK_SIZE bsize, uint8_t *preds[][MAX_MB_PLANE], + int ps[MAX_MB_PLANE], // pred buffer strides + int mode); + +void av1_get_ext_blk_preds(const AV1_COMMON *cm, MACROBLOCKD *xd, int bsize, + int mi_row, int mi_col, + uint8_t *dst_buf[][MAX_MB_PLANE], + int dst_stride[MAX_MB_PLANE]); + +void av1_get_ori_blk_pred(const AV1_COMMON *cm, MACROBLOCKD *xd, int bsize, + int mi_row, int mi_col, + uint8_t *dst_buf[MAX_MB_PLANE], + int dst_stride[MAX_MB_PLANE]); +#endif // CONFIG_NCOBMC_ADAPT_WEIGHT + #ifdef __cplusplus } // extern "C" #endif