[FFmpeg-devel,4/7] Adds gray floating-point pixel formats.

Submitted by Sergey Lavrushkin on Aug. 9, 2018, 5:15 p.m.

Details

Message ID CAAeE=qq+XgSp6Bw5QJyCwBNwTuCbfP37fvUXPnXbs=SwnbF3YQ@mail.gmail.com
State New
Headers show

Commit Message

Sergey Lavrushkin Aug. 9, 2018, 5:15 p.m.
Here are updated patches with fixes. I updated conversion functions, so
they should
properly work with format for different endianness.

2018-08-08 1:47 GMT+03:00 Michael Niedermayer <michael@niedermayer.cc>:

> On Tue, Aug 07, 2018 at 12:17:58AM +0300, Sergey Lavrushkin wrote:
> > I split patch to one for libavutil and another for libswscale,
> > also added LUT for unscaled conversion, added
> > conversions for scaling and updated fate tests.
>
> >  libavutil/pixdesc.c              |   22 ++++++++++++++++++++++
> >  libavutil/pixfmt.h               |    5 +++++
> >  libavutil/version.h              |    2 +-
> >  tests/ref/fate/sws-pixdesc-query |    3 +++
> >  4 files changed, 31 insertions(+), 1 deletion(-)
> > b58f328f5d90954c62957f127b1acbfad5795a4d  0004-libavutil-Adds-gray-
> floating-point-pixel-formats.patch
> > From 8bcc10b49c41612b4d6549e64d90acf3f0b3fc6a Mon Sep 17 00:00:00 2001
> > From: Sergey Lavrushkin <dualfal@gmail.com>
> > Date: Fri, 3 Aug 2018 18:02:49 +0300
> > Subject: [PATCH 4/9] libavutil: Adds gray floating-point pixel formats.
> >
> > ---
> >  libavutil/pixdesc.c              | 22 ++++++++++++++++++++++
> >  libavutil/pixfmt.h               |  5 +++++
> >  libavutil/version.h              |  2 +-
> >  tests/ref/fate/sws-pixdesc-query |  3 +++
> >  4 files changed, 31 insertions(+), 1 deletion(-)
> >
> > diff --git a/libavutil/pixdesc.c b/libavutil/pixdesc.c
> > index 96e079584a..970a83214c 100644
> > --- a/libavutil/pixdesc.c
> > +++ b/libavutil/pixdesc.c
> > @@ -2206,6 +2206,28 @@ static const AVPixFmtDescriptor
> av_pix_fmt_descriptors[AV_PIX_FMT_NB] = {
> >          .name  = "opencl",
> >          .flags = AV_PIX_FMT_FLAG_HWACCEL,
> >      },
> > +    [AV_PIX_FMT_GRAYF32BE] = {
> > +        .name = "grayf32be",
> > +        .nb_components = 1,
> > +        .log2_chroma_w = 0,
> > +        .log2_chroma_h = 0,
> > +        .comp = {
> > +            { 0, 4, 0, 0, 32, 3, 31, 1 },       /* Y */
> > +        },
> > +        .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_FLOAT,
> > +        .alias = "yf32be",
> > +    },
> > +    [AV_PIX_FMT_GRAYF32LE] = {
> > +        .name = "grayf32le",
> > +        .nb_components = 1,
> > +        .log2_chroma_w = 0,
> > +        .log2_chroma_h = 0,
> > +        .comp = {
> > +            { 0, 4, 0, 0, 32, 3, 31, 1 },       /* Y */
> > +        },
> > +        .flags = AV_PIX_FMT_FLAG_FLOAT,
> > +        .alias = "yf32le",
> > +    },
> >  };
> >  #if FF_API_PLUS1_MINUS1
> >  FF_ENABLE_DEPRECATION_WARNINGS
> > diff --git a/libavutil/pixfmt.h b/libavutil/pixfmt.h
> > index 2b3307845e..7b254732d8 100644
> > --- a/libavutil/pixfmt.h
> > +++ b/libavutil/pixfmt.h
> > @@ -337,6 +337,9 @@ enum AVPixelFormat {
> >      AV_PIX_FMT_GRAY14BE,   ///<        Y        , 14bpp, big-endian
> >      AV_PIX_FMT_GRAY14LE,   ///<        Y        , 14bpp, little-endian
> >
> > +    AV_PIX_FMT_GRAYF32BE,  ///< IEEE-754 single precision Y, 32bpp,
> big-endian
> > +    AV_PIX_FMT_GRAYF32LE,  ///< IEEE-754 single precision Y, 32bpp,
> little-endian
> > +
> >      AV_PIX_FMT_NB         ///< number of pixel formats, DO NOT USE THIS
> if you want to link with shared libav* because the number of formats might
> differ between versions
> >  };
> >
> > @@ -405,6 +408,8 @@ enum AVPixelFormat {
> >  #define AV_PIX_FMT_GBRPF32    AV_PIX_FMT_NE(GBRPF32BE,  GBRPF32LE)
> >  #define AV_PIX_FMT_GBRAPF32   AV_PIX_FMT_NE(GBRAPF32BE, GBRAPF32LE)
> >
> > +#define AV_PIX_FMT_GRAYF32 AV_PIX_FMT_NE(GRAYF32BE, GRAYF32LE)
> > +
> >  #define AV_PIX_FMT_YUVA420P9  AV_PIX_FMT_NE(YUVA420P9BE , YUVA420P9LE)
> >  #define AV_PIX_FMT_YUVA422P9  AV_PIX_FMT_NE(YUVA422P9BE , YUVA422P9LE)
> >  #define AV_PIX_FMT_YUVA444P9  AV_PIX_FMT_NE(YUVA444P9BE , YUVA444P9LE)
> > diff --git a/libavutil/version.h b/libavutil/version.h
> > index 44bdebdc93..5205c5bc60 100644
> > --- a/libavutil/version.h
> > +++ b/libavutil/version.h
>
> > @@ -79,7 +79,7 @@
> >   */
> >
> >  #define LIBAVUTIL_VERSION_MAJOR  56
> > -#define LIBAVUTIL_VERSION_MINOR  18
> > +#define LIBAVUTIL_VERSION_MINOR  19
> >  #define LIBAVUTIL_VERSION_MICRO 102
>
> a bump to minor must reset micro to 100
>
> [...]
>
> --
> Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
>
> In a rich man's house there is no place to spit but his face.
> -- Diogenes of Sinope
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
>

Comments

Michael Niedermayer Aug. 10, 2018, 5:24 p.m.
On Thu, Aug 09, 2018 at 08:15:16PM +0300, Sergey Lavrushkin wrote:
> Here are updated patches with fixes. I updated conversion functions, so
> they should
> properly work with format for different endianness.
[...]
> diff --git a/libswscale/input.c b/libswscale/input.c
> index 3fd3a5d81e..0e016d387f 100644
> --- a/libswscale/input.c
> +++ b/libswscale/input.c
> @@ -942,6 +942,30 @@ static av_always_inline void planar_rgb16_to_uv(uint8_t *_dstU, uint8_t *_dstV,
>  }
>  #undef rdpx
>  
> +static av_always_inline void grayf32ToY16_c(uint8_t *_dst, const uint8_t *_src, const uint8_t *unused1,
> +                                            const uint8_t *unused2, int width, uint32_t *unused)
> +{
> +    int i;
> +    const float *src = (const float *)_src;
> +    uint16_t *dst    = (uint16_t *)_dst;
> +
> +    for (i = 0; i < width; ++i){
> +        dst[i] = lrintf(65535.0f * FFMIN(FFMAX(src[i], 0.0f), 1.0f));
> +    }
> +}

is it faster to clip the float before lrintf() than the integer afterwards ?


[...]
> diff --git a/libswscale/output.c b/libswscale/output.c
> index 0af2fffea4..cd408fb285 100644
> --- a/libswscale/output.c
> +++ b/libswscale/output.c
> @@ -208,6 +208,121 @@ static void yuv2p016cX_c(SwsContext *c, const int16_t *chrFilter, int chrFilterS
>      }
>  }
>  
> +static av_always_inline void
> +yuv2plane1_float_c_template(const int32_t *src, float *dest, int dstW)
> +{
> +#if HAVE_BIGENDIAN
> +    static const int big_endian = 1;
> +#else
> +    static const int big_endian = 0;
> +#endif

you can use HAVE_BIGENDIAN in place of big_endian
its either 0 or 1 already
or static const int big_endian = HAVE_BIGENDIAN

[...]
Michael Niedermayer Aug. 11, 2018, 12:53 a.m.
On Thu, Aug 09, 2018 at 08:15:16PM +0300, Sergey Lavrushkin wrote:
> Here are updated patches with fixes. I updated conversion functions, so
> they should
> properly work with format for different endianness.
> 
> 2018-08-08 1:47 GMT+03:00 Michael Niedermayer <michael@niedermayer.cc>:
> 
> > On Tue, Aug 07, 2018 at 12:17:58AM +0300, Sergey Lavrushkin wrote:
> > > I split patch to one for libavutil and another for libswscale,
> > > also added LUT for unscaled conversion, added
> > > conversions for scaling and updated fate tests.
> >
> > >  libavutil/pixdesc.c              |   22 ++++++++++++++++++++++
> > >  libavutil/pixfmt.h               |    5 +++++
> > >  libavutil/version.h              |    2 +-
> > >  tests/ref/fate/sws-pixdesc-query |    3 +++
> > >  4 files changed, 31 insertions(+), 1 deletion(-)
> > > b58f328f5d90954c62957f127b1acbfad5795a4d  0004-libavutil-Adds-gray-
> > floating-point-pixel-formats.patch
> > > From 8bcc10b49c41612b4d6549e64d90acf3f0b3fc6a Mon Sep 17 00:00:00 2001
> > > From: Sergey Lavrushkin <dualfal@gmail.com>
> > > Date: Fri, 3 Aug 2018 18:02:49 +0300
> > > Subject: [PATCH 4/9] libavutil: Adds gray floating-point pixel formats.
> > >
> > > ---
> > >  libavutil/pixdesc.c              | 22 ++++++++++++++++++++++
> > >  libavutil/pixfmt.h               |  5 +++++
> > >  libavutil/version.h              |  2 +-
> > >  tests/ref/fate/sws-pixdesc-query |  3 +++
> > >  4 files changed, 31 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/libavutil/pixdesc.c b/libavutil/pixdesc.c
> > > index 96e079584a..970a83214c 100644
> > > --- a/libavutil/pixdesc.c
> > > +++ b/libavutil/pixdesc.c
> > > @@ -2206,6 +2206,28 @@ static const AVPixFmtDescriptor
> > av_pix_fmt_descriptors[AV_PIX_FMT_NB] = {
> > >          .name  = "opencl",
> > >          .flags = AV_PIX_FMT_FLAG_HWACCEL,
> > >      },
> > > +    [AV_PIX_FMT_GRAYF32BE] = {
> > > +        .name = "grayf32be",
> > > +        .nb_components = 1,
> > > +        .log2_chroma_w = 0,
> > > +        .log2_chroma_h = 0,
> > > +        .comp = {
> > > +            { 0, 4, 0, 0, 32, 3, 31, 1 },       /* Y */
> > > +        },
> > > +        .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_FLOAT,
> > > +        .alias = "yf32be",
> > > +    },
> > > +    [AV_PIX_FMT_GRAYF32LE] = {
> > > +        .name = "grayf32le",
> > > +        .nb_components = 1,
> > > +        .log2_chroma_w = 0,
> > > +        .log2_chroma_h = 0,
> > > +        .comp = {
> > > +            { 0, 4, 0, 0, 32, 3, 31, 1 },       /* Y */
> > > +        },
> > > +        .flags = AV_PIX_FMT_FLAG_FLOAT,
> > > +        .alias = "yf32le",
> > > +    },
> > >  };
> > >  #if FF_API_PLUS1_MINUS1
> > >  FF_ENABLE_DEPRECATION_WARNINGS
> > > diff --git a/libavutil/pixfmt.h b/libavutil/pixfmt.h
> > > index 2b3307845e..7b254732d8 100644
> > > --- a/libavutil/pixfmt.h
> > > +++ b/libavutil/pixfmt.h
> > > @@ -337,6 +337,9 @@ enum AVPixelFormat {
> > >      AV_PIX_FMT_GRAY14BE,   ///<        Y        , 14bpp, big-endian
> > >      AV_PIX_FMT_GRAY14LE,   ///<        Y        , 14bpp, little-endian
> > >
> > > +    AV_PIX_FMT_GRAYF32BE,  ///< IEEE-754 single precision Y, 32bpp,
> > big-endian
> > > +    AV_PIX_FMT_GRAYF32LE,  ///< IEEE-754 single precision Y, 32bpp,
> > little-endian
> > > +
> > >      AV_PIX_FMT_NB         ///< number of pixel formats, DO NOT USE THIS
> > if you want to link with shared libav* because the number of formats might
> > differ between versions
> > >  };
> > >
> > > @@ -405,6 +408,8 @@ enum AVPixelFormat {
> > >  #define AV_PIX_FMT_GBRPF32    AV_PIX_FMT_NE(GBRPF32BE,  GBRPF32LE)
> > >  #define AV_PIX_FMT_GBRAPF32   AV_PIX_FMT_NE(GBRAPF32BE, GBRAPF32LE)
> > >
> > > +#define AV_PIX_FMT_GRAYF32 AV_PIX_FMT_NE(GRAYF32BE, GRAYF32LE)
> > > +
> > >  #define AV_PIX_FMT_YUVA420P9  AV_PIX_FMT_NE(YUVA420P9BE , YUVA420P9LE)
> > >  #define AV_PIX_FMT_YUVA422P9  AV_PIX_FMT_NE(YUVA422P9BE , YUVA422P9LE)
> > >  #define AV_PIX_FMT_YUVA444P9  AV_PIX_FMT_NE(YUVA444P9BE , YUVA444P9LE)
> > > diff --git a/libavutil/version.h b/libavutil/version.h
> > > index 44bdebdc93..5205c5bc60 100644
> > > --- a/libavutil/version.h
> > > +++ b/libavutil/version.h
> >
> > > @@ -79,7 +79,7 @@
> > >   */
> > >
> > >  #define LIBAVUTIL_VERSION_MAJOR  56
> > > -#define LIBAVUTIL_VERSION_MINOR  18
> > > +#define LIBAVUTIL_VERSION_MINOR  19
> > >  #define LIBAVUTIL_VERSION_MICRO 102
> >
> > a bump to minor must reset micro to 100
> >
> > [...]
> >
> > --
> > Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
> >
> > In a rich man's house there is no place to spit but his face.
> > -- Diogenes of Sinope
> >
> > _______________________________________________
> > ffmpeg-devel mailing list
> > ffmpeg-devel@ffmpeg.org
> > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> >
> >

>  libavutil/pixdesc.c              |   22 ++++++++++++++++++++++
>  libavutil/pixfmt.h               |    5 +++++
>  libavutil/version.h              |    4 ++--
>  tests/ref/fate/sws-pixdesc-query |    3 +++
>  4 files changed, 32 insertions(+), 2 deletions(-)
> 3f2970b080f14bd6d039d6dd09f9ac328daa77ee  0004-libavutil-Adds-gray-floating-point-pixel-formats.patch
> From 724f34ef9c551e7ac5af6f26840c3f2d3396eebd Mon Sep 17 00:00:00 2001
> From: Sergey Lavrushkin <dualfal@gmail.com>
> Date: Fri, 3 Aug 2018 18:02:49 +0300
> Subject: [PATCH 4/9] libavutil: Adds gray floating-point pixel formats.
> 
> ---
>  libavutil/pixdesc.c              | 22 ++++++++++++++++++++++
>  libavutil/pixfmt.h               |  5 +++++
>  libavutil/version.h              |  4 ++--
>  tests/ref/fate/sws-pixdesc-query |  3 +++
>  4 files changed, 32 insertions(+), 2 deletions(-)

will apply the patch above

thx

[...]

Patch hide | download patch | download mbox

From 3a58b775dc7a4eceb7bedb8b532fc59da32c41d9 Mon Sep 17 00:00:00 2001
From: Sergey Lavrushkin <dualfal@gmail.com>
Date: Fri, 3 Aug 2018 18:06:50 +0300
Subject: [PATCH 5/9] libswscale: Adds conversions from/to float gray format.

---
 libswscale/input.c                       |  38 ++++++++++
 libswscale/output.c                      | 121 +++++++++++++++++++++++++++++++
 libswscale/ppc/swscale_altivec.c         |   1 +
 libswscale/swscale_internal.h            |   9 +++
 libswscale/swscale_unscaled.c            |  54 +++++++++++++-
 libswscale/utils.c                       |  20 ++++-
 libswscale/x86/swscale_template.c        |   3 +-
 tests/ref/fate/filter-pixdesc-grayf32be  |   1 +
 tests/ref/fate/filter-pixdesc-grayf32le  |   1 +
 tests/ref/fate/filter-pixfmts-copy       |   2 +
 tests/ref/fate/filter-pixfmts-crop       |   2 +
 tests/ref/fate/filter-pixfmts-field      |   2 +
 tests/ref/fate/filter-pixfmts-fieldorder |   2 +
 tests/ref/fate/filter-pixfmts-hflip      |   2 +
 tests/ref/fate/filter-pixfmts-il         |   2 +
 tests/ref/fate/filter-pixfmts-null       |   2 +
 tests/ref/fate/filter-pixfmts-scale      |   2 +
 tests/ref/fate/filter-pixfmts-transpose  |   2 +
 tests/ref/fate/filter-pixfmts-vflip      |   2 +
 19 files changed, 264 insertions(+), 4 deletions(-)
 create mode 100644 tests/ref/fate/filter-pixdesc-grayf32be
 create mode 100644 tests/ref/fate/filter-pixdesc-grayf32le

diff --git a/libswscale/input.c b/libswscale/input.c
index 3fd3a5d81e..0e016d387f 100644
--- a/libswscale/input.c
+++ b/libswscale/input.c
@@ -942,6 +942,30 @@  static av_always_inline void planar_rgb16_to_uv(uint8_t *_dstU, uint8_t *_dstV,
 }
 #undef rdpx
 
+static av_always_inline void grayf32ToY16_c(uint8_t *_dst, const uint8_t *_src, const uint8_t *unused1,
+                                            const uint8_t *unused2, int width, uint32_t *unused)
+{
+    int i;
+    const float *src = (const float *)_src;
+    uint16_t *dst    = (uint16_t *)_dst;
+
+    for (i = 0; i < width; ++i){
+        dst[i] = lrintf(65535.0f * FFMIN(FFMAX(src[i], 0.0f), 1.0f));
+    }
+}
+
+static av_always_inline void grayf32ToY16_bswap_c(uint8_t *_dst, const uint8_t *_src, const uint8_t *unused1,
+                                                  const uint8_t *unused2, int width, uint32_t *unused)
+{
+    int i;
+    const uint32_t *src = (const uint32_t *)_src;
+    uint16_t *dst    = (uint16_t *)_dst;
+
+    for (i = 0; i < width; ++i){
+        dst[i] = lrintf(65535.0f * FFMIN(FFMAX(av_int2float(av_bswap32(src[i])), 0.0f), 1.0f));
+    }
+}
+
 #define rgb9plus_planar_funcs_endian(nbits, endian_name, endian)                                    \
 static void planar_rgb##nbits##endian_name##_to_y(uint8_t *dst, const uint8_t *src[4],              \
                                                   int w, int32_t *rgb2yuv)                          \
