PR #22743 opened by James Almer (jamrial)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22743
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22743.patch

Should help reduce the amount of allocations where av_packet_alloc() is called 
repeatedly, as implemented for bsfs in this same PR.

This is similar to !22732


>From 9a3b547ea27fb71ef62d2a010e3cd074049f278f Mon Sep 17 00:00:00 2001
From: James Almer <[email protected]>
Date: Mon, 6 Apr 2026 23:42:33 -0300
Subject: [PATCH 1/3] avcodec/packet: use refstruct API to allocate packets

This is needed for the next commit.

Signed-off-by: James Almer <[email protected]>
---
 libavcodec/packet.c | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/libavcodec/packet.c b/libavcodec/packet.c
index 348159f7f7..06c94eb347 100644
--- a/libavcodec/packet.c
+++ b/libavcodec/packet.c
@@ -27,6 +27,7 @@
 #include "libavutil/mathematics.h"
 #include "libavutil/mem.h"
 #include "libavutil/rational.h"
+#include "libavutil/refstruct.h"
 
 #include "defs.h"
 #include "packet.h"
@@ -60,9 +61,17 @@ static void get_packet_defaults(AVPacket *pkt)
     pkt->time_base       = av_make_q(0, 1);
 }
 
+static void packet_unref(AVRefStructOpaque opaque, void *obj)
+{
+    AVPacket *pkt = obj;
+
+    av_packet_unref(pkt);
+}
+
 AVPacket *av_packet_alloc(void)
 {
-    AVPacket *pkt = av_malloc(sizeof(AVPacket));
+    AVPacket *pkt = av_refstruct_alloc_ext(sizeof(*pkt), 
AV_REFSTRUCT_FLAG_NO_ZEROING,
+                                           NULL, packet_unref);
     if (!pkt)
         return pkt;
 
@@ -76,8 +85,7 @@ void av_packet_free(AVPacket **pkt)
     if (!pkt || !*pkt)
         return;
 
-    av_packet_unref(*pkt);
-    av_freep(pkt);
+    av_refstruct_unref(pkt);
 }
 
 static int packet_alloc(AVBufferRef **buf, int size)
-- 
2.52.0


>From 11119e3f02e8992d6e178f9c43d35b0ed9372304 Mon Sep 17 00:00:00 2001
From: James Almer <[email protected]>
Date: Mon, 6 Apr 2026 23:45:03 -0300
Subject: [PATCH 2/3] avcodec/packet: add an API to allocate a pool of AVPacket

Should help reduce the amount of allocations where av_packet_alloc() is called
repeatedly.

Signed-off-by: James Almer <[email protected]>
---
 libavcodec/packet.c | 29 +++++++++++++++++++++++++++++
 libavcodec/packet.h | 33 +++++++++++++++++++++++++++++++++
 2 files changed, 62 insertions(+)

diff --git a/libavcodec/packet.c b/libavcodec/packet.c
index 06c94eb347..c6cbd14c5b 100644
--- a/libavcodec/packet.c
+++ b/libavcodec/packet.c
@@ -749,6 +749,35 @@ void av_packet_side_data_free(AVPacketSideData **psd, int 
*pnb_sd)
     *pnb_sd = 0;
 }
 
