mirror of
https://github.com/ultravideo/uvg266.git
synced 2024-11-27 19:24:06 +00:00
Merge branch 'zero-coeff-check'
This commit is contained in:
commit
75a8700630
125
src/inter.c
125
src/inter.c
|
@ -306,27 +306,27 @@ 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 ref picture to copy the data from
|
||||
* \param xpos block x position
|
||||
* \param ypos block y position
|
||||
* \param width block width
|
||||
* \param height block height
|
||||
* \param xpos PU x position
|
||||
* \param ypos PU y position
|
||||
* \param width PU width
|
||||
* \param height PU height
|
||||
* \param mv_param motion vector
|
||||
* \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,
|
||||
const kvz_picture * const 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)
|
||||
static void inter_recon_unipred(const encoder_state_t * const state,
|
||||
const kvz_picture * const 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)
|
||||
{
|
||||
const vector2d_t pu_in_tile = { xpos, ypos };
|
||||
const vector2d_t pu_in_lcu = { xpos % LCU_WIDTH, ypos % LCU_WIDTH };
|
||||
|
@ -428,27 +428,27 @@ 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 ref1 reference picture to copy the data from
|
||||
* \param ref2 other reference picture to copy the data from
|
||||
* \param xpos block x position
|
||||
* \param ypos block y position
|
||||
* \param width block width
|
||||
* \param height block height
|
||||
* \param xpos PU x position
|
||||
* \param ypos PU y position
|
||||
* \param width PU width
|
||||
* \param height PU height
|
||||
* \param mv_param motion vectors
|
||||
* \param lcu destination lcu
|
||||
*/
|
||||
void kvz_inter_recon_lcu_bipred(const encoder_state_t * const state,
|
||||
const kvz_picture * ref1,
|
||||
const kvz_picture * ref2,
|
||||
int32_t xpos,
|
||||
int32_t ypos,
|
||||
int32_t width,
|
||||
int32_t height,
|
||||
int16_t mv_param[2][2],
|
||||
lcu_t* lcu)
|
||||
void kvz_inter_recon_bipred(const encoder_state_t * const state,
|
||||
const kvz_picture * ref1,
|
||||
const kvz_picture * ref2,
|
||||
int32_t xpos,
|
||||
int32_t ypos,
|
||||
int32_t width,
|
||||
int32_t height,
|
||||
int16_t mv_param[2][2],
|
||||
lcu_t* lcu)
|
||||
{
|
||||
kvz_pixel temp_lcu_y[LCU_WIDTH*LCU_WIDTH];
|
||||
kvz_pixel temp_lcu_u[LCU_WIDTH_C*LCU_WIDTH_C];
|
||||
|
@ -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_rec1) high_precision_rec1 = kvz_hi_prec_buf_t_alloc(LCU_WIDTH*LCU_WIDTH);
|
||||
//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){
|
||||
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_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
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
* \param cu coding unit to clear
|
||||
|
|
33
src/inter.h
33
src/inter.h
|
@ -40,26 +40,21 @@ typedef struct {
|
|||
|
||||
} 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,
|
||||
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 * ref2,
|
||||
int32_t xpos,
|
||||
int32_t ypos,
|
||||
int32_t width,
|
||||
int32_t height,
|
||||
int16_t mv_param[2][2],
|
||||
lcu_t* lcu);
|
||||
void kvz_inter_recon_bipred(const encoder_state_t * const state,
|
||||
const kvz_picture * ref1,
|
||||
const kvz_picture * ref2,
|
||||
int32_t xpos,
|
||||
int32_t ypos,
|
||||
int32_t width,
|
||||
int32_t height,
|
||||
int16_t mv_param[2][2],
|
||||
lcu_t* lcu);
|
||||
|
||||
void kvz_inter_get_mv_cand(const encoder_state_t * const state,
|
||||
int32_t x,
|
||||
|
|
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;
|
||||
int cu_width = LCU_WIDTH >> depth;
|
||||
double cost = MAX_INT;
|
||||
double inter_zero_coeff_cost = MAX_INT;
|
||||
uint32_t inter_bitcost = MAX_INT;
|
||||
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
|
||||
// into account, so there is less of a chanse of luma mode being
|
||||
// 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);
|
||||
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);
|
||||
|
||||
const int num_pu = kvz_part_mode_num_parts[cur_cu->part_size];
|
||||
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);
|
||||
kvz_inter_recon_cu(state, lcu, x, y, cu_width);
|
||||
|
||||
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) {
|
||||
const kvz_picture *const refs[2] = {
|
||||
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],
|
||||
pu_x, pu_y,
|
||||
pu_w, pu_h,
|
||||
cur_pu->inter.mv,
|
||||
lcu);
|
||||
} else {
|
||||
const int mv_idx = cur_pu->inter.mv_dir - 1;
|
||||
double ssd = 0.0;
|
||||
ssd += LUMA_MULT * kvz_pixels_calc_ssd(
|
||||
&lcu->ref.y[luma_index], &lcu->rec.y[luma_index],
|
||||
LCU_WIDTH, LCU_WIDTH, cu_width
|
||||
);
|
||||
ssd += CHROMA_MULT * kvz_pixels_calc_ssd(
|
||||
&lcu->ref.u[chroma_index], &lcu->rec.u[chroma_index],
|
||||
LCU_WIDTH_C, LCU_WIDTH_C, cu_width / 2
|
||||
);
|
||||
ssd += CHROMA_MULT * kvz_pixels_calc_ssd(
|
||||
&lcu->ref.v[chroma_index], &lcu->rec.v[chroma_index],
|
||||
LCU_WIDTH_C, LCU_WIDTH_C, cu_width / 2
|
||||
);
|
||||
|
||||
const kvz_picture *const ref =
|
||||
state->frame->ref->images[
|
||||
state->frame->ref_LX[mv_idx][
|
||||
cur_pu->inter.mv_ref[mv_idx]]];
|
||||
inter_zero_coeff_cost = ssd + inter_bitcost * state->lambda;
|
||||
|
||||
kvz_inter_recon_lcu(state,
|
||||
ref,
|
||||
pu_x, pu_y,
|
||||
pu_w, pu_h,
|
||||
cur_pu->inter.mv[mv_idx],
|
||||
lcu,
|
||||
0);
|
||||
}
|
||||
// Save the pixels at a lower level of the working tree.
|
||||
copy_cu_pixels(x_local, y_local, cu_width, lcu, &work_tree[depth + 1]);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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->skipped = 1;
|
||||
// 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;
|
||||
|
||||
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 =
|
||||
|
|
|
@ -1495,18 +1495,18 @@ static void search_pu_inter(encoder_state_t * const state,
|
|||
continue;
|
||||
}
|
||||
|
||||
kvz_inter_recon_lcu_bipred(state,
|
||||
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,
|
||||
mv,
|
||||
templcu);
|
||||
kvz_inter_recon_bipred(state,
|
||||
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,
|
||||
mv,
|
||||
templcu);
|
||||
|
||||
for (int ypos = 0; ypos < height; ++ypos) {
|
||||
int dst_y = ypos * width;
|
||||
|
|
Loading…
Reference in a new issue