Commit 31ba826726 for ffmpeg

commit 31ba826726fd0d1547f2c22e041848d1d7f3f860
Author: Jun Zhao <barryjzhao@tencent.com>
Date:   Wed Oct 28 11:06:10 2026 +0800

    swscale/tests: cover chroma range conversion with FATE references

    Print intermediate chroma results for both range directions at
    8/9/10/12/14/16 bits, including neutral and nearby values. Test both
    planes with the C and available native implementations, and keep
    expected values in tests/ref/fate/sws-range-convert.

    Based on the test implementation from Forgejo_Fairy in PR #25549.

    Signed-off-by: Jun Zhao <barryjzhao@tencent.com>

diff --git a/libswscale/Makefile b/libswscale/Makefile
index 7db08ef966..9c49d6d709 100644
--- a/libswscale/Makefile
+++ b/libswscale/Makefile
@@ -51,6 +51,7 @@ SHLIBOBJS-$(HAVE_GNU_WINDRES) += swscaleres.o
 TESTPROGS = colorspace                                                  \
             floatimg_cmp                                                \
             pixdesc_query                                               \
+            range_convert                                               \
             swscale                                                     \
             unscaled_threaded                                           \

diff --git a/libswscale/tests/.gitignore b/libswscale/tests/.gitignore
index 081b75f02e..b358351617 100644
--- a/libswscale/tests/.gitignore
+++ b/libswscale/tests/.gitignore
@@ -1,6 +1,7 @@
 /colorspace
 /floatimg_cmp
 /pixdesc_query
+/range_convert
 /rational64
 /swscale
 /sws_ops
diff --git a/libswscale/tests/range_convert.c b/libswscale/tests/range_convert.c
new file mode 100644
index 0000000000..2794c42fe5
--- /dev/null
+++ b/libswscale/tests/range_convert.c
@@ -0,0 +1,94 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdio.h>
+
+#include "libavutil/common.h"
+#include "libavutil/cpu.h"
+#include "libavutil/mem_internal.h"
+#include "libavutil/pixdesc.h"
+#include "libswscale/swscale_internal.h"
+
+int main(void)
+{
+    static const enum AVPixelFormat formats[] = {
+        AV_PIX_FMT_YUV444P,   AV_PIX_FMT_YUV444P9,
+        AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUV444P12,
+        AV_PIX_FMT_YUV444P14, AV_PIX_FMT_YUV444P16,
+    };
+    const int cpu_flags = av_get_cpu_flags();
+    SwsContext *sws = sws_alloc_context();
+    SwsInternal *c;
+
+    if (!sws)
+        return 1;
+    c = sws_internal(sws);
+
+    for (int native = 0; native < 2; native++) {
+        av_force_cpu_flags(native ? cpu_flags : 0);
+        for (int p = 0; p < FF_ARRAY_ELEMS(formats); p++) {
+            const int depth = av_pix_fmt_desc_get(formats[p])->comp[0].depth;
+            const int shift = (depth <= 14 ? 15 : 19) - depth;
+            const int center = 128 << (depth - 8);
+            const int samples[] = {
+                0, 16 << (depth - 8), center - 1, center,
+                center + 1, 235 << (depth - 8), 240 << (depth - 8),
+                (1 << depth) - 1,
+            };
+            DECLARE_ALIGNED(32, int16_t, u16)[16];
+            DECLARE_ALIGNED(32, int16_t, v16)[16];
+            DECLARE_ALIGNED(32, int32_t, u32)[16];
+            DECLARE_ALIGNED(32, int32_t, v32)[16];
+
+            sws->src_format = sws->dst_format = formats[p];
+            c->dstBpc = depth;
+            for (int from = 0; from < 2; from++) {
+                sws->src_range = from;
+                sws->dst_range = !from;
+                ff_sws_init_range_convert(c);
+                for (int i = 0; i < 16; i++) {
+                    const int u = samples[i % 8] << shift;
+                    const int v = samples[7 - i % 8] << shift;
+                    if (depth == 16) {
+                        u32[i] = u;
+                        v32[i] = v;
+                    } else {
+                        u16[i] = u;
+                        v16[i] = v;
+                    }
+                }
+                c->chrConvertRange(depth == 16 ? (int16_t *) u32 : u16,
+                                   depth == 16 ? (int16_t *) v32 : v16, 16,
+                                   c->chrConvertRange_coeff,
+                                   c->chrConvertRange_offset);
+                printf("%s %2d-bit %s U:", native ? "native" : "c     ",
+                       depth, from ? "full-to-limited" : "limited-to-full");
+                for (int i = 0; i < 8; i++)
+                    printf(" %d", depth == 16 ? u32[i] : u16[i]);
+                printf(" V:");
+                for (int i = 0; i < 8; i++)
+                    printf(" %d", depth == 16 ? v32[i] : v16[i]);
+                printf("\n");
+            }
+        }
+    }
+
+    av_force_cpu_flags(cpu_flags);
+    sws_freeContext(sws);
+    return 0;
+}
diff --git a/tests/fate/libswscale.mak b/tests/fate/libswscale.mak
index 802ac72a03..97a410bc62 100644
--- a/tests/fate/libswscale.mak
+++ b/tests/fate/libswscale.mak
@@ -1,3 +1,7 @@
+FATE_LIBSWSCALE += fate-sws-range-convert
+fate-sws-range-convert: libswscale/tests/range_convert$(EXESUF)
+fate-sws-range-convert: CMD = run libswscale/tests/range_convert$(EXESUF)
+
 FATE_LIBSWSCALE += fate-sws-unscaled-threaded
 fate-sws-unscaled-threaded: libswscale/tests/unscaled_threaded$(EXESUF)
 fate-sws-unscaled-threaded: CMD = run libswscale/tests/unscaled_threaded$(EXESUF)
