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

Michael Niedermayer michael at niedermayer.cc
Wed Aug 8 01:43:51 EEST 2018


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 at 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
>  
>  #define LIBAVUTIL_VERSION_INT   AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
> diff --git a/tests/ref/fate/sws-pixdesc-query b/tests/ref/fate/sws-pixdesc-query
> index 8071ec484d..451c7d83b9 100644
> --- a/tests/ref/fate/sws-pixdesc-query
> +++ b/tests/ref/fate/sws-pixdesc-query
> @@ -126,6 +126,7 @@ isBE:
>    gray14be
>    gray16be
>    gray9be
> +  grayf32be
>    nv20be
>    p010be
>    p016be
> @@ -412,6 +413,8 @@ Gray:
>    gray16le
>    gray9be
>    gray9le
> +  grayf32be
> +  grayf32le
>    ya16be
>    ya16le
>    ya8
> -- 
> 2.14.1
> 

>  libswscale/input.c                       |   38 +++++++++++++++++++
>  libswscale/output.c                      |   60 +++++++++++++++++++++++++++++++
>  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, 203 insertions(+), 4 deletions(-)
> 19652102078d9ddbf157bd51332e3bfd1971481e  0005-libswscale-Adds-conversions-from-to-float-gray-forma.patch
> From 35f97f77465bec4344ac7d5a6742388d9c1470cc Mon Sep 17 00:00:00 2001
> From: Sergey Lavrushkin <dualfal at 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                      | 60 ++++++++++++++++++++++++++++++++
>  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, 203 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..bd2000470a 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] = (uint16_t)(65535.0f * FFMIN(FFMAX(src[i], 0.0f), 1.0f) + 0.5f);
> +    }
> +}

we generally use lrintf() to convert float to integers
casts may requires change to rounding settings of the FPU on some platforms


> +
> +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 float *src = (const float *)_src;
> +    uint16_t *dst    = (uint16_t *)_dst;
> +
> +    for (i = 0; i < width; ++i){
> +        dst[i] = (uint16_t)(65535.0f * FFMIN(FFMAX(av_bswap32(src[i]), 0.0f), 1.0f) + 0.5f);
> +    }
> +}

Was this tested ?



> +
>  #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;

please put preprocessor stuff with the "#" at the first column. There was
some compatibility issue if this is not done


>      }
>      if (c->needAlpha) {
>          if (is16BPS(srcFormat) || isNBPS(srcFormat)) {
> diff --git a/libswscale/output.c b/libswscale/output.c
> index 0af2fffea4..f388c74d1c 100644
> --- a/libswscale/output.c
> +++ b/libswscale/output.c
> @@ -208,6 +208,60 @@ 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, int big_endian)
> +{
> +    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
> +yuv2planeX_float_c_template(const int16_t *filter, int filterSize, const int32_t **src,
> +                            float *dest, int dstW, int big_endian)
> +{
> +    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;
> +    }
> +}
> +
> +#define yuv2plane1_float(is_be, BE_LE) \
> +static void yuv2plane1_float ## BE_LE ## _c(const int16_t *src, uint8_t *dest, int dstW, \
> +                                            const uint8_t *dither, int offset) \
> +{ \
> +    yuv2plane1_float_c_template((const int32_t *)src, (float *)dest, dstW, is_be); \
> +}
> +
> +#define yuv2planeX_float(is_be, 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) \
> +{ \
> +    yuv2planeX_float_c_template(filter, filterSize, (const int32_t **)src, (float *)dest, dstW, is_be); \
> +}
> +
> +yuv2plane1_float(0, LE)
> +yuv2plane1_float(1, BE)
> +yuv2planeX_float(0, LE)
> +yuv2planeX_float(1, BE)
> +
>  #undef output_pixel
>  
>  #define output_pixel(pos, val) \
> @@ -2303,6 +2357,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..f2242fe185 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] = (uint8_t)(255.0f * FFMIN(FFMAX(srcPtr[x], 0.0f), 1.0f) + 0.5f);
> +        }
> +        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..f10638b045 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 },

please keep teh = vertically aligned


[...]


-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

You can kill me, but you cannot change the truth.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: not available
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20180808/489d5935/attachment.sig>


More information about the ffmpeg-devel mailing list