From 7ff904fd9d7efe2bae84b8030477e73d3e652290 Mon Sep 17 00:00:00 2001 From: Joose Sainio Date: Tue, 27 Apr 2021 14:13:44 +0300 Subject: [PATCH] [transform-skip] Bitstream generation for transform-skip --- src/cabac.h | 9 ++ src/context.c | 179 +++++++++++++++++++++++++++++- src/context.h | 7 ++ src/encode_coding_tree.c | 203 ++++++++++++++++++++++++++++++++-- src/encoder_state-bitstream.c | 16 ++- src/search_intra.c | 17 +-- 6 files changed, 409 insertions(+), 22 deletions(-) diff --git a/src/cabac.h b/src/cabac.h index ddcf0cf8..f86a633a 100644 --- a/src/cabac.h +++ b/src/cabac.h @@ -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; diff --git a/src/context.c b/src/context.c index fb45ffcb..dd7853a2 100644 --- a/src/context.c +++ b/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,8 +442,11 @@ 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 diff --git a/src/context.h b/src/context.h index 2b44bbe1..2f02c370 100644 --- a/src/context.h +++ b/src/context.h @@ -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); diff --git a/src/encode_coding_tree.c b/src/encode_coding_tree.c index 4c49e3e2..fbcb950f 100644 --- a/src/encode_coding_tree.c +++ b/src/encode_coding_tree.c @@ -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,14 +389,21 @@ static void encode_transform_unit(encoder_state_t * const state, // CoeffNxN // Residual Coding - kvz_encode_coeff_nxn(state, - &state->cabac, - coeff_y, - width, - 0, - scan_idx, - cur_pu, - true); + 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, + cabac, + coeff_y, + width, + 0, + scan_idx, + cur_pu, + true); + } } if (depth == MAX_DEPTH) { diff --git a/src/encoder_state-bitstream.c b/src/encoder_state-bitstream.c index 46764160..8e286e38 100644 --- a/src/encoder_state-bitstream.c +++ b/src/encoder_state-bitstream.c @@ -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 diff --git a/src/search_intra.c b/src/search_intra.c index 8ae9d004..253e67f2 100644 --- a/src/search_intra.c +++ b/src/search_intra.c @@ -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 };