[FFmpeg-devel] [PATCH 1/2] swscale/swscale_unscaled: add swscale/swscale_unscaled: add unscaled x2rgb10le to planar RGB

James Almer jamrial at gmail.com
Mon Nov 4 15:31:47 EET 2024


Signed-off-by: James Almer <jamrial at gmail.com>
---
Supersedes "swscale/swscale_unscaled: add swscale/swscale_unscaled: add unscaled x2rgb10le to gbrp10"

 libswscale/swscale_unscaled.c     | 88 +++++++++++++++++++++++++++++++
 tests/ref/pixfmt/gbrp10-x2bgr10le |  2 +-
 tests/ref/pixfmt/gbrp10-x2rgb10le |  2 +-
 3 files changed, 90 insertions(+), 2 deletions(-)

diff --git a/libswscale/swscale_unscaled.c b/libswscale/swscale_unscaled.c
index c87a70e95e..fea854ece7 100644
--- a/libswscale/swscale_unscaled.c
+++ b/libswscale/swscale_unscaled.c
@@ -742,6 +742,77 @@ static void packed16togbra16(const uint8_t *src, int srcStride,
     }
 }
 
+static void packed30togbra10(const uint8_t *src, int srcStride,
+                             uint16_t *dst[], const int dstStride[], int srcSliceH,
+                             int swap, int bpc, int width)
+{
+    int x, h, i;
+    int dst_alpha = dst[3] != NULL;
+    int scale_high = bpc - 10, scale_low = 10 - scale_high;
+    for (h = 0; h < srcSliceH; h++) {
+        uint32_t *src_line = (uint32_t *)(src + srcStride * h);
+        unsigned component;
+
+        switch (swap) {
+        case 3:
+        case 2:
+            if (dst_alpha) {
+                for (x = 0; x < width; x++) {
+                    unsigned pixel = AV_RL32(src_line);
+                    component = av_bswap16((pixel >> 20) & 0x3FF);
+                    dst[0][x] = component << scale_high | component >> scale_low;
+                    component = av_bswap16((pixel >> 10) & 0x3FF);
+                    dst[1][x] = component << scale_high | component >> scale_low;
+                    component = av_bswap16( pixel        & 0x3FF);
+                    dst[2][x] = component << scale_high | component >> scale_low;
+                    dst[3][x] = 0xFFFF;
+                    src_line++;
+                }
+            } else {
+                for (x = 0; x < width; x++) {
+                    unsigned pixel = AV_RL32(src_line);
+                    component = av_bswap16((pixel >> 20) & 0x3FF);
+                    dst[0][x] = component << scale_high | component >> scale_low;
+                    component = av_bswap16((pixel >> 10) & 0x3FF);
+                    dst[1][x] = component << scale_high | component >> scale_low;
+                    component = av_bswap16( pixel        & 0x3FF);
+                    dst[2][x] = component << scale_high | component >> scale_low;
+                    src_line++;
+                }
+            }
+            break;
+        default:
+            if (dst_alpha) {
+                for (x = 0; x < width; x++) {
+                    unsigned pixel = AV_RL32(src_line);
+                    component = (pixel >> 20) & 0x3FF;
+                    dst[0][x] = component << scale_high | component >> scale_low;
+                    component = (pixel >> 10) & 0x3FF;
+                    dst[1][x] = component << scale_high | component >> scale_low;
+                    component =  pixel        & 0x3FF;
+                    dst[2][x] = component << scale_high | component >> scale_low;
+                    dst[3][x] = 0xFFFF;
+                    src_line++;
+                }
+            } else {
+                for (x = 0; x < width; x++) {
+                    unsigned pixel = AV_RL32(src_line);
+                    component = (pixel >> 20) & 0x3FF;
+                    dst[0][x] = component << scale_high | component >> scale_low;
+                    component = (pixel >> 10) & 0x3FF;
+                    dst[1][x] = component << scale_high | component >> scale_low;
+                    component =  pixel        & 0x3FF;
+                    dst[2][x] = component << scale_high | component >> scale_low;
+                    src_line++;
+                }
+            }
+            break;
+        }
+        for (i = 0; i < 4; i++)
+            dst[i] += dstStride[i] >> 1;
+    }
+}
+
 static int Rgb16ToPlanarRgb16Wrapper(SwsInternal *c, const uint8_t *const src[],
                                      const int srcStride[], int srcSliceY, int srcSliceH,
                                      uint8_t *const dst[], const int dstStride[])