diff --git a/tests/ref/fate/sws-range-convert b/tests/ref/fate/sws-range-convert
new file mode 100644
index 0000000000..171d85451e
--- /dev/null
+++ b/tests/ref/fate/sws-range-convert
@@ -0,0 +1,24 @@
+c       8-bit limited-to-full U: -2268 64 16238 16384 16530 31976 32705 32767 V: 32767 32705 31976 16530 16384 16238 64 -2268
+c       8-bit full-to-limited U: 1991 3790 16272 16384 16496 28416 28978 30665 V: 30665 28978 28416 16496 16384 16272 3790 1991
+c       9-bit limited-to-full U: -2304 32 16311 16384 16457 32006 32736 32767 V: 32767 32736 32006 16457 16384 16311 32 -2304
+c       9-bit full-to-limited U: 2019 3815 16328 16384 16440 28392 28953 30693 V: 30693 28953 28392 16440 16384 16328 3815 2019
+c      10-bit limited-to-full U: -2323 15 16347 16384 16421 32022 32753 32767 V: 32767 32753 32022 16421 16384 16347 15 -2323
+c      10-bit full-to-limited U: 2034 3828 16356 16384 16412 28380 28940 30706 V: 30706 28940 28380 16412 16384 16356 3828 2034
+c      12-bit limited-to-full U: -2336 4 16375 16384 16393 32033 32764 32767 V: 32767 32764 32033 16393 16384 16375 4 -2336
+c      12-bit full-to-limited U: 2044 3837 16377 16384 16391 28371 28932 30717 V: 30717 28932 28371 16391 16384 16377 3837 2044
+c      14-bit limited-to-full U: -2339 1 16382 16384 16386 32035 32767 32767 V: 32767 32767 32035 16386 16384 16382 1 -2339
+c      14-bit full-to-limited U: 2047 3839 16382 16384 16386 28369 28929 30719 V: 30719 28929 28369 16386 16384 16382 3839 2047
+c      16-bit limited-to-full U: -37445 4 262135 262144 262153 512582 524284 524287 V: 524287 524284 512582 262153 262144 262135 4 -37445
+c      16-bit full-to-limited U: 32764 61437 262137 262144 262151 453891 462852 491517 V: 491517 462852 453891 262151 262144 262137 61437 32764
+native  8-bit limited-to-full U: -2268 64 16238 16384 16530 31976 32705 32767 V: 32767 32705 31976 16530 16384 16238 64 -2268
+native  8-bit full-to-limited U: 1991 3790 16272 16384 16496 28416 28978 30665 V: 30665 28978 28416 16496 16384 16272 3790 1991
+native  9-bit limited-to-full U: -2304 32 16311 16384 16457 32006 32736 32767 V: 32767 32736 32006 16457 16384 16311 32 -2304
+native  9-bit full-to-limited U: 2019 3815 16328 16384 16440 28392 28953 30693 V: 30693 28953 28392 16440 16384 16328 3815 2019
+native 10-bit limited-to-full U: -2323 15 16347 16384 16421 32022 32753 32767 V: 32767 32753 32022 16421 16384 16347 15 -2323
+native 10-bit full-to-limited U: 2034 3828 16356 16384 16412 28380 28940 30706 V: 30706 28940 28380 16412 16384 16356 3828 2034
+native 12-bit limited-to-full U: -2336 4 16375 16384 16393 32033 32764 32767 V: 32767 32764 32033 16393 16384 16375 4 -2336
+native 12-bit full-to-limited U: 2044 3837 16377 16384 16391 28371 28932 30717 V: 30717 28932 28371 16391 16384 16377 3837 2044
+native 14-bit limited-to-full U: -2339 1 16382 16384 16386 32035 32767 32767 V: 32767 32767 32035 16386 16384 16382 1 -2339
+native 14-bit full-to-limited U: 2047 3839 16382 16384 16386 28369 28929 30719 V: 30719 28929 28369 16386 16384 16382 3839 2047
+native 16-bit limited-to-full U: -37445 4 262135 262144 262153 512582 524284 524287 V: 524287 524284 512582 262153 262144 262135 4 -37445
+native 16-bit full-to-limited U: 32764 61437 262137 262144 262151 453891 462852 491517 V: 491517 462852 453891 262151 262144 262137 61437 32764