mirror of
https://github.com/ultravideo/uvg266.git
synced 2024-11-27 19:24:06 +00:00
Extract inter search in a single ref frame.
Moves code for doing inter search in a single reference frame from function kvz_search_cu_inter to a new function search_cu_inter_ref.
This commit is contained in:
parent
f9f3d5929e
commit
21e19067fe
|
@ -951,6 +951,127 @@ static unsigned search_frac(const encoder_state_t * const state,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Perform inter search for a single reference frame.
|
||||||
|
*/
|
||||||
|
static void search_cu_inter_ref(const encoder_state_t * const state,
|
||||||
|
int x, int y, int depth,
|
||||||
|
lcu_t *lcu, cu_info_t *cur_cu,
|
||||||
|
int16_t mv_cand[2][2],
|
||||||
|
inter_merge_cand_t merge_cand[MRG_MAX_NUM_CANDS],
|
||||||
|
int16_t num_cand,
|
||||||
|
unsigned ref_idx,
|
||||||
|
uint32_t(*get_mvd_cost)(vector2d_t *, cabac_data_t*))
|
||||||
|
{
|
||||||
|
const int x_cu = x >> 3;
|
||||||
|
const int y_cu = y >> 3;
|
||||||
|
const videoframe_t * const frame = state->tile->frame;
|
||||||
|
kvz_picture *ref_image = state->global->ref->images[ref_idx];
|
||||||
|
uint32_t temp_bitcost = 0;
|
||||||
|
uint32_t temp_cost = 0;
|
||||||
|
vector2d_t orig, mvd;
|
||||||
|
int32_t merged = 0;
|
||||||
|
uint8_t cu_mv_cand = 0;
|
||||||
|
int8_t merge_idx = 0;
|
||||||
|
int8_t ref_list = state->global->refmap[ref_idx].list-1;
|
||||||
|
int8_t temp_ref_idx = cur_cu->inter.mv_ref[ref_list];
|
||||||
|
orig.x = x_cu * CU_MIN_SIZE_PIXELS;
|
||||||
|
orig.y = y_cu * CU_MIN_SIZE_PIXELS;
|
||||||
|
// Get MV candidates
|
||||||
|
cur_cu->inter.mv_ref[ref_list] = ref_idx;
|
||||||
|
kvz_inter_get_mv_cand(state, x, y, depth, mv_cand, cur_cu, lcu, ref_list);
|
||||||
|
cur_cu->inter.mv_ref[ref_list] = temp_ref_idx;
|
||||||
|
|
||||||
|
|
||||||
|
vector2d_t mv = { 0, 0 };
|
||||||
|
{
|
||||||
|
// Take starting point for MV search from previous frame.
|
||||||
|
// When temporal motion vector candidates are added, there is probably
|
||||||
|
// no point to this anymore, but for now it helps.
|
||||||
|
int mid_x_cu = (x + (LCU_WIDTH >> (depth+1))) / 8;
|
||||||
|
int mid_y_cu = (y + (LCU_WIDTH >> (depth+1))) / 8;
|
||||||
|
cu_info_t *ref_cu = &state->global->ref->cu_arrays[ref_idx]->data[mid_x_cu + mid_y_cu * (frame->width_in_lcu << MAX_DEPTH)];
|
||||||
|
if (ref_cu->type == CU_INTER) {
|
||||||
|
if (ref_cu->inter.mv_dir & 1) {
|
||||||
|
mv.x = ref_cu->inter.mv[0][0];
|
||||||
|
mv.y = ref_cu->inter.mv[0][1];
|
||||||
|
} else {
|
||||||
|
mv.x = ref_cu->inter.mv[1][0];
|
||||||
|
mv.y = ref_cu->inter.mv[1][1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if SEARCH_MV_FULL_RADIUS
|
||||||
|
temp_cost += search_mv_full(depth, frame, ref_pic, &orig, &mv, mv_cand, merge_cand, num_cand, ref_idx, &temp_bitcost);
|
||||||
|
#else
|
||||||
|
switch (state->encoder_control->cfg->ime_algorithm) {
|
||||||
|
case KVZ_IME_TZ:
|
||||||
|
temp_cost += tz_search(state, depth, frame->source, ref_image, &orig, &mv, mv_cand, merge_cand, num_cand, ref_idx, &temp_bitcost);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
temp_cost += hexagon_search(state, depth, frame->source, ref_image, &orig, &mv, mv_cand, merge_cand, num_cand, ref_idx, &temp_bitcost);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (state->encoder_control->cfg->fme_level > 0) {
|
||||||
|
temp_cost = search_frac(state, depth, frame->source, ref_image, &orig, &mv, mv_cand, merge_cand, num_cand, ref_idx, &temp_bitcost);
|
||||||
|
}
|
||||||
|
|
||||||
|
merged = 0;
|
||||||
|
// Check every candidate to find a match
|
||||||
|
for(merge_idx = 0; merge_idx < num_cand; merge_idx++) {
|
||||||
|
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[merge_cand[merge_idx].dir - 1] == ref_idx) {
|
||||||
|
merged = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only check when candidates are different
|
||||||
|
if (!merged && (mv_cand[0][0] != mv_cand[1][0] || mv_cand[0][1] != mv_cand[1][1])) {
|
||||||
|
vector2d_t mvd_temp1, mvd_temp2;
|
||||||
|
int cand1_cost,cand2_cost;
|
||||||
|
|
||||||
|
mvd_temp1.x = mv.x - mv_cand[0][0];
|
||||||
|
mvd_temp1.y = mv.y - mv_cand[0][1];
|
||||||
|
cand1_cost = get_mvd_cost(&mvd_temp1, (cabac_data_t*)&state->cabac);
|
||||||
|
|
||||||
|
mvd_temp2.x = mv.x - mv_cand[1][0];
|
||||||
|
mvd_temp2.y = mv.y - mv_cand[1][1];
|
||||||
|
cand2_cost = get_mvd_cost(&mvd_temp2, (cabac_data_t*)&state->cabac);
|
||||||
|
|
||||||
|
// Select candidate 1 if it has lower cost
|
||||||
|
if (cand2_cost < cand1_cost) {
|
||||||
|
cu_mv_cand = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mvd.x = mv.x - mv_cand[cu_mv_cand][0];
|
||||||
|
mvd.y = mv.y - mv_cand[cu_mv_cand][1];
|
||||||
|
|
||||||
|
if(temp_cost < cur_cu->inter.cost) {
|
||||||
|
|
||||||
|
// Map reference index to L0/L1 pictures
|
||||||
|
cur_cu->inter.mv_dir = ref_list+1;
|
||||||
|
cur_cu->inter.mv_ref_coded[ref_list] = state->global->refmap[ref_idx].idx;
|
||||||
|
|
||||||
|
cur_cu->merged = merged;
|
||||||
|
cur_cu->merge_idx = merge_idx;
|
||||||
|
cur_cu->inter.mv_ref[ref_list] = ref_idx;
|
||||||
|
cur_cu->inter.mv[ref_list][0] = (int16_t)mv.x;
|
||||||
|
cur_cu->inter.mv[ref_list][1] = (int16_t)mv.y;
|
||||||
|
cur_cu->inter.mvd[ref_list][0] = (int16_t)mvd.x;
|
||||||
|
cur_cu->inter.mvd[ref_list][1] = (int16_t)mvd.y;
|
||||||
|
cur_cu->inter.cost = temp_cost;
|
||||||
|
cur_cu->inter.bitcost = temp_bitcost + cur_cu->inter.mv_dir - 1 + cur_cu->inter.mv_ref_coded[ref_list];
|
||||||
|
cur_cu->inter.mv_cand[ref_list] = cu_mv_cand;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update lcu to have best modes at this depth.
|
* Update lcu to have best modes at this depth.
|
||||||
* \return Cost of best mode.
|
* \return Cost of best mode.
|
||||||
|
@ -961,8 +1082,6 @@ int kvz_search_cu_inter(const encoder_state_t * const state, int x, int y, int d
|
||||||
uint32_t ref_idx = 0;
|
uint32_t ref_idx = 0;
|
||||||
int x_local = SUB_SCU(x);
|
int x_local = SUB_SCU(x);
|
||||||
int y_local = SUB_SCU(y);
|
int y_local = SUB_SCU(y);
|
||||||
int x_cu = x>>3;
|
|
||||||
int y_cu = y>>3;
|
|
||||||
cu_info_t *cur_cu = LCU_GET_CU(lcu, x_local >> 3, y_local >> 3);
|
cu_info_t *cur_cu = LCU_GET_CU(lcu, x_local >> 3, y_local >> 3);
|
||||||
|
|
||||||
int16_t mv_cand[2][2];
|
int16_t mv_cand[2][2];
|
||||||
|
@ -990,108 +1109,12 @@ int kvz_search_cu_inter(const encoder_state_t * const state, int x, int y, int d
|
||||||
cur_cu->inter.cost = UINT_MAX;
|
cur_cu->inter.cost = UINT_MAX;
|
||||||
|
|
||||||
for (ref_idx = 0; ref_idx < state->global->ref->used_size; ref_idx++) {
|
for (ref_idx = 0; ref_idx < state->global->ref->used_size; ref_idx++) {
|
||||||
kvz_picture *ref_image = state->global->ref->images[ref_idx];
|
search_cu_inter_ref(state,
|
||||||
uint32_t temp_bitcost = 0;
|
x, y, depth,
|
||||||
uint32_t temp_cost = 0;
|
lcu, cur_cu,
|
||||||
vector2d_t orig, mvd;
|
mv_cand, merge_cand, num_cand,
|
||||||
int32_t merged = 0;
|
ref_idx,
|
||||||
uint8_t cu_mv_cand = 0;
|
get_mvd_cost);
|
||||||
int8_t merge_idx = 0;
|
|
||||||
int8_t ref_list = state->global->refmap[ref_idx].list-1;
|
|
||||||
int8_t temp_ref_idx = cur_cu->inter.mv_ref[ref_list];
|
|
||||||
orig.x = x_cu * CU_MIN_SIZE_PIXELS;
|
|
||||||
orig.y = y_cu * CU_MIN_SIZE_PIXELS;
|
|
||||||
// Get MV candidates
|
|
||||||
cur_cu->inter.mv_ref[ref_list] = ref_idx;
|
|
||||||
kvz_inter_get_mv_cand(state, x, y, depth, mv_cand, cur_cu, lcu, ref_list);
|
|
||||||
cur_cu->inter.mv_ref[ref_list] = temp_ref_idx;
|
|
||||||
|
|
||||||
vector2d_t mv = { 0, 0 };
|
|
||||||
{
|
|
||||||
// Take starting point for MV search from previous frame.
|
|
||||||
// When temporal motion vector candidates are added, there is probably
|
|
||||||
// no point to this anymore, but for now it helps.
|
|
||||||
int mid_x_cu = (x + (LCU_WIDTH >> (depth+1))) / 8;
|
|
||||||
int mid_y_cu = (y + (LCU_WIDTH >> (depth+1))) / 8;
|
|
||||||
cu_info_t *ref_cu = &state->global->ref->cu_arrays[ref_idx]->data[mid_x_cu + mid_y_cu * (frame->width_in_lcu << MAX_DEPTH)];
|
|
||||||
if (ref_cu->type == CU_INTER) {
|
|
||||||
if (ref_cu->inter.mv_dir & 1) {
|
|
||||||
mv.x = ref_cu->inter.mv[0][0];
|
|
||||||
mv.y = ref_cu->inter.mv[0][1];
|
|
||||||
} else {
|
|
||||||
mv.x = ref_cu->inter.mv[1][0];
|
|
||||||
mv.y = ref_cu->inter.mv[1][1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if SEARCH_MV_FULL_RADIUS
|
|
||||||
temp_cost += search_mv_full(depth, frame, ref_pic, &orig, &mv, mv_cand, merge_cand, num_cand, ref_idx, &temp_bitcost);
|
|
||||||
#else
|
|
||||||
switch (state->encoder_control->cfg->ime_algorithm) {
|
|
||||||
case KVZ_IME_TZ:
|
|
||||||
temp_cost += tz_search(state, depth, frame->source, ref_image, &orig, &mv, mv_cand, merge_cand, num_cand, ref_idx, &temp_bitcost);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
temp_cost += hexagon_search(state, depth, frame->source, ref_image, &orig, &mv, mv_cand, merge_cand, num_cand, ref_idx, &temp_bitcost);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (state->encoder_control->cfg->fme_level > 0) {
|
|
||||||
temp_cost = search_frac(state, depth, frame->source, ref_image, &orig, &mv, mv_cand, merge_cand, num_cand, ref_idx, &temp_bitcost);
|
|
||||||
}
|
|
||||||
|
|
||||||
merged = 0;
|
|
||||||
// Check every candidate to find a match
|
|
||||||
for(merge_idx = 0; merge_idx < num_cand; merge_idx++) {
|
|
||||||
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[merge_cand[merge_idx].dir - 1] == ref_idx) {
|
|
||||||
merged = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only check when candidates are different
|
|
||||||
if (!merged && (mv_cand[0][0] != mv_cand[1][0] || mv_cand[0][1] != mv_cand[1][1])) {
|
|
||||||
vector2d_t mvd_temp1, mvd_temp2;
|
|
||||||
int cand1_cost,cand2_cost;
|
|
||||||
|
|
||||||
mvd_temp1.x = mv.x - mv_cand[0][0];
|
|
||||||
mvd_temp1.y = mv.y - mv_cand[0][1];
|
|
||||||
cand1_cost = get_mvd_cost(&mvd_temp1, (cabac_data_t*)&state->cabac);
|
|
||||||
|
|
||||||
mvd_temp2.x = mv.x - mv_cand[1][0];
|
|
||||||
mvd_temp2.y = mv.y - mv_cand[1][1];
|
|
||||||
cand2_cost = get_mvd_cost(&mvd_temp2, (cabac_data_t*)&state->cabac);
|
|
||||||
|
|
||||||
// Select candidate 1 if it has lower cost
|
|
||||||
if (cand2_cost < cand1_cost) {
|
|
||||||
cu_mv_cand = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mvd.x = mv.x - mv_cand[cu_mv_cand][0];
|
|
||||||
mvd.y = mv.y - mv_cand[cu_mv_cand][1];
|
|
||||||
|
|
||||||
if(temp_cost < cur_cu->inter.cost) {
|
|
||||||
|
|
||||||
// Map reference index to L0/L1 pictures
|
|
||||||
cur_cu->inter.mv_dir = ref_list+1;
|
|
||||||
cur_cu->inter.mv_ref_coded[ref_list] = state->global->refmap[ref_idx].idx;
|
|
||||||
|
|
||||||
cur_cu->merged = merged;
|
|
||||||
cur_cu->merge_idx = merge_idx;
|
|
||||||
cur_cu->inter.mv_ref[ref_list] = ref_idx;
|
|
||||||
cur_cu->inter.mv[ref_list][0] = (int16_t)mv.x;
|
|
||||||
cur_cu->inter.mv[ref_list][1] = (int16_t)mv.y;
|
|
||||||
cur_cu->inter.mvd[ref_list][0] = (int16_t)mvd.x;
|
|
||||||
cur_cu->inter.mvd[ref_list][1] = (int16_t)mvd.y;
|
|
||||||
cur_cu->inter.cost = temp_cost;
|
|
||||||
cur_cu->inter.bitcost = temp_bitcost + cur_cu->inter.mv_dir - 1 + cur_cu->inter.mv_ref_coded[ref_list];
|
|
||||||
cur_cu->inter.mv_cand[ref_list] = cu_mv_cand;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search bi-pred positions
|
// Search bi-pred positions
|
||||||
|
|
Loading…
Reference in a new issue