@@ -353,6 +353,13 @@ static int hevc_split(AVCodecContext *avctx, const uint8_t *buf, int buf_size)
return 0;
}
+static av_cold int hevc_parser_init(AVCodecParserContext *s)
+{
+ HEVCParserContext *ctx = s->priv_data;
+
+ return ff_hevc_init_parameter_sets(&ctx->ps);
+}
+
static void hevc_parser_close(AVCodecParserContext *s)
{
HEVCParserContext *ctx = s->priv_data;
@@ -368,6 +375,7 @@ AVCodecParser ff_hevc_parser = {
.codec_ids = { AV_CODEC_ID_HEVC },
.priv_data_size = sizeof(HEVCParserContext),
.parser_parse = hevc_parse,
+ .parser_init = hevc_parser_init,
.parser_close = hevc_parser_close,
.split = hevc_split,
};
@@ -420,7 +420,7 @@ int ff_hevc_decode_nal_vps(GetBitContext *gb, AVCodecContext *avctx,
int vps_id = 0;
ptrdiff_t nal_size;
HEVCVPS *vps;
- AVBufferRef *vps_buf = av_buffer_allocz(sizeof(*vps));
+ AVBufferRef *vps_buf = av_buffer_pool_get(ps->vps_pool);
if (!vps_buf)
return AVERROR(ENOMEM);
@@ -1218,11 +1218,11 @@ int ff_hevc_parse_sps(HEVCSPS *sps, GetBitContext *gb, unsigned int *sps_id,
int ff_hevc_decode_nal_sps(GetBitContext *gb, AVCodecContext *avctx,
HEVCParamSets *ps, int apply_defdispwin)
{
- HEVCSPS *sps;
- AVBufferRef *sps_buf = av_buffer_allocz(sizeof(*sps));
unsigned int sps_id;
int ret;
ptrdiff_t nal_size;
+ HEVCSPS *sps;
+ AVBufferRef *sps_buf = av_buffer_pool_get(ps->sps_pool);
if (!sps_buf)
return AVERROR(ENOMEM);
@@ -1291,6 +1291,21 @@ static void hevc_pps_free(void *opaque, uint8_t *data)
av_freep(&pps);
}
+static AVBufferRef *hevc_pps_alloc(void *opaque, int size)
+{
+ AVBufferRef *buf;
+ uint8_t *data = av_mallocz(size);
+
+ if (!data)
+ return NULL;
+
+ buf = av_buffer_create(data, size, hevc_pps_free, NULL, 0);
+ if (!buf)
+ av_free(data);
+
+ return buf;
+}
+
static int pps_range_extensions(GetBitContext *gb, AVCodecContext *avctx,
HEVCPPS *pps, HEVCSPS *sps) {
int i;
@@ -1467,19 +1482,12 @@ int ff_hevc_decode_nal_pps(GetBitContext *gb, AVCodecContext *avctx,
unsigned int pps_id = 0;
ptrdiff_t nal_size;
unsigned log2_parallel_merge_level_minus2;
+ HEVCPPS *pps;
+ AVBufferRef *pps_buf = av_buffer_pool_get(ps->pps_pool);
- AVBufferRef *pps_buf;
- HEVCPPS *pps = av_mallocz(sizeof(*pps));
-
- if (!pps)
- return AVERROR(ENOMEM);
-
- pps_buf = av_buffer_create((uint8_t *)pps, sizeof(*pps),
- hevc_pps_free, NULL, 0);
- if (!pps_buf) {
- av_freep(&pps);
+ if (!pps_buf)
return AVERROR(ENOMEM);
- }
+ pps = (HEVCPPS*)pps_buf->data;
av_log(avctx, AV_LOG_DEBUG, "Decoding PPS\n");
@@ -1704,6 +1712,23 @@ err:
return ret;
}
+int ff_hevc_init_parameter_sets(HEVCParamSets *ps)
+{
+ ps->vps_pool = av_buffer_pool_init (sizeof(*ps->vps), av_buffer_allocz);
+ ps->sps_pool = av_buffer_pool_init (sizeof(*ps->sps), av_buffer_allocz);
+ ps->pps_pool = av_buffer_pool_init2(sizeof(*ps->pps), NULL, hevc_pps_alloc, NULL);
+
+ if (!ps->vps_pool || !ps->sps_pool || !ps->pps_pool) {
+ av_buffer_pool_uninit(&ps->vps_pool);
+ av_buffer_pool_uninit(&ps->sps_pool);
+ av_buffer_pool_uninit(&ps->pps_pool);
+
+ return AVERROR(ENOMEM);
+ }
+
+ return 0;
+}
+
void ff_hevc_uninit_parameter_sets(HEVCParamSets *ps)
{
int i;
@@ -1715,6 +1740,10 @@ void ff_hevc_uninit_parameter_sets(HEVCParamSets *ps)
for (i = 0; i < FF_ARRAY_ELEMS(ps->pps_list); i++)
av_buffer_unref(&ps->pps_list[i]);
+ av_buffer_pool_uninit(&ps->vps_pool);
+ av_buffer_pool_uninit(&ps->sps_pool);
+ av_buffer_pool_uninit(&ps->pps_pool);
+
ps->sps = NULL;
ps->pps = NULL;
ps->vps = NULL;
@@ -392,6 +392,10 @@ typedef struct HEVCPPS {
} HEVCPPS;
typedef struct HEVCParamSets {
+ AVBufferPool *vps_pool;
+ AVBufferPool *sps_pool;
+ AVBufferPool *pps_pool;
+
AVBufferRef *vps_list[HEVC_MAX_VPS_COUNT];
AVBufferRef *sps_list[HEVC_MAX_SPS_COUNT];
AVBufferRef *pps_list[HEVC_MAX_PPS_COUNT];
@@ -421,6 +425,8 @@ int ff_hevc_decode_nal_sps(GetBitContext *gb, AVCodecContext *avctx,
int ff_hevc_decode_nal_pps(GetBitContext *gb, AVCodecContext *avctx,
HEVCParamSets *ps);
+int ff_hevc_init_parameter_sets(HEVCParamSets *ps);
+
void ff_hevc_uninit_parameter_sets(HEVCParamSets *ps);
int ff_hevc_decode_short_term_rps(GetBitContext *gb, AVCodecContext *avctx,
@@ -3312,6 +3312,9 @@ static av_cold int hevc_init_context(AVCodecContext *avctx)
s->HEVClcList[0] = s->HEVClc;
s->sList[0] = s;
+ if (ff_hevc_init_parameter_sets(&s->ps) < 0)
+ goto fail;
+
s->cabac_state = av_malloc(HEVC_CONTEXTS);
if (!s->cabac_state)
goto fail;
@@ -202,6 +202,10 @@ static int hevc_set_extradata(AVCodecContext *avctx, FFAMediaFormat *format)
memset(&ps, 0, sizeof(ps));
memset(&sei, 0, sizeof(sei));
+ ret = ff_hevc_init_parameter_sets(&ps);
+ if (ret < 0)
+ goto done;
+
ret = ff_hevc_decode_extradata(avctx->extradata, avctx->extradata_size,
&ps, &sei, &is_nalff, &nal_length_size, 0, 1, avctx);
if (ret < 0) {
Signed-off-by: James Almer <jamrial@gmail.com> --- I don't know if this brings many benefits. With up to 16 sps/vps and 64 pps, plus the fact all three ff_hevc_decode_nal_* functions allocate a buffer even if the result will not be added to the HEVCParamSets list, it may considerably reduce the amount of buffer allocations on raw streams where parameter sets are repeated on every keyframe, but i can't say if it will have a noticeable effect in performance. libavcodec/hevc_parser.c | 8 +++++++ libavcodec/hevc_ps.c | 57 ++++++++++++++++++++++++++++++++++------------ libavcodec/hevc_ps.h | 6 +++++ libavcodec/hevcdec.c | 3 +++ libavcodec/mediacodecdec.c | 4 ++++ 5 files changed, 64 insertions(+), 14 deletions(-)