blob: 7ca08cad00db81dbc55b4df03f6a2efb7ef0ba24 [file] [log] [blame] [edit]
/*
* Copyright (c) 2022, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 3-Clause Clear License
* and the Alliance for Open Media Patent License 1.0. If the BSD 3-Clause Clear
* License was not distributed with this source code in the LICENSE file, you
* can obtain it at aomedia.org/license/software-license/bsd-3-c-c/. If the
* Alliance for Open Media Patent License 1.0 was not distributed with this
* source code in the PATENTS file, you can obtain it at
* aomedia.org/license/patent-license/.
*/
#include "av1/common/bru.h"
#include "av1/common/common_data.h"
#include "config/aom_config.h"
#include "config/aom_dsp_rtcd.h"
#include "config/av1_rtcd.h"
#include "av1/common/reconinter.h"
#include "av1/common/ccso.h"
/* clean up tx_skip array for support and inactive SBs */
void bru_update_txk_skip_array(const AV1_COMMON *cm, int mi_row, int mi_col,
TREE_TYPE tree_type,
const CHROMA_REF_INFO *chroma_ref_info,
int plane, int blk_w, int blk_h) {
(void)tree_type;
(void)chroma_ref_info;
if (mi_col + blk_w > cm->mi_params.mi_cols)
blk_w = cm->mi_params.mi_cols - mi_col;
if (mi_row + blk_h > cm->mi_params.mi_rows)
blk_h = cm->mi_params.mi_rows - mi_row;
blk_w = blk_w >> ((plane == 0) ? 0 : cm->seq_params.subsampling_x);
blk_h = blk_h >> ((plane == 0) ? 0 : cm->seq_params.subsampling_y);
int w = ((cm->width + MAX_SB_SIZE - 1) >> MAX_SB_SIZE_LOG2)
<< MAX_SB_SIZE_LOG2;
w >>= ((plane == 0) ? 0 : cm->seq_params.subsampling_x);
const uint32_t stride = (w + MIN_TX_SIZE - 1) >> MIN_TX_SIZE_LOG2;
const int cols = (blk_w << MI_SIZE_LOG2) >> MIN_TX_SIZE_LOG2;
const int rows = (blk_h << MI_SIZE_LOG2) >> MIN_TX_SIZE_LOG2;
int x = (mi_col << MI_SIZE_LOG2) >>
((plane == 0) ? 0 : cm->seq_params.subsampling_x);
int y = (mi_row << MI_SIZE_LOG2) >>
((plane == 0) ? 0 : cm->seq_params.subsampling_y);
x = x >> MIN_TX_SIZE_LOG2;
y = y >> MIN_TX_SIZE_LOG2;
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
const uint32_t idx = (y + r) * stride + x + c;
assert(idx < cm->mi_params.tx_skip_buf_size[plane]);
assert(stride == cm->mi_params.tx_skip_stride[plane]);
cm->mi_params.tx_skip[plane][idx] = 1;
}
}
}
/* Set correct mbmi address for inactive and support SB since there is no chance
* to set them in later stage */
BruActiveMode set_sb_mbmi_bru_mode(const AV1_COMMON *cm, MACROBLOCKD *const xd,
const int mi_col, const int mi_row,
const BLOCK_SIZE bsize,
const BruActiveMode bru_sb_mode) {
// only set very first mi
// for inactive SB, other location on the mi_grid is invalid
// for active SB, later set_offset will redo the address assignment
if (cm->bru.enabled) {
xd->mi_col = mi_col;
xd->mi_row = mi_row;
const int mi_grid_idx = get_mi_grid_idx(&cm->mi_params, mi_row, mi_col);
const int mi_alloc_idx = get_alloc_mi_idx(&cm->mi_params, mi_row, mi_col);
cm->mi_params.mi_grid_base[mi_grid_idx] =
&cm->mi_params.mi_alloc[mi_alloc_idx];
xd->mi = cm->mi_params.mi_grid_base + mi_grid_idx;
xd->mi[0]->sb_active_mode = bru_sb_mode;
// if not active, propagate to all the mi in bsize
// this function will also be used in decoder
if (bru_sb_mode != BRU_ACTIVE_SB) {
const int mi_h = mi_size_high[bsize];
const int mi_w = mi_size_wide[bsize];
MB_MODE_INFO *const mi_addr = xd->mi[0];
const int x_inside_boundary =
AOMMIN(mi_w, cm->mi_params.mi_cols - mi_col);
const int y_inside_boundary =
AOMMIN(mi_h, cm->mi_params.mi_rows - mi_row);
const int mis = cm->mi_params.mi_stride;
for (int y = 0; y < y_inside_boundary; y++) {
for (int x_idx = 0; x_idx < x_inside_boundary; x_idx++) {
xd->mi[x_idx + y * mis] = mi_addr;
}
}
}
return bru_sb_mode;
}
return BRU_ACTIVE_SB;
}
/* Copy recon data from BRU ref to current frame buffer. This is only used for
* BRU_SUPPORT_SB of BRU optimized decoder/encoder */
void bru_copy_sb(const struct AV1Common *cm, const int mi_col,
const int mi_row) {
if (cm->bru.update_ref_idx < 0)
return; // now ref_idx is the sole indicator of frame level bru
const int sb_size = cm->seq_params.sb_size;
const int w = mi_size_wide[sb_size];
const int h = mi_size_high[sb_size];
RefCntBuffer *const ref_buf = get_ref_frame_buf(cm, cm->bru.update_ref_idx);
YV12_BUFFER_CONFIG *const ref_src = &ref_buf->buf;
YV12_BUFFER_CONFIG *const rec_dst = &cm->cur_frame->buf;
const int x_inside_boundary = AOMMIN(w, cm->mi_params.mi_cols - mi_col)
<< MI_SIZE_LOG2;
const int y_inside_boundary = AOMMIN(h, cm->mi_params.mi_rows - mi_row)
<< MI_SIZE_LOG2;
const int x = mi_col << MI_SIZE_LOG2;
const int y = mi_row << MI_SIZE_LOG2;
for (int i_plane = 0; i_plane < av1_num_planes(cm); ++i_plane) {
uint16_t *rec_data = rec_dst->buffers[i_plane];
uint16_t *ref_data = ref_src->buffers[i_plane];
int rec_stride = i_plane > 0 ? rec_dst->uv_stride : rec_dst->y_stride;
int ref_stride = i_plane > 0 ? ref_src->uv_stride : ref_src->y_stride;
int subsample_x = i_plane > 0 ? ref_src->subsampling_x : 0;
int subsample_y = i_plane > 0 ? ref_src->subsampling_y : 0;
uint64_t rec_offset = scaled_buffer_offset(
x >> subsample_x, y >> subsample_y, rec_stride, NULL);
uint64_t ref_offset = scaled_buffer_offset(
x >> subsample_x, y >> subsample_y, ref_stride, NULL);
copy_tile(x_inside_boundary >> subsample_x,
y_inside_boundary >> subsample_y, ref_data + ref_offset,
ref_stride, rec_data + rec_offset, rec_stride);
}
if (cm->seq_params.order_hint_info.enable_ref_frame_mvs) {
// set cur_frame mvs to 0
bru_zero_sb_mvs(cm, -1, mi_row, mi_col, x_inside_boundary >> MI_SIZE_LOG2,
y_inside_boundary >> MI_SIZE_LOG2);
}
return;
}
/* Update recon data from current frame buffer to BRU ref. This is only used for
* BRU_ACTIVE_SB of BRU optimized decoder/encoder */
void bru_update_sb(const struct AV1Common *cm, const int mi_col,
const int mi_row) {
if (cm->bru.update_ref_idx < 0)
return; // now ref_idx is the sole indicator of frame level bru
RefCntBuffer *const ref_buf = get_ref_frame_buf(cm, cm->bru.update_ref_idx);
// just swap these two
YV12_BUFFER_CONFIG *const rec_dst = &ref_buf->buf;
YV12_BUFFER_CONFIG *const ref_src = &cm->cur_frame->buf;
const int sb_size = cm->seq_params.sb_size;
const int w = mi_size_wide[sb_size];
const int h = mi_size_high[sb_size];
const int x_inside_boundary = AOMMIN(w, cm->mi_params.mi_cols - mi_col)
<< MI_SIZE_LOG2;
const int y_inside_boundary = AOMMIN(h, cm->mi_params.mi_rows - mi_row)
<< MI_SIZE_LOG2;
const int x = mi_col << MI_SIZE_LOG2;
const int y = mi_row << MI_SIZE_LOG2;
for (int i_plane = 0; i_plane < av1_num_planes(cm); ++i_plane) {
uint16_t *rec_data = rec_dst->buffers[i_plane];
uint16_t *ref_data = ref_src->buffers[i_plane];
const int rec_stride = i_plane > 0 ? rec_dst->uv_stride : rec_dst->y_stride;
const int ref_stride = i_plane > 0 ? ref_src->uv_stride : ref_src->y_stride;
const int subsample_x = i_plane > 0 ? ref_src->subsampling_x : 0;
const int subsample_y = i_plane > 0 ? ref_src->subsampling_y : 0;
const uint64_t rec_offset = scaled_buffer_offset(
x >> subsample_x, y >> subsample_y, rec_stride, NULL);
const uint64_t ref_offset = scaled_buffer_offset(
x >> subsample_x, y >> subsample_y, ref_stride, NULL);
copy_tile(x_inside_boundary >> subsample_x,
y_inside_boundary >> subsample_y, ref_data + ref_offset,
ref_stride, rec_data + rec_offset, rec_stride);
}
if (cm->seq_params.order_hint_info.enable_ref_frame_mvs) {
// copy mvs from cur frame to ref frame
// It is ok to copy since all TMVP are collocated now
bru_copy_sb_mvs(cm, -1, cm->bru.update_ref_idx, mi_row, mi_col,
x_inside_boundary >> MI_SIZE_LOG2,
y_inside_boundary >> MI_SIZE_LOG2);
}
}
/* Set default inter mode for Support and Inactive SBs */
void bru_set_default_inter_mb_mode_info(const AV1_COMMON *const cm,
MACROBLOCKD *const xd,
MB_MODE_INFO *const mbmi,
BLOCK_SIZE bsize) {
// think reuse init_mbmi() here
mbmi->segment_id = 0;
mbmi->skip_mode = 0;
xd->tree_type = SHARED_PART;
mbmi->skip_txfm[xd->tree_type == CHROMA_PART] = 1;
mbmi->uv_mode = UV_DC_PRED;
mbmi->palette_mode_info.palette_size[0] = 0;
mbmi->palette_mode_info.palette_size[1] = 0;
mbmi->fsc_mode[PLANE_TYPE_Y] = 0;
mbmi->fsc_mode[PLANE_TYPE_UV] = 0;
#if CONFIG_NEW_CONTEXT_MODELING
mbmi->use_intrabc[0] = 0;
mbmi->use_intrabc[1] = 0;
#endif
mbmi->bawp_flag[0] = 0;
mbmi->bawp_flag[1] = 0;
mbmi->cwp_idx = CWP_EQUAL;
#if CONFIG_IBC_SR_EXT
mbmi->use_intrabc[xd->tree_type == CHROMA_PART] = 0;
#endif // CONFIG_IBC_SR_EXT
#if CONFIG_C076_INTER_MOD_CTX
#if CONFIG_REFINEMV
mbmi->refinemv_flag = 0;
#endif // CONFIG_REFINEMV
#endif // CONFIG_C076_INTER_MOD_CTX
#if CONFIG_SEP_COMP_DRL
mbmi->ref_mv_idx[0] = 0;
mbmi->ref_mv_idx[1] = 0;
#else
mbmi->ref_mv_idx = 0;
#endif
mbmi->warp_ref_idx = 0;
mbmi->max_num_warp_candidates = 0;
mbmi->warpmv_with_mvd_flag = 0;
mbmi->motion_mode = SIMPLE_TRANSLATION;
mbmi->filter_intra_mode_info.use_filter_intra = 0;
mbmi->interintra_mode = (INTERINTRA_MODE)(II_DC_PRED - 1);
mbmi->comp_group_idx = 0;
mbmi->interinter_comp.type = COMPOUND_AVERAGE;
mbmi->mv[0].as_int = 0;
mbmi->mv[1].as_int = 0;
assert(cm->bru.update_ref_idx >= 0);
#if CONFIG_WARP_INTER_INTRA
mbmi->warp_inter_intra = 0;
#endif
// todo find del idx
mbmi->ref_frame[0] = cm->bru.update_ref_idx;
mbmi->ref_frame[1] = NONE_FRAME;
mbmi->skip_mode = 0;
mbmi->skip_txfm[xd->tree_type == CHROMA_PART] = 1;
mbmi->mode = NEWMV;
mbmi->region_type = MIXED_INTER_INTRA_REGION;
mbmi->sb_type[0] = bsize;
mbmi->sb_type[1] = bsize;
mbmi->chroma_ref_info.bsize_base = bsize;
mbmi->chroma_ref_info.bsize = bsize;
xd->mi[0]->mi_col_start = xd->mi_col;
xd->mi[0]->mi_row_start = xd->mi_row;
xd->mi[0]->chroma_ref_info.mi_col_chroma_base = xd->mi_col;
xd->mi[0]->chroma_ref_info.mi_row_chroma_base = xd->mi_row;
xd->ccso_blk_y = 0;
xd->ccso_blk_u = 0;
xd->ccso_blk_v = 0;
mbmi->ccso_blk_y = 0;
mbmi->ccso_blk_u = 0;
mbmi->ccso_blk_v = 0;
mbmi->cdef_strength = -1;
mbmi->local_rest_type = 0;
mbmi->local_ccso_blk_flag = 0;
set_default_max_mv_precision(mbmi, xd->sbi->sb_mv_precision);
/// bru use only pixel precision
set_mv_precision(mbmi, MV_PRECISION_ONE_PEL);
// set_mv_precision(mbmi, mbmi->max_mv_precision);
set_default_precision_set(cm, mbmi, cm->seq_params.sb_size);
set_most_probable_mv_precision(cm, mbmi, cm->seq_params.sb_size);
mbmi->interp_fltr = MULTITAP_SHARP;
#if !CONFIG_TX_PARTITION_CTX
xd->above_txfm_context =
cm->above_contexts.txfm[xd->tile.tile_row] + xd->mi_col;
xd->left_txfm_context =
xd->left_txfm_context_buffer + (xd->mi_row & MAX_MIB_MASK);
#endif
if (is_bru_not_active_and_not_on_partial_border(cm, xd->mi_col, xd->mi_row,
bsize)) {
mbmi->tx_size = TX_64X64;
} else {
mbmi->tx_size = tx_size_from_tx_mode(bsize, cm->features.tx_mode);
}
for (int plane = 0; plane < 1; plane++) {
bru_update_txk_skip_array(cm, xd->mi_row, xd->mi_col, xd->tree_type,
&mbmi->chroma_ref_info, plane, MAX_MIB_SIZE,
MAX_MIB_SIZE);
}
}
/* Core function of swap BRU reference frame and current frame for BRU optimized
* decoder/encoder*/
RefCntBuffer *bru_swap_common(AV1_COMMON *cm) {
// should not use this function at all in none bru frames
if (cm->bru.enabled) {
assert(cm->bru.update_ref_idx >= 0);
RefCntBuffer *ref_buf = get_ref_frame_buf(cm, cm->bru.update_ref_idx);
assert(ref_buf != NULL);
cm->bru.update_ref_fc = ref_buf->frame_context; // pass all the values
MV_REFERENCE_FRAME ref_frame;
for (ref_frame = 0; ref_frame < INTER_REFS_PER_FRAME; ++ref_frame) {
const RefCntBuffer *const buf = get_ref_frame_buf(cm, ref_frame);
if (buf != NULL && ref_frame < cm->ref_frames_info.num_total_refs) {
ref_buf->ref_order_hints[ref_frame] = buf->order_hint;
ref_buf->ref_display_order_hint[ref_frame] = buf->display_order_hint;
} else {
ref_buf->ref_order_hints[ref_frame] = -1;
ref_buf->ref_display_order_hint[ref_frame] = -1;
}
}
#if CONFIG_TEMP_LR
RefCntBuffer *tmp_buf = cm->cur_frame;
#endif
ref_buf->order_hint = cm->cur_frame->order_hint;
ref_buf->display_order_hint = cm->cur_frame->display_order_hint;
ref_buf->absolute_poc = cm->cur_frame->absolute_poc;
ref_buf->pyramid_level = cm->cur_frame->pyramid_level;
ref_buf->base_qindex = cm->cur_frame->base_qindex;
ref_buf->num_ref_frames = cm->cur_frame->num_ref_frames;
#if CONFIG_OUTPUT_FRAME_BASED_ON_ORDER_HINT_ENHANCEMENT
ref_buf->frame_output_done = 0;
#endif
#if CONFIG_TEMP_LR
ref_buf->rst_info[0] = tmp_buf->rst_info[0];
ref_buf->rst_info[1] = tmp_buf->rst_info[1];
ref_buf->rst_info[2] = tmp_buf->rst_info[2];
av1_copy_rst_frame_filters(&ref_buf->rst_info[0], &tmp_buf->rst_info[0]);
av1_copy_rst_frame_filters(&ref_buf->rst_info[1], &tmp_buf->rst_info[1]);
av1_copy_rst_frame_filters(&ref_buf->rst_info[2], &tmp_buf->rst_info[2]);
#endif
if (cm->bru.frame_inactive_flag) {
ref_buf->ccso_info.ccso_frame_flag = 0;
} else {
ref_buf->ccso_info.ccso_frame_flag = tmp_buf->ccso_info.ccso_frame_flag;
}
for (int plane = 0; plane < CCSO_NUM_COMPONENTS; plane++) {
if (cm->bru.frame_inactive_flag) {
av1_copy_ccso_filters(&ref_buf->ccso_info, &cm->ccso_info, plane, 1, 0,
0);
continue;
}
// copy from current to bru ref
ref_buf->ccso_info.reuse_ccso[plane] =
tmp_buf->ccso_info.reuse_ccso[plane];
ref_buf->ccso_info.sb_reuse_ccso[plane] =
tmp_buf->ccso_info.sb_reuse_ccso[plane];
ref_buf->ccso_info.ccso_enable[plane] =
tmp_buf->ccso_info.ccso_enable[plane];
ref_buf->ccso_info.ccso_ref_idx[plane] =
tmp_buf->ccso_info.ccso_ref_idx[plane];
ref_buf->ccso_info.subsampling_x[plane] =
plane > 0 ? cm->seq_params.subsampling_x : 0;
ref_buf->ccso_info.subsampling_y[plane] =
plane > 0 ? cm->seq_params.subsampling_y : 0;
ref_buf->ccso_info.reuse_root_ref[plane] =
tmp_buf->ccso_info.reuse_root_ref[plane];
#if CONFIG_CCSO_FU_BUGFIX
const int log2_filter_unit_size_y =
plane == 0 ? CCSO_BLK_SIZE
: CCSO_BLK_SIZE - cm->seq_params.subsampling_y;
const int log2_filter_unit_size_x =
plane == 0 ? CCSO_BLK_SIZE
: CCSO_BLK_SIZE - cm->seq_params.subsampling_x;
#else
const int log2_filter_unit_size_y =
pli > 0 ? CCSO_BLK_SIZE
: CCSO_BLK_SIZE + cm->seq_params.subsampling_y;
const int log2_filter_unit_size_x =
pli > 0 ? CCSO_BLK_SIZE
: CCSO_BLK_SIZE + cm->seq_params.subsampling_x;
#endif // CONFIG_CCSO_FU_BUGFIX
const int ccso_nvfb = ((cm->mi_params.mi_rows >>
(plane ? cm->seq_params.subsampling_y : 0)) +
(1 << log2_filter_unit_size_y >> 2) - 1) /
(1 << log2_filter_unit_size_y >> 2);
const int ccso_nhfb = ((cm->mi_params.mi_cols >>
(plane ? cm->seq_params.subsampling_x : 0)) +
(1 << log2_filter_unit_size_x >> 2) - 1) /
(1 << log2_filter_unit_size_x >> 2);
const int sb_count = ccso_nvfb * ccso_nhfb;
av1_copy_ccso_filters(&ref_buf->ccso_info, &tmp_buf->ccso_info, plane, 1,
1, sb_count);
}
// replace cur by bru_ref
assign_frame_buffer_p(&cm->cur_frame, ref_buf);
return ref_buf;
}
return NULL;
}