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}
This commit is contained in:
parent
d1114c7fef
commit
0703856b53
@ -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<int>(x, y) // returns an int
|
||||
@ -187,6 +223,115 @@ constexpr R2 SafeMax(T1 a, T2 b) {
|
||||
return safe_cmp::Gt(a, b) ? static_cast<R2>(a) : static_cast<R2>(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 <typename T,
|
||||
typename L,
|
||||
typename H,
|
||||
bool int1 = IsIntlike<T>::value,
|
||||
bool int2 = IsIntlike<L>::value,
|
||||
bool int3 = IsIntlike<H>::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 <typename T, typename L, typename H>
|
||||
struct ClampType<T, L, H, false, false, false> {
|
||||
using type = typename std::common_type<T, L, H>::type;
|
||||
};
|
||||
|
||||
// Specialization for when all three types are integral.
|
||||
template <typename T, typename L, typename H>
|
||||
struct ClampType<T, L, H, true, true, true> {
|
||||
private:
|
||||
// Range of the return value. The return type must be able to represent this
|
||||
// full range.
|
||||
static constexpr auto r_min =
|
||||
SafeMax(Limits<L>::lowest, SafeMin(Limits<H>::lowest, Limits<T>::lowest));
|
||||
static constexpr auto r_max =
|
||||
SafeMin(Limits<H>::max, SafeMax(Limits<L>::max, Limits<T>::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 <typename A>
|
||||
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<A>::lowest, r_min) &&
|
||||
safe_cmp::Le(r_max, Limits<A>::max);
|
||||
|
||||
public:
|
||||
static constexpr bool value = not_too_large && range_contained;
|
||||
};
|
||||
|
||||
using best_signed_type = typename std::conditional<
|
||||
AcceptableType<int8_t>::value,
|
||||
int8_t,
|
||||
typename std::conditional<
|
||||
AcceptableType<int16_t>::value,
|
||||
int16_t,
|
||||
typename std::conditional<AcceptableType<int32_t>::value,
|
||||
int32_t,
|
||||
int64_t>::type>::type>::type;
|
||||
|
||||
using best_unsigned_type = typename std::conditional<
|
||||
AcceptableType<uint8_t>::value,
|
||||
uint8_t,
|
||||
typename std::conditional<
|
||||
AcceptableType<uint16_t>::value,
|
||||
uint16_t,
|
||||
typename std::conditional<AcceptableType<uint32_t>::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<T>::value,
|
||||
typename std::conditional<AcceptableType<best_signed_type>::value,
|
||||
best_signed_type,
|
||||
best_unsigned_type>::type,
|
||||
typename std::conditional<AcceptableType<best_unsigned_type>::value,
|
||||
best_unsigned_type,
|
||||
best_signed_type>::type>::type;
|
||||
static_assert(AcceptableType<type>::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<T>::type,
|
||||
typename safe_minmax_impl::UnderlyingType<L>::type,
|
||||
typename safe_minmax_impl::UnderlyingType<H>::type>::type>::type>
|
||||
R2 SafeClamp(T x, L min, H max) {
|
||||
static_assert(IsIntlike<H>::value || std::is_floating_point<H>::value,
|
||||
"The first argument must be integral or floating-point");
|
||||
static_assert(IsIntlike<T>::value || std::is_floating_point<T>::value,
|
||||
"The second argument must be integral or floating-point");
|
||||
static_assert(IsIntlike<L>::value || std::is_floating_point<L>::value,
|
||||
"The third argument must be integral or floating-point");
|
||||
RTC_DCHECK_LE(min, max);
|
||||
return safe_cmp::Le(x, min)
|
||||
? static_cast<R2>(min)
|
||||
: safe_cmp::Ge(x, max) ? static_cast<R2>(max) : static_cast<R2>(x);
|
||||
}
|
||||
|
||||
} // namespace rtc
|
||||
|
||||
#endif // WEBRTC_BASE_SAFE_MINMAX_H_
|
||||
|
||||
@ -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 <typename T1, typename T2, typename Tmin, typename Tmax>
|
||||
constexpr bool TypeCheckMinMax() {
|
||||
@ -41,6 +42,21 @@ constexpr bool TypeCheckMaxR() {
|
||||
decltype(SafeMax<R>(std::declval<T1>(), std::declval<T2>())), R>::value;
|
||||
}
|
||||
|
||||
template <typename T, typename L, typename H, typename R>
|
||||
constexpr bool TypeCheckClamp() {
|
||||
return std::is_same<decltype(SafeClamp(std::declval<T>(), std::declval<L>(),
|
||||
std::declval<H>())),
|
||||
R>::value;
|
||||
}
|
||||
|
||||
template <typename T, typename L, typename H, typename R>
|
||||
constexpr bool TypeCheckClampR() {
|
||||
return std::is_same<decltype(SafeClamp<R>(std::declval<T>(),
|
||||
std::declval<L>(),
|
||||
std::declval<H>())),
|
||||
R>::value;
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
|
||||
// SafeMin/SafeMax: Check that all combinations of signed/unsigned 8/64 bits
|
||||
@ -62,6 +78,73 @@ static_assert(TypeCheckMinMax<uint64_t, uint8_t, uint8_t, uint64_t>(), "");
|
||||
static_assert(TypeCheckMinMax<uint64_t, int64_t, int64_t, uint64_t>(), "");
|
||||
static_assert(TypeCheckMinMax<uint64_t, uint64_t, uint64_t, uint64_t>(), "");
|
||||
|
||||
// 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<uint64_t, int8_t, int8_t, int8_t>(), "");
|
||||
static_assert(TypeCheckClamp<uint64_t, int8_t, uint8_t, uint8_t>(), "");
|
||||
static_assert(TypeCheckClamp<uint64_t, int8_t, int64_t, int64_t>(), "");
|
||||
static_assert(TypeCheckClamp<uint64_t, int8_t, uint64_t, uint64_t>(), "");
|
||||
static_assert(TypeCheckClamp<uint64_t, uint8_t, int8_t, uint8_t>(), "");
|
||||
static_assert(TypeCheckClamp<uint64_t, uint8_t, uint8_t, uint8_t>(), "");
|
||||
static_assert(TypeCheckClamp<uint64_t, uint8_t, int64_t, uint64_t>(), "");
|
||||
static_assert(TypeCheckClamp<uint64_t, uint8_t, uint64_t, uint64_t>(), "");
|
||||
static_assert(TypeCheckClamp<uint64_t, int64_t, int8_t, int8_t>(), "");
|
||||
static_assert(TypeCheckClamp<uint64_t, int64_t, uint8_t, uint8_t>(), "");
|
||||
static_assert(TypeCheckClamp<uint64_t, int64_t, int64_t, int64_t>(), "");
|
||||
static_assert(TypeCheckClamp<uint64_t, int64_t, uint64_t, uint64_t>(), "");
|
||||
static_assert(TypeCheckClamp<uint64_t, uint64_t, int8_t, uint8_t>(), "");
|
||||
static_assert(TypeCheckClamp<uint64_t, uint64_t, uint8_t, uint8_t>(), "");
|
||||
static_assert(TypeCheckClamp<uint64_t, uint64_t, int64_t, uint64_t>(), "");
|
||||
static_assert(TypeCheckClamp<uint64_t, uint64_t, uint64_t, uint64_t>(), "");
|
||||
|
||||
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<unsigned, unsigned, unsigned, unsigned>(), "");
|
||||
static_assert(TypeCheckClamp<unsigned, unsigned, DefaultE, unsigned>(), "");
|
||||
static_assert(TypeCheckClamp<unsigned, unsigned, UInt8E, uint8_t>(), "");
|
||||
static_assert(TypeCheckClamp<unsigned, DefaultE, unsigned, unsigned>(), "");
|
||||
static_assert(TypeCheckClamp<unsigned, DefaultE, DefaultE, int>(), "");
|
||||
static_assert(TypeCheckClamp<unsigned, DefaultE, UInt8E, uint8_t>(), "");
|
||||
static_assert(TypeCheckClamp<unsigned, UInt8E, unsigned, unsigned>(), "");
|
||||
static_assert(TypeCheckClamp<unsigned, UInt8E, DefaultE, unsigned>(), "");
|
||||
static_assert(TypeCheckClamp<unsigned, UInt8E, UInt8E, uint8_t>(), "");
|
||||
static_assert(TypeCheckClamp<DefaultE, unsigned, unsigned, unsigned>(), "");
|
||||
static_assert(TypeCheckClamp<DefaultE, unsigned, DefaultE, int>(), "");
|
||||
static_assert(TypeCheckClamp<DefaultE, unsigned, UInt8E, int16_t>(), "");
|
||||
static_assert(TypeCheckClamp<DefaultE, DefaultE, unsigned, int>(), "");
|
||||
static_assert(TypeCheckClamp<DefaultE, DefaultE, DefaultE, int>(), "");
|
||||
static_assert(TypeCheckClamp<DefaultE, DefaultE, UInt8E, int>(), "");
|
||||
static_assert(TypeCheckClamp<DefaultE, UInt8E, unsigned, int>(), "");
|
||||
static_assert(TypeCheckClamp<DefaultE, UInt8E, DefaultE, int>(), "");
|
||||
static_assert(TypeCheckClamp<DefaultE, UInt8E, UInt8E, int16_t>(), "");
|
||||
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<double, float, float, double>(), "");
|
||||
static_assert(TypeCheckClamp<double, float, double, double>(), "");
|
||||
static_assert(TypeCheckClamp<double, float, ld, ld>(), "");
|
||||
static_assert(TypeCheckClamp<double, double, float, double>(), "");
|
||||
static_assert(TypeCheckClamp<double, double, double, double>(), "");
|
||||
static_assert(TypeCheckClamp<double, double, ld, ld>(), "");
|
||||
static_assert(TypeCheckClamp<double, ld, float, ld>(), "");
|
||||
static_assert(TypeCheckClamp<double, ld, double, ld>(), "");
|
||||
static_assert(TypeCheckClamp<double, ld, ld, ld>(), "");
|
||||
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<uint32_t, uint64_t, uint32_t>(), "");
|
||||
static_assert(TypeCheckMaxR<uint32_t, int32_t, uint32_t>(), "");
|
||||
// static_assert(TypeCheckMaxR<uint32_t, int32_t, int32_t>(), "");
|
||||
|
||||
// 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<int16_t, int8_t, uint8_t, int16_t>(), "");
|
||||
static_assert(TypeCheckClampR<int16_t, int8_t, uint8_t, int32_t>(), "");
|
||||
// static_assert(TypeCheckClampR<int16_t, int8_t, uint8_t, uint32_t>(), "");
|
||||
|
||||
template <typename T1, typename T2, typename Tmin, typename Tmax>
|
||||
constexpr bool CheckMinMax(T1 a, T2 b, Tmin min, Tmax max) {
|
||||
return TypeCheckMinMax<T1, T2, Tmin, Tmax>() && SafeMin(a, b) == min &&
|
||||
SafeMax(a, b) == max;
|
||||
}
|
||||
|
||||
template <typename T, typename L, typename H, typename R>
|
||||
bool CheckClamp(T x, L min, H max, R clamped) {
|
||||
return TypeCheckClamp<T, L, H, R>() && 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<int32_t>::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<int16_t>::min(),
|
||||
std::numeric_limits<int16_t>::max(),
|
||||
std::numeric_limits<int16_t>::min()));
|
||||
EXPECT_TRUE(CheckClamp(uint32_t{1000000}, std::numeric_limits<int16_t>::min(),
|
||||
std::numeric_limits<int16_t>::max(),
|
||||
std::numeric_limits<int16_t>::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
|
||||
|
||||
@ -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<int>(std::max(
|
||||
std::min(bits_per_second, kOpusMaxBitrateBps), kOpusMinBitrateBps));
|
||||
config_.bitrate_bps = rtc::Optional<int>(rtc::SafeClamp<int>(
|
||||
bits_per_second, kOpusMinBitrateBps, kOpusMaxBitrateBps));
|
||||
RTC_DCHECK(config_.IsOk());
|
||||
RTC_CHECK_EQ(0, WebRtcOpus_SetBitRate(inst_, config_.GetBitrateBps()));
|
||||
const auto new_complexity = config_.GetNewComplexity();
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
|
||||
#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<int>(std::max(min_value, std::min(max_value, new_value)));
|
||||
return static_cast<int>(rtc::SafeClamp(new_value, min_value, max_value));
|
||||
}
|
||||
|
||||
} // namespace aec3
|
||||
|
||||
@ -12,6 +12,8 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
#include <string>
|
||||
|
||||
#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.
|
||||
|
||||
@ -16,9 +16,10 @@
|
||||
#include <vector>
|
||||
|
||||
#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,
|
||||
|
||||
@ -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
|
||||
|
||||
@ -16,6 +16,7 @@
|
||||
#include <functional>
|
||||
#include <numeric>
|
||||
|
||||
#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<float>());
|
||||
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);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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<size_t>(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<int>(96 / samples_per_ms),
|
||||
delay_min),
|
||||
const int expected_median =
|
||||
rtc::SafeClamp<int>(delay_ms - system_delay_ms, delay_min, delay_max);
|
||||
const int expected_median_high = rtc::SafeClamp<int>(
|
||||
expected_median + rtc::dchecked_cast<int>(96 / samples_per_ms), delay_min,
|
||||
delay_max);
|
||||
int expected_median_low = std::min(
|
||||
std::max(expected_median - static_cast<int>(96 / samples_per_ms),
|
||||
delay_min),
|
||||
const int expected_median_low = rtc::SafeClamp<int>(
|
||||
expected_median - rtc::dchecked_cast<int>(96 / samples_per_ms), delay_min,
|
||||
delay_max);
|
||||
// Verify delay metrics.
|
||||
int median;
|
||||
|
||||
@ -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<std::vector<float>> 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<size_t>(round(center_freqs_[std::max(kOne, i - lf) - 1] *
|
||||
num_freqs / (0.5f * sample_rate_hz_)));
|
||||
size_t ll = static_cast<size_t>(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<size_t>(
|
||||
round(center_freqs_[rtc::SafeMax<size_t>(1, i - lf) - 1] * num_freqs /
|
||||
(0.5f * sample_rate_hz_)));
|
||||
size_t ll = static_cast<size_t>(
|
||||
round(center_freqs_[rtc::SafeMax<size_t>(1, i) - 1] * num_freqs /
|
||||
(0.5f * sample_rate_hz_)));
|
||||
lll = rtc::SafeClamp<size_t>(lll, 1, num_freqs) - 1;
|
||||
ll = rtc::SafeClamp<size_t>(ll, 1, num_freqs) - 1;
|
||||
|
||||
size_t rrr = static_cast<size_t>(
|
||||
round(center_freqs_[std::min(bank_size_, i + rf) - 1] * num_freqs /
|
||||
(0.5f * sample_rate_hz_)));
|
||||
round(center_freqs_[rtc::SafeMin<size_t>(bank_size_, i + rf) - 1] *
|
||||
num_freqs / (0.5f * sample_rate_hz_)));
|
||||
size_t rr = static_cast<size_t>(
|
||||
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<size_t>(bank_size_, i + 1) - 1] *
|
||||
num_freqs / (0.5f * sample_rate_hz_)));
|
||||
rrr = rtc::SafeClamp<size_t>(rrr, 1, num_freqs) - 1;
|
||||
rr = rtc::SafeClamp<size_t>(rr, 1, num_freqs) - 1;
|
||||
|
||||
float step = ll == lll ? 0.f : 1.f / (ll - lll);
|
||||
float element = 0.f;
|
||||
|
||||
@ -16,6 +16,8 @@
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
|
||||
#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<float>::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<float>::epsilon());
|
||||
const float clamped_gain = rtc::SafeClamp(gain, 1 - limit, 1 + limit);
|
||||
return rtc::SafeClamp(current * clamped_gain, kMinFactor, kMaxFactor);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@ -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<int64_t>(
|
||||
const int64_t interval = static_cast<int64_t>(
|
||||
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,
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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<int>(0.5 + kTwccReportSize * 8.0 * 1000.0 /
|
||||
(std::max(std::min(0.05 * bitrate_bps, kMaxTwccRate), kMinTwccRate)));
|
||||
send_interval_ms_ = static_cast<int>(
|
||||
0.5 + kTwccReportSize * 8.0 * 1000.0 /
|
||||
rtc::SafeClamp(0.05 * bitrate_bps, kMinTwccRate, kMaxTwccRate));
|
||||
}
|
||||
|
||||
void RemoteEstimatorProxy::OnPacketArrival(uint16_t sequence_number,
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
#include <sstream>
|
||||
|
||||
#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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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<size_t>(
|
||||
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<size_t>(max_payload_size, kMaxPaddingLength);
|
||||
}
|
||||
size_t bytes_sent = 0;
|
||||
while (bytes_sent < bytes) {
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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<const uint16_t*>(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<uint32_t>(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
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
#include <memory>
|
||||
|
||||
#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;
|
||||
|
||||
@ -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.";
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user