[FFmpeg-devel] [PATCH] swscale/input: add rgbaf16 input support

Mark Reid mindmark at gmail.com
Mon Aug 8 22:39:34 EEST 2022


On Mon, Aug 8, 2022 at 11:24 AM Timo Rothenpieler <timo at rothenpieler.org>
wrote:

> This is by no means perfect, since at least ddagrab will return scRGB
> data with values outside of 0.0f to 1.0f for HDR values.
> Its primary purpose is to be able to work with the format at all.
>
> _Float16 support was available on arm/aarch64 for a while, and with gcc
> 12 was enabled on x86 as long as SSE2 is supported.
>
> If the target arch supports f16c, gcc emits fairly efficient assembly,
> taking advantage of it. This is the case on x86-64-v3 or higher.
> Without f16c, it emulates it in software using sse2 instructions.
> ---
>
> I am by no means certain this is the correct way to implement this.
> Tested it with ddagrab output in that format, and it looks like what I'd
> expect.
>
> Specially the order of arguments is a bit of a mystery. I'd have
> expected them to be in order of the planes, so for packed formats, only
> the first one would matter.
> But a bunch of other packed formats left the first src unused, and so I
> followed along, and it ended up working fine.
>
>
Have you looked at the exr decoder half2float.h? It already has f16 to f32
decoding functions.


