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

Git pushed a commit to branch master
in repository ffmpeg.

commit 7bce47cc63425be93ac1718e70a7e45967d14415
Author:     Niklas Haas <[email protected]>
AuthorDate: Mon Dec 8 12:48:21 2025 +0100
Commit:     Niklas Haas <[email protected]>
CommitDate: Mon Dec 15 14:31:58 2025 +0000

    swscale/ops_optimizer: only commute swizzle ops if coefficients are 
identical
    
    Otherwise, this is invalid; as the result of applying the next operation
    after channel duplication may not commute with the result of duplicating
    the result of applying the next operation on only one channel.
    
    In practice, this was using the last seen channel's coefficients.
    
    Note that this did not actually affect anything in practice, because the 
only
    relevant ops (MIN/MAX) were always generated with identical coefficients for
    identical channel ranges.
    
    However, it will matter moving forwards, as e.g. dither ops may not be
    commuted freely if their matrix offsets differ per channel.
---
 libswscale/ops_optimizer.c | 21 ++++++++++++++++++---
 1 file changed, 18 insertions(+), 3 deletions(-)

diff --git a/libswscale/ops_optimizer.c b/libswscale/ops_optimizer.c
index 96d71ae108..e1b52da374 100644
--- a/libswscale/ops_optimizer.c
+++ b/libswscale/ops_optimizer.c
@@ -78,6 +78,8 @@ static bool op_commute_clear(SwsOp *op, SwsOp *next)
   */
 static bool op_commute_swizzle(SwsOp *op, SwsOp *next)
 {
+    bool seen[4] = {0};
+
     av_assert1(op->op == SWS_OP_SWIZZLE);
     switch (next->op) {
     case SWS_OP_CONVERT:
@@ -90,13 +92,26 @@ static bool op_commute_swizzle(SwsOp *op, SwsOp *next)
     case SWS_OP_SCALE:
         return true;
 
-    /* Operations with per-channel coefficients need to be un-swizzled */
+    /**
+     * We can commute per-channel ops only if the per-channel constants are the
+     * same for all duplicated channels; e.g.:
+     *   SWIZZLE {0, 0, 0, 3}
+     *   NEXT    {x, x, x, w}
+     * ->
+     *   NEXT    {x, _, _, w}
+     *   SWIZZLE {0, 0, 0, 3}
+     */
     case SWS_OP_MIN:
     case SWS_OP_MAX: {
         const SwsConst c = next->c;
         for (int i = 0; i < 4; i++) {
-            if (!next->comps.unused[i])
-                next->c.q4[op->swizzle.in[i]] = c.q4[i];
+            if (next->comps.unused[i])
+                continue;
+            const int j = op->swizzle.in[i];
+            if (seen[j] && av_cmp_q(next->c.q4[j], c.q4[i]))
+                return false;
+            next->c.q4[j] = c.q4[i];
+            seen[j] = true;
         }
         return true;
     }

_______________________________________________
ffmpeg-cvslog mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to