From 47f89ea88ba1ae9a9ac5b1b9bfa6063dfbd8c73a Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Thu, 26 Feb 2026 18:46:04 +0100 Subject: [PATCH] swscale: explicitly track if a context is "legacy" or not The legacy API is defined by sws_init_context(), sws_scale() etc., whereas the "modern" API is defined by just using sws_scale_frame() without prior init call. This int allows us to cleanly distinguish the type of context, paving the way for some minor refactoring. As an immediate benefit, we now gain a bunch of explict error checks to ensure the API is used correctly (i.e. sws_scale() not called before sws_init_context()). Sponsored-by: Sovereign Tech Fund Signed-off-by: Niklas Haas --- libswscale/swscale.c | 15 +++++++++++++-- libswscale/swscale_internal.h | 2 ++ libswscale/utils.c | 6 ++++++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/libswscale/swscale.c b/libswscale/swscale.c index 94d9102f97..e4dbef8098 100644 --- a/libswscale/swscale.c +++ b/libswscale/swscale.c @@ -1208,6 +1208,8 @@ static int scale_internal(SwsContext *sws, void sws_frame_end(SwsContext *sws) { SwsInternal *c = sws_internal(sws); + if (!c->is_legacy_init) + return; av_frame_unref(c->frame_src); av_frame_unref(c->frame_dst); c->src_ranges.nb_ranges = 0; @@ -1217,6 +1219,8 @@ int sws_frame_start(SwsContext *sws, AVFrame *dst, const AVFrame *src) { SwsInternal *c = sws_internal(sws); int ret, allocated = 0; + if (!c->is_legacy_init) + return AVERROR(EINVAL); ret = av_frame_ref(c->frame_src, src); if (ret < 0) @@ -1249,6 +1253,8 @@ int sws_send_slice(SwsContext *sws, unsigned int slice_start, { SwsInternal *c = sws_internal(sws); int ret; + if (!c->is_legacy_init) + return AVERROR(EINVAL); ret = ff_range_add(&c->src_ranges, slice_start, slice_height); if (ret < 0) @@ -1272,6 +1278,8 @@ int sws_receive_slice(SwsContext *sws, unsigned int slice_start, SwsInternal *c = sws_internal(sws); unsigned int align = sws_receive_slice_alignment(sws); uint8_t *dst[4]; + if (!c->is_legacy_init) + return AVERROR(EINVAL); /* wait until complete input has been received */ if (!(c->src_ranges.nb_ranges == 1 && @@ -1345,9 +1353,9 @@ int sws_scale_frame(SwsContext *sws, AVFrame *dst, const AVFrame *src) if (!src || !dst) return AVERROR(EINVAL); - if (c->frame_src) { + if (c->is_legacy_init) { /* Context has been initialized with explicit values, fall back to - * legacy API */ + * legacy API behavior. */ ret = sws_frame_start(sws, dst, src); if (ret < 0) return ret; @@ -1516,6 +1524,9 @@ int attribute_align_arg sws_scale(SwsContext *sws, const int dstStride[]) { SwsInternal *c = sws_internal(sws); + if (!c->is_legacy_init) + return AVERROR(EINVAL); + if (c->nb_slice_ctx) { sws = c->slice_ctx[0]; c = sws_internal(sws); diff --git a/libswscale/swscale_internal.h b/libswscale/swscale_internal.h index 5920f7ffad..7d5eeae203 100644 --- a/libswscale/swscale_internal.h +++ b/libswscale/swscale_internal.h @@ -697,6 +697,8 @@ struct SwsInternal { // Hardware specific private data void *hw_priv; /* refstruct */ + + int is_legacy_init; }; //FIXME check init (where 0) diff --git a/libswscale/utils.c b/libswscale/utils.c index 8a3462c4a3..b21e36df46 100644 --- a/libswscale/utils.c +++ b/libswscale/utils.c @@ -1885,6 +1885,7 @@ av_cold int sws_init_context(SwsContext *sws, SwsFilter *srcFilter, enum AVPixelFormat src_format, dst_format; int ret; + c->is_legacy_init = 1; c->frame_src = av_frame_alloc(); c->frame_dst = av_frame_alloc(); if (!c->frame_src || !c->frame_dst) @@ -2254,6 +2255,11 @@ void sws_freeContext(SwsContext *sws) for (i = 0; i < FF_ARRAY_ELEMS(c->graph); i++) ff_sws_graph_free(&c->graph[i]); + if (!c->is_legacy_init) { + av_free(c); + return; + } + for (i = 0; i < c->nb_slice_ctx; i++) sws_freeContext(c->slice_ctx[i]); av_freep(&c->slice_ctx);