Commit 92c554caeb for ffmpeg
commit 92c554caeb095009325dcb53d9f62827b735cfa4
Author: Kevin Watters <kevinwatters@gmail.com>
Date: Sun Oct 4 15:41:59 2026 +0000
swscale/aarch64: align unscaled YUV to RGB slices to source chroma
The NV12 and NV21 NEON converters need even slice boundaries, but the
RGB destination only requests one-row alignment. Threaded conversion
can therefore start on an odd luma row and use the wrong chroma phase.
The current two-row converters additionally write past odd slice ends.
Raise dst_slice_align when selecting a NEON converter, preserving any
larger existing alignment. This also covers planar 4:2:0 when dithering
options bypass the generic yuv2rgb selector's alignment assignment.
Update the assembly precondition comment to include graph dispatch.
Fixes #24266.
Fixes: d6fdc78e9164 ("sws: implement slice threading")
Assisted-by: Fairy
diff --git a/libswscale/aarch64/swscale_unscaled.c b/libswscale/aarch64/swscale_unscaled.c
index c9041db99f..d11625dbbb 100644
--- a/libswscale/aarch64/swscale_unscaled.c
+++ b/libswscale/aarch64/swscale_unscaled.c
@@ -146,8 +146,10 @@ static int nv24_to_yuv420p_neon_wrapper(SwsInternal *c, const uint8_t *const src
&& c->opts.dst_format == AV_PIX_FMT_##OFMT \
&& !(c->opts.src_h & 1) \
&& !(c->opts.src_w & 15) \
- && !accurate_rnd) \
+ && !accurate_rnd) { \
c->convert_unscaled = ifmt##_to_##ofmt##_neon_wrapper; \
+ c->dst_slice_align = FFMAX(c->dst_slice_align, 1 << c->chrSrcVSubSample); \
+ } \
} while (0)
#define SET_FF_YUVX_TO_ALL_RGBX_FUNC(yuvx, YUVX, accurate_rnd) do { \
diff --git a/libswscale/aarch64/yuv2rgb_neon.S b/libswscale/aarch64/yuv2rgb_neon.S
index 734b6dd174..691e903fc9 100644
--- a/libswscale/aarch64/yuv2rgb_neon.S
+++ b/libswscale/aarch64/yuv2rgb_neon.S
@@ -941,10 +941,10 @@ endfunc
// share one chroma row, so the chroma -> RGB offsets (v20-v25) are
// computed once and applied to both luma rows.
//
-// Precondition: slice height is even. SET_FF_YUVX_TO_RGBX_FUNC gates
-// on !(src_h & 1); scale_internal()'s macro_height_src check in
-// libswscale/swscale.c rejects any odd srcSliceH for vertically-
-// subsampled sources (chrSrcVSubSample > 0).
+// Precondition: the slice starts on an even luma row and has even height.
+// SET_FF_YUVX_TO_RGBX_FUNC requires an even frame height and raises
+// dst_slice_align, which both the legacy worker and graph splitter honor.
+// For direct sws_scale() calls, scale_internal() checks input slice alignment.
.macro declare_2l_packed ifmt ofmt
function ff_\ifmt\()_to_\ofmt\()_neon, export=1
uxtw widthx, width