mirror of
https://github.com/ultravideo/uvg266.git
synced 2024-12-18 03:04:06 +00:00
Cleaned up TMVP, mv candidate selection working, merge candidate selection not
This commit is contained in:
parent
d65d2ec88d
commit
1124bb5fd0
213
src/inter.c
213
src/inter.c
|
@ -671,22 +671,22 @@ static void kvz_inter_get_temporal_merge_candidates(const encoder_state_t * cons
|
||||||
*C3 = NULL;
|
*C3 = NULL;
|
||||||
*H = NULL;
|
*H = NULL;
|
||||||
|
|
||||||
// Find temporal reference, closest POC
|
// Find temporal reference, L0[0]
|
||||||
if (state->frame->ref->used_size) {
|
if (state->frame->ref->used_size) {
|
||||||
uint32_t poc_diff = UINT_MAX;
|
uint32_t colocated_ref = UINT_MAX;
|
||||||
int32_t closest_ref = 0;
|
|
||||||
|
|
||||||
|
// 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++) {
|
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];
|
if (state->frame->refmap[temporal_cand].list == 1 && state->frame->refmap[temporal_cand].idx == 0) {
|
||||||
|
colocated_ref = temporal_cand;
|
||||||
td = td < 0 ? -td : td;
|
break;
|
||||||
if (td < poc_diff) {
|
|
||||||
closest_ref = temporal_cand;
|
|
||||||
poc_diff = td;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cu_array_t *ref_cu_array = state->frame->ref->cu_arrays[closest_ref];
|
if (colocated_ref == UINT_MAX) return;
|
||||||
|
|
||||||
|
cu_array_t *ref_cu_array = state->frame->ref->cu_arrays[colocated_ref];
|
||||||
int cu_per_width = ref_cu_array->width / SCU_WIDTH;
|
int cu_per_width = ref_cu_array->width / SCU_WIDTH;
|
||||||
|
|
||||||
uint32_t xColBr = x + 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;
|
candidates = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Use Temporal Motion Vector Prediction when enabled
|
||||||
if (state->encoder_control->cfg.tmvp_enable) {
|
if (state->encoder_control->cfg.tmvp_enable) {
|
||||||
/*
|
/*
|
||||||
Predictor block locations
|
Predictor block locations
|
||||||
|
@ -1096,117 +1097,55 @@ static void get_mv_cand_from_spatial(const encoder_state_t * const state,
|
||||||
|H|
|
|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) {
|
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;
|
const cu_info_t *selected_CU = (h != NULL) ? h : (c3 != NULL) ? c3 : NULL;
|
||||||
|
|
||||||
if (selected_CU) {
|
if (selected_CU) {
|
||||||
uint32_t poc_diff = UINT_MAX;
|
uint32_t colocated_ref = UINT_MAX;
|
||||||
uint32_t closest_ref = 0;
|
uint32_t colocated_ref_poc = 0;
|
||||||
uint32_t closest_ref_poc = 0;
|
|
||||||
int td, tb;
|
int td, tb;
|
||||||
|
|
||||||
// ToDo: allow custom reference lists
|
//ToDo: allow other than L0[0] for prediction
|
||||||
// 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 {
|
|
||||||
|
|
||||||
// Handle with GOP
|
//Fetch ref idx of the selected CU in L0[0] ref list
|
||||||
//ToDo: allow other than L0[0] for prediction
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//Fetch ref idx of the selected CU in L0[0] ref list
|
if (colocated_ref != UINT_MAX) {
|
||||||
|
|
||||||
|
uint8_t used_reflist = reflist;
|
||||||
|
|
||||||
for (int temporal_cand = 0; temporal_cand < state->frame->ref->used_size; temporal_cand++) {
|
colocated_ref_poc = state->frame->ref->pocs[colocated_ref];
|
||||||
int ref_poc = state->frame->ref->pocs[temporal_cand];
|
|
||||||
int td = state->frame->poc - ref_poc;
|
|
||||||
|
|
||||||
//td = td < 0 ? UINT_MAX : td;
|
if (!(selected_CU->inter.mv_dir & (1 << used_reflist))) {
|
||||||
//if (td < poc_diff) {
|
used_reflist = !reflist;
|
||||||
if (td > 0) {
|
|
||||||
closest_ref = temporal_cand;
|
|
||||||
poc_diff = td;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The reference id the colocated block is using
|
||||||
|
uint32_t colocated_ref_mv_ref = selected_CU->inter.mv_ref[used_reflist];
|
||||||
|
|
||||||
|
td = colocated_ref_poc - state->frame->ref->images[colocated_ref]->ref_pocs[colocated_ref_mv_ref];
|
||||||
closest_ref_poc = state->frame->ref->pocs[closest_ref];
|
|
||||||
|
|
||||||
uint32_t colocated_ref_mv_ref = selected_CU->inter.mv_ref[reflist];
|
|
||||||
|
|
||||||
if (!(selected_CU->inter.mv_dir & (1 << reflist))) {
|
|
||||||
colocated_ref_mv_ref = selected_CU->inter.mv_ref[reflist2nd];
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
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);
|
|
||||||
|
|
||||||
// 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];
|
|
||||||
tb = state->frame->poc - state->frame->ref->pocs[cur_cu->inter.mv_ref[reflist]];
|
tb = 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];
|
||||||
int scale = CALCULATE_SCALE(NULL, tb, td);
|
mv_cand[candidates][1] = selected_CU->inter.mv[used_reflist][1];
|
||||||
int used_reflist = reflist;
|
} else {
|
||||||
|
int scale = CALCULATE_SCALE(NULL, tb, td);
|
||||||
// If the selected CU does not have the correct list (L0/L1) vector, use the other
|
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 (!(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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
candidates++;
|
candidates++;
|
||||||
//}
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#undef CALCULATE_SCALE
|
#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 (state->encoder_control->cfg.tmvp_enable) {
|
||||||
|
|
||||||
if (candidates < MRG_MAX_NUM_CANDS && state->frame->ref->used_size) {
|
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;
|
const cu_info_t *selected_CU = (h != NULL) ? h : (c3 != NULL) ? c3 : NULL;
|
||||||
|
|
||||||
if (selected_CU) {
|
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;
|
mv_cand[candidates].dir = 0;
|
||||||
|
|
||||||
// Find LIST_0 reference
|
// Find LIST_0 reference
|
||||||
if (h != NULL && h->inter.mv_dir & 1) {
|
if (h != NULL && h->inter.mv_dir & 1) {
|
||||||
mv_cand[candidates].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][0] = h->inter.mv[0][0];
|
||||||
mv_cand[candidates].mv[0][1] = h->inter.mv[0][1];
|
mv_cand[candidates].mv[0][1] = h->inter.mv[0][1];
|
||||||
|
|
||||||
} else if (c3 != NULL && c3->inter.mv_dir & 1) {
|
} else if (c3 != NULL && c3->inter.mv_dir & 1) {
|
||||||
mv_cand[candidates].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][0] = c3->inter.mv[0][0];
|
||||||
mv_cand[candidates].mv[0][1] = c3->inter.mv[0][1];
|
mv_cand[candidates].mv[0][1] = c3->inter.mv[0][1];
|
||||||
}
|
}
|
||||||
|
if (state->frame->slicetype == KVZ_SLICE_B) {
|
||||||
// Find LIST_1 reference
|
// Find LIST_1 reference
|
||||||
if (h != NULL && h->inter.mv_dir & 2) {
|
if (h != NULL && h->inter.mv_dir & 2) {
|
||||||
mv_cand[candidates].dir |= 2;
|
mv_cand[candidates].dir |= 2;
|
||||||
mv_cand[candidates].ref[1] = h->inter.mv_ref[1];
|
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][0] = h->inter.mv[1][0];
|
||||||
mv_cand[candidates].mv[1][1] = h->inter.mv[1][1];
|
mv_cand[candidates].mv[1][1] = h->inter.mv[1][1];
|
||||||
} else if (c3 != NULL && c3->inter.mv_dir & 2) {
|
} else if (c3 != NULL && c3->inter.mv_dir & 2) {
|
||||||
mv_cand[candidates].dir |= 2;
|
mv_cand[candidates].dir |= 2;
|
||||||
mv_cand[candidates].ref[1] = c3->inter.mv_ref[1];
|
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][0] = c3->inter.mv[1][0];
|
||||||
mv_cand[candidates].mv[1][1] = c3->inter.mv[1][1];
|
mv_cand[candidates].mv[1][1] = c3->inter.mv[1][1];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/*
|
//mv_cand[candidates].ref[0] = 0;
|
||||||
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];
|
|
||||||
*/
|
|
||||||
candidates++;
|
candidates++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1492,12 +1407,12 @@ uint8_t kvz_inter_get_merge_cand(const encoder_state_t * const state,
|
||||||
mv_cand[candidates].dir = 3;
|
mv_cand[candidates].dir = 3;
|
||||||
|
|
||||||
// get Mv from cand[i] and cand[j]
|
// 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][0] = mv_cand[i].mv[0][0];
|
||||||
mv_cand[candidates].mv[0][1] = mv_cand[i].mv[0][1];
|
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][0] = mv_cand[j].mv[1][0];
|
||||||
mv_cand[candidates].mv[1][1] = mv_cand[j].mv[1][1];
|
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[0] = mv_cand[i].ref[0];
|
||||||
mv_cand[candidates].ref[1] = mv_cand[j].ref[1];
|
mv_cand[candidates].ref[1] = mv_cand[j].ref[1];
|
||||||
|
|
||||||
if (mv_cand[i].ref[0] == 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] &&
|
mv_cand[i].mv[0][0] == mv_cand[j].mv[1][0] &&
|
||||||
|
|
Loading…
Reference in a new issue