From 23fda2332276bd3a70656eb59af09f09fe954195 Mon Sep 17 00:00:00 2001 From: Joose Sainio Date: Fri, 1 Apr 2022 10:46:51 +0300 Subject: [PATCH] [intra] Count fractional bits with get_coeff_cabac_cost --- src/cabac.c | 9 ++- src/cabac.h | 2 +- src/encode_coding_tree.c | 80 ++++++++++--------- src/encode_coding_tree.h | 5 +- src/rdo.c | 28 ++++--- src/rdo.h | 2 +- src/strategies/avx2/encode_coding_tree-avx2.c | 26 +++--- src/strategies/avx2/encode_coding_tree-avx2.h | 3 +- .../generic/encode_coding_tree-generic.c | 37 +++++---- .../generic/encode_coding_tree-generic.h | 3 +- src/strategies/strategies-encode.h | 3 +- 11 files changed, 107 insertions(+), 91 deletions(-) diff --git a/src/cabac.c b/src/cabac.c index 742f92c4..a65d08ba 100644 --- a/src/cabac.c +++ b/src/cabac.c @@ -315,15 +315,17 @@ void uvg_cabac_encode_bins_ep(cabac_data_t * const data, uint32_t bin_values, in * \param remainder Value of remaining abs coeff * \param rice_param Reference to Rice parameter. */ -void uvg_cabac_write_coeff_remain(cabac_data_t * const cabac, const uint32_t remainder, const uint32_t rice_param, const unsigned int cutoff) +int uvg_cabac_write_coeff_remain(cabac_data_t * const cabac, const uint32_t remainder, const uint32_t rice_param, const unsigned int cutoff) { const unsigned threshold = cutoff << rice_param; uint32_t bins = remainder; - + uint32_t bits = 0; 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"); + bits += length; + bits += rice_param; } else { const unsigned max_prefix_length = 32 - cutoff - 15/*max_log2_tr_dynamic_range*/; unsigned prefix_length = 0; @@ -344,8 +346,9 @@ void uvg_cabac_write_coeff_remain(cabac_data_t * const cabac, const uint32_t rem const unsigned suffix = ((code_value - ((1 << prefix_length) - 1)) << rice_param) | (bins & bit_mask); CABAC_BINS_EP(cabac, prefix, total_prefix_length, "coeff_abs_level_remaining"); CABAC_BINS_EP(cabac, suffix, suffix_length, "coeff_abs_level_remaining"); + bits += total_prefix_length + suffix_length; } - + return bits; } diff --git a/src/cabac.h b/src/cabac.h index 4efdb528..6f7aaa78 100644 --- a/src/cabac.h +++ b/src/cabac.h @@ -140,7 +140,7 @@ void uvg_cabac_encode_bins_ep(cabac_data_t *data, uint32_t bin_values, int num_b void uvg_cabac_encode_bin_trm(cabac_data_t *data, uint8_t bin_value); void uvg_cabac_write(cabac_data_t *data); void uvg_cabac_finish(cabac_data_t *data); -void uvg_cabac_write_coeff_remain(cabac_data_t *cabac, uint32_t symbol, +int uvg_cabac_write_coeff_remain(cabac_data_t *cabac, uint32_t symbol, uint32_t r_param, const unsigned int cutoff); uint32_t uvg_cabac_write_ep_ex_golomb(struct encoder_state_t * const state, cabac_data_t *data, uint32_t symbol, uint32_t count); diff --git a/src/encode_coding_tree.c b/src/encode_coding_tree.c index 48ff3c8c..8a975908 100644 --- a/src/encode_coding_tree.c +++ b/src/encode_coding_tree.c @@ -256,7 +256,8 @@ void uvg_encode_ts_residual(encoder_state_t* const state, const coeff_t* coeff, uint32_t width, uint8_t type, - int8_t scan_mode) { + int8_t scan_mode, + double* bits_out) { //const encoder_control_t * const encoder = state->encoder_control; //int c1 = 1; uint32_t i; @@ -271,7 +272,7 @@ void uvg_encode_ts_residual(encoder_state_t* const state, const uint32_t log2_cg_size = uvg_g_log2_sbb_size[log2_block_size][log2_block_size][0] + uvg_g_log2_sbb_size[log2_block_size][log2_block_size][1]; const uint32_t* scan = uvg_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]; - + double bits = 0; // Init base contexts according to block type cabac_ctx_t* base_coeff_group_ctx = &(cabac->ctx.transform_skip_sig_coeff_group[0]); @@ -304,10 +305,10 @@ void uvg_encode_ts_residual(encoder_state_t* const state, cabac->cur_ctx = &base_coeff_group_ctx[ctx_sig]; if(!sig_coeffgroup_flag[scan_cg[i]]) { - CABAC_BIN(cabac, 0, "ts_sigGroup"); + CABAC_FBITS_UPDATE(cabac, &base_coeff_group_ctx[ctx_sig], 0, bits, "ts_sigGroup"); continue; } - CABAC_BIN(cabac, 1, "ts_sigGroup"); + CABAC_FBITS_UPDATE(cabac, &base_coeff_group_ctx[ctx_sig], 1, bits, "ts_sigGroup"); no_sig_group_before_last = false; } @@ -333,10 +334,9 @@ void uvg_encode_ts_residual(encoder_state_t* const state, unsigned sigFlag = (curr_coeff != 0); if (numNonZero || nextSigPos != inferSigPos) { - cabac->cur_ctx = &cabac->ctx.transform_skip_sig[ + CABAC_FBITS_UPDATE(cabac, &cabac->ctx.transform_skip_sig[ uvg_context_get_sig_ctx_idx_abs_ts(coeff, pos_x, pos_y, width) - ]; - CABAC_BIN(cabac, sigFlag, "sig_coeff_flag"); + ], sigFlag, bits, "sig_coeff_flag"); maxCtxBins--; } @@ -344,10 +344,10 @@ void uvg_encode_ts_residual(encoder_state_t* const state, { //===== encode sign's ===== int sign = curr_coeff < 0; - cabac->cur_ctx = &cabac->ctx.transform_skip_res_sign[ - uvg_sign_ctx_id_abs_ts(coeff, pos_x, pos_y, width, 0) - ]; CABAC_BIN(cabac, sign, "coeff_sign_flag"); + CABAC_FBITS_UPDATE(cabac, &cabac->ctx.transform_skip_sig[ + uvg_sign_ctx_id_abs_ts(coeff, pos_x, pos_y, width, 0) + ], sign, bits, "coeff_sign_flag"); maxCtxBins--; numNonZero++; @@ -359,17 +359,15 @@ void uvg_encode_ts_residual(encoder_state_t* const state, remAbsLevel = modAbsCoeff - 1; unsigned gt1 = !!remAbsLevel; - cabac->cur_ctx = &cabac->ctx.transform_skip_gt1[ + CABAC_FBITS_UPDATE(cabac, &cabac->ctx.transform_skip_sig[ uvg_lrg1_ctx_id_abs_ts(coeff, pos_x, pos_y, width, 0) - ]; - CABAC_BIN(cabac, gt1, "abs_level_gtx_flag"); + ], remAbsLevel & 1, bits, "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"); + CABAC_FBITS_UPDATE(cabac, &cabac->ctx.transform_skip_par, gt1, bits, "par_level_flag"); maxCtxBins--; } } @@ -396,6 +394,9 @@ void uvg_encode_ts_residual(encoder_state_t* const state, unsigned gt2 = (absLevel >= (cutoffVal + 2)); cabac->cur_ctx = &cabac->ctx.transform_skip_gt2[cutoffVal >> 1]; CABAC_BIN(cabac, gt2, "abs_level_gtx_flag"); + CABAC_FBITS_UPDATE(cabac, &cabac->ctx.transform_skip_sig[ + kvz_lrg1_ctx_id_abs_ts(coeff, pos_x, pos_y, width, 0) + ], gt2, bits, "abs_level_gtx_flag"); maxCtxBins--; } cutoffVal += 2; @@ -419,16 +420,18 @@ void uvg_encode_ts_residual(encoder_state_t* const state, { int rice = 1; unsigned rem = scanPos <= lastScanPosPass1 ? (absLevel - cutoffVal) >> 1 : absLevel; - uvg_cabac_write_coeff_remain(cabac, rem, rice, 5); + bits += uvg_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"); + bits += 1; } } } } + if (bits_out && cabac->only_count) *bits_out += bits; } /** @@ -445,9 +448,9 @@ void uvg_encode_ts_residual(encoder_state_t* const state, * significant coefficient. */ void uvg_encode_last_significant_xy(cabac_data_t * const cabac, - uint8_t lastpos_x, uint8_t lastpos_y, - uint8_t width, uint8_t height, - uint8_t type, uint8_t scan) + uint8_t lastpos_x, uint8_t lastpos_y, + uint8_t width, uint8_t height, + uint8_t type, uint8_t scan, double* bits_out) { const int index_x = uvg_math_floor_log2(width); const int index_y = uvg_math_floor_log2(width); @@ -457,6 +460,7 @@ void uvg_encode_last_significant_xy(cabac_data_t * const cabac, uint8_t ctx_offset_y = type ? 0 : prefix_ctx[index_y]; uint8_t shift_x = type ? CLIP(0, 2, width>>3) : (index_x+1)>>2; uint8_t shift_y = type ? CLIP(0, 2, width >> 3) : (index_y + 1) >> 2; + double bits = 0; cabac_ctx_t *base_ctx_x = (type ? cabac->ctx.cu_ctx_last_x_chroma : cabac->ctx.cu_ctx_last_x_luma); cabac_ctx_t *base_ctx_y = (type ? cabac->ctx.cu_ctx_last_y_chroma : cabac->ctx.cu_ctx_last_y_luma); @@ -466,39 +470,38 @@ void uvg_encode_last_significant_xy(cabac_data_t * const cabac, // x prefix int last_x = 0; - for (last_x = 0; last_x < group_idx_x; last_x++) { - cabac->cur_ctx = &base_ctx_x[ctx_offset_x + (last_x >> shift_x)]; - CABAC_BIN(cabac, 1, "last_sig_coeff_x_prefix"); + for (; last_x < group_idx_x; last_x++) { + CABAC_FBITS_UPDATE(cabac, &base_ctx_x[ctx_offset_x + (last_x >> shift_x)], 1, bits, "last_sig_coeff_x_prefix"); } if (group_idx_x < ( /*width == 32 ? g_group_idx[15] : */g_group_idx[MIN(32, (int32_t)width) - 1])) { - cabac->cur_ctx = &base_ctx_x[ctx_offset_x + (last_x >> shift_x)]; - CABAC_BIN(cabac, 0, "last_sig_coeff_x_prefix"); + CABAC_FBITS_UPDATE(cabac, &base_ctx_x[ctx_offset_x + (last_x >> shift_x)], 0, bits, "last_sig_coeff_x_prefix"); } // y prefix int last_y = 0; - for (last_y = 0; last_y < group_idx_y; last_y++) { - cabac->cur_ctx = &base_ctx_y[ctx_offset_y + (last_y >> shift_y)]; - CABAC_BIN(cabac, 1, "last_sig_coeff_y_prefix"); + for (; last_y < group_idx_y; last_y++) { + CABAC_FBITS_UPDATE(cabac, &base_ctx_y[ctx_offset_y + (last_y >> shift_y)], 1, bits, "last_sig_coeff_y_prefix"); } if (group_idx_y < (/* height == 32 ? g_group_idx[15] : */g_group_idx[MIN(32, (int32_t)height) - 1])) { - cabac->cur_ctx = &base_ctx_y[ctx_offset_y + (last_y >> shift_y)]; - CABAC_BIN(cabac, 0, "last_sig_coeff_y_prefix"); + CABAC_FBITS_UPDATE(cabac, &base_ctx_y[ctx_offset_y + (last_y >> shift_y)], 0, bits, "last_sig_coeff_y_prefix"); } // last_sig_coeff_x_suffix if (group_idx_x > 3) { const int suffix = lastpos_x - g_min_in_group[group_idx_x]; - const int bits = (group_idx_x - 2) / 2; - CABAC_BINS_EP(cabac, suffix, bits, "last_sig_coeff_x_suffix"); + const int write_bits = (group_idx_x - 2) / 2; + CABAC_BINS_EP(cabac, suffix, write_bits, "last_sig_coeff_x_suffix"); + if (cabac->only_count) bits += write_bits; } // last_sig_coeff_y_suffix if (group_idx_y > 3) { const int suffix = lastpos_y - g_min_in_group[group_idx_y]; - const int bits = (group_idx_y - 2) / 2; - CABAC_BINS_EP(cabac, suffix, bits, "last_sig_coeff_y_suffix"); + const int write_bits = (group_idx_y - 2) / 2; + CABAC_BINS_EP(cabac, suffix, write_bits, "last_sig_coeff_y_suffix"); + if (cabac->only_count) bits += write_bits; } + if (cabac->only_count && bits_out) *bits_out += bits; } static void encode_chroma_tu(encoder_state_t* const state, int x, int y, int depth, const uint8_t width_c, cu_info_t* cur_pu, int8_t* scan_idx, lcu_coeff_t* coeff, uint8_t joint_chroma) { @@ -517,7 +520,7 @@ static void encode_chroma_tu(encoder_state_t* const state, int x, int y, int dep // TODO: transform skip for chroma blocks CABAC_BIN(cabac, 0, "transform_skip_flag"); } - uvg_encode_coeff_nxn(state, &state->cabac, coeff_u, width_c, COLOR_U, *scan_idx, cur_pu); + uvg_encode_coeff_nxn(state, &state->cabac, coeff_u, width_c, COLOR_U, *scan_idx, NULL, cur_pu); } if (cbf_is_set(cur_pu->cbf, depth, COLOR_V)) { @@ -525,7 +528,7 @@ static void encode_chroma_tu(encoder_state_t* const state, int x, int y, int dep cabac->cur_ctx = &cabac->ctx.transform_skip_model_chroma; CABAC_BIN(cabac, 0, "transform_skip_flag"); } - uvg_encode_coeff_nxn(state, &state->cabac, coeff_v, width_c, COLOR_V, *scan_idx, cur_pu); + uvg_encode_coeff_nxn(state, &state->cabac, coeff_v, width_c, COLOR_V, *scan_idx, NULL, cur_pu); } } else { @@ -534,7 +537,7 @@ static void encode_chroma_tu(encoder_state_t* const state, int x, int y, int dep cabac->cur_ctx = &cabac->ctx.transform_skip_model_chroma; CABAC_BIN(cabac, 0, "transform_skip_flag"); } - uvg_encode_coeff_nxn(state, &state->cabac, coeff_uv, width_c, COLOR_V, *scan_idx, cur_pu); + uvg_encode_coeff_nxn(state, &state->cabac, coeff_uv, width_c, COLOR_V, *scan_idx, NULL, cur_pu); } } @@ -569,7 +572,7 @@ static void encode_transform_unit(encoder_state_t * const state, DBG_YUVIEW_VALUE(state->frame->poc, DBG_YUVIEW_TR_SKIP, x, y, width, width, (cur_pu->tr_idx == MTS_SKIP) ? 1 : 0); } if(cur_pu->tr_idx == MTS_SKIP) { - uvg_encode_ts_residual(state, cabac, coeff_y, width, 0, scan_idx); + uvg_encode_ts_residual(state, cabac, coeff_y, width, 0, scan_idx, NULL); } else { uvg_encode_coeff_nxn(state, @@ -578,7 +581,8 @@ static void encode_transform_unit(encoder_state_t * const state, width, 0, scan_idx, - (cu_info_t * )cur_pu); + (cu_info_t * )cur_pu, + NULL); } } diff --git a/src/encode_coding_tree.h b/src/encode_coding_tree.h index 92e46e04..11989a63 100644 --- a/src/encode_coding_tree.h +++ b/src/encode_coding_tree.h @@ -51,7 +51,8 @@ void uvg_encode_ts_residual(encoder_state_t* const state, const coeff_t* coeff, uint32_t width, uint8_t type, - int8_t scan_mode); + int8_t scan_mode, + double* bits); void uvg_encode_mvd(encoder_state_t * const state, cabac_data_t *cabac, @@ -87,4 +88,4 @@ bool uvg_write_split_flag(const encoder_state_t* const state, cabac_data_t* caba void uvg_encode_last_significant_xy(cabac_data_t * const cabac, uint8_t lastpos_x, uint8_t lastpos_y, uint8_t width, uint8_t height, - uint8_t type, uint8_t scan); + uint8_t type, uint8_t scan, double* bits_out); diff --git a/src/rdo.c b/src/rdo.c index 22fbac20..7c84d996 100644 --- a/src/rdo.c +++ b/src/rdo.c @@ -294,7 +294,7 @@ out: * * \returns bits needed to code input coefficients */ -static INLINE uint32_t get_coeff_cabac_cost( +static INLINE double get_coeff_cabac_cost( const encoder_state_t * const state, const coeff_t *coeff, int32_t width, @@ -319,8 +319,8 @@ static INLINE uint32_t get_coeff_cabac_cost( // Clear bytes and bits and set mode to "count" cabac_copy.only_count = 1; - int num_buffered_bytes = cabac_copy.num_buffered_bytes; - int bits_left = cabac_copy.bits_left; + cabac_copy.update = 1; + double bits = 0; // Execute the coding function. // It is safe to drop the const modifier since state won't be modified @@ -332,7 +332,8 @@ static INLINE uint32_t get_coeff_cabac_cost( width, type, scan_mode, - NULL); + NULL, + &bits); } else { uvg_encode_ts_residual((encoder_state_t* const)state, @@ -340,15 +341,16 @@ static INLINE uint32_t get_coeff_cabac_cost( coeff, width, type, - scan_mode); + scan_mode, + &bits); } - if(cabac_copy.update) { + if(state->search_cabac.update) { memcpy((cabac_data_t *)&state->search_cabac, &cabac_copy, sizeof(cabac_copy)); } - return (bits_left - cabac_copy.bits_left) + ((cabac_copy.num_buffered_bytes - num_buffered_bytes) << 3); + return bits; } -static INLINE void save_ccc(int qp, const coeff_t *coeff, int32_t size, uint32_t ccc) +static INLINE void save_ccc(int qp, const coeff_t *coeff, int32_t size, double ccc) { pthread_mutex_t *mtx = outfile_mutex + qp; @@ -364,14 +366,14 @@ static INLINE void save_ccc(int qp, const coeff_t *coeff, int32_t size, uint32_t pthread_mutex_unlock(mtx); } -static INLINE void save_accuracy(int qp, uint32_t ccc, uint32_t fast_cost) +static INLINE void save_accuracy(int qp, double ccc, uint32_t fast_cost) { pthread_mutex_t *mtx = outfile_mutex + qp; assert(qp <= RD_SAMPLING_MAX_LAST_QP); pthread_mutex_lock(mtx); - fprintf(fastrd_learning_outfile[qp], "%u %u\n", fast_cost, ccc); + fprintf(fastrd_learning_outfile[qp], "%u %f\n", fast_cost, ccc); pthread_mutex_unlock(mtx); } @@ -384,7 +386,7 @@ static INLINE void save_accuracy(int qp, uint32_t ccc, uint32_t fast_cost) * * \returns number of bits needed to code coefficients */ -uint32_t uvg_get_coeff_cost(const encoder_state_t * const state, +double uvg_get_coeff_cost(const encoder_state_t * const state, const coeff_t *coeff, int32_t width, int32_t type, @@ -406,13 +408,13 @@ uint32_t uvg_get_coeff_cost(const encoder_state_t * const state, uint64_t weights = uvg_fast_coeff_get_weights(state); uint32_t fast_cost = uvg_fast_coeff_cost(coeff, width, weights); if (check_accuracy) { - uint32_t ccc = get_coeff_cabac_cost(state, coeff, width, type, scan_mode, tr_skip); + double ccc = get_coeff_cabac_cost(state, coeff, width, type, scan_mode, tr_skip); save_accuracy(state->qp, ccc, fast_cost); } return fast_cost; } } else { - uint32_t ccc = get_coeff_cabac_cost(state, coeff, width, type, scan_mode, tr_skip); + double ccc = get_coeff_cabac_cost(state, coeff, width, type, scan_mode, tr_skip); if (save_cccs) { save_ccc(state->qp, coeff, width * width, ccc); } diff --git a/src/rdo.h b/src/rdo.h index 46db8c90..de2af3cc 100644 --- a/src/rdo.h +++ b/src/rdo.h @@ -59,7 +59,7 @@ int uvg_ts_rdoq(encoder_state_t* const state, coeff_t* src_coeff, coeff_t* dest_ int32_t height, int8_t type, int8_t scan_mode); -uint32_t uvg_get_coeff_cost(const encoder_state_t * const state, +double uvg_get_coeff_cost(const encoder_state_t * const state, const coeff_t *coeff, int32_t width, int32_t type, diff --git a/src/strategies/avx2/encode_coding_tree-avx2.c b/src/strategies/avx2/encode_coding_tree-avx2.c index 8ad79ce8..c05a4fa6 100644 --- a/src/strategies/avx2/encode_coding_tree-avx2.c +++ b/src/strategies/avx2/encode_coding_tree-avx2.c @@ -252,7 +252,8 @@ void uvg_encode_coeff_nxn_avx2(encoder_state_t * const state, uint8_t width, uint8_t type, int8_t scan_mode, - int8_t tr_skip) + int8_t tr_skip, + double* bits_out) { const encoder_control_t * const encoder = state->encoder_control; int c1 = 1; @@ -260,6 +261,7 @@ void uvg_encode_coeff_nxn_avx2(encoder_state_t * const state, uint8_t last_coeff_y = 0; int32_t i; uint32_t sig_coeffgroup_nzs[8 * 8] = { 0 }; + double bits = 0; int8_t be_valid = encoder->cfg.signhide_enable; int32_t scan_pos_sig; @@ -361,7 +363,7 @@ void uvg_encode_coeff_nxn_avx2(encoder_state_t * const state, // transform skip flag if(width == 4 && encoder->cfg.trskip_enable) { cabac->cur_ctx = (type == 0) ? &(cabac->ctx.cu_sig_model_luma) : &(cabac->ctx.cu_sig_model_chroma); - CABAC_BIN(cabac, tr_skip, "transform_skip_flag"); + CABAC_FBITS_UPDATE(cabac, cabac->cur_ctx, tr_skip, bits, "transform_skip_flag"); } last_coeff_x = pos_last & (width - 1); @@ -374,7 +376,8 @@ void uvg_encode_coeff_nxn_avx2(encoder_state_t * const state, width, width, type, - scan_mode); + scan_mode, + bits_out); scan_pos_sig = scan_pos_last; @@ -406,8 +409,7 @@ void uvg_encode_coeff_nxn_avx2(encoder_state_t * const state, uint32_t sig_coeff_group = (sig_coeffgroup_nzs[cg_blk_pos] != 0); uint32_t ctx_sig = uvg_context_get_sig_coeff_group(sig_coeffgroup_nzs, cg_pos_x, cg_pos_y, width); - cabac->cur_ctx = &base_coeff_group_ctx[ctx_sig]; - CABAC_BIN(cabac, sig_coeff_group, "coded_sub_block_flag"); + CABAC_FBITS_UPDATE(cabac, &base_coeff_group_ctx[ctx_sig], sig_coeff_group, bits, "coded_sub_block_flag"); } if (sig_coeffgroup_nzs[cg_blk_pos]) { @@ -464,8 +466,7 @@ void uvg_encode_coeff_nxn_avx2(encoder_state_t * const state, if (curr_esc_flag | num_non_zero) { ctx_sig = ctx_sig_buf[id]; - cabac->cur_ctx = &baseCtx[ctx_sig]; - CABAC_BIN(cabac, curr_sig, "sig_coeff_flag"); + CABAC_FBITS_UPDATE(cabac, &baseCtx[ctx_sig], curr_sig, bits, "sig_coeff_flag"); } if (curr_sig) { @@ -519,8 +520,7 @@ void uvg_encode_coeff_nxn_avx2(encoder_state_t * const state, uint32_t shift = idx << 1; uint32_t symbol = (coeffs_gt1_bits >> shift) & 1; - cabac->cur_ctx = &base_ctx_mod[c1]; - CABAC_BIN(cabac, symbol, "coeff_abs_level_greater1_flag"); + CABAC_FBITS_UPDATE(cabac, &base_ctx_mod[c1], symbol, bits, "coeff_abs_level_greater1_flag"); c1 = (c1s_nextiter >> shift) & 3; } @@ -532,9 +532,7 @@ void uvg_encode_coeff_nxn_avx2(encoder_state_t * const state, if (first_c2_flag_idx != -1) { uint32_t shift = (first_c2_flag_idx << 1) + 1; uint8_t symbol = (coeffs_gt2_bits >> shift) & 1; - cabac->cur_ctx = &base_ctx_mod[0]; - - CABAC_BIN(cabac, symbol, "coeff_abs_level_greater2_flag"); + CABAC_FBITS_UPDATE(cabac, &base_ctx_mod[0], symbol, bits, "coeff_abs_level_greater2_flag"); } } int32_t shiftamt = (be_valid && sign_hidden) ? 1 : 0; @@ -546,6 +544,7 @@ void uvg_encode_coeff_nxn_avx2(encoder_state_t * const state, } } CABAC_BINS_EP(cabac, coeff_signs, nnz, "coeff_sign_flag"); + if (cabac->only_count) bits += nnz; if (c1 == 0 || num_non_zero > C1FLAG_NUMBER) { @@ -586,7 +585,7 @@ void uvg_encode_coeff_nxn_avx2(encoder_state_t * const state, if (!cabac->only_count && (encoder->cfg.crypto_features & UVG_CRYPTO_TRANSF_COEFFS)) { uvg_cabac_write_coeff_remain_encry(state, cabac, level_diff, go_rice_param, base_level); } else { - uvg_cabac_write_coeff_remain(cabac, level_diff, go_rice_param); + bits += uvg_cabac_write_coeff_remain(cabac, level_diff, go_rice_param); } if (curr_abs_coeff > 3 * (1 << go_rice_param)) { @@ -602,6 +601,7 @@ void uvg_encode_coeff_nxn_avx2(encoder_state_t * const state, num_non_zero = 0; coeff_signs = 0; } + if (cabac->only_count) *bits_out += bits; } #endif // COMPILE_INTEL_AVX2 diff --git a/src/strategies/avx2/encode_coding_tree-avx2.h b/src/strategies/avx2/encode_coding_tree-avx2.h index e18e6ffb..ae1845c8 100644 --- a/src/strategies/avx2/encode_coding_tree-avx2.h +++ b/src/strategies/avx2/encode_coding_tree-avx2.h @@ -47,7 +47,8 @@ void uvg_encode_coeff_nxn_avx2(encoder_state_t * const state, uint8_t width, uint8_t type, int8_t scan_mode, - int8_t tr_skip); + int8_t tr_skip, + double* bits_out); int uvg_strategy_register_encode_avx2(void* opaque, uint8_t bitdepth); diff --git a/src/strategies/generic/encode_coding_tree-generic.c b/src/strategies/generic/encode_coding_tree-generic.c index 5cf28d16..bde86ac0 100644 --- a/src/strategies/generic/encode_coding_tree-generic.c +++ b/src/strategies/generic/encode_coding_tree-generic.c @@ -57,7 +57,8 @@ void uvg_encode_coeff_nxn_generic(encoder_state_t * const state, uint8_t width, uint8_t color, int8_t scan_mode, - cu_info_t* cur_cu) { + cu_info_t* cur_cu, + double* bits_out) { //const encoder_control_t * const encoder = state->encoder_control; //int c1 = 1; @@ -70,6 +71,7 @@ void uvg_encode_coeff_nxn_generic(encoder_state_t * const state, int32_t scan_pos; //int32_t next_sig_pos; uint32_t blk_pos, pos_y, pos_x, sig, ctx_sig; + double bits = 0; // CONSTANTS @@ -115,7 +117,8 @@ void uvg_encode_coeff_nxn_generic(encoder_state_t * const state, width, width, color, - scan_mode); + scan_mode, + bits_out); @@ -144,8 +147,7 @@ void uvg_encode_coeff_nxn_generic(encoder_state_t * const state, uint32_t sig_coeff_group = (sig_coeffgroup_flag[cg_blk_pos] != 0); uint32_t ctx_sig = uvg_context_get_sig_coeff_group(sig_coeffgroup_flag, cg_pos_x, cg_pos_y, (MIN((uint8_t)32, width) >> (log2_cg_size / 2))); - cabac->cur_ctx = &base_coeff_group_ctx[ctx_sig]; - CABAC_BIN(cabac, sig_coeff_group, "significant_coeffgroup_flag"); + CABAC_FBITS_UPDATE(cabac, &base_coeff_group_ctx[ctx_sig], sig_coeff_group, bits, "significant_coeffgroup_flag"); } @@ -178,9 +180,8 @@ void uvg_encode_coeff_nxn_generic(encoder_state_t * const state, ctx_sig = uvg_context_get_sig_ctx_idx_abs(coeff, pos_x, pos_y, width, width, color, &temp_diag, &temp_sum); cabac_ctx_t* sig_ctx_luma = &(cabac->ctx.cu_sig_model_luma[MAX(0, (quant_state - 1))][ctx_sig]); cabac_ctx_t* sig_ctx_chroma = &(cabac->ctx.cu_sig_model_chroma[MAX(0, (quant_state - 1))][MIN(ctx_sig,7)]); - cabac->cur_ctx = (color == COLOR_Y ? sig_ctx_luma : sig_ctx_chroma); - CABAC_BIN(cabac, sig, "sig_coeff_flag"); + CABAC_FBITS_UPDATE(cabac, (color == 0 ? sig_ctx_luma : sig_ctx_chroma), sig, bits, "sig_coeff_flag"); reg_bins--; } else if (next_sig_pos != scan_pos_last) { @@ -214,25 +215,25 @@ void uvg_encode_coeff_nxn_generic(encoder_state_t * const state, // Code "greater than 1" flag uint8_t gt1 = remainder_abs_coeff ? 1 : 0; - cabac->cur_ctx = (color == COLOR_Y) ? &(cabac->ctx.cu_gtx_flag_model_luma[1][*offset]) : - &(cabac->ctx.cu_gtx_flag_model_chroma[1][*offset]); - CABAC_BIN(cabac, gt1, "gt1_flag"); + CABAC_FBITS_UPDATE(cabac, (color == 0) ? &(cabac->ctx.cu_gtx_flag_model_luma[1][*offset]) : + &(cabac->ctx.cu_gtx_flag_model_chroma[1][*offset]), + gt1, bits, "abs_level_gtx_flag"); reg_bins--; if (gt1) { remainder_abs_coeff -= 1; // Code coeff parity - cabac->cur_ctx = (color == COLOR_Y) ? &(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"); + CABAC_FBITS_UPDATE(cabac, (color == 0) ? &(cabac->ctx.cu_parity_flag_model_luma[*offset]) : + &(cabac->ctx.cu_parity_flag_model_chroma[*offset]), + remainder_abs_coeff & 1, bits, "par_flag"); remainder_abs_coeff >>= 1; reg_bins--; uint8_t gt2 = remainder_abs_coeff ? 1 : 0; - cabac->cur_ctx = (color == COLOR_Y) ? &(cabac->ctx.cu_gtx_flag_model_luma[0][*offset]) : - &(cabac->ctx.cu_gtx_flag_model_chroma[0][*offset]); - CABAC_BIN(cabac, gt2, "gt2_flag"); + CABAC_FBITS_UPDATE(cabac, (color == 0) ? &(cabac->ctx.cu_gtx_flag_model_luma[0][*offset]) : + &(cabac->ctx.cu_gtx_flag_model_chroma[0][*offset]), + gt2, bits, "gt2_flag"); reg_bins--; } } @@ -256,7 +257,7 @@ void uvg_encode_coeff_nxn_generic(encoder_state_t * const state, uint32_t second_pass_abs_coeff = abs(coeff[blk_pos]); if (second_pass_abs_coeff >= 4) { uint32_t remainder = (second_pass_abs_coeff - 4) >> 1; - uvg_cabac_write_coeff_remain(cabac, remainder, rice_param, 5); + bits += uvg_cabac_write_coeff_remain(cabac, remainder, rice_param, 5); } } @@ -272,7 +273,7 @@ void uvg_encode_coeff_nxn_generic(encoder_state_t * const state, rice_param = g_go_rice_pars[abs_sum]; pos0 = ((quant_state<2)?1:2) << rice_param; uint32_t remainder = (coeff_abs == 0 ? pos0 : coeff_abs <= pos0 ? coeff_abs - 1 : coeff_abs); - uvg_cabac_write_coeff_remain(cabac, remainder, rice_param, 5); + bits += uvg_cabac_write_coeff_remain(cabac, remainder, rice_param, 5); quant_state = (quant_state_transition_table >> ((quant_state << 2) + ((coeff_abs & 1) << 1))) & 3; if (coeff_abs) { num_non_zero++; @@ -296,6 +297,7 @@ void uvg_encode_coeff_nxn_generic(encoder_state_t * const state, } CABAC_BINS_EP(cabac, coeff_signs, num_signs, "coeff_signs"); + if (cabac->only_count) bits += num_signs; } if (color == COLOR_Y && cur_cu != NULL && (cg_pos_y > 3 || cg_pos_x > 3) && sig_coeffgroup_flag[cg_blk_pos] != 0) @@ -303,6 +305,7 @@ void uvg_encode_coeff_nxn_generic(encoder_state_t * const state, cur_cu->violates_mts_coeff_constraint = true; } } + if (cabac->only_count) *bits_out += bits; } diff --git a/src/strategies/generic/encode_coding_tree-generic.h b/src/strategies/generic/encode_coding_tree-generic.h index effdce85..8cfe497d 100644 --- a/src/strategies/generic/encode_coding_tree-generic.h +++ b/src/strategies/generic/encode_coding_tree-generic.h @@ -47,7 +47,8 @@ void uvg_encode_coeff_nxn_generic(encoder_state_t * const state, uint8_t width, uint8_t color, int8_t scan_mode, - cu_info_t* cur_cu); + cu_info_t* cur_cu, + double* bits_out); int uvg_strategy_register_encode_generic(void* opaque, uint8_t bitdepth); diff --git a/src/strategies/strategies-encode.h b/src/strategies/strategies-encode.h index 565c1580..8743a6ed 100644 --- a/src/strategies/strategies-encode.h +++ b/src/strategies/strategies-encode.h @@ -52,7 +52,8 @@ typedef unsigned (encode_coeff_nxn_func)(encoder_state_t * const state, uint8_t width, uint8_t color, int8_t scan_mode, - cu_info_t* cur_cu); + cu_info_t* cur_cu, + double *bits_out); // Declare function pointers. extern encode_coeff_nxn_func *uvg_encode_coeff_nxn;