Skip to content

Commit

Permalink
Add intra prediction modes encryption
Browse files Browse the repository at this point in the history
  • Loading branch information
Pierre-Loup Cabarat committed Mar 6, 2017
1 parent aae141f commit 2b8ce5e
Show file tree
Hide file tree
Showing 6 changed files with 275 additions and 2 deletions.
2 changes: 1 addition & 1 deletion src/cfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ int kvz_config_parse(kvz_config *cfg, const char *name, const char *value)

static const char * const cu_split_termination_names[] = { "zero", "off", NULL };
static const char * const crypto_toggle_names[] = { "off", "on", NULL };
static const char * const crypto_feature_names[] = { "mvs", "mv_signs", "trans_coeffs", "trans_coeff_signs", NULL };
static const char * const crypto_feature_names[] = { "mvs", "mv_signs", "trans_coeffs", "trans_coeff_signs", "intra_pred_modes", NULL };

static const char * const me_early_termination_names[] = { "off", "on", "sensitive", NULL };

Expand Down
3 changes: 3 additions & 0 deletions src/cu.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,9 @@ typedef struct
int8_t mode;
int8_t mode_chroma;
int8_t tr_skip; //!< \brief transform skip flag
#if KVZ_SEL_ENCRYPTION
int8_t mode_encry;
#endif
} intra;
struct {
int16_t mv[2][2]; // \brief Motion vectors for L0 and L1
Expand Down
202 changes: 202 additions & 0 deletions src/encode_coding_tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -694,6 +694,201 @@ static void encode_inter_prediction_unit(encoder_state_t * const state,
} // if !merge
}

#if KVZ_SEL_ENCRYPTION
static uint8_t inline intra_mode_encryption(encoder_state_t * const state,
uint8_t intra_pred_mode)
{
const uint8_t sets[3][17] =
{
{ 0, 1, 2, 3, 4, 5, 15, 16, 17, 18, 19, 20, 21, 31, 32, 33, 34}, /* 17 */
{ 22, 23, 24, 25, 27, 28, 29, 30, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 9 */
{ 6, 7, 8, 9, 11, 12, 13, 14, -1, -1, -1, -1, -1, -1, -1, -1, -1} /* 9 */
};

const uint8_t nb_elems[3] = {17, 8, 8};

if(intra_pred_mode == 26 || intra_pred_mode == 10) /* for correct chroma Inra prediction mode */
return intra_pred_mode;
else {
uint8_t keybits, scan_dir, elem_idx=0;

keybits = ff_get_key(&state->tile->dbs_g, 5);

scan_dir = SCAN_DIAG;
if (intra_pred_mode > 5 && intra_pred_mode < 15 )
scan_dir = SCAN_VER;
if (intra_pred_mode > 21 && intra_pred_mode < 31 )
scan_dir = SCAN_HOR;

for (int i = 0; i < nb_elems[scan_dir]; i++) {
if (intra_pred_mode == sets[scan_dir][i]) {
elem_idx = i;
break;
}
}

keybits = keybits % nb_elems[scan_dir];
keybits = (elem_idx + keybits) % nb_elems[scan_dir];

return sets[scan_dir][keybits];
}
}

static void encode_intra_coding_unit_encry(encoder_state_t * const state,
cabac_data_t * const cabac,
const cu_info_t * const cur_cu,
int x_ctb, int y_ctb, int depth)
{
const videoframe_t * const frame = state->tile->frame;
uint8_t intra_pred_mode[4];
uint8_t intra_pred_mode_encry[4] = {-1, -1, -1, -1};
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 mpm_preds[4] = {-1, -1, -1, -1};
uint32_t flag[4];

#if ENABLE_PCM == 1
// Code must start after variable initialization
kvz_cabac_encode_bin_trm(cabac, 0); // IPCMFlag == 0
#endif

// 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
const int num_pred_units = kvz_part_mode_num_parts[cur_cu->part_size];
const int cu_width = LCU_WIDTH >> depth;

for (int j = 0; j < num_pred_units; ++j) {
const int pu_x = PU_GET_X(cur_cu->part_size, cu_width, x_ctb << 3, j);
const int pu_y = PU_GET_Y(cur_cu->part_size, cu_width, y_ctb << 3, j);
cu_info_t *cur_pu = kvz_cu_array_at(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);
}
// 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, pu_y - 1);
}

kvz_intra_get_dir_luma_predictor_encry(pu_x, pu_y,
intra_preds[j],
(const cu_info_t *)cur_pu,
left_pu, above_pu);

intra_pred_mode[j] = cur_pu->intra.mode;

intra_pred_mode_encry[j] = intra_mode_encryption(state, intra_pred_mode[j]);

for (int i = 0; i < 3; i++) {
if (intra_preds[j][i] == intra_pred_mode_encry[j]) {
mpm_preds[j] = (int8_t)i;
break;
}
}
flag[j] = (mpm_preds[j] == -1) ? 0 : 1;
//Set the modified intra_pred_mode of the current pu here to make it available
// from its neighbours for mpm decision
cur_pu->intra.mode_encry=intra_pred_mode_encry[j];
if (cur_pu->part_size!=SIZE_NxN){
cu_info_t *cu = cur_pu;
//FIXME: there might be a more efficient way to propagate mode_encry for
//future use from left and above PUs
for (int y = pu_y; y < pu_y + cu_width; y += 4 ) {
for (int x = pu_x; x < pu_x + cu_width; x += 4) {
cu = (cu_info_t *)kvz_cu_array_at(frame->cu_array, x, y);
cu->intra.mode_encry = intra_pred_mode_encry[j];
}
}
}
}

