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

Git pushed a commit to branch master
in repository ffmpeg.

commit b4bcb00cd3853316fb8f1d869b82919fa00babb3
Author:     Niklas Haas <[email protected]>
AuthorDate: Thu Mar 5 18:08:25 2026 +0100
Commit:     Niklas Haas <[email protected]>
CommitDate: Thu Mar 5 23:34:56 2026 +0000

    swscale/ops: add and use ff_sws_op_list_input/output()
    
    Makes various pieces of code that expect to get a SWS_OP_READ more robust,
    and also allows us to generalize to introduce more input op types in the
    future (in particular, I am looking ahead towards filter ops).
    
    Signed-off-by: Niklas Haas <[email protected]>
---
 libswscale/ops.c           | 26 +++++++++++++++++++++-----
 libswscale/ops.h           | 15 +++++++++++++++
 libswscale/ops_dispatch.c  | 15 +++++----------
 libswscale/ops_optimizer.c | 14 ++++++--------
 libswscale/x86/ops.c       |  6 +++---
 5 files changed, 50 insertions(+), 26 deletions(-)

diff --git a/libswscale/ops.c b/libswscale/ops.c
index d2837d97c7..9961f4f791 100644
--- a/libswscale/ops.c
+++ b/libswscale/ops.c
@@ -541,6 +541,24 @@ SwsOpList *ff_sws_op_list_duplicate(const SwsOpList *ops)
     return copy;
 }
 
