From 0703856b53e80159d666e289762406989f08ccfa Mon Sep 17 00:00:00 2001 From: kwiberg Date: Mon, 12 Jun 2017 11:40:47 -0700 Subject: [PATCH] Add SafeClamp(), which accepts args of different types Specifically, just like SafeMin() and SafeMax() it handles all combinations of integer and all combinations of floating-point arguments by picking a result type that is guaranteed to be able to hold the result. This CL also replaces a bunch of std::min + std:max call pairs with calls to SafeClamp()---the ones that could easily be found by grep because "min" and "max" were on the same line. :-) BUG=webrtc:7459 Review-Url: https://codereview.webrtc.org/2808513003 Cr-Commit-Position: refs/heads/master@{#18542} --- webrtc/base/safe_minmax.h | 153 ++++++++++++- webrtc/base/safe_minmax_unittest.cc | 212 +++++++++++++++++- .../codecs/opus/audio_encoder_opus.cc | 5 +- .../aec3/adaptive_fir_filter_unittest.cc | 6 +- .../aec3/echo_remover_metrics.cc | 3 +- .../audio_processing/aec3/erle_estimator.cc | 4 +- .../aec3/main_filter_update_gain_unittest.cc | 11 +- .../shadow_filter_update_gain_unittest.cc | 8 +- .../audio_processing/aec3/subtractor.cc | 6 +- .../aec3/suppression_filter.cc | 5 +- .../agc/agc_manager_direct.cc | 14 +- .../audio_processing_unittest.cc | 14 +- .../intelligibility_enhancer.cc | 29 +-- .../intelligibility/intelligibility_utils.cc | 8 +- .../aimd_rate_control.cc | 6 +- .../overuse_detector.cc | 7 +- .../remote_estimator_proxy.cc | 10 +- .../test/bwe_test_framework.cc | 5 +- webrtc/modules/rtp_rtcp/source/rtp_sender.cc | 13 +- webrtc/p2p/base/port.cc | 3 +- webrtc/p2p/base/pseudotcp.cc | 10 +- webrtc/tools/agc/activity_metric.cc | 5 +- webrtc/voice_engine/channel_proxy.cc | 3 +- 23 files changed, 443 insertions(+), 97 deletions(-) diff --git a/webrtc/base/safe_minmax.h b/webrtc/base/safe_minmax.h index 16638efc61..5d6a7d077a 100644 --- a/webrtc/base/safe_minmax.h +++ b/webrtc/base/safe_minmax.h @@ -14,6 +14,8 @@ // rtc::SafeMin(x, y) // rtc::SafeMax(x, y) // +// (These are both constexpr.) +// // Accept two arguments of either any two integral or any two floating-point // types, and return the smaller and larger value, respectively, with no // truncation or wrap-around. If only one of the input types is statically @@ -21,14 +23,48 @@ // if either one would do, the result type is the smaller type. (One of these // two cases always applies.) // -// (The case with one floating-point and one integral type is not allowed, -// because the floating-point type will have greater range, but may not have -// sufficient precision to represent the integer value exactly.) +// * The case with one floating-point and one integral type is not allowed, +// because the floating-point type will have greater range, but may not +// have sufficient precision to represent the integer value exactly.) +// +// Clamp (a.k.a. constrain to a given interval) +// ============================================ +// +// rtc::SafeClamp(x, a, b) +// +// Accepts three arguments of any mix of integral types or any mix of +// floating-point types, and returns the value in the closed interval [a, b] +// that is closest to x (that is, if x < a it returns a; if x > b it returns b; +// and if a <= x <= b it returns x). As for SafeMin() and SafeMax(), there is +// no truncation or wrap-around. The result type +// +// 1. is statically guaranteed to be able to represent the result; +// +// 2. is no larger than the largest of the three argument types; and +// +// 3. has the same signedness as the type of the third argument, if this is +// possible without violating the First or Second Law. +// +// There is always at least one type that meets criteria 1 and 2. If more than +// one type meets these criteria equally well, the result type is one of the +// types that is smallest. Note that unlike SafeMin() and SafeMax(), +// SafeClamp() will sometimes pick a return type that isn't the type of any of +// its arguments. +// +// * In this context, a type A is smaller than a type B if it has a smaller +// range; that is, if A::max() - A::min() < B::max() - B::min(). For +// example, int8_t < int16_t == uint16_t < int32_t, and all integral types +// are smaller than all floating-point types.) +// +// * As for SafeMin and SafeMax, mixing integer and floating-point arguments +// is not allowed, because floating-point types have greater range than +// integer types, but do not have sufficient precision to represent the +// values of most integer types exactly. // // Requesting a specific return type // ================================= // -// Both functions allow callers to explicitly specify the return type as a +// All three functions allow callers to explicitly specify the return type as a // template parameter, overriding the default return type. E.g. // // rtc::SafeMin(x, y) // returns an int @@ -187,6 +223,115 @@ constexpr R2 SafeMax(T1 a, T2 b) { return safe_cmp::Gt(a, b) ? static_cast(a) : static_cast(b); } +namespace safe_minmax_impl { + +// Given three types T, L, and H, let ::type be a suitable return value for +// SafeClamp(T, L, H). See the docs at the top of this file for details. +template ::value, + bool int2 = IsIntlike::value, + bool int3 = IsIntlike::value> +struct ClampType { + static_assert(int1 == int2 && int1 == int3, + "You may not mix integral and floating-point arguments"); +}; + +// Specialization for when all three types are floating-point. +template +struct ClampType { + using type = typename std::common_type::type; +}; + +// Specialization for when all three types are integral. +template +struct ClampType { + private: + // Range of the return value. The return type must be able to represent this + // full range. + static constexpr auto r_min = + SafeMax(Limits::lowest, SafeMin(Limits::lowest, Limits::lowest)); + static constexpr auto r_max = + SafeMin(Limits::max, SafeMax(Limits::max, Limits::max)); + + // Is the given type an acceptable return type? (That is, can it represent + // all possible return values, and is it no larger than the largest of the + // input types?) + template + struct AcceptableType { + private: + static constexpr bool not_too_large = sizeof(A) <= sizeof(L) || + sizeof(A) <= sizeof(H) || + sizeof(A) <= sizeof(T); + static constexpr bool range_contained = + safe_cmp::Le(Limits::lowest, r_min) && + safe_cmp::Le(r_max, Limits::max); + + public: + static constexpr bool value = not_too_large && range_contained; + }; + + using best_signed_type = typename std::conditional< + AcceptableType::value, + int8_t, + typename std::conditional< + AcceptableType::value, + int16_t, + typename std::conditional::value, + int32_t, + int64_t>::type>::type>::type; + + using best_unsigned_type = typename std::conditional< + AcceptableType::value, + uint8_t, + typename std::conditional< + AcceptableType::value, + uint16_t, + typename std::conditional::value, + uint32_t, + uint64_t>::type>::type>::type; + + public: + // Pick the best type, preferring the same signedness as T but falling back + // to the other one if necessary. + using type = typename std::conditional< + std::is_signed::value, + typename std::conditional::value, + best_signed_type, + best_unsigned_type>::type, + typename std::conditional::value, + best_unsigned_type, + best_signed_type>::type>::type; + static_assert(AcceptableType::value, ""); +}; + +} // namespace safe_minmax_impl + +template < + typename R = safe_minmax_impl::DefaultType, + typename T = safe_minmax_impl::DefaultType, + typename L = safe_minmax_impl::DefaultType, + typename H = safe_minmax_impl::DefaultType, + typename R2 = typename safe_minmax_impl::TypeOr< + R, + typename safe_minmax_impl::ClampType< + typename safe_minmax_impl::UnderlyingType::type, + typename safe_minmax_impl::UnderlyingType::type, + typename safe_minmax_impl::UnderlyingType::type>::type>::type> +R2 SafeClamp(T x, L min, H max) { + static_assert(IsIntlike::value || std::is_floating_point::value, + "The first argument must be integral or floating-point"); + static_assert(IsIntlike::value || std::is_floating_point::value, + "The second argument must be integral or floating-point"); + static_assert(IsIntlike::value || std::is_floating_point::value, + "The third argument must be integral or floating-point"); + RTC_DCHECK_LE(min, max); + return safe_cmp::Le(x, min) + ? static_cast(min) + : safe_cmp::Ge(x, max) ? static_cast(max) : static_cast(x); +} + } // namespace rtc #endif // WEBRTC_BASE_SAFE_MINMAX_H_ diff --git a/webrtc/base/safe_minmax_unittest.cc b/webrtc/base/safe_minmax_unittest.cc index 519158b6ed..eb0fe809f7 100644 --- a/webrtc/base/safe_minmax_unittest.cc +++ b/webrtc/base/safe_minmax_unittest.cc @@ -18,8 +18,9 @@ namespace rtc { namespace { -// Functions that check that SafeMin() and SafeMax() return the specified type. -// The functions that end in "R" use an explicitly given return type. +// Functions that check that SafeMin(), SafeMax(), and SafeClamp() return the +// specified type. The functions that end in "R" use an explicitly given return +// type. template constexpr bool TypeCheckMinMax() { @@ -41,6 +42,21 @@ constexpr bool TypeCheckMaxR() { decltype(SafeMax(std::declval(), std::declval())), R>::value; } +template +constexpr bool TypeCheckClamp() { + return std::is_same(), std::declval(), + std::declval())), + R>::value; +} + +template +constexpr bool TypeCheckClampR() { + return std::is_same(std::declval(), + std::declval(), + std::declval())), + R>::value; +} + // clang-format off // SafeMin/SafeMax: Check that all combinations of signed/unsigned 8/64 bits @@ -62,6 +78,73 @@ static_assert(TypeCheckMinMax(), ""); static_assert(TypeCheckMinMax(), ""); static_assert(TypeCheckMinMax(), ""); +// SafeClamp: Check that all combinations of signed/unsigned 8/64 bits give the +// correct result type. +static_assert(TypeCheckClamp< int8_t, int8_t, int8_t, int8_t>(), ""); +static_assert(TypeCheckClamp< int8_t, int8_t, uint8_t, int8_t>(), ""); +static_assert(TypeCheckClamp< int8_t, int8_t, int64_t, int8_t>(), ""); +static_assert(TypeCheckClamp< int8_t, int8_t, uint64_t, int8_t>(), ""); +static_assert(TypeCheckClamp< int8_t, uint8_t, int8_t, int8_t>(), ""); +static_assert(TypeCheckClamp< int8_t, uint8_t, uint8_t, uint8_t>(), ""); +static_assert(TypeCheckClamp< int8_t, uint8_t, int64_t, int16_t>(), ""); +static_assert(TypeCheckClamp< int8_t, uint8_t, uint64_t, int16_t>(), ""); +static_assert(TypeCheckClamp< int8_t, int64_t, int8_t, int8_t>(), ""); +static_assert(TypeCheckClamp< int8_t, int64_t, uint8_t, int16_t>(), ""); +static_assert(TypeCheckClamp< int8_t, int64_t, int64_t, int64_t>(), ""); +static_assert(TypeCheckClamp< int8_t, int64_t, uint64_t, int64_t>(), ""); +static_assert(TypeCheckClamp< int8_t, uint64_t, int8_t, int8_t>(), ""); +static_assert(TypeCheckClamp< int8_t, uint64_t, uint8_t, int16_t>(), ""); +static_assert(TypeCheckClamp< int8_t, uint64_t, int64_t, int64_t>(), ""); +static_assert(TypeCheckClamp< int8_t, uint64_t, uint64_t, uint64_t>(), ""); +static_assert(TypeCheckClamp< uint8_t, int8_t, int8_t, int8_t>(), ""); +static_assert(TypeCheckClamp< uint8_t, int8_t, uint8_t, uint8_t>(), ""); +static_assert(TypeCheckClamp< uint8_t, int8_t, int64_t, int16_t>(), ""); +static_assert(TypeCheckClamp< uint8_t, int8_t, uint64_t, uint8_t>(), ""); +static_assert(TypeCheckClamp< uint8_t, uint8_t, int8_t, uint8_t>(), ""); +static_assert(TypeCheckClamp< uint8_t, uint8_t, uint8_t, uint8_t>(), ""); +static_assert(TypeCheckClamp< uint8_t, uint8_t, int64_t, uint8_t>(), ""); +static_assert(TypeCheckClamp< uint8_t, uint8_t, uint64_t, uint8_t>(), ""); +static_assert(TypeCheckClamp< uint8_t, int64_t, int8_t, int8_t>(), ""); +static_assert(TypeCheckClamp< uint8_t, int64_t, uint8_t, uint8_t>(), ""); +static_assert(TypeCheckClamp< uint8_t, int64_t, int64_t, int64_t>(), ""); +static_assert(TypeCheckClamp< uint8_t, int64_t, uint64_t, uint64_t>(), ""); +static_assert(TypeCheckClamp< uint8_t, uint64_t, int8_t, uint8_t>(), ""); +static_assert(TypeCheckClamp< uint8_t, uint64_t, uint8_t, uint8_t>(), ""); +static_assert(TypeCheckClamp< uint8_t, uint64_t, int64_t, uint64_t>(), ""); +static_assert(TypeCheckClamp< uint8_t, uint64_t, uint64_t, uint64_t>(), ""); +static_assert(TypeCheckClamp< int64_t, int8_t, int8_t, int8_t>(), ""); +static_assert(TypeCheckClamp< int64_t, int8_t, uint8_t, int16_t>(), ""); +static_assert(TypeCheckClamp< int64_t, int8_t, int64_t, int64_t>(), ""); +static_assert(TypeCheckClamp< int64_t, int8_t, uint64_t, int64_t>(), ""); +static_assert(TypeCheckClamp< int64_t, uint8_t, int8_t, int8_t>(), ""); +static_assert(TypeCheckClamp< int64_t, uint8_t, uint8_t, int16_t>(), ""); +static_assert(TypeCheckClamp< int64_t, uint8_t, int64_t, int64_t>(), ""); +static_assert(TypeCheckClamp< int64_t, uint8_t, uint64_t, int64_t>(), ""); +static_assert(TypeCheckClamp< int64_t, int64_t, int8_t, int64_t>(), ""); +static_assert(TypeCheckClamp< int64_t, int64_t, uint8_t, int64_t>(), ""); +static_assert(TypeCheckClamp< int64_t, int64_t, int64_t, int64_t>(), ""); +static_assert(TypeCheckClamp< int64_t, int64_t, uint64_t, int64_t>(), ""); +static_assert(TypeCheckClamp< int64_t, uint64_t, int8_t, int8_t>(), ""); +static_assert(TypeCheckClamp< int64_t, uint64_t, uint8_t, int16_t>(), ""); +static_assert(TypeCheckClamp< int64_t, uint64_t, int64_t, int64_t>(), ""); +static_assert(TypeCheckClamp< int64_t, uint64_t, uint64_t, uint64_t>(), ""); +static_assert(TypeCheckClamp(), ""); +static_assert(TypeCheckClamp(), ""); +static_assert(TypeCheckClamp(), ""); +static_assert(TypeCheckClamp(), ""); +static_assert(TypeCheckClamp(), ""); +static_assert(TypeCheckClamp(), ""); +static_assert(TypeCheckClamp(), ""); +static_assert(TypeCheckClamp(), ""); +static_assert(TypeCheckClamp(), ""); +static_assert(TypeCheckClamp(), ""); +static_assert(TypeCheckClamp(), ""); +static_assert(TypeCheckClamp(), ""); +static_assert(TypeCheckClamp(), ""); +static_assert(TypeCheckClamp(), ""); +static_assert(TypeCheckClamp(), ""); +static_assert(TypeCheckClamp(), ""); + enum DefaultE { kFoo = -17 }; enum UInt8E : uint8_t { kBar = 17 }; @@ -76,6 +159,35 @@ static_assert(TypeCheckMinMax< UInt8E, unsigned, uint8_t, unsigned>(), ""); static_assert(TypeCheckMinMax< UInt8E, DefaultE, int, int>(), ""); static_assert(TypeCheckMinMax< UInt8E, UInt8E, uint8_t, uint8_t>(), ""); +// SafeClamp: Check that we can use enum types. +static_assert(TypeCheckClamp(), ""); +static_assert(TypeCheckClamp(), ""); +static_assert(TypeCheckClamp(), ""); +static_assert(TypeCheckClamp(), ""); +static_assert(TypeCheckClamp(), ""); +static_assert(TypeCheckClamp(), ""); +static_assert(TypeCheckClamp(), ""); +static_assert(TypeCheckClamp(), ""); +static_assert(TypeCheckClamp(), ""); +static_assert(TypeCheckClamp(), ""); +static_assert(TypeCheckClamp(), ""); +static_assert(TypeCheckClamp(), ""); +static_assert(TypeCheckClamp(), ""); +static_assert(TypeCheckClamp(), ""); +static_assert(TypeCheckClamp(), ""); +static_assert(TypeCheckClamp(), ""); +static_assert(TypeCheckClamp(), ""); +static_assert(TypeCheckClamp(), ""); +static_assert(TypeCheckClamp< UInt8E, unsigned, unsigned, unsigned>(), ""); +static_assert(TypeCheckClamp< UInt8E, unsigned, DefaultE, unsigned>(), ""); +static_assert(TypeCheckClamp< UInt8E, unsigned, UInt8E, uint8_t>(), ""); +static_assert(TypeCheckClamp< UInt8E, DefaultE, unsigned, unsigned>(), ""); +static_assert(TypeCheckClamp< UInt8E, DefaultE, DefaultE, int>(), ""); +static_assert(TypeCheckClamp< UInt8E, DefaultE, UInt8E, uint8_t>(), ""); +static_assert(TypeCheckClamp< UInt8E, UInt8E, unsigned, uint8_t>(), ""); +static_assert(TypeCheckClamp< UInt8E, UInt8E, DefaultE, uint8_t>(), ""); +static_assert(TypeCheckClamp< UInt8E, UInt8E, UInt8E, uint8_t>(), ""); + using ld = long double; // SafeMin/SafeMax: Check that all floating-point combinations give the @@ -90,6 +202,36 @@ static_assert(TypeCheckMinMax< ld, float, ld, ld>(), ""); static_assert(TypeCheckMinMax< ld, double, ld, ld>(), ""); static_assert(TypeCheckMinMax< ld, ld, ld, ld>(), ""); +// SafeClamp: Check that all floating-point combinations give the correct +// result type. +static_assert(TypeCheckClamp< float, float, float, float>(), ""); +static_assert(TypeCheckClamp< float, float, double, double>(), ""); +static_assert(TypeCheckClamp< float, float, ld, ld>(), ""); +static_assert(TypeCheckClamp< float, double, float, double>(), ""); +static_assert(TypeCheckClamp< float, double, double, double>(), ""); +static_assert(TypeCheckClamp< float, double, ld, ld>(), ""); +static_assert(TypeCheckClamp< float, ld, float, ld>(), ""); +static_assert(TypeCheckClamp< float, ld, double, ld>(), ""); +static_assert(TypeCheckClamp< float, ld, ld, ld>(), ""); +static_assert(TypeCheckClamp(), ""); +static_assert(TypeCheckClamp(), ""); +static_assert(TypeCheckClamp(), ""); +static_assert(TypeCheckClamp(), ""); +static_assert(TypeCheckClamp(), ""); +static_assert(TypeCheckClamp(), ""); +static_assert(TypeCheckClamp(), ""); +static_assert(TypeCheckClamp(), ""); +static_assert(TypeCheckClamp(), ""); +static_assert(TypeCheckClamp< ld, float, float, ld>(), ""); +static_assert(TypeCheckClamp< ld, float, double, ld>(), ""); +static_assert(TypeCheckClamp< ld, float, ld, ld>(), ""); +static_assert(TypeCheckClamp< ld, double, float, ld>(), ""); +static_assert(TypeCheckClamp< ld, double, double, ld>(), ""); +static_assert(TypeCheckClamp< ld, double, ld, ld>(), ""); +static_assert(TypeCheckClamp< ld, ld, float, ld>(), ""); +static_assert(TypeCheckClamp< ld, ld, double, ld>(), ""); +static_assert(TypeCheckClamp< ld, ld, ld, ld>(), ""); + // clang-format on // SafeMin/SafeMax: Check some cases of explicitly specified return type. The @@ -103,12 +245,24 @@ static_assert(TypeCheckMinR(), ""); static_assert(TypeCheckMaxR(), ""); // static_assert(TypeCheckMaxR(), ""); +// SafeClamp: Check some cases of explicitly specified return type. The +// commented-out lines give compilation errors due to the requested return type +// being too small. +static_assert(TypeCheckClampR(), ""); +static_assert(TypeCheckClampR(), ""); +// static_assert(TypeCheckClampR(), ""); + template constexpr bool CheckMinMax(T1 a, T2 b, Tmin min, Tmax max) { return TypeCheckMinMax() && SafeMin(a, b) == min && SafeMax(a, b) == max; } +template +bool CheckClamp(T x, L min, H max, R clamped) { + return TypeCheckClamp() && SafeClamp(x, min, max) == clamped; +} + // SafeMin/SafeMax: Check a few values. static_assert(CheckMinMax(int8_t{1}, int8_t{-1}, int8_t{-1}, int8_t{1}), ""); static_assert(CheckMinMax(uint8_t{1}, int8_t{-1}, int8_t{-1}, uint8_t{1}), ""); @@ -127,22 +281,64 @@ static_assert(CheckMinMax(std::numeric_limits::min(), // static_assert(CheckMinMax(1.f, 2, 1.f, 2.f), ""); static_assert(CheckMinMax(1.f, 0.0, 0.0, 1.0), ""); +// SafeClamp: Check a few values. +TEST(SafeMinmaxTest, Clamp) { + EXPECT_TRUE(CheckClamp(int32_t{-1000000}, std::numeric_limits::min(), + std::numeric_limits::max(), + std::numeric_limits::min())); + EXPECT_TRUE(CheckClamp(uint32_t{1000000}, std::numeric_limits::min(), + std::numeric_limits::max(), + std::numeric_limits::max())); + EXPECT_TRUE(CheckClamp(3.f, -1.0, 1.f, 1.0)); + EXPECT_TRUE(CheckClamp(3.0, -1.f, 1.f, 1.0)); +} + } // namespace -// clang-format off - // These functions aren't used in the tests, but it's useful to look at the -// compiler output for them, and verify that (1) the same-signedness *Safe -// functions result in exactly the same code as their *Ref counterparts, and -// that (2) the mixed-signedness *Safe functions have just a few extra +// compiler output for them, and verify that (1) the same-signedness Test*Safe +// functions result in exactly the same code as their Test*Ref counterparts, +// and that (2) the mixed-signedness Test*Safe functions have just a few extra // arithmetic and logic instructions (but no extra control flow instructions). + +// clang-format off int32_t TestMinRef( int32_t a, int32_t b) { return std::min(a, b); } uint32_t TestMinRef( uint32_t a, uint32_t b) { return std::min(a, b); } int32_t TestMinSafe( int32_t a, int32_t b) { return SafeMin(a, b); } int32_t TestMinSafe( int32_t a, uint32_t b) { return SafeMin(a, b); } int32_t TestMinSafe(uint32_t a, int32_t b) { return SafeMin(a, b); } uint32_t TestMinSafe(uint32_t a, uint32_t b) { return SafeMin(a, b); } - // clang-format on +int32_t TestClampRef(int32_t x, int32_t a, int32_t b) { + return std::max(a, std::min(x, b)); +} +uint32_t TestClampRef(uint32_t x, uint32_t a, uint32_t b) { + return std::max(a, std::min(x, b)); +} +int32_t TestClampSafe(int32_t x, int32_t a, int32_t b) { + return SafeClamp(x, a, b); +} +int32_t TestClampSafe(int32_t x, int32_t a, uint32_t b) { + return SafeClamp(x, a, b); +} +int32_t TestClampSafe(int32_t x, uint32_t a, int32_t b) { + return SafeClamp(x, a, b); +} +uint32_t TestClampSafe(int32_t x, uint32_t a, uint32_t b) { + return SafeClamp(x, a, b); +} +int32_t TestClampSafe(uint32_t x, int32_t a, int32_t b) { + return SafeClamp(x, a, b); +} +uint32_t TestClampSafe(uint32_t x, int32_t a, uint32_t b) { + return SafeClamp(x, a, b); +} +int32_t TestClampSafe(uint32_t x, uint32_t a, int32_t b) { + return SafeClamp(x, a, b); +} +uint32_t TestClampSafe(uint32_t x, uint32_t a, uint32_t b) { + return SafeClamp(x, a, b); +} + } // namespace rtc diff --git a/webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.cc b/webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.cc index 64df6791db..be32aef152 100644 --- a/webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.cc +++ b/webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.cc @@ -20,6 +20,7 @@ #include "webrtc/base/numerics/exp_filter.h" #include "webrtc/base/protobuf_utils.h" #include "webrtc/base/safe_conversions.h" +#include "webrtc/base/safe_minmax.h" #include "webrtc/base/string_to_number.h" #include "webrtc/base/timeutils.h" #include "webrtc/common_types.h" @@ -690,8 +691,8 @@ void AudioEncoderOpus::SetProjectedPacketLossRate(float fraction) { } void AudioEncoderOpus::SetTargetBitrate(int bits_per_second) { - config_.bitrate_bps = rtc::Optional(std::max( - std::min(bits_per_second, kOpusMaxBitrateBps), kOpusMinBitrateBps)); + config_.bitrate_bps = rtc::Optional(rtc::SafeClamp( + bits_per_second, kOpusMinBitrateBps, kOpusMaxBitrateBps)); RTC_DCHECK(config_.IsOk()); RTC_CHECK_EQ(0, WebRtcOpus_SetBitRate(inst_, config_.GetBitrateBps())); const auto new_complexity = config_.GetNewComplexity(); diff --git a/webrtc/modules/audio_processing/aec3/adaptive_fir_filter_unittest.cc b/webrtc/modules/audio_processing/aec3/adaptive_fir_filter_unittest.cc index 4560958bfd..2402d91d0e 100644 --- a/webrtc/modules/audio_processing/aec3/adaptive_fir_filter_unittest.cc +++ b/webrtc/modules/audio_processing/aec3/adaptive_fir_filter_unittest.cc @@ -20,6 +20,7 @@ #endif #include "webrtc/base/arraysize.h" #include "webrtc/base/random.h" +#include "webrtc/base/safe_minmax.h" #include "webrtc/modules/audio_processing/aec3/aec3_fft.h" #include "webrtc/modules/audio_processing/aec3/aec_state.h" #include "webrtc/modules/audio_processing/aec3/cascaded_biquad_filter.h" @@ -350,9 +351,8 @@ TEST(AdaptiveFirFilter, FilterAndAdapt) { fft.Ifft(S, &s); std::transform(y.begin(), y.end(), s.begin() + kFftLengthBy2, e.begin(), [&](float a, float b) { return a - b * kScale; }); - std::for_each(e.begin(), e.end(), [](float& a) { - a = std::max(std::min(a, 32767.0f), -32768.0f); - }); + std::for_each(e.begin(), e.end(), + [](float& a) { a = rtc::SafeClamp(a, -32768.f, 32767.f); }); fft.ZeroPaddedFft(e, &E); gain.Compute(render_buffer, render_signal_analyzer, E, diff --git a/webrtc/modules/audio_processing/aec3/echo_remover_metrics.cc b/webrtc/modules/audio_processing/aec3/echo_remover_metrics.cc index ed1195996f..bc7e600cfa 100644 --- a/webrtc/modules/audio_processing/aec3/echo_remover_metrics.cc +++ b/webrtc/modules/audio_processing/aec3/echo_remover_metrics.cc @@ -14,6 +14,7 @@ #include #include +#include "webrtc/base/safe_minmax.h" #include "webrtc/system_wrappers/include/metrics.h" namespace webrtc { @@ -273,7 +274,7 @@ int TransformDbMetricForReporting(bool negate, if (negate) { new_value = -new_value; } - return static_cast(std::max(min_value, std::min(max_value, new_value))); + return static_cast(rtc::SafeClamp(new_value, min_value, max_value)); } } // namespace aec3 diff --git a/webrtc/modules/audio_processing/aec3/erle_estimator.cc b/webrtc/modules/audio_processing/aec3/erle_estimator.cc index c1394126a5..7faf22cf60 100644 --- a/webrtc/modules/audio_processing/aec3/erle_estimator.cc +++ b/webrtc/modules/audio_processing/aec3/erle_estimator.cc @@ -12,6 +12,8 @@ #include +#include "webrtc/base/safe_minmax.h" + namespace webrtc { namespace { @@ -48,7 +50,7 @@ void ErleEstimator::Update( if (new_erle > erle_[k]) { hold_counters_[k - 1] = 100; erle_[k] += 0.1f * (new_erle - erle_[k]); - erle_[k] = std::max(kMinErle, std::min(erle_[k], max_erle)); + erle_[k] = rtc::SafeClamp(erle_[k], kMinErle, max_erle); } } } diff --git a/webrtc/modules/audio_processing/aec3/main_filter_update_gain_unittest.cc b/webrtc/modules/audio_processing/aec3/main_filter_update_gain_unittest.cc index 2a4d4d65b9..581856b03f 100644 --- a/webrtc/modules/audio_processing/aec3/main_filter_update_gain_unittest.cc +++ b/webrtc/modules/audio_processing/aec3/main_filter_update_gain_unittest.cc @@ -15,6 +15,7 @@ #include #include "webrtc/base/random.h" +#include "webrtc/base/safe_minmax.h" #include "webrtc/modules/audio_processing/aec3/adaptive_fir_filter.h" #include "webrtc/modules/audio_processing/aec3/aec_state.h" #include "webrtc/modules/audio_processing/aec3/render_buffer.h" @@ -99,9 +100,8 @@ void RunFilterUpdateTest(int num_blocks_to_process, std::transform(y.begin(), y.end(), s.begin() + kFftLengthBy2, e_main.begin(), [&](float a, float b) { return a - b * kScale; }); - std::for_each(e_main.begin(), e_main.end(), [](float& a) { - a = std::max(std::min(a, 32767.0f), -32768.0f); - }); + std::for_each(e_main.begin(), e_main.end(), + [](float& a) { a = rtc::SafeClamp(a, -32768.f, 32767.f); }); fft.ZeroPaddedFft(e_main, &E_main); // Apply the shadow filter. @@ -110,9 +110,8 @@ void RunFilterUpdateTest(int num_blocks_to_process, std::transform(y.begin(), y.end(), s.begin() + kFftLengthBy2, e_shadow.begin(), [&](float a, float b) { return a - b * kScale; }); - std::for_each(e_shadow.begin(), e_shadow.end(), [](float& a) { - a = std::max(std::min(a, 32767.0f), -32768.0f); - }); + std::for_each(e_shadow.begin(), e_shadow.end(), + [](float& a) { a = rtc::SafeClamp(a, -32768.f, 32767.f); }); fft.ZeroPaddedFft(e_shadow, &E_shadow); // Compute spectra for future use. diff --git a/webrtc/modules/audio_processing/aec3/shadow_filter_update_gain_unittest.cc b/webrtc/modules/audio_processing/aec3/shadow_filter_update_gain_unittest.cc index 82850f80d6..40bee42985 100644 --- a/webrtc/modules/audio_processing/aec3/shadow_filter_update_gain_unittest.cc +++ b/webrtc/modules/audio_processing/aec3/shadow_filter_update_gain_unittest.cc @@ -16,9 +16,10 @@ #include #include "webrtc/base/random.h" +#include "webrtc/base/safe_minmax.h" #include "webrtc/modules/audio_processing/aec3/adaptive_fir_filter.h" -#include "webrtc/modules/audio_processing/aec3/aec_state.h" #include "webrtc/modules/audio_processing/aec3/aec3_common.h" +#include "webrtc/modules/audio_processing/aec3/aec_state.h" #include "webrtc/modules/audio_processing/test/echo_canceller_test_tools.h" #include "webrtc/test/gtest.h" @@ -75,9 +76,8 @@ void RunFilterUpdateTest(int num_blocks_to_process, std::transform(y.begin(), y.end(), s.begin() + kFftLengthBy2, e_shadow.begin(), [&](float a, float b) { return a - b * kScale; }); - std::for_each(e_shadow.begin(), e_shadow.end(), [](float& a) { - a = std::max(std::min(a, 32767.0f), -32768.0f); - }); + std::for_each(e_shadow.begin(), e_shadow.end(), + [](float& a) { a = rtc::SafeClamp(a, -32768.f, 32767.f); }); fft.ZeroPaddedFft(e_shadow, &E_shadow); shadow_gain.Compute(render_buffer, render_signal_analyzer, E_shadow, diff --git a/webrtc/modules/audio_processing/aec3/subtractor.cc b/webrtc/modules/audio_processing/aec3/subtractor.cc index 3897d947e1..dc3ec0688e 100644 --- a/webrtc/modules/audio_processing/aec3/subtractor.cc +++ b/webrtc/modules/audio_processing/aec3/subtractor.cc @@ -14,6 +14,7 @@ #include "webrtc/base/array_view.h" #include "webrtc/base/checks.h" +#include "webrtc/base/safe_minmax.h" #include "webrtc/modules/audio_processing/logging/apm_data_dumper.h" namespace webrtc { @@ -30,9 +31,8 @@ void PredictionError(const Aec3Fft& fft, constexpr float kScale = 1.0f / kFftLengthBy2; std::transform(y.begin(), y.end(), s.begin() + kFftLengthBy2, e->begin(), [&](float a, float b) { return a - b * kScale; }); - std::for_each(e->begin(), e->end(), [](float& a) { - a = std::max(std::min(a, 32767.0f), -32768.0f); - }); + std::for_each(e->begin(), e->end(), + [](float& a) { a = rtc::SafeClamp(a, -32768.f, 32767.f); }); fft.ZeroPaddedFft(*e, E); } } // namespace diff --git a/webrtc/modules/audio_processing/aec3/suppression_filter.cc b/webrtc/modules/audio_processing/aec3/suppression_filter.cc index b172a1d089..1121c74efe 100644 --- a/webrtc/modules/audio_processing/aec3/suppression_filter.cc +++ b/webrtc/modules/audio_processing/aec3/suppression_filter.cc @@ -16,6 +16,7 @@ #include #include +#include "webrtc/base/safe_minmax.h" #include "webrtc/modules/audio_processing/utility/ooura_fft.h" namespace webrtc { @@ -122,7 +123,7 @@ void SuppressionFilter::ApplyGain( std::transform((*e)[0].begin(), (*e)[0].end(), e_extended.begin(), (*e)[0].begin(), std::plus()); std::for_each((*e)[0].begin(), (*e)[0].end(), [](float& x_k) { - x_k = std::max(std::min(x_k, 32767.0f), -32768.0f); + x_k = rtc::SafeClamp(x_k, -32768.f, 32767.f); }); std::copy(e_extended.begin() + kFftLengthBy2, e_extended.begin() + kFftLength, std::begin(e_output_old_[0])); @@ -154,7 +155,7 @@ void SuppressionFilter::ApplyGain( if (e->size() > 2) { RTC_DCHECK_EQ(3, e->size()); std::for_each((*e)[2].begin(), (*e)[2].end(), [&](float& a) { - a = std::max(std::min(a * high_bands_gain, 32767.0f), -32768.0f); + a = rtc::SafeClamp(a * high_bands_gain, -32768.f, 32767.f); }); } diff --git a/webrtc/modules/audio_processing/agc/agc_manager_direct.cc b/webrtc/modules/audio_processing/agc/agc_manager_direct.cc index 5d1e7cd30a..6a19945f33 100644 --- a/webrtc/modules/audio_processing/agc/agc_manager_direct.cc +++ b/webrtc/modules/audio_processing/agc/agc_manager_direct.cc @@ -18,6 +18,7 @@ #include "webrtc/base/checks.h" #include "webrtc/base/logging.h" +#include "webrtc/base/safe_minmax.h" #include "webrtc/modules/audio_processing/agc/gain_map_internal.h" #include "webrtc/modules/audio_processing/gain_control_impl.h" #include "webrtc/modules/include/module_common_types.h" @@ -56,7 +57,7 @@ const int kMaxResidualGainChange = 15; const int kSurplusCompressionGain = 6; int ClampLevel(int mic_level) { - return std::min(std::max(kMinMicLevel, mic_level), kMaxMicLevel); + return rtc::SafeClamp(mic_level, kMinMicLevel, kMaxMicLevel); } int LevelFromGainError(int gain_error, int level) { @@ -380,8 +381,9 @@ void AgcManagerDirect::UpdateGain() { rms_error += kMinCompressionGain; // Handle as much error as possible with the compressor first. - int raw_compression = std::max(std::min(rms_error, max_compression_gain_), - kMinCompressionGain); + int raw_compression = + rtc::SafeClamp(rms_error, kMinCompressionGain, max_compression_gain_); + // Deemphasize the compression gain error. Move halfway between the current // target and the newly received target. This serves to soften perceptible // intra-talkspurt adjustments, at the cost of some adaptation speed. @@ -400,9 +402,9 @@ void AgcManagerDirect::UpdateGain() { // Residual error will be handled by adjusting the volume slider. Use the // raw rather than deemphasized compression here as we would otherwise // shrink the amount of slack the compressor provides. - int residual_gain = rms_error - raw_compression; - residual_gain = std::min(std::max(residual_gain, -kMaxResidualGainChange), - kMaxResidualGainChange); + const int residual_gain = + rtc::SafeClamp(rms_error - raw_compression, -kMaxResidualGainChange, + kMaxResidualGainChange); LOG(LS_INFO) << "[agc] rms_error=" << rms_error << ", " << "target_compression=" << target_compression_ << ", " << "residual_gain=" << residual_gain; diff --git a/webrtc/modules/audio_processing/audio_processing_unittest.cc b/webrtc/modules/audio_processing/audio_processing_unittest.cc index 4d97904c68..42cf4188fc 100644 --- a/webrtc/modules/audio_processing/audio_processing_unittest.cc +++ b/webrtc/modules/audio_processing/audio_processing_unittest.cc @@ -680,15 +680,13 @@ void ApmTest::ProcessDelayVerificationTest(int delay_ms, int system_delay_ms, // limit them w.r.t. AEC delay estimation support. const size_t samples_per_ms = rtc::SafeMin(16u, frame_->samples_per_channel_ / 10); - int expected_median = std::min(std::max(delay_ms - system_delay_ms, - delay_min), delay_max); - int expected_median_high = std::min( - std::max(expected_median + static_cast(96 / samples_per_ms), - delay_min), + const int expected_median = + rtc::SafeClamp(delay_ms - system_delay_ms, delay_min, delay_max); + const int expected_median_high = rtc::SafeClamp( + expected_median + rtc::dchecked_cast(96 / samples_per_ms), delay_min, delay_max); - int expected_median_low = std::min( - std::max(expected_median - static_cast(96 / samples_per_ms), - delay_min), + const int expected_median_low = rtc::SafeClamp( + expected_median - rtc::dchecked_cast(96 / samples_per_ms), delay_min, delay_max); // Verify delay metrics. int median; diff --git a/webrtc/modules/audio_processing/intelligibility/intelligibility_enhancer.cc b/webrtc/modules/audio_processing/intelligibility/intelligibility_enhancer.cc index 7ff2cf4042..f5414aa878 100644 --- a/webrtc/modules/audio_processing/intelligibility/intelligibility_enhancer.cc +++ b/webrtc/modules/audio_processing/intelligibility/intelligibility_enhancer.cc @@ -18,6 +18,7 @@ #include "webrtc/base/checks.h" #include "webrtc/base/logging.h" +#include "webrtc/base/safe_minmax.h" #include "webrtc/common_audio/include/audio_util.h" #include "webrtc/common_audio/window_generator.h" @@ -287,23 +288,23 @@ std::vector> IntelligibilityEnhancer::CreateErbBank( } for (size_t i = 1; i <= bank_size_; ++i) { - static const size_t kOne = 1; // Avoids repeated static_cast<>s below. - size_t lll = - static_cast(round(center_freqs_[std::max(kOne, i - lf) - 1] * - num_freqs / (0.5f * sample_rate_hz_))); - size_t ll = static_cast(round(center_freqs_[std::max(kOne, i) - 1] * - num_freqs / (0.5f * sample_rate_hz_))); - lll = std::min(num_freqs, std::max(lll, kOne)) - 1; - ll = std::min(num_freqs, std::max(ll, kOne)) - 1; + size_t lll = static_cast( + round(center_freqs_[rtc::SafeMax(1, i - lf) - 1] * num_freqs / + (0.5f * sample_rate_hz_))); + size_t ll = static_cast( + round(center_freqs_[rtc::SafeMax(1, i) - 1] * num_freqs / + (0.5f * sample_rate_hz_))); + lll = rtc::SafeClamp(lll, 1, num_freqs) - 1; + ll = rtc::SafeClamp(ll, 1, num_freqs) - 1; size_t rrr = static_cast( - round(center_freqs_[std::min(bank_size_, i + rf) - 1] * num_freqs / - (0.5f * sample_rate_hz_))); + round(center_freqs_[rtc::SafeMin(bank_size_, i + rf) - 1] * + num_freqs / (0.5f * sample_rate_hz_))); size_t rr = static_cast( - round(center_freqs_[std::min(bank_size_, i + 1) - 1] * num_freqs / - (0.5f * sample_rate_hz_))); - rrr = std::min(num_freqs, std::max(rrr, kOne)) - 1; - rr = std::min(num_freqs, std::max(rr, kOne)) - 1; + round(center_freqs_[rtc::SafeMin(bank_size_, i + 1) - 1] * + num_freqs / (0.5f * sample_rate_hz_))); + rrr = rtc::SafeClamp(rrr, 1, num_freqs) - 1; + rr = rtc::SafeClamp(rr, 1, num_freqs) - 1; float step = ll == lll ? 0.f : 1.f / (ll - lll); float element = 0.f; diff --git a/webrtc/modules/audio_processing/intelligibility/intelligibility_utils.cc b/webrtc/modules/audio_processing/intelligibility/intelligibility_utils.cc index fa8d1704c6..deaeb27f44 100644 --- a/webrtc/modules/audio_processing/intelligibility/intelligibility_utils.cc +++ b/webrtc/modules/audio_processing/intelligibility/intelligibility_utils.cc @@ -16,6 +16,8 @@ #include #include +#include "webrtc/base/safe_minmax.h" + namespace webrtc { namespace intelligibility { @@ -28,9 +30,9 @@ const float kMaxFactor = 100.f; // Return |current| changed towards |target|, with the relative change being at // most |limit|. float UpdateFactor(float target, float current, float limit) { - float gain = target / (current + std::numeric_limits::epsilon()); - gain = std::min(std::max(gain, 1.f - limit), 1.f + limit); - return std::min(std::max(current * gain, kMinFactor), kMaxFactor);; + const float gain = target / (current + std::numeric_limits::epsilon()); + const float clamped_gain = rtc::SafeClamp(gain, 1 - limit, 1 + limit); + return rtc::SafeClamp(current * clamped_gain, kMinFactor, kMaxFactor); } } // namespace diff --git a/webrtc/modules/remote_bitrate_estimator/aimd_rate_control.cc b/webrtc/modules/remote_bitrate_estimator/aimd_rate_control.cc index d903cf9af7..4b9343c440 100644 --- a/webrtc/modules/remote_bitrate_estimator/aimd_rate_control.cc +++ b/webrtc/modules/remote_bitrate_estimator/aimd_rate_control.cc @@ -62,11 +62,11 @@ int64_t AimdRateControl::GetFeedbackInterval() const { // Estimate how often we can send RTCP if we allocate up to 5% of bandwidth // to feedback. static const int kRtcpSize = 80; - int64_t interval = static_cast( + const int64_t interval = static_cast( kRtcpSize * 8.0 * 1000.0 / (0.05 * current_bitrate_bps_) + 0.5); const int64_t kMinFeedbackIntervalMs = 200; - return std::min(std::max(interval, kMinFeedbackIntervalMs), - kMaxFeedbackIntervalMs); + return rtc::SafeClamp(interval, kMinFeedbackIntervalMs, + kMaxFeedbackIntervalMs); } bool AimdRateControl::TimeToReduceFurther(int64_t time_now, diff --git a/webrtc/modules/remote_bitrate_estimator/overuse_detector.cc b/webrtc/modules/remote_bitrate_estimator/overuse_detector.cc index 399daf0ca7..6b2b518375 100644 --- a/webrtc/modules/remote_bitrate_estimator/overuse_detector.cc +++ b/webrtc/modules/remote_bitrate_estimator/overuse_detector.cc @@ -19,6 +19,7 @@ #include "webrtc/base/checks.h" #include "webrtc/base/logging.h" +#include "webrtc/base/safe_minmax.h" #include "webrtc/modules/remote_bitrate_estimator/include/bwe_defines.h" #include "webrtc/modules/remote_bitrate_estimator/test/bwe_test_logging.h" #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" @@ -144,11 +145,7 @@ void OveruseDetector::UpdateThreshold(double modified_offset, int64_t now_ms) { int64_t time_delta_ms = std::min(now_ms - last_update_ms_, kMaxTimeDeltaMs); threshold_ += k * (fabs(modified_offset) - threshold_) * time_delta_ms; - - const double kMinThreshold = 6; - const double kMaxThreshold = 600; - threshold_ = std::min(std::max(threshold_, kMinThreshold), kMaxThreshold); - + threshold_ = rtc::SafeClamp(threshold_, 6.f, 600.f); last_update_ms_ = now_ms; } diff --git a/webrtc/modules/remote_bitrate_estimator/remote_estimator_proxy.cc b/webrtc/modules/remote_bitrate_estimator/remote_estimator_proxy.cc index 3700fc428d..35bc667b5a 100644 --- a/webrtc/modules/remote_bitrate_estimator/remote_estimator_proxy.cc +++ b/webrtc/modules/remote_bitrate_estimator/remote_estimator_proxy.cc @@ -15,10 +15,11 @@ #include "webrtc/base/checks.h" #include "webrtc/base/logging.h" -#include "webrtc/system_wrappers/include/clock.h" +#include "webrtc/base/safe_minmax.h" #include "webrtc/modules/pacing/packet_router.h" -#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h" #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h" +#include "webrtc/system_wrappers/include/clock.h" namespace webrtc { @@ -104,8 +105,9 @@ void RemoteEstimatorProxy::OnBitrateChanged(int bitrate_bps) { // Let TWCC reports occupy 5% of total bandwidth. rtc::CritScope cs(&lock_); - send_interval_ms_ = static_cast(0.5 + kTwccReportSize * 8.0 * 1000.0 / - (std::max(std::min(0.05 * bitrate_bps, kMaxTwccRate), kMinTwccRate))); + send_interval_ms_ = static_cast( + 0.5 + kTwccReportSize * 8.0 * 1000.0 / + rtc::SafeClamp(0.05 * bitrate_bps, kMinTwccRate, kMaxTwccRate)); } void RemoteEstimatorProxy::OnPacketArrival(uint16_t sequence_number, diff --git a/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.cc b/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.cc index 15e759b654..1361277508 100644 --- a/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.cc +++ b/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.cc @@ -15,6 +15,7 @@ #include #include "webrtc/base/constructormagic.h" +#include "webrtc/base/safe_minmax.h" namespace webrtc { namespace testing { @@ -406,8 +407,8 @@ namespace { inline int64_t TruncatedNSigmaGaussian(Random* const random, int64_t mean, int64_t std_dev) { - int64_t gaussian_random = random->Gaussian(mean, std_dev); - return std::max(std::min(gaussian_random, kN * std_dev), -kN * std_dev); + const int64_t gaussian_random = random->Gaussian(mean, std_dev); + return rtc::SafeClamp(gaussian_random, -kN * std_dev, kN * std_dev); } } diff --git a/webrtc/modules/rtp_rtcp/source/rtp_sender.cc b/webrtc/modules/rtp_rtcp/source/rtp_sender.cc index 3cac4195b4..1bdb804e82 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_sender.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_sender.cc @@ -17,8 +17,9 @@ #include "webrtc/base/checks.h" #include "webrtc/base/logging.h" #include "webrtc/base/rate_limiter.h" -#include "webrtc/base/trace_event.h" +#include "webrtc/base/safe_minmax.h" #include "webrtc/base/timeutils.h" +#include "webrtc/base/trace_event.h" #include "webrtc/logging/rtc_event_log/rtc_event_log.h" #include "webrtc/modules/remote_bitrate_estimator/test/bwe_test_logging.h" #include "webrtc/modules/rtp_rtcp/include/rtp_cvo.h" @@ -467,16 +468,16 @@ size_t RTPSender::SendPadData(size_t bytes, if (audio_configured_) { // Allow smaller padding packets for audio. - padding_bytes_in_packet = - std::min(std::max(bytes, kMinAudioPaddingLength), max_payload_size); - if (padding_bytes_in_packet > kMaxPaddingLength) - padding_bytes_in_packet = kMaxPaddingLength; + padding_bytes_in_packet = rtc::SafeClamp( + bytes, kMinAudioPaddingLength, + rtc::SafeMin(max_payload_size, kMaxPaddingLength)); } else { // Always send full padding packets. This is accounted for by the // RtpPacketSender, which will make sure we don't send too much padding even // if a single packet is larger than requested. // We do this to avoid frequently sending small packets on higher bitrates. - padding_bytes_in_packet = std::min(max_payload_size, kMaxPaddingLength); + padding_bytes_in_packet = + rtc::SafeMin(max_payload_size, kMaxPaddingLength); } size_t bytes_sent = 0; while (bytes_sent < bytes) { diff --git a/webrtc/p2p/base/port.cc b/webrtc/p2p/base/port.cc index bf549248b7..e657125869 100644 --- a/webrtc/p2p/base/port.cc +++ b/webrtc/p2p/base/port.cc @@ -21,6 +21,7 @@ #include "webrtc/base/messagedigest.h" #include "webrtc/base/network.h" #include "webrtc/base/ptr_util.h" +#include "webrtc/base/safe_minmax.h" #include "webrtc/base/stringencode.h" #include "webrtc/base/stringutils.h" #include "webrtc/p2p/base/common.h" @@ -69,7 +70,7 @@ const int DEFAULT_RTT = 3000; // 3 seconds // Computes our estimate of the RTT given the current estimate. inline int ConservativeRTTEstimate(int rtt) { - return std::max(MINIMUM_RTT, std::min(MAXIMUM_RTT, 2 * rtt)); + return rtc::SafeClamp(2 * rtt, MINIMUM_RTT, MAXIMUM_RTT); } // Weighting of the old rtt value to new data. diff --git a/webrtc/p2p/base/pseudotcp.cc b/webrtc/p2p/base/pseudotcp.cc index 8257b92c31..d93f49e394 100644 --- a/webrtc/p2p/base/pseudotcp.cc +++ b/webrtc/p2p/base/pseudotcp.cc @@ -23,6 +23,7 @@ #include "webrtc/base/byteorder.h" #include "webrtc/base/checks.h" #include "webrtc/base/logging.h" +#include "webrtc/base/safe_minmax.h" #include "webrtc/base/socket.h" #include "webrtc/base/stringutils.h" #include "webrtc/base/timeutils.h" @@ -155,10 +156,6 @@ inline uint16_t bytes_to_short(const void* buf) { return rtc::NetworkToHost16(*static_cast(buf)); } -uint32_t bound(uint32_t lower, uint32_t middle, uint32_t upper) { - return std::min(std::max(lower, middle), upper); -} - ////////////////////////////////////////////////////////////////////// // Debugging Statistics ////////////////////////////////////////////////////////////////////// @@ -725,9 +722,8 @@ bool PseudoTcp::process(Segment& seg) { m_rx_rttvar = (3 * m_rx_rttvar + abs_err) / 4; m_rx_srtt = (7 * m_rx_srtt + rtt) / 8; } - m_rx_rto = - bound(MIN_RTO, m_rx_srtt + std::max(1, 4 * m_rx_rttvar), - MAX_RTO); + m_rx_rto = rtc::SafeClamp(m_rx_srtt + rtc::SafeMax(1, 4 * m_rx_rttvar), + MIN_RTO, MAX_RTO); #if _DEBUGMSG >= _DBG_VERBOSE LOG(LS_INFO) << "rtt: " << rtt << " srtt: " << m_rx_srtt diff --git a/webrtc/tools/agc/activity_metric.cc b/webrtc/tools/agc/activity_metric.cc index 599777c3be..9715d62060 100644 --- a/webrtc/tools/agc/activity_metric.cc +++ b/webrtc/tools/agc/activity_metric.cc @@ -17,6 +17,7 @@ #include #include "webrtc/base/flags.h" +#include "webrtc/base/safe_minmax.h" #include "webrtc/modules/audio_processing/agc/agc.h" #include "webrtc/modules/audio_processing/agc/loudness_histogram.h" #include "webrtc/modules/audio_processing/agc/utility.h" @@ -121,9 +122,7 @@ class AgcStat { for (size_t n = 0; n < features.num_frames; n++) { double p_active = p[n] * video_vad_[n]; double p_passive = (1 - p[n]) * (1 - video_vad_[n]); - p[n] = p_active / (p_active + p_passive); - // Limit probabilities. - p[n] = std::min(std::max(p[n], 0.01), 0.99); + p[n] = rtc::SafeClamp(p_active / (p_active + p_passive), 0.01, 0.99); } if (vad_->VoicingProbability(features, p) < 0) return -1; diff --git a/webrtc/voice_engine/channel_proxy.cc b/webrtc/voice_engine/channel_proxy.cc index 46bcef9942..4a0b3cc4b1 100644 --- a/webrtc/voice_engine/channel_proxy.cc +++ b/webrtc/voice_engine/channel_proxy.cc @@ -15,6 +15,7 @@ #include "webrtc/api/call/audio_sink.h" #include "webrtc/base/checks.h" #include "webrtc/base/logging.h" +#include "webrtc/base/safe_minmax.h" #include "webrtc/call/rtp_transport_controller_send_interface.h" #include "webrtc/voice_engine/channel.h" @@ -290,7 +291,7 @@ void ChannelProxy::SetMinimumPlayoutDelay(int delay_ms) { RTC_DCHECK(module_process_thread_checker_.CalledOnValidThread()); // Limit to range accepted by both VoE and ACM, so we're at least getting as // close as possible, instead of failing. - delay_ms = std::max(0, std::min(delay_ms, 10000)); + delay_ms = rtc::SafeClamp(delay_ms, 0, 10000); int error = channel()->SetMinimumPlayoutDelay(delay_ms); if (0 != error) { LOG(LS_WARNING) << "Error setting minimum playout delay.";