cabac->cur_ctx = &(cabac->ctx.intra_mode_model);
for (int j = 0; j < num_pred_units; ++j) {
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 (flag[j]) {
CABAC_BIN_EP(cabac, (mpm_preds[j] == 0 ? 0 : 1), "mpm_idx");
if (mpm_preds[j] != 0) {
CABAC_BIN_EP(cabac, (mpm_preds[j] == 1 ? 0 : 1), "mpm_idx");
}
} else {
// Signal the modified prediction mode.
int32_t tmp_pred = intra_pred_mode_encry[j];

// 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[j][0] > intra_preds[j][2]) SWAP(intra_preds[j][0], intra_preds[j][2], int8_t);
if (intra_preds[j][1] > intra_preds[j][2]) SWAP(intra_preds[j][1], intra_preds[j][2], int8_t);

// 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 = 2; i >= 0; i--) {
tmp_pred = (tmp_pred > intra_preds[j][i] ? tmp_pred - 1 : tmp_pred);
}

CABAC_BINS_EP(cabac, tmp_pred, 5, "rem_intra_luma_pred_mode");
}
}

// Code chroma prediction mode.
if (state->encoder_control->chroma_format != KVZ_CSP_400) {
unsigned pred_mode = 5;
unsigned chroma_pred_modes[4] = {0, 26, 10, 1};

if (intra_pred_mode_chroma == intra_pred_mode[0]) {
pred_mode = 4;
} else if (intra_pred_mode_chroma == 34) {
// Angular 34 mode is possible only if intra pred mode is one of the
// possible chroma pred modes, in which case it is signaled with that
// duplicate mode.
for (int i = 0; i < 4; ++i) {
if (intra_pred_mode[0] == chroma_pred_modes[i]) pred_mode = i;
}
} else {
for (int i = 0; i < 4; ++i) {
if (intra_pred_mode_chroma == chroma_pred_modes[i]) pred_mode = i;
}
}

// pred_mode == 5 mean intra_pred_mode_chroma is something that can't
// be coded.
assert(pred_mode != 5);

/**
* Table 9-35 - Binarization for intra_chroma_pred_mode
* intra_chroma_pred_mode bin_string
* 4 0
* 0 100
* 1 101
* 2 110
* 3 111
* Table 9-37 - Assignment of ctxInc to syntax elements with context coded bins
* intra_chroma_pred_mode[][] = 0, bypass, bypass
*/
cabac->cur_ctx = &(cabac->ctx.chroma_pred_model[0]);
if (pred_mode == 4) {
CABAC_BIN(cabac, 0, "intra_chroma_pred_mode");
} else {
CABAC_BIN(cabac, 1, "intra_chroma_pred_mode");
CABAC_BINS_EP(cabac, pred_mode, 2, "intra_chroma_pred_mode");
}
}

encode_transform_coeff(state, x_ctb * 2, y_ctb * 2, depth, 0, 0, 0);
}
#endif

