This is an automated email from the git hooks/post-receive script.

Git pushed a commit to branch master
in repository ffmpeg.

commit 8e362b7b51e7f9491be982d2238b06f904e51021
Author:     Kacper Michajłow <[email protected]>
AuthorDate: Sun Oct 25 06:03:38 2026 +0100
Commit:     Kacper Michajłow <[email protected]>
CommitDate: Wed Oct 28 19:22:28 2026 +0000

    swscale: scale X'Y'Z' to X'Y'Z' on the codes
    
    A scaled conversion between two XYZ formats decoded the codes into
    gamma 2.2 RGB, scaled that and encoded it back, which quantizes twice
    and clips every color outside the BT.709 gamut. Scale the codes like
    those of an RGB format instead, as the unscaled conversion already did,
    and round the result to 12 bits, which keeps the 4 padding bits zero.
    The slice contexts of the graph take the XYZ flags of their parent for
    that.
    
    Signed-off-by: Kacper Michajłow <[email protected]>
---
 libswscale/graph.c                  |  8 +++++---
 libswscale/swscale.c                | 26 ++++++++++++++++++++++++--
 tests/ref/fate/filter-pixfmts-scale |  4 ++--
 3 files changed, 31 insertions(+), 7 deletions(-)

diff --git a/libswscale/graph.c b/libswscale/graph.c
index cc8e5cf7a2..e9ee32052a 100644
--- a/libswscale/graph.c
+++ b/libswscale/graph.c
@@ -450,7 +450,6 @@ static int init_legacy_subpass(SwsGraph *graph, SwsContext 
*sws,
     SwsInternal *c = sws_internal(sws);
     const int src_w = sws->src_w, src_h = sws->src_h;
     const int dst_w = sws->dst_w, dst_h = sws->dst_h;
-    const int unscaled = src_w == dst_w && src_h == dst_h;
     int align = c->dst_slice_align;
     SwsPass *pass = NULL;
     int ret;
@@ -485,7 +484,7 @@ static int init_legacy_subpass(SwsGraph *graph, SwsContext 
*sws,
         }
     }
 
-    if (c->srcXYZ && !(c->dstXYZ && unscaled)) {
+    if (c->srcXYZ && !c->dstXYZ) {
         ret = ff_sws_graph_add_pass(graph, AV_PIX_FMT_RGB48, src_w, src_h, 
input,
                                     0, 1, run_xyz2rgb, NULL, c, NULL, &input);
         if (ret < 0) {
@@ -541,10 +540,13 @@ static int init_legacy_subpass(SwsGraph *graph, 
SwsContext *sws,
                 c2->srcColorspaceTable[i] = c->srcColorspaceTable[i];
                 c2->dstColorspaceTable[i] = c->dstColorspaceTable[i];
             }
+
+            c2->srcXYZ = c->srcXYZ;
+            c2->dstXYZ = c->dstXYZ;
         }
     }
 
-    if (c->dstXYZ && !(c->srcXYZ && unscaled)) {
+    if (c->dstXYZ && !c->srcXYZ) {
         ret = ff_sws_graph_add_pass(graph, AV_PIX_FMT_RGB48, dst_w, dst_h, 
pass,
                                     0, 1, run_rgb2xyz, NULL, c, NULL, &pass);
         if (ret < 0)
diff --git a/libswscale/swscale.c b/libswscale/swscale.c
index 3b2c63cff0..0ba3458b6d 100644
--- a/libswscale/swscale.c
+++ b/libswscale/swscale.c
@@ -254,6 +254,23 @@ static void lumRangeFromJpeg16_c(int16_t *_dst, int width,
         dst[i] = ((int64_t) dst[i] * coeff + offset) >> 18;
 }
 
+static void round_xyz12(uint8_t *plane, int stride, int width, int height, int 
y,
+                        int big_endian)
+{
+    uint8_t *ptr = plane + stride * y;
+    for (int i = 0; i < height; i++) {
+        for (int j = 0; j < 3 * width; j++) {
+            unsigned v = big_endian ? AV_RB16(ptr + 2 * j) : AV_RL16(ptr + 2 * 
j);
+            v = FFMIN(v + 8, UINT16_MAX) & 0xFFF0;
+            if (big_endian)
+                AV_WB16(ptr + 2 * j, v);
+            else
+                AV_WL16(ptr + 2 * j, v);
+        }
+        ptr += stride;
+    }
+}
+
 
 #define DEBUG_SWSCALE_BUFFERS 0
 #define DEBUG_BUFFERS(...)                      \
@@ -552,6 +569,11 @@ int ff_swscale(SwsInternal *c, const uint8_t *const src[], 
const int srcStride[]
             fillPlane(dst[3], dstStride[3], length, height, offset, 255);
     }
 
+    /* XYZ is scaled on its codes like 16-bit RGB */
+    if (c->srcXYZ && c->dstXYZ)
+        round_xyz12(dst[0], dstStride[0], dstW, dstY - lastDstY, lastDstY - 
dstSliceY,
+                    isBE(dstFormat));
+
 #if HAVE_MMXEXT_INLINE
     if (av_get_cpu_flags() & AV_CPU_FLAG_MMXEXT)
         __asm__ volatile ("sfence" ::: "memory");
@@ -1123,7 +1145,7 @@ static int scale_internal(SwsContext *sws,
         src2[0] = base;
     }
 
-    if (c->srcXYZ && !(c->dstXYZ && sws->src_w==sws->dst_w && 
sws->src_h==sws->dst_h)) {
+    if (c->srcXYZ && !c->dstXYZ) {
         uint8_t *base;
 
         av_fast_malloc(&c->xyz_scratch, &c->xyz_scratch_allocated,
@@ -1191,7 +1213,7 @@ static int scale_internal(SwsContext *sws,
                          dst2, dstStride2, dstSliceY, dstSliceH);
     }
 
-    if (c->dstXYZ && !(c->srcXYZ && sws->src_w==sws->dst_w && 
sws->src_h==sws->dst_h)) {
+    if (c->dstXYZ && !c->srcXYZ) {
         uint8_t *dst;
 
         if (scale_dst) {
diff --git a/tests/ref/fate/filter-pixfmts-scale 
b/tests/ref/fate/filter-pixfmts-scale
index 3a7b34ad96..900227f7c3 100644
--- a/tests/ref/fate/filter-pixfmts-scale
+++ b/tests/ref/fate/filter-pixfmts-scale
@@ -117,8 +117,8 @@ xv36be              4d084adca0228d7750d1e2e877e0d79b
 xv36le              de9c74e94dc19c828e1572aa283d8aca
 xv48be              9e58d1a045df100b0dec116e13be5b4e
 xv48le              fd873d53609b2fbdfe99470f515a234c
-xyz12be             0866f8e5493ea93f4523a9e873a14b1e
-xyz12le             d6990efe1c7141227054cbcda28ea6fb
+xyz12be             5390b76c745f71cbd6db031bd424c941
+xyz12le             aba95a389ce26cb603ffe4072d1791d9
 y210le              7c2aef142d88ab343ec01acd45f38466
 y212le              39a3c0c843041ad4501b3107dd91ef17
 y216le              17be2999e97d36b8ed903f07ef428c09

-- 
To stop receiving notification emails like this one, please contact
[email protected].
_______________________________________________
ffmpeg-cvslog mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to