mirror of
https://github.com/ultravideo/uvg266.git
synced 2024-11-27 11:24:05 +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 luma_planar_model[2];
|
||||
cabac_ctx_t multi_ref_line[2];
|
||||
cabac_ctx_t mip_flag;
|
||||
cabac_ctx_t bdpcm_mode[4];
|
||||
cabac_ctx_t joint_cb_cr[3];
|
||||
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;
|
||||
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
|
||||
bool enable_mrl = state->encoder_control->cfg.mrl;
|
||||
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);
|
||||
#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 +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
|
||||
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,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;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
@ -1017,7 +1058,7 @@ static void encode_intra_coding_unit(encoder_state_t * const state,
|
|||
|
||||
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_transform_coeff(state, x, y, depth, 0, 0, 0, 1, coeff);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue