blob: d95661edd62a24d59a192406ad831874be773e92 [file] [log] [blame] [edit]
/*
* Copyright (c) 2025, 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/gdf.h"
#include "pred_common.h"
#include "av1/common/gdf_block.h"
#if CONFIG_GDF
void init_gdf(GdfInfo *gi, int mib_size, int rec_height, int rec_width) {
gi->gdf_mode = 0;
gi->gdf_pic_qp_idx = 0;
gi->gdf_pic_scale_idx = 0;
gi->gdf_block_size = AOMMAX(mib_size << MI_SIZE_LOG2, GDF_TEST_BLK_SIZE);
gi->gdf_block_num_h =
1 + ((rec_height + GDF_TEST_STRIPE_OFF - 1) / gi->gdf_block_size);
gi->gdf_block_num_w = 1 + ((rec_width - 1) / gi->gdf_block_size);
gi->gdf_block_num = gi->gdf_block_num_h * gi->gdf_block_num_w;
gi->gdf_stripe_size = GDF_TEST_STRIPE_SIZE;
gi->gdf_unit_size = GDF_TEST_STRIPE_SIZE;
gi->err_height = gi->gdf_unit_size;
gi->lap_stride = gi->gdf_unit_size + GDF_ERR_STRIDE_MARGIN;
gi->cls_stride = (gi->gdf_unit_size >> 1) + GDF_ERR_STRIDE_MARGIN;
gi->err_stride = gi->gdf_unit_size + GDF_ERR_STRIDE_MARGIN;
}
void alloc_gdf_buffers(GdfInfo *gi) {
free_gdf_buffers(gi);
gi->lap_ptr =
(uint16_t **)aom_malloc(GDF_NET_INP_GRD_NUM * sizeof(uint16_t *));
const int lap_buf_height = (gi->err_height >> 1) + 2;
const int cls_buf_height = (gi->err_height >> 1) + 2;
for (int i = 0; i < GDF_NET_INP_GRD_NUM; i++) {
gi->lap_ptr[i] = (uint16_t *)aom_memalign(
32, lap_buf_height * gi->lap_stride * sizeof(uint16_t));
memset(gi->lap_ptr[i], 0,
lap_buf_height * gi->lap_stride * sizeof(uint16_t));
}
gi->cls_ptr = (uint32_t *)aom_memalign(
32, cls_buf_height * gi->cls_stride * sizeof(uint32_t));
memset(gi->cls_ptr, 0, cls_buf_height * gi->cls_stride * sizeof(uint32_t));
gi->err_ptr = (int16_t *)aom_memalign(
32, gi->err_height * gi->err_stride * sizeof(int16_t));
memset(gi->err_ptr, 0, gi->err_height * gi->err_stride * sizeof(int16_t));
gi->gdf_block_flags = (int32_t *)aom_malloc(gi->gdf_block_num * sizeof(int));
memset(gi->gdf_block_flags, 0, gi->gdf_block_num * sizeof(int));
}
void free_gdf_buffers(GdfInfo *gi) {
if (gi->lap_ptr != NULL) {
for (int i = 0; i < GDF_NET_INP_GRD_NUM; i++) {
aom_free(gi->lap_ptr[i]);
gi->lap_ptr[i] = NULL;
}
aom_free(gi->lap_ptr);
gi->lap_ptr = NULL;
}
if (gi->cls_ptr != NULL) {
aom_free(gi->cls_ptr);
gi->cls_ptr = NULL;
}
if (gi->err_ptr != NULL) {
aom_free(gi->err_ptr);
gi->err_ptr = NULL;
}
if (gi->gdf_block_flags != NULL) {
aom_free(gi->gdf_block_flags);
gi->gdf_block_flags = NULL;
}
}
#define GDF_PRINT_INT(x) printf(#x " : %d\n", x)
void gdf_print_info(AV1_COMMON *cm, char *info, int poc) {
printf("=================GDF %s info=================\n", info);
GDF_PRINT_INT(cm->cur_frame->buf.y_width);
GDF_PRINT_INT(cm->cur_frame->buf.y_height);
GDF_PRINT_INT(cm->cur_frame->buf.y_stride);
GDF_PRINT_INT(cm->cur_frame->buf.bit_depth);
GDF_PRINT_INT(cm->quant_params.base_qindex);
GDF_PRINT_INT(cm->ref_frames_info.ref_frame_distance[0]);
GDF_PRINT_INT(cm->ref_frames_info.ref_frame_distance[1]);
GDF_PRINT_INT(cm->current_frame.frame_type);
GDF_PRINT_INT(cm->tiles.height);
GDF_PRINT_INT(cm->tiles.width);
GDF_PRINT_INT(cm->mib_size);
printf("%s[%3d]: gdf_info = [ flag = %d ", info, poc, cm->gdf_info.gdf_mode);
if (cm->gdf_info.gdf_mode > 0) {
printf("=> (qp_idx, scale_idx) = (%3d %3d) ", cm->gdf_info.gdf_pic_qp_idx,
cm->gdf_info.gdf_pic_scale_idx);
}
if (cm->gdf_info.gdf_mode > 1) {
printf("(");
for (int blk_idx = 0; blk_idx < cm->gdf_info.gdf_block_num; blk_idx++) {
printf(" %d", cm->gdf_info.gdf_block_flags[blk_idx]);
}
printf(")");
}
printf(" ]\n");
}
#undef GDF_PRINT_INT
void gdf_copy_guided_frame(AV1_COMMON *cm) {
int top_buf = 3, bot_buf = 3;
const int rec_height = cm->cur_frame->buf.y_height;
const int rec_stride = cm->cur_frame->buf.y_stride;
cm->gdf_info.inp_pad_ptr = (uint16_t *)aom_memalign(
32, (top_buf + rec_height + bot_buf) * rec_stride * sizeof(uint16_t));
for (int i = top_buf; i < top_buf + rec_height; i++) {
for (int j = 0; j < rec_stride; j++) {
cm->gdf_info.inp_pad_ptr[i * rec_stride + j] =
cm->cur_frame->buf
.buffers[AOM_PLANE_Y][(i - top_buf) * rec_stride + j];
}
}
cm->gdf_info.inp_ptr = cm->gdf_info.inp_pad_ptr + top_buf * rec_stride;
}
void gdf_free_guided_frame(AV1_COMMON *cm) {
aom_free(cm->gdf_info.inp_pad_ptr);
}
int gdf_get_block_idx(const AV1_COMMON *cm, int y_h, int y_w) {
int blk_idx = -1;
if (((y_h == 0) ||
((y_h + GDF_TEST_STRIPE_OFF) % cm->gdf_info.gdf_block_size == 0)) &&
((y_w == 0) || (y_w % cm->gdf_info.gdf_block_size == 0))) {
int blk_idx_h =
(y_h == 0)
? 0
: ((y_h + GDF_TEST_STRIPE_OFF) / cm->gdf_info.gdf_block_size);
int blk_idx_w = (y_w == 0) ? 0 : (y_w / cm->gdf_info.gdf_block_size);
blk_idx = blk_idx_h * cm->gdf_info.gdf_block_num_w + blk_idx_w;
}
blk_idx = blk_idx < cm->gdf_info.gdf_block_num ? blk_idx : -1;
return blk_idx;
}
static INLINE int get_ref_dst_max(const AV1_COMMON *const cm) {
int ref_dst_max = 0;
for (int i = 0; i < cm->ref_frames_info.num_future_refs; i++) {
const int ref = cm->ref_frames_info.future_refs[i];
if ((ref == 0 || ref == 1) && get_ref_frame_buf(cm, ref) != NULL) {
ref_dst_max =
AOMMAX(ref_dst_max, abs(cm->ref_frames_info.ref_frame_distance[ref]));
}
}
for (int i = 0; i < cm->ref_frames_info.num_past_refs; i++) {
const int ref = cm->ref_frames_info.past_refs[i];
if ((ref == 0 || ref == 1) && get_ref_frame_buf(cm, ref) != NULL) {
ref_dst_max =
AOMMAX(ref_dst_max, abs(cm->ref_frames_info.ref_frame_distance[ref]));
}
}
return ref_dst_max > 0 ? ref_dst_max : INT_MAX;
}
int gdf_get_ref_dst_idx(const AV1_COMMON *cm) {
int ref_dst_idx = 0;
if (frame_is_intra_only(cm)) return ref_dst_idx;
int ref_dst_max = get_ref_dst_max(cm);
if (ref_dst_max < 2)
ref_dst_idx = 1;
else if (ref_dst_max < 3)
ref_dst_idx = 2;
else if (ref_dst_max < 6)
ref_dst_idx = 3;
else if (ref_dst_max < 11)
ref_dst_idx = 4;
else
ref_dst_idx = 5;
return ref_dst_idx;
}
int gdf_get_qp_idx_base(const AV1_COMMON *cm) {
const int is_intra = frame_is_intra_only(cm);
const int bit_depth = cm->cur_frame->buf.bit_depth;
int qp_base = is_intra ? 85 : 110;
int qp_offset = 24 * (bit_depth - 8);
int qp = cm->quant_params.base_qindex;
int qp_idx_avg, qp_idx_base;
if (qp < (qp_base + 12 + qp_offset))
qp_idx_avg = 0;
else if (qp < (qp_base + 37 + qp_offset))
qp_idx_avg = 1;
else if (qp < (qp_base + 62 + qp_offset))
qp_idx_avg = 2;
else if (qp < (qp_base + 87 + qp_offset))
qp_idx_avg = 3;
else if (qp < (qp_base + 112 + qp_offset))
qp_idx_avg = 4;
else
qp_idx_avg = 5;
qp_idx_base = CLIP(qp_idx_avg - (GDF_RDO_QP_NUM >> 1), 0,
GDF_TRAIN_QP_NUM - GDF_RDO_QP_NUM);
return qp_idx_base;
}
void gdf_filter_frame(AV1_COMMON *cm) {
uint16_t *const rec_pnt = cm->cur_frame->buf.buffers[AOM_PLANE_Y];
const int rec_height = cm->cur_frame->buf.y_height;
const int rec_width = cm->cur_frame->buf.y_width;
const int rec_stride = cm->cur_frame->buf.y_stride;
#if CONFIG_BRU
if (cm->bru.frame_inactive_flag) return;
#endif
const int bit_depth = cm->cur_frame->buf.bit_depth;
const int pxl_max = (1 << cm->cur_frame->buf.bit_depth) - 1;
const int pxl_shift = GDF_TEST_INP_PREC - bit_depth;
const int err_shift = GDF_RDO_SCALE_NUM_LOG2 + pxl_shift;
int ref_dst_idx = gdf_get_ref_dst_idx(cm);
int qp_idx_min = gdf_get_qp_idx_base(cm) + cm->gdf_info.gdf_pic_qp_idx;
int qp_idx_max_plus_1 = qp_idx_min + 1;
int scale_val = cm->gdf_info.gdf_pic_scale_idx + 1;
int blk_idx = 0;
for (int y_pos = -GDF_TEST_STRIPE_OFF; y_pos < rec_height;
y_pos += cm->gdf_info.gdf_block_size) {
for (int x_pos = 0; x_pos < rec_width;
x_pos += cm->gdf_info.gdf_block_size) {
for (int v_pos = y_pos;
v_pos < y_pos + cm->gdf_info.gdf_block_size && v_pos < rec_height;
v_pos += cm->gdf_info.gdf_unit_size) {
for (int u_pos = x_pos;
u_pos < x_pos + cm->gdf_info.gdf_block_size && u_pos < rec_width;
u_pos += cm->gdf_info.gdf_unit_size) {
int i_min = AOMMAX(v_pos, GDF_TEST_FRAME_BOUNDARY_SIZE);
int i_max = AOMMIN(v_pos + cm->gdf_info.gdf_unit_size,
rec_height - GDF_TEST_FRAME_BOUNDARY_SIZE);
int j_min = AOMMAX(u_pos, GDF_TEST_FRAME_BOUNDARY_SIZE);
int j_max = AOMMIN(u_pos + cm->gdf_info.gdf_unit_size,
rec_width - GDF_TEST_FRAME_BOUNDARY_SIZE);
int use_gdf_local = 1;
#if CONFIG_BRU
// FU level skip
if (cm->bru.enabled) {
const int mbmi_idx = get_mi_grid_idx(
&cm->mi_params, i_min >> MI_SIZE_LOG2, j_min >> MI_SIZE_LOG2);
use_gdf_local =
cm->mi_params.mi_grid_base[mbmi_idx]->local_gdf_mode;
}
#endif
use_gdf_local &=
gdf_block_adjust_and_validate(&i_min, &i_max, &j_min, &j_max);
if ((cm->gdf_info.gdf_mode == 1 ||
cm->gdf_info.gdf_block_flags[blk_idx]) &&
use_gdf_local) {
#if CONFIG_BRU
const int bru_blk_skip = !bru_is_sb_active(
cm, j_min >> MI_SIZE_LOG2, i_min >> MI_SIZE_LOG2);
if (cm->bru.enabled && bru_blk_skip) {
aom_internal_error(&cm->error, AOM_CODEC_ERROR,
"GDF on not active SB");
}
#endif
for (int qp_idx = qp_idx_min; qp_idx < qp_idx_max_plus_1;
qp_idx++) {
gdf_set_lap_and_cls_unit(
i_min, i_max, j_min, j_max, cm->gdf_info.gdf_stripe_size,
cm->gdf_info.inp_ptr + rec_stride * i_min + j_min, rec_stride,
bit_depth, cm->gdf_info.lap_ptr, cm->gdf_info.lap_stride,
cm->gdf_info.cls_ptr, cm->gdf_info.cls_stride);
gdf_inference_unit(
i_min, i_max, j_min, j_max, cm->gdf_info.gdf_stripe_size,
qp_idx, cm->gdf_info.inp_ptr + rec_stride * i_min + j_min,
rec_stride, cm->gdf_info.lap_ptr, cm->gdf_info.lap_stride,
cm->gdf_info.cls_ptr, cm->gdf_info.cls_stride,
cm->gdf_info.err_ptr, cm->gdf_info.err_stride, pxl_shift,
ref_dst_idx);
gdf_compensation_unit(
rec_pnt + i_min * rec_stride + j_min, rec_stride,
cm->gdf_info.err_ptr, cm->gdf_info.err_stride, err_shift,
scale_val, pxl_max, i_max - i_min, j_max - j_min);
}
}
}
}
blk_idx++;
}
}
}
#endif // CONFIG_GDF