@@ -785,6 +856,12 @@ static int Rgb16ToPlanarRgb16Wrapper(SwsInternal *c, const uint8_t *const src[],
                          dst2013, stride2013, srcSliceH, alpha, swap,
                          16 - bpc, c->srcW);
         break;
+    case AV_PIX_FMT_X2RGB10LE:
+        av_assert0(bpc >= 10);
+        packed30togbra10(src[0], srcStride[0],
+                         dst2013, stride2013, srcSliceH, swap,
+                         bpc, c->srcW);
+        break;
     case AV_PIX_FMT_BGR48LE:
     case AV_PIX_FMT_BGR48BE:
     case AV_PIX_FMT_BGRA64LE:
@@ -793,6 +870,12 @@ static int Rgb16ToPlanarRgb16Wrapper(SwsInternal *c, const uint8_t *const src[],
                          dst1023, stride1023, srcSliceH, alpha, swap,
                          16 - bpc, c->srcW);
         break;
+    case AV_PIX_FMT_X2BGR10LE:
+        av_assert0(bpc >= 10);
+        packed30togbra10(src[0], srcStride[0],
+                         dst1023, stride1023, srcSliceH, swap,
+                         bpc, c->srcW);
+        break;
     default:
         av_log(c, AV_LOG_ERROR,
                "unsupported conversion to planar RGB %s -> %s\n",
@@ -2301,6 +2384,11 @@ void ff_get_unscaled_swscale(SwsInternal *c)
          dstFormat == AV_PIX_FMT_GBRAP16LE || dstFormat == AV_PIX_FMT_GBRAP16BE ))
         c->convert_unscaled = Rgb16ToPlanarRgb16Wrapper;
 
+    if (av_pix_fmt_desc_get(dstFormat)->comp[0].depth >= 10 &&
+        isPlanarRGB(dstFormat) && !isFloat(dstFormat) &&
+        (srcFormat == AV_PIX_FMT_X2RGB10LE || srcFormat == AV_PIX_FMT_X2BGR10LE))
+        c->convert_unscaled = Rgb16ToPlanarRgb16Wrapper;
+
     if ((srcFormat == AV_PIX_FMT_GBRP9LE  || srcFormat == AV_PIX_FMT_GBRP9BE  ||
          srcFormat == AV_PIX_FMT_GBRP16LE || srcFormat == AV_PIX_FMT_GBRP16BE ||
          srcFormat == AV_PIX_FMT_GBRP10LE || srcFormat == AV_PIX_FMT_GBRP10BE ||
diff --git a/tests/ref/pixfmt/gbrp10-x2bgr10le b/tests/ref/pixfmt/gbrp10-x2bgr10le
index 51e9c5e4f0..568039f4ae 100644
--- a/tests/ref/pixfmt/gbrp10-x2bgr10le
+++ b/tests/ref/pixfmt/gbrp10-x2bgr10le
@@ -1,2 +1,2 @@
-909448714837e324484d85f3da37e2ba *tests/data/pixfmt/gbrp10-x2bgr10le.yuv
+1f9cc212a4081b6e35811df461b18fec *tests/data/pixfmt/gbrp10-x2bgr10le.yuv
 15206400 tests/data/pixfmt/gbrp10-x2bgr10le.yuv
diff --git a/tests/ref/pixfmt/gbrp10-x2rgb10le b/tests/ref/pixfmt/gbrp10-x2rgb10le
index 4cd95358df..bcb2208022 100644
--- a/tests/ref/pixfmt/gbrp10-x2rgb10le
+++ b/tests/ref/pixfmt/gbrp10-x2rgb10le
@@ -1,2 +1,2 @@
-909448714837e324484d85f3da37e2ba *tests/data/pixfmt/gbrp10-x2rgb10le.yuv
+1f9cc212a4081b6e35811df461b18fec *tests/data/pixfmt/gbrp10-x2rgb10le.yuv
 15206400 tests/data/pixfmt/gbrp10-x2rgb10le.yuv
-- 
2.47.0



More information about the ffmpeg-devel mailing list