PR #22662 opened by Niklas Haas (haasn)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22662
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22662.patch

Large annoying cosmetic change. I decided to split this off from my SwsCompMask 
refactor branch as that one needs more work


>From 78ae1367ba8d035e3dace5c37b1d87f99c7db8ec Mon Sep 17 00:00:00 2001
From: Niklas Haas <[email protected]>
Date: Sat, 28 Mar 2026 18:29:35 +0100
Subject: [PATCH 1/7] swscale/vulkan/ops: simplify QTYPE macro

There's no reason for this macro to hard-code op->c.q4[i].

Signed-off-by: Niklas Haas <[email protected]>
---
 libswscale/vulkan/ops.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/libswscale/vulkan/ops.c b/libswscale/vulkan/ops.c
index 4d684116ca..dd86c44580 100644
--- a/libswscale/vulkan/ops.c
+++ b/libswscale/vulkan/ops.c
@@ -181,8 +181,7 @@ static void 
add_desc_read_write(FFVulkanDescriptorSetBinding *out_desc,
 }
 
 #define QSTR "(%i/%i%s)"
-#define QTYPE(i) op->c.q4[i].num, op->c.q4[i].den,       \
-                 cur_type == SWS_PIXEL_F32 ? ".0f" : ""
+#define QTYPE(Q) (Q).num, (Q).den, cur_type == SWS_PIXEL_F32 ? ".0f" : ""
 
 static int add_ops_glsl(VulkanPriv *p, FFVulkanOpsCtx *s,
                         SwsOpList *ops, FFVulkanShader *shd)
@@ -278,7 +277,7 @@ static int add_ops_glsl(VulkanPriv *p, FFVulkanOpsCtx *s,
                 if (!op->c.q4[i].den)
                     continue;
                 av_bprintf(&shd->src, "    %s.%c = %s"QSTR";\n", type_name,
-                           "xyzw"[i], type_s, QTYPE(i));
+                           "xyzw"[i], type_s, QTYPE(op->c.q4[i]));
             }
             break;
         }
-- 
2.52.0


>From 7facee83bcfab2977e2c506fb4b7b7ba3bd2c524 Mon Sep 17 00:00:00 2001
From: Niklas Haas <[email protected]>
Date: Sat, 28 Mar 2026 18:33:46 +0100
Subject: [PATCH 2/7] swscale/vulkan/ops: simplify using QSTR/QTYPE to print
 all rationals

Now this helper is actually helping, rather than just existing.

Signed-off-by: Niklas Haas <[email protected]>
---
 libswscale/vulkan/ops.c | 22 +++++++++-------------
 1 file changed, 9 insertions(+), 13 deletions(-)

diff --git a/libswscale/vulkan/ops.c b/libswscale/vulkan/ops.c
index dd86c44580..fece479cd3 100644
--- a/libswscale/vulkan/ops.c
+++ b/libswscale/vulkan/ops.c
@@ -282,8 +282,8 @@ static int add_ops_glsl(VulkanPriv *p, FFVulkanOpsCtx *s,
             break;
         }
         case SWS_OP_SCALE:
-            av_bprintf(&shd->src, "    %s = %s*%i/%i;\n",
-                       type_name, type_name, op->c.q.num, op->c.q.den);
+            av_bprintf(&shd->src, "    %s = %s * "QSTR";\n",
+                       type_name, type_name, QTYPE(op->c.q));
             break;
         case SWS_OP_MIN:
         case SWS_OP_MAX:
@@ -293,9 +293,7 @@ static int add_ops_glsl(VulkanPriv *p, FFVulkanOpsCtx *s,
                 av_bprintf(&shd->src, "    %s.%c = %s(%s.%c, "QSTR");\n",
                            type_name, "xyzw"[i],
                            op->op == SWS_OP_MIN ? "min" : "max",
-                           type_name, "xyzw"[i],
-                           op->c.q4[i].num, op->c.q4[i].den,
-                           cur_type == SWS_PIXEL_F32 ? ".0f" : "");
+                           type_name, "xyzw"[i], QTYPE(op->c.q4[i]));
             }
             break;
         case SWS_OP_LSHIFT:
