Converted kvz_encode_coeff_nxn and related helper functions to VVC K0072 format

This commit is contained in:
Marko Viitanen 2018-08-30 14:24:03 +03:00
parent 84e78c6c50
commit 0680f240d7
5 changed files with 184 additions and 127 deletions

View file

@ -256,29 +256,35 @@ void kvz_cabac_encode_bins_ep(cabac_data_t * const data, uint32_t bin_values, in
}
/**
* \brief Coding of coeff_abs_level_minus3.
* \param symbol Value of coeff_abs_level_minus3.
* \param r_param Reference to Rice parameter.
* \brief Coding of remainder abs coeff value.
* \param remainder Value of remaining abs coeff
* \param rice_param Reference to Rice parameter.
*/
void kvz_cabac_write_coeff_remain(cabac_data_t * const cabac, const uint32_t symbol, const uint32_t r_param)
void kvz_cabac_write_coeff_remain(cabac_data_t * const cabac, const uint32_t remainder, const uint32_t rice_param)
{
int32_t code_number = symbol;
uint32_t length;
const unsigned threshold = g_go_rice_range[rice_param] << rice_param;
uint32_t bins = remainder;
if (code_number < (3 << r_param)) {
length = code_number >> r_param;
CABAC_BINS_EP(cabac, (1 << (length + 1)) - 2 , length + 1, "coeff_abs_level_remaining");
CABAC_BINS_EP(cabac, (code_number % (1 << r_param)), r_param, "coeff_abs_level_remaining");
} else {
length = r_param;
code_number = code_number - (3 << r_param);
while (code_number >= (1 << length)) {
code_number -= 1 << length;
++length;
if (bins < threshold) {
uint32_t length = (bins >> rice_param) + 1;
CABAC_BINS_EP(cabac, ((1 << (length)) - 2) , length, "coeff_abs_level_remaining");
CABAC_BINS_EP(cabac, bins & ((1 << rice_param) - 1), rice_param, "coeff_abs_level_remaining");
}
//ToDo: else if (useLimitedPrefixLength)
else {
uint32_t length = rice_param;
uint32_t delta = 1 << length;
bins -= threshold;
while (bins >= delta) {
bins -= delta;
delta = 1 << (++length);
}
CABAC_BINS_EP(cabac, (1 << (3 + length + 1 - r_param)) - 2, 3 + length + 1 - r_param, "coeff_abs_level_remaining");
CABAC_BINS_EP(cabac, code_number, length, "coeff_abs_level_remaining");
}
uint32_t num_bins = g_go_rice_range[rice_param] + length + 1 - rice_param;
CABAC_BINS_EP(cabac, (1 << num_bins) - 2, num_bins, "coeff_abs_level_remaining");
CABAC_BINS_EP(cabac, bins, length, "coeff_abs_level_remaining");
}
}
void kvz_cabac_write_coeff_remain_encry(struct encoder_state_t * const state, cabac_data_t * const cabac,const uint32_t symbol, const uint32_t r_param, int32_t base_level)

View file

@ -455,12 +455,13 @@ int32_t kvz_context_get_sig_ctx_inc(int32_t pattern_sig_ctx, uint32_t scan_idx,
* \param width width of the block
* \param height height of the block
* \param type texture type (TEXT_LUMA...)
* \param cabac current cabac state struct
* \param temp_diag temporary output value used in the next steps
* \param temp_sum temporary output value used in the next steps
* \returns context index for current scan position
*/
uint32_t kvz_context_get_sig_ctx_idx_abs(const coeff_t* coeff, int32_t pos_x, int32_t pos_y,
uint32_t height, uint32_t width, int8_t type, cabac_data_t* cabac)
uint32_t kvz_context_get_sig_ctx_idx_abs(const coeff_t* coeff, int32_t pos_x, int32_t pos_y,
uint32_t height, uint32_t width, int8_t type,
int32_t* temp_diag, int32_t* temp_sum)
{
const coeff_t* data = coeff + pos_x + pos_y * width;
const int diag = pos_x + pos_y;
@ -494,5 +495,47 @@ uint32_t kvz_context_get_sig_ctx_idx_abs(const coeff_t* coeff, int32_t pos_x, in
ctx_ofs += diag < 5 ? 6 : 0;
}
*temp_diag = diag;
*temp_sum = sum_abs - num_pos;
return ctx_ofs;
}
/**
* \brief Calculate Go rice parameter for remainder coefficient value coding
* \param coeff pointer to the current coefficient
* \param pos_x column of current scan position
* \param pos_y row of current scan position
* \param width width of the block
* \param height height of the block
* \returns context go rice parameter
*/
uint32_t kvz_go_rice_par_abs(const coeff_t* coeff, int32_t pos_x, int32_t pos_y,
uint32_t height, uint32_t width)
{
#define UPDATE(x) sum+=abs(x)-(x?1:0)
const coeff_t* data = coeff + pos_x + pos_y * width;
int sum = 0;
if (pos_x < width - 1)
{
UPDATE(data[1]);
if (pos_x < width - 2)
{
UPDATE(data[2]);
}
if (pos_y < height - 1)
{
UPDATE(data[width + 1]);
}
}
if (pos_y < height - 1)
{
UPDATE(data[width]);
if (pos_y < height - 2)
{
UPDATE(data[width << 1]);
}
}
#undef UPDATE
return g_go_rice_pars[MIN(sum, 31)];
}

View file

@ -45,7 +45,11 @@ int32_t kvz_context_get_sig_ctx_inc(int32_t pattern_sig_ctx,uint32_t scan_idx,in
int32_t pos_y,int32_t block_type, int8_t texture_type);
uint32_t kvz_context_get_sig_ctx_idx_abs(const coeff_t* coeff, int32_t pos_x, int32_t pos_y,
uint32_t height, uint32_t width, int8_t type, cabac_data_t* cabac);
uint32_t height, uint32_t width, int8_t type,
int32_t* temp_diag, int32_t* temp_sum);
uint32_t kvz_go_rice_par_abs(const coeff_t* coeff, int32_t pos_x, int32_t pos_y,
uint32_t height, uint32_t width);
#define CNU 154

View file

@ -131,7 +131,7 @@ void kvz_encode_coeff_nxn(encoder_state_t * const state,
uint32_t sig_coeffgroup_flag[8 * 8] = { 0 };
int8_t be_valid = 0;// encoder->cfg.signhide_enable; //ToDo: Enable signhide?
int32_t scan_pos_sig;
int32_t scan_pos;
uint32_t go_rice_param = 0;
uint32_t blk_pos, pos_y, pos_x, sig, ctx_sig;
@ -202,10 +202,11 @@ void kvz_encode_coeff_nxn(encoder_state_t * const state,
type,
scan_mode);
scan_pos_sig = scan_pos_last;
scan_pos = scan_pos_last;
uint32_t quant_state_transition_table = 0; //ToDo: dep quant enable changes this
uint32_t quant_state = 0;
uint8_t ctx_offset[16];
// significant_coeff_flag
for (i = scan_cg_last; i >= 0; i--) {
@ -221,13 +222,13 @@ void kvz_encode_coeff_nxn(encoder_state_t * const state,
int32_t num_non_zero = 0;
go_rice_param = 0;
if (scan_pos_sig == scan_pos_last) {
if (scan_pos == scan_pos_last) {
abs_coeff[0] = abs(coeff[pos_last]);
coeff_signs = (coeff[pos_last] < 0);
num_non_zero = 1;
last_nz_pos_in_cg = scan_pos_sig;
first_nz_pos_in_cg = scan_pos_sig;
scan_pos_sig--;
last_nz_pos_in_cg = scan_pos;
first_nz_pos_in_cg = scan_pos;
scan_pos--;
}
// !!! residual_coding_subblock() !!!
@ -247,14 +248,22 @@ void kvz_encode_coeff_nxn(encoder_state_t * const state,
if (sig_coeffgroup_flag[cg_blk_pos]) {
for (; scan_pos_sig >= sub_pos; scan_pos_sig--) {
blk_pos = scan[scan_pos_sig];
uint32_t next_pass = 0;
/*
**** FIRST PASS ****
*/
for (; scan_pos >= sub_pos; scan_pos--) {
int32_t temp_diag;
int32_t temp_sum;
blk_pos = scan[scan_pos];
pos_y = blk_pos >> log2_block_size;
pos_x = blk_pos - (pos_y << log2_block_size);
sig = (coeff[blk_pos] != 0) ? 1 : 0;
if (scan_pos_sig > sub_pos || i == 0 || num_non_zero) {
ctx_sig = kvz_context_get_sig_ctx_idx_abs(&coeff[blk_pos], pos_x, pos_y, width, width, scan_mode, cabac);
if (scan_pos > sub_pos || i == 0 || num_non_zero) {
ctx_sig = kvz_context_get_sig_ctx_idx_abs(&coeff[blk_pos], pos_x, pos_y, width, width, scan_mode, &temp_diag, &temp_sum);
cabac->cur_ctx = (type == 0) ? &(cabac->ctx.cu_sig_model_luma[MAX(0, quant_state - 1)][ctx_sig]) :
@ -263,108 +272,89 @@ void kvz_encode_coeff_nxn(encoder_state_t * const state,
}
if (sig) {
abs_coeff[num_non_zero] = abs(coeff[blk_pos]);
coeff_signs = 2 * coeff_signs + (coeff[blk_pos] < 0);
uint8_t* offset = &ctx_offset[scan_pos - sub_pos];
// ctxOffsetAbs()
{
*offset = 0;
if (temp_diag != -1)
{
*offset = MIN(temp_sum, 4) + 1;
*offset += (!temp_diag ? (type == 0 /* luma channel*/ ? 15 : 5) : type == 0 /* luma channel*/ ? temp_diag < 3 ? 10 : (temp_diag < 10 ? 5 : 0) : 0);
}
}
num_non_zero++;
if (last_nz_pos_in_cg == -1) {
last_nz_pos_in_cg = scan_pos_sig;
}
last_nz_pos_in_cg = MAX(last_nz_pos_in_cg, scan_pos);
first_nz_pos_in_cg = scan_pos;
abs_coeff[scan_pos] = abs(coeff[blk_pos]);
int32_t remainder_abs_coeff = abs_coeff[scan_pos] - 1;
// If shift sign pattern and add current sign
coeff_signs = 2 * coeff_signs + (coeff[blk_pos] < 0);
// Code coeff parity
cabac->cur_ctx = (type == 0) ? &(cabac->ctx.cu_parity_flag_model_luma[*offset]) :
&(cabac->ctx.cu_parity_flag_model_chroma[*offset]);
CABAC_BIN(cabac, remainder_abs_coeff&1, "par_flag");
remainder_abs_coeff >>= 1;
// Code "greater than 1" flag
uint8_t gt1 = remainder_abs_coeff ? 1 : 0;
cabac->cur_ctx = (type == 0) ? &(cabac->ctx.cu_gtx_flag_model_luma[1][*offset]) :
&(cabac->ctx.cu_gtx_flag_model_chroma[1][*offset]);
CABAC_BIN(cabac, gt1, "gt1_flag");
next_pass |= gt1;
first_nz_pos_in_cg = scan_pos_sig;
}
quant_state = (quant_state_transition_table >> ((quant_state << 2) + ((coeff[blk_pos] & 1) << 1))) & 3;
}
/*
**** SECOND PASS ****
*/
if (next_pass) {
next_pass = 0;
for (scan_pos = scan_pos_last; scan_pos >= sub_pos; scan_pos--) {
if (abs_coeff[scan_pos] > 2) {
uint8_t* offset = &ctx_offset[scan_pos - sub_pos];
uint8_t gt2 = abs_coeff[scan_pos] > 4 ? 1 : 0;
cabac->cur_ctx = (type == 0) ? &(cabac->ctx.cu_gtx_flag_model_luma[0][*offset]) :
&(cabac->ctx.cu_gtx_flag_model_chroma[0][*offset]);
CABAC_BIN(cabac, gt2, "gt2_flag");
next_pass |= gt2;
}
}
}
/*
**** THIRD PASS ****
*/
if (next_pass) {
for (scan_pos = scan_pos_last; scan_pos >= sub_pos; scan_pos--) {
if (abs_coeff[scan_pos] > 4) {
uint32_t remainder = (abs_coeff[scan_pos] - 5) >> 1;
uint32_t rice_param = kvz_go_rice_par_abs(&coeff[blk_pos], pos_x, pos_y, width, width);
kvz_cabac_write_coeff_remain(cabac, remainder, go_rice_param);
}
}
}
uint32_t num_signs = num_non_zero;
//ToDo: sign hiding
/*
if(sign_hiding_enabled && (last_nz_pos_in_cg - first_nz_pos_in_cg >= SBH_THRESHOLD)
{
num_signs --;
coeff_signs >>= 1;
}
*/
CABAC_BINS_EP(cabac, coeff_signs, num_signs, "coeff_signs");
}
else {
scan_pos_sig = sub_pos - 1;
}
if (num_non_zero > 0) {
bool sign_hidden = last_nz_pos_in_cg - first_nz_pos_in_cg >= 4 /* SBH_THRESHOLD */
&& !encoder->cfg.lossless;
uint32_t ctx_set = (i > 0 && type == 0) ? 2 : 0;
cabac_ctx_t *base_ctx_mod;
int32_t num_c1_flag, first_c2_flag_idx, idx, first_coeff2;
if (c1 == 0) {
ctx_set++;
}
c1 = 1;
//base_ctx_mod = (type == 0) ? &(cabac->ctx.cu_one_model_luma[4 * ctx_set]) : &(cabac->ctx.cu_one_model_chroma[4 * ctx_set]);
num_c1_flag = MIN(num_non_zero, C1FLAG_NUMBER);
first_c2_flag_idx = -1;
for (idx = 0; idx < num_c1_flag; idx++) {
uint32_t symbol = (abs_coeff[idx] > 1) ? 1 : 0;
//cabac->cur_ctx = &base_ctx_mod[c1];
//CABAC_BIN(cabac, symbol, "coeff_abs_level_greater1_flag");
if (symbol) {
c1 = 0;
if (first_c2_flag_idx == -1) {
first_c2_flag_idx = idx;
}
}
else if ((c1 < 3) && (c1 > 0)) {
c1++;
}
}
if (c1 == 0) {
//base_ctx_mod = (type == 0) ? &(cabac->ctx.cu_abs_model_luma[ctx_set]) : &(cabac->ctx.cu_abs_model_chroma[ctx_set]);
if (first_c2_flag_idx != -1) {
uint8_t symbol = (abs_coeff[first_c2_flag_idx] > 2) ? 1 : 0;
//cabac->cur_ctx = &base_ctx_mod[0];
//CABAC_BIN(cabac, symbol, "coeff_abs_level_greater2_flag");
}
}
if (be_valid && sign_hidden) {
coeff_signs = coeff_signs >> 1;
if (!cabac->only_count)
if (encoder->cfg.crypto_features & KVZ_CRYPTO_TRANSF_COEFF_SIGNS) {
coeff_signs = coeff_signs ^ kvz_crypto_get_key(state->crypto_hdl, num_non_zero - 1);
}
CABAC_BINS_EP(cabac, coeff_signs, (num_non_zero - 1), "coeff_sign_flag");
}
else {
if (!cabac->only_count)
if (encoder->cfg.crypto_features & KVZ_CRYPTO_TRANSF_COEFF_SIGNS)
coeff_signs = coeff_signs ^ kvz_crypto_get_key(state->crypto_hdl, num_non_zero);
CABAC_BINS_EP(cabac, coeff_signs, num_non_zero, "coeff_sign_flag");
}
if (c1 == 0 || num_non_zero > C1FLAG_NUMBER) {
first_coeff2 = 1;
for (idx = 0; idx < num_non_zero; idx++) {
int32_t base_level = (idx < C1FLAG_NUMBER) ? (2 + first_coeff2) : 1;
if (abs_coeff[idx] >= base_level) {
if (!cabac->only_count) {
if (encoder->cfg.crypto_features & KVZ_CRYPTO_TRANSF_COEFFS)
kvz_cabac_write_coeff_remain_encry(state, cabac, abs_coeff[idx] - base_level, go_rice_param, base_level);
else
kvz_cabac_write_coeff_remain(cabac, abs_coeff[idx] - base_level, go_rice_param);
}
else
kvz_cabac_write_coeff_remain(cabac, abs_coeff[idx] - base_level, go_rice_param);
if (abs_coeff[idx] > 3 * (1 << go_rice_param)) {
go_rice_param = MIN(go_rice_param + 1, 4);
}
}
if (abs_coeff[idx] >= 2) {
first_coeff2 = 0;
}
}
}
scan_pos = sub_pos - 1;
}
}
}

View file

@ -29,6 +29,20 @@
#include "global.h" // IWYU pragma: keep
static const uint32_t g_go_rice_pars[32] =
{
0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 2, 2, 2, 2, 2, 2, 2
};
#define MAX_GR_ORDER_RESIDUAL 10
#define COEF_REMAIN_BIN_REDUCTION 3 ///< indicates the level at which the VLC transitions from Golomb-Rice to TU+EG(k)
static const uint32_t g_go_rice_range[MAX_GR_ORDER_RESIDUAL] =
{
6, 5, 6, COEF_REMAIN_BIN_REDUCTION, COEF_REMAIN_BIN_REDUCTION, COEF_REMAIN_BIN_REDUCTION, COEF_REMAIN_BIN_REDUCTION, COEF_REMAIN_BIN_REDUCTION, COEF_REMAIN_BIN_REDUCTION, COEF_REMAIN_BIN_REDUCTION
};
/***
* List of indices for 4x4 coefficient groups within 8x8 transform block.
* First index: 0 = diagonal, 1 = vertical, 2 horizontal scan pattern.