@@ -1538,6 +1562,20 @@  av_cold void ff_sws_init_input_funcs(SwsContext *c)
     case AV_PIX_FMT_P010BE:
         c->lumToYV12 = p010BEToY_c;
         break;
+    case AV_PIX_FMT_GRAYF32LE:
+#if HAVE_BIGENDIAN
+        c->lumToYV12 = grayf32ToY16_bswap_c;
+#else
+        c->lumToYV12 = grayf32ToY16_c;
+#endif
+        break;
+    case AV_PIX_FMT_GRAYF32BE:
+#if HAVE_BIGENDIAN
+        c->lumToYV12 = grayf32ToY16_c;
+#else
+        c->lumToYV12 = grayf32ToY16_bswap_c;
+#endif
+        break;
     }
     if (c->needAlpha) {
         if (is16BPS(srcFormat) || isNBPS(srcFormat)) {
diff --git a/libswscale/output.c b/libswscale/output.c
index 0af2fffea4..cd408fb285 100644
--- a/libswscale/output.c
+++ b/libswscale/output.c
@@ -208,6 +208,121 @@  static void yuv2p016cX_c(SwsContext *c, const int16_t *chrFilter, int chrFilterS
     }
 }
 
+static av_always_inline void
+yuv2plane1_float_c_template(const int32_t *src, float *dest, int dstW)
+{
+#if HAVE_BIGENDIAN
+    static const int big_endian = 1;
+#else
+    static const int big_endian = 0;
+#endif
+    static const int shift = 3;
+    static const float float_mult = 1.0f / 65535.0f;
+    int i, val;
+    uint16_t val_uint;
+
+    for (i = 0; i < dstW; ++i){
+        val = src[i] + (1 << (shift - 1));
+        output_pixel(&val_uint, val, 0, uint);
+        dest[i] = float_mult * (float)val_uint;
+    }
+}
+
+static av_always_inline void
+yuv2plane1_float_bswap_c_template(const int32_t *src, uint32_t *dest, int dstW)
+{
+#if HAVE_BIGENDIAN
+    static const int big_endian = 1;
+#else
+    static const int big_endian = 0;
+#endif
+    static const int shift = 3;
+    static const float float_mult = 1.0f / 65535.0f;
+    int i, val;
+    uint16_t val_uint;
+
+    for (i = 0; i < dstW; ++i){
+        val = src[i] + (1 << (shift - 1));
+        output_pixel(&val_uint, val, 0, uint);
+        dest[i] = av_bswap32(av_float2int(float_mult * (float)val_uint));
+    }
+}
+
+static av_always_inline void
+yuv2planeX_float_c_template(const int16_t *filter, int filterSize, const int32_t **src,
+                            float *dest, int dstW)
+{
+#if HAVE_BIGENDIAN
+    static const int big_endian = 1;
+#else
+    static const int big_endian = 0;
+#endif
+    static const int shift = 15;
+    static const float float_mult = 1.0f / 65535.0f;
+    int i, j, val;
+    uint16_t val_uint;
+
+    for (i = 0; i < dstW; ++i){
+        val = (1 << (shift - 1)) - 0x40000000;
+        for (j = 0; j < filterSize; ++j){
+            val += src[j][i] * (unsigned)filter[j];
+        }
+        output_pixel(&val_uint, val, 0x8000, int);
+        dest[i] = float_mult * (float)val_uint;
+    }
+}
+
+static av_always_inline void
+yuv2planeX_float_bswap_c_template(const int16_t *filter, int filterSize, const int32_t **src,
+                            uint32_t *dest, int dstW)
+{
+#if HAVE_BIGENDIAN
+    static const int big_endian = 1;
+#else
+    static const int big_endian = 0;
+#endif
+    static const int shift = 15;
+    static const float float_mult = 1.0f / 65535.0f;
+    int i, j, val;
+    uint16_t val_uint;
+
+    for (i = 0; i < dstW; ++i){
+        val = (1 << (shift - 1)) - 0x40000000;
+        for (j = 0; j < filterSize; ++j){
+            val += src[j][i] * (unsigned)filter[j];
+        }
+        output_pixel(&val_uint, val, 0x8000, int);
+        dest[i] = av_bswap32(av_float2int(float_mult * (float)val_uint));
+    }
+}
+
+#define yuv2plane1_float(template, dest_type, BE_LE) \
+static void yuv2plane1_float ## BE_LE ## _c(const int16_t *src, uint8_t *dest, int dstW, \
+                                            const uint8_t *dither, int offset) \
+{ \
+    template((const int32_t *)src, (dest_type *)dest, dstW); \
+}
+
+#define yuv2planeX_float(template, dest_type, BE_LE) \
+static void yuv2planeX_float ## BE_LE ## _c(const int16_t *filter, int filterSize, \
+                                            const int16_t **src, uint8_t *dest, int dstW, \
+                                            const uint8_t *dither, int offset) \
+{ \
+    template(filter, filterSize, (const int32_t **)src, (dest_type *)dest, dstW); \
+}
+
+#if HAVE_BIGENDIAN
+yuv2plane1_float(yuv2plane1_float_c_template,       float,    BE)
+yuv2plane1_float(yuv2plane1_float_bswap_c_template, uint32_t, LE)
+yuv2planeX_float(yuv2planeX_float_c_template,       float,    BE)
+yuv2planeX_float(yuv2planeX_float_bswap_c_template, uint32_t, LE)
+#else
+yuv2plane1_float(yuv2plane1_float_c_template,       float,    LE)
+yuv2plane1_float(yuv2plane1_float_bswap_c_template, uint32_t, BE)
+yuv2planeX_float(yuv2planeX_float_c_template,       float,    LE)
+yuv2planeX_float(yuv2planeX_float_bswap_c_template, uint32_t, BE)
+#endif
+
 #undef output_pixel
 
 #define output_pixel(pos, val) \