@@ -321,9 +319,8 @@ static int add_ops_glsl(VulkanPriv *p, FFVulkanOpsCtx *s,
             for (int i = 0; i < size; i++) {
                 av_bprintf(&shd->src, "        { ");
                 for (int j = 0; j < size; j++)
-                    av_bprintf(&shd->src, "%i/%i.0, ",
-                               op->dither.matrix[i*size + j].num,
-                               op->dither.matrix[i*size + j].den);
+                    av_bprintf(&shd->src, QSTR", ",
+                               QTYPE(op->dither.matrix[i*size + j]));
                 av_bprintf(&shd->src, "}, %s\n", i == (size - 1) ? "\n    };" 
: "");
             }
             for (int i = 0; i < 4; i++) {
@@ -339,16 +336,15 @@ static int add_ops_glsl(VulkanPriv *p, FFVulkanOpsCtx *s,
         case SWS_OP_LINEAR:
             for (int i = 0; i < 4; i++) {
                 if (op->lin.m[i][4].num)
-                    av_bprintf(&shd->src, "    tmp.%c = (%i/%i.0);\n", 
"xyzw"[i],
-                               op->lin.m[i][4].num, op->lin.m[i][4].den);
+                    av_bprintf(&shd->src, "    tmp.%c = "QSTR";\n", "xyzw"[i],
+                               QTYPE(op->lin.m[i][4]));
                 else
                     av_bprintf(&shd->src, "    tmp.%c = 0;\n", "xyzw"[i]);
                 for (int j = 0; j < 4; j++) {
                     if (!op->lin.m[i][j].num)
                         continue;
-                    av_bprintf(&shd->src, "    tmp.%c += f32.%c*(%i/%i.0);\n",
-                               "xyzw"[i], "xyzw"[j],
-                               op->lin.m[i][j].num, op->lin.m[i][j].den);
+                    av_bprintf(&shd->src, "    tmp.%c += f32.%c*"QSTR";\n",
+                               "xyzw"[i], "xyzw"[j], QTYPE(op->lin.m[i][j]));
                 }
             }
             av_bprintf(&shd->src, "    f32 = tmp;\n");
-- 
2.52.0


>From 91f5b832818cdad4892df88006777607084725a1 Mon Sep 17 00:00:00 2001
From: Niklas Haas <[email protected]>
Date: Sat, 28 Mar 2026 17:57:47 +0100
Subject: [PATCH 3/7] swscale/ops_chain: remove unused helper function

Signed-off-by: Niklas Haas <[email protected]>
---
 libswscale/ops_chain.c | 12 ------------
 libswscale/ops_chain.h |  1 -
 2 files changed, 13 deletions(-)

diff --git a/libswscale/ops_chain.c b/libswscale/ops_chain.c
index df7867c248..65bd3029d3 100644
--- a/libswscale/ops_chain.c
+++ b/libswscale/ops_chain.c
@@ -269,18 +269,6 @@ int ff_sws_setup_u8(const SwsImplParams *params, 
SwsImplResult *out)
     return 0;
 }
 
-int ff_sws_setup_u(const SwsImplParams *params, SwsImplResult *out)
-{
-    const SwsOp *op = params->op;
-    switch (op->type) {
-    case SWS_PIXEL_U8:  out->priv.u8[0]  = op->c.u; return 0;
-    case SWS_PIXEL_U16: out->priv.u16[0] = op->c.u; return 0;
-    case SWS_PIXEL_U32: out->priv.u32[0] = op->c.u; return 0;
-    case SWS_PIXEL_F32: out->priv.f32[0] = op->c.u; return 0;
-    default: return AVERROR(EINVAL);
-    }
-}
-
 int ff_sws_setup_q(const SwsImplParams *params, SwsImplResult *out)
 {
     const SwsOp *op = params->op;
diff --git a/libswscale/ops_chain.h b/libswscale/ops_chain.h
index 60c83e6e9e..f9afe2b733 100644
--- a/libswscale/ops_chain.h
+++ b/libswscale/ops_chain.h
@@ -141,7 +141,6 @@ typedef struct SwsOpEntry {
 } SwsOpEntry;
 
 /* Setup helpers */
-int ff_sws_setup_u(const SwsImplParams *params, SwsImplResult *out);
 int ff_sws_setup_u8(const SwsImplParams *params, SwsImplResult *out);
 int ff_sws_setup_q(const SwsImplParams *params, SwsImplResult *out);
 int ff_sws_setup_q4(const SwsImplParams *params, SwsImplResult *out);
-- 
2.52.0


>From 51b457c759bfc5bd7d8dd58dc1553c75ef1dfcd0 Mon Sep 17 00:00:00 2001
From: Niklas Haas <[email protected]>
Date: Sat, 28 Mar 2026 18:01:25 +0100
Subject: [PATCH 4/7] swscale/ops_chain: split generic setup helpers into
 op-specific helpers

This has the side benefit of avoiding a division by zero when setting up
the clear constants for SWS_OP_CLEAR, since we can now continue out of the
loop in this case.

Signed-off-by: Niklas Haas <[email protected]>
---
 libswscale/aarch64/ops.c     |  6 +++--
 libswscale/ops_chain.c       | 43 +++++++++++++++++++++++++++---------
 libswscale/ops_chain.h       |  9 ++++----
 libswscale/ops_tmpl_common.c |  8 +++----
 libswscale/ops_tmpl_int.c    |  4 ++--
 libswscale/x86/ops.c         |  8 +++----
 6 files changed, 51 insertions(+), 27 deletions(-)

diff --git a/libswscale/aarch64/ops.c b/libswscale/aarch64/ops.c
index 4b204efd08..753aef51ae 100644
--- a/libswscale/aarch64/ops.c
+++ b/libswscale/aarch64/ops.c
@@ -143,12 +143,14 @@ static int aarch64_setup(SwsOpList *ops, int block_size, 
int n,
         }
         break;
     case SWS_OP_CLEAR:
+        ff_sws_setup_clear(&(const SwsImplParams) { .op = op }, out);
+        break;
     case SWS_OP_MIN:
     case SWS_OP_MAX:
-        ff_sws_setup_q4(&(const SwsImplParams) { .op = op }, out);
+        ff_sws_setup_clamp(&(const SwsImplParams) { .op = op }, out);
         break;
     case SWS_OP_SCALE:
-        ff_sws_setup_q(&(const SwsImplParams) { .op = op }, out);
+        ff_sws_setup_scale(&(const SwsImplParams) { .op = op }, out);
         break;
     case SWS_OP_LINEAR:
         return aarch64_setup_linear(p, op, out);
diff --git a/libswscale/ops_chain.c b/libswscale/ops_chain.c
index 65bd3029d3..c51c2b8e67 100644
--- a/libswscale/ops_chain.c
+++ b/libswscale/ops_chain.c
@@ -263,33 +263,54 @@ int ff_sws_op_compile_tables(SwsContext *ctx, const 
SwsOpTable *const tables[],
 
 #define q2pixel(type, q) ((q).den ? (type) (q).num / (q).den : 0)
 
-int ff_sws_setup_u8(const SwsImplParams *params, SwsImplResult *out)
+int ff_sws_setup_shift(const SwsImplParams *params, SwsImplResult *out)
 {
     out->priv.u8[0] = params->op->c.u;
     return 0;
 }
 
-int ff_sws_setup_q(const SwsImplParams *params, SwsImplResult *out)
+int ff_sws_setup_scale(const SwsImplParams *params, SwsImplResult *out)
 {
     const SwsOp *op = params->op;
+    const AVRational factor = op->c.q;
     switch (op->type) {
-    case SWS_PIXEL_U8:  out->priv.u8[0]  = q2pixel(uint8_t,  op->c.q); return 
0;
-    case SWS_PIXEL_U16: out->priv.u16[0] = q2pixel(uint16_t, op->c.q); return 
0;
-    case SWS_PIXEL_U32: out->priv.u32[0] = q2pixel(uint32_t, op->c.q); return 
0;
-    case SWS_PIXEL_F32: out->priv.f32[0] = q2pixel(float,    op->c.q); return 
0;
+    case SWS_PIXEL_U8:  out->priv.u8[0]  = q2pixel(uint8_t,  factor); return 0;
+    case SWS_PIXEL_U16: out->priv.u16[0] = q2pixel(uint16_t, factor); return 0;
+    case SWS_PIXEL_U32: out->priv.u32[0] = q2pixel(uint32_t, factor); return 0;
+    case SWS_PIXEL_F32: out->priv.f32[0] = q2pixel(float,    factor); return 0;
     default: return AVERROR(EINVAL);
     }
 }
 
-int ff_sws_setup_q4(const SwsImplParams *params, SwsImplResult *out)
+int ff_sws_setup_clamp(const SwsImplParams *params, SwsImplResult *out)
 {
     const SwsOp *op = params->op;
     for (int i = 0; i < 4; i++) {
+        const AVRational limit = op->c.q4[i];
         switch (op->type) {
-        case SWS_PIXEL_U8:  out->priv.u8[i]  = q2pixel(uint8_t,  op->c.q4[i]); 
break;
-        case SWS_PIXEL_U16: out->priv.u16[i] = q2pixel(uint16_t, op->c.q4[i]); 
break;
-        case SWS_PIXEL_U32: out->priv.u32[i] = q2pixel(uint32_t, op->c.q4[i]); 
break;
-        case SWS_PIXEL_F32: out->priv.f32[i] = q2pixel(float,    op->c.q4[i]); 
break;
+        case SWS_PIXEL_U8:  out->priv.u8[i]  = q2pixel(uint8_t,  limit); break;
+        case SWS_PIXEL_U16: out->priv.u16[i] = q2pixel(uint16_t, limit); break;
+        case SWS_PIXEL_U32: out->priv.u32[i] = q2pixel(uint32_t, limit); break;
+        case SWS_PIXEL_F32: out->priv.f32[i] = q2pixel(float,    limit); break;
+        default: return AVERROR(EINVAL);
+        }
+    }
+
+    return 0;
+}
+
+int ff_sws_setup_clear(const SwsImplParams *params, SwsImplResult *out)
+{
+    const SwsOp *op = params->op;
+    for (int i = 0; i < 4; i++) {
+        const AVRational value = op->c.q4[i];
+        if (!value.den)
+            continue;
+        switch (op->type) {
+        case SWS_PIXEL_U8:  out->priv.u8[i]  = q2pixel(uint8_t,  value); break;
+        case SWS_PIXEL_U16: out->priv.u16[i] = q2pixel(uint16_t, value); break;
+        case SWS_PIXEL_U32: out->priv.u32[i] = q2pixel(uint32_t, value); break;
+        case SWS_PIXEL_F32: out->priv.f32[i] = q2pixel(float,    value); break;
         default: return AVERROR(EINVAL);
         }
     }
diff --git a/libswscale/ops_chain.h b/libswscale/ops_chain.h
index f9afe2b733..fc0cd930f8 100644
--- a/libswscale/ops_chain.h
+++ b/libswscale/ops_chain.h
@@ -140,10 +140,11 @@ typedef struct SwsOpEntry {
     bool (*check)(const SwsImplParams *params); /* optional, return true if 
supported */
 } SwsOpEntry;
 
-/* Setup helpers */
-int ff_sws_setup_u8(const SwsImplParams *params, SwsImplResult *out);
-int ff_sws_setup_q(const SwsImplParams *params, SwsImplResult *out);
-int ff_sws_setup_q4(const SwsImplParams *params, SwsImplResult *out);
+/* Setup helpers for common/trivial operation types */
+int ff_sws_setup_shift(const SwsImplParams *params, SwsImplResult *out);
+int ff_sws_setup_scale(const SwsImplParams *params, SwsImplResult *out);
+int ff_sws_setup_clamp(const SwsImplParams *params, SwsImplResult *out);
+int ff_sws_setup_clear(const SwsImplParams *params, SwsImplResult *out);
 
 static inline void ff_op_priv_free(SwsOpPriv *priv)
 {
diff --git a/libswscale/ops_tmpl_common.c b/libswscale/ops_tmpl_common.c
index 5a0a399f32..3817a437e5 100644
--- a/libswscale/ops_tmpl_common.c
+++ b/libswscale/ops_tmpl_common.c
@@ -85,7 +85,7 @@ DECL_IMPL(clear##_##X##Y##Z##W)
 }                                                                              
 \
                                                                                
 \
 DECL_ENTRY(clear##_##X##Y##Z##W,                                               
 \
-    .setup = ff_sws_setup_q4,                                                  
 \
+    .setup = ff_sws_setup_clear,                                               
 \
     .op = SWS_OP_CLEAR,                                                        
 \
     .flexible = true,                                                          
 \
     .unused = { !X, !Y, !Z, !W },                                              
 \
@@ -141,13 +141,13 @@ DECL_PATTERN(max)
 
 WRAP_COMMON_PATTERNS(min,
     .op = SWS_OP_MIN,
-    .setup = ff_sws_setup_q4,
+    .setup = ff_sws_setup_clamp,
     .flexible = true,
 );
 
 WRAP_COMMON_PATTERNS(max,
     .op = SWS_OP_MAX,
-    .setup = ff_sws_setup_q4,
+    .setup = ff_sws_setup_clamp,
     .flexible = true,
 );
 
@@ -172,7 +172,7 @@ DECL_PATTERN(scale)
 
 WRAP_COMMON_PATTERNS(scale,
     .op = SWS_OP_SCALE,
-    .setup = ff_sws_setup_q,
+    .setup = ff_sws_setup_scale,
     .flexible = true,
 );
 
diff --git a/libswscale/ops_tmpl_int.c b/libswscale/ops_tmpl_int.c
index 960d0d9527..b010513bc5 100644
--- a/libswscale/ops_tmpl_int.c
+++ b/libswscale/ops_tmpl_int.c
@@ -383,13 +383,13 @@ DECL_PATTERN(rshift)
 
 WRAP_COMMON_PATTERNS(lshift,
     .op       = SWS_OP_LSHIFT,
-    .setup    = ff_sws_setup_u8,
+    .setup    = ff_sws_setup_shift,
     .flexible = true,
 );
 
 WRAP_COMMON_PATTERNS(rshift,
     .op       = SWS_OP_RSHIFT,
-    .setup    = ff_sws_setup_u8,
+    .setup    = ff_sws_setup_shift,
     .flexible = true,
 );
 #endif /* BIT_DEPTH != 8 */
diff --git a/libswscale/x86/ops.c b/libswscale/x86/ops.c
index 51c65c8ebb..734ffbac27 100644
--- a/libswscale/x86/ops.c
+++ b/libswscale/x86/ops.c
@@ -185,20 +185,20 @@ static int setup_shift(const SwsImplParams *params, 
SwsImplResult *out)
 #define DECL_MIN_MAX(EXT)                                                      
 \
     DECL_COMMON_PATTERNS(F32, min##EXT,                                        
 \
         .op = SWS_OP_MIN,                                                      
 \
-        .setup = ff_sws_setup_q4,                                              
 \
+        .setup = ff_sws_setup_clamp,                                           
 \
         .flexible = true,                                                      
 \
     );                                                                         
 \
                                                                                
 \
     DECL_COMMON_PATTERNS(F32, max##EXT,                                        
 \
         .op = SWS_OP_MAX,                                                      
 \
-        .setup = ff_sws_setup_q4,                                              
 \
+        .setup = ff_sws_setup_clamp,                                           
 \
         .flexible = true,                                                      
 \
     );
 
 #define DECL_SCALE(EXT)                                                        
 \
     DECL_COMMON_PATTERNS(F32, scale##EXT,                                      
 \
         .op = SWS_OP_SCALE,                                                    
 \
-        .setup = ff_sws_setup_q,                                               
 \
+        .setup = ff_sws_setup_scale,                                           
 \
         .flexible = true,                                                      
 \
     );
 
@@ -941,7 +941,7 @@ static void normalize_clear(SwsOp *op)
         int i;
     } c;
 
-    ff_sws_setup_q4(&(const SwsImplParams) { .op = op }, &res);
+    ff_sws_setup_clear(&(const SwsImplParams) { .op = op }, &res);
 
     for (int i = 0; i < 4; i++) {
         if (!op->c.q4[i].den)
-- 
2.52.0


>From e3615b5ed229d5d68a7eb266a7df5833c19d48a8 Mon Sep 17 00:00:00 2001
From: Niklas Haas <[email protected]>
Date: Sun, 29 Mar 2026 12:57:51 +0200
Subject: [PATCH 5/7] swscale/ops: define flags_identity as an enum constant

Signed-off-by: Niklas Haas <[email protected]>
---
 libswscale/ops.c | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/libswscale/ops.c b/libswscale/ops.c
index 1e6d68b210..8534b35c34 100644
--- a/libswscale/ops.c
+++ b/libswscale/ops.c
@@ -250,12 +250,15 @@ void ff_sws_apply_op_q(const SwsOp *op, AVRational x[4])
     av_unreachable("Invalid operation type!");
 }
 
-/* merge_comp_flags() forms a monoid with flags_identity as the null element */
-static const SwsCompFlags flags_identity = SWS_COMP_ZERO | SWS_COMP_EXACT;
+enum {
+    SWS_COMP_IDENTITY = SWS_COMP_ZERO | SWS_COMP_EXACT,
+};
+
+/* merge_comp_flags() forms a monoid with SWS_COMP_IDENTITY as the null 
element */
 static SwsCompFlags merge_comp_flags(SwsCompFlags a, SwsCompFlags b)
 {
     const SwsCompFlags flags_or  = SWS_COMP_GARBAGE;
-    const SwsCompFlags flags_and = SWS_COMP_ZERO | SWS_COMP_EXACT;
+    const SwsCompFlags flags_and = SWS_COMP_IDENTITY;
     return ((a & b) & flags_and) | ((a | b) & flags_or);
 }
 
@@ -390,7 +393,7 @@ void ff_sws_op_list_update_comps(SwsOpList *ops)
             }
             break;
         case SWS_OP_PACK: {
-            SwsCompFlags flags = flags_identity;
+            SwsCompFlags flags = SWS_COMP_IDENTITY;
             for (int i = 0; i < 4; i++) {
                 if (op->pack.pattern[i])
                     flags = merge_comp_flags(flags, prev.flags[i]);
@@ -426,7 +429,7 @@ void ff_sws_op_list_update_comps(SwsOpList *ops)
             break;
         case SWS_OP_LINEAR:
             for (int i = 0; i < 4; i++) {
-                SwsCompFlags flags = flags_identity;
+                SwsCompFlags flags = SWS_COMP_IDENTITY;
                 AVRational min = Q(0), max = Q(0);
                 for (int j = 0; j < 4; j++) {
                     const AVRational k = op->lin.m[i][j];
-- 
2.52.0


>From b0b9afdb42a5b71faebabc465719e2455e21a7fb Mon Sep 17 00:00:00 2001
From: Niklas Haas <[email protected]>
Date: Sun, 29 Mar 2026 13:02:35 +0200
Subject: [PATCH 6/7] swscale/ops: move comment (cosmetic)

Signed-off-by: Niklas Haas <[email protected]>
---
 libswscale/ops.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libswscale/ops.c b/libswscale/ops.c
index 8534b35c34..01d995252e 100644
--- a/libswscale/ops.c
+++ b/libswscale/ops.c
@@ -369,12 +369,12 @@ void ff_sws_op_list_update_comps(SwsOpList *ops)
             clear_undefined_values(op->comps.min, op->c.q4);
             break;
         case SWS_OP_DITHER:
-            /* Strip zero flag because of the nonzero dithering offset */
             for (int i = 0; i < 4; i++) {
                 op->comps.min[i] = prev.min[i];
                 op->comps.max[i] = prev.max[i];
                 if (op->dither.y_offset[i] < 0)
                     continue;
+                /* Strip zero flag because of the nonzero dithering offset */
                 op->comps.flags[i] = prev.flags[i] & ~SWS_COMP_ZERO;
                 op->comps.min[i] = av_add_q(op->comps.min[i], op->dither.min);
                 op->comps.max[i] = av_add_q(op->comps.max[i], op->dither.max);
-- 
2.52.0


>From aa07c78eeddfe5d0b558bb23e8ab17f5994e4571 Mon Sep 17 00:00:00 2001
From: Niklas Haas <[email protected]>
Date: Sat, 28 Mar 2026 18:45:26 +0100
Subject: [PATCH 7/7] swscale/ops: split SwsConst up into op-specific structs

It was a bit clunky, lacked semantic contextual information, and made it
harder to reason about the effects of extending this struct. There should be
zero runtime overhead as a result of the fact that this is already a big
union.

I made the changes in this commit by hand, but due to the length and noise
level of the commit, I used Opus 4.6 to verify that I did not accidentally
introduce any bugs or typos.

Signed-off-by: Niklas Haas <[email protected]>
---
 libswscale/aarch64/ops_impl_conv.c | 10 ++--
 libswscale/format.c                | 65 ++++++++++----------
 libswscale/ops.c                   | 46 +++++++-------
 libswscale/ops.h                   | 41 ++++++++-----
 libswscale/ops_chain.c             | 18 +++---
 libswscale/ops_memcpy.c            |  8 +--
 libswscale/ops_optimizer.c         | 96 +++++++++++++++---------------
 libswscale/tests/sws_ops.c         |  7 ++-
 libswscale/vulkan/ops.c            | 12 ++--
 libswscale/x86/ops.c               | 10 ++--
 tests/checkasm/sw_ops.c            | 78 ++++++++++++------------
 11 files changed, 205 insertions(+), 186 deletions(-)

diff --git a/libswscale/aarch64/ops_impl_conv.c 
b/libswscale/aarch64/ops_impl_conv.c
index fdc398392f..8f37af0101 100644
--- a/libswscale/aarch64/ops_impl_conv.c
+++ b/libswscale/aarch64/ops_impl_conv.c
@@ -181,14 +181,14 @@ static int convert_to_aarch64_impl(SwsContext *ctx, const 
SwsOpList *ops, int n,
         break;
     case AARCH64_SWS_OP_LSHIFT:
     case AARCH64_SWS_OP_RSHIFT:
-        out->shift = op->c.u;
+        out->shift = op->shift.amount;
         break;
     case AARCH64_SWS_OP_CLEAR:
         out->mask = 0;
-        MASK_SET(out->mask, 0, !!op->c.q4[0].den);
-        MASK_SET(out->mask, 1, !!op->c.q4[1].den);
-        MASK_SET(out->mask, 2, !!op->c.q4[2].den);
-        MASK_SET(out->mask, 3, !!op->c.q4[3].den);
+        MASK_SET(out->mask, 0, !!op->clear.value[0].den);
+        MASK_SET(out->mask, 1, !!op->clear.value[1].den);
+        MASK_SET(out->mask, 2, !!op->clear.value[2].den);
+        MASK_SET(out->mask, 3, !!op->clear.value[3].den);
         break;
     case AARCH64_SWS_OP_EXPAND:
     case AARCH64_SWS_OP_CONVERT:
diff --git a/libswscale/format.c b/libswscale/format.c
index 6fa279cc18..a26349585a 100644
--- a/libswscale/format.c
+++ b/libswscale/format.c
@@ -827,7 +827,7 @@ static int cmp_comp(const void *a, const void *b) {
 }
 
 static int fmt_analyze_regular(const AVPixFmtDescriptor *desc, SwsReadWriteOp 
*rw_op,
-                               SwsSwizzleOp *swizzle, int *shift)
+                               SwsSwizzleOp *swizzle, SwsShiftOp *shift)
 {
     if (desc->nb_components == 2) {
         /* YA formats */
@@ -848,7 +848,7 @@ static int fmt_analyze_regular(const AVPixFmtDescriptor 
*desc, SwsReadWriteOp *r
         *swizzle = swiz;
     }
 
-    *shift = desc->comp[0].shift;
+    *shift = (SwsShiftOp) { desc->comp[0].shift };
     *rw_op = (SwsReadWriteOp) {
         .elems  = desc->nb_components,
         .packed = desc->nb_components > 1 && !(desc->flags & 
AV_PIX_FMT_FLAG_PLANAR),
@@ -857,8 +857,9 @@ static int fmt_analyze_regular(const AVPixFmtDescriptor 
*desc, SwsReadWriteOp *r
 }
 
 static int fmt_analyze(enum AVPixelFormat fmt, SwsReadWriteOp *rw_op,
-                       SwsPackOp *pack_op, SwsSwizzleOp *swizzle, int *shift,
-                       SwsPixelType *pixel_type, SwsPixelType *raw_type)
+                       SwsPackOp *pack_op, SwsSwizzleOp *swizzle,
+                       SwsShiftOp *shift, SwsPixelType *pixel_type,
+                       SwsPixelType *raw_type)
 {
     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt);
     if (!desc)
@@ -889,7 +890,7 @@ static int fmt_analyze(enum AVPixelFormat fmt, 
SwsReadWriteOp *rw_op,
     *rw_op   = info.rw;
     *pack_op = info.pack;
     *swizzle = info.swizzle;
-    *shift   = info.shift;
+    *shift   = (SwsShiftOp) { info.shift };
 
     if (info.pack.pattern[0]) {
         const int sum = info.pack.pattern[0] + info.pack.pattern[1] +
@@ -923,17 +924,17 @@ static SwsSwizzleOp swizzle_inv(SwsSwizzleOp swiz) {
  * it will end up getting pushed towards the output or optimized away entirely
  * by the optimization pass.
  */
-static SwsConst fmt_clear(enum AVPixelFormat fmt)
+static SwsClearOp fmt_clear(enum AVPixelFormat fmt)
 {
     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt);
     const bool has_chroma = desc->nb_components >= 3;
     const bool has_alpha  = desc->flags & AV_PIX_FMT_FLAG_ALPHA;
 
-    SwsConst c = {0};
+    SwsClearOp c = {0};
     if (!has_chroma)
-        c.q4[1] = c.q4[2] = Q0;
+        c.value[1] = c.value[2] = Q0;
     if (!has_alpha)
-        c.q4[3] = Q0;
+        c.value[3] = Q0;
 
     return c;
 }
@@ -952,7 +953,7 @@ int ff_sws_decode_pixfmt(SwsOpList *ops, enum AVPixelFormat 
fmt)
     SwsSwizzleOp swizzle;
     SwsPackOp unpack;
     SwsComps *comps = &ops->comps_src;
-    int shift;
+    SwsShiftOp shift;
 
     RET(fmt_analyze(fmt, &rw_op, &unpack, &swizzle, &shift,
                     &pixel_type, &raw_type));
@@ -974,7 +975,7 @@ int ff_sws_decode_pixfmt(SwsOpList *ops, enum AVPixelFormat 
fmt)
          * canonical order {Y, U, V, A} */
         const int is_ya = desc->nb_components == 2;
         for (int c = 0; c < desc->nb_components; c++) {
-            const int bits   = desc->comp[c].depth + shift;
+            const int bits   = desc->comp[c].depth + shift.amount;
             const int idx    = swizzle.in[is_ya ? 3 * c : c];
             comps->min[idx]  = Q0;
             if (bits < 32) /* FIXME: AVRational is limited to INT_MAX */
@@ -1016,18 +1017,18 @@ int ff_sws_decode_pixfmt(SwsOpList *ops, enum 
AVPixelFormat fmt)
         .swizzle = swizzle,
     }));
 
-    if (shift) {
+    if (shift.amount) {
         RET(ff_sws_op_list_append(ops, &(SwsOp) {
-            .op   = SWS_OP_RSHIFT,
-            .type = pixel_type,
-            .c.u  = shift,
+            .op    = SWS_OP_RSHIFT,
+            .type  = pixel_type,
+            .shift = shift,
         }));
     }
 
     RET(ff_sws_op_list_append(ops, &(SwsOp) {
-        .op   = SWS_OP_CLEAR,
-        .type = pixel_type,
-        .c    = fmt_clear(fmt),
+        .op    = SWS_OP_CLEAR,
+        .type  = pixel_type,
+        .clear = fmt_clear(fmt),
     }));
 
     return 0;
@@ -1040,16 +1041,16 @@ int ff_sws_encode_pixfmt(SwsOpList *ops, enum 
AVPixelFormat fmt)
     SwsReadWriteOp rw_op;
     SwsSwizzleOp swizzle;
     SwsPackOp pack;
-    int shift;
+    SwsShiftOp shift;
 
     RET(fmt_analyze(fmt, &rw_op, &pack, &swizzle, &shift,
                     &pixel_type, &raw_type));
 
-    if (shift) {
+    if (shift.amount) {
         RET(ff_sws_op_list_append(ops, &(SwsOp) {
-            .op   = SWS_OP_LSHIFT,
-            .type = pixel_type,
-            .c.u  = shift,
+            .op    = SWS_OP_LSHIFT,
+            .type  = pixel_type,
+            .shift = shift,
         }));
     }
 
@@ -1059,7 +1060,7 @@ int ff_sws_encode_pixfmt(SwsOpList *ops, enum 
AVPixelFormat fmt)
         RET(ff_sws_op_list_append(ops, &(SwsOp) {
             .op   = SWS_OP_CLEAR,
             .type = pixel_type,
-            .c.q4[3] = Q0,
+            .clear.value[3] = Q0,
         }));
     }
 
@@ -1513,26 +1514,26 @@ int ff_sws_encode_colors(SwsContext *ctx, SwsPixelType 
type,
     }));
 
     if (!(dst->desc->flags & AV_PIX_FMT_FLAG_FLOAT)) {
-        SwsConst range = {0};
+        SwsClampOp range = {0};
 
         const bool is_ya = dst->desc->nb_components == 2;
         for (int i = 0; i < dst->desc->nb_components; i++) {
             /* Clamp to legal pixel range */
             const int idx = i * (is_ya ? 3 : 1);
-            range.q4[idx] = Q((1 << dst->desc->comp[i].depth) - 1);
+            range.limit[idx] = Q((1 << dst->desc->comp[i].depth) - 1);
         }
 
         RET(fmt_dither(ctx, ops, type, src, dst));
         RET(ff_sws_op_list_append(ops, &(SwsOp) {
-            .op   = SWS_OP_MAX,
-            .type = type,
-            .c.q4 = { Q0, Q0, Q0, Q0 },
+            .op    = SWS_OP_MAX,
+            .type  = type,
+            .clamp = {{ Q0, Q0, Q0, Q0 }},
         }));
 
         RET(ff_sws_op_list_append(ops, &(SwsOp) {
-            .op   = SWS_OP_MIN,
-            .type = type,
-            .c    = range,
+            .op    = SWS_OP_MIN,
+            .type  = type,
+            .clamp = range,
         }));
     }
 
diff --git a/libswscale/ops.c b/libswscale/ops.c
index 01d995252e..0824f4af48 100644
--- a/libswscale/ops.c
+++ b/libswscale/ops.c
@@ -177,13 +177,13 @@ void ff_sws_apply_op_q(const SwsOp *op, AVRational x[4])
         return;
     case SWS_OP_CLEAR:
         for (int i = 0; i < 4; i++) {
-            if (op->c.q4[i].den)
-                x[i] = op->c.q4[i];
+            if (op->clear.value[i].den)
+                x[i] = op->clear.value[i];
         }
         return;
     case SWS_OP_LSHIFT: {
         av_assert1(ff_sws_pixel_type_is_int(op->type));
-        AVRational mult = Q(1 << op->c.u);
+        AVRational mult = Q(1 << op->shift.amount);
         for (int i = 0; i < 4; i++)
             x[i] = x[i].den ? av_mul_q(x[i], mult) : x[i];
         return;
@@ -191,7 +191,7 @@ void ff_sws_apply_op_q(const SwsOp *op, AVRational x[4])
     case SWS_OP_RSHIFT: {
         av_assert1(ff_sws_pixel_type_is_int(op->type));
         for (int i = 0; i < 4; i++)
-            x[i] = x[i].den ? Q((x[i].num / x[i].den) >> op->c.u) : x[i];
+            x[i] = x[i].den ? Q((x[i].num / x[i].den) >> op->shift.amount) : 
x[i];
         return;
     }
     case SWS_OP_SWIZZLE: {
@@ -219,11 +219,11 @@ void ff_sws_apply_op_q(const SwsOp *op, AVRational x[4])
         return;
     case SWS_OP_MIN:
         for (int i = 0; i < 4; i++)
-            x[i] = av_min_q(x[i], op->c.q4[i]);
+            x[i] = av_min_q(x[i], op->clamp.limit[i]);
         return;
     case SWS_OP_MAX:
         for (int i = 0; i < 4; i++)
-            x[i] = av_max_q(x[i], op->c.q4[i]);
+            x[i] = av_max_q(x[i], op->clamp.limit[i]);
         return;
     case SWS_OP_LINEAR: {
         av_assert1(!ff_sws_pixel_type_is_int(op->type));
@@ -238,7 +238,7 @@ void ff_sws_apply_op_q(const SwsOp *op, AVRational x[4])
     }
     case SWS_OP_SCALE:
         for (int i = 0; i < 4; i++)
-            x[i] = x[i].den ? av_mul_q(x[i], op->c.q) : x[i];
+            x[i] = x[i].den ? av_mul_q(x[i], op->scale.factor) : x[i];
         return;
     case SWS_OP_FILTER_H:
     case SWS_OP_FILTER_V:
@@ -362,11 +362,11 @@ void ff_sws_op_list_update_comps(SwsOpList *ops)
             break;
         case SWS_OP_MIN:
             propagate_flags(op, &prev);
-            clear_undefined_values(op->comps.max, op->c.q4);
+            clear_undefined_values(op->comps.max, op->clamp.limit);
             break;
         case SWS_OP_MAX:
             propagate_flags(op, &prev);
-            clear_undefined_values(op->comps.min, op->c.q4);
+            clear_undefined_values(op->comps.min, op->clamp.limit);
             break;
         case SWS_OP_DITHER:
             for (int i = 0; i < 4; i++) {
@@ -405,11 +405,11 @@ void ff_sws_op_list_update_comps(SwsOpList *ops)
         }
         case SWS_OP_CLEAR:
             for (int i = 0; i < 4; i++) {
-                if (op->c.q4[i].den) {
+                if (op->clear.value[i].den) {
                     op->comps.flags[i] = 0;
-                    if (op->c.q4[i].num == 0)
+                    if (op->clear.value[i].num == 0)
                         op->comps.flags[i] |= SWS_COMP_ZERO;
-                    if (op->c.q4[i].den == 1)
+                    if (op->clear.value[i].den == 1)
                         op->comps.flags[i] |= SWS_COMP_EXACT;
                 } else {
                     op->comps.flags[i] = prev.flags[i];
@@ -460,9 +460,9 @@ void ff_sws_op_list_update_comps(SwsOpList *ops)
         case SWS_OP_SCALE:
             for (int i = 0; i < 4; i++) {
                 op->comps.flags[i] = prev.flags[i];
-                if (op->c.q.den != 1) /* fractional scale */
+                if (op->scale.factor.den != 1) /* fractional scale */
                     op->comps.flags[i] &= ~SWS_COMP_EXACT;
-                if (op->c.q.num < 0)
+                if (op->scale.factor.num < 0)
                     FFSWAP(AVRational, op->comps.min[i], op->comps.max[i]);
             }
             break;
@@ -524,7 +524,7 @@ void ff_sws_op_list_update_comps(SwsOpList *ops)
             break;
         case SWS_OP_CLEAR:
             for (int i = 0; i < 4; i++) {
-                if (!op->c.q4[i].den)
+                if (!op->clear.value[i].den)
                     need_in[i] = need_out[i];
             }
             break;
@@ -839,10 +839,10 @@ void ff_sws_op_desc(AVBPrint *bp, const SwsOp *op)
                    op->rw.filter == SWS_OP_FILTER_H ? 'H' : 'V');
         break;
     case SWS_OP_LSHIFT:
-        av_bprintf(bp, "%-20s: << %u", name, op->c.u);
+        av_bprintf(bp, "%-20s: << %u", name, op->shift.amount);
         break;
     case SWS_OP_RSHIFT:
-        av_bprintf(bp, "%-20s: >> %u", name, op->c.u);
+        av_bprintf(bp, "%-20s: >> %u", name, op->shift.amount);
         break;
     case SWS_OP_PACK:
     case SWS_OP_UNPACK:
@@ -852,7 +852,7 @@ void ff_sws_op_desc(AVBPrint *bp, const SwsOp *op)
         break;
     case SWS_OP_CLEAR:
         av_bprintf(bp, "%-20s: ", name);
-        print_q4(bp, op->c.q4, true, op->comps.flags);
+        print_q4(bp, op->clear.value, true, op->comps.flags);
         break;
     case SWS_OP_SWIZZLE:
         av_bprintf(bp, "%-20s: %d%d%d%d", name,
@@ -872,11 +872,11 @@ void ff_sws_op_desc(AVBPrint *bp, const SwsOp *op)
         break;
     case SWS_OP_MIN:
         av_bprintf(bp, "%-20s: x <= ", name);
-        print_q4(bp, op->c.q4, true, op->comps.flags);
+        print_q4(bp, op->clamp.limit, true, op->comps.flags);
         break;
     case SWS_OP_MAX:
         av_bprintf(bp, "%-20s: ", name);
-        print_q4(bp, op->c.q4, true, op->comps.flags);
+        print_q4(bp, op->clamp.limit, true, op->comps.flags);
         av_bprintf(bp, " <= x");
         break;
     case SWS_OP_LINEAR:
@@ -892,9 +892,9 @@ void ff_sws_op_desc(AVBPrint *bp, const SwsOp *op)
         av_bprintf(bp, "]");
         break;
     case SWS_OP_SCALE:
-        av_bprintf(bp, "%-20s: * %d", name, op->c.q.num);
-        if (op->c.q.den != 1)
-            av_bprintf(bp, "/%d", op->c.q.den);
+        av_bprintf(bp, "%-20s: * %d", name, op->scale.factor.num);
+        if (op->scale.factor.den != 1)
+            av_bprintf(bp, "/%d", op->scale.factor.den);
         break;
     case SWS_OP_FILTER_H:
     case SWS_OP_FILTER_V: {
diff --git a/libswscale/ops.h b/libswscale/ops.h
index a9e24ff5a9..c1723dfc6a 100644
--- a/libswscale/ops.h
+++ b/libswscale/ops.h
@@ -55,15 +55,15 @@ typedef enum SwsOpType {
     /* Bit manipulation operations. Defined for integers only. */
     SWS_OP_UNPACK,          /* split tightly packed data into components */
     SWS_OP_PACK,            /* compress components into tightly packed data */
-    SWS_OP_LSHIFT,          /* logical left shift of raw pixel values by (u8) 
*/
-    SWS_OP_RSHIFT,          /* right shift of raw pixel values by (u8) */
+    SWS_OP_LSHIFT,          /* logical left shift of raw pixel values */
+    SWS_OP_RSHIFT,          /* right shift of raw pixel values */
 
     /* Generic arithmetic. Defined and implemented for all types */
     SWS_OP_CLEAR,           /* clear pixel values */
     SWS_OP_CONVERT,         /* convert (cast) between formats */
-    SWS_OP_MIN,             /* numeric minimum (q4) */
-    SWS_OP_MAX,             /* numeric maximum (q4) */
-    SWS_OP_SCALE,           /* multiplication by scalar (q) */
+    SWS_OP_MIN,             /* numeric minimum */
+    SWS_OP_MAX,             /* numeric maximum */
+    SWS_OP_SCALE,           /* multiplication by scalar */
 
     /* Floating-point only arithmetic operations. */
     SWS_OP_LINEAR,          /* generalized linear affine transform */
@@ -87,16 +87,6 @@ typedef enum SwsCompFlags {
 
 #define SWS_OP_NEEDED(op, idx) (!((op)->comps.flags[idx] & SWS_COMP_GARBAGE))
 
-typedef union SwsConst {
-    /* Generic constant value */
-    AVRational q4[4];
-    AVRational q;
-    unsigned u;
-} SwsConst;
-
-static_assert(sizeof(SwsConst) == sizeof(AVRational) * 4,
-              "First field of SwsConst should span the entire union");
-
 typedef struct SwsComps {
     SwsCompFlags flags[4]; /* knowledge about (output) component contents */
     bool unused[4]; /* which input components are definitely unused */
@@ -152,11 +142,27 @@ typedef struct SwsSwizzleOp {
 
 #define SWS_SWIZZLE(X,Y,Z,W) ((SwsSwizzleOp) { .in = {X, Y, Z, W} })
 
+typedef struct SwsShiftOp {
+    uint8_t amount; /* number of bits to shift */
+} SwsShiftOp;
+
+typedef struct SwsClearOp {
+    AVRational value[4]; /* value to set, or {0, 0} for no-op */
+} SwsClearOp;
+
 typedef struct SwsConvertOp {
     SwsPixelType to; /* type of pixel to convert to */
     bool expand; /* if true, integers are expanded to the full range */
 } SwsConvertOp;
 
+typedef struct SwsClampOp {
+    AVRational limit[4]; /* per-component min/max value */
+} SwsClampOp;
+
+typedef struct SwsScaleOp {
+    AVRational factor; /* scalar multiplication factor */
+} SwsScaleOp;
+
 typedef struct SwsDitherOp {
     AVRational *matrix; /* tightly packed dither matrix (refstruct) */
     AVRational min, max; /* minimum/maximum value in `matrix` */
@@ -217,10 +223,13 @@ typedef struct SwsOp {
         SwsReadWriteOp  rw;
         SwsPackOp       pack;
         SwsSwizzleOp    swizzle;
+        SwsShiftOp      shift;
+        SwsClearOp      clear;
         SwsConvertOp    convert;
+        SwsClampOp      clamp;
+        SwsScaleOp      scale;
         SwsDitherOp     dither;
         SwsFilterOp     filter;
-        SwsConst        c;
     };
 
     /**
diff --git a/libswscale/ops_chain.c b/libswscale/ops_chain.c
index c51c2b8e67..87f0591c31 100644
--- a/libswscale/ops_chain.c
+++ b/libswscale/ops_chain.c
@@ -115,7 +115,9 @@ static int op_match(const SwsOp *op, const SwsOpEntry 
*entry)
     if (op->op == SWS_OP_CLEAR) {
         /* Clear pattern must match exactly, regardless of `entry->flexible` */
         for (int i = 0; i < 4; i++) {
-            if (SWS_OP_NEEDED(op, i) && entry->unused[i] != !!op->c.q4[i].den)
+            if (!SWS_OP_NEEDED(op, i))
+                continue;
+            if (entry->unused[i] != !!op->clear.value[i].den)
                 return 0;
         }
     }
@@ -147,9 +149,9 @@ static int op_match(const SwsOp *op, const SwsOpEntry 
*entry)
         return score;
     case SWS_OP_CLEAR:
         for (int i = 0; i < 4; i++) {
-            if (!op->c.q4[i].den || !SWS_OP_NEEDED(op, i))
+            if (!op->clear.value[i].den || !SWS_OP_NEEDED(op, i))
                 continue;
-            if (av_cmp_q(op->c.q4[i], Q(entry->clear_value)))
+            if (av_cmp_q(op->clear.value[i], Q(entry->clear_value)))
                 return 0;
         }
         return score;
@@ -188,7 +190,7 @@ static int op_match(const SwsOp *op, const SwsOpEntry 
*entry)
         score += av_popcount(SWS_MASK_ALL ^ entry->linear_mask);
         return score;
     case SWS_OP_SCALE:
-        return av_cmp_q(op->c.q, entry->scale) ? 0 : score;
+        return av_cmp_q(op->scale.factor, entry->scale) ? 0 : score;
     case SWS_OP_FILTER_H:
     case SWS_OP_FILTER_V:
         return score;
@@ -265,14 +267,14 @@ int ff_sws_op_compile_tables(SwsContext *ctx, const 
SwsOpTable *const tables[],
 
 int ff_sws_setup_shift(const SwsImplParams *params, SwsImplResult *out)
 {
-    out->priv.u8[0] = params->op->c.u;
+    out->priv.u8[0] = params->op->shift.amount;
     return 0;
 }
 
 int ff_sws_setup_scale(const SwsImplParams *params, SwsImplResult *out)
 {
     const SwsOp *op = params->op;
-    const AVRational factor = op->c.q;
+    const AVRational factor = op->scale.factor;
     switch (op->type) {
     case SWS_PIXEL_U8:  out->priv.u8[0]  = q2pixel(uint8_t,  factor); return 0;
     case SWS_PIXEL_U16: out->priv.u16[0] = q2pixel(uint16_t, factor); return 0;
@@ -286,7 +288,7 @@ int ff_sws_setup_clamp(const SwsImplParams *params, 
SwsImplResult *out)
 {
     const SwsOp *op = params->op;
     for (int i = 0; i < 4; i++) {
-        const AVRational limit = op->c.q4[i];
+        const AVRational limit = op->clamp.limit[i];
         switch (op->type) {
         case SWS_PIXEL_U8:  out->priv.u8[i]  = q2pixel(uint8_t,  limit); break;
         case SWS_PIXEL_U16: out->priv.u16[i] = q2pixel(uint16_t, limit); break;
@@ -303,7 +305,7 @@ int ff_sws_setup_clear(const SwsImplParams *params, 
SwsImplResult *out)
 {
     const SwsOp *op = params->op;
     for (int i = 0; i < 4; i++) {
-        const AVRational value = op->c.q4[i];
+        const AVRational value = op->clear.value[i];
         if (!value.den)
             continue;
         switch (op->type) {
diff --git a/libswscale/ops_memcpy.c b/libswscale/ops_memcpy.c
index a84067da6d..b7b56900ee 100644
--- a/libswscale/ops_memcpy.c
+++ b/libswscale/ops_memcpy.c
@@ -86,20 +86,20 @@ static int compile(SwsContext *ctx, SwsOpList *ops, 
SwsCompiledOp *out)
 
         case SWS_OP_CLEAR:
             for (int i = 0; i < 4; i++) {
-                if (!op->c.q4[i].den)
+                if (!op->clear.value[i].den)
                     continue;
-                if (op->c.q4[i].den != 1)
+                if (op->clear.value[i].den != 1)
                     return AVERROR(ENOTSUP);
 
                 /* Ensure all bytes to be cleared are the same, because we
                  * can't memset on multi-byte sequences */
-                uint8_t val = op->c.q4[i].num & 0xFF;
+                uint8_t val = op->clear.value[i].num & 0xFF;
                 uint32_t ref = val;
                 switch (ff_sws_pixel_type_size(op->type)) {
                 case 2: ref *= 0x101; break;
                 case 4: ref *= 0x1010101; break;
                 }
-                if (ref != op->c.q4[i].num)
+                if (ref != op->clear.value[i].num)
                     return AVERROR(ENOTSUP);
                 p.clear_value[i] = val;
                 p.index[i] = -1;
diff --git a/libswscale/ops_optimizer.c b/libswscale/ops_optimizer.c
index fd3c1ef969..f44a44e1b7 100644
--- a/libswscale/ops_optimizer.c
+++ b/libswscale/ops_optimizer.c
@@ -39,7 +39,7 @@
  */
 static bool op_commute_clear(SwsOp *op, SwsOp *next)
 {
-    SwsOp tmp;
+    SwsClearOp tmp;
 
     av_assert1(op->op == SWS_OP_CLEAR);
     switch (next->op) {
@@ -56,21 +56,21 @@ static bool op_commute_clear(SwsOp *op, SwsOp *next)
     case SWS_OP_SWIZZLE:
     case SWS_OP_FILTER_H:
     case SWS_OP_FILTER_V:
-        ff_sws_apply_op_q(next, op->c.q4);
+        ff_sws_apply_op_q(next, op->clear.value);
         return true;
     case SWS_OP_SWAP_BYTES:
         switch (next->type) {
         case SWS_PIXEL_U16:
-            ff_sws_apply_op_q(next, op->c.q4); /* always works */
+            ff_sws_apply_op_q(next, op->clear.value); /* always works */
             return true;
         case SWS_PIXEL_U32:
             for (int i = 0; i < 4; i++) {
-                uint32_t v = av_bswap32(op->c.q4[i].num);
+                uint32_t v = av_bswap32(op->clear.value[i].num);
                 if (v > INT_MAX)
                     return false; /* can't represent as AVRational anymore */
-                tmp.c.q4[i] = Q(v);
+                tmp.value[i] = Q(v);
             }
-            op->c = tmp.c;
+            op->clear = tmp;
             return true;
         default:
             return false;
@@ -124,14 +124,14 @@ static bool op_commute_swizzle(SwsOp *op, SwsOp *next)
      */
     case SWS_OP_MIN:
     case SWS_OP_MAX: {
-        const SwsConst c = next->c;
+        const SwsClampOp c = next->clamp;
         for (int i = 0; i < 4; i++) {
             if (!SWS_OP_NEEDED(op, i))
                 continue;
             const int j = op->swizzle.in[i];
-            if (seen[j] && av_cmp_q(next->c.q4[j], c.q4[i]))
+            if (seen[j] && av_cmp_q(next->clamp.limit[j], c.limit[i]))
                 return false;
-            next->c.q4[j] = c.q4[i];
+            next->clamp.limit[j] = c.limit[i];
             seen[j] = true;
         }
         return true;
@@ -238,9 +238,9 @@ static int exact_log2_q(const AVRational x)
  * the corresponding scaling factor, or 0 otherwise.
  */
 static bool extract_scalar(const SwsLinearOp *c, SwsComps comps, SwsComps prev,
-                           SwsConst *out_scale)
+                           SwsScaleOp *out_scale)
 {
-    SwsConst scale = {0};
+    SwsScaleOp scale = {0};
 
     /* There are components not on the main diagonal */
     if (c->mask & ~SWS_MASK_DIAG4)
@@ -251,21 +251,21 @@ static bool extract_scalar(const SwsLinearOp *c, SwsComps 
comps, SwsComps prev,
         if ((prev.flags[i]  & SWS_COMP_ZERO) ||
             (comps.flags[i] & SWS_COMP_GARBAGE))
             continue;
-        if (scale.q.den && av_cmp_q(s, scale.q))
+        if (scale.factor.den && av_cmp_q(s, scale.factor))
             return false;
-        scale.q = s;
+        scale.factor = s;
     }
 
-    if (scale.q.den)
+    if (scale.factor.den)
         *out_scale = scale;
-    return scale.q.den;
+    return scale.factor.den;
 }
 
 /* Extracts an integer clear operation (subset) from the given linear op. */
 static bool extract_constant_rows(SwsLinearOp *c, SwsComps prev,
-                                  SwsConst *out_clear)
+                                  SwsClearOp *out_clear)
 {
-    SwsConst clear = {0};
+    SwsClearOp clear = {0};
     bool ret = false;
 
     for (int i = 0; i < 4; i++) {
@@ -275,7 +275,7 @@ static bool extract_constant_rows(SwsLinearOp *c, SwsComps 
prev,
                          (prev.flags[j] & SWS_COMP_ZERO); /* input is zero */
         }
         if (const_row && (c->mask & SWS_MASK_ROW(i))) {
-            clear.q4[i] = c->m[i][4];
+            clear.value[i] = c->m[i][4];
             for (int j = 0; j < 5; j++)
                 c->m[i][j] = Q(i == j);
             c->mask &= ~SWS_MASK_ROW(i);
@@ -428,13 +428,13 @@ retry:
         case SWS_OP_RSHIFT:
             /* Two shifts in the same direction */
             if (next->op == op->op) {
-                op->c.u += next->c.u;
+                op->shift.amount += next->shift.amount;
                 ff_sws_op_list_remove_at(ops, n + 1, 1);
                 goto retry;
             }
 
             /* No-op shift */
-            if (!op->c.u) {
+            if (!op->shift.amount) {
                 ff_sws_op_list_remove_at(ops, n, 1);
                 goto retry;
             }
@@ -442,19 +442,19 @@ retry:
 
         case SWS_OP_CLEAR:
             for (int i = 0; i < 4; i++) {
-                if (!op->c.q4[i].den)
+                if (!op->clear.value[i].den)
                     continue;
 
                 if ((prev->comps.flags[i] & SWS_COMP_ZERO) &&
                     !(prev->comps.flags[i] & SWS_COMP_GARBAGE) &&
-                    op->c.q4[i].num == 0)
+                    op->clear.value[i].num == 0)
                 {
                     /* Redundant clear-to-zero of zero component */
-                    op->c.q4[i].den = 0;
+                    op->clear.value[i].den = 0;
                 } else if (!SWS_OP_NEEDED(op, i)) {
                     /* Unnecessary clear of unused component */
-                    op->c.q4[i] = (AVRational) {0, 0};
-                } else if (op->c.q4[i].den) {
+                    op->clear.value[i] = (AVRational) {0, 0};
+                } else if (op->clear.value[i].den) {
                     noop = false;
                 }
             }
@@ -467,8 +467,8 @@ retry:
             /* Transitive clear */
             if (next->op == SWS_OP_CLEAR) {
                 for (int i = 0; i < 4; i++) {
-                    if (next->c.q4[i].den)
-                        op->c.q4[i] = next->c.q4[i];
+                    if (next->clear.value[i].den)
+                        op->clear.value[i] = next->clear.value[i];
                 }
                 ff_sws_op_list_remove_at(ops, n + 1, 1);
                 goto retry;
@@ -548,7 +548,8 @@ retry:
             if (next->op == SWS_OP_SCALE && !op->convert.expand &&
                 ff_sws_pixel_type_is_int(op->type) &&
                 ff_sws_pixel_type_is_int(op->convert.to) &&
-                !av_cmp_q(next->c.q, ff_sws_pixel_expand(op->type, 
op->convert.to)))
+                !av_cmp_q(next->scale.factor,
+                          ff_sws_pixel_expand(op->type, op->convert.to)))
             {
                 op->convert.expand = true;
                 ff_sws_op_list_remove_at(ops, n + 1, 1);
@@ -558,9 +559,9 @@ retry:
 
         case SWS_OP_MIN:
             for (int i = 0; i < 4; i++) {
-                if (!SWS_OP_NEEDED(op, i) || !op->c.q4[i].den)
+                if (!SWS_OP_NEEDED(op, i) || !op->clamp.limit[i].den)
                     continue;
-                if (av_cmp_q(op->c.q4[i], prev->comps.max[i]) < 0)
+                if (av_cmp_q(op->clamp.limit[i], prev->comps.max[i]) < 0)
                     noop = false;
             }
 
@@ -572,9 +573,9 @@ retry:
 
         case SWS_OP_MAX:
             for (int i = 0; i < 4; i++) {
-                if (!SWS_OP_NEEDED(op, i) || !op->c.q4[i].den)
+                if (!SWS_OP_NEEDED(op, i) || !op->clamp.limit[i].den)
                     continue;
-                if (av_cmp_q(prev->comps.min[i], op->c.q4[i]) < 0)
+                if (av_cmp_q(prev->comps.min[i], op->clamp.limit[i]) < 0)
                     noop = false;
             }
 
@@ -604,7 +605,8 @@ retry:
 
         case SWS_OP_LINEAR: {
             SwsSwizzleOp swizzle;
-            SwsConst c;
+            SwsClearOp clear;
+            SwsScaleOp scale;
 
             /* No-op (identity) linear operation */
             if (!op->lin.mask) {
@@ -654,20 +656,20 @@ retry:
             }
 
             /* Convert constant rows to explicit clear instruction */
-            if (extract_constant_rows(&op->lin, prev->comps, &c)) {
+            if (extract_constant_rows(&op->lin, prev->comps, &clear)) {
                 RET(ff_sws_op_list_insert_at(ops, n + 1, &(SwsOp) {
                     .op    = SWS_OP_CLEAR,
                     .type  = op->type,
                     .comps = op->comps,
-                    .c     = c,
+                    .clear = clear,
                 }));
                 goto retry;
             }
 
             /* Multiplication by scalar constant */
-            if (extract_scalar(&op->lin, op->comps, prev->comps, &c)) {
-                op->op = SWS_OP_SCALE;
-                op->c  = c;
+            if (extract_scalar(&op->lin, op->comps, prev->comps, &scale)) {
+                op->op    = SWS_OP_SCALE;
+                op->scale = scale;
                 goto retry;
             }
 
@@ -684,20 +686,20 @@ retry:
         }
 
         case SWS_OP_SCALE: {
-            const int factor2 = exact_log2_q(op->c.q);
+            const int factor2 = exact_log2_q(op->scale.factor);
 
             /* No-op scaling */
-            if (op->c.q.num == 1 && op->c.q.den == 1) {
+            if (op->scale.factor.num == 1 && op->scale.factor.den == 1) {
                 ff_sws_op_list_remove_at(ops, n, 1);
                 goto retry;
             }
 
             /* Merge consecutive scaling operations (that don't overflow) */
             if (next->op == SWS_OP_SCALE) {
-                int64_t p = op->c.q.num * (int64_t) next->c.q.num;
-                int64_t q = op->c.q.den * (int64_t) next->c.q.den;
+                int64_t p = op->scale.factor.num * (int64_t) 
next->scale.factor.num;
+                int64_t q = op->scale.factor.den * (int64_t) 
next->scale.factor.den;
                 if (FFABS(p) <= INT_MAX && FFABS(q) <= INT_MAX) {
-                    av_reduce(&op->c.q.num, &op->c.q.den, p, q, INT_MAX);
+                    av_reduce(&op->scale.factor.num, &op->scale.factor.den, p, 
q, INT_MAX);
                     ff_sws_op_list_remove_at(ops, n + 1, 1);
                     goto retry;
                 }
@@ -706,7 +708,7 @@ retry:
             /* Scaling by exact power of two */
             if (factor2 && ff_sws_pixel_type_is_int(op->type)) {
                 op->op = factor2 > 0 ? SWS_OP_LSHIFT : SWS_OP_RSHIFT;
-                op->c.u = FFABS(factor2);
+                op->shift.amount = FFABS(factor2);
                 goto retry;
             }
             break;
@@ -760,7 +762,7 @@ retry:
 
         case SWS_OP_SCALE:
             /* Scaling by integer before conversion to int */
-            if (op->c.q.den == 1 && next->op == SWS_OP_CONVERT &&
+            if (op->scale.factor.den == 1 && next->op == SWS_OP_CONVERT &&
                 ff_sws_pixel_type_is_int(next->convert.to))
             {
                 op->type = next->convert.to;
@@ -812,9 +814,9 @@ int ff_sws_solve_shuffle(const SwsOpList *const ops, 
uint8_t shuffle[],
 
         case SWS_OP_CLEAR:
             for (int i = 0; i < 4; i++) {
-                if (!op->c.q4[i].den)
+                if (!op->clear.value[i].den)
                     continue;
-                if (op->c.q4[i].num != 0 || !clear_val)
+                if (op->clear.value[i].num != 0 || !clear_val)
                     return AVERROR(ENOTSUP);
                 mask[i] = 0x1010101ul * clear_val;
             }
diff --git a/libswscale/tests/sws_ops.c b/libswscale/tests/sws_ops.c
index 02049156e7..05378be18d 100644
--- a/libswscale/tests/sws_ops.c
+++ b/libswscale/tests/sws_ops.c
@@ -65,11 +65,16 @@ static int register_op(SwsContext *ctx, void *opaque, SwsOp 
*op)
         }
         break;
     case SWS_OP_SCALE:
+        op->scale.factor = (AVRational) { 0, 1 };
+        break;
     case SWS_OP_MIN:
     case SWS_OP_MAX:
+        for (int i = 0; i < 4; i++)
+            op->clamp.limit[i] = (AVRational) { 0, 1 };
+        break;
     case SWS_OP_CLEAR:
         for (int i = 0; i < 4; i++)
-            op->c.q4[i] = (AVRational) { 0, !!op->c.q4[i].den };
+            op->clear.value[i] = (AVRational) { 0, !!op->clear.value[i].den };
         break;
     case SWS_OP_DITHER:
         /* Strip arbitrary offset */
diff --git a/libswscale/vulkan/ops.c b/libswscale/vulkan/ops.c
index fece479cd3..adf81864a4 100644
--- a/libswscale/vulkan/ops.c
+++ b/libswscale/vulkan/ops.c
@@ -274,32 +274,32 @@ static int add_ops_glsl(VulkanPriv *p, FFVulkanOpsCtx *s,
         }
         case SWS_OP_CLEAR: {
             for (int i = 0; i < 4; i++) {
-                if (!op->c.q4[i].den)
+                if (!op->clear.value[i].den)
                     continue;
                 av_bprintf(&shd->src, "    %s.%c = %s"QSTR";\n", type_name,
-                           "xyzw"[i], type_s, QTYPE(op->c.q4[i]));
+                           "xyzw"[i], type_s, QTYPE(op->clear.value[i]));
             }
             break;
         }
         case SWS_OP_SCALE:
             av_bprintf(&shd->src, "    %s = %s * "QSTR";\n",
-                       type_name, type_name, QTYPE(op->c.q));
+                       type_name, type_name, QTYPE(op->scale.factor));
             break;
         case SWS_OP_MIN:
         case SWS_OP_MAX:
             for (int i = 0; i < 4; i++) {
-                if (!op->c.q4[i].den)
+                if (!op->clamp.limit[i].den)
                     continue;
                 av_bprintf(&shd->src, "    %s.%c = %s(%s.%c, "QSTR");\n",
                            type_name, "xyzw"[i],
                            op->op == SWS_OP_MIN ? "min" : "max",
-                           type_name, "xyzw"[i], QTYPE(op->c.q4[i]));
+                           type_name, "xyzw"[i], QTYPE(op->clamp.limit[i]));
             }
             break;
         case SWS_OP_LSHIFT:
         case SWS_OP_RSHIFT:
             av_bprintf(&shd->src, "    %s %s= %i;\n", type_name,
-                       op->op == SWS_OP_LSHIFT ? "<<" : ">>", op->c.u);
+                       op->op == SWS_OP_LSHIFT ? "<<" : ">>", 
op->shift.amount);
             break;
         case SWS_OP_CONVERT:
             if (ff_sws_pixel_type_is_int(cur_type) && op->convert.expand) {
diff --git a/libswscale/x86/ops.c b/libswscale/x86/ops.c
index 734ffbac27..ab113aa780 100644
--- a/libswscale/x86/ops.c
+++ b/libswscale/x86/ops.c
@@ -133,7 +133,7 @@ static int setup_clear(const SwsImplParams *params, 
SwsImplResult *out)
 {
     const SwsOp *op = params->op;
     for (int i = 0; i < 4; i++)
-        out->priv.u32[i] = (uint32_t) op->c.q4[i].num;
+        out->priv.u32[i] = (uint32_t) op->clear.value[i].num;
     return 0;
 }
 
@@ -165,7 +165,7 @@ static int setup_clear(const SwsImplParams *params, 
SwsImplResult *out)
 
 static int setup_shift(const SwsImplParams *params, SwsImplResult *out)
 {
-    out->priv.u16[0] = params->op->c.u;
+    out->priv.u16[0] = params->op->shift.amount;
     return 0;
 }
 
@@ -944,7 +944,7 @@ static void normalize_clear(SwsOp *op)
     ff_sws_setup_clear(&(const SwsImplParams) { .op = op }, &res);
 
     for (int i = 0; i < 4; i++) {
-        if (!op->c.q4[i].den)
+        if (!op->clear.value[i].den)
             continue;
         switch (ff_sws_pixel_type_size(op->type)) {
         case 1: c.u32 = 0x1010101U * res.priv.u8[i]; break;
@@ -952,8 +952,8 @@ static void normalize_clear(SwsOp *op)
         case 4: c.u32 = res.priv.u32[i]; break;
         }
 
-        op->c.q4[i].num = c.i;
-        op->c.q4[i].den = 1;
+        op->clear.value[i].num = c.i;
+        op->clear.value[i].den = 1;
     }
 }
 
diff --git a/tests/checkasm/sw_ops.c b/tests/checkasm/sw_ops.c
index 570fbfc825..39a053172c 100644
--- a/tests/checkasm/sw_ops.c
+++ b/tests/checkasm/sw_ops.c
@@ -498,45 +498,45 @@ static void check_clear(void)
             const AVRational zero   = (AVRational) { 0, 1};
             const AVRational none = {0};
 
-            const SwsConst patterns[] = {
+            const SwsClearOp patterns[] = {
                 /* Zero only */
-                {.q4 = {   none,   none,   none,   zero }},
-                {.q4 = {   zero,   none,   none,   none }},
+                {{   none,   none,   none,   zero }},
+                {{   zero,   none,   none,   none }},
                 /* Alpha only */
-                {.q4 = {   none,   none,   none,  alpha }},
-                {.q4 = {  alpha,   none,   none,   none }},
+                {{   none,   none,   none,  alpha }},
+                {{  alpha,   none,   none,   none }},
                 /* Chroma only */
-                {.q4 = { chroma, chroma,   none,   none }},
-                {.q4 = {   none, chroma, chroma,   none }},
-                {.q4 = {   none,   none, chroma, chroma }},
-                {.q4 = { chroma,   none, chroma,   none }},
-                {.q4 = {   none, chroma,   none, chroma }},
+                {{ chroma, chroma,   none,   none }},
+                {{   none, chroma, chroma,   none }},
+                {{   none,   none, chroma, chroma }},
+                {{ chroma,   none, chroma,   none }},
+                {{   none, chroma,   none, chroma }},
                 /* Alpha+chroma */
-                {.q4 = { chroma, chroma,   none,  alpha }},
-                {.q4 = {   none, chroma, chroma,  alpha }},
-                {.q4 = {  alpha,   none, chroma, chroma }},
-                {.q4 = { chroma,   none, chroma,  alpha }},
-                {.q4 = {  alpha, chroma,   none, chroma }},
+                {{ chroma, chroma,   none,  alpha }},
+                {{   none, chroma, chroma,  alpha }},
+                {{  alpha,   none, chroma, chroma }},
+                {{ chroma,   none, chroma,  alpha }},
+                {{  alpha, chroma,   none, chroma }},
                 /* Random values */
-                {.q4 = { none, rndq(t), rndq(t), rndq(t) }},
-                {.q4 = { none, rndq(t), rndq(t), rndq(t) }},
-                {.q4 = { none, rndq(t), rndq(t), rndq(t) }},
-                {.q4 = { none, rndq(t), rndq(t), rndq(t) }},
+                {{ none, rndq(t), rndq(t), rndq(t) }},
+                {{ none, rndq(t), rndq(t), rndq(t) }},
+                {{ none, rndq(t), rndq(t), rndq(t) }},
+                {{ none, rndq(t), rndq(t), rndq(t) }},
             };
 
             for (int i = 0; i < FF_ARRAY_ELEMS(patterns); i++) {
                 CHECK(FMT("clear_pattern_%s[%d]", type, i), 4, 4, t, t, {
-                    .op   = SWS_OP_CLEAR,
-                    .type = t,
-                    .c    = patterns[i],
+                    .op    = SWS_OP_CLEAR,
+                    .type  = t,
+                    .clear = patterns[i],
                 });
             }
         } else if (!ff_sws_pixel_type_is_int(t)) {
             /* Floating point YUV doesn't exist, only alpha needs to be 
cleared */
             CHECK(FMT("clear_alpha_%s", type), 4, 4, t, t, {
-                .op      = SWS_OP_CLEAR,
-                .type    = t,
-                .c.q4[3] = { 0, 1 },
+                .op   = SWS_OP_CLEAR,
+                .type = t,
+                .clear.value[3] = { 0, 1 },
             });
         }
     }
@@ -551,15 +551,15 @@ static void check_shift(void)
 
         for (int shift = 1; shift <= 8; shift++) {
             CHECK_COMMON(FMT("lshift%d_%s", shift, type), t, t, {
-                .op   = SWS_OP_LSHIFT,
-                .type = t,
-                .c.u  = shift,
+                .op    = SWS_OP_LSHIFT,
+                .type  = t,
+                .shift = { shift },
             });
 
             CHECK_COMMON(FMT("rshift%d_%s", shift, type), t, t, {
-                .op   = SWS_OP_RSHIFT,
-                .type = t,
-                .c.u  = shift,
+                .op    = SWS_OP_RSHIFT,
+                .type  = t,
+                .shift = { shift },
             });
         }
     }
@@ -697,13 +697,13 @@ static void check_min_max(void)
         CHECK_COMMON(FMT("min_%s", type), t, t, {
             .op = SWS_OP_MIN,
             .type = t,
-            .c.q4 = { rndq(t), rndq(t), rndq(t), rndq(t) },
+            .clamp = {{ rndq(t), rndq(t), rndq(t), rndq(t) }},
         });
 
         CHECK_COMMON(FMT("max_%s", type), t, t, {
             .op = SWS_OP_MAX,
             .type = t,
-            .c.q4 = { rndq(t), rndq(t), rndq(t), rndq(t) },
+            .clamp = {{ rndq(t), rndq(t), rndq(t), rndq(t) }},
         });
     }
 }
@@ -776,15 +776,15 @@ static void check_scale(void)
             const unsigned scale = rnd() & max;
             const unsigned range = max / (scale ? scale : 1);
             CHECK_COMMON_RANGE(FMT("scale_%s", type), range, t, t, {
-                .op   = SWS_OP_SCALE,
-                .type = t,
-                .c.q  = { scale, 1 },
+                .op    = SWS_OP_SCALE,
+                .type  = t,
+                .scale = {{ scale, 1 }},
             });
         } else {
             CHECK_COMMON(FMT("scale_%s", type), t, t, {
-                .op   = SWS_OP_SCALE,
-                .type = t,
-                .c.q  = rndq(t),
+                .op    = SWS_OP_SCALE,
+                .type  = t,
+                .scale = { rndq(t) },
             });
         }
     }
-- 
2.52.0

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

Reply via email to