This is an automated email from the git hooks/post-receive script. Git pushed a commit to branch master in repository ffmpeg.
commit 0fb9bceab1d953739431010cff778d8188107924 Author: YoungSoo Lee <[email protected]> AuthorDate: Fri Aug 21 10:46:32 2026 +0900 Commit: YoungSoo Lee <[email protected]> CommitDate: Thu Nov 5 18:19:58 2026 +0900 lavc/hevc: group the state that continues across CTBs The CABAC and QP prediction state sits in HEVCLocalContext next to the scratch space used while a single CTB is decoded, although the two have different lifetimes: the former has to survive from one CTB to the next within a substream, the latter does not survive at all. Move it into a HEVCSubstream struct held by the local context. Whether the CABAC decoder was already opened on the substream data now travels with the substream, which replaces the is_wpp argument of ff_hevc_cabac_init() and allows a substream to be read from its own buffer. No functional change. Signed-off-by: YoungSoo Lee <[email protected]> --- libavcodec/hevc/cabac.c | 156 +++++++++++++++++++++++++--------------------- libavcodec/hevc/filter.c | 10 +-- libavcodec/hevc/hevcdec.c | 74 ++++++++++++---------- libavcodec/hevc/hevcdec.h | 31 +++++---- 4 files changed, 150 insertions(+), 121 deletions(-) diff --git a/libavcodec/hevc/cabac.c b/libavcodec/hevc/cabac.c index 57f43be06f..5b53815630 100644 --- a/libavcodec/hevc/cabac.c +++ b/libavcodec/hevc/cabac.c @@ -407,24 +407,24 @@ void ff_hevc_save_states(HEVCLocalContext *lc, const HEVCPPS *pps, (ctb_addr_ts % sps->ctb_width == 2 || (sps->ctb_width == 2 && ctb_addr_ts % sps->ctb_width == 0))) { - memcpy(lc->common_cabac_state->state, lc->cabac_state, HEVC_CONTEXTS); + memcpy(lc->common_cabac_state->state, lc->sub.cabac_state, HEVC_CONTEXTS); if (sps->persistent_rice_adaptation_enabled) { - memcpy(lc->common_cabac_state->stat_coeff, lc->stat_coeff, HEVC_STAT_COEFFS); + memcpy(lc->common_cabac_state->stat_coeff, lc->sub.stat_coeff, HEVC_STAT_COEFFS); } } } static void load_states(HEVCLocalContext *lc, const HEVCSPS *sps) { - memcpy(lc->cabac_state, lc->common_cabac_state->state, HEVC_CONTEXTS); + memcpy(lc->sub.cabac_state, lc->common_cabac_state->state, HEVC_CONTEXTS); if (sps->persistent_rice_adaptation_enabled) { - memcpy(lc->stat_coeff, lc->common_cabac_state->stat_coeff, HEVC_STAT_COEFFS); + memcpy(lc->sub.stat_coeff, lc->common_cabac_state->stat_coeff, HEVC_STAT_COEFFS); } } static int cabac_reinit(HEVCLocalContext *lc) { - return skip_bytes(&lc->cc, 0) == NULL ? AVERROR_INVALIDDATA : 0; + return skip_bytes(&lc->sub.cc, 0) == NULL ? AVERROR_INVALIDDATA : 0; } static void cabac_init_state(HEVCLocalContext *lc, const HEVCContext *s) @@ -444,24 +444,45 @@ static void cabac_init_state(HEVCLocalContext *lc, const HEVCContext *s) pre ^= pre >> 31; if (pre > 124) pre = 124 + (pre & 1); - lc->cabac_state[i] = pre; + lc->sub.cabac_state[i] = pre; } for (i = 0; i < 4; i++) - lc->stat_coeff[i] = 0; + lc->sub.stat_coeff[i] = 0; +} + +/* Open CABAC on this substream's data, or continue byte-aligned in it if it + * is already open (one slice read from a single buffer). */ +static int substream_continue(HEVCLocalContext *lc) +{ + HEVCSubstream *const sub = &lc->sub; + int ret; + + if (sub->opened) + return cabac_reinit(lc); + + ret = ff_init_cabac_decoder(&sub->cc, sub->data, sub->size); + if (ret < 0) + return ret; + sub->opened = 1; + + return 0; } int ff_hevc_cabac_init(HEVCLocalContext *lc, const HEVCPPS *pps, - int ctb_addr_ts, const uint8_t *data, size_t size, - int is_wpp) + int ctb_addr_ts) { const HEVCContext *const s = lc->parent; const HEVCSPS *const sps = pps->sps; + HEVCSubstream *const sub = &lc->sub; if (ctb_addr_ts == pps->ctb_addr_rs_to_ts[s->sh.slice_ctb_addr_rs]) { - int ret = ff_init_cabac_decoder(&lc->cc, data, size); + /* First CTB of a slice segment. For a dependent slice segment the + * data still belongs to the new segment. */ + int ret = ff_init_cabac_decoder(&sub->cc, sub->data, sub->size); if (ret < 0) return ret; + sub->opened = 1; if (s->sh.dependent_slice_segment_flag == 0 || (pps->tiles_enabled_flag && pps->tile_id[ctb_addr_ts] != pps->tile_id[ctb_addr_ts - 1])) @@ -479,12 +500,7 @@ int ff_hevc_cabac_init(HEVCLocalContext *lc, const HEVCPPS *pps, } else { if (pps->tiles_enabled_flag && pps->tile_id[ctb_addr_ts] != pps->tile_id[ctb_addr_ts - 1]) { - int ret; - if (!is_wpp) - ret = cabac_reinit(lc); - else { - ret = ff_init_cabac_decoder(&lc->cc, data, size); - } + int ret = substream_continue(lc); if (ret < 0) return ret; cabac_init_state(lc, s); @@ -492,12 +508,10 @@ int ff_hevc_cabac_init(HEVCLocalContext *lc, const HEVCPPS *pps, if (pps->entropy_coding_sync_enabled_flag) { if (ctb_addr_ts % sps->ctb_width == 0) { int ret; - get_cabac_terminate(&lc->cc); - if (!is_wpp) - ret = cabac_reinit(lc); - else { - ret = ff_init_cabac_decoder(&lc->cc, data, size); - } + /* The end of row terminate bit is read only when continuing */ + if (sub->opened) + get_cabac_terminate(&sub->cc); + ret = substream_continue(lc); if (ret < 0) return ret; @@ -511,7 +525,7 @@ int ff_hevc_cabac_init(HEVCLocalContext *lc, const HEVCPPS *pps, return 0; } -#define GET_CABAC(ctx) get_cabac(&lc->cc, &lc->cabac_state[ctx]) +#define GET_CABAC(ctx) get_cabac(&lc->sub.cc, &lc->sub.cabac_state[ctx]) int ff_hevc_sao_merge_flag_decode(HEVCLocalContext *lc) { @@ -523,7 +537,7 @@ int ff_hevc_sao_type_idx_decode(HEVCLocalContext *lc) if (!GET_CABAC(SAO_TYPE_IDX_OFFSET)) return 0; - if (!get_cabac_bypass(&lc->cc)) + if (!get_cabac_bypass(&lc->sub.cc)) return SAO_BAND; return SAO_EDGE; } @@ -531,10 +545,10 @@ int ff_hevc_sao_type_idx_decode(HEVCLocalContext *lc) int ff_hevc_sao_band_position_decode(HEVCLocalContext *lc) { int i; - int value = get_cabac_bypass(&lc->cc); + int value = get_cabac_bypass(&lc->sub.cc); for (i = 0; i < 4; i++) - value = (value << 1) | get_cabac_bypass(&lc->cc); + value = (value << 1) | get_cabac_bypass(&lc->sub.cc); return value; } @@ -543,26 +557,26 @@ int ff_hevc_sao_offset_abs_decode(HEVCLocalContext *lc, int bit_depth) int i = 0; int length = (1 << (FFMIN(bit_depth, 10) - 5)) - 1; - while (i < length && get_cabac_bypass(&lc->cc)) + while (i < length && get_cabac_bypass(&lc->sub.cc)) i++; return i; } int ff_hevc_sao_offset_sign_decode(HEVCLocalContext *lc) { - return get_cabac_bypass(&lc->cc); + return get_cabac_bypass(&lc->sub.cc); } int ff_hevc_sao_eo_class_decode(HEVCLocalContext *lc) { - int ret = get_cabac_bypass(&lc->cc) << 1; - ret |= get_cabac_bypass(&lc->cc); + int ret = get_cabac_bypass(&lc->sub.cc) << 1; + ret |= get_cabac_bypass(&lc->sub.cc); return ret; } int ff_hevc_end_of_slice_flag_decode(HEVCLocalContext *lc) { - return get_cabac_terminate(&lc->cc); + return get_cabac_terminate(&lc->sub.cc); } int ff_hevc_cu_transquant_bypass_flag_decode(HEVCLocalContext *lc) @@ -595,7 +609,7 @@ int ff_hevc_cu_qp_delta_abs(HEVCLocalContext *lc) } if (prefix_val >= 5) { int k = 0; - while (k < 7 && get_cabac_bypass(&lc->cc)) { + while (k < 7 && get_cabac_bypass(&lc->sub.cc)) { suffix_val += 1 << k; k++; } @@ -605,14 +619,14 @@ int ff_hevc_cu_qp_delta_abs(HEVCLocalContext *lc) } while (k--) - suffix_val += get_cabac_bypass(&lc->cc) << k; + suffix_val += get_cabac_bypass(&lc->sub.cc) << k; } return prefix_val + suffix_val; } int ff_hevc_cu_qp_delta_sign_flag(HEVCLocalContext *lc) { - return get_cabac_bypass(&lc->cc); + return get_cabac_bypass(&lc->sub.cc); } int ff_hevc_cu_chroma_qp_offset_flag(HEVCLocalContext *lc) @@ -682,21 +696,21 @@ int ff_hevc_part_mode_decode(HEVCLocalContext *lc, const HEVCSPS *sps, int log2_ if (GET_CABAC(PART_MODE_OFFSET + 1)) { // 01X, 01XX if (GET_CABAC(PART_MODE_OFFSET + 3)) // 011 return PART_2NxN; - if (get_cabac_bypass(&lc->cc)) // 0101 + if (get_cabac_bypass(&lc->sub.cc)) // 0101 return PART_2NxnD; return PART_2NxnU; // 0100 } if (GET_CABAC(PART_MODE_OFFSET + 3)) // 001 return PART_Nx2N; - if (get_cabac_bypass(&lc->cc)) // 0001 + if (get_cabac_bypass(&lc->sub.cc)) // 0001 return PART_nRx2N; return PART_nLx2N; // 0000 } int ff_hevc_pcm_flag_decode(HEVCLocalContext *lc) { - return get_cabac_terminate(&lc->cc); + return get_cabac_terminate(&lc->sub.cc); } int ff_hevc_prev_intra_luma_pred_flag_decode(HEVCLocalContext *lc) @@ -707,7 +721,7 @@ int ff_hevc_prev_intra_luma_pred_flag_decode(HEVCLocalContext *lc) int ff_hevc_mpm_idx_decode(HEVCLocalContext *lc) { int i = 0; - while (i < 2 && get_cabac_bypass(&lc->cc)) + while (i < 2 && get_cabac_bypass(&lc->sub.cc)) i++; return i; } @@ -715,10 +729,10 @@ int ff_hevc_mpm_idx_decode(HEVCLocalContext *lc) int ff_hevc_rem_intra_luma_pred_mode_decode(HEVCLocalContext *lc) { int i; - int value = get_cabac_bypass(&lc->cc); + int value = get_cabac_bypass(&lc->sub.cc); for (i = 0; i < 4; i++) - value = (value << 1) | get_cabac_bypass(&lc->cc); + value = (value << 1) | get_cabac_bypass(&lc->sub.cc); return value; } @@ -728,8 +742,8 @@ int ff_hevc_intra_chroma_pred_mode_decode(HEVCLocalContext *lc) if (!GET_CABAC(INTRA_CHROMA_PRED_MODE_OFFSET)) return 4; - ret = get_cabac_bypass(&lc->cc) << 1; - ret |= get_cabac_bypass(&lc->cc); + ret = get_cabac_bypass(&lc->sub.cc) << 1; + ret |= get_cabac_bypass(&lc->sub.cc); return ret; } @@ -738,7 +752,7 @@ int ff_hevc_merge_idx_decode(HEVCLocalContext *lc) int i = GET_CABAC(MERGE_IDX_OFFSET); if (i != 0) { - while (i < lc->parent->sh.max_num_merge_cand-1 && get_cabac_bypass(&lc->cc)) + while (i < lc->parent->sh.max_num_merge_cand-1 && get_cabac_bypass(&lc->sub.cc)) i++; } return i; @@ -768,7 +782,7 @@ int ff_hevc_ref_idx_lx_decode(HEVCLocalContext *lc, int num_ref_idx_lx) while (i < max_ctx && GET_CABAC(REF_IDX_L0_OFFSET + i)) i++; if (i == 2) { - while (i < max && get_cabac_bypass(&lc->cc)) + while (i < max && get_cabac_bypass(&lc->sub.cc)) i++; } @@ -800,7 +814,7 @@ static av_always_inline int mvd_decode(HEVCLocalContext *lc) int ret = 2; int k = 1; - while (k < CABAC_MAX_BIN && get_cabac_bypass(&lc->cc)) { + while (k < CABAC_MAX_BIN && get_cabac_bypass(&lc->sub.cc)) { ret += 1U << k; k++; } @@ -809,13 +823,13 @@ static av_always_inline int mvd_decode(HEVCLocalContext *lc) return 0; } while (k--) - ret += get_cabac_bypass(&lc->cc) << k; - return get_cabac_bypass_sign(&lc->cc, -ret); + ret += get_cabac_bypass(&lc->sub.cc) << k; + return get_cabac_bypass_sign(&lc->sub.cc, -ret); } static av_always_inline int mvd_sign_flag_decode(HEVCLocalContext *lc) { - return get_cabac_bypass_sign(&lc->cc, -1); + return get_cabac_bypass_sign(&lc->sub.cc, -1); } int ff_hevc_split_transform_flag_decode(HEVCLocalContext *lc, int log2_trafo_size) @@ -894,10 +908,10 @@ static av_always_inline int last_significant_coeff_suffix_decode(HEVCLocalContex { int i; int length = (last_significant_coeff_prefix >> 1) - 1; - int value = get_cabac_bypass(&lc->cc); + int value = get_cabac_bypass(&lc->sub.cc); for (i = 1; i < length; i++) - value = (value << 1) | get_cabac_bypass(&lc->cc); + value = (value << 1) | get_cabac_bypass(&lc->sub.cc); return value; } @@ -1011,14 +1025,14 @@ static av_always_inline int coeff_abs_level_remaining_decode(HEVCLocalContext *l int last_coeff_abs_level_remaining; int i; - prefix = cabac_unary_prefix(&lc->cc, CABAC_MAX_BIN); + prefix = cabac_unary_prefix(&lc->sub.cc, CABAC_MAX_BIN); if (prefix < 3) { if (rc_rice_param > 2) - suffix = cabac_bypass_bits(&lc->cc, rc_rice_param); + suffix = cabac_bypass_bits(&lc->sub.cc, rc_rice_param); else for (i = 0; i < rc_rice_param; i++) - suffix = (suffix << 1) | get_cabac_bypass(&lc->cc); + suffix = (suffix << 1) | get_cabac_bypass(&lc->sub.cc); last_coeff_abs_level_remaining = (prefix << rc_rice_param) + suffix; } else { int prefix_minus3 = prefix - 3; @@ -1031,13 +1045,13 @@ static av_always_inline int coeff_abs_level_remaining_decode(HEVCLocalContext *l k = prefix_minus3 + rc_rice_param; if (k > 16) { - suffix = cabac_bypass_bits(&lc->cc, 16) << (k - 16); - suffix |= cabac_bypass_bits(&lc->cc, k - 16); + suffix = cabac_bypass_bits(&lc->sub.cc, 16) << (k - 16); + suffix |= cabac_bypass_bits(&lc->sub.cc, k - 16); } else if (k > 2) { - suffix = cabac_bypass_bits(&lc->cc, k); + suffix = cabac_bypass_bits(&lc->sub.cc, k); } else { for (i = 0; i < k; i++) - suffix = (suffix << 1) | get_cabac_bypass(&lc->cc); + suffix = (suffix << 1) | get_cabac_bypass(&lc->sub.cc); } last_coeff_abs_level_remaining = (((1 << prefix_minus3) + 3 - 1) << rc_rice_param) + suffix; @@ -1051,10 +1065,10 @@ static av_always_inline int coeff_sign_flag_decode(HEVCLocalContext *lc, uint8_t int ret = 0; if (nb > 2) - return cabac_bypass_bits(&lc->cc, nb); + return cabac_bypass_bits(&lc->sub.cc, nb); for (i = 0; i < nb; i++) - ret = (ret << 1) | get_cabac_bypass(&lc->cc); + ret = (ret << 1) | get_cabac_bypass(&lc->sub.cc); return ret; } @@ -1119,7 +1133,7 @@ void ff_hevc_hls_residual_coding(HEVCLocalContext *lc, const HEVCPPS *pps, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 12, 12 }; - int qp_y = lc->qp_y; + int qp_y = lc->sub.qp_y; if (pps->transform_skip_enabled_flag && log2_trafo_size <= pps->log2_max_transform_skip_block_size) { @@ -1133,10 +1147,10 @@ void ff_hevc_hls_residual_coding(HEVCLocalContext *lc, const HEVCPPS *pps, if (c_idx == 1) offset = pps->cb_qp_offset + s->sh.slice_cb_qp_offset + - lc->tu.cu_qp_offset_cb; + lc->sub.cu_qp_offset_cb; else offset = pps->cr_qp_offset + s->sh.slice_cr_qp_offset + - lc->tu.cu_qp_offset_cr; + lc->sub.cu_qp_offset_cr; qp_i = av_clip(qp_y + offset, - sps->qp_bd_offset, 57); if (sps->chroma_format_idc == 1) { @@ -1439,7 +1453,7 @@ void ff_hevc_hls_residual_coding(HEVCLocalContext *lc, const HEVCPPS *pps, sb_type = 2 * (c_idx == 0 ? 1 : 0); else sb_type = 2 * (c_idx == 0 ? 1 : 0) + 1; - c_rice_param = lc->stat_coeff[sb_type] / 4; + c_rice_param = lc->sub.stat_coeff[sb_type] / 4; } if (!(i == num_last_subset) && greater1_ctx == 0) @@ -1491,12 +1505,12 @@ void ff_hevc_hls_residual_coding(HEVCLocalContext *lc, const HEVCPPS *pps, if (trans_coeff_level > (3 << c_rice_param)) c_rice_param = sps->persistent_rice_adaptation_enabled ? c_rice_param + 1 : FFMIN(c_rice_param + 1, 4); if (sps->persistent_rice_adaptation_enabled && !rice_init) { - int c_rice_p_init = lc->stat_coeff[sb_type] / 4; + int c_rice_p_init = lc->sub.stat_coeff[sb_type] / 4; if (last_coeff_abs_level_remaining >= (3 << c_rice_p_init)) - lc->stat_coeff[sb_type]++; + lc->sub.stat_coeff[sb_type]++; else if (2 * last_coeff_abs_level_remaining < (1 << c_rice_p_init)) - if (lc->stat_coeff[sb_type] > 0) - lc->stat_coeff[sb_type]--; + if (lc->sub.stat_coeff[sb_type] > 0) + lc->sub.stat_coeff[sb_type]--; rice_init = 1; } } @@ -1507,12 +1521,12 @@ void ff_hevc_hls_residual_coding(HEVCLocalContext *lc, const HEVCPPS *pps, if (trans_coeff_level > (3 << c_rice_param)) c_rice_param = sps->persistent_rice_adaptation_enabled ? c_rice_param + 1 : FFMIN(c_rice_param + 1, 4); if (sps->persistent_rice_adaptation_enabled && !rice_init) { - int c_rice_p_init = lc->stat_coeff[sb_type] / 4; + int c_rice_p_init = lc->sub.stat_coeff[sb_type] / 4; if (last_coeff_abs_level_remaining >= (3 << c_rice_p_init)) - lc->stat_coeff[sb_type]++; + lc->sub.stat_coeff[sb_type]++; else if (2 * last_coeff_abs_level_remaining < (1 << c_rice_p_init)) - if (lc->stat_coeff[sb_type] > 0) - lc->stat_coeff[sb_type]--; + if (lc->sub.stat_coeff[sb_type] > 0) + lc->sub.stat_coeff[sb_type]--; rice_init = 1; } } diff --git a/libavcodec/hevc/filter.c b/libavcodec/hevc/filter.c index a4f1b24db7..1769014602 100644 --- a/libavcodec/hevc/filter.c +++ b/libavcodec/hevc/filter.c @@ -94,11 +94,11 @@ static int get_qPy_pred(HEVCLocalContext *lc, const HEVCContext *s, int qPy_pred, qPy_a, qPy_b; // qPy_pred - if (lc->first_qp_group || (!xQgBase && !yQgBase)) { - lc->first_qp_group = !lc->tu.is_cu_qp_delta_coded; + if (lc->sub.first_qp_group || (!xQgBase && !yQgBase)) { + lc->sub.first_qp_group = !lc->tu.is_cu_qp_delta_coded; qPy_pred = s->sh.slice_qp; } else { - qPy_pred = lc->qPy_pred; + qPy_pred = lc->sub.qPy_pred; } // qPy_a @@ -129,10 +129,10 @@ void ff_hevc_set_qPy(HEVCLocalContext *lc, if (lc->tu.cu_qp_delta != 0) { int off = sps->qp_bd_offset; - lc->qp_y = FFUMOD(qp_y + lc->tu.cu_qp_delta + 52 + 2 * off, + lc->sub.qp_y = FFUMOD(qp_y + lc->tu.cu_qp_delta + 52 + 2 * off, 52 + off) - off; } else - lc->qp_y = qp_y; + lc->sub.qp_y = qp_y; } static int get_qPy(const HEVCSPS *sps, const int8_t *qp_y_tab, int xC, int yC) diff --git a/libavcodec/hevc/hevcdec.c b/libavcodec/hevc/hevcdec.c index f1bd562291..7680cd4154 100644 --- a/libavcodec/hevc/hevcdec.c +++ b/libavcodec/hevc/hevcdec.c @@ -1385,11 +1385,11 @@ static int hls_transform_unit(HEVCLocalContext *lc, av_log(s->avctx, AV_LOG_ERROR, "cu_chroma_qp_offset_idx not yet tested.\n"); } - lc->tu.cu_qp_offset_cb = pps->cb_qp_offset_list[cu_chroma_qp_offset_idx]; - lc->tu.cu_qp_offset_cr = pps->cr_qp_offset_list[cu_chroma_qp_offset_idx]; + lc->sub.cu_qp_offset_cb = pps->cb_qp_offset_list[cu_chroma_qp_offset_idx]; + lc->sub.cu_qp_offset_cr = pps->cr_qp_offset_list[cu_chroma_qp_offset_idx]; } else { - lc->tu.cu_qp_offset_cb = 0; - lc->tu.cu_qp_offset_cr = 0; + lc->sub.cu_qp_offset_cb = 0; + lc->sub.cu_qp_offset_cr = 0; } lc->tu.is_cu_chroma_qp_offset_coded = 1; } @@ -1697,7 +1697,7 @@ static int hls_pcm_sample(HEVCLocalContext *lc, const HEVCLayerContext *l, (((cb_size >> sps->hshift[1]) * (cb_size >> sps->vshift[1])) + ((cb_size >> sps->hshift[2]) * (cb_size >> sps->vshift[2]))) * sps->pcm.bit_depth_chroma : 0); - const uint8_t *pcm = skip_bytes(&lc->cc, (length + 7) >> 3); + const uint8_t *pcm = skip_bytes(&lc->sub.cc, (length + 7) >> 3); int ret; if (!s->sh.disable_deblocking_filter_flag) @@ -2619,13 +2619,13 @@ static int hls_coding_unit(HEVCLocalContext *lc, const HEVCContext *s, x = y_cb * min_cb_width + x_cb; for (y = 0; y < length; y++) { - memset(&l->qp_y_tab[x], lc->qp_y, length); + memset(&l->qp_y_tab[x], lc->sub.qp_y, length); x += min_cb_width; } if(((x0 + (1<<log2_cb_size)) & qp_block_mask) == 0 && ((y0 + (1<<log2_cb_size)) & qp_block_mask) == 0) { - lc->qPy_pred = lc->qp_y; + lc->sub.qPy_pred = lc->sub.qp_y; } set_ct_depth(sps, l->tab_ct_depth, x0, y0, log2_cb_size, lc->ct_depth); @@ -2699,7 +2699,7 @@ static int hls_coding_quadtree(HEVCLocalContext *lc, if(((x0 + (1<<log2_cb_size)) & qp_block_mask) == 0 && ((y0 + (1<<log2_cb_size)) & qp_block_mask) == 0) - lc->qPy_pred = lc->qp_y; + lc->sub.qPy_pred = lc->sub.qp_y; if (more_data) return ((x1 + cb_size_split) < sps->width || @@ -2742,13 +2742,13 @@ static void hls_decode_neighbour(HEVCLocalContext *lc, if (pps->entropy_coding_sync_enabled_flag) { if (x_ctb == 0 && (y_ctb & (ctb_size - 1)) == 0) - lc->first_qp_group = 1; + lc->sub.first_qp_group = 1; lc->end_of_tiles_x = sps->width; } else if (pps->tiles_enabled_flag) { if (ctb_addr_ts && pps->tile_id[ctb_addr_ts] != pps->tile_id[ctb_addr_ts - 1]) { int idxX = pps->col_idxX[x_ctb >> sps->log2_ctb_size]; lc->end_of_tiles_x = x_ctb + (pps->column_width[idxX] << sps->log2_ctb_size); - lc->first_qp_group = 1; + lc->sub.first_qp_group = 1; } } else { lc->end_of_tiles_x = sps->width; @@ -2785,8 +2785,6 @@ static int hls_decode_entry(HEVCContext *s, GetBitContext *gb) const HEVCLayerContext *const l = &s->layers[s->cur_layer]; const HEVCPPS *const pps = s->pps; const HEVCSPS *const sps = pps->sps; - const uint8_t *slice_data = gb->buffer + s->sh.data_offset; - const size_t slice_size = get_bits_bytesize(gb, 1) - s->sh.data_offset; int ctb_size = 1 << sps->log2_ctb_size; int more_data = 1; int x_ctb = 0; @@ -2794,6 +2792,12 @@ static int hls_decode_entry(HEVCContext *s, GetBitContext *gb) int ctb_addr_ts = pps->ctb_addr_rs_to_ts[s->sh.slice_ctb_addr_rs]; int ret; + /* The slice segment is one buffer, so CABAC stays open across tile and + * WPP row boundaries. */ + lc->sub.data = gb->buffer + s->sh.data_offset; + lc->sub.size = get_bits_bytesize(gb, 1) - s->sh.data_offset; + lc->sub.opened = 0; + while (more_data && ctb_addr_ts < sps->ctb_size) { int ctb_addr_rs = pps->ctb_addr_ts_to_rs[ctb_addr_ts]; @@ -2801,7 +2805,7 @@ static int hls_decode_entry(HEVCContext *s, GetBitContext *gb) y_ctb = (ctb_addr_rs / ((sps->width + ctb_size - 1) >> sps->log2_ctb_size)) << sps->log2_ctb_size; hls_decode_neighbour(lc, l, pps, sps, x_ctb, y_ctb, ctb_addr_ts); - ret = ff_hevc_cabac_init(lc, pps, ctb_addr_ts, slice_data, slice_size, 0); + ret = ff_hevc_cabac_init(lc, pps, ctb_addr_ts); if (ret < 0) { l->tab_slice_address[ctb_addr_rs] = -1; return ret; @@ -2847,15 +2851,18 @@ static int hls_decode_entry_wpp(AVCodecContext *avctx, void *hevc_lclist, int ctb_addr_rs = s->sh.slice_ctb_addr_rs + ctb_row * ((sps->width + ctb_size - 1) >> sps->log2_ctb_size); int ctb_addr_ts = pps->ctb_addr_rs_to_ts[ctb_addr_rs]; - const uint8_t *data = s->data + s->sh.offset[ctb_row]; - const size_t data_size = s->sh.size[ctb_row]; - int progress = 0; int ret; + /* Substream of this row, opened at its first CTB */ + lc->sub.data = s->data + s->sh.offset[ctb_row]; + lc->sub.size = s->sh.size[ctb_row]; + lc->sub.opened = 0; + + /* Slices starting mid-row skip the initialization below */ if (ctb_row) - ff_init_cabac_decoder(&lc->cc, data, data_size); + ff_init_cabac_decoder(&lc->sub.cc, lc->sub.data, lc->sub.size); while(more_data && ctb_addr_ts < sps->ctb_size) { int x_ctb = (ctb_addr_rs % sps->ctb_width) << sps->log2_ctb_size; @@ -2875,7 +2882,7 @@ static int hls_decode_entry_wpp(AVCodecContext *avctx, void *hevc_lclist, return 0; } - ret = ff_hevc_cabac_init(lc, pps, ctb_addr_ts, data, data_size, 1); + ret = ff_hevc_cabac_init(lc, pps, ctb_addr_ts); if (ret < 0) goto error; hls_sao_param(lc, l, pps, sps, @@ -3052,8 +3059,8 @@ static int hls_slice_data_wpp(HEVCContext *s, const H2645NAL *nal) return res; for (unsigned i = 1; i < s->nb_local_ctx; i++) { - s->local_ctx[i].first_qp_group = 1; - s->local_ctx[i].qp_y = s->local_ctx[0].qp_y; + s->local_ctx[i].sub.first_qp_group = 1; + s->local_ctx[i].sub.qp_y = s->local_ctx[0].sub.qp_y; } atomic_store(&s->wpp_err, 0); @@ -3083,16 +3090,19 @@ static int hls_decode_entry_tile(AVCodecContext *avctx, void *hevc_lclist, const HEVCLayerContext *const l = &s->layers[s->cur_layer]; const HEVCPPS *const pps = s->pps; const HEVCSPS *const sps = pps->sps; - const uint8_t *data = s->data + s->sh.offset[job]; - const size_t data_size = s->sh.size[job]; /* the slice covers every tile, so job and tile are the same index */ int ctb_addr_ts = pps->ctb_addr_rs_to_ts[pps->row_bd[job / pps->num_tile_columns] * sps->ctb_width + pps->col_bd[job % pps->num_tile_columns]]; int more_data = 1, ret; - lc->tile_bs_defer = 1; - lc->tu.cu_qp_offset_cb = 0; - lc->tu.cu_qp_offset_cr = 0; + /* Substream of this tile, opened at its first CTB */ + lc->sub.data = s->data + s->sh.offset[job]; + lc->sub.size = s->sh.size[job]; + lc->sub.opened = 0; + + lc->tile_bs_defer = 1; + lc->sub.cu_qp_offset_cb = 0; + lc->sub.cu_qp_offset_cr = 0; /* hls_decode_neighbour() skips this for the first CTB of the picture */ lc->end_of_tiles_x = pps->col_bd[job % pps->num_tile_columns + 1] << sps->log2_ctb_size; @@ -3104,7 +3114,7 @@ static int hls_decode_entry_tile(AVCodecContext *avctx, void *hevc_lclist, hls_decode_neighbour(lc, l, pps, sps, x_ctb, y_ctb, ctb_addr_ts); - ret = ff_hevc_cabac_init(lc, pps, ctb_addr_ts, data, data_size, 1); + ret = ff_hevc_cabac_init(lc, pps, ctb_addr_ts); if (ret < 0) return ret; @@ -3143,8 +3153,8 @@ static int hls_slice_data_tiles(HEVCContext *s, const H2645NAL *nal) return res; for (unsigned i = 1; i < s->nb_local_ctx; i++) { - s->local_ctx[i].first_qp_group = 1; - s->local_ctx[i].qp_y = s->local_ctx[0].qp_y; + s->local_ctx[i].sub.first_qp_group = 1; + s->local_ctx[i].sub.qp_y = s->local_ctx[0].sub.qp_y; } for (ctb_addr_ts = start_ts; ctb_addr_ts < sps->ctb_size; ctb_addr_ts++) @@ -3231,13 +3241,13 @@ static int decode_slice_data(HEVCContext *s, const HEVCLayerContext *l, } } - s->local_ctx[0].first_qp_group = !s->sh.dependent_slice_segment_flag; + s->local_ctx[0].sub.first_qp_group = !s->sh.dependent_slice_segment_flag; if (!pps->cu_qp_delta_enabled_flag) - s->local_ctx[0].qp_y = s->sh.slice_qp; + s->local_ctx[0].sub.qp_y = s->sh.slice_qp; - s->local_ctx[0].tu.cu_qp_offset_cb = 0; - s->local_ctx[0].tu.cu_qp_offset_cr = 0; + s->local_ctx[0].sub.cu_qp_offset_cb = 0; + s->local_ctx[0].sub.cu_qp_offset_cr = 0; if (s->avctx->active_thread_type == FF_THREAD_SLICE && s->sh.num_entry_point_offsets > 0 && diff --git a/libavcodec/hevc/hevcdec.h b/libavcodec/hevc/hevcdec.h index 703b8df1af..b6116e74a3 100644 --- a/libavcodec/hevc/hevcdec.h +++ b/libavcodec/hevc/hevcdec.h @@ -341,8 +341,6 @@ typedef struct TransformUnit { int chroma_mode_c; uint8_t is_cu_qp_delta_coded; uint8_t is_cu_chroma_qp_offset_coded; - int8_t cu_qp_offset_cb; - int8_t cu_qp_offset_cr; uint8_t cross_pf; } TransformUnit; @@ -388,18 +386,31 @@ typedef struct HEVCFrame { uint8_t flags; } HEVCFrame; -typedef struct HEVCLocalContext { - uint8_t cabac_state[HEVC_CONTEXTS]; +/* State carried from one CTB to the next within a substream: one per tile + * column, or one per row for WPP. */ +typedef struct HEVCSubstream { + const uint8_t *data; ///< CABAC bytes of this substream + size_t size; + /* 0: open CABAC on data at first use, 1: already open, continue in it */ + uint8_t opened; + CABACContext cc; + uint8_t cabac_state[HEVC_CONTEXTS]; uint8_t stat_coeff[HEVC_STAT_COEFFS]; + int8_t qp_y; + int qPy_pred; uint8_t first_qp_group; + int8_t cu_qp_offset_cb; + int8_t cu_qp_offset_cr; +} HEVCSubstream; + +typedef struct HEVCLocalContext { + HEVCSubstream sub; void *logctx; const struct HEVCContext *parent; - CABACContext cc; - /** * This is a pointer to the common CABAC state. * In case entropy_coding_sync_enabled_flag is set, @@ -412,11 +423,6 @@ typedef struct HEVCLocalContext { */ HEVCCABACState *common_cabac_state; - int8_t qp_y; - int8_t curr_qp_y; - - int qPy_pred; - TransformUnit tu; uint8_t ctb_left_flag; @@ -615,8 +621,7 @@ int ff_hevc_slice_rpl(HEVCContext *s); void ff_hevc_save_states(HEVCLocalContext *lc, const HEVCPPS *pps, int ctb_addr_ts); int ff_hevc_cabac_init(HEVCLocalContext *lc, const HEVCPPS *pps, - int ctb_addr_ts, const uint8_t *data, size_t size, - int is_wpp); + int ctb_addr_ts); int ff_hevc_sao_merge_flag_decode(HEVCLocalContext *lc); int ff_hevc_sao_type_idx_decode(HEVCLocalContext *lc); int ff_hevc_sao_band_position_decode(HEVCLocalContext *lc); -- To stop receiving notification emails like this one, please contact [email protected]. _______________________________________________ ffmpeg-cvslog mailing list -- [email protected] To unsubscribe send an email to [email protected]
