[mrl] Pass multi_ref_idx to generic angular and DC prediction funcs. Fix some outdated comments.

This commit is contained in:
siivonek 2021-09-15 14:19:54 +02:00
parent a5dc2a3ce1
commit 511ce4991b
6 changed files with 90 additions and 45 deletions

View file

@ -212,24 +212,26 @@ static void intra_filter_reference(
/**
* \brief Generage planar prediction.
* \brief Generate dc prediction.
* \param log2_width Log2 of width, range 2..5.
* \param in_ref_above Pointer to -1 index of above reference, length=width*2+1.
* \param in_ref_left Pointer to -1 index of left reference, length=width*2+1.
* \param ref_top Pointer to -1 index of above reference, length=width*2+1.
* \param ref_left Pointer to -1 index of left reference, length=width*2+1.
* \param dst Buffer of size width*width.
* \param multi_ref_idx Multi reference line index for use with MRL.
*/
static void intra_pred_dc(
const int_fast8_t log2_width,
const kvz_pixel *const ref_top,
const kvz_pixel *const ref_left,
kvz_pixel *const out_block)
kvz_pixel *const out_block,
const uint8_t multi_ref_idx)
{
int_fast8_t width = 1 << log2_width;
int_fast16_t sum = 0;
for (int_fast8_t i = 0; i < width; ++i) {
sum += ref_top[i + 1];
sum += ref_left[i + 1];
sum += ref_top[i + 1 + multi_ref_idx];
sum += ref_left[i + 1 + multi_ref_idx];
}
// JVET_K0122
@ -549,11 +551,15 @@ void kvz_intra_predict(
int_fast8_t mode,
color_t color,
kvz_pixel *dst,
bool filter_boundary)
bool filter_boundary,
const uint8_t multi_ref_idx)
{
const int_fast8_t width = 1 << log2_width;
const kvz_config *cfg = &state->encoder_control->cfg;
// MRL only for luma
uint8_t multi_ref_index = color == COLOR_Y ? multi_ref_idx : 0;
const kvz_intra_ref *used_ref = &refs->ref;
if (cfg->intra_smoothing_disabled || color != COLOR_Y || mode == 1 || width == 4) {
// For chroma, DC and 4x4 blocks, always use unfiltered reference.
@ -586,9 +592,9 @@ void kvz_intra_predict(
if (mode == 0) {
kvz_intra_pred_planar(log2_width, used_ref->top, used_ref->left, dst);
} else if (mode == 1) {
intra_pred_dc(log2_width, used_ref->top, used_ref->left, dst);
intra_pred_dc(log2_width, used_ref->top, used_ref->left, dst, multi_ref_index);
} else {
kvz_angular_pred(log2_width, mode, color, used_ref->top, used_ref->left, dst);
kvz_angular_pred(log2_width, mode, color, used_ref->top, used_ref->left, dst, multi_ref_index);
}
// pdpc
@ -608,7 +614,7 @@ 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 mri)
const uint8_t multi_ref_idx)
{
assert(log2_width >= 2 && log2_width <= 5);
@ -621,7 +627,7 @@ void kvz_intra_build_reference_any(
const int_fast8_t width = 1 << log2_width;
// Get multiRefIdx from CU under prediction. Do not use MRL if not luma
const uint8_t multi_ref_index = !is_chroma ? mri : 0;
const uint8_t multi_ref_index = !is_chroma ? multi_ref_idx : 0;
// Convert luma coordinates to chroma coordinates for chroma.
const vector2d_t lcu_px = {
@ -737,7 +743,7 @@ void kvz_intra_build_reference_inner(
const lcu_t *const lcu,
kvz_intra_references *const refs,
bool entropy_sync,
const uint8_t mri)
const uint8_t multi_ref_idx)
{
assert(log2_width >= 2 && log2_width <= 5);
@ -749,7 +755,7 @@ void kvz_intra_build_reference_inner(
const int_fast8_t width = 1 << log2_width;
// Get multiRefIdx from CU under prediction. Do not use MRL if not luma
const uint8_t multi_ref_index = !is_chroma ? mri : 0;
const uint8_t multi_ref_index = !is_chroma ? multi_ref_idx : 0;
// Convert luma coordinates to chroma coordinates for chroma.
const vector2d_t lcu_px = {
@ -915,6 +921,7 @@ static void intra_recon_tb_leaf(
int x_scu = SUB_SCU(x);
int y_scu = SUB_SCU(y);
const vector2d_t lcu_px = {x_scu >> shift, y_scu >> shift };
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);
@ -923,7 +930,7 @@ static void intra_recon_tb_leaf(
int stride = state->tile->frame->source->stride;
const bool filter_boundary = color == COLOR_Y && !(cfg->lossless && cfg->implicit_rdpcm);
if(intra_mode < 68) {
kvz_intra_predict(state, &refs, log2width, intra_mode, color, pred, filter_boundary);
kvz_intra_predict(state, &refs, log2width, intra_mode, color, pred, filter_boundary, cur_cu->intra.multi_ref_idx);
} else {
kvz_pixels_blit(&state->tile->frame->cclm_luma_rec[x / 2 + (y * stride) / 4], pred, width, width, stride / 2, width);
if(cclm_params == NULL) {

View file

@ -79,14 +79,14 @@ int8_t kvz_intra_get_dir_luma_predictor(
const cu_info_t *const above_pu);
/**
* \brief Generage angular predictions.
* \param width Width in pixels, range 4..32.
* \param color What color pixels to use.
* \param luma_px Luma coordinates of the prediction block.
* \param pic_px Picture dimensions in luma pixels.
* \param lcu LCU struct.
* \param out_left_ref Left reference pixels, index 0 is the top-left.
* \param out_top_ref Top reference pixels, index 0 is the top-left.
* \brief Build intra prediction reference buffers.
* \param log2_width Log2 of width, range 2..5.
* \param color What color pixels to use.
* \param luma_px Luma coordinates of the prediction block.
* \param pic_px Picture dimensions in luma pixels.
* \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.
*/
void kvz_intra_build_reference(
const int_fast8_t log2_width,
@ -113,7 +113,8 @@ void kvz_intra_predict(
int_fast8_t mode,
color_t color,
kvz_pixel *dst,
bool filter_boundary);
bool filter_boundary,
const uint8_t multi_ref_idx);
void kvz_intra_recon_cu(
encoder_state_t *const state,

View file

@ -480,7 +480,7 @@ static void search_intra_chroma_rough(encoder_state_t * const state,
kvz_pixels_blit(orig_u, orig_block, width, width, origstride, width);
for (int i = 0; i < 5; ++i) {
if (modes[i] == -1) continue;
kvz_intra_predict(state, refs_u, log2_width_c, modes[i], COLOR_U, pred, false);
kvz_intra_predict(state, refs_u, log2_width_c, modes[i], COLOR_U, pred, false, 0);
//costs[i] += get_cost(encoder_state, pred, orig_block, satd_func, sad_func, width);
costs[i] += satd_func(pred, orig_block);
}
@ -494,7 +494,7 @@ static void search_intra_chroma_rough(encoder_state_t * const state,
kvz_pixels_blit(orig_v, orig_block, width, width, origstride, width);
for (int i = 0; i < 5; ++i) {
if (modes[i] == -1) continue;
kvz_intra_predict(state, refs_v, log2_width_c, modes[i], COLOR_V, pred, false);
kvz_intra_predict(state, refs_v, log2_width_c, modes[i], COLOR_V, pred, false, 0);
//costs[i] += get_cost(encoder_state, pred, orig_block, satd_func, sad_func, width);
costs[i] += satd_func(pred, orig_block);
}
@ -588,7 +588,7 @@ static int8_t search_intra_rough(encoder_state_t * const state,
double costs_out[PARALLEL_BLKS] = { 0 };
for (int i = 0; i < PARALLEL_BLKS; ++i) {
if (mode + i * offset <= 66) {
kvz_intra_predict(state, refs, log2_width, mode + i * offset, COLOR_Y, preds[i], filter_boundary);
kvz_intra_predict(state, refs, log2_width, mode + i * offset, COLOR_Y, preds[i], filter_boundary, 0);
}
}
@ -627,7 +627,7 @@ static int8_t search_intra_rough(encoder_state_t * const state,
if (mode_in_range) {
for (int i = 0; i < PARALLEL_BLKS; ++i) {
if (test_modes[i] >= 2 && test_modes[i] <= 66) {
kvz_intra_predict(state, refs, log2_width, test_modes[i], COLOR_Y, preds[i], filter_boundary);
kvz_intra_predict(state, refs, log2_width, test_modes[i], COLOR_Y, preds[i], filter_boundary, 0);
}
}
@ -664,7 +664,7 @@ static int8_t search_intra_rough(encoder_state_t * const state,
}
if (!has_mode) {
kvz_intra_predict(state, refs, log2_width, mode, COLOR_Y, preds[0], filter_boundary);
kvz_intra_predict(state, refs, log2_width, mode, COLOR_Y, preds[0], filter_boundary, 0);
costs[modes_selected] = get_cost(state, preds[0], orig_block, satd_func, sad_func, width);
modes[modes_selected] = mode;
++modes_selected;

View file

@ -446,6 +446,25 @@ static void kvz_angular_pred_avx2(
}
}
/**
* \brief Generage angular predictions.
* \param log2_width Log2 of width, range 2..5.
* \param intra_mode Angular mode in range 2..34.
* \param in_ref_above Pointer to -1 index of above reference, length=width*2+1.
* \param in_ref_left Pointer to -1 index of left reference, length=width*2+1.
* \param dst Buffer of size width*width.
* \param multi_ref_idx Multi reference line index for use with MRL.
*/
static void kvz_angular_pred_avx2(
const int_fast8_t log2_width,
const int_fast8_t intra_mode,
const uint8_t *const in_ref_above,
const uint8_t *const in_ref_left,
uint8_t *const dst,
const uint8_t multi_ref_idx)
{
assert(log2_width >= 2 && log2_width <= 5);
assert(intra_mode >= 2 && intra_mode <= 34);
// Flip the block if this is was a horizontal mode.
if (!vertical_mode) {
@ -459,6 +478,12 @@ static void kvz_angular_pred_avx2(
const __m128i vseq = _mm_setr_epi32(0, 1, 2, 3);
const __m128i vidx = _mm_slli_epi32(vseq, log2_width);
// TODO: implement usage of multi_ref_idx
// Temporary buffer for modes 11-25.
// It only needs to be big enough to hold indices from -width to width-1.
uint8_t tmp_ref[2 * 32];
const int_fast8_t width = 1 << log2_width;
// Transpose as 4x4 subblocks
for (int_fast32_t y = 0; y + 3 < width; y += 4) {
for (int_fast32_t x = y; x + 3 < width; x += 4) {
@ -590,7 +615,8 @@ static void kvz_intra_pred_planar_avx2(
// addends etc can be preinitialized for each position.
static void pred_filtered_dc_4x4(const uint8_t *ref_top,
const uint8_t *ref_left,
uint8_t *out_block)
uint8_t *out_block,
const uint8_t multi_ref_idx)
{
const uint32_t rt_u32 = *(const uint32_t *)(ref_top + 1);
const uint32_t rl_u32 = *(const uint32_t *)(ref_left + 1);
@ -651,7 +677,8 @@ static void pred_filtered_dc_4x4(const uint8_t *ref_top,
static void pred_filtered_dc_8x8(const uint8_t *ref_top,
const uint8_t *ref_left,
uint8_t *out_block)
uint8_t *out_block,
const uint8_t multi_ref_idx)
{
const uint64_t rt_u64 = *(const uint64_t *)(ref_top + 1);
const uint64_t rl_u64 = *(const uint64_t *)(ref_left + 1);
@ -755,7 +782,8 @@ static INLINE __m256i cvt_u32_si256(const uint32_t u)
static void pred_filtered_dc_16x16(const uint8_t *ref_top,
const uint8_t *ref_left,
uint8_t *out_block)
uint8_t *out_block,
const uint8_t multi_ref_idx)
{
const __m128i rt_128 = _mm_loadu_si128((const __m128i *)(ref_top + 1));
const __m128i rl_128 = _mm_loadu_si128((const __m128i *)(ref_left + 1));
@ -831,7 +859,8 @@ static void pred_filtered_dc_16x16(const uint8_t *ref_top,
static void pred_filtered_dc_32x32(const uint8_t *ref_top,
const uint8_t *ref_left,
uint8_t *out_block)
uint8_t *out_block,
const uint8_t multi_ref_idx)
{
const __m256i rt = _mm256_loadu_si256((const __m256i *)(ref_top + 1));
const __m256i rl = _mm256_loadu_si256((const __m256i *)(ref_left + 1));
@ -913,23 +942,26 @@ static void pred_filtered_dc_32x32(const uint8_t *ref_top,
* \param in_ref_above Pointer to -1 index of above reference, length=width*2+1.
* \param in_ref_left Pointer to -1 index of left reference, length=width*2+1.
* \param dst Buffer of size width*width.
* \param multi_ref_idx Reference line index. May be non-zero when MRL is used.
*/
static void kvz_intra_pred_filtered_dc_avx2(
const int_fast8_t log2_width,
const uint8_t *ref_top,
const uint8_t *ref_left,
uint8_t *out_block)
uint8_t *out_block,
const uint8_t multi_ref_idx)
{
assert(log2_width >= 2 && log2_width <= 5);
// TODO: implement multi reference index for all subfunctions
if (log2_width == 2) {
pred_filtered_dc_4x4(ref_top, ref_left, out_block);
pred_filtered_dc_4x4(ref_top, ref_left, out_block, multi_ref_idx);
} else if (log2_width == 3) {
pred_filtered_dc_8x8(ref_top, ref_left, out_block);
pred_filtered_dc_8x8(ref_top, ref_left, out_block, multi_ref_idx);
} else if (log2_width == 4) {
pred_filtered_dc_16x16(ref_top, ref_left, out_block);
pred_filtered_dc_16x16(ref_top, ref_left, out_block, multi_ref_idx);
} else if (log2_width == 5) {
pred_filtered_dc_32x32(ref_top, ref_left, out_block);
pred_filtered_dc_32x32(ref_top, ref_left, out_block, multi_ref_idx);
}
}

View file

@ -49,6 +49,7 @@
* \param in_ref_above Pointer to -1 index of above reference, length=width*2+1.
* \param in_ref_left Pointer to -1 index of left reference, length=width*2+1.
* \param dst Buffer of size width*width.
* \param multi_ref_idx Multi reference line index for use with MRL.
*/
static void kvz_angular_pred_generic(
const int_fast8_t log2_width,
@ -56,7 +57,8 @@ static void kvz_angular_pred_generic(
const int_fast8_t channel_type,
const kvz_pixel *const in_ref_above,
const kvz_pixel *const in_ref_left,
kvz_pixel *const dst)
kvz_pixel *const dst,
const uint8_t multi_ref_idx)
{
assert(log2_width >= 2 && log2_width <= 5);
@ -113,8 +115,7 @@ static void kvz_angular_pred_generic(
uint32_t pred_mode = intra_mode; // ToDo: handle WAIP
// TODO: pass the multiRefIdx to this function and assign to this variable
uint8_t multi_ref_index = 0;
uint8_t multi_ref_index = multi_ref_idx;
// Whether to swap references to always project on the left reference row.
const bool vertical_mode = intra_mode >= 34;
@ -418,12 +419,14 @@ static void kvz_intra_pred_planar_generic(
* \param in_ref_above Pointer to -1 index of above reference, length=width*2+1.
* \param in_ref_left Pointer to -1 index of left reference, length=width*2+1.
* \param dst Buffer of size width*width.
* \param multi_ref_idx Reference line index. May be non-zero when MRL is used.
*/
static void kvz_intra_pred_filtered_dc_generic(
const int_fast8_t log2_width,
const kvz_pixel *const ref_top,
const kvz_pixel *const ref_left,
kvz_pixel *const out_block)
kvz_pixel *const out_block,
const uint8_t multi_ref_idx)
{
assert(log2_width >= 2 && log2_width <= 5);
@ -432,8 +435,8 @@ static void kvz_intra_pred_filtered_dc_generic(
int_fast16_t sum = 0;
for (int_fast8_t i = 0; i < width; ++i) {
sum += ref_top[i + 1];
sum += ref_left[i + 1];
sum += ref_top[i + 1 + multi_ref_idx];
sum += ref_left[i + 1 + multi_ref_idx];
}
const kvz_pixel dc_val = (sum + width) >> (log2_width + 1);

View file

@ -49,7 +49,8 @@ typedef void (angular_pred_func)(
const int_fast8_t channel_type,
const kvz_pixel *const in_ref_above,
const kvz_pixel *const in_ref_left,
kvz_pixel *const dst);
kvz_pixel *const dst,
const uint8_t multi_ref_idx);
typedef void (intra_pred_planar_func)(
const int_fast8_t log2_width,
@ -61,7 +62,8 @@ typedef void (intra_pred_filtered_dc_func)(
const int_fast8_t log2_width,
const kvz_pixel *const ref_top,
const kvz_pixel *const ref_left,
kvz_pixel *const out_block);
kvz_pixel *const out_block,
const uint8_t multi_ref_idx);
typedef void (pdpc_planar_dc_func)(
const int mode,