mirror of
https://github.com/ultravideo/uvg266.git
synced 2024-12-03 13:44:05 +00:00
Merge branch intra_mip.
This commit is contained in:
commit
c9cbadad8a
|
@ -267,6 +267,7 @@
|
|||
<ClInclude Include="..\..\src\input_frame_buffer.h" />
|
||||
<ClInclude Include="..\..\src\kvazaar_internal.h" />
|
||||
<ClInclude Include="..\..\src\kvz_math.h" />
|
||||
<ClInclude Include="..\..\src\mip_data.h" />
|
||||
<ClInclude Include="..\..\src\ml_intra_cu_depth_pred.h" />
|
||||
<ClInclude Include="..\..\src\search_inter.h" />
|
||||
<ClInclude Include="..\..\src\search_intra.h" />
|
||||
|
|
|
@ -498,6 +498,9 @@
|
|||
<ClInclude Include="..\..\src\strategies\avx2\alf-avx2.h">
|
||||
<Filter>Optimization\strategies\avx2</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\mip_data.h">
|
||||
<Filter>Reconstruction</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\debug.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
|
|
@ -90,6 +90,7 @@ libkvazaar_la_SOURCES = \
|
|||
kvazaar.c \
|
||||
kvazaar_internal.h \
|
||||
kvz_math.h \
|
||||
mip_data.h \
|
||||
ml_intra_cu_depth_pred.c \
|
||||
ml_intra_cu_depth_pred.h \
|
||||
nal.c \
|
||||
|
|
|
@ -107,6 +107,7 @@ typedef struct
|
|||
cabac_ctx_t sig_coeff_group_model[4];
|
||||
cabac_ctx_t luma_planar_model[2];
|
||||
cabac_ctx_t multi_ref_line[2];
|
||||
cabac_ctx_t mip_flag[4];
|
||||
cabac_ctx_t bdpcm_mode[4];
|
||||
cabac_ctx_t joint_cb_cr[3];
|
||||
cabac_ctx_t transform_skip_model_luma;
|
||||
|
|
|
@ -203,6 +203,8 @@ int kvz_config_init(kvz_config *cfg)
|
|||
cfg->chroma_scale_out[2][0] = cfg->chroma_scale_in[2][0] = -1;
|
||||
|
||||
cfg->mrl = false;
|
||||
|
||||
cfg->mip = false;
|
||||
|
||||
parse_qp_map(cfg, 0);
|
||||
|
||||
|
@ -1488,6 +1490,9 @@ int kvz_config_parse(kvz_config *cfg, const char *name, const char *value)
|
|||
else if OPT("mrl") {
|
||||
cfg->mrl = atobool(value);
|
||||
}
|
||||
else if OPT("mip") {
|
||||
cfg->mip = atobool(value);
|
||||
}
|
||||
else if OPT("jccr") {
|
||||
cfg->jccr = (bool)atobool(value);
|
||||
}
|
||||
|
|
|
@ -175,6 +175,8 @@ static const struct option long_options[] = {
|
|||
{ "chroma-qp-out", required_argument, NULL, 0 },
|
||||
{ "mrl", no_argument, NULL, 0 },
|
||||
{ "no-mrl", no_argument, NULL, 0 },
|
||||
{ "mip", no_argument, NULL, 0 },
|
||||
{ "no-mip", no_argument, NULL, 0 },
|
||||
{ "jccr", no_argument, NULL, 0 },
|
||||
{ "no-jccr", no_argument, NULL, 0 },
|
||||
{ "amvr", no_argument, NULL, 0 },
|
||||
|
@ -626,6 +628,7 @@ void print_help(void)
|
|||
" --(no-)tmvp : Temporal motion vector prediction [enabled]\n"
|
||||
" --(no-)mrl : Enable use of multiple reference lines in intra\n"
|
||||
" predictions.\n"
|
||||
" --(no-)mip : Enable matrix weighted intra prediction."
|
||||
" --mts <string> : Multiple Transform Selection [off].\n"
|
||||
" (Currently only implemented for intra\n"
|
||||
" and has effect only when rd >= 2)\n"
|
||||
|
|
|
@ -93,6 +93,13 @@ static const uint8_t MULTI_REF_LINE_MODE[4][2] = {
|
|||
{ 5, 8, },
|
||||
};
|
||||
|
||||
static const uint8_t MIP_FLAG[4][4] = {
|
||||
{ 56, 57, 50, 26, },
|
||||
{ 41, 57, 58, 26, },
|
||||
{ 33, 49, 50, 25, },
|
||||
{ 9, 10, 9, 6, },
|
||||
};
|
||||
|
||||
static const uint8_t INIT_INTRA_LUMA_MPM_FLAG[4] = {
|
||||
44, 36, 45, 6
|
||||
};
|
||||
|
@ -483,6 +490,10 @@ void kvz_init_contexts(encoder_state_t *state, int8_t QP, int8_t slice)
|
|||
kvz_ctx_init(&cabac->ctx.multi_ref_line[0], QP, MULTI_REF_LINE_MODE[slice][0], MULTI_REF_LINE_MODE[3][0]);
|
||||
kvz_ctx_init(&cabac->ctx.multi_ref_line[1], QP, MULTI_REF_LINE_MODE[slice][1], MULTI_REF_LINE_MODE[3][1]);
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
kvz_ctx_init(&cabac->ctx.mip_flag[i], QP, MIP_FLAG[slice][i], MIP_FLAG[3][i]);
|
||||
}
|
||||
|
||||
kvz_ctx_init(&cabac->ctx.chroma_pred_model, QP, INIT_CHROMA_PRED_MODE[slice], INIT_CHROMA_PRED_MODE[3]);
|
||||
|
||||
kvz_ctx_init(&cabac->ctx.cclm_flag, QP, INIT_CCLM_FLAG[slice], INIT_CCLM_FLAG[3]);
|
||||
|
|
2
src/cu.h
2
src/cu.h
|
@ -169,6 +169,8 @@ typedef struct
|
|||
int8_t mode;
|
||||
int8_t mode_chroma;
|
||||
uint8_t multi_ref_idx;
|
||||
int8_t mip_flag;
|
||||
int8_t mip_is_transposed;
|
||||
} intra;
|
||||
struct {
|
||||
mv_t mv[2][2]; // \brief Motion vectors for L0 and L1
|
||||
|
|
|
@ -854,6 +854,43 @@ static void encode_intra_coding_unit(encoder_state_t * const state,
|
|||
//isp_mode += ((height > TR_MAX_WIDTH) || !enough_samples) ? 2 : 0;
|
||||
bool allow_isp = enough_samples;
|
||||
|
||||
// Code MIP related bits
|
||||
bool enable_mip = state->encoder_control->cfg.mip;
|
||||
int8_t mip_flag = enable_mip ? cur_cu->intra.mip_flag : false;
|
||||
bool mip_transpose = enable_mip ? cur_cu->intra.mip_is_transposed : false;
|
||||
int8_t mip_mode = enable_mip ? cur_cu->intra.mode : 0;
|
||||
uint8_t num_mip_modes;
|
||||
|
||||
// Number of MIP modes for this block
|
||||
if (width == 4 && height == 4) {
|
||||
num_mip_modes = 16;
|
||||
}
|
||||
else if (width == 4 || height == 4 || (width == 8 && height == 8)) {
|
||||
num_mip_modes = 8;
|
||||
}
|
||||
else {
|
||||
num_mip_modes = 6;
|
||||
}
|
||||
|
||||
if (mip_flag) {
|
||||
assert(mip_mode >= 0 && mip_mode < num_mip_modes && "Invalid MIP mode.");
|
||||
}
|
||||
|
||||
if (cur_cu->type == CU_INTRA && !cur_cu->bdpcmMode && enable_mip) {
|
||||
const int cu_width = LCU_WIDTH >> depth;
|
||||
const int cu_height = cu_width; // TODO: height for non-square blocks
|
||||
uint8_t ctx_id = kvz_get_mip_flag_context(x, y, cu_width, cu_height, NULL, frame->cu_array);
|
||||
|
||||
// Write MIP flag
|
||||
cabac->cur_ctx = &(cabac->ctx.mip_flag[ctx_id]);
|
||||
CABAC_BIN(cabac, mip_flag, "mip_flag");
|
||||
if (mip_flag) {
|
||||
// Write MIP transpose flag & mode
|
||||
CABAC_BIN_EP(cabac, mip_transpose, "mip_transposed");
|
||||
kvz_cabac_encode_trunc_bin(cabac, mip_mode, num_mip_modes);
|
||||
}
|
||||
}
|
||||
|
||||
// Code MRL related bits
|
||||
bool enable_mrl = state->encoder_control->cfg.mrl;
|
||||
int multi_ref_idx = enable_mrl ? cur_cu->intra.multi_ref_idx : 0;
|
||||
|
@ -862,7 +899,7 @@ static void encode_intra_coding_unit(encoder_state_t * const state,
|
|||
if(multi_ref_idx) DBG_YUVIEW_VALUE(state->frame->poc, DBG_YUVIEW_MRL, x, y, width, width, multi_ref_idx);
|
||||
#endif
|
||||
|
||||
if (cur_cu->type == CU_INTRA && (y % LCU_WIDTH) != 0 && !cur_cu->bdpcmMode && enable_mrl) {
|
||||
if (cur_cu->type == CU_INTRA && (y % LCU_WIDTH) != 0 && !cur_cu->bdpcmMode && enable_mrl && !mip_flag) {
|
||||
if (MAX_REF_LINE_IDX > 1) {
|
||||
cabac->cur_ctx = &(cabac->ctx.multi_ref_line[0]);
|
||||
CABAC_BIN(cabac, multi_ref_idx != 0, "multi_ref_line");
|
||||
|
@ -875,7 +912,7 @@ static void encode_intra_coding_unit(encoder_state_t * const state,
|
|||
|
||||
|
||||
// ToDo: update real usage, these if clauses as such don't make any sense
|
||||
if (isp_mode != 0 && multi_ref_idx == 0) {
|
||||
if (isp_mode != 0 && multi_ref_idx == 0 && !mip_flag) {
|
||||
if (isp_mode) {
|
||||
cabac->cur_ctx = &(cabac->ctx.intra_subpart_model[0]);
|
||||
CABAC_BIN(cabac, 0, "intra_subPartitions");
|
||||
|
@ -890,121 +927,129 @@ static void encode_intra_coding_unit(encoder_state_t * const state,
|
|||
}
|
||||
}
|
||||
|
||||
// PREDINFO CODING
|
||||
// If intra prediction mode is found from the predictors,
|
||||
// it can be signaled with two EP's. Otherwise we can send
|
||||
// 5 EP bins with the full predmode
|
||||
// ToDo: fix comments for VVC
|
||||
const int cu_width = LCU_WIDTH >> depth;
|
||||
|
||||
cabac->cur_ctx = &(cabac->ctx.intra_luma_mpm_flag_model);
|
||||
for (int j = 0; j < num_pred_units; ++j) {
|
||||
const int pu_x = PU_GET_X(cur_cu->part_size, cu_width, x, j);
|
||||
const int pu_y = PU_GET_Y(cur_cu->part_size, cu_width, y, j);
|
||||
const cu_info_t *cur_pu = kvz_cu_array_at_const(frame->cu_array, pu_x, pu_y);
|
||||
|
||||
const cu_info_t *left_pu = NULL;
|
||||
const cu_info_t *above_pu = NULL;
|
||||
|
||||
if (pu_x > 0) {
|
||||
assert(pu_x >> 2 > 0);
|
||||
left_pu = kvz_cu_array_at_const(frame->cu_array, pu_x - 1, pu_y + cu_width - 1);
|
||||
}
|
||||
// Don't take the above PU across the LCU boundary.
|
||||
if (pu_y % LCU_WIDTH > 0 && pu_y > 0) {
|
||||
assert(pu_y >> 2 > 0);
|
||||
above_pu = kvz_cu_array_at_const(frame->cu_array, pu_x + cu_width - 1, pu_y - 1);
|
||||
}
|
||||
|
||||
|
||||
kvz_intra_get_dir_luma_predictor(pu_x, pu_y,
|
||||
intra_preds[j],
|
||||
cur_pu,
|
||||
left_pu, above_pu);
|
||||
|
||||
|
||||
intra_pred_mode_actual[j] = cur_pu->intra.mode;
|
||||
|
||||
for (int i = 0; i < INTRA_MPM_COUNT; i++) {
|
||||
if (intra_preds[j][i] == intra_pred_mode[j]) {
|
||||
mpm_preds[j] = (int8_t)i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Is the mode in the MPM array or not
|
||||
flag[j] = (mpm_preds[j] == -1) ? 0 : 1;
|
||||
if (!(cur_pu->intra.multi_ref_idx || (isp_mode))) {
|
||||
CABAC_BIN(cabac, flag[j], "prev_intra_luma_pred_flag");
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < num_pred_units; ++j) {
|
||||
// Signal index of the prediction mode in the prediction list, if it is there
|
||||
if (flag[j]) {
|
||||
|
||||
// If MIP is used, skip writing normal intra modes
|
||||
if (!mip_flag) {
|
||||
// PREDINFO CODING
|
||||
// If intra prediction mode is found from the predictors,
|
||||
// it can be signaled with two EP's. Otherwise we can send
|
||||
// 5 EP bins with the full predmode
|
||||
// ToDo: fix comments for VVC
|
||||
|
||||
cabac->cur_ctx = &(cabac->ctx.intra_luma_mpm_flag_model);
|
||||
for (int j = 0; j < num_pred_units; ++j) {
|
||||
const int pu_x = PU_GET_X(cur_cu->part_size, cu_width, x, j);
|
||||
const int pu_y = PU_GET_Y(cur_cu->part_size, cu_width, y, j);
|
||||
const cu_info_t *cur_pu = kvz_cu_array_at_const(frame->cu_array, pu_x, pu_y);
|
||||
cabac->cur_ctx = &(cabac->ctx.luma_planar_model[(isp_mode ? 0 : 1)]);
|
||||
if (cur_pu->intra.multi_ref_idx == 0) {
|
||||
CABAC_BIN(cabac, (mpm_preds[j] > 0 ? 1 : 0), "mpm_idx_luma_planar");
|
||||
}
|
||||
//CABAC_BIN_EP(cabac, (mpm_preds[j] > 0 ? 1 : 0), "mpm_idx");
|
||||
if (mpm_preds[j] > 0) {
|
||||
CABAC_BIN_EP(cabac, (mpm_preds[j] > 1 ? 1 : 0), "mpm_idx");
|
||||
}
|
||||
if (mpm_preds[j] > 1) {
|
||||
CABAC_BIN_EP(cabac, (mpm_preds[j] > 2 ? 1 : 0), "mpm_idx");
|
||||
}
|
||||
if (mpm_preds[j] > 2) {
|
||||
CABAC_BIN_EP(cabac, (mpm_preds[j] > 3 ? 1 : 0), "mpm_idx");
|
||||
}
|
||||
if (mpm_preds[j] > 3) {
|
||||
CABAC_BIN_EP(cabac, (mpm_preds[j] > 4 ? 1 : 0), "mpm_idx");
|
||||
}
|
||||
} else {
|
||||
// Signal the actual prediction mode.
|
||||
int32_t tmp_pred = intra_pred_mode[j];
|
||||
const cu_info_t* cur_pu = kvz_cu_array_at_const(frame->cu_array, pu_x, pu_y);
|
||||
|
||||
uint8_t intra_preds_temp[INTRA_MPM_COUNT+2];
|
||||
memcpy(intra_preds_temp, intra_preds[j], sizeof(int8_t)*3);
|
||||
memcpy(intra_preds_temp+4, &intra_preds[j][3], sizeof(int8_t)*3);
|
||||
intra_preds_temp[3] = 255;
|
||||
intra_preds_temp[7] = 255;
|
||||
const cu_info_t* left_pu = NULL;
|
||||
const cu_info_t* above_pu = NULL;
|
||||
|
||||
// Improvised merge sort
|
||||
// Sort prediction list from lowest to highest.
|
||||
if (intra_preds_temp[0] > intra_preds_temp[1]) SWAP(intra_preds_temp[0], intra_preds_temp[1], uint8_t);
|
||||
if (intra_preds_temp[0] > intra_preds_temp[2]) SWAP(intra_preds_temp[0], intra_preds_temp[2], uint8_t);
|
||||
if (intra_preds_temp[1] > intra_preds_temp[2]) SWAP(intra_preds_temp[1], intra_preds_temp[2], uint8_t);
|
||||
if (pu_x > 0) {
|
||||
assert(pu_x >> 2 > 0);
|
||||
left_pu = kvz_cu_array_at_const(frame->cu_array, pu_x - 1, pu_y + cu_width - 1);
|
||||
}
|
||||
// Don't take the above PU across the LCU boundary.
|
||||
if (pu_y % LCU_WIDTH > 0 && pu_y > 0) {
|
||||
assert(pu_y >> 2 > 0);
|
||||
above_pu = kvz_cu_array_at_const(frame->cu_array, pu_x + cu_width - 1, pu_y - 1);
|
||||
}
|
||||
|
||||
if (intra_preds_temp[4] > intra_preds_temp[5]) SWAP(intra_preds_temp[4], intra_preds_temp[5], uint8_t);
|
||||
if (intra_preds_temp[4] > intra_preds_temp[6]) SWAP(intra_preds_temp[4], intra_preds_temp[6], uint8_t);
|
||||
if (intra_preds_temp[5] > intra_preds_temp[6]) SWAP(intra_preds_temp[5], intra_preds_temp[6], uint8_t);
|
||||
|
||||
// Merge two subarrays
|
||||
int32_t array1 = 0;
|
||||
int32_t array2 = 4;
|
||||
for (int item = 0; item < INTRA_MPM_COUNT; item++) {
|
||||
if (intra_preds_temp[array1] < intra_preds_temp[array2]) {
|
||||
intra_preds[j][item] = intra_preds_temp[array1];
|
||||
array1++;
|
||||
} else {
|
||||
intra_preds[j][item] = intra_preds_temp[array2];
|
||||
array2++;
|
||||
kvz_intra_get_dir_luma_predictor(pu_x, pu_y,
|
||||
intra_preds[j],
|
||||
cur_pu,
|
||||
left_pu, above_pu);
|
||||
|
||||
|
||||
intra_pred_mode_actual[j] = cur_pu->intra.mode;
|
||||
|
||||
for (int i = 0; i < INTRA_MPM_COUNT; i++) {
|
||||
if (intra_preds[j][i] == intra_pred_mode[j]) {
|
||||
mpm_preds[j] = (int8_t)i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Is the mode in the MPM array or not
|
||||
flag[j] = (mpm_preds[j] == -1) ? 0 : 1;
|
||||
if (!(cur_pu->intra.multi_ref_idx || (isp_mode))) {
|
||||
CABAC_BIN(cabac, flag[j], "prev_intra_luma_pred_flag");
|
||||
}
|
||||
}
|
||||
|
||||
// Reduce the index of the signaled prediction mode according to the
|
||||
// prediction list, as it has been already signaled that it's not one
|
||||
// of the prediction modes.
|
||||
for (int i = INTRA_MPM_COUNT-1; i >= 0; i--) {
|
||||
if (tmp_pred > intra_preds[j][i]) {
|
||||
tmp_pred--;
|
||||
for (int j = 0; j < num_pred_units; ++j) {
|
||||
// TODO: this loop is unnecessary in VVC. Remove in future
|
||||
assert(j == 0 && "In VVC this loop should be run only once.");
|
||||
|
||||
// Signal index of the prediction mode in the prediction list, if it is there
|
||||
if (flag[j]) {
|
||||
|
||||
const int pu_x = PU_GET_X(cur_cu->part_size, cu_width, x, j);
|
||||
const int pu_y = PU_GET_Y(cur_cu->part_size, cu_width, y, j);
|
||||
const cu_info_t* cur_pu = kvz_cu_array_at_const(frame->cu_array, pu_x, pu_y);
|
||||
cabac->cur_ctx = &(cabac->ctx.luma_planar_model[(isp_mode ? 0 : 1)]);
|
||||
if (cur_pu->intra.multi_ref_idx == 0) {
|
||||
CABAC_BIN(cabac, (mpm_preds[j] > 0 ? 1 : 0), "mpm_idx_luma_planar");
|
||||
}
|
||||
//CABAC_BIN_EP(cabac, (mpm_preds[j] > 0 ? 1 : 0), "mpm_idx");
|
||||
if (mpm_preds[j] > 0) {
|
||||
CABAC_BIN_EP(cabac, (mpm_preds[j] > 1 ? 1 : 0), "mpm_idx");
|
||||
}
|
||||
if (mpm_preds[j] > 1) {
|
||||
CABAC_BIN_EP(cabac, (mpm_preds[j] > 2 ? 1 : 0), "mpm_idx");
|
||||
}
|
||||
if (mpm_preds[j] > 2) {
|
||||
CABAC_BIN_EP(cabac, (mpm_preds[j] > 3 ? 1 : 0), "mpm_idx");
|
||||
}
|
||||
if (mpm_preds[j] > 3) {
|
||||
CABAC_BIN_EP(cabac, (mpm_preds[j] > 4 ? 1 : 0), "mpm_idx");
|
||||
}
|
||||
}
|
||||
|
||||
kvz_cabac_encode_trunc_bin(cabac, tmp_pred, 67 - INTRA_MPM_COUNT);
|
||||
else {
|
||||
// Signal the actual prediction mode.
|
||||
int32_t tmp_pred = intra_pred_mode[j];
|
||||
|
||||
uint8_t intra_preds_temp[INTRA_MPM_COUNT + 2];
|
||||
memcpy(intra_preds_temp, intra_preds[j], sizeof(int8_t) * 3);
|
||||
memcpy(intra_preds_temp + 4, &intra_preds[j][3], sizeof(int8_t) * 3);
|
||||
intra_preds_temp[3] = 255;
|
||||
intra_preds_temp[7] = 255;
|
||||
|
||||
// Improvised merge sort
|
||||
// Sort prediction list from lowest to highest.
|
||||
if (intra_preds_temp[0] > intra_preds_temp[1]) SWAP(intra_preds_temp[0], intra_preds_temp[1], uint8_t);
|
||||
if (intra_preds_temp[0] > intra_preds_temp[2]) SWAP(intra_preds_temp[0], intra_preds_temp[2], uint8_t);
|
||||
if (intra_preds_temp[1] > intra_preds_temp[2]) SWAP(intra_preds_temp[1], intra_preds_temp[2], uint8_t);
|
||||
|
||||
if (intra_preds_temp[4] > intra_preds_temp[5]) SWAP(intra_preds_temp[4], intra_preds_temp[5], uint8_t);
|
||||
if (intra_preds_temp[4] > intra_preds_temp[6]) SWAP(intra_preds_temp[4], intra_preds_temp[6], uint8_t);
|
||||
if (intra_preds_temp[5] > intra_preds_temp[6]) SWAP(intra_preds_temp[5], intra_preds_temp[6], uint8_t);
|
||||
|
||||
// Merge two subarrays
|
||||
int32_t array1 = 0;
|
||||
int32_t array2 = 4;
|
||||
for (int item = 0; item < INTRA_MPM_COUNT; item++) {
|
||||
if (intra_preds_temp[array1] < intra_preds_temp[array2]) {
|
||||
intra_preds[j][item] = intra_preds_temp[array1];
|
||||
array1++;
|
||||
}
|
||||
else {
|
||||
intra_preds[j][item] = intra_preds_temp[array2];
|
||||
array2++;
|
||||
}
|
||||
}
|
||||
|
||||
// Reduce the index of the signaled prediction mode according to the
|
||||
// prediction list, as it has been already signaled that it's not one
|
||||
// of the prediction modes.
|
||||
for (int i = INTRA_MPM_COUNT - 1; i >= 0; i--) {
|
||||
if (tmp_pred > intra_preds[j][i]) {
|
||||
tmp_pred--;
|
||||
}
|
||||
}
|
||||
|
||||
kvz_cabac_encode_trunc_bin(cabac, tmp_pred, 67 - INTRA_MPM_COUNT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -668,7 +668,11 @@ static void encoder_state_write_bitstream_seq_parameter_set(bitstream_t* stream,
|
|||
WRITE_U(stream, 0, 1, "sps_mrl_enabled_flag");
|
||||
}
|
||||
|
||||
WRITE_U(stream, 0, 1, "sps_mip_enabled_flag");
|
||||
if (state->encoder_control->cfg.mip) {
|
||||
WRITE_U(stream, 1, 1, "sps_mip_enabled_flag");
|
||||
} else {
|
||||
WRITE_U(stream, 0, 1, "sps_mip_enabled_flag");
|
||||
}
|
||||
// if(!no_cclm_constraint_flag)
|
||||
if(encoder->chroma_format != KVZ_CSP_400) {
|
||||
WRITE_U(stream, encoder->cfg.cclm, 1, "sps_cclm_enabled_flag");
|
||||
|
|
|
@ -216,6 +216,11 @@ typedef int16_t mv_t;
|
|||
*/
|
||||
#define MAX_REF_LINE_IDX 3
|
||||
|
||||
#define MIP_MAX_INPUT_SIZE 8
|
||||
#define MIP_MAX_REDUCED_OUTPUT_SAMPLES 64
|
||||
#define MIP_MAX_WIDTH 64
|
||||
#define MIP_MAX_HEIGHT 64
|
||||
|
||||
/**
|
||||
* \brief Number of pixels to delay deblocking.
|
||||
*
|
||||
|
|
390
src/intra.c
390
src/intra.c
|
@ -36,6 +36,7 @@
|
|||
|
||||
#include "image.h"
|
||||
#include "kvz_math.h"
|
||||
#include "mip_data.h"
|
||||
#include "strategies/strategies-intra.h"
|
||||
#include "tables.h"
|
||||
#include "transform.h"
|
||||
|
@ -99,14 +100,23 @@ int8_t kvz_intra_get_dir_luma_predictor(
|
|||
int8_t number_of_candidates = 0;
|
||||
|
||||
// The default mode if block is not coded yet is INTRA_PLANAR.
|
||||
// If the neighboring blocks were MIP blocks, intra mode is set to planar.
|
||||
int8_t left_intra_dir = 0;
|
||||
if (left_pu && left_pu->type == CU_INTRA) {
|
||||
left_intra_dir = left_pu->intra.mode;
|
||||
if (left_pu->intra.mip_flag) {
|
||||
left_intra_dir = PLANAR_IDX;
|
||||
} else {
|
||||
left_intra_dir = left_pu->intra.mode;
|
||||
}
|
||||
}
|
||||
|
||||
int8_t above_intra_dir = 0;
|
||||
if (above_pu && above_pu->type == CU_INTRA && y % LCU_WIDTH != 0) {
|
||||
above_intra_dir = above_pu->intra.mode;
|
||||
if (above_pu->intra.mip_flag) {
|
||||
above_intra_dir = PLANAR_IDX;
|
||||
} else {
|
||||
above_intra_dir = above_pu->intra.mode;
|
||||
}
|
||||
}
|
||||
|
||||
const int offset = 61;
|
||||
|
@ -544,6 +554,327 @@ void kvz_predict_cclm(
|
|||
linear_transform_cclm(cclm_params, sampled_luma, dst, width, height);
|
||||
}
|
||||
|
||||
|
||||
int kvz_get_mip_flag_context(int x, int y, int width, int height, const lcu_t* lcu, cu_array_t* const cu_a) {
|
||||
assert(!(lcu && cu_a));
|
||||
if (width > 2 * height || height > 2 * width) {
|
||||
return 3;
|
||||
}
|
||||
|
||||
int context = 0;
|
||||
const cu_info_t* left = NULL;
|
||||
const cu_info_t* top = NULL;
|
||||
if (lcu) {
|
||||
int x_local = SUB_SCU(x);
|
||||
int y_local = SUB_SCU(y);
|
||||
if (x) {
|
||||
left = LCU_GET_CU_AT_PX(lcu, x_local - 1, y_local);
|
||||
}
|
||||
if (y) {
|
||||
top = LCU_GET_CU_AT_PX(lcu, x_local - 1, y_local);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (x > 0) {
|
||||
left = kvz_cu_array_at_const(cu_a, x - 1, y);
|
||||
}
|
||||
if (y > 0) {
|
||||
top = kvz_cu_array_at_const(cu_a, x, y - 1);
|
||||
}
|
||||
}
|
||||
context += left && left->type == CU_INTRA ? left->intra.mip_flag : 0;
|
||||
context += top && top->type == CU_INTRA ? top->intra.mip_flag : 0;
|
||||
return context;
|
||||
}
|
||||
|
||||
|
||||
void kvz_mip_boundary_downsampling_1D(int* reduced_dst, const int* const ref_src, int src_len, int dst_len)
|
||||
{
|
||||
if (dst_len < src_len)
|
||||
{
|
||||
// Create reduced boundary by downsampling
|
||||
uint16_t down_smp_factor = src_len / dst_len;
|
||||
const int log2_factor = kvz_math_floor_log2(down_smp_factor);
|
||||
const int rounding_offset = (1 << (log2_factor - 1));
|
||||
|
||||
uint16_t src_idx = 0;
|
||||
for (uint16_t dst_idx = 0; dst_idx < dst_len; dst_idx++)
|
||||
{
|
||||
int sum = 0;
|
||||
for (int k = 0; k < down_smp_factor; k++)
|
||||
{
|
||||
sum += ref_src[src_idx++];
|
||||
}
|
||||
reduced_dst[dst_idx] = (sum + rounding_offset) >> log2_factor;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Copy boundary if no downsampling is needed
|
||||
for (uint16_t i = 0; i < dst_len; ++i)
|
||||
{
|
||||
reduced_dst[i] = ref_src[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void kvz_mip_reduced_pred(int* const output,
|
||||
const int* const input,
|
||||
const uint8_t* matrix,
|
||||
const bool transpose,
|
||||
const int red_bdry_size,
|
||||
const int red_pred_size,
|
||||
const int size_id,
|
||||
const int in_offset,
|
||||
const int in_offset_tr)
|
||||
{
|
||||
const int input_size = 2 * red_bdry_size;
|
||||
|
||||
// Use local buffer for transposed result
|
||||
int out_buf_transposed[LCU_WIDTH * LCU_WIDTH];
|
||||
int* const out_ptr = transpose ? out_buf_transposed : output;
|
||||
|
||||
int sum = 0;
|
||||
for (int i = 0; i < input_size; i++) {
|
||||
sum += input[i];
|
||||
}
|
||||
const int offset = (1 << (MIP_SHIFT_MATRIX - 1)) - MIP_OFFSET_MATRIX * sum;
|
||||
assert((input_size == 4 * (input_size >> 2)) && "MIP input size must be divisible by four");
|
||||
|
||||
const uint8_t* weight = matrix;
|
||||
const int input_offset = transpose ? in_offset_tr : in_offset;
|
||||
|
||||
const bool red_size = (size_id == 2);
|
||||
int pos_res = 0;
|
||||
for (int y = 0; y < red_pred_size; y++) {
|
||||
for (int x = 0; x < red_pred_size; x++) {
|
||||
if (red_size) {
|
||||
weight -= 1;
|
||||
}
|
||||
int tmp0 = red_size ? 0 : (input[0] * weight[0]);
|
||||
int tmp1 = input[1] * weight[1];
|
||||
int tmp2 = input[2] * weight[2];
|
||||
int tmp3 = input[3] * weight[3];
|
||||
for (int i = 4; i < input_size; i += 4) {
|
||||
tmp0 += input[i] * weight[i];
|
||||
tmp1 += input[i + 1] * weight[i + 1];
|
||||
tmp2 += input[i + 2] * weight[i + 2];
|
||||
tmp3 += input[i + 3] * weight[i + 3];
|
||||
}
|
||||
out_ptr[pos_res] = CLIP_TO_PIXEL(((tmp0 + tmp1 + tmp2 + tmp3 + offset) >> MIP_SHIFT_MATRIX) + input_offset);
|
||||
pos_res++;
|
||||
weight += input_size;
|
||||
}
|
||||
}
|
||||
|
||||
if (transpose) {
|
||||
for (int y = 0; y < red_pred_size; y++) {
|
||||
for (int x = 0; x < red_pred_size; x++) {
|
||||
output[y * red_pred_size + x] = out_ptr[x * red_pred_size + y];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void kvz_mip_pred_upsampling_1D(int* const dst, const int* const src, const int* const boundary,
|
||||
const uint16_t src_size_ups_dim, const uint16_t src_size_orth_dim,
|
||||
const uint16_t src_step, const uint16_t src_stride,
|
||||
const uint16_t dst_step, const uint16_t dst_stride,
|
||||
const uint16_t boundary_step,
|
||||
const uint16_t ups_factor)
|
||||
{
|
||||
const int log2_factor = kvz_math_floor_log2(ups_factor);
|
||||
assert(ups_factor >= 2 && "Upsampling factor must be at least 2.");
|
||||
const int rounding_offset = 1 << (log2_factor - 1);
|
||||
|
||||
uint16_t idx_orth_dim = 0;
|
||||
const int* src_line = src;
|
||||
int* dst_line = dst;
|
||||
const int* boundary_line = boundary + boundary_step - 1;
|
||||
while (idx_orth_dim < src_size_orth_dim)
|
||||
{
|
||||
uint16_t idx_upsample_dim = 0;
|
||||
const int* before = boundary_line;
|
||||
const int* behind = src_line;
|
||||
int* cur_dst = dst_line;
|
||||
while (idx_upsample_dim < src_size_ups_dim)
|
||||
{
|
||||
uint16_t pos = 1;
|
||||
int scaled_before = (*before) << log2_factor;
|
||||
int scaled_behind = 0;
|
||||
while (pos <= ups_factor)
|
||||
{
|
||||
scaled_before -= *before;
|
||||
scaled_behind += *behind;
|
||||
*cur_dst = (scaled_before + scaled_behind + rounding_offset) >> log2_factor;
|
||||
|
||||
pos++;
|
||||
cur_dst += dst_step;
|
||||
}
|
||||
|
||||
idx_upsample_dim++;
|
||||
before = behind;
|
||||
behind += src_step;
|
||||
}
|
||||
|
||||
idx_orth_dim++;
|
||||
src_line += src_stride;
|
||||
dst_line += dst_stride;
|
||||
boundary_line += boundary_step;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** \brief Matrix weighted intra prediction.
|
||||
*/
|
||||
void kvz_mip_predict(encoder_state_t const* const state, kvz_intra_references* const refs,
|
||||
const uint16_t pred_block_width, const uint16_t pred_block_height,
|
||||
kvz_pixel* dst,
|
||||
const int mip_mode, const bool mip_transp)
|
||||
{
|
||||
// MIP prediction uses int values instead of kvz_pixel as some temp values may be negative
|
||||
|
||||
kvz_pixel* out = dst;
|
||||
int result[32*32] = {0};
|
||||
const int mode_idx = mip_mode;
|
||||
|
||||
// *** INPUT PREP ***
|
||||
|
||||
// Initialize prediction parameters START
|
||||
uint16_t width = pred_block_width;
|
||||
uint16_t height = pred_block_height;
|
||||
|
||||
int size_id; // Prediction block type
|
||||
if (width == 4 && height == 4) {
|
||||
size_id = 0;
|
||||
}
|
||||
else if (width == 4 || height == 4 || (width == 8 && height == 8)) {
|
||||
size_id = 1;
|
||||
}
|
||||
else {
|
||||
size_id = 2;
|
||||
}
|
||||
|
||||
// Reduced boundary and prediction sizes
|
||||
int red_bdry_size = (size_id == 0) ? 2 : 4;
|
||||
int red_pred_size = (size_id < 2) ? 4 : 8;
|
||||
|
||||
// Upsampling factors
|
||||
uint16_t ups_hor_factor = width / red_pred_size;
|
||||
uint16_t ups_ver_factor = height / red_pred_size;
|
||||
|
||||
// Upsampling factors must be powers of two
|
||||
assert(!((ups_hor_factor < 1) || ((ups_hor_factor & (ups_hor_factor - 1))) != 0) && "Horizontal upsampling factor must be power of two.");
|
||||
assert(!((ups_ver_factor < 1) || ((ups_ver_factor & (ups_ver_factor - 1))) != 0) && "Vertical upsampling factor must be power of two.");
|
||||
|
||||
// Initialize prediction parameters END
|
||||
|
||||
int ref_samples_top[INTRA_REF_LENGTH];
|
||||
int ref_samples_left[INTRA_REF_LENGTH];
|
||||
|
||||
for (int i = 1; i < INTRA_REF_LENGTH; i++) {
|
||||
ref_samples_top[i-1] = (int)refs->ref.top[i]; // NOTE: in VTM code these are indexed as x + 1 & y + 1 during init
|
||||
ref_samples_left[i-1] = (int)refs->ref.left[i];
|
||||
}
|
||||
|
||||
// Compute reduced boundary with Haar-downsampling
|
||||
const int input_size = 2 * red_bdry_size;
|
||||
|
||||
int red_bdry[MIP_MAX_INPUT_SIZE];
|
||||
int red_bdry_trans[MIP_MAX_INPUT_SIZE];
|
||||
|
||||
int* const top_reduced = &red_bdry[0];
|
||||
int* const left_reduced = &red_bdry[red_bdry_size];
|
||||
|
||||
kvz_mip_boundary_downsampling_1D(top_reduced, ref_samples_top, width, red_bdry_size);
|
||||
kvz_mip_boundary_downsampling_1D(left_reduced, ref_samples_left, height, red_bdry_size);
|
||||
|
||||
// Transposed reduced boundaries
|
||||
int* const left_reduced_trans = &red_bdry_trans[0];
|
||||
int* const top_reduced_trans = &red_bdry_trans[red_bdry_size];
|
||||
|
||||
for (int x = 0; x < red_bdry_size; x++) {
|
||||
top_reduced_trans[x] = top_reduced[x];
|
||||
}
|
||||
for (int y = 0; y < red_bdry_size; y++) {
|
||||
left_reduced_trans[y] = left_reduced[y];
|
||||
}
|
||||
|
||||
int input_offset = red_bdry[0];
|
||||
int input_offset_trans = red_bdry_trans[0];
|
||||
|
||||
const bool has_first_col = (size_id < 2);
|
||||
// First column of matrix not needed for large blocks
|
||||
red_bdry[0] = has_first_col ? ((1 << (KVZ_BIT_DEPTH - 1)) - input_offset) : 0;
|
||||
red_bdry_trans[0] = has_first_col ? ((1 << (KVZ_BIT_DEPTH - 1)) - input_offset_trans) : 0;
|
||||
|
||||
for (int i = 1; i < input_size; ++i) {
|
||||
red_bdry[i] -= input_offset;
|
||||
red_bdry_trans[i] -= input_offset_trans;
|
||||
}
|
||||
|
||||
// *** INPUT PREP *** END
|
||||
|
||||
// *** BLOCK PREDICT ***
|
||||
|
||||
const bool need_upsampling = (ups_hor_factor > 1) || (ups_ver_factor > 1);
|
||||
const bool transpose = mip_transp;
|
||||
|
||||
const uint8_t* matrix;
|
||||
switch (size_id) {
|
||||
case 0:
|
||||
matrix = &kvz_mip_matrix_4x4[mode_idx][0][0];
|
||||
break;
|
||||
case 1:
|
||||
matrix = &kvz_mip_matrix_8x8[mode_idx][0][0];
|
||||
break;
|
||||
case 2:
|
||||
matrix = &kvz_mip_matrix_16x16[mode_idx][0][0];
|
||||
break;
|
||||
default:
|
||||
assert(false && "Invalid MIP size id.");
|
||||
}
|
||||
|
||||
// Max possible size is red_pred_size * red_pred_size, red_pred_size can be either 4 or 8
|
||||
int red_pred_buffer[8*8];
|
||||
int* const reduced_pred = need_upsampling ? red_pred_buffer : result;
|
||||
|
||||
const int* const reduced_bdry = transpose ? red_bdry_trans : red_bdry;
|
||||
|
||||
kvz_mip_reduced_pred(reduced_pred, reduced_bdry, matrix, transpose, red_bdry_size, red_pred_size, size_id, input_offset, input_offset_trans);
|
||||
if (need_upsampling) {
|
||||
const int* ver_src = reduced_pred;
|
||||
uint16_t ver_src_step = width;
|
||||
|
||||
if (ups_hor_factor > 1) {
|
||||
int* const hor_dst = result + (ups_ver_factor - 1) * width;
|
||||
ver_src = hor_dst;
|
||||
ver_src_step *= ups_ver_factor;
|
||||
|
||||
kvz_mip_pred_upsampling_1D(hor_dst, reduced_pred, ref_samples_left,
|
||||
red_pred_size, red_pred_size,
|
||||
1, red_pred_size, 1, ver_src_step,
|
||||
ups_ver_factor, ups_hor_factor);
|
||||
}
|
||||
|
||||
if (ups_ver_factor > 1) {
|
||||
kvz_mip_pred_upsampling_1D(result, ver_src, ref_samples_top,
|
||||
red_pred_size, width,
|
||||
ver_src_step, 1, width, 1,
|
||||
1, ups_ver_factor);
|
||||
}
|
||||
}
|
||||
|
||||
// Assign and cast values from temp array to output
|
||||
for (int i = 0; i < 32 * 32; i++) {
|
||||
out[i] = (kvz_pixel)result[i];
|
||||
}
|
||||
// *** BLOCK PREDICT *** END
|
||||
}
|
||||
|
||||
|
||||
void kvz_intra_predict(
|
||||
encoder_state_t *const state,
|
||||
kvz_intra_references *refs,
|
||||
|
@ -1028,7 +1359,9 @@ static void intra_recon_tb_leaf(
|
|||
cclm_parameters_t *cclm_params,
|
||||
lcu_t *lcu,
|
||||
color_t color,
|
||||
uint8_t multi_ref_idx)
|
||||
uint8_t multi_ref_idx,
|
||||
bool mip_flag,
|
||||
bool mip_transp)
|
||||
{
|
||||
const kvz_config *cfg = &state->encoder_control->cfg;
|
||||
const int shift = color == COLOR_Y ? 0 : 1;
|
||||
|
@ -1039,6 +1372,7 @@ static void intra_recon_tb_leaf(
|
|||
log2width -= 1;
|
||||
}
|
||||
const int width = 1 << log2width;
|
||||
const int height = width; // TODO: proper height for non-square blocks
|
||||
const int lcu_width = LCU_WIDTH >> shift;
|
||||
|
||||
const vector2d_t luma_px = { x, y };
|
||||
|
@ -1074,8 +1408,29 @@ static void intra_recon_tb_leaf(
|
|||
kvz_pixel pred[32 * 32];
|
||||
int stride = state->tile->frame->source->stride;
|
||||
const bool filter_boundary = color == COLOR_Y && !(cfg->lossless && cfg->implicit_rdpcm);
|
||||
bool use_mip = false;
|
||||
if (mip_flag) {
|
||||
if (color == COLOR_Y) {
|
||||
use_mip = true;
|
||||
} else {
|
||||
// MIP can be used for chroma if the chroma scheme is 444
|
||||
if (state->encoder_control->chroma_format == KVZ_CSP_444) {
|
||||
use_mip = true;
|
||||
} else {
|
||||
// If MIP cannot be used for chroma, set mode to planar
|
||||
intra_mode = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(intra_mode < 68) {
|
||||
kvz_intra_predict(state, &refs, log2width, intra_mode, color, pred, filter_boundary, multi_ref_index);
|
||||
if (use_mip) {
|
||||
assert(intra_mode >= 0 && intra_mode < 16 && "MIP mode must be between [0, 15]");
|
||||
kvz_mip_predict(state, &refs, width, height, pred, intra_mode, mip_transp);
|
||||
}
|
||||
else {
|
||||
kvz_intra_predict(state, &refs, log2width, intra_mode, color, pred, filter_boundary, multi_ref_index);
|
||||
}
|
||||
} 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) {
|
||||
|
@ -1123,6 +1478,8 @@ static void intra_recon_tb_leaf(
|
|||
* \param mode_chroma intra mode for chroma, or -1 to skip chroma recon
|
||||
* \param cur_cu pointer to the CU, or NULL to fetch CU from LCU
|
||||
* \param cclm_params pointer for the cclm_parameters, can be NULL if the mode is not cclm mode
|
||||
* \param mip_flag indicates whether the passed mode_luma is a MIP mode
|
||||
* \param mip_transp indicates whether the used MIP mode is transposed
|
||||
* \param lcu containing LCU
|
||||
*/
|
||||
void kvz_intra_recon_cu(
|
||||
|
@ -1135,6 +1492,8 @@ void kvz_intra_recon_cu(
|
|||
cu_info_t *cur_cu,
|
||||
cclm_parameters_t *cclm_params,
|
||||
uint8_t multi_ref_idx,
|
||||
bool mip_flag,
|
||||
bool mip_transp,
|
||||
lcu_t *lcu)
|
||||
{
|
||||
const vector2d_t lcu_px = { SUB_SCU(x), SUB_SCU(y) };
|
||||
|
@ -1143,6 +1502,14 @@ void kvz_intra_recon_cu(
|
|||
cur_cu = LCU_GET_CU_AT_PX(lcu, lcu_px.x, lcu_px.y);
|
||||
}
|
||||
uint8_t multi_ref_index = multi_ref_idx;
|
||||
bool use_mip = mip_flag;
|
||||
bool mip_transposed = mip_transp;
|
||||
|
||||
if (mode_luma != -1 && mode_chroma != -1) {
|
||||
if (use_mip) {
|
||||
assert(mode_luma == mode_chroma && "Chroma mode must be derived from luma mode if block uses MIP.");
|
||||
}
|
||||
}
|
||||
|
||||
// Reset CBFs because CBFs might have been set
|
||||
// for depth earlier
|
||||
|
@ -1160,10 +1527,10 @@ void kvz_intra_recon_cu(
|
|||
const int32_t x2 = x + offset;
|
||||
const int32_t y2 = y + offset;
|
||||
|
||||
kvz_intra_recon_cu(state, x, y, depth + 1, mode_luma, mode_chroma, NULL, NULL, multi_ref_index, lcu);
|
||||
kvz_intra_recon_cu(state, x2, y, depth + 1, mode_luma, mode_chroma, NULL, NULL, multi_ref_index, lcu);
|
||||
kvz_intra_recon_cu(state, x, y2, depth + 1, mode_luma, mode_chroma, NULL, NULL, multi_ref_index, lcu);
|
||||
kvz_intra_recon_cu(state, x2, y2, depth + 1, mode_luma, mode_chroma, NULL, NULL, multi_ref_index, lcu);
|
||||
kvz_intra_recon_cu(state, x, y, depth + 1, mode_luma, mode_chroma, NULL, NULL, multi_ref_index, use_mip, mip_transposed, lcu);
|
||||
kvz_intra_recon_cu(state, x2, y, depth + 1, mode_luma, mode_chroma, NULL, NULL, multi_ref_index, use_mip, mip_transposed, lcu);
|
||||
kvz_intra_recon_cu(state, x, y2, depth + 1, mode_luma, mode_chroma, NULL, NULL, multi_ref_index, use_mip, mip_transposed, lcu);
|
||||
kvz_intra_recon_cu(state, x2, y2, depth + 1, mode_luma, mode_chroma, NULL, NULL, multi_ref_index, use_mip, mip_transposed, lcu);
|
||||
|
||||
// Propagate coded block flags from child CUs to parent CU.
|
||||
uint16_t child_cbfs[3] = {
|
||||
|
@ -1182,13 +1549,14 @@ void kvz_intra_recon_cu(
|
|||
} else {
|
||||
const bool has_luma = mode_luma != -1;
|
||||
const bool has_chroma = mode_chroma != -1 && (x % 8 == 0 && y % 8 == 0);
|
||||
|
||||
// Process a leaf TU.
|
||||
if (has_luma) {
|
||||
intra_recon_tb_leaf(state, x, y, depth, mode_luma, cclm_params, lcu, COLOR_Y, multi_ref_index);
|
||||
intra_recon_tb_leaf(state, x, y, depth, mode_luma, cclm_params, lcu, COLOR_Y, multi_ref_index, use_mip, mip_transposed);
|
||||
}
|
||||
if (has_chroma) {
|
||||
intra_recon_tb_leaf(state, x, y, depth, mode_chroma, cclm_params, lcu, COLOR_U, 0);
|
||||
intra_recon_tb_leaf(state, x, y, depth, mode_chroma, cclm_params, lcu, COLOR_V, 0);
|
||||
intra_recon_tb_leaf(state, x, y, depth, mode_chroma, cclm_params, lcu, COLOR_U, 0, use_mip, mip_transposed);
|
||||
intra_recon_tb_leaf(state, x, y, depth, mode_chroma, cclm_params, lcu, COLOR_V, 0, use_mip, mip_transposed);
|
||||
}
|
||||
|
||||
kvz_quantize_lcu_residual(state, has_luma, has_chroma, x, y, depth, cur_cu, lcu, false);
|
||||
|
|
21
src/intra.h
21
src/intra.h
|
@ -42,9 +42,12 @@
|
|||
#include "global.h" // IWYU pragma: keep
|
||||
#include "kvazaar.h"
|
||||
|
||||
// Maximum possible reference line length for intra blocks
|
||||
#define INTRA_REF_LENGTH (2 * 128 + 3 + 33 * MAX_REF_LINE_IDX)
|
||||
|
||||
typedef struct {
|
||||
kvz_pixel left[2 * 128 + 3 + 33 * MAX_REF_LINE_IDX];
|
||||
kvz_pixel top[2 * 128 + 3 + 33 * MAX_REF_LINE_IDX];
|
||||
kvz_pixel left[INTRA_REF_LENGTH];
|
||||
kvz_pixel top[INTRA_REF_LENGTH];
|
||||
} kvz_intra_ref;
|
||||
typedef struct
|
||||
{
|
||||
|
@ -130,6 +133,8 @@ void kvz_intra_recon_cu(
|
|||
cu_info_t *cur_cu,
|
||||
cclm_parameters_t* cclm_params,
|
||||
uint8_t multi_ref_idx,
|
||||
bool mip_flag,
|
||||
bool mip_transp,
|
||||
lcu_t *lcu);
|
||||
|
||||
|
||||
|
@ -146,4 +151,16 @@ void kvz_predict_cclm(
|
|||
kvz_intra_references* chroma_ref,
|
||||
kvz_pixel* dst,
|
||||
cclm_parameters_t* cclm_params
|
||||
);
|
||||
|
||||
int kvz_get_mip_flag_context(int x, int y, int width, int height, const lcu_t* lcu, cu_array_t* const cu_a);
|
||||
|
||||
void kvz_mip_predict(
|
||||
encoder_state_t const * const state,
|
||||
kvz_intra_references * refs,
|
||||
const uint16_t width,
|
||||
const uint16_t height,
|
||||
kvz_pixel* dst,
|
||||
const int mip_mode,
|
||||
const bool mip_transp
|
||||
);
|
|
@ -517,6 +517,9 @@ typedef struct kvz_config
|
|||
/** \brief enable use of multiple reference lines in intra prediction */
|
||||
int8_t mrl;
|
||||
|
||||
/** \brief enable matrix weighted intra prediction */
|
||||
int8_t mip;
|
||||
|
||||
|
||||
int8_t jccr;
|
||||
|
||||
|
|
885
src/mip_data.h
Normal file
885
src/mip_data.h
Normal file
|
@ -0,0 +1,885 @@
|
|||
/*****************************************************************************
|
||||
* This file is part of uvg266 VVC encoder.
|
||||
*
|
||||
* Copyright (c) 2021, Tampere University, ITU/ISO/IEC, project contributors
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of the Tampere University or ITU/ISO/IEC nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* \ingroup Reconstruction
|
||||
* \file
|
||||
* MIP weight matrix data.
|
||||
*/
|
||||
|
||||
/** \file MipData.h
|
||||
\brief weight and bias data for matrix-based intra prediction (MIP)
|
||||
*/
|
||||
|
||||
#define MIP_SHIFT_MATRIX 6
|
||||
#define MIP_OFFSET_MATRIX 32
|
||||
|
||||
// NOTE: these matrices need to be aligned if used with avx2
|
||||
const uint8_t kvz_mip_matrix_4x4[16][16][4] =
|
||||
{
|
||||
{
|
||||
{ 32, 30, 90, 28},
|
||||
{ 32, 32, 72, 28},
|
||||
{ 34, 77, 53, 30},
|
||||
{ 51, 124, 36, 37},
|
||||
{ 31, 31, 95, 37},
|
||||
{ 33, 31, 70, 50},
|
||||
{ 52, 80, 25, 60},
|
||||
{ 78, 107, 1, 65},
|
||||
{ 31, 29, 37, 95},
|
||||
{ 38, 34, 19, 101},
|
||||
{ 73, 85, 0, 81},
|
||||
{ 92, 99, 0, 65},
|
||||
{ 34, 29, 14, 111},
|
||||
{ 48, 48, 7, 100},
|
||||
{ 80, 91, 0, 74},
|
||||
{ 89, 97, 0, 64}
|
||||
},
|
||||
{
|
||||
{ 31, 23, 34, 29},
|
||||
{ 31, 43, 34, 31},
|
||||
{ 30, 95, 34, 32},
|
||||
{ 29, 100, 35, 33},
|
||||
{ 31, 23, 34, 29},
|
||||
{ 31, 43, 34, 31},
|
||||
{ 30, 95, 34, 32},
|
||||
{ 29, 99, 35, 33},
|
||||
{ 31, 24, 35, 29},
|
||||
{ 31, 44, 34, 31},
|
||||
{ 30, 95, 35, 32},
|
||||
{ 29, 99, 35, 33},
|
||||
{ 31, 24, 35, 30},
|
||||
{ 31, 44, 35, 31},
|
||||
{ 30, 95, 35, 32},
|
||||
{ 29, 99, 35, 33}
|
||||
},
|
||||
{
|
||||
{ 32, 32, 36, 58},
|
||||
{ 32, 29, 26, 66},
|
||||
{ 36, 37, 23, 61},
|
||||
{ 79, 84, 3, 37},
|
||||
{ 32, 32, 30, 69},
|
||||
{ 33, 29, 24, 71},
|
||||
{ 44, 16, 21, 70},
|
||||
{ 96, 18, 0, 57},
|
||||
{ 32, 31, 24, 74},
|
||||
{ 33, 30, 23, 71},
|
||||
{ 36, 24, 24, 71},
|
||||
{ 59, 9, 16, 68},
|
||||
{ 32, 32, 23, 75},
|
||||
{ 33, 30, 24, 70},
|
||||
{ 32, 30, 25, 71},
|
||||
{ 36, 26, 25, 70}
|
||||
},
|
||||
{
|
||||
{ 32, 33, 34, 32},
|
||||
{ 32, 30, 22, 38},
|
||||
{ 29, 46, 25, 38},
|
||||
{ 53, 123, 28, 22},
|
||||
{ 32, 33, 30, 37},
|
||||
{ 32, 30, 21, 38},
|
||||
{ 32, 40, 24, 38},
|
||||
{ 64, 116, 26, 17},
|
||||
{ 32, 32, 23, 49},
|
||||
{ 32, 30, 21, 39},
|
||||
{ 34, 39, 24, 37},
|
||||
{ 72, 109, 23, 16},
|
||||
{ 33, 31, 17, 60},
|
||||
{ 32, 31, 21, 39},
|
||||
{ 35, 41, 24, 37},
|
||||
{ 72, 106, 22, 18}
|
||||
},
|
||||
{
|
||||
{ 34, 25, 89, 20},
|
||||
{ 38, 32, 47, 24},
|
||||
{ 40, 86, 29, 27},
|
||||
{ 38, 98, 32, 29},
|
||||
{ 34, 31, 94, 40},
|
||||
{ 44, 25, 83, 27},
|
||||
{ 54, 72, 43, 16},
|
||||
{ 47, 94, 33, 22},
|
||||
{ 33, 31, 36, 94},
|
||||
{ 43, 23, 51, 76},
|
||||
{ 62, 55, 64, 25},
|
||||
{ 57, 89, 38, 15},
|
||||
{ 32, 32, 28, 101},
|
||||
{ 38, 26, 33, 94},
|
||||
{ 55, 38, 68, 47},
|
||||
{ 59, 80, 52, 16}
|
||||
},
|
||||
{
|
||||
{ 28, 30, 68, 29},
|
||||
{ 23, 48, 23, 48},
|
||||
{ 39, 98, 16, 42},
|
||||
{ 84, 86, 20, 17},
|
||||
{ 25, 31, 52, 74},
|
||||
{ 38, 68, 5, 70},
|
||||
{ 95, 78, 7, 21},
|
||||
{ 127, 54, 12, 0},
|
||||
{ 30, 47, 14, 107},
|
||||
{ 79, 76, 0, 53},
|
||||
{ 127, 59, 7, 1},
|
||||
{ 127, 51, 9, 0},
|
||||
{ 50, 71, 1, 96},
|
||||
{ 109, 69, 7, 25},
|
||||
{ 127, 56, 9, 0},
|
||||
{ 123, 53, 13, 0}
|
||||
},
|
||||
{
|
||||
{ 40, 20, 72, 18},
|
||||
{ 48, 29, 44, 18},
|
||||
{ 53, 81, 35, 18},
|
||||
{ 48, 96, 33, 22},
|
||||
{ 45, 23, 79, 49},
|
||||
{ 61, 21, 56, 49},
|
||||
{ 72, 52, 32, 48},
|
||||
{ 65, 69, 20, 50},
|
||||
{ 41, 27, 29, 96},
|
||||
{ 49, 22, 28, 94},
|
||||
{ 52, 22, 28, 93},
|
||||
{ 49, 27, 27, 92},
|
||||
{ 37, 29, 26, 98},
|
||||
{ 39, 28, 28, 97},
|
||||
{ 38, 28, 30, 97},
|
||||
{ 38, 29, 30, 95}
|
||||
},
|
||||
{
|
||||
{ 33, 27, 43, 27},
|
||||
{ 32, 29, 31, 31},
|
||||
{ 31, 73, 33, 31},
|
||||
{ 35, 104, 34, 28},
|
||||
{ 32, 30, 63, 22},
|
||||
{ 33, 26, 33, 29},
|
||||
{ 33, 57, 33, 30},
|
||||
{ 37, 100, 35, 27},
|
||||
{ 32, 31, 85, 25},
|
||||
{ 34, 25, 39, 25},
|
||||
{ 35, 39, 32, 28},
|
||||
{ 40, 91, 35, 25},
|
||||
{ 32, 30, 77, 50},
|
||||
{ 34, 26, 54, 22},
|
||||
{ 37, 31, 34, 27},
|
||||
{ 45, 75, 34, 23}
|
||||
},
|
||||
{
|
||||
{ 34, 25, 77, 19},
|
||||
{ 36, 34, 56, 24},
|
||||
{ 41, 83, 39, 30},
|
||||
{ 47, 96, 28, 35},
|
||||
{ 34, 31, 70, 65},
|
||||
{ 38, 29, 53, 77},
|
||||
{ 43, 36, 37, 83},
|
||||
{ 48, 39, 28, 83},
|
||||
{ 33, 31, 31, 98},
|
||||
{ 33, 31, 30, 99},
|
||||
{ 34, 30, 31, 98},
|
||||
{ 36, 29, 31, 96},
|
||||
{ 32, 32, 30, 97},
|
||||
{ 32, 32, 31, 96},
|
||||
{ 31, 33, 33, 96},
|
||||
{ 32, 33, 34, 94}
|
||||
},
|
||||
{
|
||||
{ 30, 30, 93, 19},
|
||||
{ 31, 59, 67, 34},
|
||||
{ 31, 79, 36, 59},
|
||||
{ 30, 67, 17, 79},
|
||||
{ 30, 38, 68, 69},
|
||||
{ 29, 40, 43, 91},
|
||||
{ 26, 35, 32, 101},
|
||||
{ 23, 32, 30, 101},
|
||||
{ 26, 34, 30, 101},
|
||||
{ 23, 33, 30, 102},
|
||||
{ 20, 32, 31, 102},
|
||||
{ 18, 33, 32, 102},
|
||||
{ 23, 33, 31, 100},
|
||||
{ 20, 34, 32, 100},
|
||||
{ 18, 35, 33, 100},
|
||||
{ 18, 35, 33, 100}
|
||||
},
|
||||
{
|
||||
{ 31, 54, 90, 26},
|
||||
{ 32, 60, 53, 61},
|
||||
{ 34, 49, 37, 84},
|
||||
{ 34, 39, 35, 89},
|
||||
{ 35, 38, 41, 88},
|
||||
{ 35, 35, 32, 96},
|
||||
{ 35, 31, 33, 96},
|
||||
{ 35, 32, 35, 94},
|
||||
{ 34, 34, 30, 97},
|
||||
{ 35, 32, 33, 95},
|
||||
{ 35, 32, 34, 94},
|
||||
{ 35, 34, 34, 93},
|
||||
{ 34, 34, 34, 93},
|
||||
{ 35, 34, 34, 93},
|
||||
{ 35, 34, 34, 92},
|
||||
{ 36, 34, 35, 91}
|
||||
},
|
||||
{
|
||||
{ 32, 29, 54, 24},
|
||||
{ 31, 32, 34, 29},
|
||||
{ 31, 43, 34, 29},
|
||||
{ 32, 67, 36, 28},
|
||||
{ 31, 34, 69, 37},
|
||||
{ 31, 35, 46, 33},
|
||||
{ 30, 35, 39, 33},
|
||||
{ 30, 42, 39, 36},
|
||||
{ 31, 35, 39, 88},
|
||||
{ 30, 38, 41, 84},
|
||||
{ 30, 39, 40, 81},
|
||||
{ 39, 46, 38, 78},
|
||||
{ 31, 36, 34, 96},
|
||||
{ 34, 38, 37, 93},
|
||||
{ 55, 42, 38, 82},
|
||||
{ 89, 53, 38, 65}
|
||||
},
|
||||
{
|
||||
{ 32, 33, 43, 29},
|
||||
{ 32, 30, 29, 33},
|
||||
{ 31, 47, 31, 33},
|
||||
{ 33, 100, 31, 31},
|
||||
{ 32, 33, 74, 25},
|
||||
{ 32, 32, 34, 31},
|
||||
{ 32, 33, 30, 33},
|
||||
{ 32, 68, 30, 32},
|
||||
{ 32, 31, 91, 40},
|
||||
{ 32, 32, 58, 26},
|
||||
{ 31, 31, 30, 32},
|
||||
{ 31, 42, 30, 33},
|
||||
{ 32, 31, 49, 85},
|
||||
{ 32, 31, 83, 35},
|
||||
{ 31, 33, 48, 29},
|
||||
{ 31, 36, 32, 33}
|
||||
},
|
||||
{
|
||||
{ 31, 29, 81, 35},
|
||||
{ 32, 28, 34, 50},
|
||||
{ 31, 75, 16, 43},
|
||||
{ 34, 103, 29, 32},
|
||||
{ 32, 32, 53, 78},
|
||||
{ 31, 28, 36, 88},
|
||||
{ 30, 52, 18, 73},
|
||||
{ 52, 88, 17, 35},
|
||||
{ 32, 32, 35, 94},
|
||||
{ 30, 31, 35, 95},
|
||||
{ 36, 29, 31, 92},
|
||||
{ 100, 43, 16, 40},
|
||||
{ 32, 32, 35, 93},
|
||||
{ 30, 32, 38, 93},
|
||||
{ 55, 18, 37, 83},
|
||||
{ 127, 0, 30, 40}
|
||||
},
|
||||
{
|
||||
{ 31, 22, 47, 30},
|
||||
{ 31, 48, 25, 34},
|
||||
{ 30, 95, 31, 32},
|
||||
{ 32, 103, 33, 32},
|
||||
{ 30, 24, 57, 31},
|
||||
{ 30, 47, 26, 34},
|
||||
{ 31, 95, 31, 32},
|
||||
{ 43, 97, 35, 25},
|
||||
{ 29, 26, 44, 63},
|
||||
{ 37, 38, 24, 47},
|
||||
{ 74, 63, 28, 20},
|
||||
{ 110, 58, 34, 3},
|
||||
{ 46, 22, 5, 108},
|
||||
{ 93, 5, 9, 77},
|
||||
{ 127, 0, 17, 52},
|
||||
{ 127, 0, 15, 50}
|
||||
},
|
||||
{
|
||||
{ 32, 27, 68, 24},
|
||||
{ 35, 23, 35, 28},
|
||||
{ 35, 64, 29, 29},
|
||||
{ 37, 104, 33, 28},
|
||||
{ 32, 32, 91, 40},
|
||||
{ 36, 23, 67, 36},
|
||||
{ 49, 23, 39, 28},
|
||||
{ 60, 67, 30, 20},
|
||||
{ 32, 32, 36, 95},
|
||||
{ 35, 29, 38, 93},
|
||||
{ 50, 16, 30, 84},
|
||||
{ 72, 16, 15, 65},
|
||||
{ 32, 32, 27, 100},
|
||||
{ 33, 32, 29, 100},
|
||||
{ 37, 29, 30, 98},
|
||||
{ 48, 21, 29, 90}
|
||||
}
|
||||
};
|
||||
|
||||
const uint8_t kvz_mip_matrix_8x8[8][16][8] =
|
||||
{
|
||||
{
|
||||
{ 30, 63, 46, 37, 25, 33, 33, 34},
|
||||
{ 30, 60, 66, 38, 32, 31, 32, 33},
|
||||
{ 29, 45, 74, 42, 32, 32, 32, 33},
|
||||
{ 30, 39, 62, 58, 32, 33, 32, 33},
|
||||
{ 30, 66, 55, 39, 32, 30, 30, 36},
|
||||
{ 29, 54, 69, 40, 33, 31, 31, 33},
|
||||
{ 28, 48, 71, 43, 32, 33, 32, 33},
|
||||
{ 28, 41, 72, 46, 32, 34, 32, 33},
|
||||
{ 30, 66, 56, 40, 32, 33, 28, 33},
|
||||
{ 29, 55, 69, 39, 33, 33, 30, 32},
|
||||
{ 27, 46, 72, 43, 33, 33, 32, 33},
|
||||
{ 27, 42, 69, 48, 32, 34, 32, 33},
|
||||
{ 30, 63, 55, 40, 32, 33, 35, 30},
|
||||
{ 29, 56, 66, 40, 33, 33, 33, 30},
|
||||
{ 27, 47, 69, 44, 33, 33, 33, 32},
|
||||
{ 27, 42, 65, 50, 32, 34, 32, 33}
|
||||
},
|
||||
{
|
||||
{ 32, 33, 30, 31, 74, 30, 31, 32},
|
||||
{ 33, 56, 28, 30, 41, 29, 32, 32},
|
||||
{ 33, 77, 52, 26, 29, 34, 30, 32},
|
||||
{ 33, 37, 80, 41, 31, 34, 30, 32},
|
||||
{ 32, 32, 33, 31, 59, 76, 28, 31},
|
||||
{ 33, 31, 31, 30, 78, 40, 28, 32},
|
||||
{ 33, 47, 28, 29, 53, 27, 31, 31},
|
||||
{ 33, 61, 44, 28, 34, 32, 31, 31},
|
||||
{ 32, 31, 34, 30, 26, 64, 76, 27},
|
||||
{ 32, 31, 34, 29, 45, 86, 36, 29},
|
||||
{ 33, 27, 34, 29, 73, 55, 25, 32},
|
||||
{ 33, 33, 34, 30, 62, 33, 30, 31},
|
||||
{ 32, 31, 34, 30, 30, 29, 58, 74},
|
||||
{ 32, 31, 35, 29, 27, 53, 77, 35},
|
||||
{ 32, 30, 36, 29, 40, 80, 44, 31},
|
||||
{ 33, 28, 37, 30, 58, 60, 31, 33}
|
||||
},
|
||||
{
|
||||
{ 32, 51, 27, 32, 27, 50, 29, 32},
|
||||
{ 32, 95, 42, 29, 29, 42, 30, 32},
|
||||
{ 32, 27, 99, 34, 31, 41, 29, 32},
|
||||
{ 32, 34, 21, 104, 31, 42, 30, 32},
|
||||
{ 32, 45, 30, 32, 9, 88, 40, 30},
|
||||
{ 32, 77, 38, 30, 9, 76, 38, 30},
|
||||
{ 32, 38, 78, 33, 14, 67, 37, 30},
|
||||
{ 32, 30, 30, 87, 20, 59, 38, 31},
|
||||
{ 33, 37, 32, 32, 27, 18, 106, 34},
|
||||
{ 34, 44, 34, 31, 25, 17, 108, 31},
|
||||
{ 36, 39, 45, 31, 24, 15, 108, 30},
|
||||
{ 37, 31, 31, 54, 25, 14, 101, 32},
|
||||
{ 36, 33, 32, 30, 29, 37, 13, 110},
|
||||
{ 39, 32, 32, 29, 27, 37, 15, 108},
|
||||
{ 44, 33, 31, 27, 25, 37, 16, 106},
|
||||
{ 47, 30, 31, 32, 25, 34, 19, 102}
|
||||
},
|
||||
{
|
||||
{ 32, 48, 35, 35, 47, 68, 31, 31},
|
||||
{ 32, 33, 59, 40, 27, 71, 33, 30},
|
||||
{ 32, 29, 47, 65, 24, 62, 37, 30},
|
||||
{ 33, 33, 31, 81, 26, 50, 42, 32},
|
||||
{ 32, 30, 40, 38, 30, 70, 55, 31},
|
||||
{ 32, 20, 46, 50, 26, 55, 64, 31},
|
||||
{ 33, 30, 29, 66, 25, 41, 72, 33},
|
||||
{ 36, 34, 27, 69, 26, 31, 67, 39},
|
||||
{ 33, 28, 36, 40, 30, 26, 85, 47},
|
||||
{ 36, 27, 33, 50, 31, 20, 79, 53},
|
||||
{ 43, 30, 26, 57, 28, 17, 67, 62},
|
||||
{ 51, 27, 28, 55, 22, 23, 49, 70},
|
||||
{ 38, 29, 32, 39, 28, 30, 22, 104},
|
||||
{ 51, 31, 28, 43, 24, 31, 17, 102},
|
||||
{ 69, 23, 30, 40, 15, 38, 10, 95},
|
||||
{ 77, 13, 35, 38, 8, 43, 8, 90}
|
||||
},
|
||||
{
|
||||
{ 32, 38, 32, 33, 101, 40, 29, 32},
|
||||
{ 32, 40, 37, 32, 100, 36, 30, 32},
|
||||
{ 32, 37, 46, 35, 94, 33, 30, 31},
|
||||
{ 33, 34, 30, 62, 81, 35, 30, 31},
|
||||
{ 32, 32, 33, 32, 22, 102, 39, 29},
|
||||
{ 32, 31, 33, 33, 26, 104, 34, 28},
|
||||
{ 33, 33, 33, 33, 31, 103, 32, 28},
|
||||
{ 33, 32, 34, 36, 37, 94, 33, 28},
|
||||
{ 32, 33, 32, 32, 34, 24, 99, 36},
|
||||
{ 32, 34, 33, 33, 33, 30, 98, 32},
|
||||
{ 33, 33, 34, 33, 31, 37, 95, 29},
|
||||
{ 33, 33, 33, 36, 30, 46, 85, 31},
|
||||
{ 32, 33, 32, 33, 30, 34, 23, 104},
|
||||
{ 32, 34, 33, 33, 31, 32, 30, 98},
|
||||
{ 32, 33, 34, 34, 31, 29, 39, 91},
|
||||
{ 33, 33, 32, 37, 32, 30, 47, 82}
|
||||
},
|
||||
{
|
||||
{ 32, 52, 48, 31, 38, 76, 26, 32},
|
||||
{ 33, 19, 62, 50, 25, 50, 51, 31},
|
||||
{ 33, 30, 20, 74, 29, 29, 54, 51},
|
||||
{ 34, 35, 23, 56, 31, 25, 41, 76},
|
||||
{ 33, 25, 38, 39, 28, 39, 83, 35},
|
||||
{ 35, 28, 25, 47, 31, 23, 57, 74},
|
||||
{ 37, 35, 22, 38, 31, 27, 30, 101},
|
||||
{ 38, 32, 33, 29, 30, 31, 27, 103},
|
||||
{ 34, 32, 27, 37, 32, 25, 41, 92},
|
||||
{ 38, 33, 28, 32, 30, 31, 18, 111},
|
||||
{ 40, 32, 33, 27, 29, 33, 18, 111},
|
||||
{ 40, 32, 34, 27, 28, 33, 23, 105},
|
||||
{ 35, 32, 30, 33, 31, 33, 20, 107},
|
||||
{ 38, 31, 33, 30, 29, 33, 21, 106},
|
||||
{ 40, 32, 33, 29, 29, 34, 22, 105},
|
||||
{ 40, 32, 33, 30, 29, 34, 24, 101}
|
||||
},
|
||||
{
|
||||
{ 32, 28, 31, 33, 92, 33, 30, 31},
|
||||
{ 33, 30, 28, 33, 71, 26, 32, 30},
|
||||
{ 33, 60, 26, 33, 47, 28, 33, 30},
|
||||
{ 33, 63, 44, 36, 37, 31, 33, 30},
|
||||
{ 33, 30, 31, 33, 43, 90, 33, 29},
|
||||
{ 33, 28, 29, 34, 71, 71, 26, 30},
|
||||
{ 33, 30, 26, 33, 86, 45, 28, 30},
|
||||
{ 33, 38, 29, 32, 74, 32, 33, 29},
|
||||
{ 33, 32, 30, 32, 29, 41, 95, 27},
|
||||
{ 34, 31, 29, 33, 26, 71, 73, 22},
|
||||
{ 34, 31, 29, 33, 37, 88, 46, 25},
|
||||
{ 33, 32, 28, 34, 55, 75, 36, 28},
|
||||
{ 34, 31, 30, 32, 33, 27, 43, 89},
|
||||
{ 35, 32, 28, 33, 33, 23, 77, 59},
|
||||
{ 34, 33, 28, 33, 30, 35, 91, 37},
|
||||
{ 34, 34, 28, 34, 33, 53, 74, 31}
|
||||
},
|
||||
{
|
||||
{ 33, 49, 26, 32, 26, 52, 28, 31},
|
||||
{ 33, 71, 72, 24, 30, 32, 34, 31},
|
||||
{ 32, 23, 70, 68, 32, 32, 32, 32},
|
||||
{ 31, 33, 21, 106, 33, 32, 32, 33},
|
||||
{ 34, 47, 32, 29, 5, 86, 44, 26},
|
||||
{ 34, 44, 89, 28, 28, 37, 33, 30},
|
||||
{ 32, 27, 46, 89, 33, 31, 31, 32},
|
||||
{ 30, 33, 20, 107, 33, 33, 32, 33},
|
||||
{ 35, 39, 42, 27, 26, 24, 92, 35},
|
||||
{ 34, 27, 87, 43, 30, 34, 38, 31},
|
||||
{ 31, 31, 32, 100, 32, 33, 30, 32},
|
||||
{ 29, 32, 22, 106, 33, 33, 32, 33},
|
||||
{ 35, 29, 47, 32, 32, 32, 17, 100},
|
||||
{ 34, 24, 69, 60, 34, 33, 28, 44},
|
||||
{ 31, 33, 31, 99, 32, 33, 32, 31},
|
||||
{ 29, 33, 25, 103, 33, 33, 32, 35}
|
||||
}
|
||||
};
|
||||
|
||||
const uint8_t kvz_mip_matrix_16x16[6][64][7] =
|
||||
{
|
||||
{
|
||||
{ 42, 37, 33, 27, 44, 33, 35},
|
||||
{ 71, 39, 34, 24, 36, 35, 36},
|
||||
{ 77, 46, 35, 33, 30, 34, 36},
|
||||
{ 64, 60, 35, 33, 31, 32, 36},
|
||||
{ 49, 71, 38, 32, 32, 31, 36},
|
||||
{ 42, 66, 50, 33, 31, 32, 36},
|
||||
{ 40, 52, 67, 33, 31, 32, 35},
|
||||
{ 38, 43, 75, 33, 32, 32, 35},
|
||||
{ 56, 40, 33, 26, 43, 38, 36},
|
||||
{ 70, 49, 34, 30, 28, 38, 38},
|
||||
{ 65, 57, 36, 34, 28, 33, 39},
|
||||
{ 59, 60, 39, 33, 30, 31, 38},
|
||||
{ 55, 60, 43, 33, 30, 31, 38},
|
||||
{ 51, 61, 47, 33, 30, 32, 37},
|
||||
{ 46, 62, 51, 34, 30, 32, 37},
|
||||
{ 42, 60, 55, 33, 31, 32, 37},
|
||||
{ 60, 42, 34, 30, 37, 43, 38},
|
||||
{ 68, 52, 35, 35, 22, 37, 40},
|
||||
{ 62, 58, 37, 34, 28, 31, 40},
|
||||
{ 58, 59, 41, 33, 30, 30, 39},
|
||||
{ 56, 59, 44, 34, 30, 31, 38},
|
||||
{ 53, 60, 45, 33, 30, 31, 38},
|
||||
{ 49, 65, 45, 33, 30, 31, 38},
|
||||
{ 45, 64, 47, 33, 31, 32, 38},
|
||||
{ 59, 44, 35, 31, 34, 43, 41},
|
||||
{ 66, 53, 36, 35, 25, 31, 43},
|
||||
{ 61, 58, 38, 34, 29, 30, 40},
|
||||
{ 59, 57, 41, 33, 30, 31, 39},
|
||||
{ 57, 58, 43, 33, 30, 31, 39},
|
||||
{ 54, 61, 43, 33, 31, 31, 39},
|
||||
{ 51, 64, 43, 33, 31, 31, 39},
|
||||
{ 48, 64, 45, 33, 32, 31, 39},
|
||||
{ 57, 45, 35, 30, 35, 40, 44},
|
||||
{ 65, 54, 37, 33, 33, 24, 44},
|
||||
{ 63, 56, 38, 34, 30, 29, 39},
|
||||
{ 61, 56, 41, 34, 30, 32, 39},
|
||||
{ 58, 58, 42, 33, 31, 31, 39},
|
||||
{ 54, 62, 41, 33, 31, 31, 39},
|
||||
{ 51, 65, 42, 33, 31, 31, 39},
|
||||
{ 48, 63, 43, 33, 32, 31, 39},
|
||||
{ 55, 46, 35, 30, 36, 38, 47},
|
||||
{ 65, 53, 37, 32, 36, 26, 40},
|
||||
{ 65, 54, 38, 33, 31, 30, 38},
|
||||
{ 63, 55, 39, 33, 30, 32, 38},
|
||||
{ 59, 58, 40, 33, 31, 31, 39},
|
||||
{ 54, 64, 40, 33, 31, 30, 40},
|
||||
{ 49, 66, 40, 32, 32, 30, 41},
|
||||
{ 48, 64, 42, 32, 32, 30, 41},
|
||||
{ 54, 46, 35, 30, 34, 39, 49},
|
||||
{ 64, 52, 36, 32, 34, 34, 35},
|
||||
{ 65, 53, 37, 33, 32, 32, 37},
|
||||
{ 63, 55, 38, 33, 31, 31, 39},
|
||||
{ 59, 60, 38, 33, 31, 31, 40},
|
||||
{ 54, 64, 38, 33, 32, 30, 40},
|
||||
{ 49, 66, 39, 33, 32, 29, 41},
|
||||
{ 47, 64, 42, 32, 33, 29, 42},
|
||||
{ 51, 46, 35, 31, 33, 37, 54},
|
||||
{ 61, 51, 36, 32, 33, 38, 36},
|
||||
{ 63, 53, 37, 32, 32, 34, 37},
|
||||
{ 62, 55, 37, 33, 32, 32, 39},
|
||||
{ 58, 59, 37, 33, 32, 31, 40},
|
||||
{ 53, 63, 38, 33, 32, 31, 40},
|
||||
{ 49, 64, 40, 33, 33, 30, 41},
|
||||
{ 46, 62, 42, 33, 33, 30, 42}
|
||||
},
|
||||
{
|
||||
{ 39, 34, 33, 58, 44, 31, 32},
|
||||
{ 60, 38, 32, 40, 51, 30, 31},
|
||||
{ 73, 49, 31, 39, 48, 32, 31},
|
||||
{ 60, 73, 30, 39, 46, 33, 32},
|
||||
{ 43, 87, 35, 38, 45, 33, 32},
|
||||
{ 35, 78, 54, 36, 45, 33, 32},
|
||||
{ 33, 47, 86, 35, 44, 33, 32},
|
||||
{ 31, 17, 114, 34, 44, 34, 33},
|
||||
{ 43, 37, 32, 53, 70, 30, 31},
|
||||
{ 53, 50, 30, 42, 72, 31, 30},
|
||||
{ 52, 66, 30, 39, 70, 32, 30},
|
||||
{ 46, 78, 35, 37, 68, 34, 30},
|
||||
{ 43, 75, 48, 37, 66, 34, 30},
|
||||
{ 40, 62, 68, 35, 65, 35, 30},
|
||||
{ 33, 37, 97, 33, 62, 37, 31},
|
||||
{ 26, 14, 122, 32, 59, 38, 33},
|
||||
{ 40, 39, 33, 34, 87, 37, 30},
|
||||
{ 45, 54, 32, 34, 84, 41, 29},
|
||||
{ 41, 70, 35, 33, 83, 40, 29},
|
||||
{ 37, 73, 44, 32, 82, 40, 30},
|
||||
{ 37, 65, 60, 31, 81, 41, 29},
|
||||
{ 35, 48, 82, 30, 79, 43, 29},
|
||||
{ 28, 27, 108, 28, 76, 45, 30},
|
||||
{ 19, 11, 127, 27, 70, 46, 32},
|
||||
{ 38, 40, 34, 27, 73, 62, 28},
|
||||
{ 39, 54, 35, 30, 73, 62, 28},
|
||||
{ 33, 65, 41, 29, 75, 59, 28},
|
||||
{ 30, 65, 53, 27, 76, 58, 29},
|
||||
{ 29, 53, 72, 26, 77, 58, 29},
|
||||
{ 27, 35, 95, 24, 77, 60, 28},
|
||||
{ 19, 19, 117, 23, 74, 61, 30},
|
||||
{ 9, 16, 127, 23, 68, 60, 34},
|
||||
{ 35, 40, 35, 29, 44, 89, 30},
|
||||
{ 33, 51, 39, 29, 49, 86, 30},
|
||||
{ 28, 57, 49, 28, 53, 83, 30},
|
||||
{ 24, 52, 65, 26, 56, 82, 30},
|
||||
{ 22, 39, 86, 24, 58, 82, 30},
|
||||
{ 18, 22, 108, 23, 59, 82, 31},
|
||||
{ 10, 13, 125, 22, 58, 80, 33},
|
||||
{ 0, 19, 127, 22, 56, 74, 40},
|
||||
{ 33, 40, 36, 31, 28, 90, 45},
|
||||
{ 29, 46, 44, 29, 31, 92, 43},
|
||||
{ 24, 45, 58, 28, 34, 91, 43},
|
||||
{ 19, 37, 78, 26, 37, 91, 43},
|
||||
{ 15, 22, 99, 25, 38, 91, 42},
|
||||
{ 11, 11, 118, 24, 39, 90, 44},
|
||||
{ 2, 11, 127, 23, 41, 85, 48},
|
||||
{ 0, 17, 127, 23, 43, 75, 55},
|
||||
{ 31, 37, 39, 30, 28, 54, 82},
|
||||
{ 27, 37, 52, 28, 30, 58, 79},
|
||||
{ 22, 30, 70, 27, 32, 58, 79},
|
||||
{ 15, 19, 91, 26, 33, 58, 79},
|
||||
{ 10, 8, 111, 25, 34, 58, 79},
|
||||
{ 5, 2, 125, 25, 35, 57, 80},
|
||||
{ 0, 9, 127, 25, 36, 53, 84},
|
||||
{ 0, 13, 127, 25, 39, 47, 88},
|
||||
{ 28, 29, 46, 28, 39, 2, 123},
|
||||
{ 24, 24, 62, 27, 41, 1, 125},
|
||||
{ 19, 14, 81, 25, 43, 0, 126},
|
||||
{ 13, 4, 101, 24, 44, 0, 127},
|
||||
{ 6, 0, 116, 23, 45, 0, 127},
|
||||
{ 0, 0, 126, 23, 45, 1, 127},
|
||||
{ 0, 4, 127, 25, 44, 2, 127},
|
||||
{ 0, 9, 127, 25, 44, 3, 127}
|
||||
},
|
||||
{
|
||||
{ 30, 32, 32, 42, 34, 32, 32},
|
||||
{ 63, 26, 34, 16, 38, 32, 32},
|
||||
{ 98, 26, 34, 25, 34, 33, 32},
|
||||
{ 75, 61, 30, 31, 32, 33, 32},
|
||||
{ 36, 94, 32, 30, 33, 32, 32},
|
||||
{ 26, 76, 58, 30, 33, 32, 32},
|
||||
{ 30, 39, 91, 31, 32, 33, 31},
|
||||
{ 32, 23, 105, 32, 32, 32, 32},
|
||||
{ 34, 30, 33, 31, 52, 29, 32},
|
||||
{ 66, 24, 34, 11, 41, 33, 32},
|
||||
{ 97, 28, 34, 24, 34, 33, 32},
|
||||
{ 71, 65, 30, 30, 32, 33, 32},
|
||||
{ 34, 92, 35, 30, 33, 32, 32},
|
||||
{ 26, 70, 64, 29, 34, 32, 32},
|
||||
{ 30, 37, 94, 30, 33, 32, 31},
|
||||
{ 32, 23, 105, 31, 33, 33, 31},
|
||||
{ 37, 29, 33, 8, 79, 27, 32},
|
||||
{ 71, 22, 35, 5, 50, 32, 32},
|
||||
{ 98, 29, 34, 23, 34, 34, 32},
|
||||
{ 66, 70, 30, 31, 31, 33, 32},
|
||||
{ 31, 92, 38, 30, 33, 32, 32},
|
||||
{ 26, 66, 68, 29, 34, 32, 31},
|
||||
{ 30, 34, 97, 30, 34, 33, 31},
|
||||
{ 31, 22, 106, 30, 34, 33, 31},
|
||||
{ 40, 28, 34, 0, 76, 46, 28},
|
||||
{ 76, 21, 35, 0, 55, 35, 32},
|
||||
{ 97, 32, 34, 21, 37, 33, 33},
|
||||
{ 61, 75, 29, 30, 32, 32, 32},
|
||||
{ 29, 92, 40, 29, 33, 32, 32},
|
||||
{ 26, 62, 73, 29, 34, 32, 31},
|
||||
{ 29, 32, 99, 30, 34, 33, 30},
|
||||
{ 31, 22, 107, 30, 34, 33, 31},
|
||||
{ 42, 27, 34, 1, 48, 79, 25},
|
||||
{ 80, 20, 35, 0, 48, 47, 31},
|
||||
{ 94, 36, 32, 17, 40, 33, 33},
|
||||
{ 55, 80, 29, 27, 35, 31, 32},
|
||||
{ 27, 90, 43, 28, 34, 32, 31},
|
||||
{ 26, 58, 76, 29, 33, 33, 30},
|
||||
{ 29, 30, 101, 29, 34, 34, 30},
|
||||
{ 31, 21, 108, 29, 35, 34, 30},
|
||||
{ 44, 26, 34, 6, 30, 80, 40},
|
||||
{ 81, 21, 35, 0, 41, 52, 35},
|
||||
{ 90, 41, 31, 14, 41, 35, 33},
|
||||
{ 51, 82, 29, 24, 37, 32, 32},
|
||||
{ 27, 87, 47, 27, 35, 32, 31},
|
||||
{ 26, 54, 79, 29, 34, 33, 30},
|
||||
{ 29, 29, 102, 28, 34, 33, 30},
|
||||
{ 31, 21, 108, 28, 35, 33, 31},
|
||||
{ 47, 26, 34, 7, 34, 44, 75},
|
||||
{ 80, 24, 34, 0, 41, 41, 50},
|
||||
{ 84, 45, 31, 12, 40, 36, 36},
|
||||
{ 49, 81, 31, 22, 37, 33, 32},
|
||||
{ 28, 81, 51, 26, 35, 33, 31},
|
||||
{ 28, 51, 81, 28, 34, 33, 30},
|
||||
{ 29, 30, 101, 28, 35, 33, 31},
|
||||
{ 31, 22, 107, 28, 35, 33, 32},
|
||||
{ 48, 27, 34, 10, 40, 16, 97},
|
||||
{ 75, 27, 34, 3, 42, 26, 66},
|
||||
{ 77, 47, 33, 12, 40, 32, 43},
|
||||
{ 49, 75, 36, 21, 37, 33, 35},
|
||||
{ 32, 72, 55, 25, 36, 33, 32},
|
||||
{ 30, 49, 81, 27, 35, 33, 31},
|
||||
{ 30, 32, 98, 28, 35, 32, 32},
|
||||
{ 31, 24, 104, 28, 35, 32, 33}
|
||||
},
|
||||
{
|
||||
{ 36, 29, 33, 43, 47, 29, 31},
|
||||
{ 74, 20, 35, 19, 47, 34, 32},
|
||||
{ 92, 35, 32, 29, 31, 40, 34},
|
||||
{ 53, 80, 26, 33, 28, 36, 37},
|
||||
{ 24, 91, 41, 31, 31, 31, 38},
|
||||
{ 25, 57, 74, 31, 32, 30, 37},
|
||||
{ 32, 28, 99, 32, 32, 29, 36},
|
||||
{ 34, 20, 105, 33, 32, 30, 35},
|
||||
{ 50, 26, 34, 33, 74, 30, 31},
|
||||
{ 75, 28, 33, 23, 46, 47, 33},
|
||||
{ 64, 58, 29, 30, 26, 46, 40},
|
||||
{ 31, 85, 37, 31, 27, 33, 44},
|
||||
{ 22, 67, 64, 30, 31, 28, 42},
|
||||
{ 29, 35, 93, 31, 32, 27, 40},
|
||||
{ 33, 20, 105, 32, 33, 27, 37},
|
||||
{ 34, 19, 106, 33, 32, 29, 36},
|
||||
{ 51, 29, 33, 25, 72, 51, 30},
|
||||
{ 61, 42, 31, 30, 31, 60, 39},
|
||||
{ 40, 70, 34, 32, 24, 41, 50},
|
||||
{ 22, 72, 54, 30, 31, 27, 50},
|
||||
{ 25, 44, 83, 30, 33, 25, 44},
|
||||
{ 32, 23, 102, 32, 33, 26, 40},
|
||||
{ 34, 18, 107, 32, 33, 28, 37},
|
||||
{ 34, 19, 105, 33, 32, 30, 35},
|
||||
{ 45, 35, 32, 30, 39, 79, 33},
|
||||
{ 43, 53, 33, 35, 24, 53, 55},
|
||||
{ 27, 67, 45, 32, 29, 27, 61},
|
||||
{ 22, 53, 72, 30, 33, 22, 52},
|
||||
{ 28, 31, 95, 31, 33, 25, 43},
|
||||
{ 32, 20, 105, 32, 33, 27, 38},
|
||||
{ 34, 18, 107, 32, 32, 29, 36},
|
||||
{ 34, 20, 105, 33, 31, 31, 35},
|
||||
{ 38, 40, 32, 35, 23, 72, 54},
|
||||
{ 31, 55, 39, 34, 29, 32, 73},
|
||||
{ 22, 57, 60, 31, 35, 18, 64},
|
||||
{ 25, 39, 86, 31, 35, 22, 49},
|
||||
{ 30, 24, 101, 32, 33, 27, 40},
|
||||
{ 33, 19, 106, 32, 32, 30, 36},
|
||||
{ 34, 18, 107, 33, 31, 31, 35},
|
||||
{ 34, 20, 104, 33, 31, 32, 34},
|
||||
{ 33, 42, 35, 34, 28, 39, 82},
|
||||
{ 26, 51, 50, 33, 34, 18, 80},
|
||||
{ 23, 46, 74, 31, 35, 20, 59},
|
||||
{ 27, 32, 93, 32, 34, 26, 44},
|
||||
{ 31, 22, 103, 32, 32, 30, 37},
|
||||
{ 33, 19, 106, 33, 31, 31, 35},
|
||||
{ 34, 19, 106, 33, 31, 32, 34},
|
||||
{ 35, 21, 103, 34, 31, 32, 34},
|
||||
{ 29, 41, 41, 33, 34, 20, 92},
|
||||
{ 24, 44, 62, 34, 35, 18, 73},
|
||||
{ 24, 37, 83, 34, 33, 25, 52},
|
||||
{ 28, 28, 97, 33, 32, 30, 40},
|
||||
{ 32, 23, 103, 33, 31, 32, 36},
|
||||
{ 34, 20, 105, 34, 30, 33, 34},
|
||||
{ 35, 20, 104, 34, 30, 33, 33},
|
||||
{ 35, 22, 102, 34, 30, 33, 34},
|
||||
{ 27, 38, 51, 34, 34, 20, 86},
|
||||
{ 26, 37, 71, 35, 34, 24, 64},
|
||||
{ 27, 33, 87, 35, 32, 30, 47},
|
||||
{ 30, 28, 96, 34, 31, 32, 39},
|
||||
{ 32, 24, 100, 35, 30, 32, 36},
|
||||
{ 34, 23, 101, 34, 30, 33, 34},
|
||||
{ 35, 23, 101, 34, 30, 32, 34},
|
||||
{ 34, 24, 99, 35, 30, 33, 34}
|
||||
},
|
||||
{
|
||||
{ 39, 30, 31, 67, 33, 34, 31},
|
||||
{ 72, 21, 32, 43, 39, 33, 31},
|
||||
{ 100, 23, 32, 35, 39, 34, 31},
|
||||
{ 75, 63, 24, 32, 38, 34, 32},
|
||||
{ 32, 98, 26, 29, 37, 35, 32},
|
||||
{ 22, 77, 55, 29, 36, 35, 31},
|
||||
{ 31, 37, 90, 31, 35, 35, 32},
|
||||
{ 35, 22, 100, 33, 33, 36, 33},
|
||||
{ 47, 29, 32, 74, 54, 32, 31},
|
||||
{ 71, 24, 32, 60, 50, 36, 30},
|
||||
{ 86, 31, 30, 46, 48, 37, 30},
|
||||
{ 65, 63, 25, 34, 46, 39, 30},
|
||||
{ 33, 85, 32, 28, 43, 40, 30},
|
||||
{ 26, 64, 60, 27, 39, 41, 30},
|
||||
{ 33, 33, 87, 29, 35, 41, 31},
|
||||
{ 37, 23, 93, 32, 33, 41, 32},
|
||||
{ 41, 32, 32, 45, 84, 32, 32},
|
||||
{ 55, 31, 32, 50, 70, 40, 30},
|
||||
{ 62, 37, 31, 45, 61, 45, 29},
|
||||
{ 53, 55, 31, 36, 55, 48, 29},
|
||||
{ 38, 63, 40, 29, 48, 50, 28},
|
||||
{ 34, 49, 60, 27, 43, 51, 29},
|
||||
{ 38, 30, 78, 28, 38, 50, 31},
|
||||
{ 40, 24, 83, 30, 36, 48, 33},
|
||||
{ 35, 33, 33, 29, 75, 58, 29},
|
||||
{ 39, 35, 33, 34, 68, 59, 29},
|
||||
{ 41, 39, 34, 36, 61, 62, 29},
|
||||
{ 41, 43, 37, 33, 54, 64, 28},
|
||||
{ 41, 43, 45, 30, 48, 65, 29},
|
||||
{ 42, 36, 56, 27, 44, 63, 30},
|
||||
{ 42, 30, 65, 27, 41, 60, 33},
|
||||
{ 42, 28, 68, 28, 37, 56, 36},
|
||||
{ 33, 34, 33, 31, 42, 88, 30},
|
||||
{ 31, 36, 34, 31, 44, 84, 31},
|
||||
{ 31, 37, 35, 32, 43, 83, 31},
|
||||
{ 35, 35, 39, 32, 40, 82, 31},
|
||||
{ 40, 32, 44, 31, 38, 81, 31},
|
||||
{ 44, 30, 48, 30, 37, 78, 33},
|
||||
{ 44, 30, 52, 28, 37, 72, 36},
|
||||
{ 43, 30, 55, 29, 35, 66, 40},
|
||||
{ 32, 33, 33, 34, 25, 85, 48},
|
||||
{ 30, 34, 34, 33, 25, 88, 44},
|
||||
{ 30, 34, 36, 34, 25, 90, 41},
|
||||
{ 33, 32, 38, 34, 25, 90, 40},
|
||||
{ 38, 29, 41, 34, 26, 88, 40},
|
||||
{ 42, 29, 41, 33, 27, 85, 41},
|
||||
{ 43, 30, 42, 31, 28, 80, 43},
|
||||
{ 42, 31, 45, 31, 30, 72, 47},
|
||||
{ 32, 33, 33, 33, 26, 54, 79},
|
||||
{ 31, 32, 34, 35, 20, 68, 68},
|
||||
{ 32, 32, 35, 36, 17, 76, 62},
|
||||
{ 34, 31, 36, 36, 17, 79, 59},
|
||||
{ 37, 29, 37, 36, 18, 78, 58},
|
||||
{ 39, 29, 37, 35, 20, 77, 58},
|
||||
{ 41, 30, 37, 34, 22, 74, 58},
|
||||
{ 40, 31, 40, 32, 26, 68, 59},
|
||||
{ 33, 31, 34, 33, 29, 31, 98},
|
||||
{ 34, 30, 34, 35, 23, 45, 88},
|
||||
{ 34, 31, 34, 36, 20, 54, 82},
|
||||
{ 35, 31, 34, 36, 18, 59, 78},
|
||||
{ 36, 31, 34, 37, 19, 60, 76},
|
||||
{ 38, 30, 34, 36, 20, 61, 74},
|
||||
{ 39, 31, 35, 35, 22, 60, 73},
|
||||
{ 39, 31, 37, 34, 24, 59, 71}
|
||||
},
|
||||
{
|
||||
{ 30, 33, 32, 55, 32, 32, 32},
|
||||
{ 47, 30, 31, 29, 36, 32, 32},
|
||||
{ 81, 28, 32, 28, 34, 32, 32},
|
||||
{ 85, 46, 29, 32, 32, 33, 32},
|
||||
{ 54, 82, 26, 32, 32, 33, 32},
|
||||
{ 30, 90, 38, 31, 32, 33, 32},
|
||||
{ 30, 56, 73, 31, 33, 32, 32},
|
||||
{ 37, 21, 102, 32, 32, 32, 32},
|
||||
{ 33, 32, 31, 68, 39, 31, 31},
|
||||
{ 38, 32, 31, 43, 34, 33, 31},
|
||||
{ 63, 30, 31, 29, 34, 32, 32},
|
||||
{ 82, 37, 30, 29, 33, 32, 32},
|
||||
{ 71, 63, 27, 31, 32, 33, 32},
|
||||
{ 44, 86, 30, 30, 33, 33, 32},
|
||||
{ 33, 72, 55, 30, 32, 32, 31},
|
||||
{ 37, 37, 86, 31, 32, 33, 31},
|
||||
{ 34, 33, 32, 60, 61, 29, 32},
|
||||
{ 36, 33, 31, 56, 38, 32, 31},
|
||||
{ 51, 30, 31, 38, 33, 33, 32},
|
||||
{ 75, 31, 31, 30, 33, 33, 32},
|
||||
{ 80, 47, 29, 30, 32, 33, 31},
|
||||
{ 60, 73, 27, 30, 33, 33, 31},
|
||||
{ 41, 78, 41, 30, 33, 32, 31},
|
||||
{ 38, 53, 68, 30, 32, 33, 31},
|
||||
{ 33, 33, 32, 43, 77, 35, 30},
|
||||
{ 35, 33, 31, 55, 54, 29, 32},
|
||||
{ 43, 32, 31, 46, 39, 31, 32},
|
||||
{ 64, 30, 31, 35, 34, 33, 32},
|
||||
{ 79, 37, 30, 31, 32, 33, 31},
|
||||
{ 73, 57, 28, 30, 32, 33, 31},
|
||||
{ 54, 73, 33, 30, 32, 33, 31},
|
||||
{ 43, 64, 52, 30, 32, 33, 31},
|
||||
{ 33, 33, 32, 34, 68, 58, 28},
|
||||
{ 34, 33, 31, 45, 70, 33, 31},
|
||||
{ 38, 33, 31, 48, 52, 29, 32},
|
||||
{ 54, 31, 31, 40, 39, 31, 32},
|
||||
{ 73, 32, 31, 34, 34, 33, 31},
|
||||
{ 77, 45, 29, 31, 32, 32, 32},
|
||||
{ 65, 63, 30, 31, 31, 33, 31},
|
||||
{ 51, 66, 42, 30, 32, 33, 31},
|
||||
{ 33, 32, 32, 34, 44, 81, 31},
|
||||
{ 34, 33, 31, 38, 66, 52, 28},
|
||||
{ 36, 33, 30, 44, 62, 34, 31},
|
||||
{ 47, 31, 31, 43, 48, 30, 32},
|
||||
{ 64, 31, 31, 38, 38, 32, 32},
|
||||
{ 75, 38, 30, 33, 34, 32, 32},
|
||||
{ 71, 53, 30, 31, 32, 33, 32},
|
||||
{ 59, 61, 37, 30, 32, 33, 32},
|
||||
{ 33, 32, 31, 35, 31, 71, 54},
|
||||
{ 34, 33, 31, 37, 49, 70, 33},
|
||||
{ 36, 33, 31, 41, 60, 48, 30},
|
||||
{ 43, 32, 31, 43, 54, 35, 31},
|
||||
{ 56, 31, 31, 40, 44, 32, 32},
|
||||
{ 68, 35, 30, 36, 37, 32, 32},
|
||||
{ 70, 45, 30, 33, 34, 33, 32},
|
||||
{ 63, 55, 35, 31, 33, 33, 32},
|
||||
{ 33, 32, 31, 33, 34, 36, 87},
|
||||
{ 34, 32, 31, 36, 38, 62, 52},
|
||||
{ 36, 33, 31, 39, 50, 57, 36},
|
||||
{ 41, 33, 31, 41, 53, 43, 33},
|
||||
{ 50, 33, 31, 41, 48, 36, 32},
|
||||
{ 59, 35, 31, 37, 41, 34, 32},
|
||||
{ 65, 42, 31, 35, 36, 33, 32},
|
||||
{ 62, 49, 35, 33, 34, 34, 33}
|
||||
}
|
||||
};
|
29
src/search.c
29
src/search.c
|
@ -161,6 +161,8 @@ static void lcu_fill_cu_info(lcu_t *lcu, int x_local, int y_local, int width, in
|
|||
to->intra.mode = cu->intra.mode;
|
||||
to->intra.mode_chroma = cu->intra.mode_chroma;
|
||||
to->intra.multi_ref_idx = cu->intra.multi_ref_idx;
|
||||
to->intra.mip_flag = cu->intra.mip_flag;
|
||||
to->intra.mip_is_transposed = cu->intra.mip_is_transposed;
|
||||
} else {
|
||||
to->skipped = cu->skipped;
|
||||
to->merged = cu->merged;
|
||||
|
@ -502,7 +504,11 @@ static double calc_mode_bits(const encoder_state_t *state,
|
|||
kvz_intra_get_dir_luma_predictor(x, y, candidate_modes, cur_cu, left_cu, above_cu);
|
||||
}
|
||||
|
||||
double mode_bits = kvz_luma_mode_bits(state, cur_cu->intra.mode, candidate_modes, cur_cu->intra.multi_ref_idx);
|
||||
int width = LCU_WIDTH >> depth;
|
||||
int height = width; // TODO: height for non-square blocks
|
||||
int num_mip_modes_half = NUM_MIP_MODES_HALF(width, height);
|
||||
int mip_flag_ctx_id = kvz_get_mip_flag_context(x, y, width, height, lcu, NULL);
|
||||
double mode_bits = kvz_luma_mode_bits(state, cur_cu->intra.mode, candidate_modes, cur_cu->intra.multi_ref_idx, num_mip_modes_half, mip_flag_ctx_id);
|
||||
|
||||
if (((depth == 4 && x % 8 && y % 8) || (depth != 4)) && state->encoder_control->chroma_format != KVZ_CSP_400) {
|
||||
mode_bits += kvz_chroma_mode_bits(state, cur_cu->intra.mode_chroma, cur_cu->intra.mode);
|
||||
|
@ -727,14 +733,18 @@ static double search_cu(encoder_state_t * const state, int x, int y, int depth,
|
|||
int8_t intra_trafo;
|
||||
double intra_cost;
|
||||
uint8_t multi_ref_index = 0;
|
||||
bool mip_flag = false;
|
||||
bool mip_transposed = false;
|
||||
kvz_search_cu_intra(state, x, y, depth, lcu,
|
||||
&intra_mode, &intra_trafo, &intra_cost, &multi_ref_index);
|
||||
&intra_mode, &intra_trafo, &intra_cost, &multi_ref_index, &mip_flag, &mip_transposed);
|
||||
if (intra_cost < cost) {
|
||||
cost = intra_cost;
|
||||
cur_cu->type = CU_INTRA;
|
||||
cur_cu->part_size = depth > MAX_DEPTH ? SIZE_NxN : SIZE_2Nx2N;
|
||||
cur_cu->intra.mode = intra_mode;
|
||||
cur_cu->intra.multi_ref_idx = multi_ref_index;
|
||||
cur_cu->intra.mip_flag = mip_flag;
|
||||
cur_cu->intra.mip_is_transposed = mip_transposed;
|
||||
|
||||
//If the CU is not split from 64x64 block, the MTS is disabled for that CU.
|
||||
cur_cu->tr_idx = (depth > 0) ? intra_trafo : 0;
|
||||
|
@ -746,12 +756,15 @@ static double search_cu(encoder_state_t * const state, int x, int y, int depth,
|
|||
if (cur_cu->type == CU_INTRA) {
|
||||
assert(cur_cu->part_size == SIZE_2Nx2N || cur_cu->part_size == SIZE_NxN);
|
||||
cur_cu->intra.mode_chroma = cur_cu->intra.mode;
|
||||
|
||||
lcu_fill_cu_info(lcu, x_local, y_local, cu_width, cu_width, cur_cu);
|
||||
kvz_intra_recon_cu(state,
|
||||
x, y,
|
||||
depth,
|
||||
cur_cu->intra.mode, -1, // skip chroma
|
||||
NULL, NULL, cur_cu->intra.multi_ref_idx, lcu);
|
||||
NULL, NULL, cur_cu->intra.multi_ref_idx,
|
||||
cur_cu->intra.mip_flag, cur_cu->intra.mip_is_transposed,
|
||||
lcu);
|
||||
|
||||
downsample_cclm_rec(
|
||||
state, x, y, cu_width / 2, cu_width / 2, lcu->rec.y, lcu->left_ref.y[64]
|
||||
|
@ -764,7 +777,7 @@ static double search_cu(encoder_state_t * const state, int x, int y, int depth,
|
|||
// into account, so there is less of a chanse of luma mode being
|
||||
// really bad for chroma.
|
||||
cclm_parameters_t cclm_params[2];
|
||||
if (ctrl->cfg.rdo >= 3) {
|
||||
if (ctrl->cfg.rdo >= 3 && !cur_cu->intra.mip_flag) {
|
||||
cur_cu->intra.mode_chroma = kvz_search_cu_intra_chroma(state, x, y, depth, lcu, cclm_params);
|
||||
lcu_fill_cu_info(lcu, x_local, y_local, cu_width, cu_width, cur_cu);
|
||||
}
|
||||
|
@ -773,7 +786,9 @@ static double search_cu(encoder_state_t * const state, int x, int y, int depth,
|
|||
x & ~7, y & ~7, // TODO: as does this
|
||||
depth,
|
||||
-1, cur_cu->intra.mode_chroma, // skip luma
|
||||
NULL, cclm_params, 0, lcu);
|
||||
NULL, cclm_params, 0,
|
||||
cur_cu->intra.mip_flag, cur_cu->intra.mip_is_transposed,
|
||||
lcu);
|
||||
}
|
||||
} else if (cur_cu->type == CU_INTER) {
|
||||
|
||||
|
@ -908,6 +923,7 @@ static double search_cu(encoder_state_t * const state, int x, int y, int depth,
|
|||
// of the top left CU from the next depth. This should ensure that 64x64
|
||||
// gets used, at least in the most obvious cases, while avoiding any
|
||||
// searching.
|
||||
|
||||
if (cur_cu->type == CU_NOTSET && depth < MAX_PU_DEPTH
|
||||
&& x + cu_width <= frame->width && y + cu_width <= frame->height && 0)
|
||||
{
|
||||
|
@ -933,7 +949,8 @@ static double search_cu(encoder_state_t * const state, int x, int y, int depth,
|
|||
x, y,
|
||||
depth,
|
||||
cur_cu->intra.mode, mode_chroma,
|
||||
NULL,NULL, 0, lcu);
|
||||
NULL,NULL, 0, cur_cu->intra.mip_flag, cur_cu->intra.mip_is_transposed,
|
||||
lcu);
|
||||
|
||||
cost += kvz_cu_rd_cost_luma(state, x_local, y_local, depth, cur_cu, lcu);
|
||||
if (has_chroma) {
|
||||
|
|
|
@ -44,6 +44,9 @@
|
|||
#include "image.h"
|
||||
#include "constraint.h"
|
||||
|
||||
#define NUM_MIP_MODES_FULL(width, height) ((width) == 4 && (height) == 4) ? 32 : ((width) == 4 || (height) == 4 || ((width) == 8 && (height) == 8) ? 16 : 12)
|
||||
#define NUM_MIP_MODES_HALF(width, height) NUM_MIP_MODES_FULL((width), (height)) >> 1
|
||||
|
||||
void kvz_sort_modes(int8_t *__restrict modes, double *__restrict costs, uint8_t length);
|
||||
void kvz_sort_modes_intra_luma(int8_t *__restrict modes, int8_t *__restrict trafo, double *__restrict costs, uint8_t length);
|
||||
|
||||
|
|
|
@ -328,12 +328,14 @@ static double search_intra_trdepth(encoder_state_t * const state,
|
|||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
kvz_intra_recon_cu(state,
|
||||
x_px, y_px,
|
||||
depth,
|
||||
intra_mode, -1,
|
||||
pred_cu, cclm_params, pred_cu->intra.multi_ref_idx, lcu);
|
||||
pred_cu, cclm_params, pred_cu->intra.multi_ref_idx,
|
||||
pred_cu->intra.mip_flag, pred_cu->intra.mip_is_transposed,
|
||||
lcu);
|
||||
|
||||
// TODO: Not sure if this should be 0 or 1 but at least seems to work with 1
|
||||
if (pred_cu->tr_idx > 1)
|
||||
|
@ -361,7 +363,9 @@ static double search_intra_trdepth(encoder_state_t * const state,
|
|||
x_px, y_px,
|
||||
depth,
|
||||
-1, chroma_mode,
|
||||
pred_cu, cclm_params, 0, lcu);
|
||||
pred_cu, cclm_params, 0,
|
||||
pred_cu->intra.mip_flag, pred_cu->intra.mip_is_transposed,
|
||||
lcu);
|
||||
best_rd_cost += kvz_cu_rd_cost_chroma(state, lcu_px.x, lcu_px.y, depth, pred_cu, lcu);
|
||||
}
|
||||
pred_cu->tr_skip = best_tr_idx == MTS_SKIP;
|
||||
|
@ -675,7 +679,7 @@ static int8_t search_intra_rough(encoder_state_t * const state,
|
|||
// affecting the halving search.
|
||||
int lambda_cost = (int)(state->lambda_sqrt + 0.5);
|
||||
for (int mode_i = 0; mode_i < modes_selected; ++mode_i) {
|
||||
costs[mode_i] += lambda_cost * kvz_luma_mode_bits(state, modes[mode_i], intra_preds, 0);
|
||||
costs[mode_i] += lambda_cost * kvz_luma_mode_bits(state, modes[mode_i], intra_preds, 0, 0, 0);
|
||||
}
|
||||
|
||||
#undef PARALLEL_BLKS
|
||||
|
@ -715,16 +719,18 @@ static int8_t search_intra_rdo(encoder_state_t * const state,
|
|||
int8_t *intra_preds,
|
||||
int modes_to_check,
|
||||
int8_t modes[67], int8_t trafo[67], double costs[67],
|
||||
int num_mip_modes_full,
|
||||
int8_t mip_modes[32], int8_t mip_trafo[32], double mip_costs[32],
|
||||
lcu_t *lcu,
|
||||
uint8_t multi_ref_idx)
|
||||
{
|
||||
const int tr_depth = CLIP(1, MAX_PU_DEPTH, depth + state->encoder_control->cfg.tr_depth_intra);
|
||||
const int width = LCU_WIDTH >> depth;
|
||||
const int height = width; // TODO: proper height for non-square blocks
|
||||
|
||||
kvz_pixel orig_block[LCU_WIDTH * LCU_WIDTH + 1];
|
||||
|
||||
// TODO: height for non-square blocks
|
||||
kvz_pixels_blit(orig, orig_block, width, width, origstride, width);
|
||||
kvz_pixels_blit(orig, orig_block, width, height, origstride, width);
|
||||
|
||||
// Check that the predicted modes are in the RDO mode list
|
||||
if (modes_to_check < 67) {
|
||||
|
@ -749,38 +755,68 @@ static int8_t search_intra_rdo(encoder_state_t * const state,
|
|||
}
|
||||
}
|
||||
|
||||
for(int rdo_mode = 0; rdo_mode < modes_to_check; rdo_mode ++) {
|
||||
int rdo_bitcost = kvz_luma_mode_bits(state, modes[rdo_mode], intra_preds, multi_ref_idx);
|
||||
// MIP_TODO: implement this inside the standard intra for loop. Code duplication is bad.
|
||||
// MIP_TODO: loop through normal intra modes first
|
||||
|
||||
for (int mip = 0; mip <= 1; mip++) {
|
||||
const int transp_off = mip ? num_mip_modes_full >> 1 : 0;
|
||||
uint8_t ctx_id = mip ? kvz_get_mip_flag_context(x_px, y_px, width, height, lcu, NULL) : 0;
|
||||
uint8_t multi_ref_index = mip ? 0 : multi_ref_idx;
|
||||
int *num_modes = mip ? &num_mip_modes_full : &modes_to_check;
|
||||
|
||||
costs[rdo_mode] = rdo_bitcost * (int)(state->lambda + 0.5);
|
||||
for (uint8_t i = 0; i < *num_modes; i++) {
|
||||
int8_t mode = mip ? mip_modes[i] : modes[i];
|
||||
double *mode_cost_p = mip ? &mip_costs[i] : &costs[i];
|
||||
int8_t *mode_trafo_p = mip ? &mip_trafo[i] : &trafo[i];
|
||||
int rdo_bitcost = kvz_luma_mode_bits(state, mode, intra_preds, multi_ref_index, transp_off, ctx_id);
|
||||
|
||||
// Perform transform split search and save mode RD cost for the best one.
|
||||
cu_info_t pred_cu;
|
||||
pred_cu.depth = depth;
|
||||
pred_cu.type = CU_INTRA;
|
||||
pred_cu.part_size = ((depth == MAX_PU_DEPTH) ? SIZE_NxN : SIZE_2Nx2N);
|
||||
pred_cu.intra.mode = modes[rdo_mode];
|
||||
pred_cu.intra.mode_chroma = modes[rdo_mode];
|
||||
pred_cu.intra.multi_ref_idx = multi_ref_idx;
|
||||
pred_cu.joint_cb_cr = 0;
|
||||
FILL(pred_cu.cbf, 0);
|
||||
*mode_cost_p = rdo_bitcost * (int)(state->lambda + 0.5);
|
||||
|
||||
// Reset transform split data in lcu.cu for this area.
|
||||
kvz_lcu_fill_trdepth(lcu, x_px, y_px, depth, depth);
|
||||
// Mip related stuff
|
||||
// There can be 32 MIP modes, but only mode numbers [0, 15] are ever written to bitstream.
|
||||
// Half of the modes [16, 31] are indicated with the separate transpose flag.
|
||||
// Number of possible modes is less for larger blocks.
|
||||
const bool is_transposed = mip ? (mode >= transp_off ? true : false) : 0;
|
||||
int8_t pred_mode = (is_transposed ? mode - transp_off : mode);
|
||||
|
||||
double mode_cost = search_intra_trdepth(state, x_px, y_px, depth, tr_depth, modes[rdo_mode], MAX_INT, &pred_cu, lcu, NULL, -1);
|
||||
costs[rdo_mode] += mode_cost;
|
||||
trafo[rdo_mode] = pred_cu.tr_idx;
|
||||
// Perform transform split search and save mode RD cost for the best one.
|
||||
cu_info_t pred_cu;
|
||||
pred_cu.depth = depth;
|
||||
pred_cu.type = CU_INTRA;
|
||||
pred_cu.part_size = ((depth == MAX_PU_DEPTH) ? SIZE_NxN : SIZE_2Nx2N); // TODO: non-square blocks
|
||||
pred_cu.intra.mode = pred_mode;
|
||||
pred_cu.intra.mode_chroma = pred_mode;
|
||||
pred_cu.intra.multi_ref_idx = multi_ref_index;
|
||||
pred_cu.intra.mip_is_transposed = is_transposed;
|
||||
pred_cu.intra.mip_flag = mip ? true : false;
|
||||
pred_cu.joint_cb_cr = 0;
|
||||
FILL(pred_cu.cbf, 0);
|
||||
|
||||
// Early termination if no coefficients has to be coded
|
||||
if (state->encoder_control->cfg.intra_rdo_et && !cbf_is_set_any(pred_cu.cbf, depth)) {
|
||||
modes_to_check = rdo_mode + 1;
|
||||
break;
|
||||
// Reset transform split data in lcu.cu for this area.
|
||||
kvz_lcu_fill_trdepth(lcu, x_px, y_px, depth, depth);
|
||||
|
||||
double mode_cost = search_intra_trdepth(state, x_px, y_px, depth, tr_depth, pred_mode, MAX_INT, &pred_cu, lcu, NULL, -1);
|
||||
*mode_cost_p += mode_cost;
|
||||
*mode_trafo_p = pred_cu.tr_idx;
|
||||
|
||||
// Early termination if no coefficients has to be coded
|
||||
if (state->encoder_control->cfg.intra_rdo_et && !cbf_is_set_any(pred_cu.cbf, depth)) {
|
||||
*num_modes = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update order according to new costs
|
||||
kvz_sort_modes_intra_luma(modes, trafo, costs, modes_to_check);
|
||||
bool use_mip = false;
|
||||
if (num_mip_modes_full) {
|
||||
kvz_sort_modes_intra_luma(mip_modes, mip_trafo, mip_costs, num_mip_modes_full);
|
||||
if (costs[0] > mip_costs[0]) {
|
||||
use_mip = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// The best transform split hierarchy is not saved anywhere, so to get the
|
||||
// transform split hierarchy the search has to be performed again with the
|
||||
|
@ -790,57 +826,110 @@ static int8_t search_intra_rdo(encoder_state_t * const state,
|
|||
pred_cu.depth = depth;
|
||||
pred_cu.type = CU_INTRA;
|
||||
pred_cu.part_size = ((depth == MAX_PU_DEPTH) ? SIZE_NxN : SIZE_2Nx2N);
|
||||
pred_cu.intra.mode = modes[0];
|
||||
pred_cu.intra.mode_chroma = modes[0];
|
||||
pred_cu.intra.multi_ref_idx = multi_ref_idx;
|
||||
if (use_mip) {
|
||||
int transp_off = num_mip_modes_full >> 1;
|
||||
bool is_transposed = (mip_modes[0] >= transp_off ? true : false);
|
||||
int8_t pred_mode = (is_transposed ? mip_modes[0] - transp_off : mip_modes[0]);
|
||||
pred_cu.intra.mode = pred_mode;
|
||||
pred_cu.intra.mode_chroma = pred_mode;
|
||||
pred_cu.intra.multi_ref_idx = 0;
|
||||
pred_cu.intra.mip_flag = true;
|
||||
pred_cu.intra.mip_is_transposed = is_transposed;
|
||||
}
|
||||
else {
|
||||
pred_cu.intra.mode = modes[0];
|
||||
pred_cu.intra.mode_chroma = modes[0];
|
||||
pred_cu.intra.multi_ref_idx = multi_ref_idx;
|
||||
pred_cu.intra.mip_flag = false;
|
||||
pred_cu.intra.mip_is_transposed = false;
|
||||
}
|
||||
FILL(pred_cu.cbf, 0);
|
||||
search_intra_trdepth(state, x_px, y_px, depth, tr_depth, modes[0], MAX_INT, &pred_cu, lcu, NULL, trafo[0]);
|
||||
search_intra_trdepth(state, x_px, y_px, depth, tr_depth, pred_cu.intra.mode, MAX_INT, &pred_cu, lcu, NULL, trafo[0]);
|
||||
}
|
||||
|
||||
// TODO: modes to check does not consider mip modes. Maybe replace with array when mip search is optimized?
|
||||
return modes_to_check;
|
||||
}
|
||||
|
||||
|
||||
double kvz_luma_mode_bits(const encoder_state_t *state, int8_t luma_mode, const int8_t *intra_preds, const uint8_t multi_ref_idx)
|
||||
double kvz_luma_mode_bits(const encoder_state_t *state, int8_t luma_mode, const int8_t *intra_preds, const uint8_t multi_ref_idx, const uint8_t num_mip_modes_half, int mip_flag_ctx_id)
|
||||
{
|
||||
double mode_bits = 0.0;
|
||||
|
||||
int8_t mode_in_preds = -1;
|
||||
for (int i = 0; i < INTRA_MPM_COUNT; ++i) {
|
||||
if (luma_mode == intra_preds[i]) {
|
||||
mode_in_preds = i;
|
||||
break;
|
||||
bool enable_mip = state->encoder_control->cfg.mip;
|
||||
bool mip_flag = enable_mip ? (num_mip_modes_half > 0 ? true : false) : false;
|
||||
|
||||
// Mip flag cost must be calculated even if mip is not used in this block
|
||||
if (enable_mip) {
|
||||
// Make a copy of state->cabac for bit cost estimation.
|
||||
cabac_data_t state_cabac_copy;
|
||||
cabac_data_t* cabac;
|
||||
memcpy(&state_cabac_copy, &state->cabac, sizeof(cabac_data_t));
|
||||
// Clear data and set mode to count only
|
||||
state_cabac_copy.only_count = 1;
|
||||
state_cabac_copy.num_buffered_bytes = 0;
|
||||
state_cabac_copy.bits_left = 23;
|
||||
|
||||
cabac = &state_cabac_copy;
|
||||
|
||||
// Do cabac writes as normal
|
||||
const int transp_off = num_mip_modes_half;
|
||||
const bool is_transposed = luma_mode >= transp_off ? true : false;
|
||||
int8_t mip_mode = is_transposed ? luma_mode - transp_off : luma_mode;
|
||||
|
||||
// Write MIP flag
|
||||
cabac->cur_ctx = &(cabac->ctx.mip_flag[mip_flag_ctx_id]);
|
||||
CABAC_BIN(cabac, mip_flag, "mip_flag");
|
||||
|
||||
if (mip_flag) {
|
||||
// Write MIP transpose flag & mode
|
||||
CABAC_BIN_EP(cabac, is_transposed, "mip_transposed");
|
||||
kvz_cabac_encode_trunc_bin(cabac, mip_mode, transp_off);
|
||||
}
|
||||
|
||||
// Write is done. Get bit cost out of cabac
|
||||
mode_bits += (23 - state_cabac_copy.bits_left) + (state_cabac_copy.num_buffered_bytes << 3);
|
||||
}
|
||||
|
||||
bool enable_mrl = state->encoder_control->cfg.mrl;
|
||||
uint8_t multi_ref_index = enable_mrl ? multi_ref_idx : 0;
|
||||
|
||||
const cabac_ctx_t* ctx = &(state->cabac.ctx.intra_luma_mpm_flag_model);
|
||||
|
||||
if (multi_ref_index == 0) {
|
||||
mode_bits += CTX_ENTROPY_FBITS(ctx, mode_in_preds != -1);
|
||||
}
|
||||
|
||||
// Add MRL bits.
|
||||
if (enable_mrl && MAX_REF_LINE_IDX > 1) {
|
||||
ctx = &(state->cabac.ctx.multi_ref_line[0]);
|
||||
mode_bits += CTX_ENTROPY_FBITS(ctx, multi_ref_index != 0);
|
||||
|
||||
if (multi_ref_index != 0 && MAX_REF_LINE_IDX > 2) {
|
||||
ctx = &(state->cabac.ctx.multi_ref_line[1]);
|
||||
mode_bits += CTX_ENTROPY_FBITS(ctx, multi_ref_index != 1);
|
||||
if (!mip_flag) {
|
||||
int8_t mode_in_preds = -1;
|
||||
for (int i = 0; i < INTRA_MPM_COUNT; ++i) {
|
||||
if (luma_mode == intra_preds[i]) {
|
||||
mode_in_preds = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mode_in_preds != -1 || multi_ref_index != 0) {
|
||||
ctx = &(state->cabac.ctx.luma_planar_model[0]);
|
||||
bool enable_mrl = state->encoder_control->cfg.mrl;
|
||||
uint8_t multi_ref_index = enable_mrl ? multi_ref_idx : 0;
|
||||
|
||||
const cabac_ctx_t* ctx = &(state->cabac.ctx.intra_luma_mpm_flag_model);
|
||||
|
||||
if (multi_ref_index == 0) {
|
||||
mode_bits += CTX_ENTROPY_FBITS(ctx, mode_in_preds>0);
|
||||
mode_bits += CTX_ENTROPY_FBITS(ctx, mode_in_preds != -1);
|
||||
}
|
||||
|
||||
// Add MRL bits.
|
||||
if (enable_mrl && MAX_REF_LINE_IDX > 1) {
|
||||
ctx = &(state->cabac.ctx.multi_ref_line[0]);
|
||||
mode_bits += CTX_ENTROPY_FBITS(ctx, multi_ref_index != 0);
|
||||
|
||||
if (multi_ref_index != 0 && MAX_REF_LINE_IDX > 2) {
|
||||
ctx = &(state->cabac.ctx.multi_ref_line[1]);
|
||||
mode_bits += CTX_ENTROPY_FBITS(ctx, multi_ref_index != 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (mode_in_preds != -1 || multi_ref_index != 0) {
|
||||
ctx = &(state->cabac.ctx.luma_planar_model[0]);
|
||||
if (multi_ref_index == 0) {
|
||||
mode_bits += CTX_ENTROPY_FBITS(ctx, mode_in_preds > 0);
|
||||
}
|
||||
mode_bits += MIN(4.0, mode_in_preds);
|
||||
}
|
||||
else {
|
||||
mode_bits += 6.0;
|
||||
}
|
||||
mode_bits += MIN(4.0,mode_in_preds);
|
||||
} else {
|
||||
mode_bits += 6.0;
|
||||
}
|
||||
|
||||
return mode_bits;
|
||||
|
@ -921,7 +1010,7 @@ int8_t kvz_search_intra_chroma_rdo(encoder_state_t * const state,
|
|||
x_px, y_px,
|
||||
depth,
|
||||
-1, chroma.mode, // skip luma
|
||||
NULL, NULL, 0, lcu);
|
||||
NULL, NULL, 0, false, false, lcu);
|
||||
}
|
||||
else {
|
||||
|
||||
|
@ -954,7 +1043,7 @@ int8_t kvz_search_intra_chroma_rdo(encoder_state_t * const state,
|
|||
x_px, y_px,
|
||||
depth,
|
||||
-1, chroma.mode, // skip luma
|
||||
NULL, cclm_params, 0, lcu);
|
||||
NULL, cclm_params, 0, false, false, lcu);
|
||||
}
|
||||
chroma.cost = kvz_cu_rd_cost_chroma(state, lcu_px.x, lcu_px.y, depth, tr_cu, lcu);
|
||||
|
||||
|
@ -1044,7 +1133,9 @@ void kvz_search_cu_intra(encoder_state_t * const state,
|
|||
int8_t *mode_out,
|
||||
int8_t *trafo_out,
|
||||
double *cost_out,
|
||||
uint8_t *multi_ref_idx_out)
|
||||
uint8_t *multi_ref_idx_out,
|
||||
bool *mip_flag_out,
|
||||
bool * mip_transposed_out)
|
||||
{
|
||||
const vector2d_t lcu_px = { SUB_SCU(x_px), SUB_SCU(y_px) };
|
||||
const int8_t cu_width = LCU_WIDTH >> depth;
|
||||
|
@ -1081,6 +1172,29 @@ void kvz_search_cu_intra(encoder_state_t * const state,
|
|||
int8_t trafo[MAX_REF_LINE_IDX][67] = { 0 };
|
||||
double costs[MAX_REF_LINE_IDX][67];
|
||||
|
||||
bool enable_mip = state->encoder_control->cfg.mip;
|
||||
// The maximum number of mip modes is 32. Max modes can be less depending on block size.
|
||||
// Half of the possible modes are transposed, which is indicated by a separate transpose flag
|
||||
int8_t mip_modes[32];
|
||||
int8_t mip_trafo[32];
|
||||
double mip_costs[32];
|
||||
|
||||
// The maximum number of possible MIP modes depend on block size & shape
|
||||
int width = LCU_WIDTH >> depth;
|
||||
int height = width; // TODO: proper height for non-square blocks.
|
||||
int num_mip_modes = 0;
|
||||
|
||||
if (enable_mip) {
|
||||
for (int i = 0; i < 32; ++i) {
|
||||
mip_modes[i] = i;
|
||||
mip_costs[i] = MAX_INT;
|
||||
}
|
||||
// MIP is not allowed for 64 x 4 or 4 x 64 blocks
|
||||
if (!((width == 64 && height == 4) || (width == 4 && height == 64))) {
|
||||
num_mip_modes = NUM_MIP_MODES_FULL(width, height);
|
||||
}
|
||||
}
|
||||
|
||||
// Find best intra mode for 2Nx2N.
|
||||
kvz_pixel *ref_pixels = &lcu->ref.y[lcu_px.x + lcu_px.y * LCU_WIDTH];
|
||||
|
||||
|
@ -1132,24 +1246,37 @@ void kvz_search_cu_intra(encoder_state_t * const state,
|
|||
}
|
||||
|
||||
for(int8_t line = 0; line < lines; ++line) {
|
||||
// For extra reference lines, only check predicted modes
|
||||
// For extra reference lines, only check predicted modes & no MIP search.
|
||||
if (line != 0) {
|
||||
number_of_modes_to_search = 0;
|
||||
num_mip_modes = 0;
|
||||
}
|
||||
int num_modes_to_check = MIN(number_of_modes[line], number_of_modes_to_search);
|
||||
kvz_sort_modes(modes[line], costs[line], number_of_modes[line]);
|
||||
// TODO: if rough search is implemented for MIP, sort mip_modes here.
|
||||
number_of_modes[line] = search_intra_rdo(state,
|
||||
x_px, y_px, depth,
|
||||
ref_pixels, LCU_WIDTH,
|
||||
candidate_modes,
|
||||
num_modes_to_check,
|
||||
modes[line], trafo[line], costs[line], lcu, line);
|
||||
modes[line], trafo[line], costs[line],
|
||||
num_mip_modes,
|
||||
mip_modes, mip_trafo, mip_costs,
|
||||
lcu, line);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t best_line = 0;
|
||||
double best_line_mode_cost = costs[0][0];
|
||||
uint8_t best_mip_mode_idx = 0;
|
||||
uint8_t best_mode_indices[MAX_REF_LINE_IDX];
|
||||
|
||||
int8_t tmp_best_mode;
|
||||
int8_t tmp_best_trafo;
|
||||
double tmp_best_cost;
|
||||
bool tmp_mip_flag = false;
|
||||
bool tmp_mip_transp = false;
|
||||
|
||||
for (int line = 0; line < lines; ++line) {
|
||||
best_mode_indices[line] = select_best_mode_index(modes[line], costs[line], number_of_modes[line]);
|
||||
if (best_line_mode_cost > costs[line][best_mode_indices[line]]) {
|
||||
|
@ -1158,8 +1285,31 @@ void kvz_search_cu_intra(encoder_state_t * const state,
|
|||
}
|
||||
}
|
||||
|
||||
*mode_out = modes[best_line][best_mode_indices[best_line]];
|
||||
*trafo_out = trafo[best_line][best_mode_indices[best_line]];
|
||||
*cost_out = costs[best_line][best_mode_indices[best_line]];
|
||||
*multi_ref_idx_out = best_line;
|
||||
tmp_best_mode = modes[best_line][best_mode_indices[best_line]];
|
||||
tmp_best_trafo = trafo[best_line][best_mode_indices[best_line]];
|
||||
tmp_best_cost = costs[best_line][best_mode_indices[best_line]];
|
||||
|
||||
if (num_mip_modes) {
|
||||
best_mip_mode_idx = select_best_mode_index(mip_modes, mip_costs, num_mip_modes);
|
||||
if (tmp_best_cost > mip_costs[best_mip_mode_idx]) {
|
||||
tmp_best_mode = mip_modes[best_mip_mode_idx];
|
||||
tmp_best_trafo = mip_trafo[best_mip_mode_idx];
|
||||
tmp_best_cost = mip_costs[best_mip_mode_idx];
|
||||
tmp_mip_flag = true;
|
||||
tmp_mip_transp = (tmp_best_mode >= (num_mip_modes >> 1)) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (tmp_mip_flag) {
|
||||
// Transform best mode index to proper form.
|
||||
// Max mode index is half of max number of modes - 1 (i. e. for size id 2, max mode id is 5)
|
||||
tmp_best_mode = (tmp_mip_transp ? tmp_best_mode - (num_mip_modes >> 1) : tmp_best_mode);
|
||||
}
|
||||
|
||||
*mode_out = tmp_best_mode;
|
||||
*trafo_out = tmp_best_trafo;
|
||||
*cost_out = tmp_best_cost;
|
||||
*mip_flag_out = tmp_mip_flag;
|
||||
*mip_transposed_out = tmp_mip_transp;
|
||||
*multi_ref_idx_out = tmp_mip_flag ? 0 : best_line;
|
||||
}
|
||||
|
|
|
@ -43,9 +43,8 @@
|
|||
#include "global.h" // IWYU pragma: keep
|
||||
#include "intra.h"
|
||||
|
||||
|
||||
double kvz_luma_mode_bits(const encoder_state_t *state,
|
||||
int8_t luma_mode, const int8_t *intra_preds, uint8_t multi_ref_idx);
|
||||
int8_t luma_mode, const int8_t *intra_preds, uint8_t multi_ref_idx, const uint8_t num_mip_modes, int mip_flag_ctx_id);
|
||||
|
||||
double kvz_chroma_mode_bits(const encoder_state_t *state,
|
||||
int8_t chroma_mode, int8_t luma_mode);
|
||||
|
@ -60,6 +59,8 @@ void kvz_search_cu_intra(encoder_state_t * const state,
|
|||
int8_t *mode_out,
|
||||
int8_t *trafo_out,
|
||||
double *cost_out,
|
||||
uint8_t *multi_ref_idx_out);
|
||||
uint8_t *multi_ref_idx_out,
|
||||
bool *mip_flag,
|
||||
bool *mip_transp);
|
||||
|
||||
#endif // SEARCH_INTRA_H_
|
||||
|
|
|
@ -11,6 +11,7 @@ valgrind_test $common_args --rd=1
|
|||
valgrind_test $common_args --rd=2 --no-transform-skip --qp 37
|
||||
valgrind_test $common_args --rd=2 --no-transform-skip --qp 37 --signhide --rdoq
|
||||
valgrind_test $common_args --rd=2 --mrl
|
||||
valgrind_test $common_args --rd=2 --mip
|
||||
valgrind_test $common_args --rd=3
|
||||
valgrind_test $common_args --alf=full --no-wpp --threads=0 --owf=0
|
||||
valgrind_test $common_args --alf=full --wpp --threads=1
|
||||
|
|
Loading…
Reference in a new issue