Changed intra coding to use 6 MPM, implemented merge sort and MPM selection

This commit is contained in:
Marko Viitanen 2019-03-20 15:20:31 +02:00
parent 1081336868
commit d15f58517f
3 changed files with 90 additions and 28 deletions

View file

@ -966,7 +966,7 @@ static void encode_intra_coding_unit(encoder_state_t * const state,
uint8_t *intra_pred_mode = intra_pred_mode_actual; uint8_t *intra_pred_mode = intra_pred_mode_actual;
uint8_t intra_pred_mode_chroma = cur_cu->intra.mode_chroma; uint8_t intra_pred_mode_chroma = cur_cu->intra.mode_chroma;
int8_t intra_preds[4][3] = {{-1, -1, -1},{-1, -1, -1},{-1, -1, -1},{-1, -1, -1}}; int8_t intra_preds[4][INTRA_MPM_COUNT] = {{-1, -1, -1, -1, -1, -1},{-1, -1, -1, -1, -1, -1},{-1, -1, -1, -1, -1, -1},{-1, -1, -1, -1, -1, -1}};
int8_t mpm_preds[4] = {-1, -1, -1, -1}; int8_t mpm_preds[4] = {-1, -1, -1, -1};
uint32_t flag[4]; uint32_t flag[4];
@ -987,6 +987,7 @@ static void encode_intra_coding_unit(encoder_state_t * const state,
// If intra prediction mode is found from the predictors, // If intra prediction mode is found from the predictors,
// it can be signaled with two EP's. Otherwise we can send // it can be signaled with two EP's. Otherwise we can send
// 5 EP bins with the full predmode // 5 EP bins with the full predmode
// ToDo: fix comments for VVC
const int num_pred_units = kvz_part_mode_num_parts[cur_cu->part_size]; const int num_pred_units = kvz_part_mode_num_parts[cur_cu->part_size];
const int cu_width = LCU_WIDTH >> depth; const int cu_width = LCU_WIDTH >> depth;
@ -1017,7 +1018,7 @@ static void encode_intra_coding_unit(encoder_state_t * const state,
intra_pred_mode_actual[j] = cur_pu->intra.mode; intra_pred_mode_actual[j] = cur_pu->intra.mode;
for (int i = 0; i < 3; i++) { for (int i = 0; i < INTRA_MPM_COUNT; i++) {
if (intra_preds[j][i] == intra_pred_mode[j]) { if (intra_preds[j][i] == intra_pred_mode[j]) {
mpm_preds[j] = (int8_t)i; mpm_preds[j] = (int8_t)i;
break; break;
@ -1035,28 +1036,59 @@ static void encode_intra_coding_unit(encoder_state_t * const state,
for (int j = 0; j < num_pred_units; ++j) { for (int j = 0; j < num_pred_units; ++j) {
// Signal index of the prediction mode in the prediction list. // Signal index of the prediction mode in the prediction list.
if (flag[j]) { if (flag[j]) {
CABAC_BIN_EP(cabac, (mpm_preds[j] == 0 ? 0 : 1), "mpm_idx"); CABAC_BIN_EP(cabac, (mpm_preds[j] > 0 ? 1 : 0), "mpm_idx");
if (mpm_preds[j] != 0) { if (mpm_preds[j] > 0) {
CABAC_BIN_EP(cabac, (mpm_preds[j] == 1 ? 0 : 1), "mpm_idx"); CABAC_BIN_EP(cabac, (mpm_preds[j] > 1 ? 1 : 0), "mpm_idx");
} else if (mpm_preds[j] > 1) {
CABAC_BIN_EP(cabac, (mpm_preds[j] > 2 ? 1 : 0), "mpm_idx");
} else if (mpm_preds[j] > 2) {
CABAC_BIN_EP(cabac, (mpm_preds[j] > 3 ? 1 : 0), "mpm_idx");
} else if (mpm_preds[j] > 3) {
CABAC_BIN_EP(cabac, (mpm_preds[j] > 4 ? 1 : 0), "mpm_idx");
} }
} else { } else {
// Signal the actual prediction mode. // Signal the actual prediction mode.
int32_t tmp_pred = intra_pred_mode[j]; 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. // Sort prediction list from lowest to highest.
if (intra_preds[j][0] > intra_preds[j][1]) SWAP(intra_preds[j][0], intra_preds[j][1], int8_t); if (intra_preds_temp[0] > intra_preds_temp[1]) SWAP(intra_preds_temp[0], intra_preds_temp[1], int8_t);
if (intra_preds[j][0] > intra_preds[j][2]) SWAP(intra_preds[j][0], intra_preds[j][2], int8_t); if (intra_preds_temp[0] > intra_preds_temp[2]) SWAP(intra_preds_temp[0], intra_preds_temp[2], int8_t);
if (intra_preds[j][1] > intra_preds[j][2]) SWAP(intra_preds[j][1], intra_preds[j][2], int8_t); if (intra_preds_temp[1] > intra_preds_temp[2]) SWAP(intra_preds_temp[1], intra_preds_temp[2], int8_t);
if (intra_preds_temp[4] > intra_preds_temp[5]) SWAP(intra_preds_temp[4], intra_preds_temp[5], int8_t);
if (intra_preds_temp[4] > intra_preds_temp[6]) SWAP(intra_preds_temp[4], intra_preds_temp[6], int8_t);
if (intra_preds_temp[5] > intra_preds_temp[6]) SWAP(intra_preds_temp[5], intra_preds_temp[6], int8_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 // Reduce the index of the signaled prediction mode according to the
// prediction list, as it has been already signaled that it's not one // prediction list, as it has been already signaled that it's not one
// of the prediction modes. // of the prediction modes.
for (int i = 2; i >= 0; i--) { for (int i = INTRA_MPM_COUNT-1; i >= 0; i--) {
tmp_pred = (tmp_pred > intra_preds[j][i] ? tmp_pred - 1 : tmp_pred); if (tmp_pred > intra_preds[j][i]) {
tmp_pred--;
}
} }
CABAC_BINS_EP(cabac, tmp_pred, 6, "rem_intra_luma_pred_mode"); kvz_cabac_encode_trunc_bin(cabac, tmp_pred, 67 - INTRA_MPM_COUNT);
} }
} }

View file

@ -159,6 +159,12 @@ typedef int16_t coeff_t;
#define LCU_LUMA_SIZE (LCU_WIDTH * LCU_WIDTH) #define LCU_LUMA_SIZE (LCU_WIDTH * LCU_WIDTH)
#define LCU_CHROMA_SIZE (LCU_WIDTH * LCU_WIDTH >> 2) #define LCU_CHROMA_SIZE (LCU_WIDTH * LCU_WIDTH >> 2)
/**
* \brief Number of Most Probable Modes in Intra coding
*
*/
#define INTRA_MPM_COUNT 6
/** /**
* \brief Number of pixels to delay deblocking. * \brief Number of pixels to delay deblocking.
* *
@ -185,7 +191,7 @@ typedef int16_t coeff_t;
#define AMVP_MAX_NUM_CANDS 2 #define AMVP_MAX_NUM_CANDS 2
#define AMVP_MAX_NUM_CANDS_MEM 3 #define AMVP_MAX_NUM_CANDS_MEM 3
#define MRG_MAX_NUM_CANDS 5 #define MRG_MAX_NUM_CANDS 7
/* Some tools */ /* Some tools */
#define ABS(a) ((a) >= 0 ? (a) : (-a)) #define ABS(a) ((a) >= 0 ? (a) : (-a))

View file

@ -77,13 +77,19 @@ int8_t kvz_intra_get_dir_luma_predictor(
const cu_info_t *const left_pu, const cu_info_t *const left_pu,
const cu_info_t *const above_pu) const cu_info_t *const above_pu)
{ {
// The default mode if block is not coded yet is INTRA_DC. enum {
int8_t left_intra_dir = 1; PLANAR_IDX = 0,
DC_IDX = 1,
HOR_IDX = 18,
VER_IDX = 50,
};
// The default mode if block is not coded yet is INTRA_PLANAR.
int8_t left_intra_dir = 0;
if (left_pu && left_pu->type == CU_INTRA) { if (left_pu && left_pu->type == CU_INTRA) {
left_intra_dir = left_pu->intra.mode; left_intra_dir = left_pu->intra.mode;
} }
int8_t above_intra_dir = 1; int8_t above_intra_dir = 0;
if (above_pu && above_pu->type == CU_INTRA && y % LCU_WIDTH != 0) { if (above_pu && above_pu->type == CU_INTRA && y % LCU_WIDTH != 0) {
above_intra_dir = above_pu->intra.mode; above_intra_dir = above_pu->intra.mode;
} }
@ -91,26 +97,44 @@ int8_t kvz_intra_get_dir_luma_predictor(
const int offset = 61; const int offset = 61;
const int mod = 64; const int mod = 64;
preds[0] = left_intra_dir;
preds[1] = (preds[0] == PLANAR_IDX) ? DC_IDX : PLANAR_IDX;
preds[2] = VER_IDX;
preds[3] = HOR_IDX;
preds[4] = VER_IDX - 4;
preds[5] = VER_IDX + 4;
// If the predictions are the same, add new predictions // If the predictions are the same, add new predictions
if (left_intra_dir == above_intra_dir) { if (left_intra_dir == above_intra_dir) {
if (left_intra_dir > 1) { // angular modes if (left_intra_dir > DC_IDX) { // angular modes
preds[0] = left_intra_dir; preds[0] = left_intra_dir;
preds[1] = ((left_intra_dir + offset) % mod) + 2; preds[1] = PLANAR_IDX;
preds[2] = ((left_intra_dir - 1 ) % mod) + 2; preds[2] = DC_IDX;
} else { //non-angular preds[3] = ((left_intra_dir + offset) % mod) + 2;
preds[0] = 0;//PLANAR_IDX; preds[4] = ((left_intra_dir - 1) % mod) + 2;
preds[1] = 1;//DC_IDX; preds[5] = ((left_intra_dir + offset - 1) % mod) + 2;
preds[2] = 50;//VER_IDX;
} }
} else { // If we have two distinct predictions } else { // If we have two distinct predictions
preds[0] = left_intra_dir; preds[0] = left_intra_dir;
preds[1] = above_intra_dir; preds[1] = above_intra_dir;
bool max_cand_mode_idx = preds[0] > preds[1] ? 0 : 1;
// add planar mode if it's not yet present if (left_intra_dir > DC_IDX && above_intra_dir > DC_IDX) {
if (left_intra_dir && above_intra_dir ) { preds[2] = PLANAR_IDX;
preds[2] = 0; // PLANAR_IDX; preds[3] = DC_IDX;
if ((preds[max_cand_mode_idx] - preds[!max_cand_mode_idx] < 63) && (preds[max_cand_mode_idx] - preds[!max_cand_mode_idx] > 1)) {
preds[4] = ((preds[max_cand_mode_idx] + offset) % mod) + 2;
preds[5] = ((preds[max_cand_mode_idx] - 1) % mod) + 2;
} else {
preds[4] = ((preds[max_cand_mode_idx] + offset - 1) % mod) + 2;
preds[5] = ((preds[max_cand_mode_idx]) % mod) + 2;
}
} else { // Add DC mode if it's not present, otherwise VER_IDX. } else { // Add DC mode if it's not present, otherwise VER_IDX.
preds[2] = (left_intra_dir+above_intra_dir)<2? 50 : 1; preds[2] = (preds[!max_cand_mode_idx] == PLANAR_IDX) ? DC_IDX : PLANAR_IDX;
preds[3] = ((preds[max_cand_mode_idx] + offset) % mod) + 2;
preds[4] = ((preds[max_cand_mode_idx] - 1) % mod) + 2;
preds[5] = ((preds[max_cand_mode_idx] + offset - 1) % mod) + 2;
} }
} }