From 4f880667404055a0d95da067c07b32fc62f7cfc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arttu=20Yl=C3=A4-Outinen?= Date: Wed, 22 Feb 2017 01:11:53 +0900 Subject: [PATCH] Refactor MV and merge candidate selection Replaces macros APPLY_MV_SCALING and CALCULATE_SCALE with helper functions. --- src/inter.c | 269 +++++++++++++++++++++++++--------------------------- 1 file changed, 130 insertions(+), 139 deletions(-) diff --git a/src/inter.c b/src/inter.c index d0458dcd..de1d81e6 100644 --- a/src/inter.c +++ b/src/inter.c @@ -916,6 +916,47 @@ static void get_spatial_merge_candidates_cua(const cu_array_t *cua, } } +static INLINE int16_t get_scaled_mv(int16_t mv, int scale) +{ + int32_t scaled = scale * mv; + return CLIP(-32768, 32767, (scaled + 127 + (scaled < 0)) >> 8); +} + +static void apply_mv_scaling_pocs(int32_t current_poc, + int32_t current_ref_poc, + int32_t neighbor_poc, + int32_t neighbor_ref_poc, + int16_t mv_cand[2]) +{ + int32_t diff_current = current_poc - current_ref_poc; + int32_t diff_neighbor = neighbor_poc - neighbor_ref_poc; + + if (diff_current == diff_neighbor) return; + + diff_current = CLIP(-128, 127, diff_current); + diff_neighbor = CLIP(-128, 127, diff_neighbor); + + int scale = CLIP(-4096, 4095, + (diff_current * ((0x4000 + (abs(diff_neighbor) >> 1)) / diff_neighbor) + 32) >> 6); + + mv_cand[0] = get_scaled_mv(mv_cand[0], scale); + mv_cand[1] = get_scaled_mv(mv_cand[1], scale); +} + +static INLINE void apply_mv_scaling(const encoder_state_t *state, + const cu_info_t *current_cu, + const cu_info_t *neighbor_cu, + int8_t current_reflist, + int8_t neighbor_reflist, + int16_t mv_cand[2]) +{ + apply_mv_scaling_pocs(state->frame->poc, + state->frame->ref->pocs[current_cu->inter.mv_ref[current_reflist]], + state->frame->poc, + state->frame->ref->pocs[neighbor_cu->inter.mv_ref[neighbor_reflist]], + mv_cand); +} + /** * \brief Pick two mv candidates from the spatial and temporal candidates. */ @@ -939,64 +980,52 @@ static void get_mv_cand_from_candidates(const encoder_state_t * const state, uint8_t b_candidates = 0; int8_t reflist2nd = !reflist; -#define CALCULATE_SCALE(cu,tb,td) CLIP(-4096, 4095, ((tb * ((0x4000 + (abs(td)>>1))/td) + 32) >> 6)) -#define APPLY_MV_SCALING(cu, cand, list) {int td = CLIP(-128, 127, state->frame->poc - state->frame->ref->pocs[(cu)->inter.mv_ref[list]]);\ - int tb = CLIP(-128, 127, state->frame->poc - state->frame->ref->pocs[cur_cu->inter.mv_ref[reflist]]);\ - if (td != tb) { \ - int scale = CALCULATE_SCALE(cu,tb,td); \ - mv_cand[cand][0] = CLIP(-32768, 32767, ((scale * (cu)->inter.mv[list][0] + 127 + (scale * (cu)->inter.mv[list][0] < 0)) >> 8 )); \ - mv_cand[cand][1] = CLIP(-32768, 32767, ((scale * (cu)->inter.mv[list][1] + 127 + (scale * (cu)->inter.mv[list][1] < 0)) >> 8 )); }} - // Left predictors - if (a0 && ( - ((a0->inter.mv_dir & 1) && a0->inter.mv_ref[0] == cur_cu->inter.mv_ref[reflist]) || - ((a0->inter.mv_dir & 2) && a0->inter.mv_ref[1] == cur_cu->inter.mv_ref[reflist]))) { - if (a0->inter.mv_dir & (1 << reflist) && a0->inter.mv_ref[reflist] == cur_cu->inter.mv_ref[reflist]) { - mv_cand[candidates][0] = a0->inter.mv[reflist][0]; - mv_cand[candidates][1] = a0->inter.mv[reflist][1]; - } else { - mv_cand[candidates][0] = a0->inter.mv[reflist2nd][0]; - mv_cand[candidates][1] = a0->inter.mv[reflist2nd][1]; - } - candidates++; - } else if (a1 && ( - ((a1->inter.mv_dir & 1) && a1->inter.mv_ref[0] == cur_cu->inter.mv_ref[reflist]) || - ((a1->inter.mv_dir & 2) && a1->inter.mv_ref[1] == cur_cu->inter.mv_ref[reflist]))) { - if (a1->inter.mv_dir & (1 << reflist) && a1->inter.mv_ref[reflist] == cur_cu->inter.mv_ref[reflist]) { - mv_cand[candidates][0] = a1->inter.mv[reflist][0]; - mv_cand[candidates][1] = a1->inter.mv[reflist][1]; - } else { - mv_cand[candidates][0] = a1->inter.mv[reflist2nd][0]; - mv_cand[candidates][1] = a1->inter.mv[reflist2nd][1]; - } - candidates++; - } + if (a0 && + a0->inter.mv_dir & (1 << reflist) && + a0->inter.mv_ref[reflist] == cur_cu->inter.mv_ref[reflist]) { - if(!candidates) { - // Left predictors - if (a0) { - if (a0->inter.mv_dir & (1 << reflist)) { - mv_cand[candidates][0] = a0->inter.mv[reflist][0]; - mv_cand[candidates][1] = a0->inter.mv[reflist][1]; - APPLY_MV_SCALING(a0, candidates, reflist); - } else { - mv_cand[candidates][0] = a0->inter.mv[reflist2nd][0]; - mv_cand[candidates][1] = a0->inter.mv[reflist2nd][1]; - APPLY_MV_SCALING(a0, candidates, reflist2nd); - } - candidates++; - } else if (a1) { - if (a1->inter.mv_dir & (1 << reflist)) { - mv_cand[candidates][0] = a1->inter.mv[reflist][0]; - mv_cand[candidates][1] = a1->inter.mv[reflist][1]; - APPLY_MV_SCALING(a1, candidates, reflist); - } else { - mv_cand[candidates][0] = a1->inter.mv[reflist2nd][0]; - mv_cand[candidates][1] = a1->inter.mv[reflist2nd][1]; - APPLY_MV_SCALING(a1, candidates, reflist2nd); - } - candidates++; - } + mv_cand[candidates][0] = a0->inter.mv[reflist][0]; + mv_cand[candidates][1] = a0->inter.mv[reflist][1]; + candidates++; + + } else if (a0 && + a0->inter.mv_dir & (1 << reflist2nd) && + a0->inter.mv_ref[reflist2nd] == cur_cu->inter.mv_ref[reflist]) { + + mv_cand[candidates][0] = a0->inter.mv[reflist2nd][0]; + mv_cand[candidates][1] = a0->inter.mv[reflist2nd][1]; + candidates++; + + } else if (a1 && + a1->inter.mv_dir & (1 << reflist) && + a1->inter.mv_ref[reflist] == cur_cu->inter.mv_ref[reflist]) { + + mv_cand[candidates][0] = a1->inter.mv[reflist][0]; + mv_cand[candidates][1] = a1->inter.mv[reflist][1]; + candidates++; + + } else if (a1 && + a1->inter.mv_dir & (1 << reflist2nd) && + a1->inter.mv_ref[reflist2nd] == cur_cu->inter.mv_ref[reflist]) { + + mv_cand[candidates][0] = a1->inter.mv[reflist2nd][0]; + mv_cand[candidates][1] = a1->inter.mv[reflist2nd][1]; + candidates++; + + } else if (a0) { + int cand_list = a0->inter.mv_dir & (1 << reflist) ? reflist : reflist2nd; + mv_cand[candidates][0] = a0->inter.mv[cand_list][0]; + mv_cand[candidates][1] = a0->inter.mv[cand_list][1]; + apply_mv_scaling(state, cur_cu, a0, reflist, cand_list, mv_cand[candidates]); + candidates++; + + } else if (a1) { + int cand_list = a1->inter.mv_dir & (1 << reflist) ? reflist : reflist2nd; + mv_cand[candidates][0] = a1->inter.mv[cand_list][0]; + mv_cand[candidates][1] = a1->inter.mv[cand_list][1]; + apply_mv_scaling(state, cur_cu, a1, reflist, cand_list, mv_cand[candidates]); + candidates++; } // Top predictors @@ -1043,40 +1072,27 @@ static void get_mv_cand_from_candidates(const encoder_state_t * const state, b_candidates = 0; } - if(!b_candidates) { - // Top predictors + if (!b_candidates) { + // Top predictors with scaling if (b0) { - if (b0->inter.mv_dir & (1 << reflist)) { - mv_cand[candidates][0] = b0->inter.mv[reflist][0]; - mv_cand[candidates][1] = b0->inter.mv[reflist][1]; - APPLY_MV_SCALING(b0, candidates, reflist); - } else { - mv_cand[candidates][0] = b0->inter.mv[reflist2nd][0]; - mv_cand[candidates][1] = b0->inter.mv[reflist2nd][1]; - APPLY_MV_SCALING(b0, candidates, reflist2nd); - } + int cand_list = b0->inter.mv_dir & (1 << reflist) ? reflist : reflist2nd; + mv_cand[candidates][0] = b0->inter.mv[cand_list][0]; + mv_cand[candidates][1] = b0->inter.mv[cand_list][1]; + apply_mv_scaling(state, cur_cu, b0, reflist, cand_list, mv_cand[candidates]); candidates++; + } else if (b1) { - if (b1->inter.mv_dir & (1 << reflist)) { - mv_cand[candidates][0] = b1->inter.mv[reflist][0]; - mv_cand[candidates][1] = b1->inter.mv[reflist][1]; - APPLY_MV_SCALING(b1, candidates, reflist); - } else { - mv_cand[candidates][0] = b1->inter.mv[reflist2nd][0]; - mv_cand[candidates][1] = b1->inter.mv[reflist2nd][1]; - APPLY_MV_SCALING(b1, candidates, reflist2nd); - } + int cand_list = b1->inter.mv_dir & (1 << reflist) ? reflist : reflist2nd; + mv_cand[candidates][0] = b1->inter.mv[cand_list][0]; + mv_cand[candidates][1] = b1->inter.mv[cand_list][1]; + apply_mv_scaling(state, cur_cu, b1, reflist, cand_list, mv_cand[candidates]); candidates++; + } else if (b2) { - if (b2->inter.mv_dir & (1 << reflist)) { - mv_cand[candidates][0] = b2->inter.mv[reflist][0]; - mv_cand[candidates][1] = b2->inter.mv[reflist][1]; - APPLY_MV_SCALING(b2, candidates, reflist); - } else { - mv_cand[candidates][0] = b2->inter.mv[reflist2nd][0]; - mv_cand[candidates][1] = b2->inter.mv[reflist2nd][1]; - APPLY_MV_SCALING(b2, candidates, reflist2nd); - } + int cand_list = b2->inter.mv_dir & (1 << reflist) ? reflist : reflist2nd; + mv_cand[candidates][0] = b2->inter.mv[cand_list][0]; + mv_cand[candidates][1] = b2->inter.mv[cand_list][1]; + apply_mv_scaling(state, cur_cu, b2, reflist, cand_list, mv_cand[candidates]); candidates++; } } @@ -1124,9 +1140,6 @@ static void get_mv_cand_from_candidates(const encoder_state_t * const state, if (colocated_ref != UINT_MAX) { uint8_t used_reflist = reflist; - - int32_t colocated_ref_poc = state->frame->ref->pocs[colocated_ref]; - if (!(selected_CU->inter.mv_dir & (1 << used_reflist))) { used_reflist = !reflist; } @@ -1134,18 +1147,15 @@ static void get_mv_cand_from_candidates(const encoder_state_t * const state, // The reference id the colocated block is using uint32_t colocated_ref_mv_ref = selected_CU->inter.mv_ref[used_reflist]; - int td = CLIP(-128, 127, colocated_ref_poc - state->frame->ref->images[colocated_ref]->ref_pocs[colocated_ref_mv_ref]); - int tb = CLIP(-128, 127, state->frame->poc - state->frame->ref->pocs[cur_cu->inter.mv_ref[reflist]]); - - if (td == tb) { - mv_cand[candidates][0] = selected_CU->inter.mv[used_reflist][0]; - mv_cand[candidates][1] = selected_CU->inter.mv[used_reflist][1]; - } else { - int scale = CALCULATE_SCALE(NULL, tb, td); - mv_cand[candidates][0] = CLIP(-32768, 32767, ((scale * selected_CU->inter.mv[used_reflist][0] + 127 + ((scale * selected_CU->inter.mv[used_reflist][0]) < 0)) >> 8)); - mv_cand[candidates][1] = CLIP(-32768, 32767, ((scale * selected_CU->inter.mv[used_reflist][1] + 127 + ((scale * selected_CU->inter.mv[used_reflist][1]) < 0)) >> 8)); - } - + mv_cand[candidates][0] = selected_CU->inter.mv[used_reflist][0]; + mv_cand[candidates][1] = selected_CU->inter.mv[used_reflist][1]; + apply_mv_scaling_pocs( + state->frame->poc, + state->frame->ref->pocs[cur_cu->inter.mv_ref[reflist]], + state->frame->ref->pocs[colocated_ref], + state->frame->ref->images[colocated_ref]->ref_pocs[colocated_ref_mv_ref], + mv_cand[candidates] + ); candidates++; } } // TMVP @@ -1156,8 +1166,6 @@ static void get_mv_cand_from_candidates(const encoder_state_t * const state, mv_cand[candidates][1] = 0; candidates++; } -#undef CALCULATE_SCALE -#undef APPLY_MV_SCALING } /** @@ -1346,14 +1354,9 @@ uint8_t kvz_inter_get_merge_cand(const encoder_state_t * const state, } if (state->encoder_control->cfg.tmvp_enable) { - -#define CALCULATE_SCALE(tb,td) CLIP(-4096, 4095, ((tb * ((0x4000 + (abs(td) >> 1)) / td) + 32) >> 6)) - if (candidates < MRG_MAX_NUM_CANDS && state->frame->ref->used_size) { uint32_t colocated_ref = UINT_MAX; - int32_t colocated_ref_poc = 0; - int32_t td, tb; uint8_t selected_reflist = 0; cu_info_t *c3_L0 = NULL; @@ -1366,7 +1369,6 @@ uint8_t kvz_inter_get_merge_cand(const encoder_state_t * const state, selected_CU = (h_L0 != NULL) ? h_L0 : (c3_L0 != NULL) ? c3_L0 : NULL; - mv_cand[candidates].dir = 0; // Find LIST_0 reference @@ -1378,7 +1380,7 @@ uint8_t kvz_inter_get_merge_cand(const encoder_state_t * const state, uint8_t colocated_ref_found = 0; - //Fetch ref idx of the selected CU in L0[0] ref list + //Fetch ref idx of the selected CU in L0[0] ref list for (int32_t temporal_cand = 0; temporal_cand < state->frame->ref->used_size; temporal_cand++) { if (state->frame->refmap[temporal_cand].list == 1 && state->frame->refmap[temporal_cand].idx == 0) { colocated_ref = temporal_cand; @@ -1388,29 +1390,23 @@ uint8_t kvz_inter_get_merge_cand(const encoder_state_t * const state, } if (colocated_ref_found) { - colocated_ref_poc = state->frame->ref->pocs[colocated_ref]; - // The reference id the colocated block is using uint32_t colocated_ref_mv_ref = selected_CU->inter.mv_ref[selected_reflist]; - td = CLIP(-128, 127, colocated_ref_poc - state->frame->ref->images[colocated_ref]->ref_pocs[colocated_ref_mv_ref]); - tb = CLIP(-128, 127, state->frame->poc - state->frame->ref->pocs[ref_idx]); - mv_cand[candidates].dir |= 1; - - if (td == tb) { - mv_cand[candidates].mv[0][0] = selected_CU->inter.mv[selected_reflist][0]; - mv_cand[candidates].mv[0][1] = selected_CU->inter.mv[selected_reflist][1]; - } else { - int32_t scale = CALCULATE_SCALE(tb, td); - mv_cand[candidates].mv[0][0] = CLIP(-32768, 32767, ((scale * selected_CU->inter.mv[selected_reflist][0] + 127 + ((scale * selected_CU->inter.mv[selected_reflist][0]) < 0)) >> 8)); - mv_cand[candidates].mv[0][1] = CLIP(-32768, 32767, ((scale * selected_CU->inter.mv[selected_reflist][1] + 127 + ((scale * selected_CU->inter.mv[selected_reflist][1]) < 0)) >> 8)); - } mv_cand[candidates].ref[0] = colocated_ref; + mv_cand[candidates].mv[0][0] = selected_CU->inter.mv[selected_reflist][0]; + mv_cand[candidates].mv[0][1] = selected_CU->inter.mv[selected_reflist][1]; + apply_mv_scaling_pocs( + state->frame->poc, + state->frame->ref->pocs[ref_idx], + state->frame->ref->pocs[colocated_ref], + state->frame->ref->images[colocated_ref]->ref_pocs[colocated_ref_mv_ref], + mv_cand[candidates].mv[0] + ); } } - if (state->frame->slicetype == KVZ_SLICE_B) { selected_reflist = 1; @@ -1438,27 +1434,23 @@ uint8_t kvz_inter_get_merge_cand(const encoder_state_t * const state, } } - colocated_ref_poc = state->frame->ref->pocs[colocated_ref]; + int colocated_ref_poc = state->frame->ref->pocs[colocated_ref]; if (colocated_ref_found) { // The reference id the colocated block is using uint32_t colocated_ref_mv_ref = selected_CU->inter.mv_ref[selected_reflist]; - // POC differences in current and in candidate - td = CLIP(-128, 127, colocated_ref_poc - state->frame->ref->images[colocated_ref]->ref_pocs[colocated_ref_mv_ref]); - tb = CLIP(-128, 127, state->frame->poc - state->frame->ref->pocs[ref_idx]); mv_cand[candidates].dir |= 2; - - // No need for scaling when POC difference is the same - if (td == tb) { - mv_cand[candidates].mv[1][0] = selected_CU->inter.mv[selected_reflist][0]; - mv_cand[candidates].mv[1][1] = selected_CU->inter.mv[selected_reflist][1]; - } else { - int32_t scale = CALCULATE_SCALE(tb, td); - mv_cand[candidates].mv[1][0] = CLIP(-32768, 32767, ((scale * selected_CU->inter.mv[selected_reflist][0] + 127 + ((scale * selected_CU->inter.mv[selected_reflist][0]) < 0)) >> 8)); - mv_cand[candidates].mv[1][1] = CLIP(-32768, 32767, ((scale * selected_CU->inter.mv[selected_reflist][1] + 127 + ((scale * selected_CU->inter.mv[selected_reflist][1]) < 0)) >> 8)); - } mv_cand[candidates].ref[1] = colocated_ref; + mv_cand[candidates].mv[1][0] = selected_CU->inter.mv[selected_reflist][0]; + mv_cand[candidates].mv[1][1] = selected_CU->inter.mv[selected_reflist][1]; + apply_mv_scaling_pocs( + colocated_ref_poc, + state->frame->ref->images[colocated_ref]->ref_pocs[colocated_ref_mv_ref], + state->frame->poc, + state->frame->ref->pocs[ref_idx], + mv_cand[candidates].mv[1] + ); } } } @@ -1466,7 +1458,6 @@ uint8_t kvz_inter_get_merge_cand(const encoder_state_t * const state, if (mv_cand[candidates].dir != 0) candidates++; } - #undef CALCULATE_SCALE } if (candidates < MRG_MAX_NUM_CANDS && state->frame->slicetype == KVZ_SLICE_B) {