[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, int32_t picture_height,
lcu_t *lcu, lcu_t *lcu,
merge_candidates_t *cand_out, merge_candidates_t *cand_out,
uint8_t parallel_merge_level) uint8_t parallel_merge_level,
bool wpp
)
{ {
/* /*
Predictor block locations Predictor block locations
@ -916,47 +918,47 @@ static void get_spatial_merge_candidates(int32_t x,
int32_t y_local = SUB_SCU(y); int32_t y_local = SUB_SCU(y);
// A0 and A1 availability testing // A0 and A1 availability testing
if (x != 0) { 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 // 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. // the current one and the flag is not set when searching an SMP block.
if (a0->type == CU_INTER) { if (a1->type == CU_INTER) {
inter_clear_cu_unused(a0); inter_clear_cu_unused(a1);
cand_out->a[0] = a0; cand_out->a[1] = a1;
cand_out->mer_a0[0] = parallel_merge_level; cand_out->mer_a1[0] = parallel_merge_level;
} }
if (y_local + height < LCU_WIDTH && y + height < picture_height) { 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); cu_info_t *a0 = 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)) { if (a0->type == CU_INTER && is_a0_cand_coded(x, y, width, height)) {
inter_clear_cu_unused(a1); inter_clear_cu_unused(a0);
cand_out->a[1] = a1; cand_out->a[0] = a0;
} }
} }
} }
// B0, B1 and B2 availability testing // B0, B1 and B2 availability testing
if (y != 0) { if (y != 0) {
cu_info_t *b1 = NULL; cu_info_t *b0 = NULL;
if (x + width < picture_width) { // ToDo: do not use B1 when WPP enabled if (x + width < picture_width) {
if (x_local + width < LCU_WIDTH) { if (x_local + width < LCU_WIDTH) {
b1 = LCU_GET_CU_AT_PX(lcu, x_local + width, y_local - 1); b0 = LCU_GET_CU_AT_PX(lcu, x_local + width, y_local - 1);
} else if (y_local == 0) { } else if (!wpp && y_local == 0) {
// Special case, top-right CU // 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)) { if (b0 && b0->type == CU_INTER && is_b0_cand_coded(x, y, width, height)) {
inter_clear_cu_unused(b1); inter_clear_cu_unused(b0);
cand_out->b[1] = b1; 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 // 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 // before the current one and the flag is not set when searching an SMP
// block. // block.
if (b0->type == CU_INTER) { if (b1->type == CU_INTER) {
inter_clear_cu_unused(b0); inter_clear_cu_unused(b1);
cand_out->b[0] = b0; cand_out->b[1] = b1;
} }
if (x != 0) { if (x != 0) {
@ -994,7 +996,8 @@ static void get_spatial_merge_candidates_cua(const cu_array_t *cua,
int32_t height, int32_t height,
int32_t picture_width, int32_t picture_width,
int32_t picture_height, int32_t picture_height,
merge_candidates_t *cand_out) merge_candidates_t *cand_out,
bool wpp)
{ {
/* /*
Predictor block locations 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); int32_t y_local = SUB_SCU(y);
// A0 and A1 availability testing // A0 and A1 availability testing
if (x != 0) { 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. // The block above is always coded before the current one.
if (a0->type == CU_INTER) { if (a1->type == CU_INTER) {
cand_out->a[0] = a0; cand_out->a[1] = a1;
} }
if (y_local + height < LCU_WIDTH && y + height < picture_height) { 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); const cu_info_t *a0 = kvz_cu_array_at_const(cua, x - 1, y + height);
if (a1->type == CU_INTER && is_a0_cand_coded(x, y, width, height)) { if (a0->type == CU_INTER && is_a0_cand_coded(x, y, width, height)) {
cand_out->a[1] = a1; cand_out->a[0] = a0;
} }
} }
} }
// B0, B1 and B2 availability testing // B0, B1 and B2 availability testing
if (y != 0) { if (y != 0) {
if (x + width < picture_width && (x_local + width < LCU_WIDTH || y_local == 0)) { if (x + width < picture_width && (x_local + width < LCU_WIDTH || (!wpp && y_local == 0))) {
const cu_info_t *b1 = kvz_cu_array_at_const(cua, x + width, y - 1); const cu_info_t *b0 = kvz_cu_array_at_const(cua, x + width, y - 1);
if (b1->type == CU_INTER && is_b0_cand_coded(x, y, width, height)) { if (b0->type == CU_INTER && is_b0_cand_coded(x, y, width, height)) {
cand_out->b[1] = b1; 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. // The block to the left is always coded before the current one.
if (b0->type == CU_INTER) { if (b1->type == CU_INTER) {
cand_out->b[0] = b0; cand_out->b[1] = b1;
} }
if (x != 0) { 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; uint8_t b_candidates = 0;
// Left predictors without scaling // 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++; 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++; candidates++;
} }
// Top predictors without scaling // 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++; 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++; b_candidates++;
} }
else if (add_mvp_candidate(state, cur_cu, b[2], reflist, false, mv_cand[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->width,
state->tile->frame->height, state->tile->frame->height,
lcu, 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_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); 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, get_spatial_merge_candidates_cua(cua,
x, y, width, height, x, y, width, height,
state->tile->frame->width, state->tile->frame->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_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); 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->width,
state->tile->frame->height, state->tile->frame->height,
lcu, 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 **a = merge_cand.a;
const cu_info_t **b = merge_cand.b; 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 1920, 1080, // picture size
&lcu, &lcu,
&cand, &cand,
2); 2, 0);
ASSERT_EQ(cand.b[1], &lcu.cu[289]); ASSERT_EQ(cand.b[1], &lcu.cu[289]);
ASSERT_EQ(cand.b[0], &lcu.cu[ 16]); ASSERT_EQ(cand.b[0], &lcu.cu[ 16]);