[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