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