From 10f2abc41fdb8624a95676a10764904ee58e4ccb Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 4 Jun 2026 20:50:45 +0200 Subject: [PATCH] swscale: support sliced input with cascaded scaling contexts Previously scale_cascaded() assumed the whole source frame arrived in a single sws_scale() call, and the dispatcher only routed full-frame calls to it. A partial input slice fell through to ff_swscale() on the parent dispatcher context, whose scaler state (c->desc) is never initialized in cascade mode, causing a NULL dereference / crash. Top-down sliced output is bit-exact with full-frame scaling; bottom-up matches swscale's pre-existing (non-cascade) slice behaviour for subsampled intermediate formats. Signed-off-by: Michael Niedermayer --- libswscale/swscale.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/libswscale/swscale.c b/libswscale/swscale.c index 558e332eb2..c0cdd17b78 100644 --- a/libswscale/swscale.c +++ b/libswscale/swscale.c @@ -1003,6 +1003,16 @@ static int scale_cascaded(SwsInternal *c, 0, dstH0); if (ret < 0) return ret; + + /* The first stage assembles the full intermediate image from the input, + * one slice at a time (it is itself a regular slice-capable context). The + * second stage scales that whole intermediate to the output in one step, + * so it can only run once the entire source has been consumed. The first + * stage resets its slice direction to 0 at end of frame; until then the + * intermediate is incomplete and this call produces no output lines. */ + if (sws_internal(c->cascaded_context[0])->sliceDir != 0) + return 0; + ret = scale_internal(c->cascaded_context[1], (const uint8_t * const * )c->cascaded_tmp[0], c->cascaded_tmpStride[0], 0, dstH0, dstSlice, dstStride, dstSliceY, dstSliceH); @@ -1067,7 +1077,7 @@ static int scale_internal(SwsContext *sws, return scale_gamma(c, srcSlice, srcStride, srcSliceY, srcSliceH, dstSlice, dstStride, dstSliceY, dstSliceH); - if (c->cascaded_context[0] && srcSliceY == 0 && srcSliceH == c->cascaded_context[0]->src_h) + if (c->cascaded_context[0]) return scale_cascaded(c, srcSlice, srcStride, srcSliceY, srcSliceH, dstSlice, dstStride, dstSliceY, dstSliceH);