PR #25362 opened by Forgejo_Fairy
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25362
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25362.patch

Fixes #25280.

The transpose filter accepts packed formats with 12- and 16-byte pixel steps 
but initializes no function pointers for them. A TIFF decoded as `rgbaf32le` 
can therefore crash when its orientation triggers automatic transpose.

Use a generic byte-copy path for pixel steps without a specialized 
implementation. Add FATE coverage for 12-byte RGBF32 and 16-byte RGBAF32 using 
existing TIFF samples.

Verified with the issue sample, byte-for-byte checks in all four transpose 
directions, `fate-filter-transpose-rgbf32le`, 
`fate-filter-transpose-rgbaf32le`, `fate-filter-transpose`, and 
`fate-filter-pixfmts-transpose`.


>From 81e43aa9c1556b8083ae896833f8fcf56a95b554 Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Thu, 22 Oct 2026 16:42:52 +0000
Subject: [PATCH] avfilter/transpose: handle packed pixel formats wider than 8
 bytes

Use a generic byte-copy transpose for formats without a specialized pixel-step 
function. This covers packed RGB/RGBA 32-bit float and integer formats and 
prevents a NULL function pointer call.

Add FATE coverage using existing RGBF32 and RGBAF32 TIFF samples.

Assisted-by: Fairy
---
 libavfilter/vf_transpose.c                | 17 +++++++++++++++++
 tests/fate/filter-video.mak               |  5 +++++
 tests/ref/fate/filter-transpose-rgbaf32le |  6 ++++++
 tests/ref/fate/filter-transpose-rgbf32le  |  6 ++++++
 4 files changed, 34 insertions(+)
 create mode 100644 tests/ref/fate/filter-transpose-rgbaf32le
 create mode 100644 tests/ref/fate/filter-transpose-rgbf32le

diff --git a/libavfilter/vf_transpose.c b/libavfilter/vf_transpose.c
index 62c222f3c22..0608ed87aa6 100644
--- a/libavfilter/vf_transpose.c
+++ b/libavfilter/vf_transpose.c
@@ -26,6 +26,7 @@
  */
 
 #include <stdio.h>
+#include <string.h>
 
 #include "libavutil/avassert.h"
 #include "libavutil/imgutils.h"
@@ -176,6 +177,16 @@ static void transpose_8x8_64_c(uint8_t *src, ptrdiff_t 
src_linesize,
     transpose_block_64_c(src, src_linesize, dst, dst_linesize, 8, 8);
 }
 
+/* Handle pixel steps without a specialized transpose implementation. */
+static void transpose_block_generic(uint8_t *src, ptrdiff_t src_linesize,
+                                    uint8_t *dst, ptrdiff_t dst_linesize,
+                                    int w, int h, int pixstep)
+{
+    for (int y = 0; y < h; y++, dst += dst_linesize, src += pixstep)
+        for (int x = 0; x < w; x++)
+            memcpy(dst + x * pixstep, src + x * src_linesize, pixstep);
+}
+
 static int config_props_output(AVFilterLink *outlink)
 {
     AVFilterContext *ctx = outlink->src;
@@ -304,6 +315,12 @@ static int filter_slice(AVFilterContext *ctx, void *arg, 
int jobnr,
             dstlinesize *= -1;
         }
 
+        if (!v->transpose_block) {
+            transpose_block_generic(src + start * pixstep, srclinesize,
+                                    dst, dstlinesize, outw, end - start, 
pixstep);
+            continue;
+        }
+
         for (y = start; y < end - 7; y += 8) {
             for (x = 0; x < outw - 7; x += 8) {
                 v->transpose_8x8(src + x * srclinesize + y * pixstep,
diff --git a/tests/fate/filter-video.mak b/tests/fate/filter-video.mak
index 4a065ec0320..7769768a397 100644
--- a/tests/fate/filter-video.mak
+++ b/tests/fate/filter-video.mak
@@ -410,6 +410,11 @@ fate-filter-tpad-add-duration: CMD = framecrc -lavfi 
testsrc2=d=1:r=2,tpad=start
 FATE_FILTER_VSYNTH_PGMYUV-$(CONFIG_TRANSPOSE_FILTER) += fate-filter-transpose
 fate-filter-transpose: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf transpose
 
+FATE_FILTER_SAMPLES-$(call FILTERDEMDEC, TRANSPOSE, IMAGE2, TIFF) += \
+    fate-filter-transpose-rgbf32le fate-filter-transpose-rgbaf32le
+fate-filter-transpose-rgbf32le: CMD = framecrc -noautorotate -i 
$(TARGET_SAMPLES)/tiff/uncompressed_rgbf32le.tif -vf transpose=dir=clock 
-frames:v 1
+fate-filter-transpose-rgbaf32le: CMD = framecrc -noautorotate -i 
$(TARGET_SAMPLES)/tiff/uncompressed_rgbaf32le.tif -vf transpose=dir=clock 
-frames:v 1
+
 FATE_TRIM += fate-filter-trim-duration
 fate-filter-trim-duration: CMD = framecrc -i $(SRC) -vf 
trim=start=0.4:duration=0.05
 
diff --git a/tests/ref/fate/filter-transpose-rgbaf32le 
b/tests/ref/fate/filter-transpose-rgbaf32le
new file mode 100644
index 00000000000..2b0ac8a939f
--- /dev/null
+++ b/tests/ref/fate/filter-transpose-rgbaf32le
@@ -0,0 +1,6 @@
+#tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 8x8
+#sar 0: 0/1
+0,          0,          0,        1,     1024, 0xed4d1d5f
diff --git a/tests/ref/fate/filter-transpose-rgbf32le 
b/tests/ref/fate/filter-transpose-rgbf32le
new file mode 100644
index 00000000000..a6e7d87571d
--- /dev/null
+++ b/tests/ref/fate/filter-transpose-rgbf32le
@@ -0,0 +1,6 @@
+#tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 8x8
+#sar 0: 0/1
+0,          0,          0,        1,      768, 0xb985ed90
-- 
2.54.0

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

Reply via email to