mirror of
https://github.com/ultravideo/uvg266.git
synced 2024-11-27 19:24:06 +00:00
[transform-skip] Bitstream generation for transform-skip
This commit is contained in:
parent
0cc1bf197f
commit
7ff904fd9d
|
@ -96,6 +96,15 @@ typedef struct
|
|||
cabac_ctx_t multi_ref_line[2];
|
||||
cabac_ctx_t bdpcm_mode[4];
|
||||
cabac_ctx_t joint_bc_br[3];
|
||||
cabac_ctx_t transform_skip_model_luma;
|
||||
cabac_ctx_t transform_skip_model_chroma;
|
||||
cabac_ctx_t transform_skip_sig_coeff[3];
|
||||
cabac_ctx_t transform_skip_sig[3];
|
||||
cabac_ctx_t transform_skip_res_sign[6];
|
||||
cabac_ctx_t transform_skip_gt1[4];
|
||||
cabac_ctx_t transform_skip_par;
|
||||
cabac_ctx_t transform_skip_gt2[5];
|
||||
|
||||
} ctx;
|
||||
} cabac_data_t;
|
||||
|
||||
|
|
175
src/context.c
175
src/context.c
|
@ -314,6 +314,61 @@ static const uint8_t INIT_CU_TRANSQUANT_BYPASS[4][1] = {
|
|||
{ DWS, },
|
||||
};
|
||||
|
||||
static const uint8_t INIT_TRANSFORM_SKIP[4][2] = {
|
||||
{ 25, 17, },
|
||||
{ 25, 9, },
|
||||
{ 25, 9, },
|
||||
{ 1, 1, },
|
||||
};
|
||||
|
||||
static const uint8_t INIT_TRANSFORM_SKIP_SIG_COEFF[4][3] =
|
||||
{
|
||||
{ 18, 35, 45, },
|
||||
{ 18, 12, 29, },
|
||||
{ 18, 20, 38, },
|
||||
{ 5, 8, 8, },
|
||||
};
|
||||
|
||||
static const uint8_t INIT_TRANSFORM_SKIP_SIG[4][3] =
|
||||
{
|
||||
{ 25, 50, 37, },
|
||||
{ 40, 35, 44, },
|
||||
{ 25, 28, 38, },
|
||||
{ 13, 13, 8, },
|
||||
};
|
||||
|
||||
static const uint8_t INIT_TRANSFORM_SKIP_PARITY[4][1] =
|
||||
{
|
||||
{ 11, },
|
||||
{ 3, },
|
||||
{ 11, },
|
||||
{ 6, },
|
||||
};
|
||||
|
||||
static const uint8_t INIT_TRANSFORM_SKIP_GT2[4][5] =
|
||||
{
|
||||
{ CNU, 3, 4, 4, 5, },
|
||||
{ CNU, 2, 10, 3, 3, },
|
||||
{ CNU, 10, 3, 3, 3, },
|
||||
{ DWS, 1, 1, 1, 1, },
|
||||
};
|
||||
|
||||
static const uint8_t INIT_TRANSFORM_SKIP_GT1[4][4] =
|
||||
{
|
||||
{ 19, 11, 4, 6, },
|
||||
{ 18, 11, 4, 28, },
|
||||
{ 11, 5, 5, 14, },
|
||||
{ 4, 2, 1, 6, },
|
||||
};
|
||||
|
||||
static const uint8_t INIT_TRANSFORM_SKIP_RES_SIGN[4][6] =
|
||||
{
|
||||
{ 35, 25, 46, 28, 33, 38, },
|
||||
{ 5, 10, 53, 43, 25, 46, },
|
||||
{ 12, 17, 46, 28, 25, 46, },
|
||||
{ 1, 4, 4, 5, 8, 8, },
|
||||
};
|
||||
|
||||
static const uint8_t INIT_INTRA_SUBPART_MODE[4][2] = {
|
||||
{ 33, 43, },
|
||||
{ 33, 36, },
|
||||
|
@ -387,7 +442,10 @@ void kvz_init_contexts(encoder_state_t *state, int8_t QP, int8_t slice)
|
|||
kvz_ctx_init(&cabac->ctx.intra_subpart_model[0], QP, INIT_INTRA_SUBPART_MODE[slice][0], INIT_INTRA_SUBPART_MODE[3][0]);
|
||||
kvz_ctx_init(&cabac->ctx.intra_subpart_model[1], QP, INIT_INTRA_SUBPART_MODE[slice][1], INIT_INTRA_SUBPART_MODE[3][1]);
|
||||
|
||||
kvz_ctx_init(&cabac->ctx.transform_skip_model_luma, QP, INIT_TRANSFORM_SKIP[slice][0], INIT_TRANSFORM_SKIP[3][0]);
|
||||
kvz_ctx_init(&cabac->ctx.transform_skip_model_chroma, QP, INIT_TRANSFORM_SKIP[slice][1], INIT_TRANSFORM_SKIP[3][1]);
|
||||
|
||||
kvz_ctx_init(&cabac->ctx.transform_skip_par, QP, INIT_TRANSFORM_SKIP_PARITY[slice][0], INIT_TRANSFORM_SKIP_PARITY[3][0]);
|
||||
|
||||
kvz_ctx_init(&cabac->ctx.multi_ref_line[0], QP, MULTI_REF_LINE_MODE[slice][0], MULTI_REF_LINE_MODE[3][0]);
|
||||
kvz_ctx_init(&cabac->ctx.multi_ref_line[1], QP, MULTI_REF_LINE_MODE[slice][1], MULTI_REF_LINE_MODE[3][1]);
|
||||
|
@ -398,21 +456,26 @@ void kvz_init_contexts(encoder_state_t *state, int8_t QP, int8_t slice)
|
|||
for (i = 0; i < 3; i++) {
|
||||
kvz_ctx_init(&cabac->ctx.cu_skip_flag_model[i], QP, INIT_SKIP_FLAG[slice][i], INIT_SKIP_FLAG[3][i]);
|
||||
kvz_ctx_init(&cabac->ctx.joint_bc_br[i], QP, INIT_JOINT_CB_CR_FLAG[slice][i], INIT_JOINT_CB_CR_FLAG[3][i]);
|
||||
kvz_ctx_init(&cabac->ctx.transform_skip_sig_coeff[i], QP, INIT_TRANSFORM_SKIP_SIG_COEFF[slice][i], INIT_TRANSFORM_SKIP_SIG_COEFF[3][i]);
|
||||
kvz_ctx_init(&cabac->ctx.transform_skip_sig[i], QP, INIT_TRANSFORM_SKIP_SIG[slice][i], INIT_TRANSFORM_SKIP_SIG[3][i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
kvz_ctx_init(&cabac->ctx.sig_coeff_group_model[i], QP, INIT_SIG_COEFF_GROUP[slice][i], INIT_SIG_COEFF_GROUP[3][i]);
|
||||
kvz_ctx_init(&cabac->ctx.mts_idx_model[i], QP, INIT_MTS_IDX[slice][i], INIT_MTS_IDX[3][i]);
|
||||
kvz_ctx_init(&cabac->ctx.transform_skip_gt1[i], QP, INIT_TRANSFORM_SKIP_GT1[slice][i], INIT_TRANSFORM_SKIP_GT1[3][i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
kvz_ctx_init(&cabac->ctx.transform_skip_gt2[i], QP, INIT_TRANSFORM_SKIP_GT2[slice][i], INIT_TRANSFORM_SKIP_GT2[3][i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < 6; i++) {
|
||||
kvz_ctx_init(&cabac->ctx.qt_split_flag_model[i], QP, INIT_QT_SPLIT_FLAG[slice][i], INIT_QT_SPLIT_FLAG[3][i]);
|
||||
kvz_ctx_init(&cabac->ctx.alf_cc_filter_control_flag[i], QP, INIT_CC_ALF_FILTER_CONTROL_FLAG[slice][i], INIT_CC_ALF_FILTER_CONTROL_FLAG[3][i]);
|
||||
kvz_ctx_init(&cabac->ctx.transform_skip_res_sign[i], QP, INIT_TRANSFORM_SKIP_RES_SIGN[slice][i], INIT_TRANSFORM_SKIP_RES_SIGN[3][i]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
for (i = 0; i < 9; i++) {
|
||||
kvz_ctx_init(&cabac->ctx.split_flag_model[i], QP, INIT_SPLIT_FLAG[slice][i], INIT_SPLIT_FLAG[3][i]);
|
||||
kvz_ctx_init(&cabac->ctx.alf_ctb_flag_model[i], QP, INIT_CTB_ALF_FLAG[slice][i], INIT_CTB_ALF_FLAG[3][i]);
|
||||
|
@ -555,6 +618,114 @@ uint32_t kvz_context_get_sig_ctx_idx_abs(const coeff_t* coeff, int32_t pos_x, in
|
|||
return ctx_ofs;
|
||||
}
|
||||
|
||||
uint32_t kvz_context_get_sig_ctx_idx_abs_ts(const coeff_t* coeff, int32_t pos_x, int32_t pos_y, uint32_t width)
|
||||
{
|
||||
const coeff_t* data = coeff + pos_x + pos_y * width;
|
||||
int numPos = 0;
|
||||
#define UPDATE(x) {coeff_t a=abs(x);numPos+=!!a;}
|
||||
if (pos_x > 0)
|
||||
{
|
||||
UPDATE(data[-1]);
|
||||
}
|
||||
if (pos_y > 0)
|
||||
{
|
||||
UPDATE(data[-(int)width]);
|
||||
}
|
||||
#undef UPDATE
|
||||
|
||||
return numPos;
|
||||
}
|
||||
|
||||
uint32_t kvz_sign_ctx_id_abs_ts(const coeff_t* coeff, int32_t pos_x, int32_t pos_y, int32_t width, int bdpcm)
|
||||
{
|
||||
const coeff_t* pData = coeff + pos_x + pos_y * width;
|
||||
|
||||
int rightSign = 0, belowSign = 0;
|
||||
unsigned signCtx = 0;
|
||||
|
||||
#define SGN(val) ((0 < (val)) - ((val) < 0))
|
||||
if (pos_x > 0)
|
||||
{
|
||||
rightSign = SGN(pData[-1]);
|
||||
}
|
||||
if (pos_y > 0)
|
||||
{
|
||||
belowSign = SGN(pData[-(int)width]);
|
||||
}
|
||||
#undef SGN
|
||||
|
||||
if ((rightSign == 0 && belowSign == 0) || ((rightSign * belowSign) < 0))
|
||||
{
|
||||
signCtx = 0;
|
||||
}
|
||||
else if (rightSign >= 0 && belowSign >= 0)
|
||||
{
|
||||
signCtx = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
signCtx = 2;
|
||||
}
|
||||
if (bdpcm)
|
||||
{
|
||||
signCtx += 3;
|
||||
}
|
||||
return signCtx;
|
||||
}
|
||||
|
||||
int32_t kvz_derive_mod_coeff(int rightPixel, int belowPixel, coeff_t absCoeff, int bdpcm)
|
||||
{
|
||||
|
||||
if (absCoeff == 0)
|
||||
return 0;
|
||||
int pred1, absBelow = abs(belowPixel), absRight = abs(rightPixel);
|
||||
|
||||
int absCoeffMod = absCoeff;
|
||||
|
||||
if (bdpcm == 0)
|
||||
{
|
||||
pred1 = MAX(absBelow, absRight);
|
||||
|
||||
if (absCoeffMod == pred1)
|
||||
{
|
||||
absCoeffMod = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
absCoeffMod = absCoeffMod < pred1 ? absCoeffMod + 1 : absCoeffMod;
|
||||
}
|
||||
}
|
||||
|
||||
return(absCoeffMod);
|
||||
}
|
||||
|
||||
unsigned kvz_lrg1_ctx_id_abs_ts(const coeff_t* coeff, int32_t pos_x, int32_t pos_y, int32_t width, int bdpcm)
|
||||
{
|
||||
const coeff_t* posC = coeff + pos_x + pos_y * width;
|
||||
|
||||
int numPos = 0;
|
||||
#define UPDATE(x) {coeff_t a=abs(x);numPos+=!!a;}
|
||||
|
||||
if (bdpcm)
|
||||
{
|
||||
numPos = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pos_x > 0)
|
||||
{
|
||||
UPDATE(posC[-1]);
|
||||
}
|
||||
if (pos_y > 0)
|
||||
{
|
||||
UPDATE(posC[-width]);
|
||||
}
|
||||
}
|
||||
|
||||
#undef UPDATE
|
||||
return numPos;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Calculate slot of Go rice parameter for remainder coefficient value coding
|
||||
* \param coeff pointer to the current coefficient
|
||||
|
|
|
@ -43,6 +43,13 @@ uint32_t kvz_context_get_sig_ctx_idx_abs(const coeff_t* coeff, int32_t pos_x, in
|
|||
uint32_t height, uint32_t width, int8_t type,
|
||||
int32_t* temp_diag, int32_t* temp_sum);
|
||||
|
||||
uint32_t kvz_context_get_sig_ctx_idx_abs_ts(const coeff_t* coeff, int32_t pos_x, int32_t pos_y,
|
||||
uint32_t width);
|
||||
uint32_t kvz_sign_ctx_id_abs_ts(const coeff_t* coeff, int32_t pos_x, int32_t pos_y, int32_t width, int bdpcm);
|
||||
int32_t kvz_derive_mod_coeff(int rightPixel, int belowPixel, coeff_t absCoeff, int bdpcm);
|
||||
unsigned kvz_lrg1_ctx_id_abs_ts(const coeff_t* coeff, int32_t pos_x, int32_t pos_y, int32_t width, int bdpcm);
|
||||
|
||||
|
||||
uint32_t kvz_abs_sum(const coeff_t* coeff, int32_t pos_x, int32_t pos_y,
|
||||
uint32_t height, uint32_t width, uint32_t baselevel);
|
||||
|
||||
|
|
|
@ -89,6 +89,176 @@ static void encode_mts_idx(encoder_state_t * const state,
|
|||
}
|
||||
}
|
||||
|
||||
static void encode_ts_residual(encoder_state_t* const state,
|
||||
cabac_data_t* const cabac,
|
||||
const coeff_t* coeff,
|
||||
uint8_t width,
|
||||
uint8_t type,
|
||||
int8_t scan_mode) {
|
||||
//const encoder_control_t * const encoder = state->encoder_control;
|
||||
//int c1 = 1;
|
||||
int32_t i;
|
||||
int32_t blk_pos;
|
||||
// ToDo: large block support in VVC?
|
||||
uint32_t sig_coeffgroup_flag[32 * 32] = { 0 };
|
||||
|
||||
|
||||
// CONSTANTS
|
||||
|
||||
const uint32_t log2_block_size = kvz_g_convert_to_bit[width] + 2;
|
||||
const uint32_t log2_cg_size = kvz_g_log2_sbb_size[log2_block_size][log2_block_size][0] + kvz_g_log2_sbb_size[log2_block_size][log2_block_size][1];
|
||||
const uint32_t* scan =
|
||||
kvz_g_sig_last_scan[scan_mode][log2_block_size - 1];
|
||||
const uint32_t* scan_cg = g_sig_last_scan_cg[log2_block_size - 1][scan_mode];
|
||||
|
||||
|
||||
// Init base contexts according to block type
|
||||
cabac_ctx_t* base_coeff_group_ctx = &(cabac->ctx.sig_coeff_group_model[(type == 0 ? 0 : 1) * 2 + 1]);
|
||||
|
||||
cabac->cur_ctx = base_coeff_group_ctx;
|
||||
|
||||
int maxCtxBins = (width * width * 7) >> 2;
|
||||
unsigned scan_cg_last = -1;
|
||||
unsigned scan_pos_last = -1;
|
||||
|
||||
for (int i = 0; i < width * width; i++) {
|
||||
if (coeff[scan[i]]) {
|
||||
scan_pos_last = i;
|
||||
sig_coeffgroup_flag[scan_cg[i >> log2_cg_size]] = 1;
|
||||
}
|
||||
}
|
||||
scan_cg_last = scan_pos_last >> log2_cg_size;
|
||||
|
||||
|
||||
for (i = 0; i <= (width * width - 1) >> log2_cg_size; i++) {
|
||||
if (!(i == 0 || i ==scan_cg_last)) {
|
||||
if(!sig_coeffgroup_flag[scan_cg[i]]) {
|
||||
CABAC_BIN(cabac, 0, "sb_coded_flag");
|
||||
continue;
|
||||
}
|
||||
CABAC_BIN(cabac, 1, "sb_coded_flag");
|
||||
}
|
||||
|
||||
int firstSigPos = i << log2_cg_size;
|
||||
int min_sub_pos = firstSigPos + (1 << log2_cg_size) - 1;
|
||||
int nextSigPos = firstSigPos;
|
||||
|
||||
//===== encode absolute values =====
|
||||
const int inferSigPos = min_sub_pos;
|
||||
int remAbsLevel = -1;
|
||||
int numNonZero = 0;
|
||||
|
||||
int rightPixel, belowPixel, modAbsCoeff;
|
||||
|
||||
int lastScanPosPass1 = -1;
|
||||
int lastScanPosPass2 = -1;
|
||||
for (; nextSigPos <= min_sub_pos && maxCtxBins >= 4; nextSigPos++)
|
||||
{
|
||||
blk_pos = scan[nextSigPos];
|
||||
int pos_x = blk_pos % width;
|
||||
int pos_y = blk_pos / width;
|
||||
coeff_t curr_coeff = coeff[blk_pos];
|
||||
unsigned sigFlag = (curr_coeff != 0);
|
||||
if (numNonZero || nextSigPos != inferSigPos)
|
||||
{
|
||||
cabac->cur_ctx = &cabac->ctx.transform_skip_sig[
|
||||
kvz_context_get_sig_ctx_idx_abs_ts(coeff, pos_x, pos_y, width)
|
||||
];
|
||||
CABAC_BIN(cabac, sigFlag, "sig_coeff_flag");
|
||||
maxCtxBins--;
|
||||
}
|
||||
|
||||
if (sigFlag)
|
||||
{
|
||||
//===== encode sign's =====
|
||||
int sign = curr_coeff < 0;
|
||||
cabac->cur_ctx = &cabac->ctx.transform_skip_res_sign[
|
||||
kvz_sign_ctx_id_abs_ts(coeff, pos_x, pos_y, width, 0)
|
||||
];
|
||||
CABAC_BIN(cabac, sign, "coeff_sign_flag");
|
||||
maxCtxBins--;
|
||||
numNonZero++;
|
||||
|
||||
rightPixel = pos_x > 0 ? coeff[pos_x + pos_y * width - 1] : 0;
|
||||
belowPixel = pos_y > 0 ? coeff[pos_x + (pos_y - 1) * width] : 0;
|
||||
|
||||
modAbsCoeff = kvz_derive_mod_coeff(rightPixel, belowPixel, abs(curr_coeff), 0);
|
||||
|
||||
remAbsLevel = modAbsCoeff - 1;
|
||||
|
||||
unsigned gt1 = !!remAbsLevel;
|
||||
cabac->cur_ctx = &cabac->ctx.transform_skip_gt1[
|
||||
kvz_lrg1_ctx_id_abs_ts(coeff, pos_x, pos_y, width, 0)
|
||||
];
|
||||
CABAC_BIN(cabac, gt1, "abs_level_gtx_flag");
|
||||
maxCtxBins--;
|
||||
|
||||
if (gt1)
|
||||
{
|
||||
remAbsLevel -= 1;
|
||||
cabac->cur_ctx = &cabac->ctx.transform_skip_par;
|
||||
CABAC_BIN(cabac, remAbsLevel & 1, "par_level_flag");
|
||||
maxCtxBins--;
|
||||
}
|
||||
}
|
||||
lastScanPosPass1 = nextSigPos;
|
||||
}
|
||||
|
||||
|
||||
int cutoffVal = 2;
|
||||
int numGtBins = 4;
|
||||
for (int scanPos = firstSigPos; scanPos <= min_sub_pos && maxCtxBins >= 4; scanPos++)
|
||||
{
|
||||
blk_pos = scan[scanPos];
|
||||
int pos_x = blk_pos % width;
|
||||
int pos_y = blk_pos / width;
|
||||
unsigned absLevel;
|
||||
rightPixel = pos_x > 0 ? coeff[pos_x + pos_y * width - 1] : 0;
|
||||
belowPixel = pos_y > 0 ? coeff[pos_x + (pos_y - 1) * width] : 0;
|
||||
absLevel = kvz_derive_mod_coeff(rightPixel, belowPixel, abs(coeff[blk_pos]), 0);
|
||||
cutoffVal = 2;
|
||||
for (int i = 0; i < numGtBins; i++)
|
||||
{
|
||||
if (absLevel >= cutoffVal)
|
||||
{
|
||||
unsigned gt2 = (absLevel >= (cutoffVal + 2));
|
||||
cabac->cur_ctx = &cabac->ctx.transform_skip_gt2[cutoffVal >> 1];
|
||||
CABAC_BIN(cabac, gt2, "abs_level_gtx_flag");
|
||||
maxCtxBins--;
|
||||
}
|
||||
cutoffVal += 2;
|
||||
}
|
||||
lastScanPosPass2 = scanPos;
|
||||
}
|
||||
|
||||
//===== coeff bypass ====
|
||||
for (int scanPos = firstSigPos; scanPos <= min_sub_pos; scanPos++)
|
||||
{
|
||||
blk_pos = scan[scanPos];
|
||||
int pos_x = blk_pos % width;
|
||||
int pos_y = blk_pos / width;
|
||||
unsigned absLevel;
|
||||
rightPixel = pos_x > 0 ? coeff[pos_x + pos_y * width - 1] : 0;
|
||||
belowPixel = pos_y > 0 ? coeff[pos_x + (pos_y - 1) * width] : 0;
|
||||
cutoffVal = (scanPos <= lastScanPosPass2 ? 10 : (scanPos <= lastScanPosPass1 ? 2 : 0));
|
||||
absLevel = kvz_derive_mod_coeff(rightPixel, belowPixel, abs(coeff[blk_pos]), 0 || !cutoffVal);
|
||||
|
||||
if (absLevel >= cutoffVal)
|
||||
{
|
||||
int rice = 1;
|
||||
unsigned rem = scanPos <= lastScanPosPass1 ? (absLevel - cutoffVal) >> 1 : absLevel;
|
||||
kvz_cabac_write_coeff_remain(cabac, rem, rice, 5);
|
||||
|
||||
if (absLevel && scanPos > lastScanPosPass1)
|
||||
{
|
||||
int sign = coeff[blk_pos] < 0;
|
||||
CABAC_BIN_EP(cabac, sign, "coeff_sign_flag");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Encode (X,Y) position of the last significant coefficient
|
||||
*
|
||||
|
@ -162,16 +332,25 @@ void kvz_encode_last_significant_xy(cabac_data_t * const cabac,
|
|||
static void encode_chroma_tu(encoder_state_t* const state, int x, int y, int depth, const uint8_t width_c, const cu_info_t* cur_pu, int8_t* scan_idx) {
|
||||
int x_local = (x >> 1) % LCU_WIDTH_C;
|
||||
int y_local = (y >> 1) % LCU_WIDTH_C;
|
||||
cabac_data_t* const cabac = &state->cabac;
|
||||
*scan_idx = kvz_get_scan_order(cur_pu->type, cur_pu->intra.mode_chroma, depth);
|
||||
|
||||
const coeff_t *coeff_u = &state->coeff->u[xy_to_zorder(LCU_WIDTH_C, x_local, y_local)];
|
||||
const coeff_t *coeff_v = &state->coeff->v[xy_to_zorder(LCU_WIDTH_C, x_local, y_local)];
|
||||
|
||||
if (cbf_is_set(cur_pu->cbf, depth, COLOR_U)) {
|
||||
if(state->encoder_control->cfg.trskip_enable && width_c == 4){
|
||||
cabac->cur_ctx = &cabac->ctx.transform_skip_model_chroma;
|
||||
CABAC_BIN(cabac, cur_pu->tr_idx == MTS_SKIP, "transform_skip_flag");
|
||||
}
|
||||
kvz_encode_coeff_nxn(state, &state->cabac, coeff_u, width_c, 1, *scan_idx, NULL, false);
|
||||
}
|
||||
|
||||
if (cbf_is_set(cur_pu->cbf, depth, COLOR_V)) {
|
||||
if (state->encoder_control->cfg.trskip_enable && width_c == 4) {
|
||||
cabac->cur_ctx = &cabac->ctx.transform_skip_model_chroma;
|
||||
CABAC_BIN(cabac, cur_pu->tr_idx == MTS_SKIP, "transform_skip_flag");
|
||||
}
|
||||
kvz_encode_coeff_nxn(state, &state->cabac, coeff_v, width_c, 2, *scan_idx, NULL, false);
|
||||
}
|
||||
}
|
||||
|
@ -182,6 +361,7 @@ static void encode_transform_unit(encoder_state_t * const state,
|
|||
assert(depth >= 1 && depth <= MAX_PU_DEPTH);
|
||||
|
||||
const videoframe_t * const frame = state->tile->frame;
|
||||
cabac_data_t* const cabac = &state->cabac;
|
||||
const uint8_t width = LCU_WIDTH >> depth;
|
||||
const uint8_t width_c = (depth == MAX_PU_DEPTH ? width : width / 2);
|
||||
|
||||
|
@ -209,8 +389,14 @@ static void encode_transform_unit(encoder_state_t * const state,
|
|||
// CoeffNxN
|
||||
// Residual Coding
|
||||
|
||||
if(state->encoder_control->cfg.trskip_enable && width == 4) {
|
||||
cabac->cur_ctx = &cabac->ctx.transform_skip_model_luma;
|
||||
CABAC_BIN(cabac, 1, "transform_skip_flag");
|
||||
encode_ts_residual(state, cabac, coeff_y, width, 0, scan_idx);
|
||||
}
|
||||
else {
|
||||
kvz_encode_coeff_nxn(state,
|
||||
&state->cabac,
|
||||
cabac,
|
||||
coeff_y,
|
||||
width,
|
||||
0,
|
||||
|
@ -218,6 +404,7 @@ static void encode_transform_unit(encoder_state_t * const state,
|
|||
cur_pu,
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
if (depth == MAX_DEPTH) {
|
||||
// For size 4x4 luma transform the corresponding chroma transforms are
|
||||
|
|
|
@ -594,7 +594,11 @@ static void encoder_state_write_bitstream_seq_parameter_set(bitstream_t* stream,
|
|||
WRITE_U(stream, (TR_MAX_LOG2_SIZE - 5) ? 1 : 0, 1, "sps_max_luma_transform_size_64_flag");
|
||||
|
||||
|
||||
WRITE_U(stream, 0, 1, "sps_transform_skip_enabled_flag");
|
||||
WRITE_U(stream, encoder->cfg.trskip_enable, 1, "sps_transform_skip_enabled_flag");
|
||||
if (encoder->cfg.trskip_enable) {
|
||||
WRITE_UE(stream, 0, "sps_log2_transform_skip_max_size_minus2"); // Only enable transformskip for 4x4 blocks for now
|
||||
WRITE_U(stream, 0, 1, "sps_bdpcm_enabled_flag");
|
||||
}
|
||||
|
||||
const uint8_t mts_selection = encoder->cfg.mts;
|
||||
WRITE_U(stream, mts_selection ? 1 : 0, 1, "sps_mts_enabled_flag");
|
||||
|
@ -694,6 +698,11 @@ static void encoder_state_write_bitstream_seq_parameter_set(bitstream_t* stream,
|
|||
}
|
||||
|
||||
WRITE_U(stream, 0, 1, "sps_palette_enabled_flag");
|
||||
|
||||
if (encoder->cfg.trskip_enable /* || pcSPS->getPLTMode()*/) {
|
||||
WRITE_UE(stream, KVZ_BIT_DEPTH, "log2_parallel_merge_level_minus2");
|
||||
}
|
||||
|
||||
WRITE_U(stream, 0, 1, "sps_ibc_enabled_flag");
|
||||
|
||||
#if LUMA_ADAPTIVE_DEBLOCKING_FILTER_QP_OFFSET
|
||||
|
@ -1310,7 +1319,10 @@ void kvz_encoder_state_write_bitstream_slice_header(
|
|||
if (state->encoder_control->cfg.signhide_enable) {
|
||||
WRITE_U(stream, 1, 1, "sh_sign_data_hiding_used_flag");
|
||||
}
|
||||
|
||||
if (state->encoder_control->cfg.trskip_enable && !state->encoder_control->cfg.signhide_enable /* && !cfg.dep_quant*/)
|
||||
{
|
||||
WRITE_U(stream, 0, 1, "sh_ts_residual_coding_disabled_flag");
|
||||
}
|
||||
if (state->frame->slicetype != KVZ_SLICE_I) {
|
||||
|
||||
// BT Size set only with non-I-frames, in I-frames the size is 32x32
|
||||
|
|
|
@ -85,16 +85,16 @@ static double get_cost(encoder_state_t * const state,
|
|||
|
||||
// Add the offset bit costs of signaling 'luma and chroma use trskip',
|
||||
// versus signaling 'luma and chroma don't use trskip' to the SAD cost.
|
||||
//const cabac_ctx_t *ctx = &state->cabac.ctx.transform_skip_model_luma;
|
||||
double trskip_bits = 0.0;// CTX_ENTROPY_FBITS(ctx, 1) - CTX_ENTROPY_FBITS(ctx, 0);
|
||||
const cabac_ctx_t *ctx = &state->cabac.ctx.transform_skip_model_luma;
|
||||
double trskip_bits = CTX_ENTROPY_FBITS(ctx, 1) - CTX_ENTROPY_FBITS(ctx, 0);
|
||||
|
||||
|
||||
/*
|
||||
// ToDo: Check cost
|
||||
if (state->encoder_control->chroma_format != KVZ_CSP_400) {
|
||||
ctx = &state->cabac.ctx.transform_skip_model_chroma;
|
||||
trskip_bits += 2.0 * (CTX_ENTROPY_FBITS(ctx, 1) - CTX_ENTROPY_FBITS(ctx, 0));
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
double sad_cost = TRSKIP_RATIO * sad_func(pred, orig_block) + state->lambda_sqrt * trskip_bits;
|
||||
if (sad_cost < satd_cost) {
|
||||
|
@ -124,6 +124,7 @@ static void get_cost_dual(encoder_state_t * const state,
|
|||
costs_out[0] = (double)satd_costs[0];
|
||||
costs_out[1] = (double)satd_costs[1];
|
||||
|
||||
// TODO: width and height
|
||||
if (TRSKIP_RATIO != 0 && width == 4 && state->encoder_control->cfg.trskip_enable) {
|
||||
// If the mode looks better with SAD than SATD it might be a good
|
||||
// candidate for transform skip. How much better SAD has to be is
|
||||
|
@ -131,16 +132,16 @@ static void get_cost_dual(encoder_state_t * const state,
|
|||
|
||||
// Add the offset bit costs of signaling 'luma and chroma use trskip',
|
||||
// versus signaling 'luma and chroma don't use trskip' to the SAD cost.
|
||||
//const cabac_ctx_t *ctx = &state->cabac.ctx.transform_skip_model_luma;
|
||||
double trskip_bits = 0.0;// CTX_ENTROPY_FBITS(ctx, 1) - CTX_ENTROPY_FBITS(ctx, 0);
|
||||
const cabac_ctx_t *ctx = &state->cabac.ctx.transform_skip_model_luma;
|
||||
double trskip_bits = CTX_ENTROPY_FBITS(ctx, 1) - CTX_ENTROPY_FBITS(ctx, 0);
|
||||
|
||||
|
||||
/*
|
||||
// ToDo: check cost
|
||||
if (state->encoder_control->chroma_format != KVZ_CSP_400) {
|
||||
ctx = &state->cabac.ctx.transform_skip_model_chroma;
|
||||
trskip_bits += 2.0 * (CTX_ENTROPY_FBITS(ctx, 1) - CTX_ENTROPY_FBITS(ctx, 0));
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
unsigned unsigned_sad_costs[PARALLEL_BLKS] = { 0 };
|
||||
double sad_costs[PARALLEL_BLKS] = { 0 };
|
||||
|
|
Loading…
Reference in a new issue