mirror of
https://github.com/ultravideo/uvg266.git
synced 2024-11-27 19:24:06 +00:00
[mip] Implement cabac write.
This commit is contained in:
parent
59a86f339e
commit
2daa8ad537
|
@ -107,6 +107,7 @@ typedef struct
|
||||||
cabac_ctx_t sig_coeff_group_model[4];
|
cabac_ctx_t sig_coeff_group_model[4];
|
||||||
cabac_ctx_t luma_planar_model[2];
|
cabac_ctx_t luma_planar_model[2];
|
||||||
cabac_ctx_t multi_ref_line[2];
|
cabac_ctx_t multi_ref_line[2];
|
||||||
|
cabac_ctx_t mip_flag;
|
||||||
cabac_ctx_t bdpcm_mode[4];
|
cabac_ctx_t bdpcm_mode[4];
|
||||||
cabac_ctx_t joint_cb_cr[3];
|
cabac_ctx_t joint_cb_cr[3];
|
||||||
cabac_ctx_t transform_skip_model_luma;
|
cabac_ctx_t transform_skip_model_luma;
|
||||||
|
|
|
@ -854,6 +854,39 @@ static void encode_intra_coding_unit(encoder_state_t * const state,
|
||||||
//isp_mode += ((height > TR_MAX_WIDTH) || !enough_samples) ? 2 : 0;
|
//isp_mode += ((height > TR_MAX_WIDTH) || !enough_samples) ? 2 : 0;
|
||||||
bool allow_isp = enough_samples;
|
bool allow_isp = enough_samples;
|
||||||
|
|
||||||
|
// Code MIP related bits
|
||||||
|
bool enable_mip = state->encoder_control->cfg.mip;
|
||||||
|
bool 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 < 16 && "MIP mode must be between [0, 15]");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cur_cu->type == CU_INTRA && !cur_cu->bdpcmMode && enable_mip) {
|
||||||
|
// Write MIP flag
|
||||||
|
cabac->cur_ctx = &(cabac->ctx.mip_flag);
|
||||||
|
CABAC_BIN(cabac, mip_flag, "mip_flag");
|
||||||
|
if (mip_flag) {
|
||||||
|
// Write MIP transpose flag & mode
|
||||||
|
CABAC_BIN_EP(cabac, (cur_cu->intra.mip_is_transposed), "mip_transposed");
|
||||||
|
kvz_cabac_encode_trunc_bin(cabac, mip_mode, num_mip_modes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Code MRL related bits
|
// Code MRL related bits
|
||||||
bool enable_mrl = state->encoder_control->cfg.mrl;
|
bool enable_mrl = state->encoder_control->cfg.mrl;
|
||||||
int multi_ref_idx = enable_mrl ? cur_cu->intra.multi_ref_idx : 0;
|
int multi_ref_idx = enable_mrl ? cur_cu->intra.multi_ref_idx : 0;
|
||||||
|
@ -862,7 +895,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);
|
if(multi_ref_idx) DBG_YUVIEW_VALUE(state->frame->poc, DBG_YUVIEW_MRL, x, y, width, width, multi_ref_idx);
|
||||||
#endif
|
#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) {
|
if (MAX_REF_LINE_IDX > 1) {
|
||||||
cabac->cur_ctx = &(cabac->ctx.multi_ref_line[0]);
|
cabac->cur_ctx = &(cabac->ctx.multi_ref_line[0]);
|
||||||
CABAC_BIN(cabac, multi_ref_idx != 0, "multi_ref_line");
|
CABAC_BIN(cabac, multi_ref_idx != 0, "multi_ref_line");
|
||||||
|
@ -875,7 +908,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
|
// 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) {
|
if (isp_mode) {
|
||||||
cabac->cur_ctx = &(cabac->ctx.intra_subpart_model[0]);
|
cabac->cur_ctx = &(cabac->ctx.intra_subpart_model[0]);
|
||||||
CABAC_BIN(cabac, 0, "intra_subPartitions");
|
CABAC_BIN(cabac, 0, "intra_subPartitions");
|
||||||
|
@ -890,126 +923,134 @@ 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;
|
const int cu_width = LCU_WIDTH >> depth;
|
||||||
|
// 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);
|
cabac->cur_ctx = &(cabac->ctx.intra_luma_mpm_flag_model);
|
||||||
for (int j = 0; j < num_pred_units; ++j) {
|
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]) {
|
|
||||||
|
|
||||||
const int pu_x = PU_GET_X(cur_cu->part_size, cu_width, x, 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 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* 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];
|
|
||||||
|
|
||||||
uint8_t intra_preds_temp[INTRA_MPM_COUNT+2];
|
const cu_info_t* left_pu = NULL;
|
||||||
memcpy(intra_preds_temp, intra_preds[j], sizeof(int8_t)*3);
|
const cu_info_t* above_pu = NULL;
|
||||||
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
|
if (pu_x > 0) {
|
||||||
// Sort prediction list from lowest to highest.
|
assert(pu_x >> 2 > 0);
|
||||||
if (intra_preds_temp[0] > intra_preds_temp[1]) SWAP(intra_preds_temp[0], intra_preds_temp[1], uint8_t);
|
left_pu = kvz_cu_array_at_const(frame->cu_array, pu_x - 1, pu_y + cu_width - 1);
|
||||||
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);
|
// 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
|
kvz_intra_get_dir_luma_predictor(pu_x, pu_y,
|
||||||
int32_t array1 = 0;
|
intra_preds[j],
|
||||||
int32_t array2 = 4;
|
cur_pu,
|
||||||
for (int item = 0; item < INTRA_MPM_COUNT; item++) {
|
left_pu, above_pu);
|
||||||
if (intra_preds_temp[array1] < intra_preds_temp[array2]) {
|
|
||||||
intra_preds[j][item] = intra_preds_temp[array1];
|
|
||||||
array1++;
|
intra_pred_mode_actual[j] = cur_pu->intra.mode;
|
||||||
} else {
|
|
||||||
intra_preds[j][item] = intra_preds_temp[array2];
|
for (int i = 0; i < INTRA_MPM_COUNT; i++) {
|
||||||
array2++;
|
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
|
for (int j = 0; j < num_pred_units; ++j) {
|
||||||
// prediction list, as it has been already signaled that it's not one
|
// TODO: this loop is unnecessary in VVC. Remove in future
|
||||||
// of the prediction modes.
|
assert(j == 0 && "In VVC this loop should be run only once.");
|
||||||
for (int i = INTRA_MPM_COUNT-1; i >= 0; i--) {
|
|
||||||
if (tmp_pred > intra_preds[j][i]) {
|
// Signal index of the prediction mode in the prediction list, if it is there
|
||||||
tmp_pred--;
|
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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
// Signal the actual prediction mode.
|
||||||
|
int32_t tmp_pred = intra_pred_mode[j];
|
||||||
|
|
||||||
kvz_cabac_encode_trunc_bin(cabac, tmp_pred, 67 - INTRA_MPM_COUNT);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Code chroma prediction mode.
|
// Code chroma prediction mode.
|
||||||
if (state->encoder_control->chroma_format != KVZ_CSP_400 && depth != 4) {
|
if (state->encoder_control->chroma_format != KVZ_CSP_400 && depth != 4 && !mip_flag) {
|
||||||
encode_chroma_intra_cu(cabac, cur_cu, x, y, frame, cu_width, state->encoder_control->cfg.cclm);
|
encode_chroma_intra_cu(cabac, cur_cu, x, y, frame, cu_width, state->encoder_control->cfg.cclm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1017,7 +1058,7 @@ static void encode_intra_coding_unit(encoder_state_t * const state,
|
||||||
|
|
||||||
encode_mts_idx(state, cabac, cur_cu);
|
encode_mts_idx(state, cabac, cur_cu);
|
||||||
|
|
||||||
if (state->encoder_control->chroma_format != KVZ_CSP_400 && depth == 4 && x % 8 && y % 8) {
|
if (state->encoder_control->chroma_format != KVZ_CSP_400 && depth == 4 && x % 8 && y % 8 && !mip_flag) {
|
||||||
encode_chroma_intra_cu(cabac, cur_cu, x, y, frame, cu_width, state->encoder_control->cfg.cclm);
|
encode_chroma_intra_cu(cabac, cur_cu, x, y, frame, cu_width, state->encoder_control->cfg.cclm);
|
||||||
encode_transform_coeff(state, x, y, depth, 0, 0, 0, 1, coeff);
|
encode_transform_coeff(state, x, y, depth, 0, 0, 0, 1, coeff);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue