[FFmpeg-devel] [PATCH] swscale/swscale_unscaled: add unscaled rgb to planar rgba

James Almer jamrial at gmail.com
Thu Oct 31 21:55:42 EET 2024


The fate test reference changes are due to the conversion being a simple
lossless deinterleave, instead of going through a RGB -> YUV -> RGB roundtrip.

Signed-off-by: James Almer <jamrial at gmail.com>
---
 libswscale/swscale_unscaled.c             | 85 +++++++++++++++++++++++
 tests/ref/fate/filter-overlay_gbrap_gbrap |  2 +-
 tests/ref/fate/filter-overlay_gbrp_gbrap  |  2 +-
 tests/ref/fate/vbn-dxt1                   |  8 +--
 4 files changed, 91 insertions(+), 6 deletions(-)

diff --git a/libswscale/swscale_unscaled.c b/libswscale/swscale_unscaled.c
index a1930b9132..5ba0d1600a 100644
--- a/libswscale/swscale_unscaled.c
+++ b/libswscale/swscale_unscaled.c
@@ -1260,6 +1260,87 @@ static int rgbToPlanarRgbWrapper(SwsInternal *c, const uint8_t *const src[],
     return srcSliceH;
 }
 
+static void packedtogbrap(const uint8_t *src, int srcStride,
+                          uint8_t *const dst[], const int dstStride[], int srcSliceH,
+                          int alpha_first, int inc_size, int width)
+{
+    uint8_t *dest[4];
+    int x, h, A = 3;
+
+    dest[0] = dst[0];
+    dest[1] = dst[1];
+    dest[2] = dst[2];
+    dest[3] = dst[3];
+
+    if (alpha_first) {
+        src++;
+        A = -1;
+    }
+
+    for (h = 0; h < srcSliceH; h++) {
+        for (x = 0; x < width; x++) {
+            dest[0][x] = src[0];
+            dest[1][x] = src[1];
+            dest[2][x] = src[2];
+            dest[3][x] = inc_size == 4 ? src[A] : 255;
+
+            src += inc_size;
+        }
+        src     += srcStride - width * inc_size;
+        dest[0] += dstStride[0];
+        dest[1] += dstStride[1];
+        dest[2] += dstStride[2];
+        dest[3] += dstStride[3];
+    }
+}
+
+static int rgbToPlanarRgbaWrapper(SwsInternal *c, const uint8_t *const src[],
+                                  const int srcStride[], int srcSliceY, int srcSliceH,
+                                  uint8_t *const dst[], const int dstStride[])
+{
+    int alpha_first = 0;
+    int stride102[] = { dstStride[1], dstStride[0], dstStride[2], dstStride[3] };
+    int stride201[] = { dstStride[2], dstStride[0], dstStride[1], dstStride[3] };
+    uint8_t *dst102[] = { dst[1] + srcSliceY * dstStride[1],
+                          dst[0] + srcSliceY * dstStride[0],
+                          dst[2] + srcSliceY * dstStride[2],
+                          dst[3] + srcSliceY * dstStride[3] };
+    uint8_t *dst201[] = { dst[2] + srcSliceY * dstStride[2],
+                          dst[0] + srcSliceY * dstStride[0],
+                          dst[1] + srcSliceY * dstStride[1],
+                          dst[3] + srcSliceY * dstStride[3] };
+
+    switch (c->srcFormat) {
+    case AV_PIX_FMT_RGB24:
+        packedtogbrap((const uint8_t *) src[0], srcStride[0], dst201,
+                      stride201, srcSliceH, alpha_first, 3, c->srcW);
+        break;
+    case AV_PIX_FMT_BGR24:
+        packedtogbrap((const uint8_t *) src[0], srcStride[0], dst102,
+                      stride102, srcSliceH, alpha_first, 3, c->srcW);
+        break;
+    case AV_PIX_FMT_ARGB:
+        alpha_first = 1;
+    case AV_PIX_FMT_RGBA:
+        packedtogbrap((const uint8_t *) src[0], srcStride[0], dst201,
+                      stride201, srcSliceH, alpha_first, 4, c->srcW);
+        break;
+    case AV_PIX_FMT_ABGR:
+        alpha_first = 1;
+    case AV_PIX_FMT_BGRA:
+        packedtogbrap((const uint8_t *) src[0], srcStride[0], dst102,
+                      stride102, srcSliceH, alpha_first, 4, c->srcW);
+        break;
+    default:
+        av_log(c, AV_LOG_ERROR,
+               "unsupported planar RGB conversion %s -> %s\n",
+               av_get_pix_fmt_name(c->srcFormat),
+               av_get_pix_fmt_name(c->dstFormat));
+    }
+
+    return srcSliceH;
+}
+
 #define BAYER_GBRG
 #define BAYER_8
 #define BAYER_RENAME(x) bayer_gbrg8_to_##x
