[FFmpeg-devel,5/5] avcodec/hevc_ps: use the AVBufferPool API to allocate parameter set buffers

Submitted by James Almer on Jan. 20, 2018, 9:12 p.m.

Details

Message ID 20180120211253.9676-5-jamrial@gmail.com
State New
Headers show

Commit Message

James Almer Jan. 20, 2018, 9:12 p.m.
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(-)

Patch hide | download patch | download mbox

diff --git a/libavcodec/hevc_parser.c b/libavcodec/hevc_parser.c
index 09a203097b..8e4423263d 100644
--- a/libavcodec/hevc_parser.c
+++ b/libavcodec/hevc_parser.c
@@ -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,
 };
diff --git a/libavcodec/hevc_ps.c b/libavcodec/hevc_ps.c
index b18457296b..7d5195d667 100644
--- a/libavcodec/hevc_ps.c
+++ b/libavcodec/hevc_ps.c
@@ -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;
diff --git a/libavcodec/hevc_ps.h b/libavcodec/hevc_ps.h
index 871a58acc6..c05265a9be 100644
--- a/libavcodec/hevc_ps.h
+++ b/libavcodec/hevc_ps.h
@@ -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,
diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c
index 98a96defb7..a10bdf00cb 100644
--- a/libavcodec/hevcdec.c
+++ b/libavcodec/hevcdec.c
@@ -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;
diff --git a/libavcodec/mediacodecdec.c b/libavcodec/mediacodecdec.c
index b360e7a7f1..0c33a7041a 100644
--- a/libavcodec/mediacodecdec.c
+++ b/libavcodec/mediacodecdec.c
@@ -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) {