From c029a2f7ddea8e2b3c99f629c1bb54ff5a50cac1 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 31 Oct 2024 13:33:24 -0300 Subject: [PATCH] swscale/swscale_unscaled: add unscaled rgb to planar rgba 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 --- libswscale/swscale_unscaled.c | 114 ++++++++++++++++++++++ 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, 120 insertions(+), 6 deletions(-) diff --git a/libswscale/swscale_unscaled.c b/libswscale/swscale_unscaled.c index 6eb7867ff9..c87a70e95e 100644 --- a/libswscale/swscale_unscaled.c +++ b/libswscale/swscale_unscaled.c @@ -1305,6 +1305,116 @@ static int rgbToPlanarRgbWrapper(SwsInternal *c, const uint8_t *const src[], return srcSliceH; } +static void packed24togbrap(const uint8_t *src, int srcStride, + uint8_t *const dst[], const int dstStride[], + int srcSliceH, int width) +{ + uint8_t *dest[4]; + int x, h; + + dest[0] = dst[0]; + dest[1] = dst[1]; + dest[2] = dst[2]; + dest[3] = dst[3]; + + for (h = 0; h < srcSliceH; h++) { + for (x = 0; x < width; x++) { + dest[0][x] = src[x * 3 + 0]; + dest[1][x] = src[x * 3 + 1]; + dest[2][x] = src[x * 3 + 2]; + dest[3][x] = 0xff; + } + src += srcStride; + dest[0] += dstStride[0]; + dest[1] += dstStride[1]; + dest[2] += dstStride[2]; + dest[3] += dstStride[3]; + } +} + +static void packed32togbrap(const uint8_t *src, int srcStride, + uint8_t *const dst[], const int dstStride[], + int srcSliceH, int alpha_first, int width) +{ + uint8_t *dest[4]; + int x, h; + + dest[0] = dst[0]; + dest[1] = dst[1]; + dest[2] = dst[2]; + dest[3] = dst[3]; + + for (h = 0; h < srcSliceH; h++) { + if (alpha_first) { + for (x = 0; x < width; x++) { + dest[0][x] = src[x * 4 + 1]; + dest[1][x] = src[x * 4 + 2]; + dest[2][x] = src[x * 4 + 3]; + dest[3][x] = src[x * 4 + 0]; + } + } else { + for (x = 0; x < width; x++) { + dest[0][x] = src[x * 4 + 0]; + dest[1][x] = src[x * 4 + 1]; + dest[2][x] = src[x * 4 + 2]; + dest[3][x] = src[x * 4 + 3]; + } + } + src += srcStride; + 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: + packed24togbrap((const uint8_t *) src[0], srcStride[0], dst201, + stride201, srcSliceH, c->srcW); + break; + case AV_PIX_FMT_BGR24: + packed24togbrap((const uint8_t *) src[0], srcStride[0], dst102, + stride102, srcSliceH, c->srcW); + break; + case AV_PIX_FMT_ARGB: + alpha_first = 1; + case AV_PIX_FMT_RGBA: + packed32togbrap((const uint8_t *) src[0], srcStride[0], dst201, + stride201, srcSliceH, alpha_first, c->srcW); + break; + case AV_PIX_FMT_ABGR: + alpha_first = 1; + case AV_PIX_FMT_BGRA: + packed32togbrap((const uint8_t *) src[0], srcStride[0], dst102, + stride102, srcSliceH, alpha_first, 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 @@ -2215,6 +2325,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