+const SwsOp *ff_sws_op_list_input(const SwsOpList *ops)
+{
+    if (!ops->num_ops)
+        return NULL;
+
+    const SwsOp *read = &ops->ops[0];
+    return read->op == SWS_OP_READ ? read : NULL;
+}
+
+const SwsOp *ff_sws_op_list_output(const SwsOpList *ops)
+{
+    if (!ops->num_ops)
+        return NULL;
+
+    const SwsOp *write = &ops->ops[ops->num_ops - 1];
+    return write->op == SWS_OP_WRITE ? write : NULL;
+}
+
 void ff_sws_op_list_remove_at(SwsOpList *ops, int index, int count)
 {
     const int end = ops->num_ops - count;
@@ -575,11 +593,9 @@ bool ff_sws_op_list_is_noop(const SwsOpList *ops)
     if (!ops->num_ops)
         return true;
 
-    const SwsOp *read  = &ops->ops[0];
-    const SwsOp *write = &ops->ops[1];
-    if (ops->num_ops != 2 ||
-        read->op != SWS_OP_READ ||
-        write->op != SWS_OP_WRITE ||
+    const SwsOp *read  = ff_sws_op_list_input(ops);
+    const SwsOp *write = ff_sws_op_list_output(ops);
+    if (!read || !write || ops->num_ops > 2 ||
         read->type != write->type ||
         read->rw.packed != write->rw.packed ||
         read->rw.elems != write->rw.elems ||
diff --git a/libswscale/ops.h b/libswscale/ops.h
index 1684107f00..64a4a6dd61 100644
--- a/libswscale/ops.h
+++ b/libswscale/ops.h
@@ -249,6 +249,21 @@ void ff_sws_op_list_free(SwsOpList **ops);
  */
 SwsOpList *ff_sws_op_list_duplicate(const SwsOpList *ops);
 
+/**
+ * Returns the input operation for a given op list, or NULL if there is none
+ * (e.g. for a pure CLEAR-only operation list).
+ *
+ * This will always be an op of type SWS_OP_READ.
+ */
+const SwsOp *ff_sws_op_list_input(const SwsOpList *ops);
+
+/**
+ * Returns the output operation for a given op list, or NULL if there is none.
+ *
+ * This will always be an op of type SWS_OP_WRITE.
+ */
+const SwsOp *ff_sws_op_list_output(const SwsOpList *ops);
+
 /**
  * Returns whether an op list represents a true no-op operation, i.e. may be
  * eliminated entirely from an execution graph.
diff --git a/libswscale/ops_dispatch.c b/libswscale/ops_dispatch.c
index 3faa677858..5d3bb73123 100644
--- a/libswscale/ops_dispatch.c
+++ b/libswscale/ops_dispatch.c
@@ -335,8 +335,8 @@ static int compile(SwsGraph *graph, const SwsOpList *ops,
     if (ret < 0)
         goto fail;
 
-    const SwsOp *read = &ops->ops[0];
-    const SwsOp *write = &ops->ops[ops->num_ops - 1];
+    const SwsOp *read  = ff_sws_op_list_input(ops);
+    const SwsOp *write = ff_sws_op_list_output(ops);
     p->planes_in  = rw_planes(read);
     p->planes_out = rw_planes(write);
     p->pixel_bits_in  = rw_pixel_bits(read);
@@ -375,8 +375,6 @@ int ff_sws_compile_pass(SwsGraph *graph, SwsOpList *ops, 
int flags,
                         const SwsFormat *dst, SwsPass *input, SwsPass **output)
 {
     SwsContext *ctx = graph->ctx;
-    const SwsOp *read = &ops->ops[0];
-    const SwsOp *write = &ops->ops[ops->num_ops - 1];
     int ret;
 
     /* Check if the whole operation graph is an end-to-end no-op */
@@ -385,12 +383,9 @@ int ff_sws_compile_pass(SwsGraph *graph, SwsOpList *ops, 
int flags,
         return 0;
     }
 
-    if (ops->num_ops < 2) {
-        av_log(ctx, AV_LOG_ERROR, "Need at least two operations.\n");
-        return AVERROR(EINVAL);
-    }
-
-    if (read->op != SWS_OP_READ || write->op != SWS_OP_WRITE) {
+    const SwsOp *read  = ff_sws_op_list_input(ops);
+    const SwsOp *write = ff_sws_op_list_output(ops);
+    if (!read || !write) {
         av_log(ctx, AV_LOG_ERROR, "First and last operations must be a read "
                "and write, respectively.\n");
         return AVERROR(EINVAL);
diff --git a/libswscale/ops_optimizer.c b/libswscale/ops_optimizer.c
index 9cddb3d7f5..abba9df2ff 100644
--- a/libswscale/ops_optimizer.c
+++ b/libswscale/ops_optimizer.c
@@ -690,15 +690,13 @@ int ff_sws_solve_shuffle(const SwsOpList *const ops, 
uint8_t shuffle[],
     if (!ops->num_ops)
         return AVERROR(EINVAL);
 
-    const SwsOp read = ops->ops[0];
-    const int read_size = ff_sws_pixel_type_size(read.type);
-    uint32_t mask[4] = {0};
-
-    if (read.op != SWS_OP_READ || read.rw.frac ||
-        (!read.rw.packed && read.rw.elems > 1))
+    const SwsOp *read = ff_sws_op_list_input(ops);
+    if (!read || read->rw.frac || (!read->rw.packed && read->rw.elems > 1))
         return AVERROR(ENOTSUP);
 
-    for (int i = 0; i < read.rw.elems; i++)
+    const int read_size = ff_sws_pixel_type_size(read->type);
+    uint32_t mask[4] = {0};
+    for (int i = 0; i < read->rw.elems; i++)
         mask[i] = 0x01010101 * i * read_size + 0x03020100;
 
     for (int opidx = 1; opidx < ops->num_ops; opidx++) {
@@ -750,7 +748,7 @@ int ff_sws_solve_shuffle(const SwsOpList *const ops, 
uint8_t shuffle[],
             memset(shuffle, clear_val, size);
 
             const int write_size  = ff_sws_pixel_type_size(op->type);
-            const int read_chunk  = read.rw.elems * read_size;
+            const int read_chunk  = read->rw.elems * read_size;
             const int write_chunk = op->rw.elems * write_size;
             const int num_groups  = size / FFMAX(read_chunk, write_chunk);
             for (int n = 0; n < num_groups; n++) {
diff --git a/libswscale/x86/ops.c b/libswscale/x86/ops.c
index 45e2b10bff..61288cc229 100644
--- a/libswscale/x86/ops.c
+++ b/libswscale/x86/ops.c
@@ -679,9 +679,9 @@ static int compile(SwsContext *ctx, SwsOpList *ops, 
SwsCompiledOp *out)
     if (mmsize < 0)
         return mmsize;
 
-    av_assert1(ops->num_ops > 0);
-    const SwsOp *read = ops->ops[0].op == SWS_OP_READ ? &ops->ops[0] : NULL;
-    const SwsOp *write = &ops->ops[ops->num_ops - 1];
+    const SwsOp *read  = ff_sws_op_list_input(ops);
+    const SwsOp *write = ff_sws_op_list_output(ops);
+    av_assert1(write);
     int ret;
 
     /* Special fast path for in-place packed shuffle */

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

Reply via email to