Commit 80e3425ba2 for ffmpeg

commit 80e3425ba2141f1c38d64bbc9a78a649a2653db6
Author: Niklas Haas <git@haasn.dev>
Date:   Sat Nov 7 14:19:03 2026 +0100

    swscale/ops_chain: use abstract packed data buffer

    Instead of forcing a single layout (SwsOpPriv), this will allow each
    op to define its own data layout; freeing us from the 16-byte constraint
    for op private data.

    Currently, we still hard-code the assumption that the data layout exactly
    matches SwsOpPriv, but this will change in the following commits.

    Signed-off-by: Niklas Haas <git@haasn.dev>

diff --git a/libswscale/aarch64/ops.c b/libswscale/aarch64/ops.c
index 5755bac610..4ee93329a7 100644
--- a/libswscale/aarch64/ops.c
+++ b/libswscale/aarch64/ops.c
@@ -184,7 +184,7 @@ static int compile_uops_aarch64(SwsContext *ctx, const SwsUOpList *uops,
         ret = aarch64_setup(&uops->ops[i], &params, &res);
         if (ret < 0)
             goto error;
-        ret = ff_sws_op_chain_append(chain, func, res.ref, &res.priv);
+        ret = ff_sws_op_chain_append(chain, func, res.ref, &res.priv, sizeof(res.priv));
         av_refstruct_unref(&res.ref);
         if (ret < 0)
             goto error;
diff --git a/libswscale/ops_chain.c b/libswscale/ops_chain.c
index 0e2bd237a8..5b0367d6b5 100644
--- a/libswscale/ops_chain.c
+++ b/libswscale/ops_chain.c
@@ -42,20 +42,25 @@ void ff_sws_op_chain_free_cb(void *ptr)
 }

 int ff_sws_op_chain_append(SwsOpChain *chain, SwsFuncPtr func, const void *ref,
-                           const SwsOpPriv *priv)
+                           const void *data, size_t data_size)
 {
-    const int idx = chain->num_impl;
-    if (idx == SWS_MAX_OPS)
+    /* Ensures each SwsOpImpl is stored aligned, so that we can deref it */
+    const size_t op_size = FFALIGN(offsetof(SwsOpImpl, priv) + data_size,
+                                   alignof(SwsOpImpl));
+
+    if (chain->impl_size + op_size > sizeof(chain->impl))
         return AVERROR(EINVAL);
     if (ref && chain->num_ref >= FF_ARRAY_ELEMS(chain->ref))
         return AVERROR(EINVAL);

-    av_assert1(func);
-    chain->impl[idx].func = func;
-    chain->impl[idx].priv = *priv;
-    chain->num_impl++;
+    SwsOpImpl *impl = (SwsOpImpl *) &chain->impl[chain->impl_size];
+    impl->func = func;
+    if (data_size)
+        memcpy(&impl->priv, data, data_size);
+    chain->impl_size += op_size;
     if (ref)
         chain->ref[chain->num_ref++] = av_refstruct_ref_c(ref);
+
     return 0;
 }

@@ -122,7 +127,7 @@ int ff_sws_uop_lookup(SwsContext *ctx, const SwsUOpTable *const tables[],
     }

     ret = ff_sws_op_chain_append(chain, res.func ? res.func : match->func,
-                                 res.ref, &res.priv);
+                                 res.ref, &res.priv, sizeof(res.priv));
     av_refstruct_unref(&res.ref);
     if (ret < 0)
         return ret;
diff --git a/libswscale/ops_chain.h b/libswscale/ops_chain.h
index f660215520..b7e88710a3 100644
--- a/libswscale/ops_chain.h
+++ b/libswscale/ops_chain.h
@@ -78,6 +78,7 @@ typedef struct SwsOpImpl {
 #if ARCH_X86_64 || ARCH_AARCH64
 static_assert(sizeof(SwsOpImpl) == 24,        "SwsOpImpl layout mismatch");
 static_assert(offsetof(SwsOpImpl, priv) == 8, "SwsOpImpl layout mismatch");
+static_assert(alignof(SwsOpImpl) == sizeof(void *), "SwsOpImpl alignment mismatch");
 #endif

 /**
@@ -86,9 +87,13 @@ static_assert(offsetof(SwsOpImpl, priv) == 8, "SwsOpImpl layout mismatch");
  * private data for each operation.
  */
 typedef struct SwsOpChain {
-#define SWS_MAX_OPS 16
-    SwsOpImpl impl[SWS_MAX_OPS];
-    int num_impl;
+    /* Generic data buffer. This contains a packed representation of
+     * continuation addresses and kernel private data. This is placed at
+     * the front of the struct so SIMD kernels can access it directly. */
+    DECLARE_ALIGNED_8(uint8_t, impl)[1024];
+    int impl_size;
+
+    /* Metadata for the chain */
     int cpu_flags;      /* set of all used CPU flags */
     int over_read[4];   /* chain over-reads input by this many bytes */
     int over_write[4];  /* chain over-writes output by this many bytes */
@@ -107,7 +112,7 @@ static inline void ff_sws_op_chain_free(SwsOpChain *chain)

 /* Returns 0 on success, or a negative error code. */
 int ff_sws_op_chain_append(SwsOpChain *chain, SwsFuncPtr func, const void *ref,
-                           const SwsOpPriv *priv);
+                           const void *data, size_t data_size);

 /**
  * Attach a SwsOpChain and all metadata to a SwsCompiledOp (as out->priv).
diff --git a/libswscale/uops_backend.c b/libswscale/uops_backend.c
index 94d22e404e..305f74779b 100644
--- a/libswscale/uops_backend.c
+++ b/libswscale/uops_backend.c
@@ -111,7 +111,7 @@ static void process_c(const SwsOpExec *exec, const void *priv,
                       int bx_end, int y_end)
 {
     const SwsOpChain *chain = priv;
-    const SwsOpImpl *impl = chain->impl;
+    const SwsOpImpl *impl = (const SwsOpImpl *) chain->impl;
     block_t x, y, z, w; /* allocate enough space for any intermediate */

     SwsOpIter iter;