[mtt] fix dual tree

This commit is contained in:
Joose Sainio 2022-11-29 12:14:58 +02:00 committed by Marko Viitanen
parent 8fbefc0de3
commit d5d9afb1e2
6 changed files with 88 additions and 24 deletions

View file

@ -229,7 +229,7 @@ int uvg_config_init(uvg_config *cfg)
cfg->max_btt_depth[0] = 1;
cfg->max_btt_depth[1] = 0;
cfg->max_btt_depth[2] = 0;
cfg->max_btt_depth[2] = 1;
cfg->max_tt_size[0] = 64;
cfg->max_bt_size[0] = 64;

View file

@ -407,11 +407,7 @@ int uvg_get_possible_splits(const encoder_state_t * const state,
if (width <= min_qt_size) splits[QT_SPLIT] = false;
if (tree_type == UVG_CHROMA_T && width <= 4) splits[QT_SPLIT] = false;
if (tree_type == UVG_CHROMA_T)
{
splits[QT_SPLIT] = splits[BT_VER_SPLIT] = splits[TT_HOR_SPLIT] = splits[BT_VER_SPLIT] = splits[TT_VER_SPLIT] = false;
return;
}
if (implicitSplit != NO_SPLIT)
{
splits[NO_SPLIT] = splits[TT_HOR_SPLIT] = splits[TT_VER_SPLIT] = false;
@ -499,3 +495,25 @@ int uvg_count_available_edge_cus(const cu_loc_t* const cu_loc, const lcu_t* cons
}
return MAX(amount / TR_MIN_WIDTH, cu_loc->width / TR_MIN_WIDTH);
}
int uvg_count_chroma_tree_available_edge_cus(int x, int y, int width, int height, const lcu_t* const lcu, bool left)
{
if (left && x == 0 || !left && y == 0) return 0;
const int local_x = x % LCU_WIDTH_C;
const int local_y = y % LCU_WIDTH_C;
if (left && local_x == 0) return (LCU_WIDTH_C - local_y) / 4;
if (!left && local_y == 0) return width / 2;
int amount = 0;
if(left) {
while (LCU_GET_CU_AT_PX(lcu, local_x - TR_MIN_WIDTH, local_y + amount)->type != CU_NOTSET && (local_y + amount) < LCU_WIDTH_C) {
amount += TR_MIN_WIDTH;
}
return MAX(amount / TR_MIN_WIDTH, height / TR_MIN_WIDTH);
}
while (LCU_GET_CU_AT_PX(lcu, local_x + amount, local_y - TR_MIN_WIDTH)->type != CU_NOTSET && local_x + amount < LCU_WIDTH_C) {
amount += TR_MIN_WIDTH;
}
return MAX(amount / TR_MIN_WIDTH, width / TR_MIN_WIDTH);
}

View file

@ -377,6 +377,7 @@ void uvg_cu_array_copy_from_lcu(cu_array_t* dst, int dst_x, int dst_y, const lcu
tree_type);
int uvg_count_available_edge_cus(const cu_loc_t* const cu_loc, const lcu_t* const lcu, bool left);
int uvg_count_chroma_tree_available_edge_cus(int x, int y, int width, int height, const lcu_t* const lcu, bool left);
/**
* \brief Return pointer to the top right reference CU.

View file

@ -1352,13 +1352,14 @@ void uvg_encode_coding_tree(
const encoder_control_t * const ctrl = state->encoder_control;
const videoframe_t * const frame = state->tile->frame;
const cu_array_t* used_array = tree_type != UVG_CHROMA_T ? frame->cu_array : frame->chroma_cu_array;
const cu_info_t *cur_cu = uvg_cu_array_at_const(used_array, cu_loc->x, cu_loc->y);
const int cu_width = tree_type != UVG_CHROMA_T ? cu_loc->width : cu_loc->chroma_width;
const int cu_height = tree_type != UVG_CHROMA_T ? cu_loc->height : cu_loc->chroma_height;
const int x = cu_loc->x;
const int y = cu_loc->y;
const int x = tree_type != UVG_CHROMA_T ? cu_loc->x : chroma_loc->x;
const int y = tree_type != UVG_CHROMA_T ? cu_loc->y : chroma_loc->y;
const cu_info_t* cur_cu = uvg_cu_array_at_const(used_array, x, y);
const int depth = split_tree.current_depth;
@ -1397,7 +1398,7 @@ void uvg_encode_coding_tree(
cabac,
left_cu,
above_cu,
cu_loc,
tree_type != UVG_CHROMA_T ? cu_loc : chroma_loc,
split_tree,
tree_type,
NULL);
@ -1406,12 +1407,24 @@ void uvg_encode_coding_tree(
split_tree_t new_split_tree = { cur_cu->split_tree, split_tree.current_depth + 1, split_tree.mtt_depth + (split_flag != QT_SPLIT), 0};
cu_loc_t new_cu_loc[4];
cu_loc_t chroma_tree_loc;
uint8_t separate_chroma = 0;
const int splits = uvg_get_split_locs(cu_loc, split_flag, new_cu_loc, &separate_chroma);
for (int split = 0; split <splits; ++split) {
new_split_tree.part_index = split;
if (tree_type == UVG_CHROMA_T) {
chroma_tree_loc = new_cu_loc[split];
chroma_tree_loc.x >>= 1;
chroma_tree_loc.y >>= 1;
chroma_tree_loc.local_x = chroma_tree_loc.x & LCU_WIDTH_C;
chroma_tree_loc.local_y = chroma_tree_loc.y & LCU_WIDTH_C;
chroma_tree_loc.width >>= 1;
chroma_tree_loc.height >>= 1;
assert(!separate_chroma);
}
uvg_encode_coding_tree(state, coeff, tree_type,
&new_cu_loc[split], separate_chroma ? chroma_loc : &new_cu_loc[split],
&new_cu_loc[split],
separate_chroma ? chroma_loc :(tree_type == UVG_CHROMA_T ? &chroma_tree_loc : &new_cu_loc[split]),
new_split_tree, !separate_chroma || split == splits - 1);
}
return;
@ -1420,6 +1433,9 @@ void uvg_encode_coding_tree(
DBG_YUVIEW_VALUE(state->frame->poc, DBG_YUVIEW_CU_TYPE, abs_x, abs_y, cu_width, cu_height, cur_cu->type-1);
if(tree_type==UVG_CHROMA_T)
fprintf(stderr, "%d %d %d %d\n", x * 2, y * 2, cu_width * 2, cu_height*2);
if (ctrl->cfg.lossless) {
cabac->cur_ctx = &cabac->ctx.cu_transquant_bypass;
CABAC_BIN(cabac, 1, "cu_transquant_bypass_flag");
@ -1643,7 +1659,7 @@ void uvg_encode_coding_tree(
((is_local_dual_tree &&
has_chroma) || tree_type == UVG_CHROMA_T) &&
tree_type != UVG_LUMA_T) {
int8_t luma_dir = uvg_get_co_located_luma_mode(chroma_loc, cu_loc, cur_cu, NULL, frame->cu_array, UVG_CHROMA_T);
int8_t luma_dir = uvg_get_co_located_luma_mode(tree_type != UVG_CHROMA_T ? chroma_loc : cu_loc, cu_loc, cur_cu, NULL, frame->cu_array, UVG_CHROMA_T);
encode_chroma_intra_cu(cabac, cur_cu, state->encoder_control->cfg.cclm, luma_dir,NULL);
// LFNST constraints must be reset here. Otherwise the left over values will interfere when calculating new constraints
cu_info_t* tmp = (cu_info_t*)cur_cu;

View file

@ -883,13 +883,20 @@ static void encoder_state_worker_encode_lcu_bitstream(void * opaque)
//Encode coding tree
cu_loc_t start;
uvg_cu_loc_ctor(&start, lcu->position.x * LCU_WIDTH, lcu->position.y * LCU_WIDTH, LCU_WIDTH, LCU_WIDTH);
split_tree_t split_tree = { 0, 0, 0, 0 };
split_tree_t split_tree = { 0, 0, 0 };
uvg_encode_coding_tree(state, lcu->coeff, tree_type, &start, &start, split_tree, true);
if(tree_type == UVG_LUMA_T && state->encoder_control->chroma_format != UVG_CSP_400) {
uvg_cu_loc_ctor(&start, lcu->position.x * LCU_WIDTH_C, lcu->position.y * LCU_WIDTH_C, LCU_WIDTH, LCU_WIDTH);
uvg_encode_coding_tree(state, lcu->coeff, UVG_CHROMA_T, &start, &start, split_tree, true);
uvg_cu_loc_ctor(&start, lcu->position.x * LCU_WIDTH, lcu->position.y * LCU_WIDTH, LCU_WIDTH, LCU_WIDTH);
cu_loc_t chroma_tree_loc = start;
chroma_tree_loc.x >>= 1;
chroma_tree_loc.y >>= 1;
chroma_tree_loc.local_x = chroma_tree_loc.x & LCU_WIDTH_C;
chroma_tree_loc.local_y = chroma_tree_loc.y & LCU_WIDTH_C;
chroma_tree_loc.width >>= 1;
chroma_tree_loc.height >>= 1;
uvg_encode_coding_tree(state, lcu->coeff, UVG_CHROMA_T, &start, &chroma_tree_loc, split_tree, true);
}
if (!state->cabac.only_count) {

View file

@ -1119,9 +1119,14 @@ void uvg_intra_build_reference_any(
}
}
else {
if (!is_dual_tree) {
const int num_cus = uvg_count_available_edge_cus(cu_loc, lcu, true);
px_available_left = is_dual_tree || !is_chroma ? num_cus * 4 : num_cus *2;
px_available_left -= px.x % 4;
px_available_left = is_dual_tree || !is_chroma ? num_cus * 4 : num_cus * 2;
}
else {
const int num_cus = uvg_count_chroma_tree_available_edge_cus(cu_loc->x >> 1, cu_loc->y >> 1, width, height, lcu, true);
px_available_left = num_cus * 4;
}
}
// Limit the number of available pixels based on block size and dimensions
@ -1242,9 +1247,15 @@ void uvg_intra_build_reference_any(
}
}
else {
if (!is_dual_tree) {
const int num_cus = uvg_count_available_edge_cus(cu_loc, lcu, false);
px_available_top = is_dual_tree || !is_chroma ? num_cus * 4 : num_cus * 2;
}
else {
const int num_cus = uvg_count_chroma_tree_available_edge_cus(cu_loc->x >> 1, cu_loc->y >> 1, width, height, lcu, false);
px_available_top = num_cus * 4;
}
}
// Limit the number of available pixels based on block size and dimensions
// of the picture.
@ -1428,8 +1439,13 @@ void uvg_intra_build_reference_inner(
}
else {
if(!is_dual_tree) {
const int num_cus = uvg_count_available_edge_cus(cu_loc, lcu, true);
px_available_left = is_dual_tree || !is_chroma ? num_cus * 4 : num_cus * 2;
} else {
const int num_cus = uvg_count_chroma_tree_available_edge_cus(cu_loc->x >> 1, cu_loc->y >> 1, width, height, lcu, true);
px_available_left = num_cus * 4;
}
}
// Limit the number of available pixels based on block size and dimensions
@ -1490,9 +1506,15 @@ void uvg_intra_build_reference_inner(
}
}
else {
if (!is_dual_tree) {
const int num_cus = uvg_count_available_edge_cus(cu_loc, lcu, false);
px_available_top = is_dual_tree || !is_chroma ? num_cus * 4 : num_cus * 2;
}
else {
const int num_cus = uvg_count_chroma_tree_available_edge_cus(cu_loc->x >> 1, cu_loc->y >> 1, width, height, lcu, false);
px_available_top = num_cus * 4;
}
}
// Limit the number of available pixels based on block size and dimensions
// of the picture.