Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
* [FFmpeg-devel] [PR] swscale/ops: PPC / bigendian fixes (PR #22231)
@ 2026-02-20 16:53 Niklas Haas via ffmpeg-devel
  0 siblings, 0 replies; only message in thread
From: Niklas Haas via ffmpeg-devel @ 2026-02-20 16:53 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Niklas Haas

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

Discovered by FATE. One of them is what appears to be a compiler bug, but the format.c refactor commit should hopefully fix that one incidentally.


>From e0c7f2024dca894aaadf70f912f4cf2dd4dfe0e4 Mon Sep 17 00:00:00 2001
From: Niklas Haas <git@haasn.dev>
Date: Fri, 20 Feb 2026 16:59:07 +0100
Subject: [PATCH 1/3] swscale/format: don't mark single byte formats as byte
 swapped

Fixes a bug where all format lists contained redundant byte swapped
annotations on big-endian platforms, even for single-byte formats.
---
 libswscale/format.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/libswscale/format.c b/libswscale/format.c
index e0434a2024..a6dd7c6d72 100644
--- a/libswscale/format.c
+++ b/libswscale/format.c
@@ -906,7 +906,8 @@ int ff_sws_decode_pixfmt(SwsOpList *ops, enum AVPixelFormat fmt)
 
     /* Set baseline pixel content flags */
     const int integer = ff_sws_pixel_type_is_int(raw_type);
-    const int swapped = (desc->flags & AV_PIX_FMT_FLAG_BE) != NATIVE_ENDIAN_FLAG;
+    const int swapped = ff_sws_pixel_type_size(raw_type) > 1 &&
+                        (desc->flags & AV_PIX_FMT_FLAG_BE) != NATIVE_ENDIAN_FLAG;
     for (int i = 0; i < rw_op.elems; i++) {
         comps->flags[i] = (integer ? SWS_COMP_EXACT   : 0) |
                           (swapped ? SWS_COMP_SWAPPED : 0);
@@ -1027,7 +1028,8 @@ int ff_sws_encode_pixfmt(SwsOpList *ops, enum AVPixelFormat fmt)
         }));
     }
 
