Add new macro for potentially updating cabac context when obtaining the bit cost

This commit is contained in:
Joose Sainio 2021-12-13 12:23:16 +02:00
parent d8648fe1de
commit 4b8d217f2d
4 changed files with 70 additions and 93 deletions

View file

@ -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

View file

@ -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++)

View file

@ -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));

View file

@ -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");