The rationale for this function is reflected in the documentation for it, and is copied here:
Clip a double value into the long long amin-amax range. This function is needed because conversion of floating point to integers when it does not fit in the integer's representation does not necessarily saturate correctly (usually converted to a cvttsd2si on x86) which saturates numbers > INT64_MAX to INT64_MIN. The standard marks such conversions as undefined behavior, allowing this sort of mathematically bogus conversions. This provides a safe alternative that is slower obviously but assures safety and better mathematical behavior. API: @param a value to clip @param amin minimum value of the clip range @param amax maximum value of the clip range @return clipped value Note that a priori if one can guarantee from the calling side that the double is in range, it is safe to simply do an explicit/implicit cast, and that will be far faster. However, otherwise this function should be used. avutil minor version is bumped. Reviewed-by: Ronald S. Bultje <rsbul...@gmail.com> Signed-off-by: Ganesh Ajjanagadde <gajjanaga...@gmail.com> --- libavutil/common.h | 30 ++++++++++++++++++++++++++++++ libavutil/version.h | 2 +- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/libavutil/common.h b/libavutil/common.h index 6f0f582..f4687ab 100644 --- a/libavutil/common.h +++ b/libavutil/common.h @@ -298,6 +298,33 @@ static av_always_inline av_const double av_clipd_c(double a, double amin, double else return a; } +/** + * Clip and convert a double value into the long long amin-amax range. + * This function is needed because conversion of floating point to integers when + * it does not fit in the integer's representation does not necessarily saturate + * correctly (usually converted to a cvttsd2si on x86) which saturates numbers + * > INT64_MAX to INT64_MIN. The standard marks such conversions as undefined + * behavior, allowing this sort of mathematically bogus conversions. This provides + * a safe alternative that is slower obviously but assures safety and better + * mathematical behavior. + * @param a value to clip + * @param amin minimum value of the clip range + * @param amax maximum value of the clip range + * @return clipped value + */ +static av_always_inline av_const int64_t av_rint64_clip_c(double a, int64_t amin, int64_t amax) +{ +#if defined(HAVE_AV_CONFIG_H) && defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2 + if (amin > amax) abort(); +#endif + // INT64_MAX+1,INT64_MIN are exactly representable as IEEE doubles + if (a >= 9223372036854775808.0 || llrint(a) >= amax) + return amax; + if (a <= -9223372036854775808.0 || llrint(a) <= amin) + return amin; + return llrint(a); +} + /** Compute ceil(log2(x)). * @param x value used to compute ceil(log2(x)) * @return computed ceiling of log2(x) @@ -511,6 +538,9 @@ static av_always_inline av_const int av_popcount64_c(uint64_t x) #ifndef av_clipd # define av_clipd av_clipd_c #endif +#ifndef av_rint64_clip +# define av_rint64_clip av_rint64_clip_c +#endif #ifndef av_popcount # define av_popcount av_popcount_c #endif diff --git a/libavutil/version.h b/libavutil/version.h index 909f9a6..bcad658 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -56,7 +56,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 55 -#define LIBAVUTIL_VERSION_MINOR 5 +#define LIBAVUTIL_VERSION_MINOR 6 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ -- 2.6.2 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel