You've already forked FFmpeg
mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-08-15 14:13:16 +02:00
avcodec/hevcdec: Avoid allocation of common CABAC state
It used to be allocated separately, so that the pointer to it is copied to all HEVCContexts, so that all slice-threads use the same. This is completely unnecessary now that there is only one HEVCContext any more. There is just one minor complication left: The slice-threads only get a pointer to const HEVCContext, but they need to modify the common CABAC state. Fix this by adding a pointer to the common CABAC state to HEVCLocalContext and document why it exists. Reviewed-by: Anton Khirnov <anton@khirnov.net> Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
This commit is contained in:
@@ -455,18 +455,18 @@ void ff_hevc_save_states(HEVCLocalContext *lc, int ctb_addr_ts)
|
|||||||
(ctb_addr_ts % s->ps.sps->ctb_width == 2 ||
|
(ctb_addr_ts % s->ps.sps->ctb_width == 2 ||
|
||||||
(s->ps.sps->ctb_width == 2 &&
|
(s->ps.sps->ctb_width == 2 &&
|
||||||
ctb_addr_ts % s->ps.sps->ctb_width == 0))) {
|
ctb_addr_ts % s->ps.sps->ctb_width == 0))) {
|
||||||
memcpy(s->cabac->state, lc->cabac_state, HEVC_CONTEXTS);
|
memcpy(lc->common_cabac_state->state, lc->cabac_state, HEVC_CONTEXTS);
|
||||||
if (s->ps.sps->persistent_rice_adaptation_enabled_flag) {
|
if (s->ps.sps->persistent_rice_adaptation_enabled_flag) {
|
||||||
memcpy(s->cabac->stat_coeff, lc->stat_coeff, HEVC_STAT_COEFFS);
|
memcpy(lc->common_cabac_state->stat_coeff, lc->stat_coeff, HEVC_STAT_COEFFS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void load_states(HEVCLocalContext *lc, const HEVCContext *s)
|
static void load_states(HEVCLocalContext *lc, const HEVCContext *s)
|
||||||
{
|
{
|
||||||
memcpy(lc->cabac_state, s->cabac->state, HEVC_CONTEXTS);
|
memcpy(lc->cabac_state, lc->common_cabac_state->state, HEVC_CONTEXTS);
|
||||||
if (s->ps.sps->persistent_rice_adaptation_enabled_flag) {
|
if (s->ps.sps->persistent_rice_adaptation_enabled_flag) {
|
||||||
memcpy(lc->stat_coeff, s->cabac->stat_coeff, HEVC_STAT_COEFFS);
|
memcpy(lc->stat_coeff, lc->common_cabac_state->stat_coeff, HEVC_STAT_COEFFS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -2653,6 +2653,7 @@ static int hls_slice_data_wpp(HEVCContext *s, const H2645NAL *nal)
|
|||||||
return AVERROR(ENOMEM);
|
return AVERROR(ENOMEM);
|
||||||
s->HEVClcList[i]->logctx = s->avctx;
|
s->HEVClcList[i]->logctx = s->avctx;
|
||||||
s->HEVClcList[i]->parent = s;
|
s->HEVClcList[i]->parent = s;
|
||||||
|
s->HEVClcList[i]->common_cabac_state = &s->cabac;
|
||||||
}
|
}
|
||||||
|
|
||||||
offset = (lc->gb.index >> 3);
|
offset = (lc->gb.index >> 3);
|
||||||
@@ -3582,8 +3583,6 @@ static av_cold int hevc_decode_free(AVCodecContext *avctx)
|
|||||||
|
|
||||||
av_freep(&s->md5_ctx);
|
av_freep(&s->md5_ctx);
|
||||||
|
|
||||||
av_freep(&s->cabac);
|
|
||||||
|
|
||||||
for (i = 0; i < 3; i++) {
|
for (i = 0; i < 3; i++) {
|
||||||
av_freep(&s->sao_pixel_buffer_h[i]);
|
av_freep(&s->sao_pixel_buffer_h[i]);
|
||||||
av_freep(&s->sao_pixel_buffer_v[i]);
|
av_freep(&s->sao_pixel_buffer_v[i]);
|
||||||
@@ -3630,12 +3629,9 @@ static av_cold int hevc_init_context(AVCodecContext *avctx)
|
|||||||
return AVERROR(ENOMEM);
|
return AVERROR(ENOMEM);
|
||||||
s->HEVClc->parent = s;
|
s->HEVClc->parent = s;
|
||||||
s->HEVClc->logctx = avctx;
|
s->HEVClc->logctx = avctx;
|
||||||
|
s->HEVClc->common_cabac_state = &s->cabac;
|
||||||
s->HEVClcList[0] = s->HEVClc;
|
s->HEVClcList[0] = s->HEVClc;
|
||||||
|
|
||||||
s->cabac = av_malloc(sizeof(*s->cabac));
|
|
||||||
if (!s->cabac)
|
|
||||||
return AVERROR(ENOMEM);
|
|
||||||
|
|
||||||
s->output_frame = av_frame_alloc();
|
s->output_frame = av_frame_alloc();
|
||||||
if (!s->output_frame)
|
if (!s->output_frame)
|
||||||
return AVERROR(ENOMEM);
|
return AVERROR(ENOMEM);
|
||||||
|
@@ -439,6 +439,18 @@ typedef struct HEVCLocalContext {
|
|||||||
GetBitContext gb;
|
GetBitContext gb;
|
||||||
CABACContext cc;
|
CABACContext cc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a pointer to the common CABAC state.
|
||||||
|
* In case entropy_coding_sync_enabled_flag is set,
|
||||||
|
* the CABAC state after decoding the second CTU in a row is
|
||||||
|
* stored here and used to initialize the CABAC state before
|
||||||
|
* decoding the first CTU in the next row.
|
||||||
|
* This is the basis for WPP and in case slice-threading is used,
|
||||||
|
* the next row is decoded by another thread making this state
|
||||||
|
* shared between threads.
|
||||||
|
*/
|
||||||
|
HEVCCABACState *common_cabac_state;
|
||||||
|
|
||||||
int8_t qp_y;
|
int8_t qp_y;
|
||||||
int8_t curr_qp_y;
|
int8_t curr_qp_y;
|
||||||
|
|
||||||
@@ -485,8 +497,6 @@ typedef struct HEVCContext {
|
|||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
|
|
||||||
HEVCCABACState *cabac;
|
|
||||||
|
|
||||||
/** 1 if the independent slice segment header was successfully parsed */
|
/** 1 if the independent slice segment header was successfully parsed */
|
||||||
uint8_t slice_initialized;
|
uint8_t slice_initialized;
|
||||||
|
|
||||||
@@ -559,6 +569,9 @@ typedef struct HEVCContext {
|
|||||||
uint16_t seq_decode;
|
uint16_t seq_decode;
|
||||||
uint16_t seq_output;
|
uint16_t seq_output;
|
||||||
|
|
||||||
|
/** The target for the common_cabac_state of the local contexts. */
|
||||||
|
HEVCCABACState cabac;
|
||||||
|
|
||||||
int enable_parallel_tiles;
|
int enable_parallel_tiles;
|
||||||
atomic_int wpp_err;
|
atomic_int wpp_err;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user