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]