-    if ((desc->flags & AV_PIX_FMT_FLAG_BE) != NATIVE_ENDIAN_FLAG) {
+    if (ff_sws_pixel_type_size(raw_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,
-- 
2.52.0


>From ebf52161f83db823d148837f8d7e2877afba65ce Mon Sep 17 00:00:00 2001
From: Niklas Haas <git@haasn.dev>
Date: Fri, 20 Feb 2026 17:39:46 +0100
Subject: [PATCH 2/3] swscale/format: pass SwsFormat by ref instead of by value
 where possible

The one exception is in adapt_colors(), which mutates these structs on
its own stack anyways.
---
 libswscale/format.c        | 66 +++++++++++++++++++-------------------
 libswscale/format.h        |  4 +--
 libswscale/graph.c         | 66 ++++++++++++++++++++------------------
 libswscale/ops.c           | 12 +++----
 libswscale/ops.h           |  4 +--
 libswscale/tests/sws_ops.c |  4 +--
 6 files changed, 79 insertions(+), 77 deletions(-)

diff --git a/libswscale/format.c b/libswscale/format.c
index a6dd7c6d72..11fef305ff 100644
--- a/libswscale/format.c
+++ b/libswscale/format.c
@@ -1050,7 +1050,7 @@ static inline AVRational av_neg_q(AVRational x)
     return (AVRational) { -x.num, x.den };
 }
 
-static SwsLinearOp fmt_encode_range(const SwsFormat fmt, bool *incomplete)
+static SwsLinearOp fmt_encode_range(const SwsFormat *fmt, bool *incomplete)
 {
     SwsLinearOp c = { .m = {
         { Q1, Q0, Q0, Q0, Q0 },
@@ -1059,22 +1059,22 @@ static SwsLinearOp fmt_encode_range(const SwsFormat fmt, bool *incomplete)
         { Q0, Q0, Q0, Q1, Q0 },
     }};
 
-    const int depth0 = fmt.desc->comp[0].depth;
-    const int depth1 = fmt.desc->comp[1].depth;
-    const int depth2 = fmt.desc->comp[2].depth;
-    const int depth3 = fmt.desc->comp[3].depth;
+    const int depth0 = fmt->desc->comp[0].depth;
+    const int depth1 = fmt->desc->comp[1].depth;
+    const int depth2 = fmt->desc->comp[2].depth;
+    const int depth3 = fmt->desc->comp[3].depth;
 
-    if (fmt.desc->flags & AV_PIX_FMT_FLAG_FLOAT)
+    if (fmt->desc->flags & AV_PIX_FMT_FLAG_FLOAT)
         return c; /* floats are directly output as-is */
 
-    if (fmt.csp == AVCOL_SPC_RGB || (fmt.desc->flags & AV_PIX_FMT_FLAG_XYZ)) {
+    if (fmt->csp == AVCOL_SPC_RGB || (fmt->desc->flags & AV_PIX_FMT_FLAG_XYZ)) {
         c.m[0][0] = Q((1 << depth0) - 1);
         c.m[1][1] = Q((1 << depth1) - 1);
         c.m[2][2] = Q((1 << depth2) - 1);
-    } else if (fmt.range == AVCOL_RANGE_JPEG) {
+    } else if (fmt->range == AVCOL_RANGE_JPEG) {
         /* Full range YUV */
         c.m[0][0] = Q((1 << depth0) - 1);
-        if (fmt.desc->nb_components >= 3) {
+        if (fmt->desc->nb_components >= 3) {
             /* This follows the ITU-R convention, which is slightly different
              * from the JFIF convention. */
             c.m[1][1] = Q((1 << depth1) - 1);
@@ -1084,11 +1084,11 @@ static SwsLinearOp fmt_encode_range(const SwsFormat fmt, bool *incomplete)
         }
     } else {
         /* Limited range YUV */
-        if (fmt.range == AVCOL_RANGE_UNSPECIFIED)
+        if (fmt->range == AVCOL_RANGE_UNSPECIFIED)
             *incomplete = true;
         c.m[0][0] = Q(219 << (depth0 - 8));
         c.m[0][4] = Q( 16 << (depth0 - 8));
-        if (fmt.desc->nb_components >= 3) {
+        if (fmt->desc->nb_components >= 3) {
             c.m[1][1] = Q(224 << (depth1 - 8));
             c.m[2][2] = Q(224 << (depth2 - 8));
             c.m[1][4] = Q(128 << (depth1 - 8));
@@ -1096,12 +1096,12 @@ static SwsLinearOp fmt_encode_range(const SwsFormat fmt, bool *incomplete)
         }
     }
 
-    if (fmt.desc->flags & AV_PIX_FMT_FLAG_ALPHA) {
-        const bool is_ya = fmt.desc->nb_components == 2;
+    if (fmt->desc->flags & AV_PIX_FMT_FLAG_ALPHA) {
+        const bool is_ya = fmt->desc->nb_components == 2;
         c.m[3][3] = Q((1 << (is_ya ? depth1 : depth3)) - 1);
     }
 
-    if (fmt.format == AV_PIX_FMT_MONOWHITE) {
+    if (fmt->format == AV_PIX_FMT_MONOWHITE) {
         /* This format is inverted, 0 = white, 1 = black */
         c.m[0][4] = av_add_q(c.m[0][4], c.m[0][0]);
         c.m[0][0] = av_neg_q(c.m[0][0]);
@@ -1111,7 +1111,7 @@ static SwsLinearOp fmt_encode_range(const SwsFormat fmt, bool *incomplete)
     return c;
 }
 
-static SwsLinearOp fmt_decode_range(const SwsFormat fmt, bool *incomplete)
+static SwsLinearOp fmt_decode_range(const SwsFormat *fmt, bool *incomplete)
 {
     SwsLinearOp c = fmt_encode_range(fmt, incomplete);
 
@@ -1123,7 +1123,7 @@ static SwsLinearOp fmt_decode_range(const SwsFormat fmt, bool *incomplete)
     }
 
     /* Explicitly initialize alpha for sanity */
-    if (!(fmt.desc->flags & AV_PIX_FMT_FLAG_ALPHA))
+    if (!(fmt->desc->flags & AV_PIX_FMT_FLAG_ALPHA))
         c.m[3][4] = Q1;
 
     c.mask = ff_sws_linear_mask(c);
@@ -1189,15 +1189,15 @@ static bool trc_is_hdr(enum AVColorTransferCharacteristic trc)
 
 static int fmt_dither(SwsContext *ctx, SwsOpList *ops,
                       const SwsPixelType type,
-                      const SwsFormat src, const SwsFormat dst)
+                      const SwsFormat *src, const SwsFormat *dst)
 {
     SwsDither mode = ctx->dither;
     SwsDitherOp dither;
-    const int bpc = dst.desc->comp[0].depth;
+    const int bpc = dst->desc->comp[0].depth;
 
     if (mode == SWS_DITHER_AUTO) {
         /* Visual threshold of perception: 12 bits for SDR, 14 bits for HDR */
-        const int jnd_bits = trc_is_hdr(dst.color.trc) ? 14 : 12;
+        const int jnd_bits = trc_is_hdr(dst->color.trc) ? 14 : 12;
         mode = bpc >= jnd_bits ? SWS_DITHER_NONE : SWS_DITHER_BAYER;
     }
 
@@ -1234,7 +1234,7 @@ static int fmt_dither(SwsContext *ctx, SwsOpList *ops,
         for (int i = 0; i < 4; i++)
             dither.y_offset[i] = offsets_16x16[i];
 
-        if (src.desc->nb_components < 3 && bpc >= 8) {
+        if (src->desc->nb_components < 3 && bpc >= 8) {
             /**
              * For high-bit-depth sources without chroma, use same matrix
              * offset for all color channels. This prevents introducing color
@@ -1284,13 +1284,13 @@ linear_mat3(const AVRational m00, const AVRational m01, const AVRational m02,
 }
 
 int ff_sws_decode_colors(SwsContext *ctx, SwsPixelType type,
-                         SwsOpList *ops, const SwsFormat fmt, bool *incomplete)
+                         SwsOpList *ops, const SwsFormat *fmt, bool *incomplete)
 {
-    const AVLumaCoefficients *c = av_csp_luma_coeffs_from_avcsp(fmt.csp);
+    const AVLumaCoefficients *c = av_csp_luma_coeffs_from_avcsp(fmt->csp);
 
     RET(ff_sws_op_list_append(ops, &(SwsOp) {
         .op         = SWS_OP_CONVERT,
-        .type       = fmt_pixel_type(fmt.format),
+        .type       = fmt_pixel_type(fmt->format),
         .convert.to = type,
     }));
 
@@ -1302,7 +1302,7 @@ int ff_sws_decode_colors(SwsContext *ctx, SwsPixelType type,
     }));
 
     /* Final step, decode colorspace */
-    switch (fmt.csp) {
+    switch (fmt->csp) {
     case AVCOL_SPC_RGB:
         return 0;
     case AVCOL_SPC_UNSPECIFIED:
@@ -1366,12 +1366,12 @@ int ff_sws_decode_colors(SwsContext *ctx, SwsPixelType type,
 }
 
 int ff_sws_encode_colors(SwsContext *ctx, SwsPixelType type,
-                         SwsOpList *ops, const SwsFormat src,
-                         const SwsFormat dst, bool *incomplete)
+                         SwsOpList *ops, const SwsFormat *src,
+                         const SwsFormat *dst, bool *incomplete)
 {
-    const AVLumaCoefficients *c = av_csp_luma_coeffs_from_avcsp(dst.csp);
+    const AVLumaCoefficients *c = av_csp_luma_coeffs_from_avcsp(dst->csp);
 
-    switch (dst.csp) {
+    switch (dst->csp) {
     case AVCOL_SPC_RGB:
         break;
     case AVCOL_SPC_UNSPECIFIED:
@@ -1437,14 +1437,14 @@ int ff_sws_encode_colors(SwsContext *ctx, SwsPixelType type,
         .lin  = fmt_encode_range(dst, incomplete),
     }));
 
-    if (!(dst.desc->flags & AV_PIX_FMT_FLAG_FLOAT)) {
+    if (!(dst->desc->flags & AV_PIX_FMT_FLAG_FLOAT)) {
         SwsConst range = {0};
 
-        const bool is_ya = dst.desc->nb_components == 2;
-        for (int i = 0; i < dst.desc->nb_components; i++) {
+        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.q4[idx] = Q((1 << dst->desc->comp[i].depth) - 1);
         }
 
         RET(fmt_dither(ctx, ops, type, src, dst));
@@ -1464,7 +1464,7 @@ int ff_sws_encode_colors(SwsContext *ctx, SwsPixelType type,
     return ff_sws_op_list_append(ops, &(SwsOp) {
         .type       = type,
         .op         = SWS_OP_CONVERT,
-        .convert.to = fmt_pixel_type(dst.format),
+        .convert.to = fmt_pixel_type(dst->format),
     });
 }
 
diff --git a/libswscale/format.h b/libswscale/format.h
index fbb65d6805..fe37b3a32e 100644
--- a/libswscale/format.h
+++ b/libswscale/format.h
@@ -167,9 +167,9 @@ int ff_sws_encode_pixfmt(SwsOpList *ops, enum AVPixelFormat fmt);
  * Returns 0 on success, or a negative error code on failure.
  */
 int ff_sws_decode_colors(SwsContext *ctx, SwsPixelType type, SwsOpList *ops,
-                         const SwsFormat fmt, bool *incomplete);
+                         const SwsFormat *fmt, bool *incomplete);
 int ff_sws_encode_colors(SwsContext *ctx, SwsPixelType type, SwsOpList *ops,
-                         const SwsFormat src, const SwsFormat dst,
+                         const SwsFormat *src, const SwsFormat *dst,
                          bool *incomplete);
 
 #endif /* SWSCALE_FORMAT_H */
diff --git a/libswscale/graph.c b/libswscale/graph.c
index e47b2d07f2..c81988e4ed 100644
--- a/libswscale/graph.c
+++ b/libswscale/graph.c
@@ -395,8 +395,9 @@ static int init_legacy_subpass(SwsGraph *graph, SwsContext *sws,
     return 0;
 }
 
-static int add_legacy_sws_pass(SwsGraph *graph, SwsFormat src, SwsFormat dst,
-                               SwsPass *input, SwsPass **output)
+static int add_legacy_sws_pass(SwsGraph *graph, const SwsFormat *src,
+                               const SwsFormat *dst, SwsPass *input,
+                               SwsPass **output)
 {
     int ret, warned = 0;
     SwsContext *const ctx = graph->ctx;
@@ -409,20 +410,20 @@ static int add_legacy_sws_pass(SwsGraph *graph, SwsFormat src, SwsFormat dst,
     sws->alpha_blend = ctx->alpha_blend;
     sws->gamma_flag  = ctx->gamma_flag;
 
-    sws->src_w       = src.width;
-    sws->src_h       = src.height;
-    sws->src_format  = src.format;
-    sws->src_range   = src.range == AVCOL_RANGE_JPEG;
+    sws->src_w       = src->width;
+    sws->src_h       = src->height;
+    sws->src_format  = src->format;
+    sws->src_range   = src->range == AVCOL_RANGE_JPEG;
 
-    sws->dst_w      = dst.width;
-    sws->dst_h      = dst.height;
-    sws->dst_format = dst.format;
-    sws->dst_range  = dst.range == AVCOL_RANGE_JPEG;
-    get_chroma_pos(graph, &sws->src_h_chr_pos, &sws->src_v_chr_pos, &src);
-    get_chroma_pos(graph, &sws->dst_h_chr_pos, &sws->dst_v_chr_pos, &dst);
+    sws->dst_w      = dst->width;
+    sws->dst_h      = dst->height;
+    sws->dst_format = dst->format;
+    sws->dst_range  = dst->range == AVCOL_RANGE_JPEG;
+    get_chroma_pos(graph, &sws->src_h_chr_pos, &sws->src_v_chr_pos, src);
+    get_chroma_pos(graph, &sws->dst_h_chr_pos, &sws->dst_v_chr_pos, dst);
 
-    graph->incomplete |= src.range == AVCOL_RANGE_UNSPECIFIED;
-    graph->incomplete |= dst.range == AVCOL_RANGE_UNSPECIFIED;
+    graph->incomplete |= src->range == AVCOL_RANGE_UNSPECIFIED;
+    graph->incomplete |= dst->range == AVCOL_RANGE_UNSPECIFIED;
 
     /* Allow overriding chroma position with the legacy API */
     legacy_chr_pos(graph, &sws->src_h_chr_pos, ctx->src_h_chr_pos, &warned);
@@ -447,12 +448,12 @@ static int add_legacy_sws_pass(SwsGraph *graph, SwsFormat src, SwsFormat dst,
                                 (int **)&table, &out_full,
                                 &brightness, &contrast, &saturation);
 
-        inv_table = sws_getCoefficients(src.csp);
-        table     = sws_getCoefficients(dst.csp);
+        inv_table = sws_getCoefficients(src->csp);
+        table     = sws_getCoefficients(dst->csp);
 
-        graph->incomplete |= src.csp != dst.csp &&
-                            (src.csp == AVCOL_SPC_UNSPECIFIED ||
-                             dst.csp == AVCOL_SPC_UNSPECIFIED);
+        graph->incomplete |= src->csp != dst->csp &&
+                            (src->csp == AVCOL_SPC_UNSPECIFIED ||
+                             dst->csp == AVCOL_SPC_UNSPECIFIED);
 
         sws_setColorspaceDetails(sws, inv_table, in_full, table, out_full,
                                 brightness, contrast, saturation);
@@ -466,8 +467,9 @@ static int add_legacy_sws_pass(SwsGraph *graph, SwsFormat src, SwsFormat dst,
  *********************/
 
 #if CONFIG_UNSTABLE
-static int add_convert_pass(SwsGraph *graph, SwsFormat src, SwsFormat dst,
-                            SwsPass *input, SwsPass **output)
+static int add_convert_pass(SwsGraph *graph, const SwsFormat *src,
+                            const SwsFormat *dst, SwsPass *input,
+                            SwsPass **output)
 {
     const SwsPixelType type = SWS_PIXEL_F32;
 
@@ -480,23 +482,23 @@ static int add_convert_pass(SwsGraph *graph, SwsFormat src, SwsFormat dst,
         goto fail;
 
     /* The new format conversion layer cannot scale for now */
-    if (src.width != dst.width || src.height != dst.height ||
-        src.desc->log2_chroma_h || src.desc->log2_chroma_w ||
-        dst.desc->log2_chroma_h || dst.desc->log2_chroma_w)
+    if (src->width != dst->width || src->height != dst->height ||
+        src->desc->log2_chroma_h || src->desc->log2_chroma_w ||
+        dst->desc->log2_chroma_h || dst->desc->log2_chroma_w)
         goto fail;
 
     /* The new code does not yet support alpha blending */
-    if (src.desc->flags & AV_PIX_FMT_FLAG_ALPHA &&
+    if (src->desc->flags & AV_PIX_FMT_FLAG_ALPHA &&
         ctx->alpha_blend != SWS_ALPHA_BLEND_NONE)
         goto fail;
 
     ops = ff_sws_op_list_alloc();
     if (!ops)
         return AVERROR(ENOMEM);
-    ops->src = src;
-    ops->dst = dst;
+    ops->src = *src;
+    ops->dst = *dst;
 
-    ret = ff_sws_decode_pixfmt(ops, src.format);
+    ret = ff_sws_decode_pixfmt(ops, src->format);
     if (ret < 0)
         goto fail;
     ret = ff_sws_decode_colors(ctx, type, ops, src, &graph->incomplete);
@@ -505,12 +507,12 @@ static int add_convert_pass(SwsGraph *graph, SwsFormat src, SwsFormat dst,
     ret = ff_sws_encode_colors(ctx, type, ops, src, dst, &graph->incomplete);
     if (ret < 0)
         goto fail;
-    ret = ff_sws_encode_pixfmt(ops, dst.format);
+    ret = ff_sws_encode_pixfmt(ops, dst->format);
     if (ret < 0)
         goto fail;
 
     av_log(ctx, AV_LOG_VERBOSE, "Conversion pass for %s -> %s:\n",
-           av_get_pix_fmt_name(src.format), av_get_pix_fmt_name(dst.format));
+           av_get_pix_fmt_name(src->format), av_get_pix_fmt_name(dst->format));
 
     av_log(ctx, AV_LOG_DEBUG, "Unoptimized operation list:\n");
     ff_sws_op_list_print(ctx, AV_LOG_DEBUG, ops);
@@ -605,7 +607,7 @@ static int adapt_colors(SwsGraph *graph, SwsFormat src, SwsFormat dst,
     if (fmt_in != src.format) {
         SwsFormat tmp = src;
         tmp.format = fmt_in;
-        ret = add_convert_pass(graph, src, tmp, input, &input);
+        ret = add_convert_pass(graph, &src, &tmp, input, &input);
         if (ret < 0)
             return ret;
     }
@@ -647,7 +649,7 @@ static int init_passes(SwsGraph *graph)
     src.color  = dst.color;
 
     if (!ff_fmt_equal(&src, &dst)) {
-        ret = add_convert_pass(graph, src, dst, pass, &pass);
+        ret = add_convert_pass(graph, &src, &dst, pass, &pass);
         if (ret < 0)
             return ret;
     }
diff --git a/libswscale/ops.c b/libswscale/ops.c
index 900077584a..edadbb572d 100644
--- a/libswscale/ops.c
+++ b/libswscale/ops.c
@@ -1110,8 +1110,8 @@ static int rw_pixel_bits(const SwsOp *op)
     return elems * size * bits;
 }
 
-int ff_sws_compile_pass(SwsGraph *graph, SwsOpList *ops, int flags, SwsFormat dst,
-                        SwsPass *input, SwsPass **output)
+int ff_sws_compile_pass(SwsGraph *graph, SwsOpList *ops, int flags,
+                        const SwsFormat *dst, SwsPass *input, SwsPass **output)
 {
     SwsContext *ctx = graph->ctx;
     SwsOpPass *p = NULL;
@@ -1155,8 +1155,8 @@ int ff_sws_compile_pass(SwsGraph *graph, SwsOpList *ops, int flags, SwsFormat ds
     p->pixel_bits_in  = rw_pixel_bits(read);
     p->pixel_bits_out = rw_pixel_bits(write);
     p->exec_base = (SwsOpExec) {
-        .width  = dst.width,
-        .height = dst.height,
+        .width  = dst->width,
+        .height = dst->height,
         .block_size_in  = p->comp.block_size * p->pixel_bits_in  >> 3,
         .block_size_out = p->comp.block_size * p->pixel_bits_out >> 3,
     };
@@ -1166,8 +1166,8 @@ int ff_sws_compile_pass(SwsGraph *graph, SwsOpList *ops, int flags, SwsFormat ds
         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);
+    pass = ff_sws_graph_add_pass(graph, dst->format, dst->width, dst->height,
+                                 input, 1, p, op_pass_run);
     if (!pass) {
         ret = AVERROR(ENOMEM);
         goto fail;
diff --git a/libswscale/ops.h b/libswscale/ops.h
index 9f93c12fa8..e04c5ff9f5 100644
--- a/libswscale/ops.h
+++ b/libswscale/ops.h
@@ -296,7 +296,7 @@ enum SwsOpCompileFlags {
  *
  * Note: `ops` may be modified by this function.
  */
-int ff_sws_compile_pass(SwsGraph *graph, SwsOpList *ops, int flags, SwsFormat dst,
-                        SwsPass *input, SwsPass **output);
+int ff_sws_compile_pass(SwsGraph *graph, SwsOpList *ops, int flags,
+                        const SwsFormat *dst, SwsPass *input, SwsPass **output);
 
 #endif
diff --git a/libswscale/tests/sws_ops.c b/libswscale/tests/sws_ops.c
index bf84128291..9bad2ddff7 100644
--- a/libswscale/tests/sws_ops.c
+++ b/libswscale/tests/sws_ops.c
@@ -46,9 +46,9 @@ static int run_test(SwsContext *const ctx, AVFrame *frame,
 
     if (ff_sws_decode_pixfmt(ops, src.format) < 0)
         goto fail;
-    if (ff_sws_decode_colors(ctx, SWS_PIXEL_F32, ops, src, &incomplete) < 0)
+    if (ff_sws_decode_colors(ctx, SWS_PIXEL_F32, ops, &src, &incomplete) < 0)
         goto fail;
-    if (ff_sws_encode_colors(ctx, SWS_PIXEL_F32, ops, src, dst, &incomplete) < 0)
+    if (ff_sws_encode_colors(ctx, SWS_PIXEL_F32, ops, &src, &dst, &incomplete) < 0)
         goto fail;
     if (ff_sws_encode_pixfmt(ops, dst.format) < 0)
         goto fail;
-- 
2.52.0


>From c79352897b8c33ad12826fcb317780c33eb2ddf0 Mon Sep 17 00:00:00 2001
From: Niklas Haas <git@haasn.dev>
Date: Fri, 20 Feb 2026 17:50:39 +0100
Subject: [PATCH 3/3] tests/swscale: disable fate-sws-ops-list on BE platforms

The issue is that every le/be pair ends up with a swapped op list:

 rgb24 -> rgb48be:
   [ u8 XXXX -> +++X] SWS_OP_READ         : 3 elem(s) packed >> 0
   [ u8 ...X -> +++X] SWS_OP_CONVERT      : u8 -> u16 (expand)
-  [u16 ...X -> zzzX] SWS_OP_SWAP_BYTES
-  [u16 ...X -> zzzX] SWS_OP_WRITE        : 3 elem(s) packed >> 0
+  [u16 ...X -> +++X] SWS_OP_WRITE        : 3 elem(s) packed >> 0
     (X = unused, z = byteswapped, + = exact, 0 = zero)
 rgb24 -> rgb48le:
   [ u8 XXXX -> +++X] SWS_OP_READ         : 3 elem(s) packed >> 0
   [ u8 ...X -> +++X] SWS_OP_CONVERT      : u8 -> u16 (expand)
-  [u16 ...X -> +++X] SWS_OP_WRITE        : 3 elem(s) packed >> 0
+  [u16 ...X -> zzzX] SWS_OP_SWAP_BYTES
+  [u16 ...X -> zzzX] SWS_OP_WRITE        : 3 elem(s) packed >> 0
     (X = unused, z = byteswapped, + = exact, 0 = zero)

I'm not sure of a good work-around that's not needlessly difficult to
implement, so just disable it on BE platforms for now. The actual underlying
conversions should still be covered by the sws-unscaled test.
---
 tests/fate/libswscale.mak | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/tests/fate/libswscale.mak b/tests/fate/libswscale.mak
index 8d87c39ebf..db4d132c49 100644
--- a/tests/fate/libswscale.mak
+++ b/tests/fate/libswscale.mak
@@ -36,9 +36,13 @@ FATE_LIBSWSCALE-$(CONFIG_UNSTABLE) += fate-sws-unscaled
 fate-sws-unscaled: libswscale/tests/swscale$(EXESUF)
 fate-sws-unscaled: CMD = run libswscale/tests/swscale$(EXESUF) -unscaled 1 -flags 0x100000 -v 16
 
+ifneq ($(HAVE_BIGENDIAN),yes)
+# Disable on big endian because big endian platforms generate different op
+# lists for le vs be formats; this breaks the checksum otherwise
 FATE_LIBSWSCALE-$(CONFIG_UNSTABLE) += fate-sws-ops-list
 fate-sws-ops-list: libswscale/tests/sws_ops$(EXESUF)
 fate-sws-ops-list: CMD = run libswscale/tests/sws_ops$(EXESUF) | do_md5sum | cut -d" " -f1
+endif
 
 FATE_LIBSWSCALE += $(FATE_LIBSWSCALE-yes)
 FATE_LIBSWSCALE_SAMPLES += $(FATE_LIBSWSCALE_SAMPLES-yes)
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org
To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2026-02-20 18:42 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-02-20 16:53 [FFmpeg-devel] [PR] swscale/ops: PPC / bigendian fixes (PR #22231) Niklas Haas via ffmpeg-devel

Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
		ffmpegdev@gitmailbox.com
	public-inbox-index ffmpegdev

Example config snippet for mirrors.


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git