From 0e958ebe84d3f9fd9d3580cd75ae6cc9b6f1a910 Mon Sep 17 00:00:00 2001 From: Marko Viitanen Date: Thu, 23 Apr 2015 12:18:33 +0300 Subject: [PATCH] Fixed merge candidate selection --- src/inter.c | 33 ++++++++++++++++++++++++--------- src/search.c | 22 ++++++++++++++++++++-- 2 files changed, 44 insertions(+), 11 deletions(-) diff --git a/src/inter.c b/src/inter.c index 09743fd3..731cc857 100644 --- a/src/inter.c +++ b/src/inter.c @@ -373,7 +373,18 @@ void inter_recon_lcu_bipred(const encoder_state_t * const state, const image_t * 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 @@ -408,11 +419,13 @@ void inter_get_spatial_merge_candidates(int32_t x, int32_t y, int8_t depth, cu_i if (x != 0) { *a1 = &cu[x_cu - 1 + (y_cu + cur_block_in_scu - 1) * LCU_T_CU_WIDTH]; if (!(*a1)->coded) *a1 = NULL; + if(*a1) inter_clear_cu_unused(*a1); 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]; if (!(*a0)->coded) *a0 = NULL; } + if(*a0) inter_clear_cu_unused(*a0); } // 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]; 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]; if (!(*b1)->coded) *b1 = NULL; + if(*b1) inter_clear_cu_unused(*b1); if (x != 0) { *b2 = &cu[x_cu - 1 + (y_cu - 1) * LCU_T_CU_WIDTH]; if(!(*b2)->coded) *b2 = NULL; } + if(*b2) inter_clear_cu_unused(*b2); } } @@ -637,14 +653,15 @@ 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 && \ + (CU1)->inter.mv_dir == (CU2)->inter.mv_dir && \ (!(((CU1)->inter.mv_dir & 1) && ((CU2)->inter.mv_dir & 1)) || \ ((CU1)->inter.mv[0][0] == (CU2)->inter.mv[0][0] && \ - (CU1)->inter.mv[0][1] == (CU2)->inter.mv[0][1] && \ - (CU1)->inter.mv_ref[0] == (CU2)->inter.mv_ref[0]) ) && \ - (!(((CU1)->inter.mv_dir & 2) && ((CU2)->inter.mv_dir & 2)) || \ + (CU1)->inter.mv[0][1] == (CU2)->inter.mv[0][1] && \ + (CU1)->inter.mv_ref[0] == (CU2)->inter.mv_ref[0]) ) && \ + (!(((CU1)->inter.mv_dir & 2) && ((CU2)->inter.mv_dir & 2) ) || \ ((CU1)->inter.mv[1][0] == (CU2)->inter.mv[1][0] && \ - (CU1)->inter.mv[1][1] == (CU2)->inter.mv[1][1] && \ - (CU1)->inter.mv_ref[1] == (CU2)->inter.mv_ref[1])) \ + (CU1)->inter.mv[1][1] == (CU2)->inter.mv[1][1] && \ + (CU1)->inter.mv_ref[1] == (CU2)->inter.mv_ref[1]) ) \ ) duplicate = 1; } if (a1 && a1->type == CU_INTER) { @@ -775,12 +792,10 @@ uint8_t inter_get_merge_cand(const encoder_state_t * const state, int32_t x, int } else { ref_positive++; } - if (!ref_negative) ref_negative = 1; - if (!ref_positive) ref_positive = 1; } num_ref = MIN(ref_negative, ref_positive); } - + // Add (0,0) prediction while (candidates != MRG_MAX_NUM_CANDS) { mv_cand[candidates].mv[0][0] = 0; diff --git a/src/search.c b/src/search.c index 528b25e9..01cd8f38 100644 --- a/src/search.c +++ b/src/search.c @@ -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 && 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 && - (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; 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[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[1] = merge_cand[j].ref[1]; 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[1][0] = merge_cand[j].mv[1][0] & 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++) { cu_mv_cand = 0;