diff --git a/src/inter.c b/src/inter.c index f65831a8..85065928 100644 --- a/src/inter.c +++ b/src/inter.c @@ -671,22 +671,22 @@ static void kvz_inter_get_temporal_merge_candidates(const encoder_state_t * cons *C3 = NULL; *H = NULL; - // Find temporal reference, closest POC + // Find temporal reference, L0[0] if (state->frame->ref->used_size) { - uint32_t poc_diff = UINT_MAX; - int32_t closest_ref = 0; + uint32_t colocated_ref = UINT_MAX; + // ToDo: allow other reference than L0[0] + // Select L0[0] reference for (int temporal_cand = 0; temporal_cand < state->frame->ref->used_size; temporal_cand++) { - int td = state->frame->poc - state->frame->ref->pocs[temporal_cand]; - - td = td < 0 ? -td : td; - if (td < poc_diff) { - closest_ref = temporal_cand; - poc_diff = td; + if (state->frame->refmap[temporal_cand].list == 1 && state->frame->refmap[temporal_cand].idx == 0) { + colocated_ref = temporal_cand; + break; } } + + if (colocated_ref == UINT_MAX) return; - cu_array_t *ref_cu_array = state->frame->ref->cu_arrays[closest_ref]; + cu_array_t *ref_cu_array = state->frame->ref->cu_arrays[colocated_ref]; int cu_per_width = ref_cu_array->width / SCU_WIDTH; uint32_t xColBr = x + width; @@ -1085,6 +1085,7 @@ static void get_mv_cand_from_spatial(const encoder_state_t * const state, candidates = 1; } + // Use Temporal Motion Vector Prediction when enabled if (state->encoder_control->cfg.tmvp_enable) { /* Predictor block locations @@ -1096,117 +1097,55 @@ static void get_mv_cand_from_spatial(const encoder_state_t * const state, |H| */ + // TMVP required at least two sequential P/B-frames if (state->frame->poc > 1 && state->frame->ref->used_size && candidates < AMVP_MAX_NUM_CANDS) { + // Use "H" as the primary predictor and "C3" as secondary const cu_info_t *selected_CU = (h != NULL) ? h : (c3 != NULL) ? c3 : NULL; if (selected_CU) { - uint32_t poc_diff = UINT_MAX; - uint32_t closest_ref = 0; - uint32_t closest_ref_poc = 0; + uint32_t colocated_ref = UINT_MAX; + uint32_t colocated_ref_poc = 0; int td, tb; - // ToDo: allow custom reference lists - // Without GOP, assume that every frame is a reference frame in an order - if (state->encoder_control->cfg->gop_len) { - td = selected_CU->inter.mv_ref[reflist] + 1; - tb = cur_cu->inter.mv_ref[reflist] + 1; - } else { + //ToDo: allow other than L0[0] for prediction - // Handle with GOP - //ToDo: allow other than L0[0] for prediction - - //Fetch ref idx of the selected CU in L0[0] ref list - - - for (int temporal_cand = 0; temporal_cand < state->frame->ref->used_size; temporal_cand++) { - int ref_poc = state->frame->ref->pocs[temporal_cand]; - int td = state->frame->poc - ref_poc; - - //td = td < 0 ? UINT_MAX : td; - //if (td < poc_diff) { - if (td > 0) { - closest_ref = temporal_cand; - poc_diff = td; - break; - } + //Fetch ref idx of the selected CU in L0[0] ref list + for (int 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; + break; } - - + } - closest_ref_poc = state->frame->ref->pocs[closest_ref]; + if (colocated_ref != UINT_MAX) { - uint32_t colocated_ref_mv_ref = selected_CU->inter.mv_ref[reflist]; + uint8_t used_reflist = reflist; - if (!(selected_CU->inter.mv_dir & (1 << reflist))) { - colocated_ref_mv_ref = selected_CU->inter.mv_ref[reflist2nd]; + colocated_ref_poc = state->frame->ref->pocs[colocated_ref]; + + if (!(selected_CU->inter.mv_dir & (1 << used_reflist))) { + used_reflist = !reflist; } - /* - int32_t colocated_ref_frame = state->frame->num+1; - uint32_t gop_len = state->encoder_control->cfg->gop_len; - uint32_t base_POC = state->frame->poc - (state->frame->poc % gop_len); - // Search the POC using the GOP structure - for (; colocated_ref_frame > 0; colocated_ref_frame--) { - if (base_POC + state->encoder_control->cfg->gop[colocated_ref_frame % gop_len].poc_offset == closest_ref_poc) { - break; - } - if (colocated_ref_frame % gop_len == 0) base_POC -= gop_len; - } - - //uint32_t colocated_pocs[MAX_REF_PIC_COUNT]; - base_POC = closest_ref_poc - (closest_ref_poc % gop_len); + // The reference id the colocated block is using + uint32_t colocated_ref_mv_ref = selected_CU->inter.mv_ref[used_reflist]; - // Reconstruct ref list - - uint32_t max_refs = (state->encoder_control->cfg->gop[colocated_ref_frame % gop_len].ref_neg_count + state->encoder_control->cfg->gop[colocated_ref_frame % gop_len].ref_pos_count); - uint32_t current_ref = 0; - for (int32_t temp_frame = colocated_ref_frame-1; temp_frame >= 0; temp_frame--) { - if (state->encoder_control->cfg->gop[temp_frame % gop_len].is_ref) { - colocated_pocs[current_ref] = base_POC + state->encoder_control->cfg->gop[temp_frame % gop_len].poc_offset; - if (current_ref == max_refs) break; - current_ref++; - } - if (temp_frame == 0) { - colocated_pocs[current_ref] = 0; - current_ref++; - break; - } - if (temp_frame % gop_len == 0) base_POC -= gop_len; - } - */ - - td = closest_ref_poc - state->frame->ref->images[closest_ref]->ref_pocs[colocated_ref_mv_ref]; + td = colocated_ref_poc - state->frame->ref->images[colocated_ref]->ref_pocs[colocated_ref_mv_ref]; tb = state->frame->poc - state->frame->ref->pocs[cur_cu->inter.mv_ref[reflist]]; - - } - - int scale = CALCULATE_SCALE(NULL, tb, td); - int used_reflist = reflist; - - // If the selected CU does not have the correct list (L0/L1) vector, use the other - - if (!(selected_CU->inter.mv_dir & (1 << reflist))) { - //td = state->frame->poc - state->previous_encoder_state->frame->ref->pocs[selected_CU->inter.mv_ref[reflist2nd]]; - used_reflist = reflist2nd; - } - - mv_cand[candidates][0] = ((scale * selected_CU->inter.mv[used_reflist][0] + 127 + (scale * selected_CU->inter.mv[used_reflist][0] < 0)) >> 8); - mv_cand[candidates][1] = ((scale * selected_CU->inter.mv[used_reflist][1] + 127 + (scale * selected_CU->inter.mv[used_reflist][1] < 0)) >> 8); - //if (poc_diff != UINT_MAX) { - - { - int td = selected_CU->inter.mv_ref[reflist] + 1; - int tb = cur_cu->inter.mv_ref[reflist] + 1; - - int scale = CALCULATE_SCALE(NULL, tb, td); - mv_cand[candidates][0] = ((scale * selected_CU->inter.mv[0][0] + 127 + (scale * selected_CU->inter.mv[0][0] < 0)) >> 8); - mv_cand[candidates][1] = ((scale * selected_CU->inter.mv[0][1] + 127 + (scale * selected_CU->inter.mv[0][1] < 0)) >> 8); - } - + 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] = ((scale * selected_CU->inter.mv[used_reflist][0] + 127 + ((scale * selected_CU->inter.mv[used_reflist][0]) < 0)) >> 8); + mv_cand[candidates][1] = ((scale * selected_CU->inter.mv[used_reflist][1] + 127 + ((scale * selected_CU->inter.mv[used_reflist][1]) < 0)) >> 8); + } + candidates++; - //} + + } } #undef CALCULATE_SCALE } @@ -1404,7 +1343,7 @@ uint8_t kvz_inter_get_merge_cand(const encoder_state_t * const state, } } } - return candidates; + if (state->encoder_control->cfg.tmvp_enable) { if (candidates < MRG_MAX_NUM_CANDS && state->frame->ref->used_size) { @@ -1417,61 +1356,37 @@ uint8_t kvz_inter_get_merge_cand(const encoder_state_t * const state, const cu_info_t *selected_CU = (h != NULL) ? h : (c3 != NULL) ? c3 : NULL; if (selected_CU) { - /* - uint32_t poc_diff = UINT_MAX; - for (int temporal_cand = 0; temporal_cand < state->frame->ref->used_size; temporal_cand++) { - int td = state->frame->poc - state->frame->ref->pocs[temporal_cand]; - td = td < 0 ? UINT_MAX : td; - if (td < poc_diff) { - poc_diff = td; - } - }*/ - + mv_cand[candidates].dir = 0; // Find LIST_0 reference if (h != NULL && h->inter.mv_dir & 1) { mv_cand[candidates].dir |= 1; - mv_cand[candidates].ref[0] = h->inter.mv_ref[0]; + mv_cand[candidates].ref[0] = 0; mv_cand[candidates].mv[0][0] = h->inter.mv[0][0]; mv_cand[candidates].mv[0][1] = h->inter.mv[0][1]; } else if (c3 != NULL && c3->inter.mv_dir & 1) { mv_cand[candidates].dir |= 1; - mv_cand[candidates].ref[0] = c3->inter.mv_ref[0]; + mv_cand[candidates].ref[0] = 0; mv_cand[candidates].mv[0][0] = c3->inter.mv[0][0]; mv_cand[candidates].mv[0][1] = c3->inter.mv[0][1]; } - - // Find LIST_1 reference - if (h != NULL && h->inter.mv_dir & 2) { - mv_cand[candidates].dir |= 2; - mv_cand[candidates].ref[1] = h->inter.mv_ref[1]; - mv_cand[candidates].mv[1][0] = h->inter.mv[1][0]; - mv_cand[candidates].mv[1][1] = h->inter.mv[1][1]; - } else if (c3 != NULL && c3->inter.mv_dir & 2) { - mv_cand[candidates].dir |= 2; - mv_cand[candidates].ref[1] = c3->inter.mv_ref[1]; - mv_cand[candidates].mv[1][0] = c3->inter.mv[1][0]; - mv_cand[candidates].mv[1][1] = c3->inter.mv[1][1]; + if (state->frame->slicetype == KVZ_SLICE_B) { + // Find LIST_1 reference + if (h != NULL && h->inter.mv_dir & 2) { + mv_cand[candidates].dir |= 2; + mv_cand[candidates].ref[1] = h->inter.mv_ref[1]; + mv_cand[candidates].mv[1][0] = h->inter.mv[1][0]; + mv_cand[candidates].mv[1][1] = h->inter.mv[1][1]; + } else if (c3 != NULL && c3->inter.mv_dir & 2) { + mv_cand[candidates].dir |= 2; + mv_cand[candidates].ref[1] = c3->inter.mv_ref[1]; + mv_cand[candidates].mv[1][0] = c3->inter.mv[1][0]; + mv_cand[candidates].mv[1][1] = c3->inter.mv[1][1]; + } } - /* - int tb = state->frame->poc - state->frame->ref->pocs[selected_CU->inter.mv_ref[0]]; - int td = 1; - - int scale = ((tb * ((0x4000 + (abs(td) >> 1)) / td) + 32) >> 6); - */ - /* - mv_cand[candidates].mv[0][0] = ((scale * selected_CU->inter.mv[0][0] + 127 + (scale * selected_CU->inter.mv[0][0] < 0)) >> 8); - mv_cand[candidates].mv[0][1] = ((scale * selected_CU->inter.mv[0][1] + 127 + (scale * selected_CU->inter.mv[0][1] < 0)) >> 8); - mv_cand[candidates].mv[1][0] = ((scale * selected_CU->inter.mv[1][0] + 127 + (scale * selected_CU->inter.mv[1][0] < 0)) >> 8); - mv_cand[candidates].mv[1][1] = ((scale * selected_CU->inter.mv[1][1] + 127 + (scale * selected_CU->inter.mv[1][1] < 0)) >> 8); - - - mv_cand[candidates].dir = tmvp_dir; - mv_cand[candidates].ref[0] = selected_CU->inter.mv_ref[0]; - mv_cand[candidates].ref[1] = selected_CU->inter.mv_ref[1]; - */ + //mv_cand[candidates].ref[0] = 0; candidates++; } } @@ -1492,12 +1407,12 @@ uint8_t kvz_inter_get_merge_cand(const encoder_state_t * const state, mv_cand[candidates].dir = 3; // get Mv from cand[i] and cand[j] - mv_cand[candidates].mv[0][0] = mv_cand[i].mv[0][0]; - mv_cand[candidates].mv[0][1] = mv_cand[i].mv[0][1]; - mv_cand[candidates].mv[1][0] = mv_cand[j].mv[1][0]; - mv_cand[candidates].mv[1][1] = mv_cand[j].mv[1][1]; - mv_cand[candidates].ref[0] = mv_cand[i].ref[0]; - mv_cand[candidates].ref[1] = mv_cand[j].ref[1]; + mv_cand[candidates].mv[0][0] = mv_cand[i].mv[0][0]; + mv_cand[candidates].mv[0][1] = mv_cand[i].mv[0][1]; + mv_cand[candidates].mv[1][0] = mv_cand[j].mv[1][0]; + mv_cand[candidates].mv[1][1] = mv_cand[j].mv[1][1]; + mv_cand[candidates].ref[0] = mv_cand[i].ref[0]; + mv_cand[candidates].ref[1] = mv_cand[j].ref[1]; if (mv_cand[i].ref[0] == mv_cand[j].ref[1] && mv_cand[i].mv[0][0] == mv_cand[j].mv[1][0] &&