@@ -2144,6 +2225,10 @@ void ff_get_unscaled_swscale(SwsInternal *c)
         isPackedRGB(srcFormat) && dstFormat == AV_PIX_FMT_GBRP)
         c->convert_unscaled = rgbToPlanarRgbWrapper;
 
+    if (av_pix_fmt_desc_get(srcFormat)->comp[0].depth == 8 &&
+        isPackedRGB(srcFormat) && dstFormat == AV_PIX_FMT_GBRAP)
+        c->convert_unscaled = rgbToPlanarRgbaWrapper;
+
     if (isBayer(srcFormat)) {
         c->dst_slice_align = 2;
         if (dstFormat == AV_PIX_FMT_RGB24)
diff --git a/tests/ref/fate/filter-overlay_gbrap_gbrap b/tests/ref/fate/filter-overlay_gbrap_gbrap
index 5048a346ae..49e14c643c 100644
--- a/tests/ref/fate/filter-overlay_gbrap_gbrap
+++ b/tests/ref/fate/filter-overlay_gbrap_gbrap
@@ -3,4 +3,4 @@
 #codec_id 0: rawvideo
 #dimensions 0: 128x128
 #sar 0: 1/1
-0,          0,          0,        1,    65536, 0x821bcb9b
+0,          0,          0,        1,    65536, 0xbac99946
diff --git a/tests/ref/fate/filter-overlay_gbrp_gbrap b/tests/ref/fate/filter-overlay_gbrp_gbrap
index 99524c3355..204c9d0625 100644
--- a/tests/ref/fate/filter-overlay_gbrp_gbrap
+++ b/tests/ref/fate/filter-overlay_gbrp_gbrap
@@ -3,4 +3,4 @@
 #codec_id 0: rawvideo
 #dimensions 0: 128x128
 #sar 0: 1/1
-0,          0,          0,        1,    49152, 0x738d07ea
+0,          0,          0,        1,    49152, 0xa905d586
diff --git a/tests/ref/fate/vbn-dxt1 b/tests/ref/fate/vbn-dxt1
index e33d9b63e1..8ff8da3406 100644
--- a/tests/ref/fate/vbn-dxt1
+++ b/tests/ref/fate/vbn-dxt1
@@ -5,7 +5,7 @@ lavfi.psnr.mse.g=33.508362
 lavfi.psnr.psnr.g=32.879272
 lavfi.psnr.mse.b=27.947266
 lavfi.psnr.psnr.b=33.667412
-lavfi.psnr.mse.a=21186.988281
-lavfi.psnr.psnr.a=4.870111
-lavfi.psnr.mse_avg=5321.285645
-lavfi.psnr.psnr_avg=10.870638
+lavfi.psnr.mse.a=21248.300781
+lavfi.psnr.psnr.a=4.857562
+lavfi.psnr.mse_avg=5336.613770
+lavfi.psnr.psnr_avg=10.858146
-- 
2.47.0



More information about the ffmpeg-devel mailing list