Fixed merge candidate selection

This commit is contained in:
Marko Viitanen 2015-04-23 12:18:33 +03:00
parent 3c694a8f6e
commit 0e958ebe84
2 changed files with 44 additions and 11 deletions

View file

@ -373,7 +373,18 @@ void inter_recon_lcu_bipred(const encoder_state_t * const state, const image_t *
FREE_POINTER(temp_lcu_v); FREE_POINTER(temp_lcu_v);
} }
static void inter_clear_cu_unused(cu_info_t* cu) {
if(!(cu->inter.mv_dir & 1)) {
cu->inter.mv[0][0] = 0;
cu->inter.mv[0][1] = 0;
cu->inter.mv_ref[0] = 255;
}
if(!(cu->inter.mv_dir & 2)) {
cu->inter.mv[1][0] = 0;
cu->inter.mv[1][1] = 0;
cu->inter.mv_ref[1] = 255;
}
}
/** /**
* \brief Get merge candidates for current block * \brief Get merge candidates for current block
@ -408,11 +419,13 @@ void inter_get_spatial_merge_candidates(int32_t x, int32_t y, int8_t depth, cu_i
if (x != 0) { if (x != 0) {
*a1 = &cu[x_cu - 1 + (y_cu + cur_block_in_scu - 1) * LCU_T_CU_WIDTH]; *a1 = &cu[x_cu - 1 + (y_cu + cur_block_in_scu - 1) * LCU_T_CU_WIDTH];
if (!(*a1)->coded) *a1 = NULL; if (!(*a1)->coded) *a1 = NULL;
if(*a1) inter_clear_cu_unused(*a1);
if (y_cu + cur_block_in_scu < LCU_WIDTH>>3) { if (y_cu + cur_block_in_scu < LCU_WIDTH>>3) {
*a0 = &cu[x_cu - 1 + (y_cu + cur_block_in_scu) * LCU_T_CU_WIDTH]; *a0 = &cu[x_cu - 1 + (y_cu + cur_block_in_scu) * LCU_T_CU_WIDTH];
if (!(*a0)->coded) *a0 = NULL; if (!(*a0)->coded) *a0 = NULL;
} }
if(*a0) inter_clear_cu_unused(*a0);
} }
// B0, B1 and B2 availability testing // B0, B1 and B2 availability testing
@ -425,14 +438,17 @@ void inter_get_spatial_merge_candidates(int32_t x, int32_t y, int8_t depth, cu_i
*b0 = &lcu->cu[LCU_T_CU_WIDTH*LCU_T_CU_WIDTH]; *b0 = &lcu->cu[LCU_T_CU_WIDTH*LCU_T_CU_WIDTH];
if (!(*b0)->coded) *b0 = NULL; if (!(*b0)->coded) *b0 = NULL;
} }
if(*b0) inter_clear_cu_unused(*b0);
*b1 = &cu[x_cu + cur_block_in_scu - 1 + (y_cu - 1) * LCU_T_CU_WIDTH]; *b1 = &cu[x_cu + cur_block_in_scu - 1 + (y_cu - 1) * LCU_T_CU_WIDTH];
if (!(*b1)->coded) *b1 = NULL; if (!(*b1)->coded) *b1 = NULL;
if(*b1) inter_clear_cu_unused(*b1);
if (x != 0) { if (x != 0) {
*b2 = &cu[x_cu - 1 + (y_cu - 1) * LCU_T_CU_WIDTH]; *b2 = &cu[x_cu - 1 + (y_cu - 1) * LCU_T_CU_WIDTH];
if(!(*b2)->coded) *b2 = NULL; if(!(*b2)->coded) *b2 = NULL;
} }
if(*b2) inter_clear_cu_unused(*b2);
} }
} }
@ -637,6 +653,7 @@ uint8_t inter_get_merge_cand(const encoder_state_t * const state, int32_t x, int
#define CHECK_DUPLICATE(CU1,CU2) {duplicate = 0; if ((CU2) && (CU2)->type == CU_INTER && \ #define CHECK_DUPLICATE(CU1,CU2) {duplicate = 0; if ((CU2) && (CU2)->type == CU_INTER && \
(CU1)->inter.mv_dir == (CU2)->inter.mv_dir && \
(!(((CU1)->inter.mv_dir & 1) && ((CU2)->inter.mv_dir & 1)) || \ (!(((CU1)->inter.mv_dir & 1) && ((CU2)->inter.mv_dir & 1)) || \
((CU1)->inter.mv[0][0] == (CU2)->inter.mv[0][0] && \ ((CU1)->inter.mv[0][0] == (CU2)->inter.mv[0][0] && \
(CU1)->inter.mv[0][1] == (CU2)->inter.mv[0][1] && \ (CU1)->inter.mv[0][1] == (CU2)->inter.mv[0][1] && \
@ -775,8 +792,6 @@ uint8_t inter_get_merge_cand(const encoder_state_t * const state, int32_t x, int
} else { } else {
ref_positive++; ref_positive++;
} }
if (!ref_negative) ref_negative = 1;
if (!ref_positive) ref_positive = 1;
} }
num_ref = MIN(ref_negative, ref_positive); num_ref = MIN(ref_negative, ref_positive);
} }

View file

@ -1054,7 +1054,7 @@ static int search_cu_inter(const encoder_state_t * const state, int x, int y, in
if (merge_cand[merge_idx].dir != 3 && if (merge_cand[merge_idx].dir != 3 &&
merge_cand[merge_idx].mv[merge_cand[merge_idx].dir - 1][0] == mv.x && merge_cand[merge_idx].mv[merge_cand[merge_idx].dir - 1][0] == mv.x &&
merge_cand[merge_idx].mv[merge_cand[merge_idx].dir - 1][1] == mv.y && merge_cand[merge_idx].mv[merge_cand[merge_idx].dir - 1][1] == mv.y &&
(uint32_t)merge_cand[merge_idx].ref == ref_idx) { (uint32_t)merge_cand[merge_idx].ref[merge_cand[merge_idx].dir - 1] == ref_idx) {
merged = 1; merged = 1;
break; break;
} }
@ -1153,13 +1153,31 @@ static int search_cu_inter(const encoder_state_t * const state, int x, int y, in
cur_cu->inter.mv_ref_coded[0] = state->global->refmap[merge_cand[i].ref[0]].idx; cur_cu->inter.mv_ref_coded[0] = state->global->refmap[merge_cand[i].ref[0]].idx;
cur_cu->inter.mv_ref_coded[1] = state->global->refmap[merge_cand[j].ref[1]].idx; cur_cu->inter.mv_ref_coded[1] = state->global->refmap[merge_cand[j].ref[1]].idx;
cur_cu->merged = 0;
cur_cu->inter.mv_ref[0] = merge_cand[i].ref[0]; cur_cu->inter.mv_ref[0] = merge_cand[i].ref[0];
cur_cu->inter.mv_ref[1] = merge_cand[j].ref[1]; cur_cu->inter.mv_ref[1] = merge_cand[j].ref[1];
cur_cu->inter.mv[0][0] = merge_cand[i].mv[0][0] & 0xfff8; cur_cu->inter.mv[0][0] = merge_cand[i].mv[0][0] & 0xfff8;
cur_cu->inter.mv[0][1] = merge_cand[i].mv[0][1] & 0xfff8; cur_cu->inter.mv[0][1] = merge_cand[i].mv[0][1] & 0xfff8;
cur_cu->inter.mv[1][0] = merge_cand[j].mv[1][0] & 0xfff8; cur_cu->inter.mv[1][0] = merge_cand[j].mv[1][0] & 0xfff8;
cur_cu->inter.mv[1][1] = merge_cand[j].mv[1][1] & 0xfff8; cur_cu->inter.mv[1][1] = merge_cand[j].mv[1][1] & 0xfff8;
cur_cu->merged = 0;
// Check every candidate to find a match
for(int merge_idx = 0; merge_idx < num_cand; merge_idx++) {
if (
merge_cand[merge_idx].mv[0][0] == cur_cu->inter.mv[0][0] &&
merge_cand[merge_idx].mv[0][1] == cur_cu->inter.mv[0][1] &&
merge_cand[merge_idx].mv[1][0] == cur_cu->inter.mv[1][0] &&
merge_cand[merge_idx].mv[1][1] == cur_cu->inter.mv[1][1] &&
merge_cand[merge_idx].ref[0] == cur_cu->inter.mv_ref[0] &&
merge_cand[merge_idx].ref[1] == cur_cu->inter.mv_ref[1]) {
cur_cu->merged = 1;
cur_cu->merge_idx = merge_idx;
break;
}
}
for (int reflist = 0; reflist < 2; reflist++) { for (int reflist = 0; reflist < 2; reflist++) {
cu_mv_cand = 0; cu_mv_cand = 0;