>  configure            |  2 +
>  libswscale/input.c   | 95 ++++++++++++++++++++++++++++++++++++++++++++
>  libswscale/utils.c   |  3 ++
>  libswscale/version.h |  2 +-
>  4 files changed, 101 insertions(+), 1 deletion(-)
>
> diff --git a/configure b/configure
> index 6761d0cb32..d989498bba 100755
> --- a/configure
> +++ b/configure
> @@ -2143,6 +2143,7 @@ ARCH_FEATURES="
>      fast_64bit
>      fast_clz
>      fast_cmov
> +    float16
>      local_aligned
>      simd_align_16
>      simd_align_32
> @@ -6228,6 +6229,7 @@ check_builtin MemoryBarrier windows.h
> "MemoryBarrier()"
>  check_builtin sync_val_compare_and_swap "" "int *ptr; int oldval, newval;
> __sync_val_compare_and_swap(ptr, oldval, newval)"
>  check_builtin gmtime_r time.h "time_t *time; struct tm *tm;
> gmtime_r(time, tm)"
>  check_builtin localtime_r time.h "time_t *time; struct tm *tm;
> localtime_r(time, tm)"
> +check_builtin float16 "" "_Float16 f16var"
>
>  case "$custom_allocator" in
>      jemalloc)
> diff --git a/libswscale/input.c b/libswscale/input.c
> index 68abc4d62c..0b5bd952e8 100644
> --- a/libswscale/input.c
> +++ b/libswscale/input.c
> @@ -1111,6 +1111,89 @@ static void grayf32##endian_name##ToY16_c(uint8_t
> *dst, const uint8_t *src,
>  rgbf32_planar_funcs_endian(le, 0)
>  rgbf32_planar_funcs_endian(be, 1)
>
> +static void rgbaf16ToUV_half_c(uint8_t *_dstU, uint8_t *_dstV,
> +                               const uint8_t *unused0, const uint8_t
> *src1, const uint8_t *src2,
> +                               int width, uint32_t *_rgb2yuv)
> +{
> +#if HAVE_FLOAT16
> +    const _Float16 *src = (const _Float16*)src1;
> +    uint16_t *dstU = (uint16_t*)_dstU;
> +    uint16_t *dstV = (uint16_t*)_dstV;
> +    int32_t *rgb2yuv = (int32_t*)_rgb2yuv;
> +    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];
> +    int i;
> +    av_assert1(src1==src2);
> +    for (i = 0; i < width; i++) {
> +        int r = (lrintf(av_clipf(65535.0f * src[i*8+0], 0.0f, 65535.0f)) +
> +                 lrintf(av_clipf(65535.0f * src[i*8+4], 0.0f, 65535.0f)))
> >> 1;
> +        int g = (lrintf(av_clipf(65535.0f * src[i*8+1], 0.0f, 65535.0f)) +
> +                 lrintf(av_clipf(65535.0f * src[i*8+5], 0.0f, 65535.0f)))
> >> 1;
> +        int b = (lrintf(av_clipf(65535.0f * src[i*8+2], 0.0f, 65535.0f)) +
> +                 lrintf(av_clipf(65535.0f * src[i*8+6], 0.0f, 65535.0f)))
> >> 1;
> +
> +        dstU[i] = (ru*r + gu*g + bu*b + (0x10001<<(RGB2YUV_SHIFT-1))) >>
> RGB2YUV_SHIFT;
> +        dstV[i] = (rv*r + gv*g + bv*b + (0x10001<<(RGB2YUV_SHIFT-1))) >>
> RGB2YUV_SHIFT;
> +    }
> +#endif
> +}
> +
> +static void rgbaf16ToUV_c(uint8_t *_dstU, uint8_t *_dstV,
> +                          const uint8_t *unused0, const uint8_t *src1,
> const uint8_t *src2,
> +                          int width, uint32_t *_rgb2yuv)
> +{
> +#if HAVE_FLOAT16
> +    const _Float16 *src = (const _Float16*)src1;
> +    uint16_t *dstU = (uint16_t*)_dstU;
> +    uint16_t *dstV = (uint16_t*)_dstV;
> +    int32_t *rgb2yuv = (int32_t*)_rgb2yuv;
> +    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];
> +    int i;
> +    av_assert1(src1==src2);
> +    for (i = 0; i < width; i++) {
> +        int r = lrintf(av_clipf(65535.0f * src[i*4+0], 0.0f, 65535.0f));
> +        int g = lrintf(av_clipf(65535.0f * src[i*4+1], 0.0f, 65535.0f));
> +        int b = lrintf(av_clipf(65535.0f * src[i*4+2], 0.0f, 65535.0f));
> +
> +        dstU[i] = (ru*r + gu*g + bu*b + (0x10001<<(RGB2YUV_SHIFT-1))) >>
> RGB2YUV_SHIFT;
> +        dstV[i] = (rv*r + gv*g + bv*b + (0x10001<<(RGB2YUV_SHIFT-1))) >>
> RGB2YUV_SHIFT;
> +    }
> +#endif
> +}
> +
> +static void rgbaf16ToY_c(uint8_t *_dst, const uint8_t *_src, const
> uint8_t *unused0, const uint8_t *unused1,
> +                         int width, uint32_t *_rgb2yuv)
> +{
> +#if HAVE_FLOAT16
> +    const _Float16 *src = (const _Float16*)_src;
> +    uint16_t *dst = (uint16_t*)_dst;
> +    int32_t *rgb2yuv = (int32_t*)_rgb2yuv;
> +    int32_t ry = rgb2yuv[RY_IDX], gy = rgb2yuv[GY_IDX], by =
> rgb2yuv[BY_IDX];
> +    int i;
> +    for (i = 0; i < width; i++) {
> +        int r = lrintf(av_clipf(65535.0f * src[i*4+0], 0.0f, 65535.0f));
> +        int g = lrintf(av_clipf(65535.0f * src[i*4+1], 0.0f, 65535.0f));
> +        int b = lrintf(av_clipf(65535.0f * src[i*4+2], 0.0f, 65535.0f));
> +
> +        dst[i] = (ry*r + gy*g + by*b + (0x2001<<(RGB2YUV_SHIFT-1))) >>
> RGB2YUV_SHIFT;
> +    }
> +#endif
> +}
> +
> +static void rgbaf16ToA_c(uint8_t *_dst, const uint8_t *_src, const
> uint8_t *unused0, const uint8_t *unused1,
> +                         int width, uint32_t *unused2)
> +{
> +#if HAVE_FLOAT16
> +    const _Float16 *src = (const _Float16*)_src;
> +    uint16_t *dst = (uint16_t*)_dst;
> +    int i;
> +    for (i=0; i<width; i++) {
> +        dst[i] = lrintf(av_clipf(65535.0f * src[i*4+3], 0.0f, 65535.0f));
> +    }
> +#endif
> +}
> +
>  av_cold void ff_sws_init_input_funcs(SwsContext *c)
>  {
>      enum AVPixelFormat srcFormat = c->srcFormat;
> @@ -1375,6 +1458,9 @@ av_cold void ff_sws_init_input_funcs(SwsContext *c)
>          case AV_PIX_FMT_X2BGR10LE:
>              c->chrToYV12 = bgr30leToUV_half_c;
>              break;
> +        case AV_PIX_FMT_RGBAF16:
> +            c->chrToYV12 = rgbaf16ToUV_half_c;
> +            break;
>          }
>      } else {
>          switch (srcFormat) {
> @@ -1462,6 +1548,9 @@ av_cold void ff_sws_init_input_funcs(SwsContext *c)
>          case AV_PIX_FMT_X2BGR10LE:
>              c->chrToYV12 = bgr30leToUV_c;
>              break;
> +        case AV_PIX_FMT_RGBAF16:
> +            c->chrToYV12 = rgbaf16ToUV_c;
> +            break;
>          }
>      }
>
> @@ -1750,6 +1839,9 @@ av_cold void ff_sws_init_input_funcs(SwsContext *c)
>      case AV_PIX_FMT_X2BGR10LE:
>          c->lumToYV12 = bgr30leToY_c;
>          break;
> +    case AV_PIX_FMT_RGBAF16:
> +        c->lumToYV12 = rgbaf16ToY_c;
> +        break;
>      }
>      if (c->needAlpha) {
>          if (is16BPS(srcFormat) || isNBPS(srcFormat)) {
> @@ -1769,6 +1861,9 @@ av_cold void ff_sws_init_input_funcs(SwsContext *c)
>          case AV_PIX_FMT_ARGB:
>              c->alpToYV12 = abgrToA_c;
>              break;
> +        case AV_PIX_FMT_RGBAF16:
> +            c->alpToYV12 = rgbaf16ToA_c;
> +            break;
>          case AV_PIX_FMT_YA8:
>              c->alpToYV12 = uyvyToY_c;
>              break;
> diff --git a/libswscale/utils.c b/libswscale/utils.c
> index 34503e57f4..c5c22017ff 100644
> --- a/libswscale/utils.c
> +++ b/libswscale/utils.c
> @@ -259,6 +259,9 @@ static const FormatEntry format_entries[] = {
>      [AV_PIX_FMT_P416LE]      = { 1, 1 },
>      [AV_PIX_FMT_NV16]        = { 1, 1 },
>      [AV_PIX_FMT_VUYA]        = { 1, 1 },
> +#if HAVE_FLOAT16
> +    [AV_PIX_FMT_RGBAF16]     = { 1, 0 },
> +#endif
>  };
>
>  int ff_shuffle_filter_coefficients(SwsContext *c, int *filterPos,
> diff --git a/libswscale/version.h b/libswscale/version.h
> index 3193562d18..d8694bb5c0 100644
> --- a/libswscale/version.h
> +++ b/libswscale/version.h
> @@ -29,7 +29,7 @@
>  #include "version_major.h"
>
>  #define LIBSWSCALE_VERSION_MINOR   8
> -#define LIBSWSCALE_VERSION_MICRO 102
> +#define LIBSWSCALE_VERSION_MICRO 103
>
>  #define LIBSWSCALE_VERSION_INT  AV_VERSION_INT(LIBSWSCALE_VERSION_MAJOR, \
>                                                 LIBSWSCALE_VERSION_MINOR, \
> --
> 2.34.1
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request at ffmpeg.org with subject "unsubscribe".
>


More information about the ffmpeg-devel mailing list