static void encode_intra_coding_unit(encoder_state_t * const state,
cabac_data_t * const cabac,
const cu_info_t * const cur_cu,
Expand All @@ -706,6 +901,13 @@ static void encode_intra_coding_unit(encoder_state_t * const state,
int8_t intra_preds[4][3] = {{-1, -1, -1},{-1, -1, -1},{-1, -1, -1},{-1, -1, -1}};
int8_t mpm_preds[4] = {-1, -1, -1, -1};
uint32_t flag[4];
#if KVZ_SEL_ENCRYPTION
if(!state->cabac.only_count)
if (state->encoder_control->cfg.crypto_features & KVZ_CRYPTO_INTRA_MODE) {
encode_intra_coding_unit_encry(state, cabac, (cu_info_t *)cur_cu, x_ctb, y_ctb, depth);
return;
}
#endif

#if ENABLE_PCM == 1
// Code must start after variable initialization
Expand Down
46 changes: 46 additions & 0 deletions src/intra.c
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,52 @@ int8_t kvz_intra_get_dir_luma_predictor(
return 1;
}

#if KVZ_SEL_ENCRYPTION
int8_t kvz_intra_get_dir_luma_predictor_encry(
const uint32_t x,
const uint32_t y,
int8_t *preds,
const cu_info_t *const cur_pu,
const cu_info_t *const left_pu,
const cu_info_t *const above_pu)
{
// The default mode if block is not coded yet is INTRA_DC.
int8_t left_intra_dir = 1;
if (left_pu && left_pu->type == CU_INTRA) {
left_intra_dir = left_pu->intra.mode_encry ;
}

int8_t above_intra_dir = 1;
if (above_pu && above_pu->type == CU_INTRA && y % LCU_WIDTH != 0) {
above_intra_dir = above_pu->intra.mode_encry;
}

// If the predictions are the same, add new predictions
if (left_intra_dir == above_intra_dir) {
if (left_intra_dir > 1) { // angular modes
preds[0] = left_intra_dir;
preds[1] = ((left_intra_dir + 29) % 32) + 2;
preds[2] = ((left_intra_dir - 1 ) % 32) + 2;
} else { //non-angular
preds[0] = 0;//PLANAR_IDX;
preds[1] = 1;//DC_IDX;
preds[2] = 26;//VER_IDX;
}
} else { // If we have two distinct predictions
preds[0] = left_intra_dir;
preds[1] = above_intra_dir;

// add planar mode if it's not yet present
if (left_intra_dir && above_intra_dir ) {
preds[2] = 0; // PLANAR_IDX;
} else { // Add DC mode if it's not present, otherwise 26.
preds[2] = (left_intra_dir+above_intra_dir)<2? 26 : 1;
}
}

return 1;
}
#endif

static void intra_filter_reference(
int_fast8_t log2_width,
Expand Down
20 changes: 20 additions & 0 deletions src/intra.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,26 @@ int8_t kvz_intra_get_dir_luma_predictor(
const cu_info_t *const left_pu,
const cu_info_t *const above_pu);

#if KVZ_SEL_ENCRYPTION
/**
* \brief Function for deriving intra luma predictions with encryption
* \param x x-coordinate of the PU in pixels
* \param y y-coordinate of the PU in pixels
* \param preds output buffer for 3 predictions
* \param cur_pu PU to check
* \param left_pu PU to the left of cur_pu
* \param above_pu PU above cur_pu
* \returns 1 if predictions are found, otherwise 0
*/
int8_t kvz_intra_get_dir_luma_predictor_encry(
const uint32_t x,
const uint32_t y,
int8_t *preds,
const cu_info_t *const cur_pu,
const cu_info_t *const left_pu,
const cu_info_t *const above_pu);
#endif

/**
* \brief Generage angular predictions.
* \param width Width in pixels, range 4..32.
Expand Down
4 changes: 3 additions & 1 deletion src/kvazaar.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,9 @@ enum kvz_crypto_features {
KVZ_CRYPTO_MV_SIGNS = (1 << 1),
KVZ_CRYPTO_TRANSF_COEFFS = (1 << 2),
KVZ_CRYPTO_TRANSF_COEFF_SIGNS = (1 << 3),
KVZ_CRYPTO_ON = (1 << 4) - 1,
KVZ_CRYPTO_INTRA_MODE = (1 << 4),
KVZ_CRYPTO_ON = (1 << 5) - 1,

};

/**
Expand Down

0 comments on commit 2b8ce5e

Please sign in to comment.