Commit 40997528d5 for ffmpeg

commit 40997528d5f344c4aca3856e2fb879dee2267274
Author: Niklas Haas <git@haasn.dev>
Date:   Tue Oct 20 22:22:38 2026 +0200

    swscale/ops: store SwsPixelType in SwsReadWriteOp

    This is redundant with SwsOp.type, but that field will be removed.

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

diff --git a/libswscale/format.c b/libswscale/format.c
index 1167c0446c..cf37a5633d 100644
--- a/libswscale/format.c
+++ b/libswscale/format.c
@@ -760,9 +760,8 @@ static inline const AVPixFmtDescriptor *fmt_desc_decoded(enum AVPixelFormat fmt)
 }

 /* Returns the type suitable for a pixel after fully decoding/unpacking it */
-static SwsPixelType fmt_pixel_type(enum AVPixelFormat fmt)
+static SwsPixelType fmt_pixel_type(const AVPixFmtDescriptor *desc)
 {
-    const AVPixFmtDescriptor *desc = fmt_desc_decoded(fmt);
     const int bits = FFALIGN(desc->comp[0].depth, 8);
     if (desc->flags & AV_PIX_FMT_FLAG_FLOAT) {
         switch (bits) {
@@ -962,6 +961,7 @@ static int fmt_analyze_regular(const AVPixFmtDescriptor *desc, SwsReadWriteOp *r

     *shift = (SwsShiftOp) { desc->comp[0].shift };
     *rw_op = (SwsReadWriteOp) {
+        .type  = fmt_pixel_type(desc),
         .elems = desc->nb_components,
         .mode  = mode,
     };
@@ -970,8 +970,7 @@ 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,
-                       SwsShiftOp *shift, SwsPixelType *pixel_type,
-                       SwsPixelType *raw_type)
+                       SwsShiftOp *shift, SwsPixelType *pixel_type)
 {
     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt);
     if (!desc)
@@ -986,7 +985,7 @@ static int fmt_analyze(enum AVPixelFormat fmt, SwsReadWriteOp *rw_op,
         av_pix_fmt_count_planes(fmt) < desc->nb_components)
         return AVERROR(ENOTSUP);

-    *pixel_type = *raw_type = fmt_pixel_type(fmt);
+    *pixel_type = fmt_pixel_type(desc);
     if (!*pixel_type)
         return AVERROR(ENOTSUP);

@@ -1008,11 +1007,13 @@ static int fmt_analyze(enum AVPixelFormat fmt, SwsReadWriteOp *rw_op,
         const int sum = info.pack.pattern[0] + info.pack.pattern[1] +
                         info.pack.pattern[2] + info.pack.pattern[3];
         if (sum > 16)
-            *raw_type = SWS_PIXEL_U32;
+            rw_op->type = SWS_PIXEL_U32;
         else if (sum > 8)
-            *raw_type = SWS_PIXEL_U16;
+            rw_op->type = SWS_PIXEL_U16;
         else
-            *raw_type = SWS_PIXEL_U8;
+            rw_op->type = SWS_PIXEL_U8;
+    } else {
+        rw_op->type = *pixel_type;
     }

     return 0;
@@ -1024,9 +1025,8 @@ static int test_format_ops(enum AVPixelFormat format, int output)
     SwsSwizzleOp swizzle;
     SwsPackOp pack;
     SwsShiftOp shift;
-    SwsPixelType pixel_type, raw_type;
-    int ret = fmt_analyze(format, &rw, &pack, &swizzle, &shift,
-                          &pixel_type, &raw_type);
+    SwsPixelType pixel_type;
+    int ret = fmt_analyze(format, &rw, &pack, &swizzle, &shift, &pixel_type);
     if (ret < 0)
         return 0;
     if (rw.mode == SWS_RW_PALETTE && output)
@@ -1089,21 +1089,19 @@ static inline AVRational64 intmax_q64(int bits)
 static int decode_pixfmt(SwsOpList *ops, const SwsFormat *fmt)
 {
     const AVPixFmtDescriptor *desc = fmt_desc_decoded(fmt->format);
-    SwsPixelType pixel_type, raw_type;
+    SwsPixelType pixel_type;
     SwsReadWriteOp rw_op;
     SwsSwizzleOp swizzle;
     SwsPackOp unpack;
     SwsOpPad *inputs = ops->inputs;
     SwsShiftOp shift;

-    RET(fmt_analyze(fmt->format, &rw_op, &unpack, &swizzle, &shift,
-                    &pixel_type, &raw_type));
-
+    RET(fmt_analyze(fmt->format, &rw_op, &unpack, &swizzle, &shift, &pixel_type));
     swizzle_inv(&swizzle);

     /* Set baseline pixel content flags */
-    const int integer = ff_sws_pixel_type_is_int(raw_type);
-    const int swapped = ff_sws_pixel_type_size(raw_type) > 1 &&
+    const int integer = ff_sws_pixel_type_is_int(rw_op.type);
+    const int swapped = ff_sws_pixel_type_size(rw_op.type) > 1 &&
                         (desc->flags & AV_PIX_FMT_FLAG_BE) != NATIVE_ENDIAN_FLAG;
     for (int i = 0; i < rw_op.elems; i++) {
         inputs[i].flags = (integer ? SWS_COMP_EXACT   : 0) |
@@ -1126,27 +1124,27 @@ static int decode_pixfmt(SwsOpList *ops, const SwsFormat *fmt)
     /* TODO: handle subsampled or semipacked input formats */
     RET(ff_sws_op_list_append(ops, &(SwsOp) {
         .op    = SWS_OP_READ,
-        .type  = raw_type,
+        .type  = rw_op.type,
         .rw    = rw_op,
     }));

     if (swapped) {
         RET(ff_sws_op_list_append(ops, &(SwsOp) {
             .op   = SWS_OP_SWAP_BYTES,
-            .type = raw_type,
+            .type = rw_op.type,
         }));
     }

     if (unpack.pattern[0]) {
         RET(ff_sws_op_list_append(ops, &(SwsOp) {
             .op   = SWS_OP_UNPACK,
-            .type = raw_type,
+            .type = rw_op.type,
             .pack = unpack,
         }));

         RET(ff_sws_op_list_append(ops, &(SwsOp) {
             .op   = SWS_OP_CONVERT,
-            .type = raw_type,
+            .type = rw_op.type,
             .convert.to = pixel_type,
         }));
     }
@@ -1178,15 +1176,13 @@ static int decode_pixfmt(SwsOpList *ops, const SwsFormat *fmt)
 static int encode_pixfmt(SwsOpList *ops, const SwsFormat *fmt)
 {
     const AVPixFmtDescriptor *desc = fmt_desc_decoded(fmt->format);
-    SwsPixelType pixel_type, raw_type;
+    SwsPixelType pixel_type;
     SwsReadWriteOp rw_op;
     SwsSwizzleOp swizzle;
     SwsPackOp pack;
     SwsShiftOp shift;

-    RET(fmt_analyze(fmt->format, &rw_op, &pack, &swizzle, &shift,
-                    &pixel_type, &raw_type));
-
+    RET(fmt_analyze(fmt->format, &rw_op, &pack, &swizzle, &shift, &pixel_type));
     if (rw_op.mode == SWS_RW_PALETTE)
         return AVERROR(ENOTSUP);

@@ -1219,27 +1215,27 @@ static int encode_pixfmt(SwsOpList *ops, const SwsFormat *fmt)
         RET(ff_sws_op_list_append(ops, &(SwsOp) {
             .op   = SWS_OP_CONVERT,
             .type = pixel_type,
-            .convert.to = raw_type,
+            .convert.to = rw_op.type,
         }));

         RET(ff_sws_op_list_append(ops, &(SwsOp) {
             .op   = SWS_OP_PACK,
-            .type = raw_type,
+            .type = rw_op.type,
             .pack = pack,
         }));
     }

-    if (ff_sws_pixel_type_size(raw_type) > 1 &&
+    if (ff_sws_pixel_type_size(rw_op.type) > 1 &&
         (desc->flags & AV_PIX_FMT_FLAG_BE) != NATIVE_ENDIAN_FLAG) {
         RET(ff_sws_op_list_append(ops, &(SwsOp) {
             .op   = SWS_OP_SWAP_BYTES,
-            .type = raw_type,
+            .type = rw_op.type,
         }));
     }

     RET(ff_sws_op_list_append(ops, &(SwsOp) {
         .op   = SWS_OP_WRITE,
-        .type = raw_type,
+        .type = rw_op.type,
         .rw   = rw_op,
     }));

@@ -1504,7 +1500,7 @@ static int decode_colors(SwsContext *ctx, SwsPixelType type, SwsOpList *ops,
                          const SwsFormat *fmt, bool *incomplete)
 {
     const AVLumaCoefficients *c = av_csp_luma_coeffs_from_avcsp(fmt->csp);
-    const SwsPixelType pixel_type = fmt_pixel_type(fmt->format);
+    const SwsPixelType pixel_type = fmt_pixel_type(fmt->desc);
     if (!pixel_type)
          return AVERROR(ENOTSUP);

@@ -1598,7 +1594,7 @@ static int encode_colors(SwsContext *ctx, SwsPixelType type, SwsOpList *ops,
                          bool *incomplete)
 {
     const AVLumaCoefficients *c = av_csp_luma_coeffs_from_avcsp(dst->csp);
-    const SwsPixelType pixel_type = fmt_pixel_type(dst->format);
+    const SwsPixelType pixel_type = fmt_pixel_type(dst->desc);
     if (!pixel_type)
          return AVERROR(ENOTSUP);

diff --git a/libswscale/ops.c b/libswscale/ops.c
index 1100ce59ba..895fefc7ef 100644
--- a/libswscale/ops.c
+++ b/libswscale/ops.c
@@ -783,7 +783,7 @@ bool ff_sws_op_list_is_noop(const SwsOpList *ops)
     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.type != write->rw.type ||
         read->rw.mode != write->rw.mode ||
         read->rw.elems != write->rw.elems ||
         read->rw.frac != write->rw.frac ||
@@ -901,8 +901,9 @@ void ff_sws_op_desc(AVBPrint *bp, const SwsOp *op)
         break;
     case SWS_OP_READ:
     case SWS_OP_WRITE:
+        av_assert0(op->rw.type == op->type);
         av_bprintf(bp, "%-20s: %dx %s %s >> %d", name,
-                   op->rw.elems, ff_sws_pixel_type_name(op->type),
+                   op->rw.elems, ff_sws_pixel_type_name(op->rw.type),
                    rw_mode_names[op->rw.mode], op->rw.frac);
         if (!op->rw.filter.op)
             break;
diff --git a/libswscale/ops.h b/libswscale/ops.h
index 5a74434c9f..addfce7583 100644
--- a/libswscale/ops.h
+++ b/libswscale/ops.h
@@ -99,6 +99,7 @@ typedef struct SwsReadWriteOp {
      *   rgb4      = 1x u8 (frac 1)
      *   pal8      = 4x u8 (palette)
      */
+    SwsPixelType type;     /* pixel type to read */
     SwsReadWriteMode mode; /* how data is laid out in memory */
     uint8_t elems; /* number of elements (of type `op.type`) to read/write */
     uint8_t frac;  /* fractional pixel step factor (log2) */
diff --git a/libswscale/ops_dispatch.c b/libswscale/ops_dispatch.c
index 3177f4b667..d2669d6cbd 100644
--- a/libswscale/ops_dispatch.c
+++ b/libswscale/ops_dispatch.c
@@ -475,7 +475,7 @@ static void op_list_get_plane_copy(const SwsOpList *ops, SwsPass *pass)
     const SwsOp *read  = ff_sws_op_list_input(ops);
     if (!write || write->rw.mode != SWS_RW_PLANAR ||
         !read  || read->rw.mode  != SWS_RW_PLANAR ||
-        read->type    != write->type ||
+        read->rw.type != write->rw.type ||
         read->rw.frac != write->rw.frac)
         return; /* only regular planes can be directly ref'd */

@@ -514,7 +514,7 @@ static int rw_pixel_bits(const SwsOp *op)
     case SWS_RW_PACKED: elems = op->rw.elems; break;
     }

-    const int size  = ff_sws_pixel_type_size(op->type);
+    const int size  = ff_sws_pixel_type_size(op->rw.type);
     const int bits  = 8 >> op->rw.frac;
     av_assert1(bits >= 1);
     return elems * size * bits;
diff --git a/libswscale/ops_optimizer.c b/libswscale/ops_optimizer.c
index bd1723f053..a7ef19e086 100644
--- a/libswscale/ops_optimizer.c
+++ b/libswscale/ops_optimizer.c
@@ -1225,6 +1225,7 @@ int ff_sws_op_list_split_at(SwsOpList *ops1, SwsOpList **out_ops2, int index)
     ret = ff_sws_op_list_append(ops1, &(SwsOp) {
         .op       = SWS_OP_WRITE,
         .type     = type,
+        .rw.type  = type,
         .rw.elems = nb_planes,
     });
     if (ret < 0)
@@ -1233,6 +1234,7 @@ int ff_sws_op_list_split_at(SwsOpList *ops1, SwsOpList **out_ops2, int index)
     ret = ff_sws_op_list_insert_at(ops2, 0, &(SwsOp) {
         .op        = SWS_OP_READ,
         .type      = type,
+        .rw.type   = type,
         .rw.elems  = nb_planes,
     });
     if (ret < 0)
diff --git a/libswscale/vulkan/ops.c b/libswscale/vulkan/ops.c
index ac64491703..7754abfe97 100644
--- a/libswscale/vulkan/ops.c
+++ b/libswscale/vulkan/ops.c
@@ -711,7 +711,7 @@ static void define_shader_bindings(const SwsOpList *ops, SPICtx *spi, SPIRVIDs *

     /* Define image types for descriptors */
     id->out_img_type = spi_OpTypeImage(spi,
-                                       op_w->type == SWS_PIXEL_F32 ?
+                                       op_w->rw.type == SWS_PIXEL_F32 ?
                                        id->f32_type : id->u32_type,
                                        2, 0, 0, 0, 2, SpvImageFormatUnknown);
     id->out_img_array_id = spi_OpTypeArray(spi, id->out_img_type, spi_get_id(spi),
@@ -722,11 +722,11 @@ static void define_shader_bindings(const SwsOpList *ops, SPICtx *spi, SPIRVIDs *
     if (op_r) {
         /* If the formats match, we have to reuse the types due to SPIR-V not
          * allowing redundant type defines */
-        int match = ((op_w->type == SWS_PIXEL_F32) ==
-                     (op_r->type == SWS_PIXEL_F32));
+        int match = ((op_w->rw.type == SWS_PIXEL_F32) ==
+                     (op_r->rw.type == SWS_PIXEL_F32));
         id->in_img_type = match ? id->out_img_type :
                           spi_OpTypeImage(spi,
-                                          op_r->type == SWS_PIXEL_F32 ?
+                                          op_r->rw.type == SWS_PIXEL_F32 ?
                                           id->f32_type : id->u32_type,
                                           2, 0, 0, 0, 2, SpvImageFormatUnknown);
         id->in_img_array_id = spi_OpTypeArray(spi, id->in_img_type, spi_get_id(spi),
@@ -834,7 +834,7 @@ static int read_filtered(SPICtx *spi, SPIRVIDs *id, const SwsOpList *ops,
     const int is_h = f->filter == SWS_OP_FILTER_H;
     const int src_interlaced = ops->src.interlaced;

-    const int src_float = op->type == SWS_PIXEL_F32;
+    const int src_float = op->rw.type == SWS_PIXEL_F32;
     const int read_vtype = src_float ? id->f32vec4_type : id->u32vec4_type;

     /* Buffer array index along the filtered axis: pos.x (H) or pos.y (V) */
@@ -905,7 +905,7 @@ static VkFormat packed_word_fmt(const SwsOp *op)
     if (!op || op->rw.mode != SWS_RW_PACKED || op->rw.elems != 1)
         return VK_FORMAT_UNDEFINED;

-    switch (op->type) {
+    switch (op->rw.type) {
     case SWS_PIXEL_U8:  return VK_FORMAT_R8_UINT;
     case SWS_PIXEL_U16: return VK_FORMAT_R16_UINT;
     case SWS_PIXEL_U32: return VK_FORMAT_R32_UINT;
@@ -920,7 +920,7 @@ static int get_view_fmts(VkFormat view_fmts[AV_NUM_DATA_POINTERS],
     const VkFormat word_fmt = packed_word_fmt(op);
     enum FFVkShaderRepFormat rep = FF_VK_REP_NATIVE;
     if (op)
-        rep = op->type == SWS_PIXEL_F32 ? FF_VK_REP_FLOAT : FF_VK_REP_UINT;
+        rep = op->rw.type == SWS_PIXEL_F32 ? FF_VK_REP_FLOAT : FF_VK_REP_UINT;
     if (!vk_fmts)
         return AVERROR(ENOTSUP);