mirror of
https://github.com/ultravideo/uvg266.git
synced 2024-12-18 03:04:06 +00:00
Merge branch 'zero-coeff-check'
This commit is contained in:
commit
75a8700630
93
src/inter.c
93
src/inter.c
|
@ -306,19 +306,19 @@ static void inter_cp_with_ext_border(const kvz_pixel *ref_buf, int ref_stride,
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Reconstruct inter block
|
* \brief Reconstruct an inter PU using uniprediction.
|
||||||
*
|
*
|
||||||
* \param state encoder state
|
* \param state encoder state
|
||||||
* \param ref picture to copy the data from
|
* \param ref picture to copy the data from
|
||||||
* \param xpos block x position
|
* \param xpos PU x position
|
||||||
* \param ypos block y position
|
* \param ypos PU y position
|
||||||
* \param width block width
|
* \param width PU width
|
||||||
* \param height block height
|
* \param height PU height
|
||||||
* \param mv_param motion vector
|
* \param mv_param motion vector
|
||||||
* \param lcu destination lcu
|
* \param lcu destination lcu
|
||||||
* \param hi_prec_out destination of high precision output (null if not needed)
|
* \param hi_prec_out destination of high precision output, or NULL if not needed
|
||||||
*/
|
*/
|
||||||
void kvz_inter_recon_lcu(const encoder_state_t * const state,
|
static void inter_recon_unipred(const encoder_state_t * const state,
|
||||||
const kvz_picture * const ref,
|
const kvz_picture * const ref,
|
||||||
int32_t xpos,
|
int32_t xpos,
|
||||||
int32_t ypos,
|
int32_t ypos,
|
||||||
|
@ -428,19 +428,19 @@ void kvz_inter_recon_lcu(const encoder_state_t * const state,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Reconstruct bi-pred inter block
|
* \brief Reconstruct bi-pred inter PU
|
||||||
*
|
*
|
||||||
* \param state encoder state
|
* \param state encoder state
|
||||||
* \param ref1 reference picture to copy the data from
|
* \param ref1 reference picture to copy the data from
|
||||||
* \param ref2 other reference picture to copy the data from
|
* \param ref2 other reference picture to copy the data from
|
||||||
* \param xpos block x position
|
* \param xpos PU x position
|
||||||
* \param ypos block y position
|
* \param ypos PU y position
|
||||||
* \param width block width
|
* \param width PU width
|
||||||
* \param height block height
|
* \param height PU height
|
||||||
* \param mv_param motion vectors
|
* \param mv_param motion vectors
|
||||||
* \param lcu destination lcu
|
* \param lcu destination lcu
|
||||||
*/
|
*/
|
||||||
void kvz_inter_recon_lcu_bipred(const encoder_state_t * const state,
|
void kvz_inter_recon_bipred(const encoder_state_t * const state,
|
||||||
const kvz_picture * ref1,
|
const kvz_picture * ref1,
|
||||||
const kvz_picture * ref2,
|
const kvz_picture * ref2,
|
||||||
int32_t xpos,
|
int32_t xpos,
|
||||||
|
@ -468,7 +468,7 @@ void kvz_inter_recon_lcu_bipred(const encoder_state_t * const state,
|
||||||
if (hi_prec_chroma_rec0) high_precision_rec0 = kvz_hi_prec_buf_t_alloc(LCU_WIDTH*LCU_WIDTH);
|
if (hi_prec_chroma_rec0) high_precision_rec0 = kvz_hi_prec_buf_t_alloc(LCU_WIDTH*LCU_WIDTH);
|
||||||
if (hi_prec_chroma_rec1) high_precision_rec1 = kvz_hi_prec_buf_t_alloc(LCU_WIDTH*LCU_WIDTH);
|
if (hi_prec_chroma_rec1) high_precision_rec1 = kvz_hi_prec_buf_t_alloc(LCU_WIDTH*LCU_WIDTH);
|
||||||
//Reconstruct both predictors
|
//Reconstruct both predictors
|
||||||
kvz_inter_recon_lcu(state, ref1, xpos, ypos, width, height, mv_param[0], lcu, high_precision_rec0);
|
inter_recon_unipred(state, ref1, xpos, ypos, width, height, mv_param[0], lcu, high_precision_rec0);
|
||||||
if (!hi_prec_luma_rec0){
|
if (!hi_prec_luma_rec0){
|
||||||
memcpy(temp_lcu_y, lcu->rec.y, sizeof(kvz_pixel) * 64 * 64);
|
memcpy(temp_lcu_y, lcu->rec.y, sizeof(kvz_pixel) * 64 * 64);
|
||||||
}
|
}
|
||||||
|
@ -476,7 +476,7 @@ void kvz_inter_recon_lcu_bipred(const encoder_state_t * const state,
|
||||||
memcpy(temp_lcu_u, lcu->rec.u, sizeof(kvz_pixel) * 32 * 32);
|
memcpy(temp_lcu_u, lcu->rec.u, sizeof(kvz_pixel) * 32 * 32);
|
||||||
memcpy(temp_lcu_v, lcu->rec.v, sizeof(kvz_pixel) * 32 * 32);
|
memcpy(temp_lcu_v, lcu->rec.v, sizeof(kvz_pixel) * 32 * 32);
|
||||||
}
|
}
|
||||||
kvz_inter_recon_lcu(state, ref2, xpos, ypos, width, height, mv_param[1], lcu, high_precision_rec1);
|
inter_recon_unipred(state, ref2, xpos, ypos, width, height, mv_param[1], lcu, high_precision_rec1);
|
||||||
|
|
||||||
// After reconstruction, merge the predictors by taking an average of each pixel
|
// After reconstruction, merge the predictors by taking an average of each pixel
|
||||||
for (temp_y = 0; temp_y < height; ++temp_y) {
|
for (temp_y = 0; temp_y < height; ++temp_y) {
|
||||||
|
@ -506,6 +506,69 @@ void kvz_inter_recon_lcu_bipred(const encoder_state_t * const state,
|
||||||
if (high_precision_rec1 != 0) kvz_hi_prec_buf_t_free(high_precision_rec1);
|
if (high_precision_rec1 != 0) kvz_hi_prec_buf_t_free(high_precision_rec1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reconstruct a single CU.
|
||||||
|
*
|
||||||
|
* The CU may consist of multiple PUs, each of which can use either
|
||||||
|
* uniprediction or biprediction.
|
||||||
|
*
|
||||||
|
* \param state encoder state
|
||||||
|
* \param lcu containing LCU
|
||||||
|
* \param x x-coordinate of the CU in pixels
|
||||||
|
* \param y y-coordinate of the CU in pixels
|
||||||
|
* \param width CU width
|
||||||
|
*/
|
||||||
|
void kvz_inter_recon_cu(const encoder_state_t * const state,
|
||||||
|
lcu_t *lcu,
|
||||||
|
int32_t x,
|
||||||
|
int32_t y,
|
||||||
|
int32_t width)
|
||||||
|
{
|
||||||
|
cu_info_t *cu = LCU_GET_CU_AT_PX(lcu, SUB_SCU(x), SUB_SCU(y));
|
||||||
|
|
||||||
|
const int num_pu = kvz_part_mode_num_parts[cu->part_size];
|
||||||
|
for (int i = 0; i < num_pu; ++i) {
|
||||||
|
const int pu_x = PU_GET_X(cu->part_size, width, x, i);
|
||||||
|
const int pu_y = PU_GET_Y(cu->part_size, width, y, i);
|
||||||
|
const int pu_w = PU_GET_W(cu->part_size, width, i);
|
||||||
|
const int pu_h = PU_GET_H(cu->part_size, width, i);
|
||||||
|
|
||||||
|
cu_info_t *pu = LCU_GET_CU_AT_PX(lcu, SUB_SCU(pu_x), SUB_SCU(pu_y));
|
||||||
|
|
||||||
|
if (pu->inter.mv_dir == 3) {
|
||||||
|
const kvz_picture *const refs[2] = {
|
||||||
|
state->frame->ref->images[
|
||||||
|
state->frame->ref_LX[0][
|
||||||
|
pu->inter.mv_ref[0]]],
|
||||||
|
state->frame->ref->images[
|
||||||
|
state->frame->ref_LX[1][
|
||||||
|
pu->inter.mv_ref[1]]],
|
||||||
|
};
|
||||||
|
kvz_inter_recon_bipred(state,
|
||||||
|
refs[0], refs[1],
|
||||||
|
pu_x, pu_y,
|
||||||
|
pu_w, pu_h,
|
||||||
|
pu->inter.mv,
|
||||||
|
lcu);
|
||||||
|
} else {
|
||||||
|
const int mv_idx = pu->inter.mv_dir - 1;
|
||||||
|
const kvz_picture *const ref =
|
||||||
|
state->frame->ref->images[
|
||||||
|
state->frame->ref_LX[mv_idx][
|
||||||
|
pu->inter.mv_ref[mv_idx]]];
|
||||||
|
|
||||||
|
inter_recon_unipred(state,
|
||||||
|
ref,
|
||||||
|
pu_x, pu_y,
|
||||||
|
pu_w, pu_h,
|
||||||
|
pu->inter.mv[mv_idx],
|
||||||
|
lcu,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Clear unused L0/L1 motion vectors and reference
|
* \brief Clear unused L0/L1 motion vectors and reference
|
||||||
* \param cu coding unit to clear
|
* \param cu coding unit to clear
|
||||||
|
|
17
src/inter.h
17
src/inter.h
|
@ -40,18 +40,13 @@ typedef struct {
|
||||||
|
|
||||||
} inter_merge_cand_t;
|
} inter_merge_cand_t;
|
||||||
|
|
||||||
|
void kvz_inter_recon_cu(const encoder_state_t * const state,
|
||||||
|
lcu_t *lcu,
|
||||||
|
int32_t x,
|
||||||
|
int32_t y,
|
||||||
|
int32_t width);
|
||||||
|
|
||||||
void kvz_inter_recon_lcu(const encoder_state_t * const state,
|
void kvz_inter_recon_bipred(const encoder_state_t * const state,
|
||||||
const kvz_picture * ref,
|
|
||||||
int32_t xpos,
|
|
||||||
int32_t ypos,
|
|
||||||
int32_t width,
|
|
||||||
int32_t height,
|
|
||||||
const int16_t mv_param[2],
|
|
||||||
lcu_t* lcu,
|
|
||||||
hi_prec_buf_t *hi_prec_out);
|
|
||||||
|
|
||||||
void kvz_inter_recon_lcu_bipred(const encoder_state_t * const state,
|
|
||||||
const kvz_picture * ref1,
|
const kvz_picture * ref1,
|
||||||
const kvz_picture * ref2,
|
const kvz_picture * ref2,
|
||||||
int32_t xpos,
|
int32_t xpos,
|
||||||
|
|
83
src/search.c
83
src/search.c
|
@ -392,6 +392,7 @@ static double search_cu(encoder_state_t * const state, int x, int y, int depth,
|
||||||
const videoframe_t * const frame = state->tile->frame;
|
const videoframe_t * const frame = state->tile->frame;
|
||||||
int cu_width = LCU_WIDTH >> depth;
|
int cu_width = LCU_WIDTH >> depth;
|
||||||
double cost = MAX_INT;
|
double cost = MAX_INT;
|
||||||
|
double inter_zero_coeff_cost = MAX_INT;
|
||||||
uint32_t inter_bitcost = MAX_INT;
|
uint32_t inter_bitcost = MAX_INT;
|
||||||
cu_info_t *cur_cu;
|
cu_info_t *cur_cu;
|
||||||
|
|
||||||
|
@ -518,7 +519,7 @@ static double search_cu(encoder_state_t * const state, int x, int y, int depth,
|
||||||
// rd2. Possibly because the luma mode search already takes chroma
|
// rd2. Possibly because the luma mode search already takes chroma
|
||||||
// into account, so there is less of a chanse of luma mode being
|
// into account, so there is less of a chanse of luma mode being
|
||||||
// really bad for chroma.
|
// really bad for chroma.
|
||||||
if (state->encoder_control->cfg.rdo == 3) {
|
if (ctrl->cfg.rdo == 3) {
|
||||||
cur_cu->intra.mode_chroma = kvz_search_cu_intra_chroma(state, x, y, depth, lcu);
|
cur_cu->intra.mode_chroma = kvz_search_cu_intra_chroma(state, x, y, depth, lcu);
|
||||||
lcu_fill_cu_info(lcu, x_local, y_local, cu_width, cu_width, cur_cu);
|
lcu_fill_cu_info(lcu, x_local, y_local, cu_width, cu_width, cur_cu);
|
||||||
}
|
}
|
||||||
|
@ -538,46 +539,30 @@ static double search_cu(encoder_state_t * const state, int x, int y, int depth,
|
||||||
}
|
}
|
||||||
kvz_lcu_set_trdepth(lcu, x, y, depth, tr_depth);
|
kvz_lcu_set_trdepth(lcu, x, y, depth, tr_depth);
|
||||||
|
|
||||||
const int num_pu = kvz_part_mode_num_parts[cur_cu->part_size];
|
kvz_inter_recon_cu(state, lcu, x, y, cu_width);
|
||||||
for (int i = 0; i < num_pu; ++i) {
|
|
||||||
const int pu_x = PU_GET_X(cur_cu->part_size, cu_width, x, i);
|
|
||||||
const int pu_y = PU_GET_Y(cur_cu->part_size, cu_width, y, i);
|
|
||||||
const int pu_w = PU_GET_W(cur_cu->part_size, cu_width, i);
|
|
||||||
const int pu_h = PU_GET_H(cur_cu->part_size, cu_width, i);
|
|
||||||
|
|
||||||
cu_info_t *cur_pu = LCU_GET_CU_AT_PX(lcu, SUB_SCU(pu_x), SUB_SCU(pu_y));
|
if (!ctrl->cfg.lossless && !ctrl->cfg.rdoq_enable) {
|
||||||
|
const int luma_index = y_local * LCU_WIDTH + x_local;
|
||||||
|
const int chroma_index = (y_local / 2) * LCU_WIDTH_C + (x_local / 2);
|
||||||
|
|
||||||
if (cur_pu->inter.mv_dir == 3) {
|
double ssd = 0.0;
|
||||||
const kvz_picture *const refs[2] = {
|
ssd += LUMA_MULT * kvz_pixels_calc_ssd(
|
||||||
state->frame->ref->images[
|
&lcu->ref.y[luma_index], &lcu->rec.y[luma_index],
|
||||||
state->frame->ref_LX[0][
|
LCU_WIDTH, LCU_WIDTH, cu_width
|
||||||
cur_pu->inter.mv_ref[0]]],
|
);
|
||||||
state->frame->ref->images[
|
ssd += CHROMA_MULT * kvz_pixels_calc_ssd(
|
||||||
state->frame->ref_LX[1][
|
&lcu->ref.u[chroma_index], &lcu->rec.u[chroma_index],
|
||||||
cur_pu->inter.mv_ref[1]]],
|
LCU_WIDTH_C, LCU_WIDTH_C, cu_width / 2
|
||||||
};
|
);
|
||||||
kvz_inter_recon_lcu_bipred(state,
|
ssd += CHROMA_MULT * kvz_pixels_calc_ssd(
|
||||||
refs[0], refs[1],
|
&lcu->ref.v[chroma_index], &lcu->rec.v[chroma_index],
|
||||||
pu_x, pu_y,
|
LCU_WIDTH_C, LCU_WIDTH_C, cu_width / 2
|
||||||
pu_w, pu_h,
|
);
|
||||||
cur_pu->inter.mv,
|
|
||||||
lcu);
|
|
||||||
} else {
|
|
||||||
const int mv_idx = cur_pu->inter.mv_dir - 1;
|
|
||||||
|
|
||||||
const kvz_picture *const ref =
|
inter_zero_coeff_cost = ssd + inter_bitcost * state->lambda;
|
||||||
state->frame->ref->images[
|
|
||||||
state->frame->ref_LX[mv_idx][
|
|
||||||
cur_pu->inter.mv_ref[mv_idx]]];
|
|
||||||
|
|
||||||
kvz_inter_recon_lcu(state,
|
// Save the pixels at a lower level of the working tree.
|
||||||
ref,
|
copy_cu_pixels(x_local, y_local, cu_width, lcu, &work_tree[depth + 1]);
|
||||||
pu_x, pu_y,
|
|
||||||
pu_w, pu_h,
|
|
||||||
cur_pu->inter.mv[mv_idx],
|
|
||||||
lcu,
|
|
||||||
0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool has_chroma = state->encoder_control->chroma_format != KVZ_CSP_400;
|
const bool has_chroma = state->encoder_control->chroma_format != KVZ_CSP_400;
|
||||||
|
@ -589,7 +574,7 @@ static double search_cu(encoder_state_t * const state, int x, int y, int depth,
|
||||||
|
|
||||||
int cbf = cbf_is_set_any(cur_cu->cbf, depth);
|
int cbf = cbf_is_set_any(cur_cu->cbf, depth);
|
||||||
|
|
||||||
if(cur_cu->merged && !cbf && cur_cu->part_size == SIZE_2Nx2N) {
|
if (cur_cu->merged && !cbf && cur_cu->part_size == SIZE_2Nx2N) {
|
||||||
cur_cu->merged = 0;
|
cur_cu->merged = 0;
|
||||||
cur_cu->skipped = 1;
|
cur_cu->skipped = 1;
|
||||||
// Selecting skip reduces bits needed to code the CU
|
// Selecting skip reduces bits needed to code the CU
|
||||||
|
@ -615,6 +600,28 @@ static double search_cu(encoder_state_t * const state, int x, int y, int depth,
|
||||||
}
|
}
|
||||||
|
|
||||||
cost += mode_bits * state->lambda;
|
cost += mode_bits * state->lambda;
|
||||||
|
|
||||||
|
if (inter_zero_coeff_cost <= cost) {
|
||||||
|
cost = inter_zero_coeff_cost;
|
||||||
|
|
||||||
|
// Restore saved pixels from lower level of the working tree.
|
||||||
|
copy_cu_pixels(x_local, y_local, cu_width, &work_tree[depth + 1], lcu);
|
||||||
|
|
||||||
|
if (cur_cu->merged && cur_cu->part_size == SIZE_2Nx2N) {
|
||||||
|
cur_cu->merged = 0;
|
||||||
|
cur_cu->skipped = 1;
|
||||||
|
lcu_fill_cu_info(lcu, x_local, y_local, cu_width, cu_width, cur_cu);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cur_cu->tr_depth != depth) {
|
||||||
|
// Reset transform depth since there are no coefficients. This
|
||||||
|
// ensures that CBF is cleared for the whole area of the CU.
|
||||||
|
kvz_lcu_set_trdepth(lcu, x, y, depth, depth);
|
||||||
|
}
|
||||||
|
|
||||||
|
cur_cu->cbf = 0;
|
||||||
|
lcu_set_coeff(lcu, x_local, y_local, cu_width, cur_cu);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool can_split_cu =
|
bool can_split_cu =
|
||||||
|
|
|
@ -1495,7 +1495,7 @@ static void search_pu_inter(encoder_state_t * const state,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
kvz_inter_recon_lcu_bipred(state,
|
kvz_inter_recon_bipred(state,
|
||||||
state->frame->ref->images[
|
state->frame->ref->images[
|
||||||
state->frame->ref_LX[0][merge_cand[i].ref[0]]
|
state->frame->ref_LX[0][merge_cand[i].ref[0]]
|
||||||
],
|
],
|
||||||
|
|
Loading…
Reference in a new issue