diff mbox series

[FFmpeg-devel] swscale/input: clamp rgbf32 values between 0, 1 before scaling

Message ID 20211107055221.99121-1-mindmark@gmail.com
State New
Headers show
Series [FFmpeg-devel] swscale/input: clamp rgbf32 values between 0, 1 before scaling
Related show

Checks

Context Check Description
andriy/make_x86 success Make finished
andriy/make_fate_x86 success Make fate finished
andriy/make_ppc success Make finished
andriy/make_fate_ppc fail Make fate failed
andriy/make_x86 success Make finished
andriy/make_fate_x86 success Make fate finished

Commit Message

Mark Reid Nov. 7, 2021, 5:52 a.m. UTC
From: Mark Reid <mindmark@gmail.com>

if the float pixel * 65535.0f > 2147483647.0f
lrintf may overfow and return negative values, depending on implementation.
nan and +/-inf values may also be implementation defined

clamp the values between 0,1 before scaling, so lrintf
always works.

values <=0.0f, -inf, nan = 0.0f
values >=1.0f, +inf      = 1.0f
---
 libswscale/input.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

--
2.29.2

Comments

Mark Reid Nov. 7, 2021, 9:02 a.m. UTC | #1
On Sat, Nov 6, 2021 at 10:52 PM <mindmark@gmail.com> wrote:

> From: Mark Reid <mindmark@gmail.com>
>
> if the float pixel * 65535.0f > 2147483647.0f
> lrintf may overfow and return negative values, depending on implementation.
> nan and +/-inf values may also be implementation defined
>
> clamp the values between 0,1 before scaling, so lrintf
> always works.
>
> values <=0.0f, -inf, nan = 0.0f
> values >=1.0f, +inf      = 1.0f
> ---
>  libswscale/input.c | 12 +++++++-----
>  1 file changed, 7 insertions(+), 5 deletions(-)
>
> diff --git a/libswscale/input.c b/libswscale/input.c
> index 336f957c8c..ea50c9de5c 100644
> --- a/libswscale/input.c
> +++ b/libswscale/input.c
> @@ -964,7 +964,7 @@ static av_always_inline void
> planar_rgb16_to_uv(uint8_t *_dstU, uint8_t *_dstV,
>  }
>  #undef rdpx
>
> -#define rdpx(src) (is_be ? av_int2float(AV_RB32(src)):
> av_int2float(AV_RL32(src)))
> +#define rdpx(src) (FFMIN(FFMAX(is_be ? av_int2float(AV_RB32(src)):
> av_int2float(AV_RL32(src)), 0.0f), 1.0f))
>
>  static av_always_inline void planar_rgbf32_to_a(uint8_t *_dst, const
> uint8_t *_src[4], int width, int is_be, int32_t *rgb2yuv)
>  {
> @@ -1013,17 +1013,16 @@ static av_always_inline void
> planar_rgbf32_to_y(uint8_t *_dst, const uint8_t *_s
>      }
>  }
>
> -#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;
> +    int is_be = 0;
>
>      for (i = 0; i < width; ++i){
> -        dst[i] = av_clip_uint16(lrintf(65535.0f * src[i]));
> +        dst[i] = av_clip_uint16(lrintf(65535.0f * rdpx(src + i)));
>      }
>  }
>
> @@ -1033,12 +1032,15 @@ static av_always_inline void
> grayf32ToY16_bswap_c(uint8_t *_dst, const uint8_t *
>      int i;
>      const uint32_t *src = (const uint32_t *)_src;
>      uint16_t *dst    = (uint16_t *)_dst;
> +    int is_be = 1;
>
>      for (i = 0; i < width; ++i){
> -        dst[i] = av_clip_uint16(lrintf(65535.0f *
> av_int2float(av_bswap32(src[i]))));
> +        dst[i] = av_clip_uint16(lrintf(65535.0f * rdpx(src+ i)));
>      }
>  }
>
> +#undef rdpx
> +
>  #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)                          \
> --
> 2.29.2
>
>
seem to not work on PowerPC, I see what's going on, I'll send a new patch
diff mbox series

Patch

diff --git a/libswscale/input.c b/libswscale/input.c
index 336f957c8c..ea50c9de5c 100644
--- a/libswscale/input.c
+++ b/libswscale/input.c
@@ -964,7 +964,7 @@  static av_always_inline void planar_rgb16_to_uv(uint8_t *_dstU, uint8_t *_dstV,
 }
 #undef rdpx

-#define rdpx(src) (is_be ? av_int2float(AV_RB32(src)): av_int2float(AV_RL32(src)))
+#define rdpx(src) (FFMIN(FFMAX(is_be ? av_int2float(AV_RB32(src)): av_int2float(AV_RL32(src)), 0.0f), 1.0f))

 static av_always_inline void planar_rgbf32_to_a(uint8_t *_dst, const uint8_t *_src[4], int width, int is_be, int32_t *rgb2yuv)
 {
@@ -1013,17 +1013,16 @@  static av_always_inline void planar_rgbf32_to_y(uint8_t *_dst, const uint8_t *_s
     }
 }

-#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;
+    int is_be = 0;

     for (i = 0; i < width; ++i){
-        dst[i] = av_clip_uint16(lrintf(65535.0f * src[i]));
+        dst[i] = av_clip_uint16(lrintf(65535.0f * rdpx(src + i)));
     }
 }

@@ -1033,12 +1032,15 @@  static av_always_inline void grayf32ToY16_bswap_c(uint8_t *_dst, const uint8_t *
     int i;
     const uint32_t *src = (const uint32_t *)_src;
     uint16_t *dst    = (uint16_t *)_dst;
+    int is_be = 1;

     for (i = 0; i < width; ++i){
-        dst[i] = av_clip_uint16(lrintf(65535.0f * av_int2float(av_bswap32(src[i]))));
+        dst[i] = av_clip_uint16(lrintf(65535.0f * rdpx(src+ i)));
     }
 }

+#undef rdpx
+
 #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)                          \