Changes to refence lists to behave more like L0/L1 lists from the specification

This commit is contained in:
Miika Metsoila 2017-06-26 15:31:57 +03:00
parent 00c9f52bd4
commit f8b6234fdb
10 changed files with 148 additions and 127 deletions

View file

@ -144,7 +144,7 @@ typedef struct
} intra;
struct {
int16_t mv[2][2]; // \brief Motion vectors for L0 and L1
uint8_t mv_ref[2]; // \brief Index of the encoder_control.ref array.
uint8_t mv_ref[2]; // \brief Index of the L0 and L1 array.
uint8_t mv_cand0 : 3; // \brief selected MV candidate
uint8_t mv_cand1 : 3; // \brief selected MV candidate
uint8_t mv_dir : 2; // \brief Probably describes if mv_ref is L0, L1 or both (bi-pred)

View file

@ -551,15 +551,6 @@ static void encode_inter_prediction_unit(encoder_state_t * const state,
}
} else {
uint32_t ref_list_idx;
uint32_t j;
int ref_list[2] = { 0, 0 };
for (j = 0; j < state->frame->ref->used_size; j++) {
if (state->frame->ref->pocs[j] < state->frame->poc) {
ref_list[0]++;
} else {
ref_list[1]++;
}
}
// Void TEncSbac::codeInterDir( TComDataCU* pcCU, UInt uiAbsPartIdx )
if (state->frame->slicetype == KVZ_SLICE_B)
@ -583,16 +574,20 @@ static void encode_inter_prediction_unit(encoder_state_t * const state,
for (ref_list_idx = 0; ref_list_idx < 2; ref_list_idx++) {
if (cur_cu->inter.mv_dir & (1 << ref_list_idx)) {
if (ref_list[ref_list_idx] > 1) {
// size of the current reference index list (L0/L1)
uint8_t ref_LX_size = state->frame->ref_LX_size[ref_list_idx];
if (ref_LX_size > 1) {
// parseRefFrmIdx
int32_t ref_frame = state->frame->refmap[cur_cu->inter.mv_ref[ref_list_idx]].idx;
int32_t ref_frame = cur_cu->inter.mv_ref[ref_list_idx];
cabac->cur_ctx = &(cabac->ctx.cu_ref_pic_model[0]);
CABAC_BIN(cabac, (ref_frame != 0), "ref_idx_lX");
if (ref_frame > 0) {
int32_t i;
int32_t ref_num = ref_list[ref_list_idx] - 2;
int32_t ref_num = ref_LX_size - 2;
cabac->cur_ctx = &(cabac->ctx.cu_ref_pic_model[1]);
ref_frame--;

View file

@ -787,81 +787,51 @@ static void encoder_state_encode(encoder_state_t * const main_state) {
}
static void encoder_ref_insertion_sort(int reflist[16], int length) {
static void encoder_ref_insertion_sort(const encoder_state_t *const state, uint8_t reflist[16], uint8_t length) {
for (uint8_t i = 1; i < length; ++i) {
const int16_t cur_poc = reflist[i];
int16_t j = i;
while (j > 0 && cur_poc < reflist[j - 1]) {
const int32_t cur_poc = state->frame->ref->pocs[reflist[i]];
uint8_t cur_idx = reflist[i];
int8_t j = i;
while (j > 0 && cur_poc < state->frame->ref->pocs[reflist[j - 1]]) {
reflist[j] = reflist[j - 1];
--j;
}
reflist[j] = cur_poc;
reflist[j] = cur_idx;
}
}
/**
* \brief Return reference picture lists.
* \brief Generate reference picture lists.
*
* \param state main encoder state
* \param ref_list_len_out Returns the lengths of the reference lists.
* \param ref_list_poc_out Returns two lists of POCs of the reference pictures.
*/
void kvz_encoder_get_ref_lists(const encoder_state_t *const state,
int ref_list_len_out[2],
int ref_list_poc_out[2][16])
void kvz_encoder_create_ref_lists(const encoder_state_t *const state)
{
FILL_ARRAY(ref_list_len_out, 0, 2);
// TODO check possibility to add L0 references to L1 list also
FILL_ARRAY(state->frame->ref_LX_size, 0, 2);
// List all pocs of lists
int j = 0;
for (j = 0; j < state->frame->ref->used_size; j++) {
if (state->frame->ref->pocs[j] < state->frame->poc) {
ref_list_poc_out[0][ref_list_len_out[0]] = state->frame->ref->pocs[j];
ref_list_len_out[0]++;
state->frame->ref_LX[0][state->frame->ref_LX_size[0]] = state->frame->ref->pocs[j];
state->frame->ref_LX_size[0] += 1;
} else {
ref_list_poc_out[1][ref_list_len_out[1]] = state->frame->ref->pocs[j];
ref_list_len_out[1]++;
state->frame->ref_LX[1][state->frame->ref_LX_size[1]] = state->frame->ref->pocs[j];
state->frame->ref_LX_size[1] += 1;
}
}
// Fill the rest of ref_list_poc_out array with -1s.
for (; j < 16; j++) {
ref_list_poc_out[0][j] = -1;
ref_list_poc_out[1][j] = -1;
state->frame->ref_LX[0][j] = (uint8_t) -1;
state->frame->ref_LX[1][j] = (uint8_t) -1;
}
encoder_ref_insertion_sort(ref_list_poc_out[0], ref_list_len_out[0]);
encoder_ref_insertion_sort(ref_list_poc_out[1], ref_list_len_out[1]);
}
static void encoder_state_ref_sort(encoder_state_t *state) {
int ref_list_len[2];
int ref_list_poc[2][16];
kvz_encoder_get_ref_lists(state, ref_list_len, ref_list_poc);
for (int j = 0; j < state->frame->ref->used_size; j++) {
if (state->frame->ref->pocs[j] < state->frame->poc) {
for (int ref_idx = 0; ref_idx < ref_list_len[0]; ref_idx++) {
if (ref_list_poc[0][ref_idx] == state->frame->ref->pocs[j]) {
state->frame->refmap[j].idx = ref_list_len[0] - ref_idx - 1;
break;
}
}
state->frame->refmap[j].list = 1;
} else {
for (int ref_idx = 0; ref_idx < ref_list_len[1]; ref_idx++) {
if (ref_list_poc[1][ref_idx] == state->frame->ref->pocs[j]) {
state->frame->refmap[j].idx = ref_idx;
break;
}
}
state->frame->refmap[j].list = 2;
}
state->frame->refmap[j].poc = state->frame->ref->pocs[j];
}
encoder_ref_insertion_sort(state, state->frame->ref_LX[0], state->frame->ref_LX_size[0]);
encoder_ref_insertion_sort(state, state->frame->ref_LX[1], state->frame->ref_LX_size[1]);
}
/**
@ -1037,7 +1007,7 @@ static void encoder_state_init_new_frame(encoder_state_t * const state, kvz_pict
}
encoder_state_remove_refs(state);
encoder_state_ref_sort(state);
kvz_encoder_create_ref_lists(state);
normalize_lcu_weights(state);
kvz_set_picture_lambda_and_qp(state);

View file

@ -91,15 +91,14 @@ typedef struct encoder_state_config_frame_t {
//! \brief quantization factor
double QP_factor;
//Current picture available references
//! Current pictures available for references
image_list_t *ref;
int8_t ref_list;
struct {
int32_t poc;
int8_t list;
int8_t idx;
} refmap[16];
//! L0 and L1 reference index list
uint8_t ref_LX[2][16];
//! L0 reference index list size
uint8_t ref_LX_size[2];
bool is_idr_frame;
uint8_t pictype;
@ -282,9 +281,7 @@ int kvz_encoder_state_match_children_of_previous_frame(encoder_state_t * const s
coeff_scan_order_t kvz_get_scan_order(int8_t cu_type, int intra_mode, int depth);
void kvz_encoder_get_ref_lists(const encoder_state_t *const state,
int ref_list_len_out[2],
int ref_list_poc_out[2][16]);
void kvz_encoder_create_ref_lists(const encoder_state_t *const state);
lcu_stats_t* kvz_get_lcu_stats(encoder_state_t *state, int lcu_x, int lcu_y);

View file

@ -401,10 +401,13 @@ static void filter_deblock_edge_luma(encoder_state_t * const state,
// Non-zero residual/coeffs and transform boundary
// Neither CU is intra so tr_depth <= MAX_DEPTH.
strength = 1;
} else if (cu_p->inter.mv_dir != 3 && cu_q->inter.mv_dir != 3 && ((abs(cu_q->inter.mv[cu_q->inter.mv_dir - 1][0] - cu_p->inter.mv[cu_p->inter.mv_dir - 1][0]) >= 4) || (abs(cu_q->inter.mv[cu_q->inter.mv_dir - 1][1] - cu_p->inter.mv[cu_p->inter.mv_dir - 1][1]) >= 4))) {
} else if (cu_p->inter.mv_dir != 3 && cu_q->inter.mv_dir != 3 &&
((abs(cu_q->inter.mv[cu_q->inter.mv_dir - 1][0] - cu_p->inter.mv[cu_p->inter.mv_dir - 1][0]) >= 4) ||
(abs(cu_q->inter.mv[cu_q->inter.mv_dir - 1][1] - cu_p->inter.mv[cu_p->inter.mv_dir - 1][1]) >= 4))) {
// Absolute motion vector diff between blocks >= 1 (Integer pixel)
strength = 1;
} else if (cu_p->inter.mv_dir != 3 && cu_q->inter.mv_dir != 3 && cu_q->inter.mv_ref[cu_q->inter.mv_dir - 1] != cu_p->inter.mv_ref[cu_p->inter.mv_dir - 1]) {
} else if (cu_p->inter.mv_dir != 3 && cu_q->inter.mv_dir != 3 &&
cu_q->inter.mv_ref[cu_q->inter.mv_dir - 1] != cu_p->inter.mv_ref[cu_p->inter.mv_dir - 1]) {
strength = 1;
}
@ -429,10 +432,10 @@ static void filter_deblock_edge_luma(encoder_state_t * const state,
cu_p->inter.mv[1][0] = 0;
cu_p->inter.mv[1][1] = 0;
}
const int refP0 = (cu_p->inter.mv_dir & 1) ? cu_p->inter.mv_ref[0] : -1;
const int refP1 = (cu_p->inter.mv_dir & 2) ? cu_p->inter.mv_ref[1] : -1;
const int refQ0 = (cu_q->inter.mv_dir & 1) ? cu_q->inter.mv_ref[0] : -1;
const int refQ1 = (cu_q->inter.mv_dir & 2) ? cu_q->inter.mv_ref[1] : -1;
const int refP0 = (cu_p->inter.mv_dir & 1) ? state->frame->ref_LX[0][cu_p->inter.mv_ref[0]] : -1;
const int refP1 = (cu_p->inter.mv_dir & 2) ? state->frame->ref_LX[1][cu_p->inter.mv_ref[1]] : -1;
const int refQ0 = (cu_q->inter.mv_dir & 1) ? state->frame->ref_LX[0][cu_q->inter.mv_ref[0]] : -1;
const int refQ1 = (cu_q->inter.mv_dir & 2) ? state->frame->ref_LX[1][cu_q->inter.mv_ref[1]] : -1;
const int16_t* mvQ0 = cu_q->inter.mv[0];
const int16_t* mvQ1 = cu_q->inter.mv[1];

View file

@ -652,11 +652,13 @@ static bool is_b0_cand_coded(int x, int y, int width, int height)
/**
* \brief Get merge candidates for current block
*
* \param encoder encoder control struct to use
* \param state encoder control state to use
* \param x block x position in SCU
* \param y block y position in SCU
* \param width current block width
* \param height current block height
* \param ref_list which reference list, L0 is 1 and L1 is 2
* \param ref_idx index in the reference list
* \param cand_out will be filled with C3 and H candidates
*/
static void get_temporal_merge_candidates(const encoder_state_t * const state,
@ -682,17 +684,15 @@ static void get_temporal_merge_candidates(const encoder_state_t * const state,
// Find temporal reference
if (state->frame->ref->used_size) {
uint32_t colocated_ref = UINT_MAX;
uint32_t colocated_ref;
// Select L0/L1 ref_idx reference
for (int temporal_cand = 0; temporal_cand < state->frame->ref->used_size; temporal_cand++) {
if (state->frame->refmap[temporal_cand].list == ref_list && state->frame->refmap[temporal_cand].idx == ref_idx) {
colocated_ref = temporal_cand;
break;
}
if (state->frame->ref_LX_size[ref_list-1] > ref_idx) {
colocated_ref = state->frame->ref_LX[ref_list - 1][ref_idx];
} else {
// not found
return;
}
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;
@ -938,9 +938,13 @@ static INLINE void apply_mv_scaling(const encoder_state_t *state,
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->ref->pocs[
state->frame->ref_LX[current_reflist][
current_cu->inter.mv_ref[current_reflist]]],
state->frame->poc,
state->frame->ref->pocs[neighbor_cu->inter.mv_ref[neighbor_reflist]],
state->frame->ref->pocs[
state->frame->ref_LX[current_reflist][
neighbor_cu->inter.mv_ref[neighbor_reflist]]],
mv_cand);
}
@ -966,23 +970,21 @@ static bool add_temporal_candidate(const encoder_state_t *state,
{
if (!colocated) return false;
int colocated_ref = -1;
for (int i = 0; i < state->frame->ref->used_size; i++) {
if (state->frame->refmap[i].list == 1 &&
state->frame->refmap[i].idx == 0) {
colocated_ref = i;
break;
}
int colocated_ref;
if (state->frame->ref_LX_size[0] > 0) {
// get the first reference from L0 if it exists
colocated_ref = state->frame->ref_LX[0][0];
} else {
// otherwise no candidate added
return false;
}
if (colocated_ref < 0) return false;
int cand_list = colocated->inter.mv_dir & (1 << reflist) ? reflist : !reflist;
// The reference id the colocated block is using
uint32_t colocated_ref_mv_ref = colocated->inter.mv_ref[cand_list];
uint32_t colocated_ref_mv_ref = state->frame->ref_LX[cand_list][colocated->inter.mv_ref[cand_list]];
if (ref_out) *ref_out = colocated_ref;
if (ref_out) *ref_out = 0; //colocated_ref;
mv_out[0] = colocated->inter.mv[cand_list][0];
mv_out[1] = colocated->inter.mv[cand_list][1];
@ -1105,7 +1107,7 @@ static void get_mv_cand_from_candidates(const encoder_state_t * const state,
(h != NULL || c3 != NULL);
if (can_use_tmvp && add_temporal_candidate(state,
cur_cu->inter.mv_ref[reflist],
state->frame->ref_LX[reflist][cur_cu->inter.mv_ref[reflist]],
(h != NULL) ? h : c3,
reflist,
mv_cand[candidates],
@ -1220,7 +1222,7 @@ static bool add_merge_candidate(const cu_info_t *cand,
merge_cand_out->mv[0][1] = cand->inter.mv[0][1];
merge_cand_out->mv[1][0] = cand->inter.mv[1][0];
merge_cand_out->mv[1][1] = cand->inter.mv[1][1];
merge_cand_out->ref[0] = cand->inter.mv_ref[0];
merge_cand_out->ref[0] = cand->inter.mv_ref[0]; // L0/L1 references
merge_cand_out->ref[1] = cand->inter.mv_ref[1];
merge_cand_out->dir = cand->inter.mv_dir;
return true;
@ -1325,9 +1327,11 @@ uint8_t kvz_inter_get_merge_cand(const encoder_state_t * const state,
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] &&
mv_cand[i].mv[0][1] == mv_cand[j].mv[1][1]) {
if (state->frame->ref_LX[0][mv_cand[i].ref[0]] ==
state->frame->ref_LX[1][mv_cand[j].ref[1]]
&&
mv_cand[i].mv[0][0] == mv_cand[j].mv[1][0] &&
mv_cand[i].mv[0][1] == mv_cand[j].mv[1][1]) {
// Not a candidate
} else {
candidates++;

View file

@ -141,7 +141,12 @@ static void set_frame_info(kvz_frame_info *const info, const encoder_state_t *co
info->qp = state->frame->QP;
info->nal_unit_type = state->frame->pictype;
info->slice_type = state->frame->slicetype;
kvz_encoder_get_ref_lists(state, info->ref_list_len, info->ref_list);
memcpy(info->ref_list[0], state->frame->ref_LX[0], 16);
memcpy(info->ref_list[1], state->frame->ref_LX[1], 16);
info->ref_list_len[0] = state->frame->ref_LX_size[0];
info->ref_list_len[1] = state->frame->ref_LX_size[1];
//kvz_encoder_create_ref_lists(state);
}

View file

@ -915,7 +915,10 @@ int kvz_calc_mvd_cost_cabac(encoder_state_t * const state, int x, int y, int mv_
if (merge_cand[merge_idx].dir == 3) continue;
if (merge_cand[merge_idx].mv[merge_cand[merge_idx].dir - 1][0] == x &&
merge_cand[merge_idx].mv[merge_cand[merge_idx].dir - 1][1] == y &&
merge_cand[merge_idx].ref[merge_cand[merge_idx].dir - 1] == ref_idx) {
state->frame->ref_LX[merge_cand[merge_idx].dir - 1][
merge_cand[merge_idx].ref[merge_cand[merge_idx].dir - 1]
] == ref_idx)
{
merged = 1;
break;
}

View file

@ -553,8 +553,12 @@ static double search_cu(encoder_state_t * const state, int x, int y, int depth,
if (cur_pu->inter.mv_dir == 3) {
const kvz_picture *const refs[2] = {
state->frame->ref->images[cur_pu->inter.mv_ref[0]],
state->frame->ref->images[cur_pu->inter.mv_ref[1]],
state->frame->ref->images[
state->frame->ref_LX[0][
cur_pu->inter.mv_ref[0]]],
state->frame->ref->images[
state->frame->ref_LX[1][
cur_pu->inter.mv_ref[1]]],
};
kvz_inter_recon_lcu_bipred(state,
refs[0], refs[1],
@ -564,8 +568,12 @@ static double search_cu(encoder_state_t * const state, int x, int y, int depth,
lcu);
} else {
const int mv_idx = cur_pu->inter.mv_dir - 1;
const kvz_picture *const ref =
state->frame->ref->images[cur_pu->inter.mv_ref[mv_idx]];
state->frame->ref->images[
state->frame->ref_LX[mv_idx][
cur_pu->inter.mv_ref[mv_idx]]];
kvz_inter_recon_lcu(state,
ref,
pu_x, pu_y,

View file

@ -229,7 +229,9 @@ static int calc_mvd_cost(encoder_state_t * const state, int x, int y, int mv_shi
if (merge_cand[merge_idx].dir == 3) continue;
if (merge_cand[merge_idx].mv[merge_cand[merge_idx].dir - 1][0] == x &&
merge_cand[merge_idx].mv[merge_cand[merge_idx].dir - 1][1] == y &&
merge_cand[merge_idx].ref[merge_cand[merge_idx].dir - 1] == ref_idx) {
state->frame->ref_LX[merge_cand[merge_idx].dir - 1][
merge_cand[merge_idx].ref[merge_cand[merge_idx].dir - 1]
] == ref_idx) {
temp_bitcost += merge_idx;
merged = 1;
break;
@ -1241,10 +1243,37 @@ static void search_pu_inter_ref(encoder_state_t * const state,
int32_t merged = 0;
uint8_t cu_mv_cand = 0;
int8_t merge_idx = 0;
int8_t ref_list = state->frame->refmap[ref_idx].list-1;
// which list, L0 or L1, ref_idx is in and in what index
int8_t ref_list = -1;
// the index of the ref_idx in L0 or L1 list
int8_t LX_idx;
// max value of LX_idx plus one
const int8_t LX_IDX_MAX_PLUS_1 = max(state->frame->ref_LX_size[0],
state->frame->ref_LX_size[1]);
for (LX_idx = 0; LX_idx < LX_IDX_MAX_PLUS_1; LX_idx++)
{
// check if ref_idx is in L0
if (LX_idx < state->frame->ref_LX_size[0] &&
state->frame->ref_LX[0][LX_idx] == ref_idx) {
ref_list = 0;
break;
}
// check if ref_idx is in L1
if (LX_idx < state->frame->ref_LX_size[1] &&
state->frame->ref_LX[1][LX_idx] == ref_idx) {
ref_list = 1;
break;
}
}
// ref_idx has to be found in either L0 or L1
assert(LX_idx < LX_IDX_MAX_PLUS_1);
int8_t temp_ref_idx = cur_cu->inter.mv_ref[ref_list];
// Get MV candidates
cur_cu->inter.mv_ref[ref_list] = ref_idx;
cur_cu->inter.mv_ref[ref_list] = LX_idx;
kvz_inter_get_mv_cand(state, x, y, width, height, mv_cand, cur_cu, lcu, ref_list);
cur_cu->inter.mv_ref[ref_list] = temp_ref_idx;
@ -1352,7 +1381,8 @@ static void search_pu_inter_ref(encoder_state_t * const state,
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) {
(uint32_t)state->frame->ref_LX[merge_cand[merge_idx].dir - 1][
merge_cand[merge_idx].ref[merge_cand[merge_idx].dir - 1]] == ref_idx) {
merged = 1;
break;
}
@ -1380,11 +1410,11 @@ static void search_pu_inter_ref(encoder_state_t * const state,
if (temp_cost < *inter_cost) {
// Map reference index to L0/L1 pictures
cur_cu->inter.mv_dir = ref_list+1;
uint8_t mv_ref_coded = state->frame->refmap[ref_idx].idx;
uint8_t mv_ref_coded = LX_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[ref_list] = LX_idx;
cur_cu->inter.mv[ref_list][0] = (int16_t)mv.x;
cur_cu->inter.mv[ref_list][1] = (int16_t)mv.y;
CU_SET_MV_CAND(cur_cu, ref_list, cu_mv_cand);
@ -1512,17 +1542,18 @@ static void search_pu_inter(encoder_state_t * const state,
// Find one L0 and L1 candidate according to the priority list
if ((merge_cand[i].dir & 0x1) && (merge_cand[j].dir & 0x2)) {
if (merge_cand[i].ref[0] != merge_cand[j].ref[1] ||
merge_cand[i].mv[0][0] != merge_cand[j].mv[1][0] ||
merge_cand[i].mv[0][1] != merge_cand[j].mv[1][1]) {
if (state->frame->ref_LX[0][merge_cand[i].ref[0]] !=
state->frame->ref_LX[1][merge_cand[j].ref[1]] ||
merge_cand[i].mv[0][0] != merge_cand[j].mv[1][0] ||
merge_cand[i].mv[0][1] != merge_cand[j].mv[1][1])
{
uint32_t bitcost[2];
uint32_t cost = 0;
int8_t cu_mv_cand = 0;
int16_t mv[2][2];
kvz_pixel tmp_block[64 * 64];
kvz_pixel tmp_pic[64 * 64];
// Force L0 and L1 references
if (state->frame->refmap[merge_cand[i].ref[0]].list == 2 || state->frame->refmap[merge_cand[j].ref[1]].list == 1) continue;
mv[0][0] = merge_cand[i].mv[0][0];
mv[0][1] = merge_cand[i].mv[0][1];
@ -1540,8 +1571,12 @@ static void search_pu_inter(encoder_state_t * const state,
}
kvz_inter_recon_lcu_bipred(state,
state->frame->ref->images[merge_cand[i].ref[0]],
state->frame->ref->images[merge_cand[j].ref[1]],
state->frame->ref->images[
state->frame->ref_LX[0][merge_cand[i].ref[0]]
],
state->frame->ref->images[
state->frame->ref_LX[1][merge_cand[j].ref[1]]
],
x, y,
width,
height,
@ -1566,8 +1601,8 @@ static void search_pu_inter(encoder_state_t * const state,
cur_cu->inter.mv_dir = 3;
uint8_t mv_ref_coded[2] = {
state->frame->refmap[merge_cand[i].ref[0]].idx,
state->frame->refmap[merge_cand[j].ref[1]].idx
state->frame->ref_LX[0][merge_cand[i].ref[0]],
state->frame->ref_LX[1][merge_cand[j].ref[1]]
};
cur_cu->inter.mv_ref[0] = merge_cand[i].ref[0];
@ -1586,8 +1621,9 @@ static void search_pu_inter(encoder_state_t * const state,
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]) {
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;