mirror of
https://github.com/ultravideo/uvg266.git
synced 2024-11-23 18:14:06 +00:00
[mtt] search with depth 1 mtt kinda working
This commit is contained in:
parent
13aae7d03d
commit
657254d38a
5
src/cu.c
5
src/cu.c
|
@ -399,11 +399,11 @@ int uvg_get_possible_splits(const encoder_state_t * const state,
|
||||||
splits[NO_SPLIT] = splits[QT_SPLIT] = splits[BT_HOR_SPLIT] = splits[TT_HOR_SPLIT] = splits[BT_VER_SPLIT] = splits[TT_VER_SPLIT] = true;
|
splits[NO_SPLIT] = splits[QT_SPLIT] = splits[BT_HOR_SPLIT] = splits[TT_HOR_SPLIT] = splits[BT_VER_SPLIT] = splits[TT_VER_SPLIT] = true;
|
||||||
bool can_btt = split_tree.mtt_depth < max_btd;
|
bool can_btt = split_tree.mtt_depth < max_btd;
|
||||||
|
|
||||||
const enum split_type last_split = (split_tree.split_tree >> (split_tree.current_depth * 3)) & 7;
|
const enum split_type last_split = (split_tree.split_tree >> (split_tree.current_depth * 3 - 3)) & 7;
|
||||||
const enum split_type parl_split = last_split == BT_HOR_SPLIT ? BT_HOR_SPLIT : BT_VER_SPLIT;
|
const enum split_type parl_split = last_split == BT_HOR_SPLIT ? BT_HOR_SPLIT : BT_VER_SPLIT;
|
||||||
|
|
||||||
// don't allow QT-splitting below a BT split
|
// don't allow QT-splitting below a BT split
|
||||||
if (split_tree.current_depth != 0 && last_split != QT_SPLIT && (width > 64 || height > 64)) splits[QT_SPLIT] = false;
|
if (split_tree.current_depth != 0 && last_split != QT_SPLIT /* && !(width > 64 || height > 64)*/) splits[QT_SPLIT] = false;
|
||||||
if (width <= min_qt_size) splits[QT_SPLIT] = false;
|
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 && width <= 4) splits[QT_SPLIT] = false;
|
||||||
|
@ -488,6 +488,7 @@ int uvg_count_available_edge_cus(const cu_loc_t* const cu_loc, const lcu_t* cons
|
||||||
|
|
||||||
int amount = 0;
|
int amount = 0;
|
||||||
if(left) {
|
if(left) {
|
||||||
|
if (cu_loc->local_y == 0 && cu_loc->local_x == 32 && cu_loc->height == 32 && cu_loc->width == 32) return 8;
|
||||||
while (LCU_GET_CU_AT_PX(lcu, cu_loc->local_x - TR_MIN_WIDTH, cu_loc->local_y + amount)->type != CU_NOTSET && (cu_loc->local_y + amount) < LCU_WIDTH) {
|
while (LCU_GET_CU_AT_PX(lcu, cu_loc->local_x - TR_MIN_WIDTH, cu_loc->local_y + amount)->type != CU_NOTSET && (cu_loc->local_y + amount) < LCU_WIDTH) {
|
||||||
amount += TR_MIN_WIDTH;
|
amount += TR_MIN_WIDTH;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1643,7 +1643,7 @@ void uvg_encode_coding_tree(
|
||||||
((is_local_dual_tree &&
|
((is_local_dual_tree &&
|
||||||
has_chroma) || tree_type == UVG_CHROMA_T) &&
|
has_chroma) || tree_type == UVG_CHROMA_T) &&
|
||||||
tree_type != UVG_LUMA_T) {
|
tree_type != UVG_LUMA_T) {
|
||||||
int8_t luma_dir = uvg_get_co_located_luma_mode(chroma_loc->x, chroma_loc->y, chroma_loc->width, chroma_loc->height, NULL, frame->cu_array, UVG_CHROMA_T);
|
int8_t luma_dir = uvg_get_co_located_luma_mode(chroma_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);
|
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
|
// 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;
|
cu_info_t* tmp = (cu_info_t*)cur_cu;
|
||||||
|
@ -1793,9 +1793,9 @@ double uvg_mock_encode_coding_unit(
|
||||||
uvg_encode_intra_luma_coding_unit(state, cabac, cur_cu, cu_loc, lcu, &bits);
|
uvg_encode_intra_luma_coding_unit(state, cabac, cur_cu, cu_loc, lcu, &bits);
|
||||||
}
|
}
|
||||||
if((chroma_loc || tree_type == UVG_CHROMA_T) && state->encoder_control->chroma_format != UVG_CSP_400 && tree_type != UVG_LUMA_T) {
|
if((chroma_loc || tree_type == UVG_CHROMA_T) && state->encoder_control->chroma_format != UVG_CSP_400 && tree_type != UVG_LUMA_T) {
|
||||||
int8_t luma_dir = uvg_get_co_located_luma_mode(chroma_loc->x, chroma_loc->y, chroma_loc->width, chroma_loc->height,
|
int8_t luma_dir = uvg_get_co_located_luma_mode(chroma_loc,cu_loc , cur_cu, tree_type != UVG_CHROMA_T ? lcu : NULL,
|
||||||
tree_type != UVG_CHROMA_T ? lcu : NULL,
|
tree_type == UVG_CHROMA_T ? state->tile->frame->cu_array : NULL,
|
||||||
tree_type == UVG_CHROMA_T ? state->tile->frame->cu_array : NULL, is_separate_tree ? UVG_CHROMA_T : tree_type);
|
is_separate_tree ? UVG_CHROMA_T : tree_type);
|
||||||
encode_chroma_intra_cu(cabac, cur_cu, state->encoder_control->cfg.cclm, luma_dir, &bits);
|
encode_chroma_intra_cu(cabac, cur_cu, state->encoder_control->cfg.cclm, luma_dir, &bits);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
18
src/intra.c
18
src/intra.c
|
@ -1603,22 +1603,26 @@ void uvg_intra_predict(
|
||||||
|
|
||||||
// This function works on luma coordinates
|
// This function works on luma coordinates
|
||||||
int8_t uvg_get_co_located_luma_mode(
|
int8_t uvg_get_co_located_luma_mode(
|
||||||
int x,
|
const cu_loc_t* const chroma_loc,
|
||||||
int y,
|
const cu_loc_t* const cu_loc,
|
||||||
int width,
|
const cu_info_t* luma_cu,
|
||||||
int height,
|
|
||||||
const lcu_t* const lcu,
|
const lcu_t* const lcu,
|
||||||
const cu_array_t* const cu_array,
|
const cu_array_t* const cu_array,
|
||||||
enum uvg_tree_type tree_type)
|
enum uvg_tree_type tree_type)
|
||||||
{
|
{
|
||||||
|
int x = chroma_loc->x;
|
||||||
|
int y = chroma_loc->y;
|
||||||
assert((cu_array || lcu) && !(cu_array && lcu));
|
assert((cu_array || lcu) && !(cu_array && lcu));
|
||||||
assert(tree_type != UVG_LUMA_T && "Luma only CU shouldn't need colocated luma CU");
|
assert(tree_type != UVG_LUMA_T && "Luma only CU shouldn't need colocated luma CU");
|
||||||
if(tree_type == UVG_CHROMA_T) {
|
if(tree_type == UVG_CHROMA_T) {
|
||||||
x += width >> 1;
|
x += chroma_loc->width >> 1;
|
||||||
y += height >> 1;
|
y += chroma_loc->height >> 1;
|
||||||
}
|
}
|
||||||
const cu_info_t* cu;
|
const cu_info_t* cu;
|
||||||
if(cu_array) {
|
if (lcu && cu_loc->x <= x && x < cu_loc->x + cu_loc->width && cu_loc->y <= y && y < cu_loc->y + cu_loc->height) {
|
||||||
|
cu = luma_cu;
|
||||||
|
}
|
||||||
|
else if(cu_array) {
|
||||||
cu = uvg_cu_array_at_const(cu_array, x, y);
|
cu = uvg_cu_array_at_const(cu_array, x, y);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -152,10 +152,9 @@ void uvg_intra_recon_cu(
|
||||||
bool recon_chroma);
|
bool recon_chroma);
|
||||||
|
|
||||||
int8_t uvg_get_co_located_luma_mode(
|
int8_t uvg_get_co_located_luma_mode(
|
||||||
int x,
|
const cu_loc_t* const chroma_loc,
|
||||||
int y,
|
const cu_loc_t* const cu_loc,
|
||||||
int width,
|
const cu_info_t* luma_cu,
|
||||||
int height,
|
|
||||||
const lcu_t* const lcu,
|
const lcu_t* const lcu,
|
||||||
const cu_array_t* const cu_array,
|
const cu_array_t* const cu_array,
|
||||||
enum uvg_tree_type tree_type);
|
enum uvg_tree_type tree_type);
|
||||||
|
|
60
src/search.c
60
src/search.c
|
@ -1107,9 +1107,10 @@ static double search_cu(
|
||||||
|
|
||||||
intra_search.pred_cu.joint_cb_cr = 0;
|
intra_search.pred_cu.joint_cb_cr = 0;
|
||||||
if(tree_type == UVG_CHROMA_T || is_separate_tree) {
|
if(tree_type == UVG_CHROMA_T || is_separate_tree) {
|
||||||
intra_mode = uvg_get_co_located_luma_mode(chroma_loc->x, chroma_loc->y, chroma_loc->width, chroma_loc->height,
|
intra_mode = uvg_get_co_located_luma_mode(
|
||||||
is_separate_tree ? lcu : NULL,
|
chroma_loc, cu_loc, &intra_search.pred_cu, is_separate_tree ? lcu : NULL,
|
||||||
tree_type == UVG_CHROMA_T ? state->tile->frame->cu_array : NULL, UVG_CHROMA_T);
|
tree_type == UVG_CHROMA_T ? state->tile->frame->cu_array : NULL,
|
||||||
|
UVG_CHROMA_T);
|
||||||
intra_search.pred_cu.type = CU_INTRA;
|
intra_search.pred_cu.type = CU_INTRA;
|
||||||
} else if (intra_search.pred_cu.intra.mip_flag) {
|
} else if (intra_search.pred_cu.intra.mip_flag) {
|
||||||
intra_mode = 0;
|
intra_mode = 0;
|
||||||
|
@ -1346,9 +1347,20 @@ static double search_cu(
|
||||||
fwrite(&state->search_cabac.ctx, 1, sizeof(state->search_cabac.ctx), state->encoder_control->cabac_debug_file);
|
fwrite(&state->search_cabac.ctx, 1, sizeof(state->search_cabac.ctx), state->encoder_control->cabac_debug_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool can_split[6];
|
||||||
|
uvg_get_possible_splits(state, cu_loc, split_tree, tree_type, can_split);
|
||||||
|
can_split_cu &= can_split[1] || can_split[2] || can_split[3] || can_split[4] || can_split[5];
|
||||||
|
|
||||||
// Recursively split all the way to max search depth.
|
// Recursively split all the way to max search depth.
|
||||||
if (can_split_cu) {
|
if (can_split_cu) {
|
||||||
const int split_type = depth == 2 ? TT_VER_SPLIT : QT_SPLIT;
|
lcu_t * split_lcu = MALLOC(lcu_t, 5);
|
||||||
|
enum split_type best_split = 0;
|
||||||
|
double best_split_cost = MAX_DOUBLE;
|
||||||
|
cabac_data_t post_seach_cabac;
|
||||||
|
cabac_data_t best_split_cabac;
|
||||||
|
memcpy(&post_seach_cabac, &state->search_cabac, sizeof(post_seach_cabac));
|
||||||
|
for (int split_type = QT_SPLIT; split_type <= TT_VER_SPLIT; ++split_type) {
|
||||||
|
if (!can_split[split_type] || split_type != QT_SPLIT) continue;
|
||||||
split_tree_t new_split = {
|
split_tree_t new_split = {
|
||||||
split_tree.split_tree | split_type << (split_tree.current_depth * 3),
|
split_tree.split_tree | split_type << (split_tree.current_depth * 3),
|
||||||
split_tree.current_depth + 1,
|
split_tree.current_depth + 1,
|
||||||
|
@ -1358,13 +1370,10 @@ static double search_cu(
|
||||||
|
|
||||||
double split_cost = 0.0;
|
double split_cost = 0.0;
|
||||||
int cbf = cbf_is_set_any(cur_cu->cbf);
|
int cbf = cbf_is_set_any(cur_cu->cbf);
|
||||||
cabac_data_t post_seach_cabac;
|
|
||||||
memcpy(&post_seach_cabac, &state->search_cabac, sizeof(post_seach_cabac));
|
|
||||||
memcpy(&state->search_cabac, &pre_search_cabac, sizeof(post_seach_cabac));
|
memcpy(&state->search_cabac, &pre_search_cabac, sizeof(post_seach_cabac));
|
||||||
|
|
||||||
|
|
||||||
double split_bits = 0;
|
double split_bits = 0;
|
||||||
lcu_t split_lcu;
|
|
||||||
|
|
||||||
if (cur_cu->log2_height + cur_cu->log2_width > 4) {
|
if (cur_cu->log2_height + cur_cu->log2_width > 4) {
|
||||||
|
|
||||||
|
@ -1387,13 +1396,15 @@ static double search_cu(
|
||||||
above_cu = uvg_cu_array_at_const(state->tile->frame->chroma_cu_array, x >> 1, (y >> 1) - 1);
|
above_cu = uvg_cu_array_at_const(state->tile->frame->chroma_cu_array, x >> 1, (y >> 1) - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
split_tree_t count_tree = split_tree;
|
||||||
|
count_tree.split_tree = split_tree.split_tree | split_type << (split_tree.current_depth * 3);
|
||||||
uvg_write_split_flag(
|
uvg_write_split_flag(
|
||||||
state,
|
state,
|
||||||
&state->search_cabac,
|
&state->search_cabac,
|
||||||
left_cu,
|
left_cu,
|
||||||
above_cu,
|
above_cu,
|
||||||
tree_type != UVG_CHROMA_T ? cu_loc : &separate_tree_chroma_loc,
|
tree_type != UVG_CHROMA_T ? cu_loc : &separate_tree_chroma_loc,
|
||||||
split_tree,
|
count_tree,
|
||||||
tree_type,
|
tree_type,
|
||||||
&split_bits);
|
&split_bits);
|
||||||
}
|
}
|
||||||
|
@ -1410,16 +1421,16 @@ static double search_cu(
|
||||||
cu_loc_t new_cu_loc[4];
|
cu_loc_t new_cu_loc[4];
|
||||||
uint8_t separate_chroma = 0;
|
uint8_t separate_chroma = 0;
|
||||||
const int splits = uvg_get_split_locs(cu_loc, split_type, new_cu_loc, &separate_chroma);
|
const int splits = uvg_get_split_locs(cu_loc, split_type, new_cu_loc, &separate_chroma);
|
||||||
initialize_partial_work_tree(lcu, &split_lcu, cu_loc, tree_type);
|
initialize_partial_work_tree(lcu, &split_lcu[split_type - 1], cu_loc, tree_type);
|
||||||
for (int split = 0; split < splits; ++split) {
|
for (int split = 0; split < splits; ++split) {
|
||||||
new_split.part_index = split;
|
new_split.part_index = split;
|
||||||
split_cost += search_cu(state,
|
split_cost += search_cu(state,
|
||||||
&new_cu_loc[split], separate_chroma ? chroma_loc : &new_cu_loc[split],
|
&new_cu_loc[split], separate_chroma ? chroma_loc : &new_cu_loc[split],
|
||||||
&split_lcu,
|
&split_lcu[split_type -1],
|
||||||
tree_type, new_split,
|
tree_type, new_split,
|
||||||
!separate_chroma || split == splits - 1);
|
!separate_chroma || split == splits - 1);
|
||||||
// If there is no separate chroma the block will always have chroma, otherwise it is the last block of the split that has the chroma
|
// If there is no separate chroma the block will always have chroma, otherwise it is the last block of the split that has the chroma
|
||||||
if (split_cost > cost) {
|
if (split_cost > cost || split_cost > best_split_cost) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1427,6 +1438,12 @@ static double search_cu(
|
||||||
} else {
|
} else {
|
||||||
split_cost = INT_MAX;
|
split_cost = INT_MAX;
|
||||||
}
|
}
|
||||||
|
if (split_cost < best_split_cost) {
|
||||||
|
best_split_cost = split_cost;
|
||||||
|
best_split = split_type;
|
||||||
|
memcpy(&best_split_cabac, &state->search_cabac, sizeof(cabac_data_t));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If no search is not performed for this depth, try just the best mode
|
// If no search is not performed for this depth, try just the best mode
|
||||||
// of the top left CU from the next depth. This should ensure that 64x64
|
// of the top left CU from the next depth. This should ensure that 64x64
|
||||||
|
@ -1440,7 +1457,7 @@ static double search_cu(
|
||||||
&& tree_type == UVG_BOTH_T)
|
&& tree_type == UVG_BOTH_T)
|
||||||
{
|
{
|
||||||
|
|
||||||
cu_info_t *cu_d1 = LCU_GET_CU_AT_PX(&split_lcu, x_local, y_local);
|
cu_info_t *cu_d1 = LCU_GET_CU_AT_PX(&split_lcu[best_split - 1], x_local, y_local);
|
||||||
|
|
||||||
// If the best CU in depth+1 is intra and the biggest it can be, try it.
|
// If the best CU in depth+1 is intra and the biggest it can be, try it.
|
||||||
if (cu_d1->type == CU_INTRA && (cu_d1->log2_height + 1 == cur_cu->log2_height || cu_d1->log2_width + 1 == cur_cu->log2_width)) {
|
if (cu_d1->type == CU_INTRA && (cu_d1->log2_height + 1 == cur_cu->log2_height || cu_d1->log2_width + 1 == cur_cu->log2_width)) {
|
||||||
|
@ -1488,10 +1505,14 @@ static double search_cu(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (split_cost < cost) {
|
if (best_split_cost < cost) {
|
||||||
// Copy split modes to this depth.
|
// Copy split modes to this depth.
|
||||||
cost = split_cost;
|
cost = best_split_cost;
|
||||||
work_tree_copy_up(&split_lcu, lcu, state->encoder_control->cfg.jccr, tree_type, cu_loc, is_separate_tree && !has_chroma ? NULL : chroma_loc);
|
memcpy(&state->search_cabac, &best_split_cabac, sizeof(best_split_cabac));
|
||||||
|
work_tree_copy_up(&split_lcu[best_split -1], lcu, state->encoder_control->cfg.jccr, tree_type, cu_loc, is_separate_tree && !has_chroma ? NULL : chroma_loc);
|
||||||
|
downsample_cclm_rec(
|
||||||
|
state, x, y, cu_width / 2, cu_height / 2, lcu->rec.y, lcu->left_ref.y[64]
|
||||||
|
);
|
||||||
#if UVG_DEBUG
|
#if UVG_DEBUG
|
||||||
//debug_split = 1;
|
//debug_split = 1;
|
||||||
#endif
|
#endif
|
||||||
|
@ -1522,6 +1543,7 @@ static double search_cu(
|
||||||
state, x, y, cu_width / 2, cu_height / 2, lcu->rec.y, lcu->left_ref.y[64]
|
state, x, y, cu_width / 2, cu_height / 2, lcu->rec.y, lcu->left_ref.y[64]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
FREE_POINTER(split_lcu);
|
||||||
} else if (cur_cu->log2_height + cur_cu->log2_width > 4) {
|
} else if (cur_cu->log2_height + cur_cu->log2_width > 4) {
|
||||||
// Need to copy modes down since the lower level of the work tree is used
|
// Need to copy modes down since the lower level of the work tree is used
|
||||||
// when searching SMP and AMP blocks.
|
// when searching SMP and AMP blocks.
|
||||||
|
@ -1745,11 +1767,11 @@ void uvg_search_lcu(encoder_state_t * const state, const int x, const int y, con
|
||||||
double cost = search_cu(
|
double cost = search_cu(
|
||||||
state,
|
state,
|
||||||
&start,
|
&start,
|
||||||
NULL,
|
&start,
|
||||||
&work_tree,
|
&work_tree,
|
||||||
tree_type,
|
tree_type,
|
||||||
split_tree,
|
split_tree,
|
||||||
false);
|
true);
|
||||||
|
|
||||||
// Save squared cost for rate control.
|
// Save squared cost for rate control.
|
||||||
if(state->encoder_control->cfg.rc_algorithm == UVG_LAMBDA) {
|
if(state->encoder_control->cfg.rc_algorithm == UVG_LAMBDA) {
|
||||||
|
@ -1766,10 +1788,10 @@ void uvg_search_lcu(encoder_state_t * const state, const int x, const int y, con
|
||||||
if(state->frame->slicetype == UVG_SLICE_I && state->encoder_control->cfg.dual_tree) {
|
if(state->frame->slicetype == UVG_SLICE_I && state->encoder_control->cfg.dual_tree) {
|
||||||
cost = search_cu(
|
cost = search_cu(
|
||||||
state, &start,
|
state, &start,
|
||||||
NULL,
|
&start,
|
||||||
&work_tree, UVG_CHROMA_T,
|
&work_tree, UVG_CHROMA_T,
|
||||||
split_tree,
|
split_tree,
|
||||||
false);
|
true);
|
||||||
|
|
||||||
if (state->encoder_control->cfg.rc_algorithm == UVG_LAMBDA) {
|
if (state->encoder_control->cfg.rc_algorithm == UVG_LAMBDA) {
|
||||||
uvg_get_lcu_stats(state, x / LCU_WIDTH, y / LCU_WIDTH)->weight += cost * cost;
|
uvg_get_lcu_stats(state, x / LCU_WIDTH, y / LCU_WIDTH)->weight += cost * cost;
|
||||||
|
|
Loading…
Reference in a new issue