From aea1133e6a48715be04d738e500aaccd6d0b871e Mon Sep 17 00:00:00 2001 From: Joose Sainio Date: Thu, 16 Dec 2021 08:40:23 +0200 Subject: [PATCH] Function for mock coding a CU and counting the bits --- src/cabac.c | 3 +- src/cabac.h | 4 +- src/encode_coding_tree.c | 228 +++++++++++++++++++++++++++++++-------- src/encode_coding_tree.h | 19 +++- src/rdo.c | 20 ++-- src/rdo.h | 8 +- src/search.c | 56 +++++++--- src/search_inter.c | 8 +- 8 files changed, 261 insertions(+), 85 deletions(-) diff --git a/src/cabac.c b/src/cabac.c index 5842edbe..ed480e17 100644 --- a/src/cabac.c +++ b/src/cabac.c @@ -547,7 +547,7 @@ void kvz_cabac_write_unary_max_symbol_ep(cabac_data_t * const data, unsigned int /** * \brief */ -void kvz_cabac_write_ep_ex_golomb(encoder_state_t * const state, +uint32_t kvz_cabac_write_ep_ex_golomb(encoder_state_t * const state, cabac_data_t * const data, uint32_t symbol, uint32_t count) @@ -576,4 +576,5 @@ void kvz_cabac_write_ep_ex_golomb(encoder_state_t * const state, } } kvz_cabac_encode_bins_ep(data, bins, num_bins); + return num_bins; } diff --git a/src/cabac.h b/src/cabac.h index 8f0c7c70..62d59d9e 100644 --- a/src/cabac.h +++ b/src/cabac.h @@ -122,7 +122,7 @@ void kvz_cabac_write_coeff_remain(cabac_data_t *cabac, uint32_t symbol, uint32_t r_param); 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); -void kvz_cabac_write_ep_ex_golomb(struct encoder_state_t * const state, cabac_data_t *data, +uint32_t kvz_cabac_write_ep_ex_golomb(struct encoder_state_t * const state, cabac_data_t *data, uint32_t symbol, uint32_t count); void kvz_cabac_write_unary_max_symbol(cabac_data_t *data, cabac_ctx_t *ctx, uint32_t symbol, int32_t offset, @@ -133,7 +133,7 @@ extern const float kvz_f_entropy_bits[128]; #define CTX_ENTROPY_FBITS(ctx, val) kvz_f_entropy_bits[(ctx)->uc_state ^ (val)] #define CABAC_FBITS_UPDATE(cabac, ctx, val, bits, name) do { \ - (bits) += kvz_f_entropy_bits[(ctx)->uc_state ^ (val)]; \ + if((cabac)->only_count) (bits) += kvz_f_entropy_bits[(ctx)->uc_state ^ (val)]; \ if((cabac)->update) {\ (cabac)->cur_ctx = ctx;\ CABAC_BIN((cabac), (val), (name));\ diff --git a/src/encode_coding_tree.c b/src/encode_coding_tree.c index 76f0cc7e..a847640e 100644 --- a/src/encode_coding_tree.c +++ b/src/encode_coding_tree.c @@ -309,15 +309,17 @@ static void encode_transform_coeff(encoder_state_t * const state, } void kvz_encode_inter_prediction_unit(encoder_state_t * const state, - cabac_data_t * const cabac, - const cu_info_t * const cur_cu, - int x, int y, int width, int height, - int depth, lcu_t* lcu) + cabac_data_t * const cabac, + const cu_info_t * const cur_cu, + int x, int y, int width, int height, + int depth, lcu_t* lcu, double* bits_out) { // Mergeflag int16_t num_cand = 0; - cabac->cur_ctx = &(cabac->ctx.cu_merge_flag_ext_model); - CABAC_BIN(cabac, cur_cu->merged, "MergeFlag"); + double bits = 0; + + CABAC_FBITS_UPDATE(cabac, &(cabac->ctx.cu_merge_flag_ext_model), cur_cu->merged, bits, "MergeFlag"); + num_cand = state->encoder_control->cfg.max_merge; if (cur_cu->merged) { //merge if (num_cand > 1) { @@ -325,10 +327,10 @@ void kvz_encode_inter_prediction_unit(encoder_state_t * const state, for (ui = 0; ui < num_cand - 1; ui++) { int32_t symbol = (ui != cur_cu->merge_idx); if (ui == 0) { - cabac->cur_ctx = &(cabac->ctx.cu_merge_idx_ext_model); - CABAC_BIN(cabac, symbol, "MergeIndex"); + CABAC_FBITS_UPDATE(cabac, &(cabac->ctx.cu_merge_idx_ext_model), symbol, bits, "MergeIndex"); } else { CABAC_BIN_EP(cabac,symbol,"MergeIndex"); + if(cabac->only_count) bits += 1; } if (symbol == 0) break; } @@ -339,12 +341,10 @@ void kvz_encode_inter_prediction_unit(encoder_state_t * const state, uint8_t inter_dir = cur_cu->inter.mv_dir-1; if (cur_cu->part_size == SIZE_2Nx2N || (LCU_WIDTH >> depth) != 8) { - cabac->cur_ctx = &(cabac->ctx.inter_dir[depth]); - CABAC_BIN(cabac, (inter_dir == 2), "inter_pred_idc"); + CABAC_FBITS_UPDATE(cabac, &(cabac->ctx.inter_dir[depth]), inter_dir == 2, bits, "inter_pred_idc"); } if (inter_dir < 2) { - cabac->cur_ctx = &(cabac->ctx.inter_dir[4]); - CABAC_BIN(cabac, inter_dir, "inter_pred_idc"); + CABAC_FBITS_UPDATE(cabac, &(cabac->ctx.inter_dir[4]), inter_dir, bits, "inter_pred_idc"); } } @@ -359,9 +359,8 @@ void kvz_encode_inter_prediction_unit(encoder_state_t * const state, if (ref_LX_size > 1) { // parseRefFrmIdx int32_t ref_frame = cur_cu->inter.mv_ref[ref_list_idx]; - - cabac->cur_ctx = &(cabac->ctx.cu_ref_pic_model[0]); - CABAC_BIN(cabac, (ref_frame != 0), "ref_idx_lX"); + + CABAC_FBITS_UPDATE(cabac, &(cabac->ctx.cu_ref_pic_model[0]), (ref_frame != 0), bits, "ref_idx_lX"); if (ref_frame > 0) { ref_frame--; @@ -373,9 +372,10 @@ void kvz_encode_inter_prediction_unit(encoder_state_t * const state, if (i == 0) { cabac->cur_ctx = &cabac->ctx.cu_ref_pic_model[1]; - CABAC_BIN(cabac, symbol, "ref_idx_lX"); + CABAC_FBITS_UPDATE(cabac, &cabac->ctx.cu_ref_pic_model[1], symbol, bits, "ref_idx_lX"); } else { CABAC_BIN_EP(cabac, symbol, "ref_idx_lX"); + if (cabac->only_count) bits += 1; } if (symbol == 0) break; } @@ -404,7 +404,7 @@ void kvz_encode_inter_prediction_unit(encoder_state_t * const state, const int32_t mvd_hor = cur_cu->inter.mv[ref_list_idx][0] - mv_cand[cu_mv_cand][0]; const int32_t mvd_ver = cur_cu->inter.mv[ref_list_idx][1] - mv_cand[cu_mv_cand][1]; - kvz_encode_mvd(state, cabac, mvd_hor, mvd_ver); + kvz_encode_mvd(state, cabac, mvd_hor, mvd_ver, bits_out); } // Signal which candidate MV to use @@ -416,6 +416,7 @@ void kvz_encode_inter_prediction_unit(encoder_state_t * const state, } // for ref_list } // if !merge + if(bits_out) *bits_out += bits; } @@ -466,7 +467,7 @@ static INLINE uint8_t intra_mode_encryption(encoder_state_t * const state, static void encode_intra_coding_unit(encoder_state_t * const state, cabac_data_t * const cabac, const cu_info_t * const cur_cu, - int x, int y, int depth) + int x, int y, int depth, double* bits_out) { const videoframe_t * const frame = state->tile->frame; uint8_t intra_pred_mode_actual[4]; @@ -569,18 +570,19 @@ static void encode_intra_coding_unit(encoder_state_t * const state, } #endif } - - cabac->cur_ctx = &(cabac->ctx.intra_mode_model); + for (int j = 0; j < num_pred_units; ++j) { - CABAC_BIN(cabac, flag[j], "prev_intra_luma_pred_flag"); + CABAC_FBITS_UPDATE(cabac, &(cabac->ctx.intra_mode_model),flag[j], *bits_out, "prev_intra_luma_pred_flag"); } for (int j = 0; j < num_pred_units; ++j) { // Signal index of the prediction mode in the prediction list. if (flag[j]) { CABAC_BIN_EP(cabac, (mpm_preds[j] == 0 ? 0 : 1), "mpm_idx"); + if (cabac->only_count) *bits_out += 1; if (mpm_preds[j] != 0) { CABAC_BIN_EP(cabac, (mpm_preds[j] == 1 ? 0 : 1), "mpm_idx"); + if (cabac->only_count) *bits_out += 1; } } else { // Signal the actual prediction mode. @@ -599,6 +601,7 @@ static void encode_intra_coding_unit(encoder_state_t * const state, } CABAC_BINS_EP(cabac, tmp_pred, 5, "rem_intra_luma_pred_mode"); + if (cabac->only_count) *bits_out += 5; } } @@ -639,17 +642,21 @@ static void encode_intra_coding_unit(encoder_state_t * const state, */ cabac->cur_ctx = &(cabac->ctx.chroma_pred_model[0]); if (pred_mode == 4) { - CABAC_BIN(cabac, 0, "intra_chroma_pred_mode"); + CABAC_FBITS_UPDATE(cabac, &(cabac->ctx.chroma_pred_model[0]), 0, *bits_out,"intra_chroma_pred_mode"); } else { - CABAC_BIN(cabac, 1, "intra_chroma_pred_mode"); + CABAC_FBITS_UPDATE(cabac, &(cabac->ctx.chroma_pred_model[0]), 1, *bits_out,"intra_chroma_pred_mode"); CABAC_BINS_EP(cabac, pred_mode, 2, "intra_chroma_pred_mode"); + if (cabac->only_count) *bits_out += 2; } } - encode_transform_coeff(state, x, y, depth, 0, 0, 0); + // if we are counting bits, the cost for transform coeffs is done separately + // To get the distortion at the same time + if(!cabac->only_count) + encode_transform_coeff(state, x, y, depth, 0, 0, 0); } -static void encode_part_mode(encoder_state_t * const state, +static double encode_part_mode(encoder_state_t * const state, cabac_data_t * const cabac, const cu_info_t * const cur_cu, int depth) @@ -684,32 +691,32 @@ static void encode_part_mode(encoder_state_t * const state, // log2CbSize == MinCbLog2SizeY | 0 1 2 bypass // log2CbSize > MinCbLog2SizeY | 0 1 3 bypass // ------------------------------+------------------ - + double bits = 0; if (cur_cu->type == CU_INTRA) { if (depth == MAX_DEPTH) { cabac->cur_ctx = &(cabac->ctx.part_size_model[0]); if (cur_cu->part_size == SIZE_2Nx2N) { - CABAC_BIN(cabac, 1, "part_mode 2Nx2N"); + CABAC_FBITS_UPDATE(cabac, &(cabac->ctx.part_size_model[0]), 1, bits, "part_mode 2Nx2N"); } else { - CABAC_BIN(cabac, 0, "part_mode NxN"); + CABAC_FBITS_UPDATE(cabac, &(cabac->ctx.part_size_model[0]), 0, bits, "part_mode NxN"); } } } else { cabac->cur_ctx = &(cabac->ctx.part_size_model[0]); if (cur_cu->part_size == SIZE_2Nx2N) { - CABAC_BIN(cabac, 1, "part_mode 2Nx2N"); - return; + CABAC_FBITS_UPDATE(cabac, &(cabac->ctx.part_size_model[0]), 1, bits, "part_mode 2Nx2N"); + return bits; } - CABAC_BIN(cabac, 0, "part_mode split"); + CABAC_FBITS_UPDATE(cabac, &(cabac->ctx.part_size_model[0]), 0, bits, "part_mode split"); cabac->cur_ctx = &(cabac->ctx.part_size_model[1]); if (cur_cu->part_size == SIZE_2NxN || cur_cu->part_size == SIZE_2NxnU || cur_cu->part_size == SIZE_2NxnD) { - CABAC_BIN(cabac, 1, "part_mode vertical"); + CABAC_FBITS_UPDATE(cabac, &(cabac->ctx.part_size_model[1]), 1, bits, "part_mode vertical"); } else { - CABAC_BIN(cabac, 0, "part_mode horizontal"); + CABAC_FBITS_UPDATE(cabac, &(cabac->ctx.part_size_model[1]), 0, bits, "part_mode horizontal"); } if (state->encoder_control->cfg.amp_enable && depth < MAX_DEPTH) { @@ -717,19 +724,22 @@ static void encode_part_mode(encoder_state_t * const state, if (cur_cu->part_size == SIZE_2NxN || cur_cu->part_size == SIZE_Nx2N) { - CABAC_BIN(cabac, 1, "part_mode SMP"); - return; + CABAC_FBITS_UPDATE(cabac, &(cabac->ctx.part_size_model[3]), 1, bits, "part_mode SMP"); + return bits; } - CABAC_BIN(cabac, 0, "part_mode AMP"); + CABAC_FBITS_UPDATE(cabac, &(cabac->ctx.part_size_model[3]), 0, bits, "part_mode AMP"); if (cur_cu->part_size == SIZE_2NxnU || cur_cu->part_size == SIZE_nLx2N) { CABAC_BINS_EP(cabac, 0, 1, "part_mode AMP"); + if(cabac->only_count) bits += 1; } else { CABAC_BINS_EP(cabac, 1, 1, "part_mode AMP"); + if(cabac->only_count) bits += 1; } } } + return bits; } void kvz_encode_coding_tree(encoder_state_t * const state, @@ -865,7 +875,7 @@ void kvz_encode_coding_tree(encoder_state_t * const state, const int pu_h = PU_GET_H(cur_cu->part_size, cu_width, i); const cu_info_t *cur_pu = kvz_cu_array_at_const(frame->cu_array, pu_x, pu_y); - kvz_encode_inter_prediction_unit(state, cabac, cur_pu, pu_x, pu_y, pu_w, pu_h, depth, NULL); + kvz_encode_inter_prediction_unit(state, cabac, cur_pu, pu_x, pu_y, pu_w, pu_h, depth, NULL, NULL); } { @@ -883,7 +893,7 @@ void kvz_encode_coding_tree(encoder_state_t * const state, } } } else if (cur_cu->type == CU_INTRA) { - encode_intra_coding_unit(state, cabac, cur_cu, x, y, depth); + encode_intra_coding_unit(state, cabac, cur_cu, x, y, depth, NULL); } #if ENABLE_PCM @@ -942,11 +952,135 @@ end: } +void kvz_mock_encode_coding_unit( + encoder_state_t* const state, + cabac_data_t* cabac, + int x, int y, int depth, + lcu_t* lcu) { + double bits = 0; + const encoder_control_t* const ctrl = state->encoder_control; + + int x_local = SUB_SCU(x); + int y_local = SUB_SCU(y); + + const int cu_width = LCU_WIDTH >> depth; + const int half_cu = cu_width >> 1; + + const cu_info_t* cur_cu = LCU_GET_CU_AT_PX(lcu, x_local, y_local); + const cu_info_t* left_cu = NULL, *above_cu = NULL; + if (x) { + left_cu = LCU_GET_CU_AT_PX(lcu, x_local - 1, y_local); + } + if (y) { + above_cu = LCU_GET_CU_AT_PX(lcu, x_local, y_local-1); + } + uint8_t split_model = 0; + + // Absolute coordinates + uint16_t abs_x = x + state->tile->offset_x; + uint16_t abs_y = y + state->tile->offset_y; + + // Check for slice border + bool border_x = ctrl->in.width < abs_x + cu_width; + bool border_y = ctrl->in.height < abs_y + cu_width; + bool border = border_x || border_y; /*!< are we in any border CU */ + + if (depth <= state->frame->max_qp_delta_depth) { + state->must_code_qp_delta = true; + } + + // When not in MAX_DEPTH, insert split flag and split the blocks if needed + if (depth != MAX_DEPTH) { + // Implicit split flag when on border + if (!border) { + // Get left and top block split_flags and if they are present and true, increase model number + if (left_cu && GET_SPLITDATA(left_cu, depth) == 1) { + split_model++; + } + + if (above_cu && GET_SPLITDATA(above_cu, depth) == 1) { + split_model++; + } + + // This mocks encoding the current CU so it should be never split + CABAC_FBITS_UPDATE(cabac, &(cabac->ctx.split_flag_model[split_model]), 0, bits, "SplitFlag"); + } + } + + // Encode skip flag + if (state->frame->slicetype != KVZ_SLICE_I) { + int8_t ctx_skip = 0; + + if (left_cu && left_cu->skipped) { + ctx_skip++; + } + if (above_cu && above_cu->skipped) { + ctx_skip++; + } + + CABAC_FBITS_UPDATE(cabac, &(cabac->ctx.cu_skip_flag_model[ctx_skip]), cur_cu->skipped, bits, "SkipFlag"); + + if (cur_cu->skipped) { + int16_t num_cand = state->encoder_control->cfg.max_merge; + if (num_cand > 1) { + for (int ui = 0; ui < num_cand - 1; ui++) { + int32_t symbol = (ui != cur_cu->merge_idx); + if (ui == 0) { + CABAC_FBITS_UPDATE(cabac, &(cabac->ctx.cu_merge_idx_ext_model), symbol, bits, "MergeIndex"); + } + else { + CABAC_BIN_EP(cabac, symbol, "MergeIndex"); + if(cabac->only_count) bits += 1; + } + if (symbol == 0) { + break; + } + } + } + return; + } + } + // Prediction mode + if (state->frame->slicetype != KVZ_SLICE_I) { + CABAC_FBITS_UPDATE(cabac, &(cabac->ctx.cu_pred_mode_model), (cur_cu->type == CU_INTRA), bits, "PredMode"); + } + + // part_mode + bits += encode_part_mode(state, cabac, cur_cu, depth); + + if (cur_cu->type == CU_INTER) { + const int num_pu = kvz_part_mode_num_parts[cur_cu->part_size]; + + for (int i = 0; i < num_pu; ++i) { + const int pu_x = PU_GET_X(cur_cu->part_size, cu_width, x, i); + const int pu_y = PU_GET_Y(cur_cu->part_size, cu_width, y, i); + const int pu_w = PU_GET_W(cur_cu->part_size, cu_width, i); + const int pu_h = PU_GET_H(cur_cu->part_size, cu_width, i); + const cu_info_t* cur_pu = LCU_GET_CU_AT_PX(lcu, SUB_SCU(pu_x), SUB_SCU(pu_y)); + + kvz_encode_inter_prediction_unit(state, cabac, cur_pu, pu_x, pu_y, pu_w, pu_h, depth, lcu, &bits); + } + + { + int cbf = cbf_is_set_any(cur_cu->cbf, depth); + // Only need to signal coded block flag if not skipped or merged + // skip = no coded residual, merge = coded residual + if (cur_cu->part_size != SIZE_2Nx2N || !cur_cu->merged) { + CABAC_FBITS_UPDATE(cabac, &(cabac->ctx.cu_qt_root_cbf_model), cbf, bits, "rqt_root_cbf"); + } + + } + } + else if (cur_cu->type == CU_INTRA) { + encode_intra_coding_unit(state, cabac, cur_cu, x, y, depth, NULL); + } +} + void kvz_encode_mvd(encoder_state_t * const state, cabac_data_t *cabac, int32_t mvd_hor, - int32_t mvd_ver) + int32_t mvd_ver, double* bits_out) { const int8_t hor_abs_gr0 = mvd_hor != 0; const int8_t ver_abs_gr0 = mvd_ver != 0; @@ -954,20 +1088,21 @@ void kvz_encode_mvd(encoder_state_t * const state, const uint32_t mvd_ver_abs = abs(mvd_ver); cabac->cur_ctx = &cabac->ctx.cu_mvd_model[0]; - CABAC_BIN(cabac, (mvd_hor != 0), "abs_mvd_greater0_flag_hor"); - CABAC_BIN(cabac, (mvd_ver != 0), "abs_mvd_greater0_flag_ver"); + CABAC_FBITS_UPDATE(cabac, &cabac->ctx.cu_mvd_model[0], (mvd_hor != 0), *bits_out, "abs_mvd_greater0_flag_hor"); + CABAC_FBITS_UPDATE(cabac, &cabac->ctx.cu_mvd_model[0], (mvd_ver != 0), *bits_out, "abs_mvd_greater0_flag_ver"); cabac->cur_ctx = &cabac->ctx.cu_mvd_model[1]; if (hor_abs_gr0) { - CABAC_BIN(cabac, (mvd_hor_abs>1), "abs_mvd_greater1_flag_hor"); + CABAC_FBITS_UPDATE(cabac, &cabac->ctx.cu_mvd_model[1], (mvd_hor_abs>1), *bits_out,"abs_mvd_greater1_flag_hor"); } if (ver_abs_gr0) { - CABAC_BIN(cabac, (mvd_ver_abs>1), "abs_mvd_greater1_flag_ver"); + CABAC_FBITS_UPDATE(cabac, &cabac->ctx.cu_mvd_model[1], (mvd_ver_abs>1), *bits_out, "abs_mvd_greater1_flag_ver"); } if (hor_abs_gr0) { if (mvd_hor_abs > 1) { - kvz_cabac_write_ep_ex_golomb(state, cabac, mvd_hor_abs - 2, 1); + uint32_t bits = kvz_cabac_write_ep_ex_golomb(state, cabac, mvd_hor_abs - 2, 1); + if(cabac->only_count) *bits_out += bits; } uint32_t mvd_hor_sign = (mvd_hor > 0) ? 0 : 1; if (!state->cabac.only_count && @@ -976,10 +1111,12 @@ void kvz_encode_mvd(encoder_state_t * const state, mvd_hor_sign = mvd_hor_sign ^ kvz_crypto_get_key(state->crypto_hdl, 1); } CABAC_BIN_EP(cabac, mvd_hor_sign, "mvd_sign_flag_hor"); + if (cabac->only_count) *bits_out += 1; } if (ver_abs_gr0) { if (mvd_ver_abs > 1) { - kvz_cabac_write_ep_ex_golomb(state, cabac, mvd_ver_abs - 2, 1); + uint32_t bits = kvz_cabac_write_ep_ex_golomb(state, cabac, mvd_ver_abs - 2, 1); + if (cabac->only_count) *bits_out += bits; } uint32_t mvd_ver_sign = mvd_ver > 0 ? 0 : 1; if (!state->cabac.only_count && @@ -988,5 +1125,6 @@ void kvz_encode_mvd(encoder_state_t * const state, mvd_ver_sign = mvd_ver_sign^kvz_crypto_get_key(state->crypto_hdl, 1); } CABAC_BIN_EP(cabac, mvd_ver_sign, "mvd_sign_flag_ver"); + if (cabac->only_count) *bits_out += 1; } } diff --git a/src/encode_coding_tree.h b/src/encode_coding_tree.h index a3f95b36..b8e29358 100644 --- a/src/encode_coding_tree.h +++ b/src/encode_coding_tree.h @@ -49,13 +49,22 @@ void kvz_encode_coding_tree(encoder_state_t * const state, void kvz_encode_mvd(encoder_state_t * const state, cabac_data_t *cabac, int32_t mvd_hor, - int32_t mvd_ver); + int32_t mvd_ver, + double* bits_out); + +void kvz_mock_encode_coding_unit( + encoder_state_t* const state, + cabac_data_t* cabac, + int x, int y, int depth, + lcu_t* lcu); void kvz_encode_inter_prediction_unit(encoder_state_t* const state, - cabac_data_t* const cabac, - const cu_info_t* const cur_cu, - int x, int y, int width, int height, - int depth, lcu_t* lcu); + cabac_data_t* const cabac, + const cu_info_t* const cur_cu, + int x, int y, int width, int height, + int depth, + lcu_t* lcu, + double* bits_out); void kvz_encode_last_significant_xy(cabac_data_t * const cabac, uint8_t lastpos_x, uint8_t lastpos_y, diff --git a/src/rdo.c b/src/rdo.c index 6b8960ee..5b6c3b49 100644 --- a/src/rdo.c +++ b/src/rdo.c @@ -1010,22 +1010,18 @@ void kvz_rdoq(encoder_state_t * const state, coeff_t *coef, coeff_t *dest_coeff, /** * Calculate cost of actual motion vectors using CABAC coding */ -uint32_t kvz_get_mvd_coding_cost_cabac(const encoder_state_t *state, - const cabac_data_t* cabac, - const int32_t mvd_hor, - const int32_t mvd_ver) +double kvz_get_mvd_coding_cost_cabac(const encoder_state_t* state, + const cabac_data_t* cabac, + const int32_t mvd_hor, + const int32_t mvd_ver) { cabac_data_t cabac_copy = *cabac; cabac_copy.only_count = 1; - + double bits = 0; // It is safe to drop const here because cabac->only_count is set. - kvz_encode_mvd((encoder_state_t*) state, &cabac_copy, mvd_hor, mvd_ver); + kvz_encode_mvd((encoder_state_t*) state, &cabac_copy, mvd_hor, mvd_ver, &bits); - uint32_t bitcost = - ((23 - cabac_copy.bits_left) + (cabac_copy.num_buffered_bytes << 3)) - - ((23 - cabac->bits_left) + (cabac->num_buffered_bytes << 3)); - - return bitcost; + return bits; } /** MVD cost calculation with CABAC @@ -1160,7 +1156,7 @@ double kvz_calc_mvd_cost_cabac(const encoder_state_t * state, // ToDo: Bidir vector support if (!(state->frame->ref_list == REF_PIC_LIST_1 && /*cur_cu->inter.mv_dir == 3*/ 0)) { // It is safe to drop const here because cabac->only_count is set. - kvz_encode_mvd((encoder_state_t*) state, cabac, mvd.x, mvd.y); + kvz_encode_mvd((encoder_state_t*) state, cabac, mvd.x, mvd.y, NULL); } // Signal which candidate MV to use diff --git a/src/rdo.h b/src/rdo.h index dd75fdb9..23453eee 100644 --- a/src/rdo.h +++ b/src/rdo.h @@ -71,10 +71,10 @@ uint32_t kvz_get_coded_level(encoder_state_t * state, double* coded_cost, double kvz_mvd_cost_func kvz_calc_mvd_cost_cabac; -uint32_t kvz_get_mvd_coding_cost_cabac(const encoder_state_t *state, - const cabac_data_t* cabac, - int32_t mvd_hor, - int32_t mvd_ver); +double kvz_get_mvd_coding_cost_cabac(const encoder_state_t* state, + const cabac_data_t* cabac, + int32_t mvd_hor, + int32_t mvd_ver); // Number of fixed point fractional bits used in the fractional bit table. #define CTX_FRAC_BITS 15 diff --git a/src/search.c b/src/search.c index 43a07d4b..ad24b501 100644 --- a/src/search.c +++ b/src/search.c @@ -740,29 +740,61 @@ static double search_cu(encoder_state_t * const state, int x, int y, int depth, if (cur_cu->type == CU_INTRA || cur_cu->type == CU_INTER) { double bits = 0; - state->search_cabac.update = 1; + cabac_data_t* cabac = &state->search_cabac; + cabac->update = 1; if(depth < MAX_DEPTH) { uint8_t split_model = get_ctx_cu_split_model(lcu, x, y, depth); - cabac_ctx_t* ctx = &(state->search_cabac.ctx.split_flag_model[split_model]); - CABAC_FBITS_UPDATE(&state->search_cabac, ctx, 0, bits, "no_split_search"); + cabac_ctx_t* ctx = &(cabac->ctx.split_flag_model[split_model]); + CABAC_FBITS_UPDATE(cabac, ctx, 0, bits, "no_split_search"); } else if(depth == MAX_DEPTH && cur_cu->type == CU_INTRA) { // Add cost of intra part_size. - cabac_ctx_t* ctx = &(state->search_cabac.ctx.part_size_model[0]); - CABAC_FBITS_UPDATE(&state->search_cabac, ctx, 0, bits, "no_split_search"); + cabac_ctx_t* ctx = &(cabac->ctx.part_size_model[0]); + CABAC_FBITS_UPDATE(cabac, ctx, 0, bits, "no_split_search"); } - double mode_bits; + double mode_bits = 0; + if (state->frame->slicetype != KVZ_SLICE_I) { + int ctx_skip = 0; + if (x > 0) { + ctx_skip += LCU_GET_CU_AT_PX(lcu, x_local - 1, y_local)->skipped; + } + if (y > 0) { + ctx_skip += LCU_GET_CU_AT_PX(lcu, x_local, y_local - 1)->skipped; + } + CABAC_FBITS_UPDATE(cabac, &(cabac->ctx.cu_skip_flag_model[ctx_skip]), cur_cu->skipped, mode_bits, "skip_flag"); + if (cur_cu->skipped) { + int16_t num_cand = state->encoder_control->cfg.max_merge; + if (num_cand > 1) { + for (int ui = 0; ui < num_cand - 1; ui++) { + int32_t symbol = (ui != cur_cu->merge_idx); + if (ui == 0) { + CABAC_FBITS_UPDATE(cabac, &(cabac->ctx.cu_merge_idx_ext_model), symbol, mode_bits, "MergeIndex"); + } + else { + CABAC_BIN_EP(cabac, symbol, "MergeIndex"); + mode_bits += 1; + } + if (symbol == 0) { + break; + } + } + } + } + + } if (cur_cu->type == CU_INTRA) { if(state->frame->slicetype != KVZ_SLICE_I) { - cabac_ctx_t* ctx = &(state->search_cabac.ctx.cu_pred_mode_model); - CABAC_FBITS_UPDATE(&state->search_cabac, &state->search_cabac.ctx.cu_pred_mode_model, 1, bits, "pred_mode_flag"); + cabac_ctx_t* ctx = &(cabac->ctx.cu_pred_mode_model); + CABAC_FBITS_UPDATE(cabac, ctx, 1, mode_bits, "pred_mode_flag"); } - mode_bits = calc_mode_bits(state, lcu, cur_cu, x, y); + mode_bits += calc_mode_bits(state, lcu, cur_cu, x, y); } - else { - mode_bits = inter_bitcost; + else if (!cur_cu->skipped) { + cabac_ctx_t* ctx = &(cabac->ctx.cu_pred_mode_model); + CABAC_FBITS_UPDATE(cabac, ctx, 0, mode_bits, "pred_mode_flag"); + mode_bits += inter_bitcost; } bits += mode_bits; cost = mode_bits * state->lambda; @@ -795,7 +827,7 @@ static double search_cu(encoder_state_t * const state, int x, int y, int depth, cur_cu->cbf = 0; lcu_fill_cbf(lcu, x_local, y_local, cu_width, cur_cu); } - state->search_cabac.update = 0; + cabac->update = 0; } bool can_split_cu = diff --git a/src/search_inter.c b/src/search_inter.c index 983ffcc8..a4c75d9e 100644 --- a/src/search_inter.c +++ b/src/search_inter.c @@ -323,19 +323,19 @@ static void select_starting_point(inter_search_info_t *info, } -static uint32_t get_mvd_coding_cost(const encoder_state_t *state, +static double get_mvd_coding_cost(const encoder_state_t *state, const cabac_data_t* cabac, const int32_t mvd_hor, const int32_t mvd_ver) { - unsigned bitcost = 0; + double bitcost = 0; const vector2d_t abs_mvd = { abs(mvd_hor), abs(mvd_ver) }; bitcost += get_ep_ex_golomb_bitcost(abs_mvd.x) << CTX_FRAC_BITS; bitcost += get_ep_ex_golomb_bitcost(abs_mvd.y) << CTX_FRAC_BITS; // Round and shift back to integer bits. - return (bitcost + CTX_FRAC_HALF_BIT) >> CTX_FRAC_BITS; + return bitcost / (1 << CTX_FRAC_BITS); } @@ -353,7 +353,7 @@ static int select_mv_cand(const encoder_state_t *state, return 0; } - uint32_t (*mvd_coding_cost)(const encoder_state_t * const state, + double (*mvd_coding_cost)(const encoder_state_t * const state, const cabac_data_t*, int32_t, int32_t); if (state->encoder_control->cfg.mv_rdo) {