[inter] MVP candidate order fix and limit b0 with wpp

This commit is contained in:
Marko Viitanen 2021-10-25 22:57:58 +03:00
parent 5b3d87f6c1
commit b0e6ab9f96
2 changed files with 47 additions and 44 deletions

View file

@ -900,7 +900,9 @@ static void get_spatial_merge_candidates(int32_t x,
int32_t picture_height,
lcu_t *lcu,
merge_candidates_t *cand_out,
uint8_t parallel_merge_level)
uint8_t parallel_merge_level,
bool wpp
)
{
/*
Predictor block locations
@ -916,47 +918,47 @@ static void get_spatial_merge_candidates(int32_t x,
int32_t y_local = SUB_SCU(y);
// A0 and A1 availability testing
if (x != 0) {
cu_info_t *a0 = LCU_GET_CU_AT_PX(lcu, x_local - 1, y_local + height - 1);
cu_info_t *a1 = LCU_GET_CU_AT_PX(lcu, x_local - 1, y_local + height - 1);
// Do not check a1->coded because the block above is always coded before
// the current one and the flag is not set when searching an SMP block.
if (a0->type == CU_INTER) {
inter_clear_cu_unused(a0);
cand_out->a[0] = a0;
cand_out->mer_a0[0] = parallel_merge_level;
if (a1->type == CU_INTER) {
inter_clear_cu_unused(a1);
cand_out->a[1] = a1;
cand_out->mer_a1[0] = parallel_merge_level;
}
if (y_local + height < LCU_WIDTH && y + height < picture_height) {
cu_info_t *a1 = LCU_GET_CU_AT_PX(lcu, x_local - 1, y_local + height);
if (a1->type == CU_INTER && is_a0_cand_coded(x, y, width, height)) {
inter_clear_cu_unused(a1);
cand_out->a[1] = a1;
cu_info_t *a0 = LCU_GET_CU_AT_PX(lcu, x_local - 1, y_local + height);
if (a0->type == CU_INTER && is_a0_cand_coded(x, y, width, height)) {
inter_clear_cu_unused(a0);
cand_out->a[0] = a0;
}
}
}
// B0, B1 and B2 availability testing
if (y != 0) {
cu_info_t *b1 = NULL;
if (x + width < picture_width) { // ToDo: do not use B1 when WPP enabled
cu_info_t *b0 = NULL;
if (x + width < picture_width) {
if (x_local + width < LCU_WIDTH) {
b1 = LCU_GET_CU_AT_PX(lcu, x_local + width, y_local - 1);
} else if (y_local == 0) {
b0 = LCU_GET_CU_AT_PX(lcu, x_local + width, y_local - 1);
} else if (!wpp && y_local == 0) {
// Special case, top-right CU
b1 = LCU_GET_TOP_RIGHT_CU(lcu);
b0 = LCU_GET_TOP_RIGHT_CU(lcu);
}
}
if (b1 && b1->type == CU_INTER && is_b0_cand_coded(x, y, width, height)) {
inter_clear_cu_unused(b1);
cand_out->b[1] = b1;
if (b0 && b0->type == CU_INTER && is_b0_cand_coded(x, y, width, height)) {
inter_clear_cu_unused(b0);
cand_out->b[0] = b0;
}
cu_info_t *b0 = LCU_GET_CU_AT_PX(lcu, x_local + width - 1, y_local - 1);
cu_info_t *b1 = LCU_GET_CU_AT_PX(lcu, x_local + width - 1, y_local - 1);
// Do not check b0->coded because the block to the left is always coded
// before the current one and the flag is not set when searching an SMP
// block.
if (b0->type == CU_INTER) {
inter_clear_cu_unused(b0);
cand_out->b[0] = b0;
if (b1->type == CU_INTER) {
inter_clear_cu_unused(b1);
cand_out->b[1] = b1;
}
if (x != 0) {
@ -994,7 +996,8 @@ static void get_spatial_merge_candidates_cua(const cu_array_t *cua,
int32_t height,
int32_t picture_width,
int32_t picture_height,
merge_candidates_t *cand_out)
merge_candidates_t *cand_out,
bool wpp)
{
/*
Predictor block locations
@ -1010,33 +1013,33 @@ static void get_spatial_merge_candidates_cua(const cu_array_t *cua,
int32_t y_local = SUB_SCU(y);
// A0 and A1 availability testing
if (x != 0) {
const cu_info_t *a0 = kvz_cu_array_at_const(cua, x - 1, y + height - 1);
const cu_info_t *a1 = kvz_cu_array_at_const(cua, x - 1, y + height - 1);
// The block above is always coded before the current one.
if (a0->type == CU_INTER) {
cand_out->a[0] = a0;
if (a1->type == CU_INTER) {
cand_out->a[1] = a1;
}
if (y_local + height < LCU_WIDTH && y + height < picture_height) {
const cu_info_t *a1 = kvz_cu_array_at_const(cua, x - 1, y + height);
if (a1->type == CU_INTER && is_a0_cand_coded(x, y, width, height)) {
cand_out->a[1] = a1;
const cu_info_t *a0 = kvz_cu_array_at_const(cua, x - 1, y + height);
if (a0->type == CU_INTER && is_a0_cand_coded(x, y, width, height)) {
cand_out->a[0] = a0;
}
}
}
// B0, B1 and B2 availability testing
if (y != 0) {
if (x + width < picture_width && (x_local + width < LCU_WIDTH || y_local == 0)) {
const cu_info_t *b1 = kvz_cu_array_at_const(cua, x + width, y - 1);
if (b1->type == CU_INTER && is_b0_cand_coded(x, y, width, height)) {
cand_out->b[1] = b1;
if (x + width < picture_width && (x_local + width < LCU_WIDTH || (!wpp && y_local == 0))) {
const cu_info_t *b0 = kvz_cu_array_at_const(cua, x + width, y - 1);
if (b0->type == CU_INTER && is_b0_cand_coded(x, y, width, height)) {
cand_out->b[0] = b0;
}
}
const cu_info_t *b0 = kvz_cu_array_at_const(cua, x + width - 1, y - 1);
const cu_info_t* b1 = kvz_cu_array_at_const(cua, x + width - 1, y - 1);
// The block to the left is always coded before the current one.
if (b0->type == CU_INTER) {
cand_out->b[0] = b0;
if (b1->type == CU_INTER) {
cand_out->b[1] = b1;
}
if (x != 0) {
@ -1216,17 +1219,17 @@ static void get_mv_cand_from_candidates(const encoder_state_t * const state,
uint8_t b_candidates = 0;
// Left predictors without scaling
if (add_mvp_candidate(state, cur_cu, a[1], reflist, false, mv_cand[candidates])) {
if (add_mvp_candidate(state, cur_cu, a[0], reflist, false, mv_cand[candidates])) {
candidates++;
} else if (add_mvp_candidate(state, cur_cu, a[0], reflist, false, mv_cand[candidates])) {
} else if (add_mvp_candidate(state, cur_cu, a[1], reflist, false, mv_cand[candidates])) {
candidates++;
}
// Top predictors without scaling
if (add_mvp_candidate(state, cur_cu, b[1], reflist, false, mv_cand[candidates])) {
if (add_mvp_candidate(state, cur_cu, b[0], reflist, false, mv_cand[candidates])) {
b_candidates++;
} else if (add_mvp_candidate(state, cur_cu, b[0], reflist, false, mv_cand[candidates])) {
} else if (add_mvp_candidate(state, cur_cu, b[1], reflist, false, mv_cand[candidates])) {
b_candidates++;
}
else if (add_mvp_candidate(state, cur_cu, b[2], reflist, false, mv_cand[candidates])) {
@ -1309,7 +1312,7 @@ void kvz_inter_get_mv_cand(const encoder_state_t * const state,
state->tile->frame->width,
state->tile->frame->height,
lcu,
&merge_cand, parallel_merge_level);
&merge_cand, parallel_merge_level,state->encoder_control->cfg.wpp);
get_temporal_merge_candidates(state, x, y, width, height, 1, 0, &merge_cand);
get_mv_cand_from_candidates(state, x, y, width, height, &merge_cand, cur_cu, reflist, mv_cand);
}
@ -1341,7 +1344,7 @@ void kvz_inter_get_mv_cand_cua(const encoder_state_t * const state,
get_spatial_merge_candidates_cua(cua,
x, y, width, height,
state->tile->frame->width, state->tile->frame->height,
&merge_cand);
&merge_cand, state->encoder_control->cfg.wpp);
get_temporal_merge_candidates(state, x, y, width, height, 1, 0, &merge_cand);
get_mv_cand_from_candidates(state, x, y, width, height, &merge_cand, cur_cu, reflist, mv_cand);
}
@ -1487,7 +1490,7 @@ uint8_t kvz_inter_get_merge_cand(const encoder_state_t * const state,
state->tile->frame->width,
state->tile->frame->height,
lcu,
&merge_cand, parallel_merge_level);
&merge_cand, parallel_merge_level, state->encoder_control->cfg.wpp);
const cu_info_t **a = merge_cand.a;
const cu_info_t **b = merge_cand.b;

View file

@ -38,7 +38,7 @@ TEST test_get_spatial_merge_cand(void)
1920, 1080, // picture size
&lcu,
&cand,
2);
2, 0);
ASSERT_EQ(cand.b[1], &lcu.cu[289]);
ASSERT_EQ(cand.b[0], &lcu.cu[ 16]);