+static av_cold int packet_pool_init_cb(AVRefStructOpaque opaque, void *obj)
+{
+    AVPacket *pkt = obj;
+
+    get_packet_defaults(pkt);
+
+    return 0;
+}
+
+AVPacket *av_packet_pool_get(AVPacketPool *pool)
+{
+    return av_refstruct_pool_get((AVRefStructPool *)pool);
+}
+
+AVPacketPool *av_packet_pool_alloc(void)
+{
+    return (AVPacketPool *)
+        av_refstruct_pool_alloc_ext(sizeof(AVPacket),
+                                    AV_REFSTRUCT_POOL_FLAG_NO_ZEROING, NULL,
+                                    packet_pool_init_cb,
+                                    packet_unref,
+                                    NULL, NULL);
+}
+
+void av_packet_pool_uninit(AVPacketPool **poolp)
+{
+    av_refstruct_pool_uninit((AVRefStructPool **)poolp);
+}
+
 static void *container_packet_alloc(void *opaque)
 {
     return av_packet_alloc();
diff --git a/libavcodec/packet.h b/libavcodec/packet.h
index 59bfddf4cc..66d1fc68da 100644
--- a/libavcodec/packet.h
+++ b/libavcodec/packet.h
@@ -916,6 +916,39 @@ int av_packet_make_refcounted(AVPacket *pkt);
  */
 int av_packet_make_writable(AVPacket *pkt);
 
+typedef struct AVPacketPool AVPacketPool;
+
+/**
+ * Allocate a pool of AVPacket. The resulting pool must be uninitialized
+ * using @ref av_packet_pool_uninit() once it's no longer needed.
+ *
+ * AVPacket must be fetched with @ref av_packet_pool_get().
+ */
+AVPacketPool *av_packet_pool_alloc(void);
+
+/**
+ * Get an AVPacket from a pool and set its fields to default values. The 
structs
+ * behave as if they were freshly allocated by @ref av_packet_alloc(), and must
+ * be freed using @ref av_packet_free().
+ *
+ * @see av_packet_pool_alloc()
+ * @return An AVPacket filled with default values or NULL on failure.
+ */
+AVPacket *av_packet_pool_get(AVPacketPool *pool);
+
+/**
+ * Mark the pool as being available for freeing. It will actually be freed
+ * only once all the allocated packets associated with the pool are released.
+ * Thus it is safe to call this function while some of the allocated packets
+ * are still in use.
+ *
+ * It is illegal to try to get a new entry after this function has been called.
+ *
+ * @param poolp pointer to a pointer to either NULL or a pool to be freed.
+ *              `*poolp` will be set to NULL.
+ */
+void av_packet_pool_uninit(AVPacketPool **poolp);
+
 /**
  * Convert valid timing fields (timestamps / durations) in a packet from one
  * timebase to another. Timestamps with unknown values (AV_NOPTS_VALUE) will be
-- 
2.52.0


>From 048274e21b75e22e5185965cb5373db7412bed18 Mon Sep 17 00:00:00 2001
From: James Almer <[email protected]>
Date: Mon, 6 Apr 2026 23:45:32 -0300
Subject: [PATCH 3/3] avcodec/bsf: use av_packet_pool_alloc() to allocate
 AVPacket

Signed-off-by: James Almer <[email protected]>
---
 libavcodec/bsf.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/libavcodec/bsf.c b/libavcodec/bsf.c
index 1e710f7d4a..cd43b6fdbe 100644
--- a/libavcodec/bsf.c
+++ b/libavcodec/bsf.c
@@ -41,6 +41,7 @@ static av_always_inline const FFBitStreamFilter *ff_bsf(const 
AVBitStreamFilter
 typedef struct FFBSFContext {
     AVBSFContext pub;
     AVPacket *buffer_pkt;
+    AVPacketPool *pool;
     int eof;
 } FFBSFContext;
 
@@ -67,6 +68,7 @@ void av_bsf_free(AVBSFContext **pctx)
         av_freep(&ctx->priv_data);
     }
     av_packet_free(&bsfi->buffer_pkt);
+    av_packet_pool_uninit(&bsfi->pool);
 
     avcodec_parameters_free(&ctx->par_in);
     avcodec_parameters_free(&ctx->par_out);
@@ -133,7 +135,13 @@ int av_bsf_alloc(const AVBitStreamFilter *filter, 
AVBSFContext **pctx)
             av_opt_set_defaults(ctx->priv_data);
         }
     }
-    bsfi->buffer_pkt = av_packet_alloc();
+    bsfi->pool = av_packet_pool_alloc();
+    if (!bsfi->pool) {
+        ret = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    bsfi->buffer_pkt = av_packet_pool_get(bsfi->pool);
     if (!bsfi->buffer_pkt) {
         ret = AVERROR(ENOMEM);
         goto fail;
@@ -243,7 +251,7 @@ int ff_bsf_get_packet(AVBSFContext *ctx, AVPacket **pkt)
     if (AVPACKET_IS_EMPTY(bsfi->buffer_pkt))
         return AVERROR(EAGAIN);
 
-    tmp_pkt = av_packet_alloc();
+    tmp_pkt = av_packet_pool_get(bsfi->pool);
     if (!tmp_pkt)
         return AVERROR(ENOMEM);
 
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to