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

Git pushed a commit to branch master
in repository ffmpeg.

commit 1cc4c2b236d55feec158f04b20caa1aa0e2e1a50
Author:     Niklas Haas <[email protected]>
AuthorDate: Thu Dec 4 19:51:22 2025 +0100
Commit:     Niklas Haas <[email protected]>
CommitDate: Mon Dec 15 14:31:58 2025 +0000

    swscale/ops_optimizer: rework ambiguous op_type_is_independent()
    
    The current usage is ambiguous between "affects each component equally" and
    "affects each component independently" - and arguably, the current behavior
    was a bug (since SWS_OP_DITHER should not commute with a SWIZZLE, at least
    from a bit-exactness PoV).
    
    However, when trying to define cleaner replacements for these concepts, I
    realized there are too many special cases; and given that we only have two
    use sites, I decided to just split them directly into "commute" functions
    for those particular usage cases.
    
    As an added benefit, this moves the commutation logic out of the 
already-long
    ff_sws_ops_list_optimize().
---
 libswscale/ops_optimizer.c | 87 ++++++++++++++++++++++++++++++++++------------
 1 file changed, 64 insertions(+), 23 deletions(-)

diff --git a/libswscale/ops_optimizer.c b/libswscale/ops_optimizer.c
index f173e1f78f..96d71ae108 100644
--- a/libswscale/ops_optimizer.c
+++ b/libswscale/ops_optimizer.c
@@ -31,20 +31,76 @@
             return ret;                                                        
\
     } while (0)
 
-/* Returns true for operations that are independent per channel. These can
- * usually be commuted freely other such operations. */
-static bool op_type_is_independent(SwsOpType op)
+/**
+ * Try to commute a clear op with the next operation. Makes any adjustments
+ * to the operations as needed, but does not perform the actual commutation.
+ *
+ * Returns whether successful.
+ */
+static bool op_commute_clear(SwsOp *op, SwsOp *next)
 {
-    switch (op) {
-    case SWS_OP_SWAP_BYTES:
+    av_assert1(op->op == SWS_OP_CLEAR);
+    switch (next->op) {
+    case SWS_OP_CONVERT:
+        op->type = next->convert.to;
+        /* fall through */
     case SWS_OP_LSHIFT:
     case SWS_OP_RSHIFT:
-    case SWS_OP_CONVERT:
     case SWS_OP_DITHER:
     case SWS_OP_MIN:
     case SWS_OP_MAX:
     case SWS_OP_SCALE:
+    case SWS_OP_CLEAR:
+    case SWS_OP_READ:
+    case SWS_OP_SWIZZLE:
+        ff_sws_apply_op_q(next, op->c.q4);
         return true;
+    case SWS_OP_INVALID:
+    case SWS_OP_SWAP_BYTES:
+    case SWS_OP_WRITE:
+    case SWS_OP_LINEAR:
+    case SWS_OP_PACK:
+    case SWS_OP_UNPACK:
+        return false;
+    case SWS_OP_TYPE_NB:
+        break;
+    }
+
+    av_unreachable("Invalid operation type!");
+    return false;
+}
+
+ /**
+  * Try to commute a swizzle op with the next operation. Makes any adjustments
+  * to the operations as needed, but does not perform the actual commutation.
+  *
+  * Returns whether successful.
+  */
+static bool op_commute_swizzle(SwsOp *op, SwsOp *next)
+{
+    av_assert1(op->op == SWS_OP_SWIZZLE);
+    switch (next->op) {
+    case SWS_OP_CONVERT:
+        op->type = next->convert.to;
+        /* fall through */
+    case SWS_OP_SWAP_BYTES:
+    case SWS_OP_LSHIFT:
+    case SWS_OP_RSHIFT:
+    case SWS_OP_DITHER:
+    case SWS_OP_SCALE:
+        return true;
+
+    /* Operations with per-channel coefficients need to be un-swizzled */
+    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];
+        }
+        return true;
+    }
+
     case SWS_OP_INVALID:
     case SWS_OP_READ:
     case SWS_OP_WRITE:
@@ -523,12 +579,7 @@ retry:
 
             /* Prefer to clear as late as possible, to avoid doing
              * redundant work */
-            if ((op_type_is_independent(next->op) && next->op != 
SWS_OP_SWAP_BYTES) ||
-                next->op == SWS_OP_SWIZZLE)
-            {
-                if (next->op == SWS_OP_CONVERT)
-                    op->type = next->convert.to;
-                ff_sws_apply_op_q(next, op->c.q4);
+            if (op_commute_clear(op, next)) {
                 FFSWAP(SwsOp, *op, *next);
                 goto retry;
             }
@@ -562,17 +613,7 @@ retry:
             }
 
             /* Try to push swizzles with duplicates towards the output */
-            if (has_duplicates && op_type_is_independent(next->op)) {
-                if (next->op == SWS_OP_CONVERT)
-                    op->type = next->convert.to;
-                if (next->op == SWS_OP_MIN || next->op == SWS_OP_MAX) {
-                    /* Un-swizzle the next operation */
-                    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 (has_duplicates && op_commute_swizzle(op, next)) {
                 FFSWAP(SwsOp, *op, *next);
                 goto retry;
             }

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

Reply via email to