From: Lynne <dev@lynne.ee> To: FFmpeg development discussions and patches <ffmpeg-devel@ffmpeg.org> Subject: Re: [FFmpeg-devel] [PATCH v9 03/13] vvcdec: add cabac decoder Date: Mon, 1 Jan 2024 16:13:42 +0100 (CET) Message-ID: <Nn4_bVu--3-9@lynne.ee> (raw) In-Reply-To: <TYSPR06MB64337C13ECE97978A56C1152AA62A@TYSPR06MB6433.apcprd06.prod.outlook.com> Jan 1, 2024, 15:14 by nuomi2021@gmail.com: > + > +//fixme > +static void vvc_refill2(CABACContext* c) { > Fix what? Also, wrong coding style. > + int i; > + unsigned x; > +#if !HAVE_FAST_CLZ > + x = c->low ^ (c->low - 1); > + i = 7 - ff_h264_norm_shift[x >> (CABAC_BITS - 1)]; > +#else > + i = ff_ctz(c->low) - CABAC_BITS; > +#endif > + > + x = -CABAC_MASK; > + > +#if CABAC_BITS == 16 > + x += (c->bytestream[0] << 9) + (c->bytestream[1] << 1); > +#else > + x += c->bytestream[0] << 1; > +#endif > CABAC_BITS? > + > + c->low += x << i; > +#if !UNCHECKED_BITSTREAM_READER > + if (c->bytestream < c->bytestream_end) > +#endif > + c->bytestream += CABAC_BITS / 8; > +} > + > +static int inline vvc_get_cabac(CABACContext *c, VVCCabacState* base, const int ctx) > +{ > + VVCCabacState *s = base + ctx; > + const int qRangeIdx = c->range >> 5; > + const int pState = s->state[1] + (s->state[0] << 4); > + const int valMps = pState >> 14; > + const int RangeLPS = (qRangeIdx * ((valMps ? 32767 - pState : pState) >> 9 ) >> 1) + 4; > + int bit, lps_mask; > + > + c->range -= RangeLPS; > + lps_mask = ((c->range<<(CABAC_BITS+1)) - c->low)>>31; > + > + c->low -= (c->range<<(CABAC_BITS+1)) & lps_mask; > + c->range += (RangeLPS - c->range) & lps_mask; > + > + bit = valMps ^ (lps_mask & 1); > + > + lps_mask = ff_h264_norm_shift[c->range]; > + c->range <<= lps_mask; > + c->low <<= lps_mask; > + > + if (!(c->low & CABAC_MASK)) > + vvc_refill2(c); > + s->state[0] = s->state[0] - (s->state[0] >> s->shift[0]) + (1023 * bit >> s->shift[0]); > + s->state[1] = s->state[1] - (s->state[1] >> s->shift[1]) + (16383 * bit >> s->shift[1]); > + return bit; > +} > + > +#define GET_CABAC(ctx) vvc_get_cabac(&lc->ep->cc, lc->ep->cabac_state, ctx) > + > +//9.3.3.4 Truncated binary (TB) binarization process > +static int truncated_binary_decode(VVCLocalContext *lc, const int c_max) > +{ > + const int n = c_max + 1; > + const int k = av_log2(n); > + const int u = (1 << (k+1)) - n; > + int v = 0; > + for (int i = 0; i < k; i++) > + v = (v << 1) | get_cabac_bypass(&lc->ep->cc); > + if (v >= u) { > + v = (v << 1) | get_cabac_bypass(&lc->ep->cc); > + v -= u; > + } > + return v; > +} > + > +// 9.3.3.6 Limited k-th order Exp-Golomb binarization process > +static int limited_kth_order_egk_decode(CABACContext *c, const int k, const int max_pre_ext_len, const int trunc_suffix_len) > +{ > + int pre_ext_len = 0; > + int escape_length; > + int val = 0; > + while ((pre_ext_len < max_pre_ext_len) && get_cabac_bypass(c)) > + pre_ext_len++; > + if (pre_ext_len == max_pre_ext_len) > + escape_length = trunc_suffix_len; > + else > + escape_length = pre_ext_len + k; > + while (escape_length-- > 0) { > + val = (val << 1) + get_cabac_bypass(c); > + } > + val += ((1 << pre_ext_len) - 1) << k; > + return val; > +} > + > +static av_always_inline > +void get_left_top(const VVCLocalContext *lc, uint8_t *left, uint8_t *top, > + const int x0, const int y0, const uint8_t *left_ctx, const uint8_t *top_ctx) > +{ > + const VVCFrameContext *fc = lc->fc; > + const VVCSPS *sps = fc->ps.sps; > + const int min_cb_width = fc->ps.pps->min_cb_width; > + const int x0b = av_mod_uintp2(x0, sps->ctb_log2_size_y); > + const int y0b = av_mod_uintp2(y0, sps->ctb_log2_size_y); > + const int x_cb = x0 >> sps->min_cb_log2_size_y; > + const int y_cb = y0 >> sps->min_cb_log2_size_y; > + > + if (lc->ctb_left_flag || x0b) > + *left = SAMPLE_CTB(left_ctx, x_cb - 1, y_cb); > + if (lc->ctb_up_flag || y0b) > + *top = SAMPLE_CTB(top_ctx, x_cb, y_cb - 1); > +} > + > +static av_always_inline > +uint8_t get_inc(VVCLocalContext *lc, const uint8_t *ctx) > +{ > + uint8_t left = 0, top = 0; > + get_left_top(lc, &left, &top, lc->cu->x0, lc->cu->y0, ctx, ctx); > + return left + top; > +} > + > +int ff_vvc_sao_merge_flag_decode(VVCLocalContext *lc) > +{ > + return GET_CABAC(SAO_MERGE_FLAG); > +} > + > +int ff_vvc_sao_type_idx_decode(VVCLocalContext *lc) > +{ > + if (!GET_CABAC(SAO_TYPE_IDX)) > + return SAO_NOT_APPLIED; > + > + if (!get_cabac_bypass(&lc->ep->cc)) > + return SAO_BAND; > + return SAO_EDGE; > +} > + > +int ff_vvc_sao_band_position_decode(VVCLocalContext *lc) > +{ > + int value = get_cabac_bypass(&lc->ep->cc); > + > + for (int i = 0; i < 4; i++) > + value = (value << 1) | get_cabac_bypass(&lc->ep->cc); > + return value; > +} > + > +int ff_vvc_sao_offset_abs_decode(VVCLocalContext *lc) > +{ > + int i = 0; > + const int length = (1 << (FFMIN(lc->fc->ps.sps->bit_depth, 10) - 5)) - 1; > + > + while (i < length && get_cabac_bypass(&lc->ep->cc)) > + i++; > + return i; > +} > + > +int ff_vvc_sao_offset_sign_decode(VVCLocalContext *lc) > +{ > + return get_cabac_bypass(&lc->ep->cc); > +} > + > +int ff_vvc_sao_eo_class_decode(VVCLocalContext *lc) > +{ > + int ret = get_cabac_bypass(&lc->ep->cc) << 1; > + ret |= get_cabac_bypass(&lc->ep->cc); > + return ret; > +} > + > +int ff_vvc_alf_ctb_flag(VVCLocalContext *lc, const int rx, const int ry, const int c_idx) > +{ > + int inc = c_idx * 3; > + const VVCFrameContext *fc = lc->fc; > + if (lc->ctb_left_flag) { > + const ALFParams *left = &CTB(fc->tab.alf, rx - 1, ry); > + inc += left->ctb_flag[c_idx]; > + } > + if (lc->ctb_up_flag) { > + const ALFParams *above = &CTB(fc->tab.alf, rx, ry - 1); > + inc += above->ctb_flag[c_idx]; > + } > + return GET_CABAC(ALF_CTB_FLAG + inc); > +} > + > +int ff_vvc_alf_use_aps_flag(VVCLocalContext *lc) > +{ > + return GET_CABAC(ALF_USE_APS_FLAG); > +} > + > +int ff_vvc_alf_luma_prev_filter_idx(VVCLocalContext *lc) > +{ > + return truncated_binary_decode(lc, lc->sc->sh.r->sh_num_alf_aps_ids_luma - 1); > +} > + > +int ff_vvc_alf_luma_fixed_filter_idx(VVCLocalContext *lc) > +{ > + return truncated_binary_decode(lc, 15); > +} > + > +int ff_vvc_alf_ctb_filter_alt_idx(VVCLocalContext *lc, const int c_idx, const int num_chroma_filters) > +{ > + int i = 0; > + const int length = num_chroma_filters - 1; > + > + while (i < length && GET_CABAC(ALF_CTB_FILTER_ALT_IDX + c_idx - 1)) > + i++; > + return i; > +} > + > +int ff_vvc_alf_ctb_cc_idc(VVCLocalContext *lc, const int rx, const int ry, const int idx, const int cc_filters_signalled) > +{ > + int inc = !idx ? ALF_CTB_CC_CB_IDC : ALF_CTB_CC_CR_IDC; > + int i = 0; > + const VVCFrameContext *fc = lc->fc; > + if (lc->ctb_left_flag) { > + const ALFParams *left = &CTB(fc->tab.alf, rx - 1, ry); > + inc += left->ctb_cc_idc[idx] != 0; > + } > + if (lc->ctb_up_flag) { > + const ALFParams *above = &CTB(fc->tab.alf, rx, ry - 1); > + inc += above->ctb_cc_idc[idx] != 0; > + } > + > + if (!GET_CABAC(inc)) > + return 0; > + i++; > + while (i < cc_filters_signalled && get_cabac_bypass(&lc->ep->cc)) > + i++; > + return i; > +} > + > +int ff_vvc_split_cu_flag(VVCLocalContext *lc, const int x0, const int y0, > + const int cb_width, const int cb_height, const int is_chroma, const VVCAllowedSplit *a) > +{ > + const VVCFrameContext *fc = lc->fc; > + const VVCPPS *pps = fc->ps.pps; > + const int is_inside = (x0 + cb_width <= pps->width) && (y0 + cb_height <= pps->height); > + > + if ((a->btv || a->bth || a->ttv || a->tth || a->qt) && is_inside) > + { > + uint8_t inc = 0, left_height = cb_height, top_width = cb_width; > + > + get_left_top(lc, &left_height, &top_width, x0, y0, fc->tab.cb_height[is_chroma], fc->tab.cb_width[is_chroma]); > + inc += left_height < cb_height; > + inc += top_width < cb_width; > + inc += (a->btv + a->bth + a->ttv + a->tth + 2 * a->qt - 1) / 2 * 3; > + > + return GET_CABAC(SPLIT_CU_FLAG + inc); > + > + } > + return !is_inside; > +} > + > +static int split_qt_flag_decode(VVCLocalContext *lc, const int x0, const int y0, const int ch_type, const int cqt_depth) > +{ > + const VVCFrameContext *fc = lc->fc; > + int inc = 0; > + uint8_t depth_left = 0, depth_top = 0; > + > + get_left_top(lc, &depth_left, &depth_top, x0, y0, fc->tab.cqt_depth[ch_type], fc->tab.cqt_depth[ch_type]); > + inc += depth_left > cqt_depth; > + inc += depth_top > cqt_depth; > + inc += (cqt_depth >= 2) * 3; > + > + return GET_CABAC(SPLIT_QT_FLAG + inc); > +} > + > +static int mtt_split_cu_vertical_flag_decode(VVCLocalContext *lc, const int x0, const int y0, > + const int cb_width, const int cb_height, const int ch_type, const VVCAllowedSplit* a) > +{ > + if ((a->bth || a->tth) && (a->btv || a->ttv)) { > + int inc; > + const int v = a->btv + a->ttv; > + const int h = a->bth + a->tth; > + if (v > h) > + inc = 4; > + else if (v < h) > + inc = 3; > + else { > + const VVCFrameContext *fc = lc->fc; > + const VVCSPS *sps = fc->ps.sps; > + const int min_cb_width = fc->ps.pps->min_cb_width; > + const int x0b = av_mod_uintp2(x0, sps->ctb_log2_size_y); > + const int y0b = av_mod_uintp2(y0, sps->ctb_log2_size_y); > + const int x_cb = x0 >> sps->min_cb_log2_size_y; > + const int y_cb = y0 >> sps->min_cb_log2_size_y; > + const int available_a = lc->ctb_up_flag || y0b; > + const int available_l = lc->ctb_left_flag || x0b; > + const int da = cb_width / (available_a ? SAMPLE_CTB(fc->tab.cb_width[ch_type], x_cb, y_cb - 1) : 1); > + const int dl = cb_height / (available_l ? SAMPLE_CTB(fc->tab.cb_height[ch_type], x_cb - 1, y_cb) : 1); > + > + if (da == dl || !available_a || !available_l) > + inc = 0; > + else if (da < dl) > + inc = 1; > + else > + inc = 2; > + } > + return GET_CABAC(MTT_SPLIT_CU_VERTICAL_FLAG + inc); > + } > + return !(a->bth || a->tth); > +} > + > +static int mtt_split_cu_binary_flag_decode(VVCLocalContext *lc, const int mtt_split_cu_vertical_flag, const int mtt_depth) > +{ > + const int inc = (2 * mtt_split_cu_vertical_flag) + ((mtt_depth <= 1) ? 1 : 0); > + return GET_CABAC(MTT_SPLIT_CU_BINARY_FLAG + inc); > +} > + > +VVCSplitMode ff_vvc_split_mode(VVCLocalContext *lc, const int x0, const int y0, const int cb_width, const int cb_height, > + const int cqt_depth, const int mtt_depth, const int ch_type, const VVCAllowedSplit *a) > +{ > + const int allow_no_qt = a->btv || a->bth || a->ttv || a->tth; > + int split_qt_flag; > + int mtt_split_cu_vertical_flag; > + int mtt_split_cu_binary_flag; > + const VVCSplitMode mtt_split_modes[] = { > + SPLIT_TT_HOR, SPLIT_BT_HOR, SPLIT_TT_VER, SPLIT_BT_VER, > + }; > + if (allow_no_qt && a->qt) { > + split_qt_flag = split_qt_flag_decode(lc, x0, y0, ch_type, cqt_depth); > + } else { > + split_qt_flag = !allow_no_qt || a->qt; > + } > + if (split_qt_flag) > + return SPLIT_QT; > + mtt_split_cu_vertical_flag = mtt_split_cu_vertical_flag_decode(lc, x0, y0, cb_width, cb_height, ch_type, a); > + if ((a->btv && a->ttv && mtt_split_cu_vertical_flag) || > + (a->bth && a->tth && !mtt_split_cu_vertical_flag)) { > + mtt_split_cu_binary_flag = mtt_split_cu_binary_flag_decode(lc, mtt_split_cu_vertical_flag, mtt_depth); > + } else { > + if (!a->btv && !a->bth) > + mtt_split_cu_binary_flag = 0; > + else if (!a->ttv && !a->tth) > + mtt_split_cu_binary_flag = 1; > + else if (a->bth && a->ttv) > + mtt_split_cu_binary_flag = 1 - mtt_split_cu_vertical_flag; > + else > + mtt_split_cu_binary_flag = mtt_split_cu_vertical_flag; > + } > + return mtt_split_modes[(mtt_split_cu_vertical_flag << 1) + mtt_split_cu_binary_flag]; > +} > + > +int ff_vvc_non_inter_flag(VVCLocalContext *lc, const int x0, const int y0, const int ch_type) > +{ > + const VVCFrameContext *fc = lc->fc; > + uint8_t inc, left = 0, top = 0; > + > + get_left_top(lc, &left, &top, x0, y0, fc->tab.cpm[ch_type], fc->tab.cpm[ch_type]); > + inc = left || top; > + return GET_CABAC(NON_INTER_FLAG + inc); > +} > + > +int ff_vvc_pred_mode_flag(VVCLocalContext *lc, const int is_chroma) > +{ > + const VVCFrameContext *fc = lc->fc; > + const CodingUnit *cu = lc->cu; > + uint8_t inc, left = 0, top = 0; > + > + get_left_top(lc, &left, &top, cu->x0, cu->y0, fc->tab.cpm[is_chroma], fc->tab.cpm[is_chroma]); > + inc = left || top; > + return GET_CABAC(PRED_MODE_FLAG + inc); > +} > + > +int ff_vvc_pred_mode_plt_flag(VVCLocalContext *lc) > +{ > + return GET_CABAC(PRED_MODE_PLT_FLAG); > +} > + > +int ff_vvc_intra_bdpcm_luma_flag(VVCLocalContext *lc) > +{ > + return GET_CABAC(INTRA_BDPCM_LUMA_FLAG); > +} > + > +int ff_vvc_intra_bdpcm_luma_dir_flag(VVCLocalContext *lc) > +{ > + return GET_CABAC(INTRA_BDPCM_LUMA_DIR_FLAG); > +} > + > +int ff_vvc_intra_bdpcm_chroma_flag(VVCLocalContext *lc) > +{ > + return GET_CABAC(INTRA_BDPCM_CHROMA_FLAG); > +} > + > +int ff_vvc_intra_bdpcm_chroma_dir_flag(VVCLocalContext *lc) > +{ > + return GET_CABAC(INTRA_BDPCM_CHROMA_DIR_FLAG); > +} > + > +int ff_vvc_cu_skip_flag(VVCLocalContext *lc, const uint8_t *cu_skip_flag) > +{ > + const int inc = get_inc(lc, cu_skip_flag); > + return GET_CABAC(CU_SKIP_FLAG + inc); > +} > + > +int ff_vvc_pred_mode_ibc_flag(VVCLocalContext *lc, const int is_chroma) > +{ > + const VVCFrameContext *fc = lc->fc; > + const CodingUnit *cu = lc->cu; > + uint8_t left_mode = MODE_INTER, top_mode = MODE_INTER; > + int inc; > + > + get_left_top(lc, &left_mode, &top_mode, cu->x0, cu->y0, fc->tab.cpm[is_chroma], fc->tab.cpm[is_chroma]); > + inc = (left_mode == MODE_IBC) + (top_mode == MODE_IBC); > + return GET_CABAC(PRED_MODE_IBC_FLAG + inc); > +} > + > +int ff_vvc_intra_mip_flag(VVCLocalContext *lc, const uint8_t *intra_mip_flag) > +{ > + const int w = lc->cu->cb_width; > + const int h = lc->cu->cb_height; > + const int inc = (w > h * 2 || h > w * 2) ? 3 : get_inc(lc, intra_mip_flag); > + return GET_CABAC(INTRA_MIP_FLAG + inc); > +} > + > +int ff_vvc_intra_mip_transposed_flag(VVCLocalContext *lc) > +{ > + return get_cabac_bypass(&lc->ep->cc); > +} > + > +int ff_vvc_intra_mip_mode(VVCLocalContext *lc) > +{ > + const int w = lc->cu->cb_width; > + const int h = lc->cu->cb_height; > + const int c_max = (w == 4 && h == 4) ? 15 : > + ((w == 4 || h == 4) || (w == 8 && h == 8)) ? 7: 5; > + return truncated_binary_decode(lc, c_max); > +} > + > +int ff_vvc_intra_luma_ref_idx(VVCLocalContext *lc) > +{ > + int i; > + for (i = 0; i < 2; i++) { > + if (!GET_CABAC(INTRA_LUMA_REF_IDX + i)) > + return i; > + } > + return i; > +} > + > +int ff_vvc_intra_subpartitions_mode_flag(VVCLocalContext *lc) > +{ > + return GET_CABAC(INTRA_SUBPARTITIONS_MODE_FLAG); > +} > + > +enum IspType ff_vvc_isp_split_type(VVCLocalContext *lc, const int intra_subpartitions_mode_flag) > +{ > + if (!intra_subpartitions_mode_flag) > + return ISP_NO_SPLIT; > + return 1 + GET_CABAC(INTRA_SUBPARTITIONS_SPLIT_FLAG); > +} > + > +int ff_vvc_intra_luma_mpm_flag(VVCLocalContext *lc) > +{ > + return GET_CABAC(INTRA_LUMA_MPM_FLAG); > +} > + > +int ff_vvc_intra_luma_not_planar_flag(VVCLocalContext *lc, const int intra_subpartitions_mode_flag) > +{ > + return GET_CABAC(INTRA_LUMA_NOT_PLANAR_FLAG + !intra_subpartitions_mode_flag); > +} > + > +int ff_vvc_intra_luma_mpm_idx(VVCLocalContext *lc) > +{ > + int i; > + for (i = 0; i < 4 && get_cabac_bypass(&lc->ep->cc); i++) > + /* nothing */; > + return i; > +} > + > +int ff_vvc_intra_luma_mpm_remainder(VVCLocalContext *lc) > +{ > + return truncated_binary_decode(lc, 60); > +} > + > +int ff_vvc_cclm_mode_flag(VVCLocalContext *lc) > +{ > + return GET_CABAC(CCLM_MODE_FLAG); > +} > + > +int ff_vvc_cclm_mode_idx(VVCLocalContext *lc) > +{ > + if (!GET_CABAC(CCLM_MODE_IDX)) > + return 0; > + return get_cabac_bypass(&lc->ep->cc) + 1; > +} > + > +int ff_vvc_intra_chroma_pred_mode(VVCLocalContext *lc) > +{ > + if (!GET_CABAC(INTRA_CHROMA_PRED_MODE)) > + return 4; > + return (get_cabac_bypass(&lc->ep->cc) << 1) | get_cabac_bypass(&lc->ep->cc); > +} > + > +int ff_vvc_general_merge_flag(VVCLocalContext *lc) > +{ > + return GET_CABAC(GENERAL_MERGE_FLAG); > +} > + > +static int get_inter_flag_inc(VVCLocalContext *lc, const int x0, const int y0) > +{ > + uint8_t left_merge = 0, top_merge = 0; > + uint8_t left_affine = 0, top_affine = 0; > + const VVCFrameContext *fc = lc->fc; > + > + get_left_top(lc, &left_merge, &top_merge, x0, y0, fc->tab.msf, fc->tab.msf); > + get_left_top(lc, &left_affine, &top_affine, x0, y0, fc->tab.iaf, fc->tab.iaf); > + return (left_merge || left_affine) + (top_merge + top_affine); > +} > + > +int ff_vvc_merge_subblock_flag(VVCLocalContext *lc) > +{ > + const int inc = get_inter_flag_inc(lc, lc->cu->x0, lc->cu->y0); > + return GET_CABAC(MERGE_SUBBLOCK_FLAG + inc); > +} > + > +int ff_vvc_merge_subblock_idx(VVCLocalContext *lc, const int max_num_subblock_merge_cand) > +{ > + int i; > + if (!GET_CABAC(MERGE_SUBBLOCK_IDX)) > + return 0; > + for (i = 1; i < max_num_subblock_merge_cand - 1 && get_cabac_bypass(&lc->ep->cc); i++) > + /* nothing */; > + return i; > +} > + > +int ff_vvc_regular_merge_flag(VVCLocalContext *lc, const int cu_skip_flag) > +{ > + int inc = !cu_skip_flag; > + return GET_CABAC(REGULAR_MERGE_FLAG + inc); > +} > + > +int ff_vvc_mmvd_merge_flag(VVCLocalContext *lc) > +{ > + return GET_CABAC(MMVD_MERGE_FLAG); > +} > + > +int ff_vvc_mmvd_cand_flag(VVCLocalContext *lc) > +{ > + return GET_CABAC(MMVD_CAND_FLAG); > +} > + > +static int mmvd_distance_idx_decode(VVCLocalContext *lc) > +{ > + int i; > + if (!GET_CABAC(MMVD_DISTANCE_IDX)) > + return 0; > + for (i = 1; i < 7 && get_cabac_bypass(&lc->ep->cc); i++) > + /* nothing */; > + return i; > +} > + > +static int mmvd_direction_idx_decode(VVCLocalContext *lc) > +{ > + return (get_cabac_bypass(&lc->ep->cc) << 1) | get_cabac_bypass(&lc->ep->cc); > +} > + > +void ff_vvc_mmvd_offset_coding(VVCLocalContext *lc, Mv *mmvd_offset, const int ph_mmvd_fullpel_only_flag) > +{ > + const int shift = ph_mmvd_fullpel_only_flag ? 4 : 2; > + const int mmvd_distance = 1 << (mmvd_distance_idx_decode(lc) + shift); > + const int mmvd_direction_idx = mmvd_direction_idx_decode(lc); > + const int mmvd_signs[][2] = { {1, 0}, {-1, 0}, {0, 1}, {0, -1} }; > + mmvd_offset->x = mmvd_distance * mmvd_signs[mmvd_direction_idx][0]; > + mmvd_offset->y = mmvd_distance * mmvd_signs[mmvd_direction_idx][1]; > +} > + > +static PredMode get_luma_pred_mode(VVCLocalContext *lc) > +{ > + const VVCFrameContext *fc = lc->fc; > + const CodingUnit *cu = lc->cu; > + PredMode pred_mode; > + > + if (cu->tree_type != DUAL_TREE_CHROMA) { > + pred_mode = cu->pred_mode; > + } else { > + const int x_cb = cu->x0 >> fc->ps.sps->min_cb_log2_size_y; > + const int y_cb = cu->y0 >> fc->ps.sps->min_cb_log2_size_y; > + const int min_cb_width = fc->ps.pps->min_cb_width; > + pred_mode = SAMPLE_CTB(fc->tab.cpm[0], x_cb, y_cb); > + } > + return pred_mode; > +} > + > +int ff_vvc_merge_idx(VVCLocalContext *lc) > +{ > + const VVCSPS *sps = lc->fc->ps.sps; > + const int is_ibc = get_luma_pred_mode(lc) == MODE_IBC; > + const int c_max = (is_ibc ? sps->max_num_ibc_merge_cand : sps->max_num_merge_cand) - 1; > + int i; > + > + if (!GET_CABAC(MERGE_IDX)) > + return 0; > + > + for (i = 1; i < c_max && get_cabac_bypass(&lc->ep->cc); i++) > + /* nothing */; > + return i; > +} > + > +int ff_vvc_merge_gpm_partition_idx(VVCLocalContext *lc) > +{ > + int i = 0; > + > + for (int j = 0; j < 6; j++) > + i = (i << 1) | get_cabac_bypass(&lc->ep->cc); > + > + return i; > +} > + > +int ff_vvc_merge_gpm_idx(VVCLocalContext *lc, const int idx) > +{ > + const int c_max = lc->fc->ps.sps->max_num_gpm_merge_cand - idx - 1; > + int i; > + > + if (!GET_CABAC(MERGE_IDX)) > + return 0; > + > + for (i = 1; i < c_max && get_cabac_bypass(&lc->ep->cc); i++) > + /* nothing */; > + > + return i; > +} > + > +int ff_vvc_ciip_flag(VVCLocalContext *lc) > +{ > + return GET_CABAC(CIIP_FLAG); > +} > + > +PredFlag ff_vvc_pred_flag(VVCLocalContext *lc, const int is_b) > +{ > + const int w = lc->cu->cb_width; > + const int h = lc->cu->cb_height; > + if (!is_b) > + return PF_L0; > + if (w + h > 12) { > + const int log2 = av_log2(w) + av_log2(h); > + const int inc = 7 - ((1 + log2)>>1); > + if (GET_CABAC(INTER_PRED_IDC + inc)) > + return PF_BI; > + } > + return PF_L0 + GET_CABAC(INTER_PRED_IDC + 5); > +} > + > +int ff_vvc_inter_affine_flag(VVCLocalContext *lc) > +{ > + const int inc = get_inter_flag_inc(lc, lc->cu->x0, lc->cu->y0); > + return GET_CABAC(INTER_AFFINE_FLAG + inc); > +} > + > +int ff_vvc_cu_affine_type_flag(VVCLocalContext *lc) > +{ > + return GET_CABAC(CU_AFFINE_TYPE_FLAG); > +} > + > +int ff_vvc_sym_mvd_flag(VVCLocalContext *lc) > +{ > + return GET_CABAC(SYM_MVD_FLAG); > +} > + > +int ff_vvc_ref_idx_lx(VVCLocalContext *lc, const uint8_t nb_refs) > +{ > + const int c_max = nb_refs - 1; > + const int max_ctx = FFMIN(c_max, 2); > + int i = 0; > + > + while (i < max_ctx && GET_CABAC(REF_IDX_LX + i)) > + i++; > + if (i == 2) { > + while (i < c_max && get_cabac_bypass(&lc->ep->cc)) > + i++; > + } > + return i; > +} > + > +int ff_vvc_abs_mvd_greater0_flag(VVCLocalContext *lc) > +{ > + return GET_CABAC(ABS_MVD_GREATER0_FLAG); > +} > + > +int ff_vvc_abs_mvd_greater1_flag(VVCLocalContext *lc) > +{ > + return GET_CABAC(ABS_MVD_GREATER1_FLAG); > +} > + > +int ff_vvc_abs_mvd_minus2(VVCLocalContext *lc) > +{ > + return limited_kth_order_egk_decode(&lc->ep->cc, 1, 15, 17); > +} > + > +int ff_vvc_mvd_sign_flag(VVCLocalContext *lc) > +{ > + return get_cabac_bypass(&lc->ep->cc); > +} > + > +int ff_vvc_mvp_lx_flag(VVCLocalContext *lc) > +{ > + return GET_CABAC(MVP_LX_FLAG); > +} > + > +static int amvr_flag(VVCLocalContext *lc, const int inter_affine_flag) > +{ > + return GET_CABAC(AMVR_FLAG + inter_affine_flag); > +} > + > +static int amvr_precision_idx(VVCLocalContext *lc, const int inc, const int c_max) > +{ > + int i = 0; > + if (!GET_CABAC(AMVR_PRECISION_IDX + inc)) > + return 0; > + i++; > + if (i < c_max && GET_CABAC(AMVR_PRECISION_IDX + 1)) > + i++; > + return i; > +} > + > +int ff_vvc_amvr_shift(VVCLocalContext *lc, const int inter_affine_flag, > + const PredMode pred_mode, const int has_amvr_flag) > +{ > + int amvr_shift = 2; > + if (has_amvr_flag) { > + if (amvr_flag(lc, inter_affine_flag)) { > + int idx; > + if (inter_affine_flag) { > + idx = amvr_precision_idx(lc, 2, 1); > + amvr_shift = idx * 4; > + } else if (pred_mode == MODE_IBC) { > + idx = amvr_precision_idx(lc, 1, 1); > + amvr_shift = 4 + idx * 2; > + } else { > + static const int shifts[] = {3, 4, 6}; > + idx = amvr_precision_idx(lc, 0, 2); > + amvr_shift = shifts[idx]; > + } > + } > + } > + return amvr_shift; > +} > + > +int ff_vvc_bcw_idx(VVCLocalContext *lc, const int no_backward_pred_flag) > +{ > + const int c_max = no_backward_pred_flag ? 4 : 2; > + int i = 1; > + if (!GET_CABAC(BCW_IDX)) > + return 0; > + while (i < c_max && get_cabac_bypass(&lc->ep->cc)) > + i++; > + return i; > +} > + > +int ff_vvc_tu_cb_coded_flag(VVCLocalContext *lc) > +{ > + return GET_CABAC(TU_CB_CODED_FLAG + lc->cu->bdpcm_flag[1]); > +} > + > +int ff_vvc_tu_cr_coded_flag(VVCLocalContext *lc, int tu_cb_coded_flag) > +{ > + return GET_CABAC(TU_CR_CODED_FLAG + (lc->cu->bdpcm_flag[1] ? 2 : tu_cb_coded_flag)); > +} > + > +int ff_vvc_tu_y_coded_flag(VVCLocalContext *lc) > +{ > + const CodingUnit *cu = lc->cu; > + int inc; > + if (cu->bdpcm_flag[0]) > + inc = 1; > + else if (cu->isp_split_type == ISP_NO_SPLIT) > + inc = 0; > + else > + inc = 2 + lc->parse.prev_tu_cbf_y; > + lc->parse.prev_tu_cbf_y = GET_CABAC(TU_Y_CODED_FLAG + inc); > + return lc->parse.prev_tu_cbf_y; > +} > + > +int ff_vvc_cu_qp_delta_abs(VVCLocalContext *lc) > +{ > + int v, i, k; > + if (!GET_CABAC(CU_QP_DELTA_ABS)) > + return 0; > + > + // prefixVal > + for (v = 1; v < 5 && GET_CABAC(CU_QP_DELTA_ABS + 1); v++) > + /* nothing */; > + if (v < 5) > + return v; > + > + // 9.3.3.5 k-th order Exp-Golomb binarization process > + // suffixVal > + > + // CuQpDeltaVal shall in the range of −( 32 + QpBdOffset / 2 ) to +( 31 + QpBdOffset / 2 ) > + // so k = 6 should enough > + for (k = 0; k < 6 && get_cabac_bypass(&lc->ep->cc); k++) > + /* nothing */; > + i = (1 << k) - 1; > + v = 0; > + while (k--) > + v = (v << 1) + get_cabac_bypass(&lc->ep->cc); > + v += i; > + > + return v + 5; > +} > + > +int ff_vvc_cu_qp_delta_sign_flag(VVCLocalContext *lc) > +{ > + return get_cabac_bypass(&lc->ep->cc); > +} > + > +int ff_vvc_cu_chroma_qp_offset_flag(VVCLocalContext *lc) > +{ > + return GET_CABAC(CU_CHROMA_QP_OFFSET_FLAG); > +} > + > +int ff_vvc_cu_chroma_qp_offset_idx(VVCLocalContext *lc) > +{ > + const int c_max = lc->fc->ps.pps->r->pps_chroma_qp_offset_list_len_minus1; > + int i; > + for (i = 0; i < c_max && GET_CABAC(CU_CHROMA_QP_OFFSET_IDX); i++) > + /* nothing */; > + return i; > +} > + > +static av_always_inline int last_significant_coeff_xy_prefix(VVCLocalContext *lc, > + const int log2_tb_size, const int log2_zo_tb_size, const int c_idx, const int ctx) > +{ > + int i = 0; > + int max = (log2_zo_tb_size << 1) - 1; > + int ctx_offset, ctx_shift; > + if (!log2_tb_size) > + return 0; > + if (!c_idx) { > + const int offset_y[] = {0, 0, 3, 6, 10, 15}; > + ctx_offset = offset_y[log2_tb_size - 1]; > + ctx_shift = (log2_tb_size + 1) >> 2; > + } else { > + const int shifts[] = {0, 0, 0, 1, 2, 2, 2}; > + ctx_offset = 20; > + ctx_shift = shifts[log2_tb_size]; > + } > + while (i < max && GET_CABAC(ctx + (i >> ctx_shift) + ctx_offset)) > + i++; > + return i; > +} > + > +static av_always_inline int last_significant_coeff_x_prefix_decode(VVCLocalContext *lc, > + const int log2_tb_width, const int log2_zo_tb_width, const int c_idx) > +{ > + return last_significant_coeff_xy_prefix(lc, log2_tb_width, log2_zo_tb_width, c_idx, LAST_SIG_COEFF_X_PREFIX); > +} > + > +static av_always_inline int last_significant_coeff_y_prefix_decode(VVCLocalContext *lc, > + const int log2_tb_height, const int log2_zo_tb_height, const int c_idx) > +{ > + return last_significant_coeff_xy_prefix(lc, log2_tb_height, log2_zo_tb_height, c_idx, LAST_SIG_COEFF_Y_PREFIX); > +} > + > +static av_always_inline int last_sig_coeff_suffix_decode(VVCLocalContext *lc, > + const int last_significant_coeff_y_prefix) > +{ > + const int length = (last_significant_coeff_y_prefix >> 1) - 1; > + int value = get_cabac_bypass(&lc->ep->cc); > + > + for (int i = 1; i < length; i++) > + value = (value << 1) | get_cabac_bypass(&lc->ep->cc); > + return value; > +} > + > +int ff_vvc_tu_joint_cbcr_residual_flag(VVCLocalContext *lc, const int tu_cb_coded_flag, const int tu_cr_coded_flag) > +{ > + return GET_CABAC(TU_JOINT_CBCR_RESIDUAL_FLAG + 2 * tu_cb_coded_flag + tu_cr_coded_flag - 1); > +} > + > +int ff_vvc_transform_skip_flag(VVCLocalContext *lc, const int inc) > +{ > + return GET_CABAC(TRANSFORM_SKIP_FLAG + inc); > +} > + > +//9.3.4.2.7 Derivation process for the variables locNumSig, locSumAbsPass1 > +static int get_local_sum(const int *level, const int w, const int h, > + const int xc, const int yc, const int hist_value) > +{ > + int loc_sum = 3 * hist_value; > + level += w * yc + xc; > + if (xc < w - 1) { > + loc_sum += level[1]; > + if (xc < w - 2) > + loc_sum += level[2] - hist_value; > + if (yc < h - 1) > + loc_sum += level[w + 1] - hist_value; > + } > + if (yc < h - 1) { > + loc_sum += level[w]; > + if (yc < h - 2) > + loc_sum += level[w << 1] - hist_value; > + } > + return loc_sum; > +} > + > +//9.3.4.2.7 Derivation process for the variables locNumSig, locSumAbsPass1 > +static int get_local_sum_ts(const int *level, const int w, const int h, const int xc, const int yc) > +{ > + int loc_sum = 0; > + level += w * yc + xc; > + if (xc > 0) > + loc_sum += level[-1]; > + if (yc > 0) > + loc_sum += level[-w]; > + return loc_sum; > +} > + > +static int get_gtx_flag_inc(const ResidualCoding* rc, const int xc, const int yc, const int last) > +{ > + const TransformBlock *tb = rc->tb; > + int inc; > + if (last) { > + const int incs[] = {0, 21, 21}; > + inc = incs[tb->c_idx]; > + } else { > + const int d = xc + yc; > + const int local_sum_sig = get_local_sum(rc->sig_coeff_flag, > + tb->tb_width,tb->tb_height, xc, yc, rc->hist_value); > + const int loc_sum_abs_pass1 = get_local_sum(rc->abs_level_pass1, > + tb->tb_width, tb->tb_height, xc, yc, rc->hist_value); > + const int offset = FFMIN(loc_sum_abs_pass1 - local_sum_sig, 4); > + > + if (!tb->c_idx) > + inc = 1 + offset + (!d ? 15 : (d < 3 ? 10 : (d < 10 ? 5 : 0))); > + else > + inc = 22 + offset + (!d ? 5 : 0); > + } > + return inc; > +} > + > +static int abs_level_gtx_flag_decode(VVCLocalContext *lc, const int inc) > +{ > + return GET_CABAC(ABS_LEVEL_GTX_FLAG + inc); > +} > + > +static int par_level_flag_decode(VVCLocalContext *lc, const int inc) > +{ > + return GET_CABAC(PAR_LEVEL_FLAG + inc); > +} > + > +static int par_level_flag_ts_decode(VVCLocalContext *lc) > +{ > + const int inc = 32; > + return GET_CABAC(PAR_LEVEL_FLAG + inc); > +} > This is equal to par_level_flag_decode with a fixed argument. Just macro it. > + > +static int sb_coded_flag_decode(VVCLocalContext *lc, const uint8_t *sb_coded_flag, > + const ResidualCoding *rc, const int xs, const int ys) > +{ > + const H266RawSliceHeader *rsh = lc->sc->sh.r; > + const TransformBlock *tb = rc->tb; > + const int w = rc->width_in_sbs; > + const int h = rc->height_in_sbs; > + int inc; > + > + if (tb->ts && !rsh->sh_ts_residual_coding_disabled_flag) { > + const int left = xs > 0 ? sb_coded_flag[-1] : 0; > + const int above = ys > 0 ? sb_coded_flag[-w] : 0; > + inc = left + above + 4; > + } else { > + const int right = (xs < w - 1) ? sb_coded_flag[1] : 0; > + const int bottom = (ys < h - 1) ? sb_coded_flag[w] : 0; > + inc = (right | bottom) + (tb->c_idx ? 2 : 0); > + } > + return GET_CABAC(SB_CODED_FLAG + inc); > +} > + > +static int sig_coeff_flag_decode(VVCLocalContext *lc, const ResidualCoding* rc, const int xc, const int yc) > +{ > + const H266RawSliceHeader *rsh = lc->sc->sh.r; > + const TransformBlock *tb = rc->tb; > + int inc; > + > + if (tb->ts && !rsh->sh_ts_residual_coding_disabled_flag) { > + const int local_num_sig = get_local_sum_ts(rc->sig_coeff_flag, tb->tb_width, tb->tb_height, xc, yc); > + inc = 60 + local_num_sig; > + } else { > + const int d = xc + yc; > + const int loc_sum_abs_pass1 = get_local_sum(rc->abs_level_pass1, > + tb->tb_width, tb->tb_height, xc, yc, 0); > + > + if (!tb->c_idx) { > + inc = 12 * FFMAX(0, rc->qstate - 1) + FFMIN((loc_sum_abs_pass1 + 1) >> 1, 3) + ((d < 2) ? 8 : (d < 5 ? 4 : 0)); > + } else { > + inc = 36 + 8 * FFMAX(0, rc->qstate - 1) + FFMIN((loc_sum_abs_pass1 + 1) >> 1, 3) + (d < 2 ? 4 : 0); > + } > + } > + return GET_CABAC(SIG_COEFF_FLAG + inc); > +} > + > +static int abs_get_rice_param(VVCLocalContext *lc, const ResidualCoding* rc, > + const int xc, const int yc, const int base_level) > +{ > + const VVCSPS *sps = lc->fc->ps.sps; > + const TransformBlock* tb = rc->tb; > + const int rice_params[] = { > + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, > + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, > + }; > + int loc_sum_abs; > + int shift_val; > + > + loc_sum_abs = get_local_sum(rc->abs_level, tb->tb_width, tb->tb_height, xc, > + yc, rc->hist_value); > + > + if (!sps->r->sps_rrc_rice_extension_flag) { > + shift_val = 0; > + } else { > + shift_val = (av_log2(FFMAX(FFMIN(loc_sum_abs, 2048), 8)) - 3) & ~1; > + } > + > + loc_sum_abs = av_clip_uintp2((loc_sum_abs >> shift_val) - base_level * 5, 5); > + > + return rice_params[loc_sum_abs] + shift_val; > +} > + > +static int abs_decode(VVCLocalContext *lc, const int c_rice_param) > +{ > + const VVCSPS *sps = lc->fc->ps.sps; > + const int MAX_BIN = 6; > + int prefix = 0; > + int suffix = 0; > + > + while (prefix < MAX_BIN && get_cabac_bypass(&lc->ep->cc)) > + prefix++; > + if (prefix < MAX_BIN) { > + for (int i = 0; i < c_rice_param; i++) { > + suffix = (suffix << 1) | get_cabac_bypass(&lc->ep->cc); > + } > + } else { > + suffix = limited_kth_order_egk_decode(&lc->ep->cc, > + c_rice_param + 1, > + 26 - sps->log2_transform_range, > + sps->log2_transform_range); > + } > + return suffix + (prefix << c_rice_param); > +} > + > +static int abs_remainder_decode(VVCLocalContext *lc, const ResidualCoding* rc, const int xc, const int yc) > +{ > + const VVCSPS *sps = lc->fc->ps.sps; > + const H266RawSliceHeader *rsh = lc->sc->sh.r; > + const int base_level[][2][2] = { > + { {4, 4}, {4, 4} }, > + { {3, 2}, {2, 1} } > + }; > + const int c_rice_param = abs_get_rice_param(lc, rc, xc, yc, > + base_level[sps->r->sps_rrc_rice_extension_flag][sps->bit_depth > 12][IS_I(rsh)]); > + const int rem = abs_decode(lc, c_rice_param); > + > + return rem; > +} > + > +static int abs_remainder_ts_decode(VVCLocalContext *lc, const ResidualCoding* rc, const int xc, const int yc) > +{ > + const H266RawSliceHeader *rsh = lc->sc->sh.r; > + const int c_rice_param = rsh->sh_ts_residual_coding_rice_idx_minus1 + 1; > + const int rem = abs_decode(lc, c_rice_param); > + > + return rem; > +} > + > +static int coeff_sign_flag_decode(VVCLocalContext *lc) > +{ > + return get_cabac_bypass(&lc->ep->cc); > +} > + > +//9.3.4.2.10 Derivation process of ctxInc for the syntax element coeff_sign_flag for transform skip mode > +static int coeff_sign_flag_ts_decode(VVCLocalContext *lc, const CodingUnit *cu, const ResidualCoding *rc, const int xc, const int yc) > +{ > + const TransformBlock *tb = rc->tb; > + const int w = tb->tb_width; > + const int *level = rc->coeff_sign_level + yc * w + xc; > + const int left_sign = xc ? level[-1] : 0; > + const int above_sign = yc ? level[-w] : 0; > + const int bdpcm_flag = cu->bdpcm_flag[tb->c_idx]; > + int inc; > + > + if (left_sign == -above_sign) > + inc = bdpcm_flag ? 3 : 0; > + else if (left_sign >= 0 && above_sign >= 0) > + inc = bdpcm_flag ? 4 : 1; > + else > + inc = bdpcm_flag ? 5 : 2; > + return GET_CABAC(COEFF_SIGN_FLAG + inc); > +} > + > +static int abs_level_gt1_flag_ts_decode(VVCLocalContext *lc, const CodingUnit *cu, const ResidualCoding *rc, const int xc, const int yc) > +{ > + const TransformBlock *tb = rc->tb; > + const int *sig_coeff_flag = rc->sig_coeff_flag + yc * tb->tb_width + xc; > + int inc; > + > + if (cu->bdpcm_flag[tb->c_idx]) { > + inc = 67; > + } else { > + const int l = xc > 0 ? sig_coeff_flag[-1] : 0; > + const int a = yc > 0 ? sig_coeff_flag[-tb->tb_width] : 0; > + inc = 64 + a + l; > + } > + return GET_CABAC(ABS_LEVEL_GTX_FLAG + inc); > +} > + > +static int abs_level_gtx_flag_ts_decode(VVCLocalContext *lc, const int j) > +{ > + const int inc = 67 + j; > + return GET_CABAC(ABS_LEVEL_GTX_FLAG + inc); > +} > + > +static const uint8_t qstate_translate_table[][2] = { > + { 0, 2 }, { 2, 0 }, { 1, 3 }, { 3, 1 } > +}; > + > +static int dec_abs_level_decode(VVCLocalContext *lc, const ResidualCoding *rc, > + const int xc, const int yc, int *abs_level) > +{ > + const int c_rice_param = abs_get_rice_param(lc, rc, xc, yc, 0); > + const int dec_abs_level = abs_decode(lc, c_rice_param); > + const int zero_pos = (rc->qstate < 2 ? 1 : 2) << c_rice_param; > + > + *abs_level = 0; > + if (dec_abs_level != zero_pos) { > + *abs_level = dec_abs_level; > + if (dec_abs_level < zero_pos) > + *abs_level += 1; > + } > + return dec_abs_level; > +} > + > +static void ep_update_hist(EntryPoint *ep, ResidualCoding *rc, > + const int remainder, const int addin) > +{ > + int *stat = ep->stat_coeff + rc->tb->c_idx; > + if (rc->update_hist && remainder > 0) { > + *stat = (*stat + av_log2(remainder) + addin) >> 1; > + rc->update_hist = 0; > + } > +} > + > +static void init_residual_coding(const VVCLocalContext *lc, ResidualCoding *rc, > + const int log2_zo_tb_width, const int log2_zo_tb_height, > + TransformBlock *tb) > +{ > + const VVCSPS *sps = lc->fc->ps.sps; > + int log2_sb_w = (FFMIN(log2_zo_tb_width, log2_zo_tb_height ) < 2 ? 1 : 2 ); > + int log2_sb_h = log2_sb_w; > + > + if ( log2_zo_tb_width + log2_zo_tb_height > 3 ) { > + if ( log2_zo_tb_width < 2 ) { > + log2_sb_w = log2_zo_tb_width; > + log2_sb_h = 4 - log2_sb_w; > + } else if ( log2_zo_tb_height < 2 ) { > + log2_sb_h = log2_zo_tb_height; > + log2_sb_w = 4 - log2_sb_h; > + } > + } > + rc->log2_sb_w = log2_sb_w; > + rc->log2_sb_h = log2_sb_h; > + rc->num_sb_coeff = 1 << (log2_sb_w + log2_sb_h); > + rc->last_sub_block = ( 1 << ( log2_zo_tb_width + log2_zo_tb_height - (log2_sb_w + log2_sb_h))) - 1; > + rc->hist_value = sps->r->sps_persistent_rice_adaptation_enabled_flag ? (1 << lc->ep->stat_coeff[tb->c_idx]) : 0; > + rc->update_hist = sps->r->sps_persistent_rice_adaptation_enabled_flag ? 1 : 0; > + rc->rem_bins_pass1 = (( 1 << ( log2_zo_tb_width + log2_zo_tb_height)) * 7 ) >> 2; > + > + > + rc->sb_scan_x_off = ff_vvc_diag_scan_x[log2_zo_tb_width - log2_sb_w][log2_zo_tb_height - log2_sb_h]; > + rc->sb_scan_y_off = ff_vvc_diag_scan_y[log2_zo_tb_width - log2_sb_w][log2_zo_tb_height - log2_sb_h]; > + > + rc->scan_x_off = ff_vvc_diag_scan_x[log2_sb_w][log2_sb_h]; > + rc->scan_y_off = ff_vvc_diag_scan_y[log2_sb_w][log2_sb_h]; > + > + rc->infer_sb_cbf = 1; > + > + rc->width_in_sbs = (1 << (log2_zo_tb_width - log2_sb_w)); > + rc->height_in_sbs = (1 << (log2_zo_tb_height - log2_sb_h)); > + rc->nb_sbs = rc->width_in_sbs * rc->height_in_sbs; > + > + rc->last_scan_pos = rc->num_sb_coeff; > + rc->qstate = 0; > + > + rc->tb = tb; > +} > + > +static int residual_ts_coding_subblock(VVCLocalContext *lc, ResidualCoding* rc, const int i) > +{ > + const CodingUnit *cu = lc->cu; > + TransformBlock *tb = rc->tb; > + const int bdpcm_flag = cu->bdpcm_flag[tb->c_idx]; > + const int xs = rc->sb_scan_x_off[i]; > + const int ys = rc->sb_scan_y_off[i]; > + uint8_t *sb_coded_flag = rc->sb_coded_flag + ys * rc->width_in_sbs + xs; > + int infer_sb_sig_coeff_flag = 1; > + int last_scan_pos_pass1 = -1, last_scan_pos_pass2 = -1, n; > + int abs_level_gtx_flag[MAX_SUB_BLOCK_SIZE * MAX_SUB_BLOCK_SIZE]; > + int abs_level_pass2[MAX_SUB_BLOCK_SIZE * MAX_SUB_BLOCK_SIZE]; ///< AbsLevelPass2 > + > + if (i != rc->last_sub_block || !rc->infer_sb_cbf) > + *sb_coded_flag = sb_coded_flag_decode(lc, sb_coded_flag, rc, xs, ys); > + else > + *sb_coded_flag = 1; > + if (*sb_coded_flag && i < rc->last_sub_block) > + rc->infer_sb_cbf = 0; > + > + //first scan pass > + for (n = 0; n < rc->num_sb_coeff && rc->rem_bins_pass1 >= 4; n++) { > + const int xc = (xs << rc->log2_sb_w) + rc->scan_x_off[n]; > + const int yc = (ys << rc->log2_sb_h) + rc->scan_y_off[n]; > + const int off = yc * tb->tb_width + xc; > + int *sig_coeff_flag = rc->sig_coeff_flag + off; > + int *abs_level_pass1 = rc->abs_level_pass1 + off; > + int *coeff_sign_level = rc->coeff_sign_level + off; > + int par_level_flag = 0; > + > + abs_level_gtx_flag[n] = 0; > + last_scan_pos_pass1 = n; > + if (*sb_coded_flag && (n != rc->num_sb_coeff - 1 || !infer_sb_sig_coeff_flag)) { > + *sig_coeff_flag = sig_coeff_flag_decode(lc, rc, xc, yc); > + rc->rem_bins_pass1--; > + if (*sig_coeff_flag) > + infer_sb_sig_coeff_flag = 0; > + } else { > + *sig_coeff_flag = (n == rc->num_sb_coeff - 1) && infer_sb_sig_coeff_flag && *sb_coded_flag; > + } > + *coeff_sign_level = 0; > + if (*sig_coeff_flag) { > + *coeff_sign_level = 1 - 2 * coeff_sign_flag_ts_decode(lc, cu, rc, xc, yc); > + abs_level_gtx_flag[n] = abs_level_gt1_flag_ts_decode(lc, cu, rc, xc, yc); > + rc->rem_bins_pass1 -= 2; > + if (abs_level_gtx_flag[n]) { > + par_level_flag = par_level_flag_ts_decode(lc); > + rc->rem_bins_pass1--; > + } > + } > + *abs_level_pass1 = *sig_coeff_flag + par_level_flag + abs_level_gtx_flag[n]; > + } > + > + //greater than x scan pass > + for (n = 0; n < rc->num_sb_coeff && rc->rem_bins_pass1 >= 4; n++) { > + const int xc = (xs << rc->log2_sb_w) + rc->scan_x_off[n]; > + const int yc = (ys << rc->log2_sb_h) + rc->scan_y_off[n]; > + const int off = yc * tb->tb_width + xc; > + > + abs_level_pass2[n] = rc->abs_level_pass1[off]; > + for (int j = 1; j < 5 && abs_level_gtx_flag[n]; j++) { > + abs_level_gtx_flag[n] = abs_level_gtx_flag_ts_decode(lc, j); > + abs_level_pass2[n] += abs_level_gtx_flag[n] << 1; > + rc->rem_bins_pass1--; > + } > + last_scan_pos_pass2 = n; > + } > + > + /* remainder scan pass */ > + for (n = 0; n < rc->num_sb_coeff; n++) { > + const int xc = (xs << rc->log2_sb_w) + rc->scan_x_off[n]; > + const int yc = (ys << rc->log2_sb_h) + rc->scan_y_off[n]; > + const int off = yc * tb->tb_width + xc; > + const int *abs_level_pass1 = rc->abs_level_pass1 + off; > + int *abs_level = rc->abs_level + off; > + int *coeff_sign_level = rc->coeff_sign_level + off; > + int abs_remainder = 0; > + > + if ((n <= last_scan_pos_pass2 && abs_level_pass2[n] >= 10) || > + (n > last_scan_pos_pass2 && n <= last_scan_pos_pass1 && > + *abs_level_pass1 >= 2) || > + (n > last_scan_pos_pass1 && *sb_coded_flag)) > + abs_remainder = abs_remainder_ts_decode(lc, rc, xc, yc); > + if (n <= last_scan_pos_pass2) { > + *abs_level = abs_level_pass2[n] + 2 * abs_remainder; > + } else if (n <= last_scan_pos_pass1) { > + *abs_level = *abs_level_pass1 + 2 * abs_remainder; > + } else { > + *abs_level = abs_remainder; > + if (abs_remainder) { > + //n > lastScanPosPass1 > + *coeff_sign_level = 1 - 2 * coeff_sign_flag_decode(lc); > + } > + } > + if (!bdpcm_flag && n <= last_scan_pos_pass1) { > + const int left = xc > 0 ? abs_level[-1] : 0; > + const int above = yc > 0 ? abs_level[-tb->tb_width] : 0; > + const int pred = FFMAX(left, above); > + > + if (*abs_level == 1 && pred > 0) > + *abs_level = pred; > + else if (*abs_level > 0 && *abs_level <= pred) > + (*abs_level)--; > + } > + if (*abs_level) { > + tb->coeffs[off] = *coeff_sign_level * *abs_level; > + tb->max_scan_x = FFMAX(xc, tb->max_scan_x); > + tb->max_scan_y = FFMAX(yc, tb->max_scan_y); > + tb->min_scan_x = FFMIN(xc, tb->min_scan_x); > + tb->min_scan_y = FFMIN(yc, tb->min_scan_y); > + } else { > + tb->coeffs[off] = 0; > + } > + } > + > + return 0; > +} > + > +static int hls_residual_ts_coding(VVCLocalContext *lc, TransformBlock *tb) > +{ > + ResidualCoding rc; > + tb->min_scan_x = tb->min_scan_y = INT_MAX; > + init_residual_coding(lc, &rc, tb->log2_tb_width, tb->log2_tb_height, tb); > + for (int i = 0; i <= rc.last_sub_block; i++) { > + int ret = residual_ts_coding_subblock(lc, &rc, i); > + if (ret < 0) > + return ret; > + } > + > + return 0; > +} > + > +static inline int residual_coding_subblock(VVCLocalContext *lc, ResidualCoding *rc, const int i) > +{ > + const H266RawSliceHeader *rsh = lc->sc->sh.r; > + TransformBlock *tb = rc->tb; > + int first_sig_scan_pos_sb, last_sig_scan_pos_sb; > + int first_pos_mode0, first_pos_mode1; > + int infer_sb_dc_sig_coeff_flag = 0; > + int n, sig_hidden_flag, sum = 0; > + int abs_level_gt2_flag[MAX_SUB_BLOCK_SIZE * MAX_SUB_BLOCK_SIZE]; > + const int start_qstate_sb = rc->qstate; > + const int xs = rc->sb_scan_x_off[i]; > + const int ys = rc->sb_scan_y_off[i]; > + uint8_t *sb_coded_flag = rc->sb_coded_flag + ys * rc->width_in_sbs + xs; > + > + > + av_assert0(rc->num_sb_coeff <= MAX_SUB_BLOCK_SIZE * MAX_SUB_BLOCK_SIZE); > + if (i < rc->last_sub_block && i > 0) { > + *sb_coded_flag = sb_coded_flag_decode(lc, sb_coded_flag, rc, xs, ys); > + infer_sb_dc_sig_coeff_flag = 1; > + } else { > + *sb_coded_flag = 1; > + } > + if (*sb_coded_flag && (xs > 3 || ys > 3) && !tb->c_idx) > + lc->parse.mts_zero_out_sig_coeff_flag = 0; > + > + if (!*sb_coded_flag) > + return 0; > + > + first_sig_scan_pos_sb = rc->num_sb_coeff; > + last_sig_scan_pos_sb = -1; > + first_pos_mode0 = (i == rc->last_sub_block ? rc->last_scan_pos : rc->num_sb_coeff -1); > + first_pos_mode1 = first_pos_mode0; > + for (n = first_pos_mode0; n >= 0 && rc->rem_bins_pass1 >= 4; n--) { > + const int xc = (xs << rc->log2_sb_w) + rc->scan_x_off[n]; > + const int yc = (ys << rc->log2_sb_h) + rc->scan_y_off[n]; > + const int last = (xc == rc->last_significant_coeff_x && yc == rc->last_significant_coeff_y); > + int *abs_level_pass1 = rc->abs_level_pass1 + yc * tb->tb_width + xc; > + int *sig_coeff_flag = rc->sig_coeff_flag + yc * tb->tb_width + xc; > + > + if ((n > 0 || !infer_sb_dc_sig_coeff_flag ) && !last) { > + *sig_coeff_flag = sig_coeff_flag_decode(lc, rc, xc, yc); > + rc->rem_bins_pass1--; > + if (*sig_coeff_flag) > + infer_sb_dc_sig_coeff_flag = 0; > + } else { > + *sig_coeff_flag = last || (!rc->scan_x_off[n] && !rc ->scan_y_off[n] && > + infer_sb_dc_sig_coeff_flag); > + } > + *abs_level_pass1 = 0; > + if (*sig_coeff_flag) { > + int abs_level_gt1_flag, par_level_flag = 0; > + const int inc = get_gtx_flag_inc(rc, xc, yc, last); > + abs_level_gt1_flag = abs_level_gtx_flag_decode(lc, inc); > + rc->rem_bins_pass1--; > + if (abs_level_gt1_flag) { > + par_level_flag = par_level_flag_decode(lc, inc); > + abs_level_gt2_flag[n] = abs_level_gtx_flag_decode(lc, inc + 32); > + rc->rem_bins_pass1 -= 2; > + } else { > + abs_level_gt2_flag[n] = 0; > + } > + if (last_sig_scan_pos_sb == -1) > + last_sig_scan_pos_sb = n; > + first_sig_scan_pos_sb = n; > + > + *abs_level_pass1 = > + 1 + par_level_flag + abs_level_gt1_flag + (abs_level_gt2_flag[n] << 1); > + } else { > + abs_level_gt2_flag[n] = 0; > + } > + > + if (rsh->sh_dep_quant_used_flag) > + rc->qstate = qstate_translate_table[rc->qstate][*abs_level_pass1 & 1]; > + > + first_pos_mode1 = n - 1; > + } > + for (n = first_pos_mode0; n > first_pos_mode1; n--) { > + const int xc = (xs << rc->log2_sb_w) + rc->scan_x_off[n]; > + const int yc = (ys << rc->log2_sb_h) + rc->scan_y_off[n]; > + const int *abs_level_pass1 = rc->abs_level_pass1 + yc * tb->tb_width + xc; > + int *abs_level = rc->abs_level + yc * tb->tb_width + xc; > + > + *abs_level = *abs_level_pass1; > + if (abs_level_gt2_flag[n]) { > + const int abs_remainder = abs_remainder_decode(lc, rc, xc, yc); > + ep_update_hist(lc->ep, rc, abs_remainder, 2); > + *abs_level += 2 * abs_remainder; > + } > + } > + for (n = first_pos_mode1; n >= 0; n--) { > + const int xc = (xs << rc->log2_sb_w) + rc->scan_x_off[n]; > + const int yc = (ys << rc->log2_sb_h) + rc->scan_y_off[n]; > + int *abs_level = rc->abs_level + yc * tb->tb_width + xc; > + > + if (*sb_coded_flag) { > + const int dec_abs_level = dec_abs_level_decode(lc, rc, xc, yc, abs_level); > + ep_update_hist(lc->ep, rc, dec_abs_level, 0); > + } > + if (*abs_level > 0) { > + if (last_sig_scan_pos_sb == -1) > + last_sig_scan_pos_sb = n; > + first_sig_scan_pos_sb = n; > + } > + if (rsh->sh_dep_quant_used_flag) > + rc->qstate = qstate_translate_table[rc->qstate][*abs_level & 1]; > + } > + sig_hidden_flag = rsh->sh_sign_data_hiding_used_flag && > + (last_sig_scan_pos_sb - first_sig_scan_pos_sb > 3 ? 1 : 0); > + > + if (rsh->sh_dep_quant_used_flag) > + rc->qstate = start_qstate_sb; > + n = (i == rc->last_sub_block ? rc->last_scan_pos : rc->num_sb_coeff -1); > + for (/* nothing */; n >= 0; n--) { > + int trans_coeff_level; > + const int xc = (xs << rc->log2_sb_w) + rc->scan_x_off[n]; > + const int yc = (ys << rc->log2_sb_h) + rc->scan_y_off[n]; > + const int off = yc * tb->tb_width + xc; > + const int *abs_level = rc->abs_level + off; > + > + if (*abs_level > 0) { > + int sign = 1; > + if (!sig_hidden_flag || (n != first_sig_scan_pos_sb)) > + sign = 1 - 2 * coeff_sign_flag_decode(lc); > + if (rsh->sh_dep_quant_used_flag) { > + trans_coeff_level = (2 * *abs_level - (rc->qstate > 1)) * sign; > + } else { > + trans_coeff_level = *abs_level * sign; > + if (sig_hidden_flag) { > + sum += *abs_level; > + if (n == first_sig_scan_pos_sb && (sum % 2)) > + trans_coeff_level = -trans_coeff_level; > + } > + } > + tb->coeffs[off] = trans_coeff_level; > + tb->max_scan_x = FFMAX(xc, tb->max_scan_x); > + tb->max_scan_y = FFMAX(yc, tb->max_scan_y); > + } > + if (rsh->sh_dep_quant_used_flag) > + rc->qstate = qstate_translate_table[rc->qstate][*abs_level & 1]; > + } > + > + return 0; > +} > + > +static void derive_last_scan_pos(ResidualCoding *rc) > +{ > + int xc, yc, xs, ys; > + do { > + if (!rc->last_scan_pos) { > + rc->last_scan_pos = rc->num_sb_coeff; > + rc->last_sub_block--; > + } > + rc->last_scan_pos--; > + xs = rc->sb_scan_x_off[rc->last_sub_block]; > + ys = rc->sb_scan_y_off[rc->last_sub_block]; > + xc = (xs << rc->log2_sb_w) + rc->scan_x_off[rc->last_scan_pos]; > + yc = (ys << rc->log2_sb_h) + rc->scan_y_off[rc->last_scan_pos]; > + } while ((xc != rc->last_significant_coeff_x) || (yc != rc->last_significant_coeff_y)); > +} > + > +static void last_significant_coeff_x_y_decode(ResidualCoding *rc, VVCLocalContext *lc, > + const int log2_zo_tb_width, const int log2_zo_tb_height) > +{ > + const H266RawSliceHeader *rsh = lc->sc->sh.r; > + const TransformBlock *tb = rc->tb; > + int last_significant_coeff_x, last_significant_coeff_y; > + > + last_significant_coeff_x = last_significant_coeff_x_prefix_decode(lc, > + tb->log2_tb_width, log2_zo_tb_width, tb->c_idx); > + > + last_significant_coeff_y = last_significant_coeff_y_prefix_decode(lc, > + tb->log2_tb_height, log2_zo_tb_height, tb->c_idx); > + > + if (last_significant_coeff_x > 3) { > + int suffix = last_sig_coeff_suffix_decode(lc, last_significant_coeff_x); > + last_significant_coeff_x = (1 << ((last_significant_coeff_x >> 1) - 1)) * > + (2 + (last_significant_coeff_x & 1)) + suffix; > + } > + if (last_significant_coeff_y > 3) { > + int suffix = last_sig_coeff_suffix_decode(lc, last_significant_coeff_y); > + last_significant_coeff_y = (1 << ((last_significant_coeff_y >> 1) - 1)) * > + (2 + (last_significant_coeff_y & 1)) + suffix; > + } > + if (rsh->sh_reverse_last_sig_coeff_flag) { > + last_significant_coeff_x = (1 << log2_zo_tb_width) - 1 - last_significant_coeff_x; > + last_significant_coeff_y = (1 << log2_zo_tb_height) - 1 - last_significant_coeff_y; > + } > + rc->last_significant_coeff_x = last_significant_coeff_x; > + rc->last_significant_coeff_y = last_significant_coeff_y; > +} > + > +static int hls_residual_coding(VVCLocalContext *lc, TransformBlock *tb) > +{ > + const VVCSPS *sps = lc->fc->ps.sps; > + const CodingUnit *cu = lc->cu; > + const int log2_tb_width = tb->log2_tb_width; > + const int log2_tb_height = tb->log2_tb_height; > + const int c_idx = tb->c_idx; > + int log2_zo_tb_width, log2_zo_tb_height; > + ResidualCoding rc; > + > + if (sps->r->sps_mts_enabled_flag && cu->sbt_flag && !c_idx && log2_tb_width == 5 && log2_tb_height < 6) > + log2_zo_tb_width = 4; > + else > + log2_zo_tb_width = FFMIN(log2_tb_width, 5 ); > + > + if (sps->r->sps_mts_enabled_flag && cu->sbt_flag && !c_idx && log2_tb_width < 6 && log2_tb_height == 5 ) > + log2_zo_tb_height = 4; > + else > + log2_zo_tb_height = FFMIN(log2_tb_height, 5); > + > + init_residual_coding(lc, &rc, log2_zo_tb_width, log2_zo_tb_height, tb); > + last_significant_coeff_x_y_decode(&rc, lc, log2_zo_tb_width, log2_zo_tb_height); > + derive_last_scan_pos(&rc); > + > + if (!rc.last_sub_block && log2_tb_width >= 2 && log2_tb_height >= 2 && !tb->ts && rc.last_scan_pos > 0) > + lc->parse.lfnst_dc_only = 0; > + if ((rc.last_sub_block > 0 && log2_tb_width >= 2 && log2_tb_height >= 2 ) || > + (rc.last_scan_pos > 7 && (log2_tb_width == 2 || log2_tb_width == 3 ) && > + log2_tb_width == log2_tb_height)) > + lc->parse.lfnst_zero_out_sig_coeff_flag = 0; > + if ((rc.last_sub_block > 0 || rc.last_scan_pos > 0 ) && !c_idx) > + lc->parse.mts_dc_only = 0; > + > + memset(tb->coeffs, 0, tb->tb_width * tb->tb_height * sizeof(*tb->coeffs)); > + memset(rc.abs_level, 0, tb->tb_width * tb->tb_height * sizeof(rc.abs_level[0])); > + memset(rc.sb_coded_flag, 0, rc.nb_sbs); > + memset(rc.abs_level_pass1, 0, tb->tb_width * tb->tb_height * sizeof(rc.abs_level_pass1[0])); > + memset(rc.sig_coeff_flag, 0, tb->tb_width * tb->tb_height * sizeof(rc.sig_coeff_flag[0])); > + > + for (int i = rc.last_sub_block; i >= 0; i--) { > + int ret = residual_coding_subblock(lc, &rc, i); > + if (ret < 0) > + return ret; > + } > + > + return 0; > +} > + > +int ff_vvc_residual_coding(VVCLocalContext *lc, TransformBlock *tb) > +{ > + const H266RawSliceHeader *rsh = lc->sc->sh.r; > + const int ts = !rsh->sh_ts_residual_coding_disabled_flag && tb->ts; > + > + return ts ? hls_residual_ts_coding(lc, tb) : hls_residual_coding(lc, tb); > +} > + > +int ff_vvc_cu_coded_flag(VVCLocalContext *lc) > +{ > + return GET_CABAC(CU_CODED_FLAG); > +} > + > +int ff_vvc_sbt_flag(VVCLocalContext *lc) > +{ > + const int w = lc->cu->cb_width; > + const int h = lc->cu->cb_height; > + const int inc = w * h <= 256; > + return GET_CABAC(CU_SBT_FLAG + inc); > +} > + > +int ff_vvc_sbt_quad_flag(VVCLocalContext *lc) > +{ > + return GET_CABAC(CU_SBT_QUAD_FLAG); > +} > + > +int ff_vvc_sbt_horizontal_flag(VVCLocalContext *lc) > +{ > + const int w = lc->cu->cb_width; > + const int h = lc->cu->cb_height; > + const int inc = (w == h) ? 0 : ((w < h) ? 1 : 2); > + return GET_CABAC(CU_SBT_HORIZONTAL_FLAG + inc); > +} > + > +int ff_vvc_sbt_pos_flag(VVCLocalContext *lc) > +{ > + return GET_CABAC(CU_SBT_POS_FLAG); > +} > + > +int ff_vvc_lfnst_idx(VVCLocalContext *lc, const int inc) > +{ > + if (!GET_CABAC(LFNST_IDX + inc)) > + return 0; > + if (!GET_CABAC(LFNST_IDX + 2)) > + return 1; > + return 2; > +} > + > +int ff_vvc_mts_idx(VVCLocalContext *lc) > +{ > + int i; > + for (i = 0; i < 4; i++) { > + if (!GET_CABAC(MTS_IDX + i)) > + return i; > + } > + return i; > +} > + > +int ff_vvc_end_of_slice_flag_decode(VVCLocalContext *lc) > +{ > + return get_cabac_terminate(&lc->ep->cc); > +} > + > +int ff_vvc_end_of_tile_one_bit(VVCLocalContext *lc) > +{ > + return get_cabac_terminate(&lc->ep->cc); > +} > + > +int ff_vvc_end_of_subset_one_bit(VVCLocalContext *lc) > +{ > + return get_cabac_terminate(&lc->ep->cc); > +} > diff --git a/libavcodec/vvc/vvc_cabac.h b/libavcodec/vvc/vvc_cabac.h > new file mode 100644 > index 0000000000..172ab272ff > --- /dev/null > +++ b/libavcodec/vvc/vvc_cabac.h > @@ -0,0 +1,126 @@ > +/* > + * VVC CABAC decoder > + * > + * Copyright (C) 2022 Nuo Mi > + * > + * This file is part of FFmpeg. > + * > + * FFmpeg is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Lesser General Public > + * License as published by the Free Software Foundation; either > + * version 2.1 of the License, or (at your option) any later version. > + * > + * FFmpeg is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * Lesser General Public License for more details. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with FFmpeg; if not, write to the Free Software > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA > + */ > + > +#ifndef AVCODEC_VVC_VVC_CABAC_H > +#define AVCODEC_VVC_VVC_CABAC_H > + > +#include "vvc_ctu.h" > + > +int ff_vvc_cabac_init(VVCLocalContext *lc, int ctu_idx, int rx, int ry); > + > +//sao > +int ff_vvc_sao_merge_flag_decode(VVCLocalContext *lc); > +int ff_vvc_sao_type_idx_decode(VVCLocalContext *lc); > +int ff_vvc_sao_band_position_decode(VVCLocalContext *lc); > +int ff_vvc_sao_offset_abs_decode(VVCLocalContext *lc); > +int ff_vvc_sao_offset_sign_decode(VVCLocalContext *lc); > +int ff_vvc_sao_eo_class_decode(VVCLocalContext *lc); > + > +//alf > +int ff_vvc_alf_ctb_flag(VVCLocalContext *lc, int rx, int ry, int c_idx); > +int ff_vvc_alf_use_aps_flag(VVCLocalContext *lc); > +int ff_vvc_alf_luma_prev_filter_idx(VVCLocalContext *lc); > +int ff_vvc_alf_luma_fixed_filter_idx(VVCLocalContext *lc); > +int ff_vvc_alf_ctb_filter_alt_idx(VVCLocalContext *lc, int c_idx, int num_chroma_filters); > +int ff_vvc_alf_ctb_cc_idc(VVCLocalContext *lc, int rx, int ry, int idx, int cc_filters_signalled); > + > +//coding_tree > +int ff_vvc_split_cu_flag(VVCLocalContext* lc, int x0, int y0, int cb_width, int cb_height, > + int ch_type, const VVCAllowedSplit *a); > +VVCSplitMode ff_vvc_split_mode(VVCLocalContext *lc, int x0, int y0, int cb_width, int cb_height, > + int cqt_depth, int mtt_depth, int ch_type, const VVCAllowedSplit *a); > +int ff_vvc_non_inter_flag(VVCLocalContext *lc, int x0, int y0, int ch_type); > + > +//coding unit > +int ff_vvc_pred_mode_flag(VVCLocalContext *lc, int is_chroma); > +int ff_vvc_pred_mode_plt_flag(VVCLocalContext *lc); > +int ff_vvc_intra_bdpcm_luma_flag(VVCLocalContext *lc); > +int ff_vvc_intra_bdpcm_luma_dir_flag(VVCLocalContext *lc); > +int ff_vvc_intra_bdpcm_chroma_flag(VVCLocalContext *lc); > +int ff_vvc_intra_bdpcm_chroma_dir_flag(VVCLocalContext *lc); > +int ff_vvc_cu_skip_flag(VVCLocalContext *lc, const uint8_t *cu_skip_flag); > +int ff_vvc_pred_mode_ibc_flag(VVCLocalContext *lc, int ch_type); > +int ff_vvc_cu_coded_flag(VVCLocalContext *lc); > +int ff_vvc_cu_qp_delta_abs(VVCLocalContext *lc); > +int ff_vvc_cu_qp_delta_sign_flag(VVCLocalContext *lc); > +int ff_vvc_sbt_flag(VVCLocalContext *lc); > +int ff_vvc_sbt_quad_flag(VVCLocalContext *lc); > +int ff_vvc_sbt_horizontal_flag(VVCLocalContext *lc); > +int ff_vvc_sbt_pos_flag(VVCLocalContext *lc); > + > +//intra > +int ff_vvc_intra_mip_flag(VVCLocalContext *lc, const uint8_t *intra_mip_flag); > +int ff_vvc_intra_mip_transposed_flag(VVCLocalContext *lc); > +int ff_vvc_intra_mip_mode(VVCLocalContext *lc); > +int ff_vvc_intra_luma_ref_idx(VVCLocalContext *lc); > +int ff_vvc_intra_subpartitions_mode_flag(VVCLocalContext *lc); > +enum IspType ff_vvc_isp_split_type(VVCLocalContext *lc, int intra_subpartitions_mode_flag); > +int ff_vvc_intra_luma_mpm_flag(VVCLocalContext *lc); > +int ff_vvc_intra_luma_not_planar_flag(VVCLocalContext *lc, int intra_subpartitions_mode_flag); > +int ff_vvc_intra_luma_mpm_idx(VVCLocalContext *lc); > +int ff_vvc_intra_luma_mpm_remainder(VVCLocalContext *lc); > +int ff_vvc_cclm_mode_flag(VVCLocalContext *lc); > +int ff_vvc_cclm_mode_idx(VVCLocalContext *lc); > +int ff_vvc_intra_chroma_pred_mode(VVCLocalContext *lc); > + > +//inter > +int ff_vvc_general_merge_flag(VVCLocalContext *lc); > +int ff_vvc_merge_subblock_flag(VVCLocalContext *lc); > +int ff_vvc_merge_subblock_idx(VVCLocalContext *lc, int max_num_subblock_merge_cand); > +int ff_vvc_regular_merge_flag(VVCLocalContext *lc, int cu_skip_flag); > +int ff_vvc_merge_idx(VVCLocalContext *lc); > +int ff_vvc_mmvd_merge_flag(VVCLocalContext *lc); > +int ff_vvc_mmvd_cand_flag(VVCLocalContext *lc); > +void ff_vvc_mmvd_offset_coding(VVCLocalContext *lc, Mv *mvd_offset, int ph_mmvd_fullpel_only_flag); > +int ff_vvc_ciip_flag(VVCLocalContext *lc); > +int ff_vvc_merge_gpm_partition_idx(VVCLocalContext *lc); > +int ff_vvc_merge_gpm_idx(VVCLocalContext *lc, int idx); > +PredFlag ff_vvc_pred_flag(VVCLocalContext *lc, int is_b); > +int ff_vvc_inter_affine_flag(VVCLocalContext *lc); > +int ff_vvc_cu_affine_type_flag(VVCLocalContext *lc); > +int ff_vvc_sym_mvd_flag(VVCLocalContext *lc); > +int ff_vvc_ref_idx_lx(VVCLocalContext *lc, uint8_t nb_refs); > +int ff_vvc_abs_mvd_greater0_flag(VVCLocalContext *lc); > +int ff_vvc_abs_mvd_greater1_flag(VVCLocalContext *lc); > +int ff_vvc_abs_mvd_minus2(VVCLocalContext *lc); > +int ff_vvc_mvd_sign_flag(VVCLocalContext *lc); > +int ff_vvc_mvp_lx_flag(VVCLocalContext *lc); > +int ff_vvc_amvr_shift(VVCLocalContext *lc, int inter_affine_flag, PredMode pred_mode, int has_amvr_flag); > +int ff_vvc_bcw_idx(VVCLocalContext *lc, int no_backward_pred_flag); > + > +//transform > +int ff_vvc_tu_cb_coded_flag(VVCLocalContext *lc); > +int ff_vvc_tu_cr_coded_flag(VVCLocalContext *lc, int tu_cb_coded_flag); > +int ff_vvc_tu_y_coded_flag(VVCLocalContext *lc); > +int ff_vvc_cu_chroma_qp_offset_flag(VVCLocalContext *lc); > +int ff_vvc_cu_chroma_qp_offset_idx(VVCLocalContext *lc); > +int ff_vvc_tu_joint_cbcr_residual_flag(VVCLocalContext *lc, int tu_cb_coded_flag, int tu_cr_coded_flag); > +int ff_vvc_transform_skip_flag(VVCLocalContext *lc, int ctx); > +int ff_vvc_residual_coding(VVCLocalContext *lc, TransformBlock *tb); > +int ff_vvc_lfnst_idx(VVCLocalContext *lc, int inc); > +int ff_vvc_mts_idx(VVCLocalContext *lc); > + > +int ff_vvc_end_of_slice_flag_decode(VVCLocalContext *lc); > +int ff_vvc_end_of_tile_one_bit(VVCLocalContext *lc); > +int ff_vvc_end_of_subset_one_bit(VVCLocalContext *lc); > + > +#endif //AVCODEC_VVC_VVC_CABAC_H > diff --git a/libavcodec/vvc/vvc_ctu.c b/libavcodec/vvc/vvc_ctu.c > new file mode 100644 > index 0000000000..78b13ffb00 > --- /dev/null > +++ b/libavcodec/vvc/vvc_ctu.c > @@ -0,0 +1,32 @@ > +/* > + * VVC CTU(Coding Tree Unit) parser > + * > + * Copyright (C) 2022 Nuo Mi > + * > + * This file is part of FFmpeg. > + * > + * FFmpeg is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Lesser General Public > + * License as published by the Free Software Foundation; either > + * version 2.1 of the License, or (at your option) any later version. > + * > + * FFmpeg is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * Lesser General Public License for more details. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with FFmpeg; if not, write to the Free Software > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA > + */ > + > +#include "vvc_ctu.h" > + > +void ff_vvc_ep_init_stat_coeff(EntryPoint *ep, > + const int bit_depth, const int persistent_rice_adaptation_enabled_flag) > +{ > + for (size_t i = 0; i < FF_ARRAY_ELEMS(ep->stat_coeff); ++i) { > + ep->stat_coeff[i] = > + persistent_rice_adaptation_enabled_flag ? 2 * (av_log2(bit_depth - 10)) : 0; > + } > +} > diff --git a/libavcodec/vvc/vvc_ctu.h b/libavcodec/vvc/vvc_ctu.h > new file mode 100644 > index 0000000000..7cf9d9f045 > --- /dev/null > +++ b/libavcodec/vvc/vvc_ctu.h > @@ -0,0 +1,464 @@ > +/* > + * VVC CTU(Coding Tree Unit) parser > + * > + * Copyright (C) 2022 Nuo Mi > + * > + * This file is part of FFmpeg. > + * > + * FFmpeg is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Lesser General Public > + * License as published by the Free Software Foundation; either > + * version 2.1 of the License, or (at your option) any later version. > + * > + * FFmpeg is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * Lesser General Public License for more details. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with FFmpeg; if not, write to the Free Software > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA > + */ > + > +#ifndef AVCODEC_VVC_VVC_CTU_H > +#define AVCODEC_VVC_VVC_CTU_H > + > +#include "libavcodec/cabac.h" > +#include "libavutil/mem_internal.h" > + > +#include "vvcdec.h" > + > +#define MAX_CTU_SIZE 128 > + > +#define MAX_CU_SIZE MAX_CTU_SIZE > +#define MIN_CU_SIZE 4 > +#define MIN_CU_LOG2 2 > +#define MAX_CU_DEPTH 7 > + > +#define MAX_PARTS_IN_CTU ((MAX_CTU_SIZE >> MIN_CU_LOG2) * (MAX_CTU_SIZE >> MIN_CU_LOG2)) > + > +#define MIN_PU_SIZE 4 > + > +#define MAX_TB_SIZE 64 > +#define MIN_TU_SIZE 4 > +#define MAX_TUS_IN_CU 64 > + > +#define MAX_QP 63 > + > +#define MAX_PB_SIZE 128 > +#define EDGE_EMU_BUFFER_STRIDE (MAX_PB_SIZE + 32) > + > +#define CHROMA_EXTRA_BEFORE 1 > +#define CHROMA_EXTRA_AFTER 2 > +#define CHROMA_EXTRA 3 > +#define LUMA_EXTRA_BEFORE 3 > +#define LUMA_EXTRA_AFTER 4 > +#define LUMA_EXTRA 7 > +#define BILINEAR_EXTRA_BEFORE 0 > +#define BILINEAR_EXTRA_AFTER 1 > +#define BILINEAR_EXTRA 1 > + > +#define MAX_CONTROL_POINTS 3 > + > +#define AFFINE_MIN_BLOCK_SIZE 4 > + > +#define MRG_MAX_NUM_CANDS 6 > +#define MAX_NUM_HMVP_CANDS 5 > + > +#define SAO_PADDING_SIZE 1 > + > +#define ALF_PADDING_SIZE 8 > +#define ALF_BLOCK_SIZE 4 > + > +#define ALF_BORDER_LUMA 3 > +#define ALF_BORDER_CHROMA 2 > + > +#define ALF_VB_POS_ABOVE_LUMA 4 > +#define ALF_VB_POS_ABOVE_CHROMA 2 > + > +#define ALF_GRADIENT_STEP 2 > +#define ALF_GRADIENT_BORDER 2 > +#define ALF_GRADIENT_SIZE ((MAX_CU_SIZE + ALF_GRADIENT_BORDER * 2) / ALF_GRADIENT_STEP) > +#define ALF_NUM_DIR 4 > + > + > +/** > + * Value of the luma sample at position (x, y) in the 2D array tab. > + */ > +#define SAMPLE(tab, x, y) ((tab)[(y) * s->sps->width + (x)]) > +#define SAMPLE_CTB(tab, x, y) ((tab)[(y) * min_cb_width + (x)]) > +#define CTB(tab, x, y) ((tab)[(y) * fc->ps.pps->ctb_width + (x)]) > + > +enum SAOType { > + SAO_NOT_APPLIED = 0, > + SAO_BAND, > + SAO_EDGE, > +}; > + > +enum SAOEOClass { > + SAO_EO_HORIZ = 0, > + SAO_EO_VERT, > + SAO_EO_135D, > + SAO_EO_45D, > +}; > + > +typedef struct NeighbourAvailable { > + int cand_left; > + int cand_up; > + int cand_up_left; > + int cand_up_right; > + int cand_up_right_sap; > +} NeighbourAvailable; > + > +enum IspType{ > + ISP_NO_SPLIT, > + ISP_HOR_SPLIT, > + ISP_VER_SPLIT, > +}; > + > +typedef enum VVCSplitMode { > + SPLIT_NONE, > + SPLIT_TT_HOR, > + SPLIT_BT_HOR, > + SPLIT_TT_VER, > + SPLIT_BT_VER, > + SPLIT_QT, > +} VVCSplitMode; > + > +typedef enum MtsIdx { > + MTS_DCT2_DCT2, > + MTS_DST7_DST7, > + MTS_DST7_DCT8, > + MTS_DCT8_DST7, > + MTS_DCT8_DCT8, > +} MtsIdx; > + > +typedef struct TransformBlock { > + uint8_t has_coeffs; > + uint8_t c_idx; > + uint8_t ts; ///< transform_skip_flag > + int x0; > + int y0; > + > + int tb_width; > + int tb_height; > + int log2_tb_width; > + int log2_tb_height; > + > + int max_scan_x; > + int max_scan_y; > + int min_scan_x; > + int min_scan_y; > + > + int qp; > + int rect_non_ts_flag; > + int bd_shift; > + int bd_offset; > + > + int *coeffs; > +} TransformBlock; > + > +typedef enum VVCTreeType { > + SINGLE_TREE, > + DUAL_TREE_LUMA, > + DUAL_TREE_CHROMA, > +} VVCTreeType; > + > +typedef struct TransformUnit { > + int x0; > + int y0; > + int width; > + int height; > + > + uint8_t joint_cbcr_residual_flag; ///< tu_joint_cbcr_residual_flag > + > + uint8_t coded_flag[VVC_MAX_SAMPLE_ARRAYS]; ///< tu_y_coded_flag, tu_cb_coded_flag, tu_cr_coded_flag > + uint8_t nb_tbs; > + TransformBlock tbs[VVC_MAX_SAMPLE_ARRAYS]; > + > + struct TransformUnit *next; ///< RefStruct reference > +} TransformUnit; > + > +typedef enum PredMode { > + MODE_INTER, > + MODE_INTRA, > + MODE_SKIP, > + MODE_PLT, > + MODE_IBC, > +} PredMode; > + > +typedef struct Mv { > + int x; ///< horizontal component of motion vector > + int y; ///< vertical component of motion vector > +} Mv; > + > +typedef struct MvField { > + DECLARE_ALIGNED(4, Mv, mv)[2]; ///< mvL0, vvL1 > + int8_t ref_idx[2]; ///< refIdxL0, refIdxL1 > + uint8_t hpel_if_idx; ///< hpelIfIdx > + uint8_t bcw_idx; ///< bcwIdx > + uint8_t pred_flag; > + uint8_t ciip_flag; ///< ciip_flag > +} MvField; > + > +typedef struct DMVRInfo { > + DECLARE_ALIGNED(4, Mv, mv)[2]; ///< mvL0, vvL1 > + uint8_t dmvr_enabled; > +} DMVRInfo; > + > +typedef enum MotionModelIdc { > + MOTION_TRANSLATION, > + MOTION_4_PARAMS_AFFINE, > + MOTION_6_PARAMS_AFFINE, > +} MotionModelIdc; > + > +typedef enum PredFlag { > + PF_INTRA = 0x0, > + PF_L0 = 0x1, > + PF_L1 = 0x2, > + PF_BI = 0x3, > +} PredFlag; > + > +typedef enum IntraPredMode { > + INTRA_INVALID = -1, > + INTRA_PLANAR = 0, > + INTRA_DC, > + INTRA_HORZ = 18, > + INTRA_DIAG = 34, > + INTRA_VERT = 50, > + INTRA_VDIAG = 66, > + INTRA_LT_CCLM = 81, > + INTRA_L_CCLM, > + INTRA_T_CCLM > +} IntraPredMode; > + > +typedef struct MotionInfo { > + MotionModelIdc motion_model_idc; ///< MotionModelIdc > + int8_t ref_idx[2]; ///< refIdxL0, refIdxL1 > + uint8_t hpel_if_idx; ///< hpelIfIdx > + uint8_t bcw_idx; ///< bcwIdx > + PredFlag pred_flag; > + > + Mv mv[2][MAX_CONTROL_POINTS]; > + > + int num_sb_x, num_sb_y; > +} MotionInfo; > + > +typedef struct PredictionUnit { > + uint8_t general_merge_flag; > + uint8_t mmvd_merge_flag; > + //InterPredIdc inter_pred_idc; > + uint8_t inter_affine_flag; > + > + //subblock predict > + uint8_t merge_subblock_flag; > + > + uint8_t merge_gpm_flag; > + uint8_t gpm_partition_idx; > + MvField gpm_mv[2]; > + > + int sym_mvd_flag; > + > + MotionInfo mi; > + > + // for regular prediction only > + uint8_t dmvr_flag; > + uint8_t bdof_flag; > + > + int16_t diff_mv_x[2][AFFINE_MIN_BLOCK_SIZE * AFFINE_MIN_BLOCK_SIZE]; ///< diffMvLX > + int16_t diff_mv_y[2][AFFINE_MIN_BLOCK_SIZE * AFFINE_MIN_BLOCK_SIZE]; ///< diffMvLX > + int cb_prof_flag[2]; > +} PredictionUnit; > + > +typedef struct CodingUnit { > + VVCTreeType tree_type; > + int x0; > + int y0; > + int cb_width; > + int cb_height; > + int ch_type; > + int cqt_depth; > + > + uint8_t coded_flag; > + > + uint8_t sbt_flag; > + uint8_t sbt_horizontal_flag; > + uint8_t sbt_pos_flag; > + > + int lfnst_idx; > + MtsIdx mts_idx; > + > + uint8_t act_enabled_flag; > + > + uint8_t intra_luma_ref_idx; ///< IntraLumaRefLineIdx[][] > + uint8_t intra_mip_flag; ///< intra_mip_flag > + uint8_t skip_flag; ///< cu_skip_flag; > + > + //inter > + uint8_t ciip_flag; > + > + // Inferred parameters > + enum IspType isp_split_type; ///< IntraSubPartitionsSplitType > + > + enum PredMode pred_mode; ///< PredMode > + > + int num_intra_subpartitions; > + > + IntraPredMode intra_pred_mode_y; ///< IntraPredModeY > + IntraPredMode intra_pred_mode_c; ///< IntraPredModeC > + int mip_chroma_direct_flag; ///< MipChromaDirectFlag > + > + int bdpcm_flag[VVC_MAX_SAMPLE_ARRAYS]; ///< BdpcmFlag > + > + int apply_lfnst_flag[VVC_MAX_SAMPLE_ARRAYS]; ///< ApplyLfnstFlag[] > + > + struct { > + TransformUnit *head; ///< RefStruct reference > + TransformUnit *tail; ///< RefStruct reference > + } tus; > + > + int8_t qp[4]; ///< QpY, Qp′Cb, Qp′Cr, Qp′CbCr > + > + PredictionUnit pu; > + > + struct CodingUnit *next; ///< RefStruct reference > +} CodingUnit; > + > +typedef struct CTU { > + CodingUnit *cus; > + int max_y[2][VVC_MAX_REF_ENTRIES]; > + int max_y_idx[2]; > + int has_dmvr; > +} CTU; > + > +typedef struct ReconstructedArea { > + int x; > + int y; > + int w; > + int h; > +} ReconstructedArea; > + > +typedef struct VVCCabacState { > + uint16_t state[2]; > + uint8_t shift[2]; > +} VVCCabacState; > + > +// VVC_CONTEXTS matched with SYNTAX_ELEMENT_LAST, it's checked by cabac_init_state. > +#define VVC_CONTEXTS 378 > +typedef struct EntryPoint { > + int8_t qp_y; ///< QpY > + > + int stat_coeff[VVC_MAX_SAMPLE_ARRAYS]; ///< StatCoeff > + > + VVCCabacState cabac_state[VVC_CONTEXTS]; > + CABACContext cc; > + > + int ctu_start; > + int ctu_end; > + > + uint8_t is_first_qg; // first quantization group > + MvField hmvp[MAX_NUM_HMVP_CANDS]; ///< HmvpCandList > + int num_hmvp; ///< NumHmvpCand > +} EntryPoint; > + > +typedef struct VVCLocalContext { > + uint8_t ctb_left_flag; > + uint8_t ctb_up_flag; > + uint8_t ctb_up_right_flag; > + uint8_t ctb_up_left_flag; > + int end_of_tiles_x; > + int end_of_tiles_y; > + > + /* +7 is for subpixel interpolation, *2 for high bit depths */ > + DECLARE_ALIGNED(32, uint8_t, edge_emu_buffer)[(MAX_PB_SIZE + 7) * EDGE_EMU_BUFFER_STRIDE * 2]; > + /* The extended size between the new edge emu buffer is abused by SAO */ > + DECLARE_ALIGNED(32, uint8_t, edge_emu_buffer2)[(MAX_PB_SIZE + 7) * EDGE_EMU_BUFFER_STRIDE * 2]; > + DECLARE_ALIGNED(32, int16_t, tmp)[MAX_PB_SIZE * MAX_PB_SIZE]; > + DECLARE_ALIGNED(32, int16_t, tmp1)[MAX_PB_SIZE * MAX_PB_SIZE]; > + DECLARE_ALIGNED(32, int16_t, tmp2)[MAX_PB_SIZE * MAX_PB_SIZE]; > + DECLARE_ALIGNED(32, uint8_t, ciip_tmp1)[MAX_PB_SIZE * MAX_PB_SIZE * 2]; > + DECLARE_ALIGNED(32, uint8_t, ciip_tmp2)[MAX_PB_SIZE * MAX_PB_SIZE * 2]; > + DECLARE_ALIGNED(32, uint8_t, sao_buffer)[(MAX_CTU_SIZE + 2 * SAO_PADDING_SIZE) * EDGE_EMU_BUFFER_STRIDE * 2]; > + DECLARE_ALIGNED(32, uint8_t, alf_buffer_luma)[(MAX_CTU_SIZE + 2 * ALF_PADDING_SIZE) * EDGE_EMU_BUFFER_STRIDE * 2]; > + DECLARE_ALIGNED(32, uint8_t, alf_buffer_chroma)[(MAX_CTU_SIZE + 2 * ALF_PADDING_SIZE) * EDGE_EMU_BUFFER_STRIDE * 2]; > + DECLARE_ALIGNED(32, int32_t, alf_gradient_tmp)[ALF_GRADIENT_SIZE * ALF_GRADIENT_SIZE * ALF_NUM_DIR]; > + > + struct { > + int sbt_num_fourths_tb0; ///< SbtNumFourthsTb0 > + > + uint8_t is_cu_qp_delta_coded; ///< IsCuQpDeltaCoded > + int cu_qg_top_left_x; ///< CuQgTopLeftX > + int cu_qg_top_left_y; ///< CuQgTopLeftY > + int is_cu_chroma_qp_offset_coded; ///< IsCuChromaQpOffsetCoded > + int chroma_qp_offset[3]; ///< CuQpOffsetCb, CuQpOffsetCr, CuQpOffsetCbCr > + > + int infer_tu_cbf_luma; ///< InferTuCbfLuma > + int prev_tu_cbf_y; ///< prevTuCbfY; > + > + int lfnst_dc_only; ///< LfnstDcOnly > + int lfnst_zero_out_sig_coeff_flag; ///< LfnstZeroOutSigCoeffFlag > + > + int mts_dc_only; ///< MtsDcOnly > + int mts_zero_out_sig_coeff_flag; ///< MtsZeroOutSigCoeffFlag; > + } parse; > + > + struct { > + // lmcs cache, for recon only > + int chroma_scale; > + int x_vpdu; > + int y_vpdu; > + } lmcs; > + > + CodingUnit *cu; > + ReconstructedArea ras[2][MAX_PARTS_IN_CTU]; > + int num_ras[2]; > + > + NeighbourAvailable na; > + > +#define BOUNDARY_LEFT_SLICE (1 << 0) > +#define BOUNDARY_LEFT_TILE (1 << 1) > +#define BOUNDARY_UPPER_SLICE (1 << 2) > +#define BOUNDARY_UPPER_TILE (1 << 3) > + /* properties of the boundary of the current CTB for the purposes > + * of the deblocking filter */ > + int boundary_flags; > + > + SliceContext *sc; > + VVCFrameContext *fc; > + EntryPoint *ep; > + int *coeffs; > +} VVCLocalContext; > + > +typedef struct VVCAllowedSplit { > + int qt; > + int btv; > + int bth; > + int ttv; > + int tth; > +} VVCAllowedSplit; > + > +typedef struct SAOParams { > + int offset_abs[3][4]; ///< sao_offset_abs > + int offset_sign[3][4]; ///< sao_offset_sign > + > + uint8_t band_position[3]; ///< sao_band_position > + > + int eo_class[3]; ///< sao_eo_class > + > + int16_t offset_val[3][5]; ///< SaoOffsetVal > + > + uint8_t type_idx[3]; ///< sao_type_idx > +} SAOParams; > + > +typedef struct ALFParams { > + uint8_t ctb_flag[3]; ///< alf_ctb_flag[] > + uint8_t ctb_filt_set_idx_y; ///< AlfCtbFiltSetIdxY > + uint8_t alf_ctb_filter_alt_idx[2]; ///< alf_ctb_filter_alt_idx[] > + uint8_t ctb_cc_idc[2]; ///< alf_ctb_cc_cb_idc, alf_ctb_cc_cr_idc > + > + uint8_t applied[3]; > +} ALFParams; > + > +void ff_vvc_ep_init_stat_coeff(EntryPoint *ep, int bit_depth, int persistent_rice_adaptation_enabled_flag); > + > +#endif // AVCODEC_VVC_VVC_CTU_H > diff --git a/libavcodec/vvc/vvcdec.h b/libavcodec/vvc/vvcdec.h > index cde9b2c965..15ece2a83c 100644 > --- a/libavcodec/vvc/vvcdec.h > +++ b/libavcodec/vvc/vvcdec.h > @@ -80,6 +80,7 @@ typedef struct VVCFrame { > > typedef struct SliceContext { > int slice_idx; > + VVCSH sh; > struct EntryPoint *eps; > int nb_eps; > RefPicList *rpl; > @@ -95,6 +96,8 @@ typedef struct VVCFrameContext { > struct AVFrame *frame; > struct AVFrame *output_frame; > > + VVCFrameParamSets ps; > + > SliceContext **slices; > int nb_slices; > int nb_slices_allocated; > @@ -114,6 +117,10 @@ typedef struct VVCFrameContext { > struct { > int16_t *slice_idx; > > + DBParams *deblock; > + struct SAOParams *sao; > + struct ALFParams *alf; > + > int *cb_pos_x[2]; ///< CbPosX[][][] > int *cb_pos_y[2]; ///< CbPosY[][][] > uint8_t *cb_width[2]; ///< CbWidth[][][] > -- > 2.25.1 > > _______________________________________________ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > To unsubscribe, visit link above, or email > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe". > _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
next prev parent reply other threads:[~2024-01-01 15:13 UTC|newest] Thread overview: 49+ messages / expand[flat|nested] mbox.gz Atom feed top [not found] <20240101141239.6623-1-nuomi2021@gmail.com> 2024-01-01 14:12 ` [FFmpeg-devel] [PATCH v9 01/13] vvcdec: add vvc_data Nuo Mi 2024-01-01 14:12 ` [FFmpeg-devel] [PATCH v9 02/13] vvcdec: add parameter parser for sps, pps, ph, sh Nuo Mi 2024-01-01 14:12 ` [FFmpeg-devel] [PATCH v9 03/13] vvcdec: add cabac decoder Nuo Mi 2024-01-01 15:13 ` Lynne [this message] 2024-01-02 13:21 ` Nuo Mi 2024-01-02 15:57 ` Lynne 2024-01-03 1:38 ` Nuo Mi 2024-01-01 17:34 ` Michael Niedermayer 2024-01-02 13:44 ` Nuo Mi 2024-01-01 14:12 ` [FFmpeg-devel] [PATCH v9 04/13] vvcdec: add reference management Nuo Mi 2024-01-01 14:12 ` [FFmpeg-devel] [PATCH v9 05/13] vvcdec: add motion vector decoder Nuo Mi 2024-01-01 14:12 ` [FFmpeg-devel] [PATCH v9 06/13] vvcdec: add inter prediction Nuo Mi 2024-01-01 15:04 ` Lynne 2024-01-02 14:16 ` Nuo Mi 2024-01-02 14:30 ` Kieran Kunhya 2024-01-02 15:59 ` Lynne 2024-01-01 14:12 ` [FFmpeg-devel] [PATCH v9 07/13] vvcdec: add inv transform 1d Nuo Mi 2024-01-01 14:50 ` Lynne 2024-01-02 13:01 ` Nuo Mi 2024-01-02 15:55 ` Lynne 2024-01-03 12:04 ` Nuo Mi 2024-01-01 14:12 ` [FFmpeg-devel] [PATCH v9 08/13] vvcdec: add intra prediction Nuo Mi 2024-01-01 14:12 ` [FFmpeg-devel] [PATCH v9 09/13] vvcdec: add LMCS, Deblocking, SAO, and ALF filters Nuo Mi 2024-01-01 15:17 ` Lynne 2024-01-02 9:47 ` Nuo Mi 2024-01-02 11:38 ` Jean-Baptiste Kempf 2024-01-02 15:51 ` Lynne 2024-01-03 1:14 ` Nuo Mi 2024-01-03 18:38 ` Michael Niedermayer 2024-01-04 11:45 ` Nuo Mi 2024-01-04 12:06 ` Martin Storsjö 2024-01-04 13:57 ` Nuo Mi 2024-01-04 14:53 ` James Almer 2024-01-05 0:02 ` Nuo Mi 2024-01-05 11:55 ` Martin Storsjö 2024-01-05 20:47 ` Michael Niedermayer 2024-01-01 14:12 ` [FFmpeg-devel] [PATCH v9 10/13] vvcdec: add dsp init and inv transform Nuo Mi 2024-01-01 14:12 ` [FFmpeg-devel] [PATCH v9 11/13] vvcdec: add CTU parser Nuo Mi 2024-01-01 14:12 ` [FFmpeg-devel] [PATCH v9 12/13] vvcdec: add CTU thread logical Nuo Mi 2024-01-01 14:12 ` [FFmpeg-devel] [PATCH v9 13/13] vvcdec: add vvc decoder Nuo Mi 2024-01-01 14:53 ` Lynne 2024-01-01 15:14 ` Hendrik Leppkes 2024-01-01 15:22 ` Lynne 2024-01-02 9:38 ` Nuo Mi 2024-01-02 11:41 ` Jean-Baptiste Kempf 2024-01-02 16:00 ` Lynne 2024-01-05 20:48 ` James Almer 2024-01-06 17:47 ` James Almer 2024-01-07 5:31 ` Nuo Mi
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=Nn4_bVu--3-9@lynne.ee \ --to=dev@lynne.ee \ --cc=ffmpeg-devel@ffmpeg.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel This inbox may be cloned and mirrored by anyone: git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git # If you have public-inbox 1.1+ installed, you may # initialize and index your mirror using the following commands: public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \ ffmpegdev@gitmailbox.com public-inbox-index ffmpegdev Example config snippet for mirrors. AGPL code for this site: git clone https://public-inbox.org/public-inbox.git