From 4b8d217f2dcc7dfba3e3abd17ca6c95013437d5b Mon Sep 17 00:00:00 2001 From: Joose Sainio Date: Mon, 13 Dec 2021 12:23:16 +0200 Subject: [PATCH] Add new macro for potentially updating cabac context when obtaining the bit cost --- src/cabac.h | 8 +++++ src/sao.c | 50 +++++++++++++++-------------- src/search.c | 78 ++++++++++++++-------------------------------- src/search_intra.c | 27 +++++++--------- 4 files changed, 70 insertions(+), 93 deletions(-) diff --git a/src/cabac.h b/src/cabac.h index 59fb448c..8f0c7c70 100644 --- a/src/cabac.h +++ b/src/cabac.h @@ -131,6 +131,14 @@ void kvz_cabac_write_unary_max_symbol_ep(cabac_data_t *data, unsigned int symbol 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)->update) {\ + (cabac)->cur_ctx = ctx;\ + CABAC_BIN((cabac), (val), (name));\ + } \ +} while(0) extern double bits_written; // Macros diff --git a/src/sao.c b/src/sao.c index 35be7176..179f4311 100644 --- a/src/sao.c +++ b/src/sao.c @@ -49,63 +49,64 @@ static void init_sao_info(sao_info_t *sao) { } -static float sao_mode_bits_none(const encoder_state_t * const state, sao_info_t *sao_top, sao_info_t *sao_left) +static double sao_mode_bits_none(const encoder_state_t * const state, sao_info_t *sao_top, sao_info_t *sao_left) { - float mode_bits = 0.0; - const cabac_data_t * const cabac = &state->search_cabac; + double mode_bits = 0.0; + cabac_data_t * cabac = (cabac_data_t*)&state->search_cabac; const cabac_ctx_t *ctx = NULL; // FL coded merges. if (sao_left != NULL) { ctx = &(cabac->ctx.sao_merge_flag_model); - mode_bits += CTX_ENTROPY_FBITS(ctx, 0); + CABAC_FBITS_UPDATE(cabac, ctx, 0, mode_bits, "sao_merge_flag"); } if (sao_top != NULL) { ctx = &(cabac->ctx.sao_merge_flag_model); - mode_bits += CTX_ENTROPY_FBITS(ctx, 0); + CABAC_FBITS_UPDATE(cabac, ctx, 0, mode_bits, "sao_merge_flag"); } // TR coded type_idx_, none = 0 ctx = &(cabac->ctx.sao_type_idx_model); - mode_bits += CTX_ENTROPY_FBITS(ctx, 0); + CABAC_FBITS_UPDATE(cabac, ctx, 0, mode_bits, "sao_type"); return mode_bits; } -static float sao_mode_bits_merge(const encoder_state_t * const state, +static double sao_mode_bits_merge(const encoder_state_t * const state, int8_t merge_cand) { - float mode_bits = 0.0; - const cabac_data_t * const cabac = &state->search_cabac; + double mode_bits = 0.0; + cabac_data_t * const cabac = (cabac_data_t*)&state->search_cabac; const cabac_ctx_t *ctx = NULL; // FL coded merges. ctx = &(cabac->ctx.sao_merge_flag_model); - mode_bits += CTX_ENTROPY_FBITS(ctx, merge_cand == 1); + CABAC_FBITS_UPDATE(cabac, ctx, merge_cand == 1, mode_bits, "sao_merge_flag"); if (merge_cand == 1) return mode_bits; - mode_bits += CTX_ENTROPY_FBITS(ctx, merge_cand == 2); + CABAC_FBITS_UPDATE(cabac, ctx, merge_cand == 2, mode_bits, "sao_merge_flag"); return mode_bits; } -static float sao_mode_bits_edge(const encoder_state_t * const state, +static double sao_mode_bits_edge(const encoder_state_t * const state, int edge_class, int offsets[NUM_SAO_EDGE_CATEGORIES], sao_info_t *sao_top, sao_info_t *sao_left, unsigned buf_cnt) { - float mode_bits = 0.0; - const cabac_data_t * const cabac = &state->search_cabac; + double mode_bits = 0.0; + cabac_data_t * const cabac = (cabac_data_t*)&state->search_cabac; const cabac_ctx_t *ctx = NULL; // FL coded merges. if (sao_left != NULL) { - ctx = &(cabac->ctx.sao_merge_flag_model); - mode_bits += CTX_ENTROPY_FBITS(ctx, 0); + ctx = &(cabac->ctx.sao_merge_flag_model); + CABAC_FBITS_UPDATE(cabac, ctx, 0, mode_bits, "sao_merge_flag"); } if (sao_top != NULL) { ctx = &(cabac->ctx.sao_merge_flag_model); - mode_bits += CTX_ENTROPY_FBITS(ctx, 0); + CABAC_FBITS_UPDATE(cabac, ctx, 0, mode_bits, "sao_merge_flag"); } // TR coded type_idx_, edge = 2 = cMax ctx = &(cabac->ctx.sao_type_idx_model); - mode_bits += CTX_ENTROPY_FBITS(ctx, 1) + 1.0; + CABAC_FBITS_UPDATE(cabac, ctx, 1, mode_bits, "sao_type"); + mode_bits += 1.0; // TR coded offsets. for (unsigned buf_index = 0; buf_index < buf_cnt; buf_index++) { @@ -126,26 +127,27 @@ static float sao_mode_bits_edge(const encoder_state_t * const state, } -static float sao_mode_bits_band(const encoder_state_t * const state, +static double sao_mode_bits_band(const encoder_state_t * const state, int band_position[2], int offsets[10], sao_info_t *sao_top, sao_info_t *sao_left, unsigned buf_cnt) { - float mode_bits = 0.0; - const cabac_data_t * const cabac = &state->search_cabac; + double mode_bits = 0.0; + cabac_data_t * const cabac = (cabac_data_t*)&state->search_cabac; const cabac_ctx_t *ctx = NULL; // FL coded merges. if (sao_left != NULL) { ctx = &(cabac->ctx.sao_merge_flag_model); - mode_bits += CTX_ENTROPY_FBITS(ctx, 0); + CABAC_FBITS_UPDATE(cabac, ctx, 0, mode_bits, "sao_merge_flag"); } if (sao_top != NULL) { ctx = &(cabac->ctx.sao_merge_flag_model); - mode_bits += CTX_ENTROPY_FBITS(ctx, 0); + CABAC_FBITS_UPDATE(cabac, ctx, 0, mode_bits, "sao_merge_flag"); } // TR coded sao_type_idx_, band = 1 ctx = &(cabac->ctx.sao_type_idx_model); - mode_bits += CTX_ENTROPY_FBITS(ctx, 1) + 1.0; + CABAC_FBITS_UPDATE(cabac, ctx, 1, mode_bits, "sao_type"); + mode_bits += 1.0; // TR coded offsets and possible FL coded offset signs. for (unsigned buf_index = 0; buf_index < buf_cnt; buf_index++) diff --git a/src/search.c b/src/search.c index 553c4380..43a07d4b 100644 --- a/src/search.c +++ b/src/search.c @@ -282,11 +282,7 @@ double kvz_cu_rd_cost_luma(const encoder_state_t *const state, && MIN(tr_cu->tr_depth, depth) - tr_cu->depth < max_tr_depth) { cabac_ctx_t *ctx = &(cabac->ctx.trans_subdiv_model[5 - (6 - depth)]); - tr_tree_bits += CTX_ENTROPY_FBITS(ctx, tr_depth > 0); - if (cabac->update) { - cabac->cur_ctx = ctx; - CABAC_BIN(cabac, tr_depth > 0, "tr_split_search"); - } + CABAC_FBITS_UPDATE(cabac, ctx, tr_depth > 0, tr_tree_bits, "tr_split_search"); *bit_cost += tr_tree_bits; } @@ -318,23 +314,16 @@ double kvz_cu_rd_cost_luma(const encoder_state_t *const state, // However, if we have different tr_depth, the bits cannot be written in correct // order anyways so do not touch the chroma cbf here. if (state->encoder_control->chroma_format != KVZ_CSP_400) { - cabac_ctx_t* cr_ctx = &(state->search_cabac.ctx.qt_cbf_model_chroma[tr_depth]); + cabac_ctx_t* cr_ctx = &(cabac->ctx.qt_cbf_model_chroma[tr_depth]); cabac->cur_ctx = cr_ctx; int u_is_set = cbf_is_set(pred_cu->cbf, depth, COLOR_U); int v_is_set = cbf_is_set(pred_cu->cbf, depth, COLOR_V); - tr_tree_bits += CTX_ENTROPY_FBITS(cr_ctx, u_is_set); - CABAC_BIN(cabac, u_is_set, "cbf_cb_search"); - tr_tree_bits += CTX_ENTROPY_FBITS(cr_ctx, v_is_set); - CABAC_BIN(cabac, v_is_set, "cbf_cr_search"); + CABAC_FBITS_UPDATE(cabac, cr_ctx, u_is_set, tr_tree_bits, "cbf_cb_search"); + CABAC_FBITS_UPDATE(cabac, cr_ctx, v_is_set, tr_tree_bits, "cbf_cb_search"); } } - tr_tree_bits += CTX_ENTROPY_FBITS(ctx, is_set); + CABAC_FBITS_UPDATE(cabac, ctx, is_set, tr_tree_bits, "cbf_y_search"); *bit_cost += tr_tree_bits; - if(cabac->update) { - cabac->cur_ctx = ctx; - CABAC_BIN(cabac, is_set, "luma_cbf_search"); - } - } // SSD between reconstruction and original @@ -389,13 +378,11 @@ double kvz_cu_rd_cost_chroma(const encoder_state_t *const state, cabac->cur_ctx = ctx; if (tr_depth == 0 || cbf_is_set(pred_cu->cbf, depth - 1, COLOR_U)) { int u_is_set = cbf_is_set(pred_cu->cbf, depth, COLOR_U); - tr_tree_bits += CTX_ENTROPY_FBITS(ctx, u_is_set); - if(state->search_cabac.update) CABAC_BIN(cabac, u_is_set, "cbf_cb_search"); + CABAC_FBITS_UPDATE(cabac, ctx, u_is_set, tr_tree_bits, "cbf_cb_search"); } if (tr_depth == 0 || cbf_is_set(pred_cu->cbf, depth - 1, COLOR_V)) { int v_is_set = cbf_is_set(pred_cu->cbf, depth, COLOR_V); - tr_tree_bits += CTX_ENTROPY_FBITS(ctx, v_is_set); - if (state->search_cabac.update) CABAC_BIN(cabac, v_is_set, "cbf_cb_search"); + CABAC_FBITS_UPDATE(cabac, ctx, v_is_set, tr_tree_bits, "cbf_cb_search"); } *bit_cost += tr_tree_bits; } @@ -638,7 +625,9 @@ static double search_cu(encoder_state_t * const state, int x, int y, int depth, copy_cu_info(x_local, y_local, cu_width, &work_tree[depth + 1], lcu); } } - cost += CTX_ENTROPY_FBITS(&state->search_cabac.ctx.cu_pred_mode_model, 0) * state->lambda; + double pred_mode_type_bits = 0; + CABAC_FBITS_UPDATE(&state->search_cabac, &state->search_cabac.ctx.cu_pred_mode_model, 0, pred_mode_type_bits, "pred_mode_flag"); + cost += pred_mode_type_bits * state->lambda; } } @@ -666,7 +655,9 @@ static double search_cu(encoder_state_t * const state, int x, int y, int depth, kvz_search_cu_intra(state, x, y, depth, lcu, &intra_mode, &intra_cost); if(state->frame->slicetype != KVZ_SLICE_I) { - intra_cost += CTX_ENTROPY_FBITS(&state->search_cabac.ctx.cu_pred_mode_model, 1) * state->lambda; + double pred_mode_type_bits = 0; + CABAC_FBITS_UPDATE(&state->search_cabac, &state->search_cabac.ctx.cu_pred_mode_model, 1, pred_mode_type_bits, "pred_mode_flag"); + intra_cost += pred_mode_type_bits * state->lambda; } if (intra_cost < cost) { cost = intra_cost; @@ -754,26 +745,19 @@ static double search_cu(encoder_state_t * const state, int x, int y, int depth, 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]); - state->search_cabac.cur_ctx = ctx; - bits += CTX_ENTROPY_FBITS(ctx, 0); - CABAC_BIN(&state->search_cabac, 0, "no_split_search"); + CABAC_FBITS_UPDATE(&state->search_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]); - bits += CTX_ENTROPY_FBITS(ctx, 1); // NxN - state->search_cabac.cur_ctx = ctx; - FILE_BITS(CTX_ENTROPY_FBITS(ctx, 1), x, y, depth, "split"); - CABAC_BIN(&state->search_cabac, 1, "split_search"); + CABAC_FBITS_UPDATE(&state->search_cabac, ctx, 0, bits, "no_split_search"); } double mode_bits; 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); - bits += CTX_ENTROPY_FBITS(ctx, 1); // Intra - state->search_cabac.cur_ctx = ctx; - CABAC_BIN(&state->search_cabac, 1, "pred_mode"); + CABAC_FBITS_UPDATE(&state->search_cabac, &state->search_cabac.ctx.cu_pred_mode_model, 1, bits, "pred_mode_flag"); } mode_bits = calc_mode_bits(state, lcu, cur_cu, x, y); } @@ -832,25 +816,22 @@ static double search_cu(encoder_state_t * const state, int x, int y, int depth, memcpy(&state->search_cabac, &pre_search_cabac, sizeof(post_seach_cabac)); state->search_cabac.update = 1; + double split_bits = 0; + if (depth < MAX_DEPTH) { // Add cost of cu_split_flag. 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]); - split_cost += CTX_ENTROPY_FBITS(ctx, 1) * state->lambda; - state->search_cabac.cur_ctx = ctx; - FILE_BITS(CTX_ENTROPY_FBITS(ctx, 1), x, y, depth, "split"); - CABAC_BIN(&state->search_cabac, 1, "split_search"); + CABAC_FBITS_UPDATE(&state->search_cabac, ctx, 1, split_bits, "split_search"); } if (cur_cu->type == CU_INTRA && depth == MAX_DEPTH) { // Add cost of intra part_size. cabac_ctx_t *ctx = &(state->search_cabac.ctx.part_size_model[0]); - split_cost += CTX_ENTROPY_FBITS(ctx, 0) * state->lambda; // NxN - state->search_cabac.cur_ctx = ctx; - FILE_BITS(CTX_ENTROPY_FBITS(ctx, 0), x, y, depth, "split"); - CABAC_BIN(&state->search_cabac, 0, "split_search"); + CABAC_FBITS_UPDATE(&state->search_cabac, ctx, 0, split_bits, "split_search"); } state->search_cabac.update = 0; + split_cost += split_bits * state->lambda; // If skip mode was selected for the block, skip further search. // Skip mode means there's no coefficients in the block, so splitting @@ -887,17 +868,12 @@ static double search_cu(encoder_state_t * const state, int x, int y, int depth, 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]); - state->search_cabac.cur_ctx = ctx; - bits += CTX_ENTROPY_FBITS(ctx, 0); - CABAC_BIN(&state->search_cabac, 0, "no_split_search"); + CABAC_FBITS_UPDATE(&state->search_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]); - bits += CTX_ENTROPY_FBITS(ctx, 1); // NxN - state->search_cabac.cur_ctx = ctx; - FILE_BITS(CTX_ENTROPY_FBITS(ctx, 1), x, y, depth, "split"); - CABAC_BIN(&state->search_cabac, 1, "split_search"); + CABAC_FBITS_UPDATE(&state->search_cabac, ctx, 1, bits, "no_split_search"); } cur_cu->intra = cu_d1->intra; @@ -915,7 +891,7 @@ static double search_cu(encoder_state_t * const state, int x, int y, int depth, cur_cu->intra.mode, mode_chroma, NULL, lcu); - double mode_bits = calc_mode_bits(state, lcu, cur_cu, x, y); + double mode_bits = calc_mode_bits(state, lcu, cur_cu, x, y) + bits; cost += mode_bits * state->lambda; cost += kvz_cu_rd_cost_luma(state, x_local, y_local, depth, cur_cu, lcu, &bits); @@ -924,12 +900,6 @@ static double search_cu(encoder_state_t * const state, int x, int y, int depth, } FILE_BITS(bits, x, y, depth, "merged intra bits"); - // Add the cost of coding no-split. - uint8_t split_model = get_ctx_cu_split_model(lcu, x, y, depth); - const cabac_ctx_t *ctx = &(state->search_cabac.ctx.split_flag_model[split_model]); - cost += CTX_ENTROPY_FBITS(ctx, 0) * state->lambda; - - // Add the cost of coding intra mode only once. memcpy(&post_seach_cabac, &state->search_cabac, sizeof(post_seach_cabac)); memcpy(&state->search_cabac, &temp_cabac, sizeof(temp_cabac)); diff --git a/src/search_intra.c b/src/search_intra.c index ac72bd44..e29f29a3 100644 --- a/src/search_intra.c +++ b/src/search_intra.c @@ -270,7 +270,7 @@ static double search_intra_trdepth(encoder_state_t * const state, // the normal recursion in the cost functions. if (depth >= 1 && depth <= 3) { const cabac_ctx_t *ctx = &(state->search_cabac.ctx.trans_subdiv_model[5 - (6 - depth)]); - tr_split_bit += CTX_ENTROPY_FBITS(ctx, 1); + CABAC_FBITS_UPDATE(&state->search_cabac, ctx, 1, tr_split_bit, "tr_split"); *bit_cost += tr_split_bit; } @@ -285,10 +285,10 @@ static double search_intra_trdepth(encoder_state_t * const state, const cabac_ctx_t *ctx = &(state->search_cabac.ctx.qt_cbf_model_chroma[tr_depth]); if (tr_depth == 0 || cbf_is_set(pred_cu->cbf, depth - 1, COLOR_U)) { - cbf_bits += CTX_ENTROPY_FBITS(ctx, cbf_is_set(pred_cu->cbf, depth, COLOR_U)); + CABAC_FBITS_UPDATE(&state->search_cabac, ctx, cbf_is_set(pred_cu->cbf, depth, COLOR_U), cbf_bits, "cbf_cb"); } if (tr_depth == 0 || cbf_is_set(pred_cu->cbf, depth - 1, COLOR_V)) { - cbf_bits += CTX_ENTROPY_FBITS(ctx, cbf_is_set(pred_cu->cbf, depth, COLOR_V)); + CABAC_FBITS_UPDATE(&state->search_cabac, ctx, cbf_is_set(pred_cu->cbf, depth, COLOR_V), cbf_bits, "cbf_cr"); } *bit_cost += cbf_bits; } @@ -650,7 +650,7 @@ static int8_t search_intra_rdo(encoder_state_t * const state, double kvz_luma_mode_bits(encoder_state_t *state, int8_t luma_mode, const int8_t *intra_preds) { cabac_data_t* cabac = &state->search_cabac; - double mode_bits; + double mode_bits = 0; bool mode_in_preds = false; for (int i = 0; i < 3; ++i) { @@ -660,10 +660,8 @@ double kvz_luma_mode_bits(encoder_state_t *state, int8_t luma_mode, const int8_t } const cabac_ctx_t *ctx = &(cabac->ctx.intra_mode_model); - mode_bits = CTX_ENTROPY_FBITS(ctx, mode_in_preds); + CABAC_FBITS_UPDATE(cabac, ctx, mode_in_preds, mode_bits, "prev_intra_luma_pred_flag_search"); if (state->search_cabac.update) { - state->search_cabac.cur_ctx = ctx; - CABAC_BIN(&state->search_cabac, mode_in_preds, "prev_intra_luma_pred_flag_search"); if(mode_in_preds) { CABAC_BIN_EP(cabac, !(luma_mode == intra_preds[0]), "mpm_idx"); if(luma_mode != intra_preds[0]) { @@ -689,17 +687,16 @@ double kvz_luma_mode_bits(encoder_state_t *state, int8_t luma_mode, const int8_t double kvz_chroma_mode_bits(const encoder_state_t *state, int8_t chroma_mode, int8_t luma_mode) { - cabac_data_t* cabac = &state->search_cabac; + cabac_data_t* cabac = (cabac_data_t*)&state->search_cabac; const cabac_ctx_t *ctx = &(cabac->ctx.chroma_pred_model[0]); - double mode_bits; - if (chroma_mode == luma_mode) { - mode_bits = CTX_ENTROPY_FBITS(ctx, 0); - } else { - mode_bits = 2.0 + CTX_ENTROPY_FBITS(ctx, 1); + + double mode_bits = 0; + CABAC_FBITS_UPDATE(cabac, ctx, chroma_mode != luma_mode, mode_bits, "intra_chroma_pred_mode"); + if (chroma_mode != luma_mode) { + mode_bits += 2.0; } + if(cabac->update) { - cabac->cur_ctx = ctx; - CABAC_BIN(cabac, chroma_mode != luma_mode, "intra_chroma_pred_mode"); if(chroma_mode != luma_mode) { // Again it does not matter what we actually write here CABAC_BINS_EP(cabac, 0, 2, "intra_chroma_pred_mode");