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

Git pushed a commit to branch master
in repository ffmpeg.

commit 9586b813730b32d52f9088c4365313bc1dfbba97
Author:     Niklas Haas <[email protected]>
AuthorDate: Mon Dec 22 14:16:50 2025 +0100
Commit:     Niklas Haas <[email protected]>
CommitDate: Wed Dec 24 16:37:22 2025 +0000

    swscale/ops: don't strip SwsComps from SWS_OP_READ
    
    The current behavior of assuming the value range implicitly on SWS_OP_READ
    has a number of serious drawbacks and shortcomings:
    
    - It ignored the effects of SWS_OP_RSHIFT, such as for p010 and related
      MSB-aligned formats. (This is actually a bug)
    
    - It adds a needless dependency on the "purely informative" src/dst fields
      inside SwsOpList.
    
    - It is difficult to reason about when acted upon by SWS_OP_SWAP_BYTES, and
      the existing hack of simply ignoring SWAP_BYTES on the value range is not
      a very good solution here.
    
    Instead, we need a more principled way for the op list generating code
    to communicate extra metadata about the operations read to the optimizer.
    
    I think the simplest way of doing this is to allow the SwsComps field 
attached
    to SWS_OP_READ to carry additional, user-provided information about the 
values
    read.
    
    This requires changing ff_sws_op_list_update_comps() slightly to not 
completely
    overwrite SwsComps on SWS_OP_READ, but instead merge the implicit 
information
    with the explictly provided one.
---
 libswscale/ops.c | 30 ++++++++++++++++++------------
 libswscale/ops.h | 15 ++++++++++++++-
 2 files changed, 32 insertions(+), 13 deletions(-)

diff --git a/libswscale/ops.c b/libswscale/ops.c
index 5b08b743bf..3fd6f678f5 100644
--- a/libswscale/ops.c
+++ b/libswscale/ops.c
@@ -232,14 +232,15 @@ void ff_sws_op_list_update_comps(SwsOpList *ops)
     for (int n = 0; n < ops->num_ops; n++) {
         SwsOp *op = &ops->ops[n];
 
-        /* Prefill min/max values automatically; may have to be fixed in
-         * special cases */
-        memcpy(op->comps.min, prev.min, sizeof(prev.min));
-        memcpy(op->comps.max, prev.max, sizeof(prev.max));
-
-        if (op->op != SWS_OP_SWAP_BYTES) {
-            ff_sws_apply_op_q(op, op->comps.min);
-            ff_sws_apply_op_q(op, op->comps.max);
+        if (op->op != SWS_OP_READ) {
+            /* Prefill min/max values automatically; may have to be fixed in
+             * special cases */
+            memcpy(op->comps.min, prev.min, sizeof(prev.min));
+            memcpy(op->comps.max, prev.max, sizeof(prev.max));
+            if (op->op != SWS_OP_SWAP_BYTES) {
+                ff_sws_apply_op_q(op, op->comps.min);
+                ff_sws_apply_op_q(op, op->comps.max);
+            }
         }
 
         switch (op->op) {
@@ -260,13 +261,18 @@ void ff_sws_op_list_update_comps(SwsOpList *ops)
                         }
                     }
 
-                    op->comps.flags[i] = SWS_COMP_EXACT;
-                    op->comps.min[i] = Q(0);
-                    op->comps.max[i] = Q((1ULL << bits) - 1);
+                    op->comps.flags[i] |= SWS_COMP_EXACT;
+                    op->comps.min[i] = av_max_q(Q(0), op->comps.min[i]);
+                    op->comps.max[i] = av_min_q(Q((1ULL << bits) - 1), 
op->comps.max[i]);
                 }
             }
-            for (int i = op->rw.elems; i < 4; i++)
+
+            /* Explicitly strip flags and min/max range data for unread comps 
*/
+            for (int i = op->rw.elems; i < 4; i++) {
                 op->comps.flags[i] = prev.flags[i];
+                op->comps.min[i]   = prev.min[i];
+                op->comps.max[i]   = prev.max[i];
+            }
             break;
         case SWS_OP_WRITE:
             for (int i = 0; i < op->rw.elems; i++)
diff --git a/libswscale/ops.h b/libswscale/ops.h
index 6fc7e60a02..a91b63e63a 100644
--- a/libswscale/ops.h
+++ b/libswscale/ops.h
@@ -195,7 +195,20 @@ typedef struct SwsOp {
         SwsConst        c;
     };
 
-    /* For use internal use inside ff_sws_*() functions */
+    /**
+     * Metadata about the operation's input/output components.
+     *
+     * For SWS_OP_READ, this is informative; and lets the optimizer know
+     * additional information about the value range and/or pixel data to 
expect.
+     * The default value of {0} is safe to pass in the case that no additional
+     * information is known.
+     *
+     * For every other operation, this metadata is discarded and regenerated
+     * automatically by `ff_sws_op_list_update_comps()`.
+     *
+     * Note that backends may rely on the presence and accuracy of this
+     * metadata for all operations, during ff_sws_ops_compile().
+     */
     SwsComps comps;
 } SwsOp;
 

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

Reply via email to