Pass coeffs through encoder state

Changes the way coefficients are passed from kvz_search_lcu to
kvz_encode_coding_tree. Drops fields coeff_y, coeff_u and coeff_v in
videoframe_t and instead passes them through field coeff in
endoder_state_t.
This commit is contained in:
Arttu Ylä-Outinen 2017-05-11 14:51:09 +03:00
parent 2cad3173ec
commit 1357dd0599
7 changed files with 37 additions and 47 deletions

View file

@ -359,21 +359,20 @@ static void encode_transform_unit(encoder_state_t * const state,
coeff_t coeff_y[LCU_WIDTH*LCU_WIDTH+1];
coeff_t coeff_u[LCU_WIDTH*LCU_WIDTH>>2];
coeff_t coeff_v[LCU_WIDTH*LCU_WIDTH>>2];
int32_t coeff_stride = frame->width;
int8_t scan_idx = kvz_get_scan_order(cur_pu->type, cur_pu->intra.mode, depth);
int cbf_y = cbf_is_set(cur_pu->cbf, depth, COLOR_Y);
if (cbf_y) {
int x = x_pu * (LCU_WIDTH >> MAX_PU_DEPTH);
int y = y_pu * (LCU_WIDTH >> MAX_PU_DEPTH);
coeff_t *orig_pos = &frame->coeff_y[x + y * frame->width];
for (y = 0; y < width; y++) {
for (x = 0; x < width; x++) {
coeff_y[x+y*width] = orig_pos[x];
int x_local = x_pu * (LCU_WIDTH >> MAX_PU_DEPTH) % LCU_WIDTH;
int y_local = y_pu * (LCU_WIDTH >> MAX_PU_DEPTH) % LCU_WIDTH;
const coeff_t *orig_pos = &state->coeff->y[x_local + y_local * LCU_WIDTH];
for (int y = 0; y < width; y++) {
for (int x = 0; x < width; x++) {
coeff_y[x + y * width] = orig_pos[x];
}
orig_pos += coeff_stride;
orig_pos += LCU_WIDTH;
}
}
@ -393,26 +392,26 @@ static void encode_transform_unit(encoder_state_t * const state,
bool chroma_cbf_set = cbf_is_set(cur_cu->cbf, depth, COLOR_U) ||
cbf_is_set(cur_cu->cbf, depth, COLOR_V);
if (chroma_cbf_set) {
int x, y;
coeff_t *orig_pos_u, *orig_pos_v;
int x_local, y_local;
if (depth <= MAX_DEPTH) {
x = x_pu * (LCU_WIDTH >> (MAX_PU_DEPTH + 1));
y = y_pu * (LCU_WIDTH >> (MAX_PU_DEPTH + 1));
x_local = x_pu * (LCU_WIDTH >> (MAX_PU_DEPTH + 1)) % LCU_WIDTH_C;
y_local = y_pu * (LCU_WIDTH >> (MAX_PU_DEPTH + 1)) % LCU_WIDTH_C;
} else {
// for 4x4 select top left pixel of the CU.
x = x_cu * (LCU_WIDTH >> (MAX_DEPTH + 1));
y = y_cu * (LCU_WIDTH >> (MAX_DEPTH + 1));
x_local = x_cu * (LCU_WIDTH >> (MAX_DEPTH + 1)) % LCU_WIDTH_C;
y_local = y_cu * (LCU_WIDTH >> (MAX_DEPTH + 1)) % LCU_WIDTH_C;
}
orig_pos_u = &frame->coeff_u[x + y * (frame->width >> 1)];
orig_pos_v = &frame->coeff_v[x + y * (frame->width >> 1)];
for (y = 0; y < (width_c); y++) {
for (x = 0; x < (width_c); x++) {
coeff_u[x+y*(width_c)] = orig_pos_u[x];
coeff_v[x+y*(width_c)] = orig_pos_v[x];
const coeff_t *orig_pos_u = &state->coeff->u[x_local + y_local * LCU_WIDTH_C];
const coeff_t *orig_pos_v = &state->coeff->v[x_local + y_local * LCU_WIDTH_C];
for (int y = 0; y < width_c; y++) {
for (int x = 0; x < width_c; x++) {
coeff_u[x + y * width_c] = orig_pos_u[x];
coeff_v[x + y * width_c] = orig_pos_v[x];
}
orig_pos_u += coeff_stride>>1;
orig_pos_v += coeff_stride>>1;
orig_pos_u += LCU_WIDTH_C;
orig_pos_v += LCU_WIDTH_C;
}
scan_idx = kvz_get_scan_order(cur_cu->type, cur_cu->intra.mode_chroma, depth);

View file

@ -83,12 +83,6 @@ static int encoder_state_config_tile_init(encoder_state_t * const state,
return 0;
}
// Init coeff data table
//FIXME: move them
state->tile->frame->coeff_y = MALLOC(coeff_t, width * height);
state->tile->frame->coeff_u = MALLOC(coeff_t, (width * height) >> 2);
state->tile->frame->coeff_v = MALLOC(coeff_t, (width * height) >> 2);
state->tile->lcu_offset_x = lcu_offset_x;
state->tile->lcu_offset_y = lcu_offset_y;

View file

@ -274,8 +274,10 @@ static void encoder_state_worker_encode_lcu(void * opaque)
kvz_set_lcu_lambda_and_qp(state, lcu->position);
lcu_coeff_t coeff;
state->coeff = &coeff;
//This part doesn't write to bitstream, it's only search, deblock and sao
kvz_search_lcu(state, lcu->position_px.x, lcu->position_px.y, state->tile->hor_buf_search, state->tile->ver_buf_search);
encoder_state_recdata_to_bufs(state, lcu, state->tile->hor_buf_search, state->tile->ver_buf_search);
@ -329,6 +331,9 @@ static void encoder_state_worker_encode_lcu(void * opaque)
//Encode coding tree
kvz_encode_coding_tree(state, lcu->position.x << MAX_DEPTH, lcu->position.y << MAX_DEPTH, 0);
// Coeffs are not needed anymore.
state->coeff = NULL;
bool end_of_slice_segment_flag;
if (state->encoder_control->cfg.slices & KVZ_SLICES_WPP) {
// Slice segments end after each WPP row.

View file

@ -263,6 +263,11 @@ typedef struct encoder_state_t {
*/
int8_t ref_qp;
/**
* \brief Coeffs for the LCU.
*/
lcu_coeff_t *coeff;
//Jobs to wait for
threadqueue_job_t * tqj_recon_done; //Reconstruction is done
threadqueue_job_t * tqj_bitstream_written; //Bitstream is written

View file

@ -933,23 +933,15 @@ static void copy_lcu_to_cu_data(const encoder_state_t * const state, int x_px, i
const int pic_width = pic->width;
const int x_max = MIN(x_px + LCU_WIDTH, pic_width) - x_px;
const int y_max = MIN(y_px + LCU_WIDTH, pic->height) - y_px;
const int luma_index = x_px + y_px * pic_width;
const int chroma_index = (x_px / 2) + (y_px / 2) * (pic_width / 2);
kvz_pixels_blit(lcu->rec.y, &pic->rec->y[x_px + y_px * pic->rec->stride],
x_max, y_max, LCU_WIDTH, pic->rec->stride);
kvz_coefficients_blit(lcu->coeff.y, &pic->coeff_y[luma_index],
x_max, y_max, LCU_WIDTH, pic_width);
if (state->encoder_control->chroma_format != KVZ_CSP_400) {
kvz_pixels_blit(lcu->rec.u, &pic->rec->u[(x_px / 2) + (y_px / 2) * (pic->rec->stride / 2)],
x_max / 2, y_max / 2, LCU_WIDTH / 2, pic->rec->stride / 2);
kvz_pixels_blit(lcu->rec.v, &pic->rec->v[(x_px / 2) + (y_px / 2) * (pic->rec->stride / 2)],
x_max / 2, y_max / 2, LCU_WIDTH / 2, pic->rec->stride / 2);
kvz_coefficients_blit(lcu->coeff.u, &pic->coeff_u[chroma_index],
x_max / 2, y_max / 2, LCU_WIDTH / 2, pic_width / 2);
kvz_coefficients_blit(lcu->coeff.v, &pic->coeff_v[chroma_index],
x_max / 2, y_max / 2, LCU_WIDTH / 2, pic_width / 2);
}
}
}
@ -983,4 +975,9 @@ void kvz_search_lcu(encoder_state_t * const state, const int x, const int y, con
// The best decisions through out the LCU got propagated back to depth 0,
// so copy those back to the frame.
copy_lcu_to_cu_data(state, x, y, &work_tree[0]);
// Copy coeffs to encoder state.
memcpy(state->coeff->y, work_tree[0].coeff.y, LCU_WIDTH * LCU_WIDTH * sizeof(coeff_t));
memcpy(state->coeff->u, work_tree[0].coeff.u, LCU_WIDTH_C * LCU_WIDTH_C * sizeof(coeff_t));
memcpy(state->coeff->v, work_tree[0].coeff.v, LCU_WIDTH_C * LCU_WIDTH_C * sizeof(coeff_t));
}

View file

@ -54,8 +54,6 @@ videoframe_t * kvz_videoframe_alloc(int32_t width,
frame->cu_array = kvz_cu_array_alloc(cu_array_width, cu_array_height);
}
frame->coeff_y = NULL; frame->coeff_u = NULL; frame->coeff_v = NULL;
frame->sao_luma = MALLOC(sao_info_t, frame->width_in_lcu * frame->height_in_lcu);
if (chroma_format != KVZ_CSP_400) {
frame->sao_chroma = MALLOC(sao_info_t, frame->width_in_lcu * frame->height_in_lcu);
@ -78,10 +76,6 @@ int kvz_videoframe_free(videoframe_t * const frame)
kvz_cu_array_free(frame->cu_array);
FREE_POINTER(frame->coeff_y);
FREE_POINTER(frame->coeff_u);
FREE_POINTER(frame->coeff_v);
FREE_POINTER(frame->sao_luma);
FREE_POINTER(frame->sao_chroma);

View file

@ -39,10 +39,6 @@ typedef struct videoframe
kvz_picture *source; //!< \brief Source image.
kvz_picture *rec; //!< \brief Reconstructed image.
coeff_t* coeff_y; //!< \brief coefficient pointer Y
coeff_t* coeff_u; //!< \brief coefficient pointer U
coeff_t* coeff_v; //!< \brief coefficient pointer V
int32_t width; //!< \brief Luma pixel array width.
int32_t height; //!< \brief Luma pixel array height.
int32_t height_in_lcu; //!< \brief Picture width in number of LCU's.