From 665b0cf3bffa184d9803c25af077691c047c5e1d Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 9 Jan 2025 22:14:57 +0100 Subject: [PATCH] swscale: 16bit planar float input support Sponsored-by: Sovereign Tech Fund Signed-off-by: Michael Niedermayer --- libswscale/input.c | 97 +++++++++++++++++++++++++++++++++++ libswscale/swscale_unscaled.c | 3 +- libswscale/utils.c | 8 +++ 3 files changed, 107 insertions(+), 1 deletion(-) diff --git a/libswscale/input.c b/libswscale/input.c index 9f9410f922..d6b319f25f 100644 --- a/libswscale/input.c +++ b/libswscale/input.c @@ -1369,6 +1369,57 @@ rgbf32_funcs_endian(le, 0) rgbf32_funcs_endian(be, 1) #define rdpx(src) av_int2float(half2float(is_be ? AV_RB16(&src) : AV_RL16(&src), h2f_tbl)) +#define rdpx2(src) av_int2float(half2float(is_be ? AV_RB16(src) : AV_RL16(src), h2f_tbl)) + +static av_always_inline void planar_rgbf16_to_a(uint8_t *dst, const uint8_t *src[4], int width, int is_be, int32_t *rgb2yuv, Half2FloatTables *h2f_tbl) +{ + int i; + + for (i = 0; i < width; i++) { + AV_WN16(dst + 2*i, lrintf(av_clipf(65535.0f * rdpx2(src[3] + 2*i), 0.0f, 65535.0f))); + } +} + +static av_always_inline void planar_rgbf16_to_uv(uint8_t *dstU, uint8_t *dstV, const uint8_t *src[4], int width, int is_be, int32_t *rgb2yuv, Half2FloatTables *h2f_tbl) +{ + int i; + int32_t ru = rgb2yuv[RU_IDX], gu = rgb2yuv[GU_IDX], bu = rgb2yuv[BU_IDX]; + int32_t rv = rgb2yuv[RV_IDX], gv = rgb2yuv[GV_IDX], bv = rgb2yuv[BV_IDX]; + + for (i = 0; i < width; i++) { + int g = lrintf(av_clipf(65535.0f * rdpx2(src[0] + 2*i), 0.0f, 65535.0f)); + int b = lrintf(av_clipf(65535.0f * rdpx2(src[1] + 2*i), 0.0f, 65535.0f)); + int r = lrintf(av_clipf(65535.0f * rdpx2(src[2] + 2*i), 0.0f, 65535.0f)); + + AV_WN16(dstU + 2*i, (ru*r + gu*g + bu*b + (0x10001 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT); + AV_WN16(dstV + 2*i, (rv*r + gv*g + bv*b + (0x10001 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT); + } +} + +static av_always_inline void planar_rgbf16_to_y(uint8_t *dst, const uint8_t *src[4], int width, int is_be, int32_t *rgb2yuv, Half2FloatTables *h2f_tbl) +{ + int i; + + int32_t ry = rgb2yuv[RY_IDX], gy = rgb2yuv[GY_IDX], by = rgb2yuv[BY_IDX]; + + for (i = 0; i < width; i++) { + int g = lrintf(av_clipf(65535.0f * rdpx2(src[0] + 2*i), 0.0f, 65535.0f)); + int b = lrintf(av_clipf(65535.0f * rdpx2(src[1] + 2*i), 0.0f, 65535.0f)); + int r = lrintf(av_clipf(65535.0f * rdpx2(src[2] + 2*i), 0.0f, 65535.0f)); + + AV_WN16(dst + 2*i, (ry*r + gy*g + by*b + (0x2001 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT); + } +} + +static av_always_inline void grayf16ToY16_c(uint8_t *dst, const uint8_t *src, const uint8_t *unused1, + const uint8_t *unused2, int width, int is_be, uint32_t *unused, Half2FloatTables *h2f_tbl) +{ + int i; + + for (i = 0; i < width; ++i){ + AV_WN16(dst + 2*i, lrintf(av_clipf(65535.0f * rdpx2(src + 2*i), 0.0f, 65535.0f))); + } +} static av_always_inline void rgbaf16ToUV_half_endian(uint16_t *dstU, uint16_t *dstV, int is_be, const uint16_t *src, int width, @@ -1484,6 +1535,28 @@ static av_always_inline void rgbf16ToY_endian(uint16_t *dst, const uint16_t *src #undef rdpx #define rgbaf16_funcs_endian(endian_name, endian) \ +static void planar_rgbf16##endian_name##_to_y(uint8_t *dst, const uint8_t *src[4], \ + int w, int32_t *rgb2yuv, void *opq) \ +{ \ + planar_rgbf16_to_y(dst, src, w, endian, rgb2yuv, opq); \ +} \ +static void planar_rgbf16##endian_name##_to_uv(uint8_t *dstU, uint8_t *dstV, \ + const uint8_t *src[4], int w, int32_t *rgb2yuv, \ + void *opq) \ +{ \ + planar_rgbf16_to_uv(dstU, dstV, src, w, endian, rgb2yuv, opq); \ +} \ +static void planar_rgbf16##endian_name##_to_a(uint8_t *dst, const uint8_t *src[4], \ + int w, int32_t *rgb2yuv, void *opq) \ +{ \ + planar_rgbf16_to_a(dst, src, w, endian, rgb2yuv, opq); \ +} \ +static void grayf16##endian_name##ToY16_c(uint8_t *dst, const uint8_t *src, \ + const uint8_t *unused1, const uint8_t *unused2, \ + int width, uint32_t *unused, void *opq) \ +{ \ + grayf16ToY16_c(dst, src, unused1, unused2, width, endian, unused, opq); \ +} \ static void rgbaf16##endian_name##ToUV_half_c(uint8_t *_dstU, uint8_t *_dstV, const uint8_t *unused, \ const uint8_t *src1, const uint8_t *src2, \ int width, uint32_t *_rgb2yuv, void *opq) \ @@ -1618,6 +1691,10 @@ av_cold void ff_sws_init_input_funcs(SwsInternal *c, case AV_PIX_FMT_GBRPF32LE: *readChrPlanar = planar_rgbf32le_to_uv; break; + case AV_PIX_FMT_GBRAPF16LE: + case AV_PIX_FMT_GBRPF16LE: + *readChrPlanar = planar_rgbf16le_to_uv; + break; case AV_PIX_FMT_GBRP9BE: *readChrPlanar = planar_rgb9be_to_uv; break; @@ -1641,6 +1718,10 @@ av_cold void ff_sws_init_input_funcs(SwsInternal *c, case AV_PIX_FMT_GBRPF32BE: *readChrPlanar = planar_rgbf32be_to_uv; break; + case AV_PIX_FMT_GBRAPF16BE: + case AV_PIX_FMT_GBRPF16BE: + *readChrPlanar = planar_rgbf16be_to_uv; + break; case AV_PIX_FMT_GBRAP: case AV_PIX_FMT_GBRP: *readChrPlanar = planar_rgb_to_uv; @@ -2025,6 +2106,11 @@ av_cold void ff_sws_init_input_funcs(SwsInternal *c, case AV_PIX_FMT_GBRPF32LE: *readLumPlanar = planar_rgbf32le_to_y; break; + case AV_PIX_FMT_GBRAPF16LE: + *readAlpPlanar = planar_rgbf16le_to_a; + case AV_PIX_FMT_GBRPF16LE: + *readLumPlanar = planar_rgbf16le_to_y; + break; case AV_PIX_FMT_GBRP9BE: *readLumPlanar = planar_rgb9be_to_y; break; @@ -2053,6 +2139,11 @@ av_cold void ff_sws_init_input_funcs(SwsInternal *c, case AV_PIX_FMT_GBRPF32BE: *readLumPlanar = planar_rgbf32be_to_y; break; + case AV_PIX_FMT_GBRAPF16BE: + *readAlpPlanar = planar_rgbf16be_to_a; + case AV_PIX_FMT_GBRPF16BE: + *readLumPlanar = planar_rgbf16be_to_y; + break; case AV_PIX_FMT_GBRAP: *readAlpPlanar = planar_rgb_to_a; case AV_PIX_FMT_GBRP: @@ -2309,6 +2400,12 @@ av_cold void ff_sws_init_input_funcs(SwsInternal *c, case AV_PIX_FMT_GRAYF32BE: *lumToYV12 = grayf32beToY16_c; break; + case AV_PIX_FMT_GRAYF16LE: + *lumToYV12 = grayf16leToY16_c; + break; + case AV_PIX_FMT_GRAYF16BE: + *lumToYV12 = grayf16beToY16_c; + break; case AV_PIX_FMT_Y210LE: *lumToYV12 = y210le_Y_c; break; diff --git a/libswscale/swscale_unscaled.c b/libswscale/swscale_unscaled.c index dae3f45df9..1ab36b9568 100644 --- a/libswscale/swscale_unscaled.c +++ b/libswscale/swscale_unscaled.c @@ -2655,11 +2655,12 @@ void ff_get_unscaled_swscale(SwsInternal *c) c->convert_unscaled = nv24ToYuv420Wrapper; #define isPlanarGray(x) (isGray(x) && (x) != AV_PIX_FMT_YA8 && (x) != AV_PIX_FMT_YA16LE && (x) != AV_PIX_FMT_YA16BE) + /* simple copy */ if ( srcFormat == dstFormat || (srcFormat == AV_PIX_FMT_YUVA420P && dstFormat == AV_PIX_FMT_YUV420P) || (srcFormat == AV_PIX_FMT_YUV420P && dstFormat == AV_PIX_FMT_YUVA420P) || - (isFloat(srcFormat) == isFloat(dstFormat)) && ((isPlanarYUV(srcFormat) && isPlanarGray(dstFormat)) || + (isFloat(srcFormat) == isFloat(dstFormat) && isFloat16(srcFormat) == isFloat16(dstFormat)) && ((isPlanarYUV(srcFormat) && isPlanarGray(dstFormat)) || (isPlanarYUV(dstFormat) && isPlanarGray(srcFormat)) || (isPlanarGray(dstFormat) && isPlanarGray(srcFormat)) || (isPlanarYUV(srcFormat) && isPlanarYUV(dstFormat) && diff --git a/libswscale/utils.c b/libswscale/utils.c index 445ad8ae71..c2fbaf5515 100644 --- a/libswscale/utils.c +++ b/libswscale/utils.c @@ -219,6 +219,10 @@ static const FormatEntry format_entries[] = { [AV_PIX_FMT_GBRPF32BE] = { 1, 1 }, [AV_PIX_FMT_GBRAPF32LE] = { 1, 1 }, [AV_PIX_FMT_GBRAPF32BE] = { 1, 1 }, + [AV_PIX_FMT_GBRPF16LE] = { 1, 0 }, + [AV_PIX_FMT_GBRPF16BE] = { 1, 0 }, + [AV_PIX_FMT_GBRAPF16LE] = { 1, 0 }, + [AV_PIX_FMT_GBRAPF16BE] = { 1, 0 }, [AV_PIX_FMT_GBRAP] = { 1, 1 }, [AV_PIX_FMT_GBRAP16LE] = { 1, 1 }, [AV_PIX_FMT_GBRAP16BE] = { 1, 1 }, @@ -246,6 +250,8 @@ static const FormatEntry format_entries[] = { [AV_PIX_FMT_P016BE] = { 1, 1 }, [AV_PIX_FMT_GRAYF32LE] = { 1, 1 }, [AV_PIX_FMT_GRAYF32BE] = { 1, 1 }, + [AV_PIX_FMT_GRAYF16LE] = { 1, 0 }, + [AV_PIX_FMT_GRAYF16BE] = { 1, 0 }, [AV_PIX_FMT_YUVA422P12BE] = { 1, 1 }, [AV_PIX_FMT_YUVA422P12LE] = { 1, 1 }, [AV_PIX_FMT_YUVA444P12BE] = { 1, 1 }, @@ -1578,6 +1584,8 @@ av_cold int ff_sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter, srcFormat != AV_PIX_FMT_GBRAP16BE && srcFormat != AV_PIX_FMT_GBRAP16LE && srcFormat != AV_PIX_FMT_GBRPF32BE && srcFormat != AV_PIX_FMT_GBRPF32LE && srcFormat != AV_PIX_FMT_GBRAPF32BE && srcFormat != AV_PIX_FMT_GBRAPF32LE && + srcFormat != AV_PIX_FMT_GBRPF16BE && srcFormat != AV_PIX_FMT_GBRPF16LE && + srcFormat != AV_PIX_FMT_GBRAPF16BE && srcFormat != AV_PIX_FMT_GBRAPF16LE && ((dstW >> c->chrDstHSubSample) <= (srcW >> 1) || (flags & SWS_FAST_BILINEAR))) c->chrSrcHSubSample = 1;