@@ -2303,6 +2418,12 @@  av_cold void ff_sws_init_output_funcs(SwsContext *c,
             *yuv2plane1 = isBE(dstFormat) ? yuv2plane1_14BE_c  : yuv2plane1_14LE_c;
         } else
             av_assert0(0);
+    } else if (dstFormat == AV_PIX_FMT_GRAYF32BE) {
+        *yuv2planeX = yuv2planeX_floatBE_c;
+        *yuv2plane1 = yuv2plane1_floatBE_c;
+    } else if (dstFormat == AV_PIX_FMT_GRAYF32LE) {
+        *yuv2planeX = yuv2planeX_floatLE_c;
+        *yuv2plane1 = yuv2plane1_floatLE_c;
     } else {
         *yuv2plane1 = yuv2plane1_8_c;
         *yuv2planeX = yuv2planeX_8_c;
diff --git a/libswscale/ppc/swscale_altivec.c b/libswscale/ppc/swscale_altivec.c
index 9438a63ff2..2fb2337769 100644
--- a/libswscale/ppc/swscale_altivec.c
+++ b/libswscale/ppc/swscale_altivec.c
@@ -339,6 +339,7 @@  av_cold void ff_sws_init_swscale_ppc(SwsContext *c)
     }
     if (!is16BPS(dstFormat) && !isNBPS(dstFormat) &&
         dstFormat != AV_PIX_FMT_NV12 && dstFormat != AV_PIX_FMT_NV21 &&
+        dstFormat != AV_PIX_FMT_GRAYF32BE && dstFormat != AV_PIX_FMT_GRAYF32LE &&
         !c->needAlpha) {
         c->yuv2planeX = yuv2planeX_altivec;
     }
