PR #22822 opened by mkver URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22822 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22822.patch
>From 8ae06df5cf512b51d2eca1498b0932b1f2f07e44 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <[email protected]> Date: Wed, 15 Apr 2026 14:49:56 +0200 Subject: [PATCH 1/8] avcodec/lcevcdec: Use pool to avoid allocations of FFLCEVCFrame Signed-off-by: Andreas Rheinhardt <[email protected]> --- libavcodec/decode.c | 10 ++-------- libavcodec/lcevcdec.c | 39 ++++++++++++++++++++++++++++++++++++--- libavcodec/lcevcdec.h | 1 + 3 files changed, 39 insertions(+), 11 deletions(-) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 206b711390..892f6fce1d 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -1726,16 +1726,10 @@ int ff_attach_decode_data(AVCodecContext *avctx, AVFrame *frame) return 0; } - frame_ctx = av_mallocz(sizeof(*frame_ctx)); + frame_ctx = av_refstruct_pool_get(dc->lcevc.ctx->frame_pool); if (!frame_ctx) return AVERROR(ENOMEM); - frame_ctx->frame = av_frame_alloc(); - if (!frame_ctx->frame) { - av_free(frame_ctx); - return AVERROR(ENOMEM); - } - frame_ctx->lcevc = av_refstruct_ref(dc->lcevc.ctx); frame_ctx->frame->width = dc->lcevc.width; frame_ctx->frame->height = dc->lcevc.height; @@ -1747,7 +1741,7 @@ int ff_attach_decode_data(AVCodecContext *avctx, AVFrame *frame) ret = avctx->get_buffer2(avctx, frame_ctx->frame, 0); if (ret < 0) { - ff_lcevc_unref(frame_ctx); + av_refstruct_unref(&frame_ctx); return ret; } diff --git a/libavcodec/lcevcdec.c b/libavcodec/lcevcdec.c index 013cae9147..70e6733909 100644 --- a/libavcodec/lcevcdec.c +++ b/libavcodec/lcevcdec.c @@ -300,9 +300,35 @@ static void lcevc_free(AVRefStructOpaque unused, void *obj) ff_cbs_fragment_free(lcevc->frag); av_freep(&lcevc->frag); ff_cbs_close(&lcevc->cbc); + av_refstruct_pool_uninit(&lcevc->frame_pool); memset(lcevc, 0, sizeof(*lcevc)); } +static av_cold int lcevc_frame_init_cb(AVRefStructOpaque unused, void *obj) +{ + FFLCEVCFrame *frame = obj; + + frame->frame = av_frame_alloc(); + if (!frame->frame) + return AVERROR(ENOMEM); + return 0; +} + +static void lcevc_frame_reset_cb(AVRefStructOpaque unused, void *obj) +{ + FFLCEVCFrame *frame = obj; + + av_frame_unref(frame->frame); + av_refstruct_unref(&frame->lcevc); +} + +static av_cold void lcevc_frame_free_entry_cb(AVRefStructOpaque unused, void *obj) +{ + FFLCEVCFrame *frame = obj; + + av_frame_free(&frame->frame); +} + static int lcevc_init(FFLCEVCContext *lcevc, void *logctx) { LCEVC_AccelContextHandle dummy = { 0 }; @@ -423,6 +449,15 @@ int ff_lcevc_alloc(FFLCEVCContext **plcevc, void *logctx) lcevc->cbc->decompose_unit_types = decompose_unit_types; lcevc->cbc->nb_decompose_unit_types = FF_ARRAY_ELEMS(decompose_unit_types); + lcevc->frame_pool = av_refstruct_pool_alloc_ext(sizeof(FFLCEVCFrame), 0, NULL, + lcevc_frame_init_cb, + lcevc_frame_reset_cb, + lcevc_frame_free_entry_cb, NULL); + if (!lcevc->frame_pool) { + ret = AVERROR(ENOMEM); + goto fail; + } + *plcevc = lcevc; return 0; fail: @@ -433,7 +468,5 @@ fail: void ff_lcevc_unref(void *opaque) { FFLCEVCFrame *lcevc = opaque; - av_refstruct_unref(&lcevc->lcevc); - av_frame_free(&lcevc->frame); - av_free(opaque); + av_refstruct_unref(&lcevc); } diff --git a/libavcodec/lcevcdec.h b/libavcodec/lcevcdec.h index 0a255d2951..5aed07f999 100644 --- a/libavcodec/lcevcdec.h +++ b/libavcodec/lcevcdec.h @@ -35,6 +35,7 @@ typedef struct FFLCEVCContext { LCEVC_DecoderHandle decoder; struct CodedBitstreamContext *cbc; struct CodedBitstreamFragment *frag; + struct AVRefStructPool *frame_pool; ///< pool of FFLCEVCFrame int initialized; } FFLCEVCContext; -- 2.52.0 >From 0e78b552d2341bdf1a096184ed58eac9f0a45e50 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <[email protected]> Date: Wed, 15 Apr 2026 15:02:04 +0200 Subject: [PATCH 2/8] avcodec/decode: Make post_process_opaque a RefStruct reference Avoids the post_process_opaque_free callback; the only user of this is already a RefStruct reference and presumably other users would want to use a pool for this, too, so they would use RefStruct-objects, too. Signed-off-by: Andreas Rheinhardt <[email protected]> --- libavcodec/decode.c | 4 +--- libavcodec/decode.h | 3 +-- libavcodec/lcevcdec.c | 6 ------ libavcodec/lcevcdec.h | 2 +- 4 files changed, 3 insertions(+), 12 deletions(-) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 892f6fce1d..b7392cae23 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -1676,8 +1676,7 @@ static void decode_data_free(AVRefStructOpaque unused, void *obj) { FrameDecodeData *fdd = obj; - if (fdd->post_process_opaque_free) - fdd->post_process_opaque_free(fdd->post_process_opaque); + av_refstruct_unref(&fdd->post_process_opaque); if (fdd->hwaccel_priv_free) fdd->hwaccel_priv_free(fdd->hwaccel_priv); @@ -1748,7 +1747,6 @@ int ff_attach_decode_data(AVCodecContext *avctx, AVFrame *frame) validate_avframe_allocation(avctx, frame_ctx->frame); fdd->post_process_opaque = frame_ctx; - fdd->post_process_opaque_free = ff_lcevc_unref; fdd->post_process = ff_lcevc_process; } dc->lcevc.frame = 0; diff --git a/libavcodec/decode.h b/libavcodec/decode.h index 5a7ab64c29..b4ae0ba8fe 100644 --- a/libavcodec/decode.h +++ b/libavcodec/decode.h @@ -42,8 +42,7 @@ typedef struct FrameDecodeData { * stored in the post_process_opaque object. */ int (*post_process)(void *logctx, AVFrame *frame); - void *post_process_opaque; - void (*post_process_opaque_free)(void *opaque); + void *post_process_opaque; ///< RefStruct reference /** * Per-frame private data for hwaccels. diff --git a/libavcodec/lcevcdec.c b/libavcodec/lcevcdec.c index 70e6733909..3aba6f6aeb 100644 --- a/libavcodec/lcevcdec.c +++ b/libavcodec/lcevcdec.c @@ -464,9 +464,3 @@ fail: av_refstruct_unref(&lcevc); return ret; } - -void ff_lcevc_unref(void *opaque) -{ - FFLCEVCFrame *lcevc = opaque; - av_refstruct_unref(&lcevc); -} diff --git a/libavcodec/lcevcdec.h b/libavcodec/lcevcdec.h index 5aed07f999..3120f423d1 100644 --- a/libavcodec/lcevcdec.h +++ b/libavcodec/lcevcdec.h @@ -50,5 +50,5 @@ int ff_lcevc_alloc(FFLCEVCContext **plcevc, void *logctx); int ff_lcevc_process(void *logctx, struct AVFrame *frame); int ff_lcevc_parse_frame(FFLCEVCContext *lcevc, const struct AVFrame *frame, enum AVPixelFormat *format, int *width, int *height, void *logctx); -void ff_lcevc_unref(void *opaque); + #endif /* AVCODEC_LCEVCDEC_H */ -- 2.52.0 >From f9a3f4440b64c6922b513161da150d0e76f83dba Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <[email protected]> Date: Wed, 15 Apr 2026 15:06:00 +0200 Subject: [PATCH 3/8] avcodec/decode: Remove always-true checks dc->lcevc.ctx is only != NULL for video. Signed-off-by: Andreas Rheinhardt <[email protected]> --- libavcodec/decode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index b7392cae23..c1f3d6d6d9 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -1626,7 +1626,7 @@ int ff_decode_frame_props(AVCodecContext *avctx, AVFrame *frame) AVCodecInternal *avci = avctx->internal; DecodeContext *dc = decode_ctx(avci); - dc->lcevc.frame = dc->lcevc.ctx && avctx->codec_type == AVMEDIA_TYPE_VIDEO && + dc->lcevc.frame = dc->lcevc.ctx && av_frame_get_side_data(frame, AV_FRAME_DATA_LCEVC); if (dc->lcevc.frame) { @@ -1700,7 +1700,7 @@ int ff_attach_decode_data(AVCodecContext *avctx, AVFrame *frame) DecodeContext *dc = decode_ctx(avci); if (!dc->lcevc.frame) { - dc->lcevc.frame = dc->lcevc.ctx && avctx->codec_type == AVMEDIA_TYPE_VIDEO && + dc->lcevc.frame = dc->lcevc.ctx && av_frame_get_side_data(frame, AV_FRAME_DATA_LCEVC); if (dc->lcevc.frame) { -- 2.52.0 >From ac6ccbee9190bc9715f6111cf30115cf7178cd6a Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <[email protected]> Date: Wed, 15 Apr 2026 15:10:18 +0200 Subject: [PATCH 4/8] avcodec/decode: Optimize call away if possible post_process_opaque is only used by LCEVC, so it is unused on most builds. Signed-off-by: Andreas Rheinhardt <[email protected]> --- libavcodec/decode.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index c1f3d6d6d9..735ee3bf91 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -1676,7 +1676,10 @@ static void decode_data_free(AVRefStructOpaque unused, void *obj) { FrameDecodeData *fdd = obj; - av_refstruct_unref(&fdd->post_process_opaque); + if (CONFIG_LIBLCEVC_DEC) + av_refstruct_unref(&fdd->post_process_opaque); + else + av_assert1(!fdd->post_process_opaque); if (fdd->hwaccel_priv_free) fdd->hwaccel_priv_free(fdd->hwaccel_priv); -- 2.52.0 >From a882ccbefc2216d5367d7aef37ed2dada4fd050b Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <[email protected]> Date: Wed, 15 Apr 2026 15:12:54 +0200 Subject: [PATCH 5/8] avcodec/decode: Fix shadowing Signed-off-by: Andreas Rheinhardt <[email protected]> --- libavcodec/decode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 735ee3bf91..a49395c9b3 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -1570,7 +1570,7 @@ int ff_decode_frame_props_from_pkt(const AVCodecContext *avctx, } if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { - int ret = av_buffer_replace(&frame->opaque_ref, pkt->opaque_ref); + ret = av_buffer_replace(&frame->opaque_ref, pkt->opaque_ref); if (ret < 0) return ret; frame->opaque = pkt->opaque; @@ -1630,7 +1630,7 @@ int ff_decode_frame_props(AVCodecContext *avctx, AVFrame *frame) av_frame_get_side_data(frame, AV_FRAME_DATA_LCEVC); if (dc->lcevc.frame) { - int ret = ff_lcevc_parse_frame(dc->lcevc.ctx, frame, &dc->lcevc.format, + ret = ff_lcevc_parse_frame(dc->lcevc.ctx, frame, &dc->lcevc.format, &dc->lcevc.width, &dc->lcevc.height, avctx); if (ret < 0 && (avctx->err_recognition & AV_EF_EXPLODE)) return ret; -- 2.52.0 >From 629b68d41ec6d04511c061922846ed47b2c37c73 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <[email protected]> Date: Wed, 15 Apr 2026 15:58:48 +0200 Subject: [PATCH 6/8] avcodec/decode: Avoid temporary frame in ff_reget_buffer() Signed-off-by: Andreas Rheinhardt <[email protected]> --- libavcodec/decode.c | 39 +++++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index a49395c9b3..7ad3077521 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -18,6 +18,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include <assert.h> #include <stdint.h> #include <stdbool.h> #include <string.h> @@ -1833,7 +1834,6 @@ fail: static int reget_buffer_internal(AVCodecContext *avctx, AVFrame *frame, int flags) { - AVFrame *tmp; int ret; av_assert0(avctx->codec_type == AVMEDIA_TYPE_VIDEO); @@ -1855,22 +1855,37 @@ static int reget_buffer_internal(AVCodecContext *avctx, AVFrame *frame, int flag if ((flags & FF_REGET_BUFFER_FLAG_READONLY) || av_frame_is_writable(frame)) return ff_decode_frame_props(avctx, frame); - tmp = av_frame_alloc(); - if (!tmp) - return AVERROR(ENOMEM); + uint8_t *data[AV_VIDEO_MAX_PLANES]; + AVBufferRef *buf[AV_VIDEO_MAX_PLANES]; + int linesize[AV_VIDEO_MAX_PLANES]; - av_frame_move_ref(tmp, frame); + static_assert(AV_VIDEO_MAX_PLANES <= FF_ARRAY_ELEMS(frame->data) && + AV_VIDEO_MAX_PLANES <= FF_ARRAY_ELEMS(frame->buf) && + AV_VIDEO_MAX_PLANES <= FF_ARRAY_ELEMS(frame->linesize), + "Copying code needs to be adjusted"); + static_assert(sizeof(frame->linesize[0]) == sizeof(linesize[0]), + "linesize needs to be switched to ptrdiff_t"); + + for (int i = 0; i < AV_VIDEO_MAX_PLANES; ++i) { + data[i] = frame->data[i]; + linesize[i] = frame->linesize[i]; + buf[i] = frame->buf[i]; + frame->buf[i] = NULL; + } + av_assert1(!frame->buf[AV_VIDEO_MAX_PLANES] && !frame->extended_buf); + + av_frame_unref(frame); ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF); - if (ret < 0) { - av_frame_free(&tmp); - return ret; + if (ret >= 0) { + av_image_copy2(frame->data, frame->linesize, + data, linesize, + frame->format, frame->width, frame->height); } + for (int i = 0; i < AV_VIDEO_MAX_PLANES; ++i) + av_buffer_unref(&buf[i]); - av_frame_copy(frame, tmp); - av_frame_free(&tmp); - - return 0; + return ret; } int ff_reget_buffer(AVCodecContext *avctx, AVFrame *frame, int flags) -- 2.52.0 >From fe0c6460bb7e70d3b6528b08a2f0d7ba1966098f Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <[email protected]> Date: Wed, 15 Apr 2026 16:21:28 +0200 Subject: [PATCH 7/8] avcodec/decode: Short-circuit side-data processing Signed-off-by: Andreas Rheinhardt <[email protected]> --- libavcodec/decode.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 7ad3077521..ac654f1f4c 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -1556,15 +1556,17 @@ int ff_decode_frame_props_from_pkt(const AVCodecContext *avctx, frame->pts = pkt->pts; frame->duration = pkt->duration; - ret = side_data_map(frame, pkt->side_data, pkt->side_data_elems, ff_sd_global_map); - if (ret < 0) - return ret; + if (pkt->side_data_elems) { + ret = side_data_map(frame, pkt->side_data, pkt->side_data_elems, ff_sd_global_map); + if (ret < 0) + return ret; - ret = side_data_map(frame, pkt->side_data, pkt->side_data_elems, sd); - if (ret < 0) - return ret; + ret = side_data_map(frame, pkt->side_data, pkt->side_data_elems, sd); + if (ret < 0) + return ret; - add_metadata_from_side_data(pkt, frame); + add_metadata_from_side_data(pkt, frame); + } if (pkt->flags & AV_PKT_FLAG_DISCARD) { frame->flags |= AV_FRAME_FLAG_DISCARD; -- 2.52.0 >From fa4697a805122ceb992e703248cb2780be4b8012 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <[email protected]> Date: Wed, 15 Apr 2026 16:22:45 +0200 Subject: [PATCH 8/8] avcodec/packet: Remove always-true check Signed-off-by: Andreas Rheinhardt <[email protected]> --- libavcodec/packet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/packet.c b/libavcodec/packet.c index 348159f7f7..a2d453a4b3 100644 --- a/libavcodec/packet.c +++ b/libavcodec/packet.c @@ -358,7 +358,7 @@ int av_packet_unpack_dictionary(const uint8_t *data, size_t size, if (!dict || !data || !size) return 0; end = data + size; - if (size && end[-1]) + if (end[-1]) return AVERROR_INVALIDDATA; while (data < end) { const uint8_t *key = data; -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
