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

Git pushed a commit to branch master
in repository ffmpeg.

commit 998cffb4327b0ebbe154bcfa19410e01b972a914
Author:     Niklas Haas <[email protected]>
AuthorDate: Thu Jan 8 15:10:30 2026 +0100
Commit:     Niklas Haas <[email protected]>
CommitDate: Thu Feb 19 19:44:46 2026 +0000

    swscale/ops: add input/output plane swizzle mask to SwsOpList
    
    This can be used to have the execution code directly swizzle the plane
    pointers, instead of swizzling the data via SWS_OP_SWIZZLE. This can be used
    to, for example, extract a subset of the input/output planes for partial
    processing of split graphs (e.g. subsampled chroma, or independent alpha),
    or just to skip an SWS_OP_SWIZZLE operation.
    
    Sponsored-by: Sovereign Tech Fund
    Signed-off-by: Niklas Haas <[email protected]>
---
 libswscale/ops.c | 60 ++++++++++++++++++++++++++++++++++++++++++--------------
 libswscale/ops.h |  3 +++
 2 files changed, 48 insertions(+), 15 deletions(-)

diff --git a/libswscale/ops.c b/libswscale/ops.c
index 556c11467b..edd0e76eec 100644
--- a/libswscale/ops.c
+++ b/libswscale/ops.c
@@ -465,6 +465,7 @@ SwsOpList *ff_sws_op_list_alloc(void)
     if (!ops)
         return NULL;
 
+    ops->order_src = ops->order_dst = SWS_SWIZZLE(0, 1, 2, 3);
     ff_fmt_clear(&ops->src);
     ff_fmt_clear(&ops->dst);
     return ops;
@@ -845,6 +846,8 @@ typedef struct SwsOpPass {
     int planes_out;
     int pixel_bits_in;
     int pixel_bits_out;
+    int idx_in[4];
+    int idx_out[4];
     bool memcpy_in;
     bool memcpy_out;
 } SwsOpPass;
@@ -861,10 +864,27 @@ static void op_pass_free(void *ptr)
     av_free(p);
 }
 
