mirror of
https://github.com/ultravideo/uvg266.git
synced 2024-11-27 19:24:06 +00:00
Converted kvz_encode_coeff_nxn and related helper functions to VVC K0072 format
This commit is contained in:
parent
84e78c6c50
commit
0680f240d7
44
src/cabac.c
44
src/cabac.c
|
@ -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)
|
||||
|
|
|
@ -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)];
|
||||
}
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
14
src/tables.h
14
src/tables.h
|
@ -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.
|
||||
|
|
Loading…
Reference in a new issue