Fix MRL behaviour on left LCU edge. Pass additional left edge reference buffers to reference building for MRL.

This commit is contained in:
siivonek 2021-11-09 05:58:26 +02:00
parent ddd0474c21
commit 9cce86ff61
3 changed files with 64 additions and 12 deletions

View file

@ -614,7 +614,8 @@ void kvz_intra_build_reference_any(
const vector2d_t *const pic_px,
const lcu_t *const lcu,
kvz_intra_references *const refs,
const uint8_t multi_ref_idx)
const uint8_t multi_ref_idx,
kvz_pixel *extra_ref_lines)
{
assert(log2_width >= 2 && log2_width <= 5);
@ -641,7 +642,18 @@ void kvz_intra_build_reference_any(
};
// Init pointers to LCUs reconstruction buffers, such that index 0 refers to block coordinate 0.
const kvz_pixel *left_ref = !color ? &lcu->left_ref.y[1] : (color == 1) ? &lcu->left_ref.u[1] : &lcu->left_ref.v[1];
const kvz_pixel *left_ref;
bool extra_ref = false;
// On the left LCU edge, if left neighboring LCU is available,
// left_ref needs to point to correct extra reference line if MRL is used.
if (luma_px->x > 0 && lcu_px.x == 0 && multi_ref_index != 0) {
left_ref = &extra_ref_lines[multi_ref_index * 2 * 128];
extra_ref = true;
}
else {
left_ref = !color ? &lcu->left_ref.y[1] : (color == 1) ? &lcu->left_ref.u[1] : &lcu->left_ref.v[1];
}
const kvz_pixel *top_ref = !color ? &lcu->top_ref.y[1] : (color == 1) ? &lcu->top_ref.u[1] : &lcu->top_ref.v[1];
const kvz_pixel *rec_ref = !color ? lcu->rec.y : (color == 1) ? lcu->rec.u : lcu->rec.v;
@ -660,7 +672,12 @@ void kvz_intra_build_reference_any(
left_border = &rec_ref[px.x - 1 - multi_ref_index + px.y * (LCU_WIDTH >> is_chroma)];
left_stride = LCU_WIDTH >> is_chroma;
} else {
left_border = &left_ref[px.y]; // No need for multi_ref_index on the left border
if (extra_ref) {
left_border = &left_ref[MAX_REF_LINE_IDX];
}
else {
left_border = &left_ref[px.y]; // No need for multi_ref_index on the left border
}
left_stride = 1;
}
@ -709,10 +726,10 @@ void kvz_intra_build_reference_any(
}
else if (px.x == 0) {
// LCU left border case
kvz_pixel nearest = left_border[-1 * left_stride];
kvz_pixel *top_left_corner = &extra_ref_lines[multi_ref_index * 2 * 128];
for (int i = 0; i <= multi_ref_index; ++i) {
out_left_ref[i] = left_border[(i - 1 - multi_ref_index) * left_stride];
out_top_ref[i] = nearest;
out_top_ref[i] = top_left_corner[(2 * 128 * -i) + MAX_REF_LINE_IDX - 1 - multi_ref_index];
}
}
else if (px.y == 0) {
@ -947,13 +964,14 @@ void kvz_intra_build_reference(
const vector2d_t *const pic_px,
const lcu_t *const lcu,
kvz_intra_references *const refs,
bool entropy_sync)
bool entropy_sync,
kvz_pixel *extra_ref_lines)
{
const vector2d_t lcu_px = { SUB_SCU(luma_px->x), SUB_SCU(luma_px->y) };
cu_info_t* cur_cu = LCU_GET_CU_AT_PX(lcu, lcu_px.x, lcu_px.y);
// Make this common case work with MRL, implement inner after this one works
kvz_intra_build_reference_any(log2_width, color, luma_px, pic_px, lcu, refs, cur_cu->intra.multi_ref_idx);
kvz_intra_build_reference_any(log2_width, color, luma_px, pic_px, lcu, refs, cur_cu->intra.multi_ref_idx, extra_ref_lines);
// Much logic can be discarded if not on the edge
/*if (luma_px->x > 0 && luma_px->y > 0) {
@ -995,7 +1013,22 @@ static void intra_recon_tb_leaf(
cu_info_t* cur_cu = LCU_GET_CU_AT_PX(lcu, lcu_px.x, lcu_px.y);
kvz_intra_references refs;
kvz_intra_build_reference(log2width, color, &luma_px, &pic_px, lcu, &refs, cfg->wpp);
// Extra reference lines for use with MRL. Extra lines needed only for left edge.
kvz_pixel extra_refs[2 * 128 * MAX_REF_LINE_IDX] = { 0 };
if (x > 0 && lcu_px.x == 0) {
videoframe_t* const frame = state->tile->frame;
// Copy ref lines 2 & 3. Line 1 is stored in LCU ref buffers.
for (int i = 0; i < MAX_REF_LINE_IDX; ++i) {
int height = (LCU_WIDTH >> depth) * 2 + MAX_REF_LINE_IDX;
kvz_pixels_blit(&frame->rec->y[(y - MAX_REF_LINE_IDX) * frame->rec->stride + x - (1 + i)],
&extra_refs[i * 2 * 128],
1, height,
frame->rec->stride, 1);
}
}
kvz_intra_build_reference(log2width, color, &luma_px, &pic_px, lcu, &refs, cfg->wpp, extra_refs);
kvz_pixel pred[32 * 32];
int stride = state->tile->frame->source->stride;

View file

@ -87,6 +87,7 @@ int8_t kvz_intra_get_dir_luma_predictor(
* \param lcu LCU struct.
* \param refs Pointer to top and left references.
* \param entropy_sync Indicate that top right is not available if WPP is enabled.
* \param extra_refs Additional left edge reference lines for use with MRL.
*/
void kvz_intra_build_reference(
const int_fast8_t log2_width,
@ -95,7 +96,8 @@ void kvz_intra_build_reference(
const vector2d_t *const pic_px,
const lcu_t *const lcu,
kvz_intra_references *const refs,
bool entropy_sync);
bool entropy_sync,
kvz_pixel *extra_refs);
/**
* \brief Generate intra predictions.

View file

@ -991,10 +991,10 @@ int8_t kvz_search_cu_intra_chroma(encoder_state_t * const state,
const vector2d_t luma_px = { x_px, y_px };
kvz_intra_references refs_u;
kvz_intra_build_reference(log2_width_c, COLOR_U, &luma_px, &pic_px, lcu, &refs_u, state->encoder_control->cfg.wpp);
kvz_intra_build_reference(log2_width_c, COLOR_U, &luma_px, &pic_px, lcu, &refs_u, state->encoder_control->cfg.wpp, NULL);
kvz_intra_references refs_v;
kvz_intra_build_reference(log2_width_c, COLOR_V, &luma_px, &pic_px, lcu, &refs_v, state->encoder_control->cfg.wpp);
kvz_intra_build_reference(log2_width_c, COLOR_V, &luma_px, &pic_px, lcu, &refs_v, state->encoder_control->cfg.wpp, NULL);
vector2d_t lcu_cpx = { lcu_px.x / 2, lcu_px.y / 2 };
kvz_pixel *ref_u = &lcu->ref.u[lcu_cpx.x + lcu_cpx.y * LCU_WIDTH_C];
@ -1052,7 +1052,24 @@ void kvz_search_cu_intra(encoder_state_t * const state,
if (depth > 0) {
const vector2d_t luma_px = { x_px, y_px };
const vector2d_t pic_px = { state->tile->frame->width, state->tile->frame->height };
kvz_intra_build_reference(log2_width, COLOR_Y, &luma_px, &pic_px, lcu, &refs, state->encoder_control->cfg.wpp);
// Extra reference lines for use with MRL. Extra lines needed only for left edge.
kvz_pixel extra_refs[2 * 128 * MAX_REF_LINE_IDX] = {0};
if (x_px > 0 && lcu_px.x == 0) {
videoframe_t* const frame = state->tile->frame;
// Copy extra ref lines, including ref line 1 and top left corner.
for (int i = 0; i < MAX_REF_LINE_IDX; ++i) {
int height = (LCU_WIDTH >> depth) * 2 + MAX_REF_LINE_IDX;
kvz_pixels_blit(&frame->rec->y[(y_px - MAX_REF_LINE_IDX) * frame->rec->stride + x_px - (1 + i)],
&extra_refs[i * 2 * 128],
1, height,
frame->rec->stride, 1);
}
}
kvz_intra_build_reference(log2_width, COLOR_Y, &luma_px, &pic_px, lcu, &refs, state->encoder_control->cfg.wpp, extra_refs);
}
int8_t modes[MAX_REF_LINE_IDX][67];