-static void op_pass_setup(const SwsImg *out, const SwsImg *in, const SwsPass 
*pass)
+static inline SwsImg img_shift_idx(const SwsImg *base, const int y,
+                                   const int plane_idx[4])
 {
-    const AVPixFmtDescriptor *indesc  = av_pix_fmt_desc_get(in->fmt);
-    const AVPixFmtDescriptor *outdesc = av_pix_fmt_desc_get(out->fmt);
+    SwsImg img = *base;
+    for (int i = 0; i < 4; i++) {
+        const int idx = plane_idx[i];
+        if (idx >= 0) {
+            const int yshift = y >> ff_fmt_vshift(base->fmt, idx);
+            img.data[i] = base->data[idx] + yshift * base->linesize[idx];
+        } else {
+            img.data[i] = NULL;
+        }
+    }
+    return img;
+}
+
+static void op_pass_setup(const SwsImg *out_base, const SwsImg *in_base,
+                          const SwsPass *pass)
+{
+    const AVPixFmtDescriptor *indesc  = av_pix_fmt_desc_get(in_base->fmt);
+    const AVPixFmtDescriptor *outdesc = av_pix_fmt_desc_get(out_base->fmt);
 
     SwsOpPass *p = pass->priv;
     SwsOpExec *exec = &p->exec_base;
@@ -883,22 +903,27 @@ static void op_pass_setup(const SwsImg *out, const SwsImg 
*in, const SwsPass *pa
     p->memcpy_in     = false;
     p->memcpy_out    = false;
 
+    const SwsImg in  = img_shift_idx(in_base,  0, p->idx_in);
+    const SwsImg out = img_shift_idx(out_base, 0, p->idx_out);
+
     for (int i = 0; i < p->planes_in; i++) {
-        const int sub_x      = (i == 1 || i == 2) ? indesc->log2_chroma_w : 0;
+        const int idx        = p->idx_in[i];
+        const int sub_x      = (idx == 1 || idx == 2) ? indesc->log2_chroma_w 
: 0;
         const int plane_w    = (aligned_w + sub_x) >> sub_x;
         const int plane_pad  = (comp->over_read + sub_x) >> sub_x;
         const int plane_size = plane_w * p->pixel_bits_in >> 3;
-        p->memcpy_in |= plane_size + plane_pad > in->linesize[i];
-        exec->in_stride[i] = in->linesize[i];
+        p->memcpy_in |= plane_size + plane_pad > in.linesize[i];
+        exec->in_stride[i] = in.linesize[i];
     }
 
     for (int i = 0; i < p->planes_out; i++) {
-        const int sub_x      = (i == 1 || i == 2) ? outdesc->log2_chroma_w : 0;
+        const int idx        = p->idx_out[i];
+        const int sub_x      = (idx == 1 || idx == 2) ? outdesc->log2_chroma_w 
: 0;
         const int plane_w    = (aligned_w + sub_x) >> sub_x;
         const int plane_pad  = (comp->over_write + sub_x) >> sub_x;
         const int plane_size = plane_w * p->pixel_bits_out >> 3;
-        p->memcpy_out |= plane_size + plane_pad > out->linesize[i];
-        exec->out_stride[i] = out->linesize[i];
+        p->memcpy_out |= plane_size + plane_pad > out.linesize[i];
+        exec->out_stride[i] = out.linesize[i];
     }
 
     /* Pre-fill pointer bump for the main section only; this value does not
@@ -906,8 +931,8 @@ static void op_pass_setup(const SwsImg *out, const SwsImg 
*in, const SwsPass *pa
      * process a single line */
     const int blocks_main = p->num_blocks - p->memcpy_out;
     for (int i = 0; i < 4; i++) {
-        exec->in_bump[i]  = in->linesize[i]  - blocks_main * 
exec->block_size_in;
-        exec->out_bump[i] = out->linesize[i] - blocks_main * 
exec->block_size_out;
+        exec->in_bump[i]  = in.linesize[i]  - blocks_main * 
exec->block_size_in;
+        exec->out_bump[i] = out.linesize[i] - blocks_main * 
exec->block_size_out;
     }
 }
 
@@ -925,8 +950,8 @@ handle_tail(const SwsOpPass *p, SwsOpExec *exec,
     const int tail_size_out = p->tail_size_out;
     const int bx = p->num_blocks - 1;
 
-    SwsImg in  = ff_sws_img_shift(in_base,  y);
-    SwsImg out = ff_sws_img_shift(out_base, y);
+    SwsImg in  = img_shift_idx(in_base,  y, p->idx_in);
+    SwsImg out = img_shift_idx(out_base, y, p->idx_out);
     for (int i = 0; i < p->planes_in; i++) {
         in.data[i]  += p->tail_off_in;
         if (copy_in) {
@@ -980,8 +1005,8 @@ static void op_pass_run(const SwsImg *out_base, const 
SwsImg *in_base,
 {
     const SwsOpPass *p = pass->priv;
     const SwsCompiledOp *comp = &p->comp;
-    const SwsImg in  = ff_sws_img_shift(in_base,  y);
-    const SwsImg out = ff_sws_img_shift(out_base, y);
+    const SwsImg in  = img_shift_idx(in_base,  y, p->idx_in);
+    const SwsImg out = img_shift_idx(out_base, y, p->idx_out);
 
     /* Fill exec metadata for this slice */
     DECLARE_ALIGNED_32(SwsOpExec, exec) = p->exec_base;
@@ -1100,6 +1125,11 @@ int ff_sws_compile_pass(SwsGraph *graph, SwsOpList *ops, 
int flags, SwsFormat ds
         .block_size_out = p->comp.block_size * p->pixel_bits_out >> 3,
     };
 
+    for (int i = 0; i < 4; i++) {
+        p->idx_in[i]  = i < p->planes_in  ? ops->order_src.in[i] : -1;
+        p->idx_out[i] = i < p->planes_out ? ops->order_dst.in[i] : -1;
+    }
+
     pass = ff_sws_graph_add_pass(graph, dst.format, dst.width, dst.height, 
input,
                                  1, p, op_pass_run);
     if (!pass) {
diff --git a/libswscale/ops.h b/libswscale/ops.h
index ad007be868..27f79b2471 100644
--- a/libswscale/ops.h
+++ b/libswscale/ops.h
@@ -230,6 +230,9 @@ typedef struct SwsOpList {
     SwsOp *ops;
     int num_ops;
 
+    /* Input/output plane pointer swizzle mask */
+    SwsSwizzleOp order_src, order_dst;
+
     /* Purely informative metadata associated with this operation list */
     SwsFormat src, dst;
 } SwsOpList;

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

Reply via email to