diff --git a/libswscale/swscale_internal.h b/libswscale/swscale_internal.h
index 1703856ab2..4fa59386a6 100644
--- a/libswscale/swscale_internal.h
+++ b/libswscale/swscale_internal.h
@@ -336,6 +336,8 @@  typedef struct SwsContext {
     uint32_t pal_yuv[256];
     uint32_t pal_rgb[256];
 
+    float uint2float_lut[256];
+
     /**
      * @name Scaled horizontal lines ring buffer.
      * The horizontal scaler keeps just enough scaled lines in a ring buffer
@@ -764,6 +766,13 @@  static av_always_inline int isAnyRGB(enum AVPixelFormat pix_fmt)
             pix_fmt == AV_PIX_FMT_MONOBLACK || pix_fmt == AV_PIX_FMT_MONOWHITE;
 }
 
+static av_always_inline int isFloat(enum AVPixelFormat pix_fmt)
+{
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
+    av_assert0(desc);
+    return desc->flags & AV_PIX_FMT_FLAG_FLOAT;
+}
+
 static av_always_inline int isALPHA(enum AVPixelFormat pix_fmt)
 {
     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
diff --git a/libswscale/swscale_unscaled.c b/libswscale/swscale_unscaled.c
index 6480070cbf..8fd1c51078 100644
--- a/libswscale/swscale_unscaled.c
+++ b/libswscale/swscale_unscaled.c
@@ -1467,6 +1467,46 @@  static int yvu9ToYv12Wrapper(SwsContext *c, const uint8_t *src[],
     return srcSliceH;
 }
 
+static int uint_y_to_float_y_wrapper(SwsContext *c, const uint8_t *src[],
+                                     int srcStride[], int srcSliceY,
+                                     int srcSliceH, uint8_t *dst[], int dstStride[])
+{
+    int y, x;
+    ptrdiff_t dstStrideFloat = dstStride[0] >> 2;
+    const uint8_t *srcPtr = src[0];
+    float *dstPtr = (float *)(dst[0] + dstStride[0] * srcSliceY);
+
+    for (y = 0; y < srcSliceH; ++y){
+        for (x = 0; x < c->srcW; ++x){
+            dstPtr[x] = c->uint2float_lut[srcPtr[x]];
+        }
+        srcPtr += srcStride[0];
+        dstPtr += dstStrideFloat;
+    }
+
+    return srcSliceH;
+}
+
+static int float_y_to_uint_y_wrapper(SwsContext *c, const uint8_t* src[],
+                                     int srcStride[], int srcSliceY,
+                                     int srcSliceH, uint8_t* dst[], int dstStride[])
+{
+    int y, x;
+    ptrdiff_t srcStrideFloat = srcStride[0] >> 2;
+    const float *srcPtr = (const float *)src[0];
+    uint8_t *dstPtr = dst[0] + dstStride[0] * srcSliceY;
+
+    for (y = 0; y < srcSliceH; ++y){
+        for (x = 0; x < c->srcW; ++x){
+            dstPtr[x] = lrintf(255.0f * FFMIN(FFMAX(srcPtr[x], 0.0f), 1.0f));
+        }
+        srcPtr += srcStrideFloat;
+        dstPtr += dstStride[0];
+    }
+
+    return srcSliceH;
+}
+
 /* unscaled copy like stuff (assumes nearly identical formats) */
 static int packedCopyWrapper(SwsContext *c, const uint8_t *src[],
                              int srcStride[], int srcSliceY, int srcSliceH,
@@ -1899,6 +1939,16 @@  void ff_get_unscaled_swscale(SwsContext *c)
             c->swscale = yuv422pToUyvyWrapper;
     }
 
+    /* uint Y to float Y */
+    if (srcFormat == AV_PIX_FMT_GRAY8 && dstFormat == AV_PIX_FMT_GRAYF32){
+        c->swscale = uint_y_to_float_y_wrapper;
+    }
+
+    /* float Y to uint Y */
+    if (srcFormat == AV_PIX_FMT_GRAYF32 && dstFormat == AV_PIX_FMT_GRAY8){
+        c->swscale = float_y_to_uint_y_wrapper;
+    }
+
     /* LQ converters if -sws 0 or -sws 4*/
     if (c->flags&(SWS_FAST_BILINEAR|SWS_POINT)) {
         /* yv12_to_yuy2 */
@@ -1925,13 +1975,13 @@  void ff_get_unscaled_swscale(SwsContext *c)
     if ( srcFormat == dstFormat ||
         (srcFormat == AV_PIX_FMT_YUVA420P && dstFormat == AV_PIX_FMT_YUV420P) ||
         (srcFormat == AV_PIX_FMT_YUV420P && dstFormat == AV_PIX_FMT_YUVA420P) ||
-        (isPlanarYUV(srcFormat) && isPlanarGray(dstFormat)) ||
+        (isFloat(srcFormat) == isFloat(dstFormat)) && ((isPlanarYUV(srcFormat) && isPlanarGray(dstFormat)) ||
         (isPlanarYUV(dstFormat) && isPlanarGray(srcFormat)) ||
         (isPlanarGray(dstFormat) && isPlanarGray(srcFormat)) ||
         (isPlanarYUV(srcFormat) && isPlanarYUV(dstFormat) &&
          c->chrDstHSubSample == c->chrSrcHSubSample &&
          c->chrDstVSubSample == c->chrSrcVSubSample &&
-         !isSemiPlanarYUV(srcFormat) && !isSemiPlanarYUV(dstFormat)))
+         !isSemiPlanarYUV(srcFormat) && !isSemiPlanarYUV(dstFormat))))
     {
         if (isPacked(c->srcFormat))
             c->swscale = packedCopyWrapper;
diff --git a/libswscale/utils.c b/libswscale/utils.c
index 61b47182f8..5e56371180 100644
--- a/libswscale/utils.c
+++ b/libswscale/utils.c
@@ -258,6 +258,8 @@  static const FormatEntry format_entries[AV_PIX_FMT_NB] = {
     [AV_PIX_FMT_P010BE]      = { 1, 1 },
     [AV_PIX_FMT_P016LE]      = { 1, 1 },
     [AV_PIX_FMT_P016BE]      = { 1, 1 },
+    [AV_PIX_FMT_GRAYF32LE]   = { 1, 1 },
+    [AV_PIX_FMT_GRAYF32BE]   = { 1, 1 },
 };
 
 int sws_isSupportedInput(enum AVPixelFormat pix_fmt)
@@ -1173,6 +1175,7 @@  av_cold int sws_init_context(SwsContext *c, SwsFilter *srcFilter,
     const AVPixFmtDescriptor *desc_dst;
     int ret = 0;
     enum AVPixelFormat tmpFmt;
+    static const float float_mult = 1.0f / 255.0f;
 
     cpu_flags = av_get_cpu_flags();
     flags     = c->flags;
@@ -1537,6 +1540,19 @@  av_cold int sws_init_context(SwsContext *c, SwsFilter *srcFilter,
         }
     }
 
+    if (unscaled && c->srcBpc == 8 && dstFormat == AV_PIX_FMT_GRAYF32){
+        for (i = 0; i < 256; ++i){
+            c->uint2float_lut[i] = (float)i * float_mult;
+        }
+    }
+
+    // float will be converted to uint16_t
+    if ((srcFormat == AV_PIX_FMT_GRAYF32BE || srcFormat == AV_PIX_FMT_GRAYF32LE) &&
+        (!unscaled || unscaled && dstFormat != srcFormat && (srcFormat != AV_PIX_FMT_GRAYF32 ||
+        dstFormat != AV_PIX_FMT_GRAY8))){
+        c->srcBpc = 16;
+    }
+
     if (CONFIG_SWSCALE_ALPHA && isALPHA(srcFormat) && !isALPHA(dstFormat)) {
         enum AVPixelFormat tmpFormat = alphaless_fmt(srcFormat);
 
@@ -1793,7 +1809,9 @@  av_cold int sws_init_context(SwsContext *c, SwsFilter *srcFilter,
 
     /* unscaled special cases */
     if (unscaled && !usesHFilter && !usesVFilter &&
-        (c->srcRange == c->dstRange || isAnyRGB(dstFormat))) {
+        (c->srcRange == c->dstRange || isAnyRGB(dstFormat) ||
+         srcFormat == AV_PIX_FMT_GRAYF32 && dstFormat == AV_PIX_FMT_GRAY8 ||
+         srcFormat == AV_PIX_FMT_GRAY8 && dstFormat == AV_PIX_FMT_GRAYF32)) {
         ff_get_unscaled_swscale(c);
 
         if (c->swscale) {
diff --git a/libswscale/x86/swscale_template.c b/libswscale/x86/swscale_template.c
index b8bdcd4d03..7c30470679 100644
--- a/libswscale/x86/swscale_template.c
+++ b/libswscale/x86/swscale_template.c
@@ -1500,7 +1500,8 @@  static av_cold void RENAME(sws_init_swscale)(SwsContext *c)
 
     c->use_mmx_vfilter= 0;
     if (!is16BPS(dstFormat) && !isNBPS(dstFormat) && dstFormat != AV_PIX_FMT_NV12
-        && dstFormat != AV_PIX_FMT_NV21 && !(c->flags & SWS_BITEXACT)) {
+        && dstFormat != AV_PIX_FMT_NV21 && dstFormat != AV_PIX_FMT_GRAYF32BE && dstFormat != AV_PIX_FMT_GRAYF32LE
+        && !(c->flags & SWS_BITEXACT)) {
             if (c->flags & SWS_ACCURATE_RND) {
                 if (!(c->flags & SWS_FULL_CHR_H_INT)) {
                     switch (c->dstFormat) {
diff --git a/tests/ref/fate/filter-pixdesc-grayf32be b/tests/ref/fate/filter-pixdesc-grayf32be
new file mode 100644
index 0000000000..423bbfbebc
--- /dev/null
+++ b/tests/ref/fate/filter-pixdesc-grayf32be
@@ -0,0 +1 @@ 
+pixdesc-grayf32be   381c8d0f19d286809b91cd6e6c0048ab
diff --git a/tests/ref/fate/filter-pixdesc-grayf32le b/tests/ref/fate/filter-pixdesc-grayf32le
new file mode 100644
index 0000000000..a76e0a995e
--- /dev/null
+++ b/tests/ref/fate/filter-pixdesc-grayf32le
@@ -0,0 +1 @@ 
+pixdesc-grayf32le   381c8d0f19d286809b91cd6e6c0048ab
diff --git a/tests/ref/fate/filter-pixfmts-copy b/tests/ref/fate/filter-pixfmts-copy
index 013b33f1c0..5385036a82 100644
--- a/tests/ref/fate/filter-pixfmts-copy
+++ b/tests/ref/fate/filter-pixfmts-copy
@@ -47,6 +47,8 @@  gray16be            08d997a3faa25a3db9d6be272d282eef
 gray16le            df65eb804360795e3e38a2701fa9641a
 gray9be             6382a14594a8b68f0ec7de25531f9334
 gray9le             4eb1dda58706436e3b69aef29b0089db
+grayf32be           f3bf178835f8146aa09d1da94bba4d8a
+grayf32le           fb6ea85bfbc8cd21c51fc0e110197294
 monob               8b04f859fee6a0be856be184acd7a0b5
 monow               54d16d2c01abfd72ecdb5e51e283937c
 nv12                8e24feb2c544dc26a20047a71e4c27aa
diff --git a/tests/ref/fate/filter-pixfmts-crop b/tests/ref/fate/filter-pixfmts-crop
index 750ea27404..ae48c2bf42 100644
--- a/tests/ref/fate/filter-pixfmts-crop
+++ b/tests/ref/fate/filter-pixfmts-crop
@@ -47,6 +47,8 @@  gray16be            38f599da990224de86e3dc7a543121a9
 gray16le            9ff7c866bd98def4e6c91542c1c45f80
 gray9be             8ffcb18d699480f55414bfc21ab33321
 gray9le             4d1932d4968a248584f5e39c25f1dd43
+grayf32be           cf40ec06a8abe54852b7f85a00549eec
+grayf32le           b672526c9da9c8959ab881f242f6890a
 nv12                92cda427f794374731ec0321ee00caac
 nv21                1bcfc197f4fb95de85ba58182d8d2f69
 p010be              8b2de2eb6b099bbf355bfc55a0694ddc
diff --git a/tests/ref/fate/filter-pixfmts-field b/tests/ref/fate/filter-pixfmts-field
index 4fdc214781..857ded1c41 100644
--- a/tests/ref/fate/filter-pixfmts-field
+++ b/tests/ref/fate/filter-pixfmts-field
@@ -47,6 +47,8 @@  gray16be            e1700e056de9917744a7ff4ab2ca63fd
 gray16le            338de7ac5f7d36d5ad5ac2c8d5bbea68
 gray9be             25e50940fa300a8f09edfb6eba4fd250
 gray9le             1146cfc1b92bfd07ed238e65ffcd134f
+grayf32be           72fbfa47b2863658a8a80d588f23b3e7
+grayf32le           6b856bdbf2a2bfcd2bc7d50f109daaf0
 monob               2129cc72a484d7e10a44de9117aa9f80
 monow               03d783611d265cae78293f88ea126ea1
 nv12                16f7a46708ef25ebd0b72e47920cc11e
diff --git a/tests/ref/fate/filter-pixfmts-fieldorder b/tests/ref/fate/filter-pixfmts-fieldorder
index 7fc158b0af..fc003457fc 100644
--- a/tests/ref/fate/filter-pixfmts-fieldorder
+++ b/tests/ref/fate/filter-pixfmts-fieldorder
@@ -47,6 +47,8 @@  gray16be            293a36548ce16543494790f8f7f76a05
 gray16le            84f83f5fcbb5d458efb8395a50a3797e
 gray9be             ec877f5bcf0ea275a6f36c12cc9adf11
 gray9le             fba944fde7923d5089f4f52d12988b9e
+grayf32be           1aa7960131f880c54fe3c77f13448674
+grayf32le           4029ac9d197f255794c1b9e416520fc7
 rgb0                2e3d8c91c7a83d451593dfd06607ff39
 rgb24               b82577f8215d3dc2681be60f1da247af
 rgb444be            1c3afc3a0c53c51139c76504f59bb1f4
diff --git a/tests/ref/fate/filter-pixfmts-hflip b/tests/ref/fate/filter-pixfmts-hflip
index 70a43d9959..e97c185f6e 100644
--- a/tests/ref/fate/filter-pixfmts-hflip
+++ b/tests/ref/fate/filter-pixfmts-hflip
@@ -47,6 +47,8 @@  gray16be            cf7294d9aa23e1b838692ec01ade587b
 gray16le            d91ce41e304419bcf32ac792f01bd64f
 gray9be             ac8d260669479ae720a5b6d4d8639e34
 gray9le             424fc581947bc8c357c9ec5e3c1c04d1
+grayf32be           a69add7bbf892a71fe81b3b75982dbe2
+grayf32le           4563e176a35dc8a8a07e0829fad5eb88
 nv12                801e58f1be5fd0b5bc4bf007c604b0b4
 nv21                9f10dfff8963dc327d3395af21f0554f
 p010be              744b13e44d39e1ff7588983fa03e0101
diff --git a/tests/ref/fate/filter-pixfmts-il b/tests/ref/fate/filter-pixfmts-il
index ba06851e24..a006fc19a3 100644
--- a/tests/ref/fate/filter-pixfmts-il
+++ b/tests/ref/fate/filter-pixfmts-il
@@ -47,6 +47,8 @@  gray16be            92c3b09f371b610cc1b6a9776034f4d0
 gray16le            1db278d23a554e01910cedacc6c02521
 gray9be             ed7db5bb2ddc09bc26068c8b858db204
 gray9le             2ec9188f0dcfefef76a09f371d7beb8e
+grayf32be           f36197c9e2ef5c50a995e980c1a37203
+grayf32le           8bf3d295c3ffd53da0e06d0702e7c1ca
 monob               faba75df28033ba7ce3d82ff2a99ee68
 monow               6e9cfb8d3a344c5f0c3e1d5e1297e580
 nv12                3c3ba9b1b4c4dfff09c26f71b51dd146
diff --git a/tests/ref/fate/filter-pixfmts-null b/tests/ref/fate/filter-pixfmts-null
index 013b33f1c0..5385036a82 100644
--- a/tests/ref/fate/filter-pixfmts-null
+++ b/tests/ref/fate/filter-pixfmts-null
@@ -47,6 +47,8 @@  gray16be            08d997a3faa25a3db9d6be272d282eef
 gray16le            df65eb804360795e3e38a2701fa9641a
 gray9be             6382a14594a8b68f0ec7de25531f9334
 gray9le             4eb1dda58706436e3b69aef29b0089db
+grayf32be           f3bf178835f8146aa09d1da94bba4d8a
+grayf32le           fb6ea85bfbc8cd21c51fc0e110197294
 monob               8b04f859fee6a0be856be184acd7a0b5
 monow               54d16d2c01abfd72ecdb5e51e283937c
 nv12                8e24feb2c544dc26a20047a71e4c27aa
diff --git a/tests/ref/fate/filter-pixfmts-scale b/tests/ref/fate/filter-pixfmts-scale
index 559355be49..05879ee3c7 100644
--- a/tests/ref/fate/filter-pixfmts-scale
+++ b/tests/ref/fate/filter-pixfmts-scale
@@ -47,6 +47,8 @@  gray16be            32891cb0928b1119d8d43a6e1bef0e2b
 gray16le            f96cfb5652b090dad52615930f0ce65f
 gray9be             779dec0c6c2df008128b91622a20daf8
 gray9le             fa87a96ca275f82260358635f838b514
+grayf32be           5e4c715519f53c15f1345df90481e5f5
+grayf32le           2ff1b84023e820307b1ba7a9550115bc
 monob               f01cb0b623357387827902d9d0963435
 monow               35c68b86c226d6990b2dcb573a05ff6b
 nv12                b118d24a3653fe66e5d9e079033aef79
diff --git a/tests/ref/fate/filter-pixfmts-transpose b/tests/ref/fate/filter-pixfmts-transpose
index 78218cda4e..44644099c6 100644
--- a/tests/ref/fate/filter-pixfmts-transpose
+++ b/tests/ref/fate/filter-pixfmts-transpose
@@ -47,6 +47,8 @@  gray16be            4aef307021a91b1de67f1d4381a39132
 gray16le            76f2afe156edca7ae05cfa4e5867126e
 gray9be             2c425fa532c940d226822da8b3592310
 gray9le             bcc575942910b3c72eaa72e8794f3acd
+grayf32be           823288e1ec497bb1f22c070e502e5272
+grayf32le           6e9ec0e1cac3617f3041e681afd2c575
 nv12                1965e3826144686748f2f6b516fca5ba
 nv21                292adaf5271c5c8516b71640458c01f4
 p010be              ad0de2cc9bff81688b182a870fcf7000
diff --git a/tests/ref/fate/filter-pixfmts-vflip b/tests/ref/fate/filter-pixfmts-vflip
index 3cb99e7d8d..51628f14ce 100644
--- a/tests/ref/fate/filter-pixfmts-vflip
+++ b/tests/ref/fate/filter-pixfmts-vflip
@@ -47,6 +47,8 @@  gray16be            29f24ba7cb0fc4fd2ae78963d008f6e6
 gray16le            a37e9c4ea76e8eeddc2af8f600ba2c10
 gray9be             dda11d4ffd62b414012ffc4667fb4971
 gray9le             159bf6482d217b2b8276eb2216cd7a09
+grayf32be           c1ba5943a0d24d70e6a280f37e4f4593
+grayf32le           8e6c048a5b3b8b26d3a5ddfce255f3f6
 monob               7810c4857822ccfc844d78f5e803269a
 monow               90a947bfcd5f2261e83b577f48ec57b1
 nv12                261ebe585ae2aa4e70d39a10c1679294
-- 
2.14.1