Commit 0fb9bceab1 for ffmpeg
commit 0fb9bceab1d953739431010cff778d8188107924
Author: YoungSoo Lee <youngsoo.lee@navercorp.com>
Date: Fri Aug 21 10:46:32 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 <youngsoo.lee@navercorp.com>
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);