diff --git a/src/cu.h b/src/cu.h index dfad7861..c954ce9b 100644 --- a/src/cu.h +++ b/src/cu.h @@ -119,7 +119,7 @@ typedef struct { uint8_t type : 3; //!< \brief block type, one of cu_type_t values uint8_t depth : 3; //!< \brief depth / size of this block - uint8_t tr_depth ; //!< \brief transform depth + uint8_t tr_depth : 3; //!< \brief transform depth uint8_t skipped : 1; //!< \brief flag to indicate this block is skipped uint8_t merged : 1; //!< \brief flag to indicate this block is merged uint8_t merge_idx : 3; //!< \brief merge index @@ -127,6 +127,9 @@ typedef struct uint8_t tr_idx : 3; //!< \brief transform index uint8_t joint_cb_cr : 3; //!< \brief joint chroma residual coding + uint8_t log2_width : 3; + uint8_t log2_height : 3; + uint16_t cbf; uint32_t split_tree : 3 * 9; @@ -594,7 +597,6 @@ static INLINE void cbf_copy(uint16_t *cbf, uint16_t src, color_t plane) *cbf |= src & (cbf_masks[0] << (NUM_CBF_DEPTHS * plane)); } -#define GET_SPLITDATA(CU,curDepth) ((CU)->depth > curDepth) -#define SET_SPLITDATA(CU,flag) { (CU)->split=(flag); } +#define GET_SPLITDATA(CU,curDepth) (((CU)->split_tree >> (curDepth)) & 7) #endif diff --git a/src/encode_coding_tree.c b/src/encode_coding_tree.c index 8c19df4b..931df0db 100644 --- a/src/encode_coding_tree.c +++ b/src/encode_coding_tree.c @@ -654,8 +654,6 @@ static void encode_transform_coeff( const cu_loc_t * cu_loc, int8_t depth, int8_t tr_depth, - uint8_t parent_coeff_u, - uint8_t parent_coeff_v, bool only_chroma, lcu_coeff_t* coeff, enum uvg_tree_type tree_type, @@ -726,13 +724,27 @@ static void encode_transform_coeff( } */ + if (split) { + int split_width = width >> 1; + int split_height = height >> 1; + + for (int j = 0; j < 2; j++) { + for (int i = 0; i < 2; i++) { + cu_loc_t loc; + uvg_cu_loc_ctor(&loc, (x + i * split_width), (y + j * split_height), width >> 1, height >> 1); + + encode_transform_coeff(state, &loc, depth + 1, tr_depth + 1, only_chroma, coeff, tree_type, true, luma_cbf_ctx, &loc); + } + } + return; + } // Chroma cb flags are not signaled when one of the following: // - transform size is 4 (2x2 chroma transform doesn't exist) // - they have already been signaled to 0 previously // When they are not present they are inferred to be 0, except for size 4 // when the flags from previous level are used. if (state->encoder_control->chroma_format != UVG_CSP_400 && (depth != 4 || only_chroma) && tree_type != UVG_LUMA_T && last_split) { - + if (!split) { if (true) { assert(tr_depth < 5); @@ -741,14 +753,11 @@ static void encode_transform_coeff( } if (true) { cabac->cur_ctx = &(cabac->ctx.qt_cbf_model_cr[cb_flag_u ? 1 : 0]); - CABAC_BIN(cabac, cb_flag_v, "cbf_cr"); + CABAC_BIN(cabac, cb_flag_v, "cbf_cr"); } } } - if (split) { - int split_width = width >> 1; - int split_height = height >> 1; for (int j = 0; j < 2; j++) { for (int i = 0; i < 2; i++) { @@ -1672,7 +1681,7 @@ void uvg_encode_coding_tree( // Code (possible) coeffs to bitstream if (cbf) { int luma_cbf_ctx = 0; - encode_transform_coeff(state, &cu_loc, depth, 0, 0, 0, 0, coeff, tree_type, true, false, &luma_cbf_ctx, cu_loc); + encode_transform_coeff(state, cu_loc, depth, 0, 0, 0, 0, coeff, tree_type, true, false, &luma_cbf_ctx, cu_loc); } encode_mts_idx(state, cabac, cur_cu, cu_loc); @@ -1704,7 +1713,7 @@ void uvg_encode_coding_tree( // Check if last split to write chroma bool last_split = (i + 1) == split_limit; - encode_transform_coeff(state, &split_loc, depth, 0, 0, 0, 0, coeff, tree_type, last_split, can_skip_last_cbf, &luma_cbf_ctx, cu_loc); + encode_transform_coeff(state, &split_loc, depth, 0, 0, coeff, tree_type, last_split, can_skip_last_cbf, &luma_cbf_ctx, cu_loc); can_skip_last_cbf &= luma_cbf_ctx == 2; } } @@ -1724,7 +1733,7 @@ void uvg_encode_coding_tree( tmp->violates_lfnst_constrained_luma = false; tmp->violates_lfnst_constrained_chroma = false; tmp->lfnst_last_scan_pos = false; - encode_transform_coeff(state, &cu_loc, depth, 0, 0, 0, 1, coeff, tree_type, true, false, &luma_cbf_ctx, cu_loc); + encode_transform_coeff(state, &cu_loc, depth, 0, 1, coeff, tree_type, true, false, &luma_cbf_ctx, cu_loc); // Write LFNST only once for single tree structure encode_lfnst_idx(state, cabac, tmp, x, y, depth, cu_width, cu_height, tree_type, COLOR_UV); } diff --git a/src/encoderstate.c b/src/encoderstate.c index 593ffd16..a42ce424 100644 --- a/src/encoderstate.c +++ b/src/encoderstate.c @@ -635,7 +635,7 @@ static void set_cu_qps(encoder_state_t *state, const cu_loc_t* const cu_loc, int if (cu_loc->x >= state->tile->frame->width || cu_loc->y >= state->tile->frame->height) return; cu_info_t *cu = uvg_cu_array_at(state->tile->frame->cu_array, cu_loc->x, cu_loc->y); - const int width = LCU_WIDTH >> cu->depth; + const int width = 1 << cu->log2_width; if (depth <= state->frame->max_qp_delta_depth) { *prev_qp = -1; diff --git a/src/search.c b/src/search.c index 11d934b9..2874248e 100644 --- a/src/search.c +++ b/src/search.c @@ -455,23 +455,6 @@ double uvg_cu_rd_cost_chroma( int u_is_set = pred_cu->joint_cb_cr ? (pred_cu->joint_cb_cr & 2) >> 1 : cbf_is_set(pred_cu->cbf, depth, COLOR_U); int v_is_set = pred_cu->joint_cb_cr ? (pred_cu->joint_cb_cr & 1) : cbf_is_set(pred_cu->cbf, depth, COLOR_V); - - // See luma for why the second condition - if (!skip_residual_coding) { - const int tr_depth = depth - pred_cu->depth; - cabac_data_t* cabac = (cabac_data_t*)&state->search_cabac; - cabac_ctx_t *ctx = &(cabac->ctx.qt_cbf_model_cb[0]); - cabac->cur_ctx = ctx; - if (tr_depth == 0 || cbf_is_set(pred_cu->cbf, depth - 1, COLOR_U)) { - CABAC_FBITS_UPDATE(cabac, ctx, u_is_set, tr_tree_bits, "cbf_cb_search"); - } - ctx = &(cabac->ctx.qt_cbf_model_cr[u_is_set]); - if (tr_depth == 0 || cbf_is_set(pred_cu->cbf, depth - 1, COLOR_V)) { - CABAC_FBITS_UPDATE(cabac, ctx, v_is_set, tr_tree_bits, "cbf_cb_search"); - } - } - - if (cu_loc->width > TR_MAX_WIDTH || cu_loc->height > TR_MAX_WIDTH) { double sum = 0; // Recursively process sub-CUs. @@ -490,6 +473,22 @@ double uvg_cu_rd_cost_chroma( return sum + tr_tree_bits * state->lambda; } + + if (!skip_residual_coding) { + const int tr_depth = depth - pred_cu->depth; + cabac_data_t* cabac = (cabac_data_t*)&state->search_cabac; + cabac_ctx_t* ctx = &(cabac->ctx.qt_cbf_model_cb[0]); + cabac->cur_ctx = ctx; + if (tr_depth == 0 || cbf_is_set(pred_cu->cbf, depth - 1, COLOR_U)) { + CABAC_FBITS_UPDATE(cabac, ctx, u_is_set, tr_tree_bits, "cbf_cb_search"); + } + ctx = &(cabac->ctx.qt_cbf_model_cr[u_is_set]); + if (tr_depth == 0 || cbf_is_set(pred_cu->cbf, depth - 1, COLOR_V)) { + CABAC_FBITS_UPDATE(cabac, ctx, v_is_set, tr_tree_bits, "cbf_cb_search"); + } + } + + if (state->encoder_control->cfg.jccr) { int cbf_mask = u_is_set * 2 + v_is_set - 1; @@ -570,17 +569,7 @@ static double cu_rd_cost_tr_split_accurate( } } - - bool has_chroma = state->encoder_control->chroma_format != UVG_CSP_400 && (depth != 4 || (cu_loc->x % 8 && cu_loc->y % 8)) && tree_type != UVG_LUMA_T; - if( !skip_residual_coding && has_chroma) { - if(tr_cu->tr_depth == depth) { - CABAC_FBITS_UPDATE(cabac, &(cabac->ctx.qt_cbf_model_cb[0]), cb_flag_u, tr_tree_bits, "cbf_cb"); - } - if(tr_cu->tr_depth == depth) { - CABAC_FBITS_UPDATE(cabac, &(cabac->ctx.qt_cbf_model_cr[cb_flag_u]), cb_flag_v, tr_tree_bits, "cbf_cr"); - } - } - + if (cu_loc->width > TR_MAX_WIDTH || cu_loc->height > TR_MAX_WIDTH) { double sum = 0; @@ -597,6 +586,13 @@ static double cu_rd_cost_tr_split_accurate( sum += cu_rd_cost_tr_split_accurate(state, pred_cu, lcu, tree_type, isp_cbf, &split_cu_loc); return sum + tr_tree_bits * state->lambda; } + + bool has_chroma = state->encoder_control->chroma_format != UVG_CSP_400 && (depth != 4 || (cu_loc->x % 8 && cu_loc->y % 8)) && tree_type != UVG_LUMA_T; + if (!skip_residual_coding && has_chroma) { + CABAC_FBITS_UPDATE(cabac, &(cabac->ctx.qt_cbf_model_cb[0]), cb_flag_u, tr_tree_bits, "cbf_cb"); + CABAC_FBITS_UPDATE(cabac, &(cabac->ctx.qt_cbf_model_cr[cb_flag_u]), cb_flag_v, tr_tree_bits, "cbf_cr"); + } + const int cb_flag_y = cbf_is_set(tr_cu->cbf, depth, COLOR_Y) && tree_type != UVG_CHROMA_T; const bool is_isp = !(pred_cu->type == CU_INTER || pred_cu->intra.isp_mode == ISP_MODE_NO_ISP);