From e367e47bd2aa984b0f34bd06ba230bd5b2657179 Mon Sep 17 00:00:00 2001 From: kingqn0321 Date: Mon, 10 Jul 2023 18:31:42 +0800 Subject: [PATCH 1/2] =?UTF-8?q?Add=20webrtc=20transport-cc=20feedback=20me?= =?UTF-8?q?chanism=201=E3=80=81improve=20the=20accuracy=20of=20gcc=20bwe?= =?UTF-8?q?=20when=20uplink=20network=20exists=20a=20big=20propagate=20jit?= =?UTF-8?q?ter(eg:=20100ms)=202=E3=80=81this=20optimization=20logic=20is?= =?UTF-8?q?=20ported=20from=20google=20webrtc(see:=20RemoteEstimatorProxy)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../libwebrtc/libwebrtc/rtc_base/checks.h | 434 ++++++++++++++++++ .../libwebrtc/rtc_base/numerics/mod_ops.h | 142 ++++++ .../rtc_base/numerics/sequence_number_util.h | 118 +++++ .../libwebrtc/rtc_base/system/inline.h | 31 ++ .../RTC/TransportCongestionControlServer.hpp | 15 + .../RTC/TransportCongestionControlServer.cpp | 224 +++++++-- 6 files changed, 929 insertions(+), 35 deletions(-) create mode 100644 worker/deps/libwebrtc/libwebrtc/rtc_base/checks.h create mode 100644 worker/deps/libwebrtc/libwebrtc/rtc_base/numerics/mod_ops.h create mode 100644 worker/deps/libwebrtc/libwebrtc/rtc_base/numerics/sequence_number_util.h create mode 100644 worker/deps/libwebrtc/libwebrtc/rtc_base/system/inline.h diff --git a/worker/deps/libwebrtc/libwebrtc/rtc_base/checks.h b/worker/deps/libwebrtc/libwebrtc/rtc_base/checks.h new file mode 100644 index 0000000000..dbdc004433 --- /dev/null +++ b/worker/deps/libwebrtc/libwebrtc/rtc_base/checks.h @@ -0,0 +1,434 @@ +/* + * Copyright 2006 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef RTC_BASE_CHECKS_H_ +#define RTC_BASE_CHECKS_H_ + +// If you for some reson need to know if DCHECKs are on, test the value of +// RTC_DCHECK_IS_ON. (Test its value, not if it's defined; it'll always be +// defined, to either a true or a false value.) +#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON) +#define RTC_DCHECK_IS_ON 1 +#else +#define RTC_DCHECK_IS_ON 0 +#endif + +// Annotate a function that will not return control flow to the caller. +#if defined(_MSC_VER) +#define RTC_NORETURN __declspec(noreturn) +#elif defined(__GNUC__) +#define RTC_NORETURN __attribute__ ((__noreturn__)) +#else +#define RTC_NORETURN +#endif + +#ifdef __cplusplus +extern "C" { +#endif +RTC_NORETURN void rtc_FatalMessage(const char* file, int line, const char* msg); +#ifdef __cplusplus +} // extern "C" +#endif + +#ifdef __cplusplus +// C++ version. + +#include + +#include "absl/strings/string_view.h" +#include "rtc_base/numerics/safe_compare.h" +#include "rtc_base/system/inline.h" + +// The macros here print a message to stderr and abort under various +// conditions. All will accept additional stream messages. For example: +// RTC_DCHECK_EQ(foo, bar) << "I'm printed when foo != bar."; +// +// - RTC_CHECK(x) is an assertion that x is always true, and that if it isn't, +// it's better to terminate the process than to continue. During development, +// the reason that it's better to terminate might simply be that the error +// handling code isn't in place yet; in production, the reason might be that +// the author of the code truly believes that x will always be true, but that +// she recognizes that if she is wrong, abrupt and unpleasant process +// termination is still better than carrying on with the assumption violated. +// +// RTC_CHECK always evaluates its argument, so it's OK for x to have side +// effects. +// +// - RTC_DCHECK(x) is the same as RTC_CHECK(x)---an assertion that x is always +// true---except that x will only be evaluated in debug builds; in production +// builds, x is simply assumed to be true. This is useful if evaluating x is +// expensive and the expected cost of failing to detect the violated +// assumption is acceptable. You should not handle cases where a production +// build fails to spot a violated condition, even those that would result in +// crashes. If the code needs to cope with the error, make it cope, but don't +// call RTC_DCHECK; if the condition really can't occur, but you'd sleep +// better at night knowing that the process will suicide instead of carrying +// on in case you were wrong, use RTC_CHECK instead of RTC_DCHECK. +// +// RTC_DCHECK only evaluates its argument in debug builds, so if x has visible +// side effects, you need to write e.g. +// bool w = x; RTC_DCHECK(w); +// +// - RTC_CHECK_EQ, _NE, _GT, ..., and RTC_DCHECK_EQ, _NE, _GT, ... are +// specialized variants of RTC_CHECK and RTC_DCHECK that print prettier +// messages if the condition doesn't hold. Prefer them to raw RTC_CHECK and +// RTC_DCHECK. +// +// - FATAL() aborts unconditionally. +// +// TODO(ajm): Ideally, checks.h would be combined with logging.h, but +// consolidation with system_wrappers/logging.h should happen first. + +namespace rtc { +namespace webrtc_checks_impl { +enum class CheckArgType : int8_t { + kEnd = 0, + kInt, + kLong, + kLongLong, + kUInt, + kULong, + kULongLong, + kDouble, + kLongDouble, + kCharP, + kStdString, + kStringView, + kVoidP, + + // kCheckOp doesn't represent an argument type. Instead, it is sent as the + // first argument from RTC_CHECK_OP to make FatalLog use the next two + // arguments to build the special CHECK_OP error message + // (the "a == b (1 vs. 2)" bit). + kCheckOp, +}; + +RTC_NORETURN void FatalLog(const char* file, + int line, + const char* message, + const CheckArgType* fmt, + ...); + +// Wrapper for log arguments. Only ever make values of this type with the +// MakeVal() functions. +template +struct Val { + static constexpr CheckArgType Type() { return N; } + T GetVal() const { return val; } + T val; +}; + +// Case for when we need to construct a temp string and then print that. +// (We can't use Val +// because we need somewhere to store the temp string.) +struct ToStringVal { + static constexpr CheckArgType Type() { return CheckArgType::kStdString; } + const std::string* GetVal() const { return &val; } + std::string val; +}; + +inline Val MakeVal(int x) { + return {x}; +} +inline Val MakeVal(long x) { + return {x}; +} +inline Val MakeVal(long long x) { + return {x}; +} +inline Val MakeVal(unsigned int x) { + return {x}; +} +inline Val MakeVal(unsigned long x) { + return {x}; +} +inline Val MakeVal( + unsigned long long x) { + return {x}; +} + +inline Val MakeVal(double x) { + return {x}; +} +inline Val MakeVal(long double x) { + return {x}; +} + +inline Val MakeVal(const char* x) { + return {x}; +} +inline Val MakeVal( + const std::string& x) { + return {&x}; +} +inline Val MakeVal( + const absl::string_view& x) { + return {&x}; +} + +inline Val MakeVal(const void* x) { + return {x}; +} + +// The enum class types are not implicitly convertible to arithmetic types. +template < + typename T, + typename std::enable_if::value && + !std::is_arithmetic::value>::type* = nullptr> +inline decltype(MakeVal(std::declval::type>())) +MakeVal(T x) { + return {static_cast::type>(x)}; +} + +template ::type, + typename T2 = decltype(ToLogString(std::declval())), + typename std::enable_if::value>::type* = + nullptr> +ToStringVal MakeVal(const T& x) { + return {ToLogString(x)}; +} + +// Ephemeral type that represents the result of the logging << operator. +template +class LogStreamer; + +// Base case: Before the first << argument. +template <> +class LogStreamer<> final { + public: + template ::value || + std::is_enum::value>::type* = nullptr> + RTC_FORCE_INLINE LogStreamer()))> operator<<( + U arg) const { + return LogStreamer()))>(MakeVal(arg), + this); + } + + template ::value && + !std::is_enum::value>::type* = nullptr> + RTC_FORCE_INLINE LogStreamer()))> operator<<( + const U& arg) const { + return LogStreamer()))>(MakeVal(arg), + this); + } + + template + RTC_NORETURN RTC_FORCE_INLINE static void Call(const char* file, + const int line, + const char* message, + const Us&... args) { + static constexpr CheckArgType t[] = {Us::Type()..., CheckArgType::kEnd}; + FatalLog(file, line, message, t, args.GetVal()...); + } + + template + RTC_NORETURN RTC_FORCE_INLINE static void CallCheckOp(const char* file, + const int line, + const char* message, + const Us&... args) { + static constexpr CheckArgType t[] = {CheckArgType::kCheckOp, Us::Type()..., + CheckArgType::kEnd}; + FatalLog(file, line, message, t, args.GetVal()...); + } +}; + +// Inductive case: We've already seen at least one << argument. The most recent +// one had type `T`, and the earlier ones had types `Ts`. +template +class LogStreamer final { + public: + RTC_FORCE_INLINE LogStreamer(T arg, const LogStreamer* prior) + : arg_(arg), prior_(prior) {} + + template ::value || + std::is_enum::value>::type* = nullptr> + RTC_FORCE_INLINE LogStreamer())), T, Ts...> + operator<<(U arg) const { + return LogStreamer())), T, Ts...>( + MakeVal(arg), this); + } + + template ::value && + !std::is_enum::value>::type* = nullptr> + RTC_FORCE_INLINE LogStreamer())), T, Ts...> + operator<<(const U& arg) const { + return LogStreamer())), T, Ts...>( + MakeVal(arg), this); + } + + template + RTC_NORETURN RTC_FORCE_INLINE void Call(const char* file, + const int line, + const char* message, + const Us&... args) const { + prior_->Call(file, line, message, arg_, args...); + } + + template + RTC_NORETURN RTC_FORCE_INLINE void CallCheckOp(const char* file, + const int line, + const char* message, + const Us&... args) const { + prior_->CallCheckOp(file, line, message, arg_, args...); + } + + private: + // The most recent argument. + T arg_; + + // Earlier arguments. + const LogStreamer* prior_; +}; + +template +class FatalLogCall final { + public: + FatalLogCall(const char* file, int line, const char* message) + : file_(file), line_(line), message_(message) {} + + // This can be any binary operator with precedence lower than <<. + template + RTC_NORETURN RTC_FORCE_INLINE void operator&( + const LogStreamer& streamer) { + isCheckOp ? streamer.CallCheckOp(file_, line_, message_) + : streamer.Call(file_, line_, message_); + } + + private: + const char* file_; + int line_; + const char* message_; +}; +} // namespace webrtc_checks_impl + +// The actual stream used isn't important. We reference |ignored| in the code +// but don't evaluate it; this is to avoid "unused variable" warnings (we do so +// in a particularly convoluted way with an extra ?: because that appears to be +// the simplest construct that keeps Visual Studio from complaining about +// condition being unused). +#define RTC_EAT_STREAM_PARAMETERS(ignored) \ + (true ? true : ((void)(ignored), true)) \ + ? static_cast(0) \ + : rtc::webrtc_checks_impl::FatalLogCall("", 0, "") & \ + rtc::webrtc_checks_impl::LogStreamer<>() + +// Call RTC_EAT_STREAM_PARAMETERS with an argument that fails to compile if +// values of the same types as |a| and |b| can't be compared with the given +// operation, and that would evaluate |a| and |b| if evaluated. +#define RTC_EAT_STREAM_PARAMETERS_OP(op, a, b) \ + RTC_EAT_STREAM_PARAMETERS(((void)rtc::Safe##op(a, b))) + +// RTC_CHECK dies with a fatal error if condition is not true. It is *not* +// controlled by NDEBUG or anything else, so the check will be executed +// regardless of compilation mode. +// +// We make sure RTC_CHECK et al. always evaluates |condition|, as +// doing RTC_CHECK(FunctionWithSideEffect()) is a common idiom. +#define RTC_CHECK(condition) \ + while (!(condition)) \ + rtc::webrtc_checks_impl::FatalLogCall(__FILE__, __LINE__, \ + #condition) & \ + rtc::webrtc_checks_impl::LogStreamer<>() + +// Helper macro for binary operators. +// Don't use this macro directly in your code, use RTC_CHECK_EQ et al below. +#define RTC_CHECK_OP(name, op, val1, val2) \ + while (!rtc::Safe##name((val1), (val2))) \ + rtc::webrtc_checks_impl::FatalLogCall(__FILE__, __LINE__, \ + #val1 " " #op " " #val2) & \ + rtc::webrtc_checks_impl::LogStreamer<>() << (val1) << (val2) + +#define RTC_CHECK_EQ(val1, val2) RTC_CHECK_OP(Eq, ==, val1, val2) +#define RTC_CHECK_NE(val1, val2) RTC_CHECK_OP(Ne, !=, val1, val2) +#define RTC_CHECK_LE(val1, val2) RTC_CHECK_OP(Le, <=, val1, val2) +#define RTC_CHECK_LT(val1, val2) RTC_CHECK_OP(Lt, <, val1, val2) +#define RTC_CHECK_GE(val1, val2) RTC_CHECK_OP(Ge, >=, val1, val2) +#define RTC_CHECK_GT(val1, val2) RTC_CHECK_OP(Gt, >, val1, val2) + +// The RTC_DCHECK macro is equivalent to RTC_CHECK except that it only generates +// code in debug builds. It does reference the condition parameter in all cases, +// though, so callers won't risk getting warnings about unused variables. +#if RTC_DCHECK_IS_ON +#define RTC_DCHECK(condition) RTC_CHECK(condition) +#define RTC_DCHECK_EQ(v1, v2) RTC_CHECK_EQ(v1, v2) +#define RTC_DCHECK_NE(v1, v2) RTC_CHECK_NE(v1, v2) +#define RTC_DCHECK_LE(v1, v2) RTC_CHECK_LE(v1, v2) +#define RTC_DCHECK_LT(v1, v2) RTC_CHECK_LT(v1, v2) +#define RTC_DCHECK_GE(v1, v2) RTC_CHECK_GE(v1, v2) +#define RTC_DCHECK_GT(v1, v2) RTC_CHECK_GT(v1, v2) +#else +#define RTC_DCHECK(condition) RTC_EAT_STREAM_PARAMETERS(condition) +#define RTC_DCHECK_EQ(v1, v2) RTC_EAT_STREAM_PARAMETERS_OP(Eq, v1, v2) +#define RTC_DCHECK_NE(v1, v2) RTC_EAT_STREAM_PARAMETERS_OP(Ne, v1, v2) +#define RTC_DCHECK_LE(v1, v2) RTC_EAT_STREAM_PARAMETERS_OP(Le, v1, v2) +#define RTC_DCHECK_LT(v1, v2) RTC_EAT_STREAM_PARAMETERS_OP(Lt, v1, v2) +#define RTC_DCHECK_GE(v1, v2) RTC_EAT_STREAM_PARAMETERS_OP(Ge, v1, v2) +#define RTC_DCHECK_GT(v1, v2) RTC_EAT_STREAM_PARAMETERS_OP(Gt, v1, v2) +#endif + +#define RTC_UNREACHABLE_CODE_HIT false +#define RTC_NOTREACHED() RTC_DCHECK(RTC_UNREACHABLE_CODE_HIT) + +// TODO(bugs.webrtc.org/8454): Add an RTC_ prefix or rename differently. +#define FATAL() \ + rtc::webrtc_checks_impl::FatalLogCall(__FILE__, __LINE__, \ + "FATAL()") & \ + rtc::webrtc_checks_impl::LogStreamer<>() + +// Performs the integer division a/b and returns the result. CHECKs that the +// remainder is zero. +template +inline T CheckedDivExact(T a, T b) { + RTC_CHECK_EQ(a % b, 0) << a << " is not evenly divisible by " << b; + return a / b; +} + +} // namespace rtc + +#else // __cplusplus not defined +// C version. Lacks many features compared to the C++ version, but usage +// guidelines are the same. + +#define RTC_CHECK(condition) \ + do { \ + if (!(condition)) { \ + rtc_FatalMessage(__FILE__, __LINE__, "CHECK failed: " #condition); \ + } \ + } while (0) + +#define RTC_CHECK_EQ(a, b) RTC_CHECK((a) == (b)) +#define RTC_CHECK_NE(a, b) RTC_CHECK((a) != (b)) +#define RTC_CHECK_LE(a, b) RTC_CHECK((a) <= (b)) +#define RTC_CHECK_LT(a, b) RTC_CHECK((a) < (b)) +#define RTC_CHECK_GE(a, b) RTC_CHECK((a) >= (b)) +#define RTC_CHECK_GT(a, b) RTC_CHECK((a) > (b)) + +#define RTC_DCHECK(condition) \ + do { \ + if (RTC_DCHECK_IS_ON && !(condition)) { \ + rtc_FatalMessage(__FILE__, __LINE__, "DCHECK failed: " #condition); \ + } \ + } while (0) + +#define RTC_DCHECK_EQ(a, b) RTC_DCHECK((a) == (b)) +#define RTC_DCHECK_NE(a, b) RTC_DCHECK((a) != (b)) +#define RTC_DCHECK_LE(a, b) RTC_DCHECK((a) <= (b)) +#define RTC_DCHECK_LT(a, b) RTC_DCHECK((a) < (b)) +#define RTC_DCHECK_GE(a, b) RTC_DCHECK((a) >= (b)) +#define RTC_DCHECK_GT(a, b) RTC_DCHECK((a) > (b)) + +#endif // __cplusplus + +#endif // RTC_BASE_CHECKS_H_ diff --git a/worker/deps/libwebrtc/libwebrtc/rtc_base/numerics/mod_ops.h b/worker/deps/libwebrtc/libwebrtc/rtc_base/numerics/mod_ops.h new file mode 100644 index 0000000000..65618b4876 --- /dev/null +++ b/worker/deps/libwebrtc/libwebrtc/rtc_base/numerics/mod_ops.h @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef RTC_BASE_NUMERICS_MOD_OPS_H_ +#define RTC_BASE_NUMERICS_MOD_OPS_H_ + +#include +#include + +#include "rtc_base/checks.h" + +namespace webrtc { + +template // NOLINT +inline unsigned long Add(unsigned long a, unsigned long b) { // NOLINT + RTC_DCHECK_LT(a, M); + unsigned long t = M - b % M; // NOLINT + unsigned long res = a - t; // NOLINT + if (t > a) + return res + M; + return res; +} + +template // NOLINT +inline unsigned long Subtract(unsigned long a, unsigned long b) { // NOLINT + RTC_DCHECK_LT(a, M); + unsigned long sub = b % M; // NOLINT + if (a < sub) + return M - (sub - a); + return a - sub; +} + +// Calculates the forward difference between two wrapping numbers. +// +// Example: +// uint8_t x = 253; +// uint8_t y = 2; +// +// ForwardDiff(x, y) == 5 +// +// 252 253 254 255 0 1 2 3 +// ################################################# +// | | x | | | | | y | | +// ################################################# +// |----->----->----->----->-----> +// +// ForwardDiff(y, x) == 251 +// +// 252 253 254 255 0 1 2 3 +// ################################################# +// | | x | | | | | y | | +// ################################################# +// -->-----> |----->--- +// +// If M > 0 then wrapping occurs at M, if M == 0 then wrapping occurs at the +// largest value representable by T. +template +inline typename std::enable_if<(M > 0), T>::type ForwardDiff(T a, T b) { + static_assert(std::is_unsigned::value, + "Type must be an unsigned integer."); + RTC_DCHECK_LT(a, M); + RTC_DCHECK_LT(b, M); + return a <= b ? b - a : M - (a - b); +} + +template +inline typename std::enable_if<(M == 0), T>::type ForwardDiff(T a, T b) { + static_assert(std::is_unsigned::value, + "Type must be an unsigned integer."); + return b - a; +} + +template +inline T ForwardDiff(T a, T b) { + return ForwardDiff(a, b); +} + +// Calculates the reverse difference between two wrapping numbers. +// +// Example: +// uint8_t x = 253; +// uint8_t y = 2; +// +// ReverseDiff(y, x) == 5 +// +// 252 253 254 255 0 1 2 3 +// ################################################# +// | | x | | | | | y | | +// ################################################# +// <-----<-----<-----<-----<-----| +// +// ReverseDiff(x, y) == 251 +// +// 252 253 254 255 0 1 2 3 +// ################################################# +// | | x | | | | | y | | +// ################################################# +// ---<-----| |<-----<-- +// +// If M > 0 then wrapping occurs at M, if M == 0 then wrapping occurs at the +// largest value representable by T. +template +inline typename std::enable_if<(M > 0), T>::type ReverseDiff(T a, T b) { + static_assert(std::is_unsigned::value, + "Type must be an unsigned integer."); + RTC_DCHECK_LT(a, M); + RTC_DCHECK_LT(b, M); + return b <= a ? a - b : M - (b - a); +} + +template +inline typename std::enable_if<(M == 0), T>::type ReverseDiff(T a, T b) { + static_assert(std::is_unsigned::value, + "Type must be an unsigned integer."); + return a - b; +} + +template +inline T ReverseDiff(T a, T b) { + return ReverseDiff(a, b); +} + +// Calculates the minimum distance between to wrapping numbers. +// +// The minimum distance is defined as min(ForwardDiff(a, b), ReverseDiff(a, b)) +template +inline T MinDiff(T a, T b) { + static_assert(std::is_unsigned::value, + "Type must be an unsigned integer."); + return std::min(ForwardDiff(a, b), ReverseDiff(a, b)); +} + +} // namespace webrtc + +#endif // RTC_BASE_NUMERICS_MOD_OPS_H_ diff --git a/worker/deps/libwebrtc/libwebrtc/rtc_base/numerics/sequence_number_util.h b/worker/deps/libwebrtc/libwebrtc/rtc_base/numerics/sequence_number_util.h new file mode 100644 index 0000000000..57efb5128d --- /dev/null +++ b/worker/deps/libwebrtc/libwebrtc/rtc_base/numerics/sequence_number_util.h @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef RTC_BASE_NUMERICS_SEQUENCE_NUMBER_UTIL_H_ +#define RTC_BASE_NUMERICS_SEQUENCE_NUMBER_UTIL_H_ + +#include +#include +#include + +#include "absl/types/optional.h" +#include "rtc_base/checks.h" +#include "rtc_base/numerics/mod_ops.h" + +namespace webrtc { + +// Test if the sequence number |a| is ahead or at sequence number |b|. +// +// If |M| is an even number and the two sequence numbers are at max distance +// from each other, then the sequence number with the highest value is +// considered to be ahead. +template +inline typename std::enable_if<(M > 0), bool>::type AheadOrAt(T a, T b) { + static_assert(std::is_unsigned::value, + "Type must be an unsigned integer."); + const T maxDist = M / 2; + if (!(M & 1) && MinDiff(a, b) == maxDist) + return b < a; + return ForwardDiff(b, a) <= maxDist; +} + +template +inline typename std::enable_if<(M == 0), bool>::type AheadOrAt(T a, T b) { + static_assert(std::is_unsigned::value, + "Type must be an unsigned integer."); + const T maxDist = std::numeric_limits::max() / 2 + T(1); + if (a - b == maxDist) + return b < a; + return ForwardDiff(b, a) < maxDist; +} + +template +inline bool AheadOrAt(T a, T b) { + return AheadOrAt(a, b); +} + +// Test if the sequence number |a| is ahead of sequence number |b|. +// +// If |M| is an even number and the two sequence numbers are at max distance +// from each other, then the sequence number with the highest value is +// considered to be ahead. +template +inline bool AheadOf(T a, T b) { + static_assert(std::is_unsigned::value, + "Type must be an unsigned integer."); + return a != b && AheadOrAt(a, b); +} + +// Comparator used to compare sequence numbers in a continuous fashion. +// +// WARNING! If used to sort sequence numbers of length M then the interval +// covered by the sequence numbers may not be larger than floor(M/2). +template +struct AscendingSeqNumComp { + bool operator()(T a, T b) const { return AheadOf(a, b); } +}; + +// Comparator used to compare sequence numbers in a continuous fashion. +// +// WARNING! If used to sort sequence numbers of length M then the interval +// covered by the sequence numbers may not be larger than floor(M/2). +template +struct DescendingSeqNumComp { + bool operator()(T a, T b) const { return AheadOf(b, a); } +}; + +// A sequence number unwrapper where the first unwrapped value equals the +// first value being unwrapped. +template +class SeqNumUnwrapper { + static_assert( + std::is_unsigned::value && + std::numeric_limits::max() < std::numeric_limits::max(), + "Type unwrapped must be an unsigned integer smaller than int64_t."); + + public: + int64_t Unwrap(T value) { + if (!last_value_) { + last_unwrapped_ = {value}; + } else { + last_unwrapped_ += ForwardDiff(*last_value_, value); + + if (!AheadOrAt(value, *last_value_)) { + constexpr int64_t kBackwardAdjustment = + M == 0 ? int64_t{std::numeric_limits::max()} + 1 : M; + last_unwrapped_ -= kBackwardAdjustment; + } + } + + last_value_ = value; + return last_unwrapped_; + } + + private: + int64_t last_unwrapped_ = 0; + absl::optional last_value_; +}; + +} // namespace webrtc + +#endif // RTC_BASE_NUMERICS_SEQUENCE_NUMBER_UTIL_H_ diff --git a/worker/deps/libwebrtc/libwebrtc/rtc_base/system/inline.h b/worker/deps/libwebrtc/libwebrtc/rtc_base/system/inline.h new file mode 100644 index 0000000000..f585d34ded --- /dev/null +++ b/worker/deps/libwebrtc/libwebrtc/rtc_base/system/inline.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef RTC_BASE_SYSTEM_INLINE_H_ +#define RTC_BASE_SYSTEM_INLINE_H_ + +#if defined(_MSC_VER) + +#define RTC_FORCE_INLINE __forceinline +#define RTC_NO_INLINE __declspec(noinline) + +#elif defined(__GNUC__) + +#define RTC_FORCE_INLINE __attribute__((__always_inline__)) +#define RTC_NO_INLINE __attribute__((__noinline__)) + +#else + +#define RTC_FORCE_INLINE +#define RTC_NO_INLINE + +#endif + +#endif // RTC_BASE_SYSTEM_INLINE_H_ diff --git a/worker/include/RTC/TransportCongestionControlServer.hpp b/worker/include/RTC/TransportCongestionControlServer.hpp index 5747d13d03..c01108d900 100644 --- a/worker/include/RTC/TransportCongestionControlServer.hpp +++ b/worker/include/RTC/TransportCongestionControlServer.hpp @@ -8,7 +8,9 @@ #include "RTC/RtpPacket.hpp" #include "handles/Timer.hpp" #include +#include #include +using namespace webrtc; namespace RTC { @@ -59,6 +61,13 @@ namespace RTC void SendTransportCcFeedback(); void MaySendLimitationRembFeedback(); void UpdatePacketLoss(double packetLoss); + void OnPacketArrival(uint16_t sequence_number, uint64_t arrival_time); + void SendPeriodicFeedbacks(); + int64_t BuildFeedbackPacket( + int64_t base_sequence_number, + std::map::const_iterator begin_iterator, // |begin_iterator| is inclusive. + std::map::const_iterator end_iterator // |end_iterator| is exclusive. + ); /* Pure virtual methods inherited from webrtc::RemoteBitrateEstimator::Listener. */ public: @@ -89,6 +98,12 @@ namespace RTC uint8_t unlimitedRembCounter{ 0u }; std::deque packetLossHistory; double packetLoss{ 0 }; + SeqNumUnwrapper unwrapper; + absl::optional periodicWindowStartSeq; + // Map unwrapped seq -> time. + std::map packetArrivalTimes; + // Use buffer policy similar to webrtc + bool useBufferPolicy{ true }; }; } // namespace RTC diff --git a/worker/src/RTC/TransportCongestionControlServer.cpp b/worker/src/RTC/TransportCongestionControlServer.cpp index 8c7a016949..b168090435 100644 --- a/worker/src/RTC/TransportCongestionControlServer.cpp +++ b/worker/src/RTC/TransportCongestionControlServer.cpp @@ -16,6 +16,9 @@ namespace RTC static constexpr uint64_t LimitationRembInterval{ 1500u }; // In ms. static constexpr uint8_t UnlimitedRembNumPackets{ 4u }; static constexpr size_t PacketLossHistogramLength{ 24 }; + static constexpr int64_t kMaxTimeMs{ std::numeric_limits::max() / 1000 }; + // Impossible to request feedback older than what can be represented by 15 bits. + static constexpr int kMaxNumberOfPackets{ (1 << 15) }; /* Instance methods. */ @@ -109,6 +112,143 @@ namespace RTC return this->packetLoss; } + void TransportCongestionControlServer::OnPacketArrival(uint16_t sequence_number, uint64_t arrival_time) + { + if (arrival_time > kMaxTimeMs) + { + MS_WARN_DEV("Arrival time out of bounds:%" PRIu64 "", arrival_time); + return; + } + int64_t seq = this->unwrapper.Unwrap(sequence_number); + if (seq <= 0) + { + MS_WARN_DEV("Invalid seq_num:%" PRIu16 ", unwrap-seq:%" PRId64 "", sequence_number, seq); + return; + } + if ( + this->periodicWindowStartSeq && + this->packetArrivalTimes.lower_bound(*this->periodicWindowStartSeq) == + this->packetArrivalTimes.end()) + { + // Start new feedback packet, cull old packets. + for (auto it = this->packetArrivalTimes.begin(); it != this->packetArrivalTimes.end() && + it->first < seq && + arrival_time - it->second >= 500;) + { + it = this->packetArrivalTimes.erase(it); + } + } + + if (!this->periodicWindowStartSeq || seq < *this->periodicWindowStartSeq) + { + this->periodicWindowStartSeq = seq; + } + + // We are only interested in the first time a packet is received. + if (this->packetArrivalTimes.find(seq) != this->packetArrivalTimes.end()) + return; + + this->packetArrivalTimes[seq] = arrival_time; + // Limit the range of sequence numbers to send feedback for. + auto first_arrival_time_to_keep = this->packetArrivalTimes.lower_bound( + this->packetArrivalTimes.rbegin()->first - kMaxNumberOfPackets); + if (first_arrival_time_to_keep != this->packetArrivalTimes.begin()) + { + this->packetArrivalTimes.erase(this->packetArrivalTimes.begin(), first_arrival_time_to_keep); + + // |this->packetArrivalTimes| cannot be empty since we just added one element + // and the last element is not deleted. + // RTC_DCHECK(!this->packetArrivalTimes.empty()); + this->periodicWindowStartSeq = this->packetArrivalTimes.begin()->first; + } + } + + void TransportCongestionControlServer::SendPeriodicFeedbacks() + { + // |this->periodicWindowStartSeq| is the first sequence number to include in the + // current feedback packet. Some older may still be in the map, in case a + // reordering happens and we need to retransmit them. + if (!this->periodicWindowStartSeq) + return; + + for (auto begin_iterator = this->packetArrivalTimes.lower_bound(*this->periodicWindowStartSeq); + begin_iterator != this->packetArrivalTimes.cend(); + begin_iterator = this->packetArrivalTimes.lower_bound(*this->periodicWindowStartSeq)) + { + int64_t next_sequence_number = BuildFeedbackPacket( + *this->periodicWindowStartSeq, begin_iterator, this->packetArrivalTimes.cend()); + // If build feedback packet fail, it will not be sent. + if (next_sequence_number < 0) + { + // Reset and create a new feedback packet for next periodic. + this->transportCcFeedbackPacket.reset(new RTC::RTCP::FeedbackRtpTransportPacket( + this->transportCcFeedbackSenderSsrc, this->transportCcFeedbackMediaSsrc)); + return; + } + + this->periodicWindowStartSeq = next_sequence_number; + SendTransportCcFeedback(); + // Note: Don't erase items from this->packetArrivalTimes after sending, in case + // they need to be re-sent after a reordering. Removal will be handled + // by OnPacketArrival once packets are too old. + } + } + + int64_t TransportCongestionControlServer::BuildFeedbackPacket( + int64_t base_sequence_number, + std::map::const_iterator begin_iterator, + std::map::const_iterator end_iterator) + { + // Set base sequence numer and reference time(arrival time of first received packet in the feedback). + uint64_t ref_timestamp_ms = begin_iterator->second; + this->transportCcFeedbackPacket->AddPacket( + static_cast((base_sequence_number - 1) & 0xFFFF), + ref_timestamp_ms, + this->maxRtcpPacketLen); + + // RTC_DCHECK(begin_iterator != end_iterator); + int64_t next_sequence_number = base_sequence_number; + for (auto it = begin_iterator; it != end_iterator; ++it) + { + auto result = this->transportCcFeedbackPacket->AddPacket( + static_cast(it->first & 0xFFFF), it->second, this->maxRtcpPacketLen); + if (RTC::RTCP::FeedbackRtpTransportPacket::AddPacketResult::SUCCESS != result) + { + // If we can't even add the first seq to the feedback packet, we won't be + // able to build it at all. + // RTC_CHECK(begin_iterator != it); + MS_WARN_DEV( + "Add fail! result:%" PRIu32 ", cur-seq:%" PRId64 ", next-seq:%" PRId64 + ", base-seq:%" PRId64 "", + static_cast(result), + it->first, + next_sequence_number, + base_sequence_number); + // When add not success then update startSeq to current seq. + this->periodicWindowStartSeq = it->first; + // Could not add timestamp, feedback packet max size exceeded. Return and + // try again with a fresh packet. + if (RTC::RTCP::FeedbackRtpTransportPacket::AddPacketResult::MAX_SIZE_EXCEEDED == result) + { + break; + } + else /*if (RTC::RTCP::FeedbackRtpTransportPacket::AddPacketResult::FATAL == result)*/ + { + // When add fail really then discard this feedback packet. + return -1; + } + } + next_sequence_number = it->first + 1; + // If the feedback packet is full, send it now. + if (this->transportCcFeedbackPacket->IsFull()) + { + MS_DEBUG_DEV("transport-cc feedback packet is full, sending feedback now"); + break; + } + } + return next_sequence_number; + } + void TransportCongestionControlServer::IncomingPacket(uint64_t nowMs, const RTC::RtpPacket* packet) { MS_TRACE(); @@ -131,50 +271,57 @@ namespace RTC this->transportCcFeedbackPacket->SetSenderSsrc(0u); this->transportCcFeedbackPacket->SetMediaSsrc(this->transportCcFeedbackMediaSsrc); - // Provide the feedback packet with the RTP packet info. If it fails, - // send current feedback and add the packet info to a new one. - auto result = - this->transportCcFeedbackPacket->AddPacket(wideSeqNumber, nowMs, this->maxRtcpPacketLen); - - switch (result) + if (this->useBufferPolicy) + { + this->OnPacketArrival(wideSeqNumber, nowMs); + } + else { - case RTC::RTCP::FeedbackRtpTransportPacket::AddPacketResult::SUCCESS: + // Provide the feedback packet with the RTP packet info. If it fails, + // send current feedback and add the packet info to a new one. + auto result = + this->transportCcFeedbackPacket->AddPacket(wideSeqNumber, nowMs, this->maxRtcpPacketLen); + + switch (result) { - // If the feedback packet is full, send it now. - if (this->transportCcFeedbackPacket->IsFull()) + case RTC::RTCP::FeedbackRtpTransportPacket::AddPacketResult::SUCCESS: { - MS_DEBUG_DEV("transport-cc feedback packet is full, sending feedback now"); + // If the feedback packet is full, send it now. + if (this->transportCcFeedbackPacket->IsFull()) + { + MS_DEBUG_DEV("transport-cc feedback packet is full, sending feedback now"); - SendTransportCcFeedback(); - } + SendTransportCcFeedback(); + } - break; - } + break; + } - case RTC::RTCP::FeedbackRtpTransportPacket::AddPacketResult::MAX_SIZE_EXCEEDED: - { - // Send ongoing feedback packet and add the new packet info to the - // regenerated one. - SendTransportCcFeedback(); + case RTC::RTCP::FeedbackRtpTransportPacket::AddPacketResult::MAX_SIZE_EXCEEDED: + { + // Send ongoing feedback packet and add the new packet info to the + // regenerated one. + SendTransportCcFeedback(); - this->transportCcFeedbackPacket->AddPacket(wideSeqNumber, nowMs, this->maxRtcpPacketLen); + this->transportCcFeedbackPacket->AddPacket(wideSeqNumber, nowMs, this->maxRtcpPacketLen); - break; - } + break; + } - case RTC::RTCP::FeedbackRtpTransportPacket::AddPacketResult::FATAL: - { - // Create a new feedback packet. - this->transportCcFeedbackPacket.reset(new RTC::RTCP::FeedbackRtpTransportPacket( - this->transportCcFeedbackSenderSsrc, this->transportCcFeedbackMediaSsrc)); + case RTC::RTCP::FeedbackRtpTransportPacket::AddPacketResult::FATAL: + { + // Create a new feedback packet. + this->transportCcFeedbackPacket.reset(new RTC::RTCP::FeedbackRtpTransportPacket( + this->transportCcFeedbackSenderSsrc, this->transportCcFeedbackMediaSsrc)); - // Use current packet count. - // NOTE: Do not increment it since the previous ongoing feedback - // packet was not sent. - this->transportCcFeedbackPacket->SetFeedbackPacketCount( - this->transportCcFeedbackPacketCount); + // Use current packet count. + // NOTE: Do not increment it since the previous ongoing feedback + // packet was not sent. + this->transportCcFeedbackPacket->SetFeedbackPacketCount( + this->transportCcFeedbackPacketCount); - break; + break; + } } } @@ -264,7 +411,7 @@ namespace RTC this->transportCcFeedbackPacket->SetFeedbackPacketCount(++this->transportCcFeedbackPacketCount); // Pass the latest packet info (if any) as pre base for the new feedback packet. - if (latestTimestamp > 0u) + if (latestTimestamp > 0u && !this->useBufferPolicy) { this->transportCcFeedbackPacket->AddPacket( latestWideSeqNumber, latestTimestamp, this->maxRtcpPacketLen); @@ -389,7 +536,14 @@ namespace RTC if (timer == this->transportCcFeedbackSendPeriodicTimer) { - SendTransportCcFeedback(); + if (this->useBufferPolicy) + { + SendPeriodicFeedbacks(); + } + else + { + SendTransportCcFeedback(); + } } } } // namespace RTC From 01ca264610ec2307ede43c2982e2a88d5222a4d3 Mon Sep 17 00:00:00 2001 From: kingqn0321 Date: Tue, 11 Jul 2023 11:32:36 +0800 Subject: [PATCH 2/2] Clean Code --- .../libwebrtc/libwebrtc/rtc_base/checks.h | 434 ------------------ .../libwebrtc/rtc_base/numerics/mod_ops.h | 14 +- .../rtc_base/numerics/sequence_number_util.h | 1 - .../libwebrtc/rtc_base/system/inline.h | 31 -- .../RTC/TransportCongestionControlServer.cpp | 25 +- 5 files changed, 29 insertions(+), 476 deletions(-) delete mode 100644 worker/deps/libwebrtc/libwebrtc/rtc_base/checks.h delete mode 100644 worker/deps/libwebrtc/libwebrtc/rtc_base/system/inline.h diff --git a/worker/deps/libwebrtc/libwebrtc/rtc_base/checks.h b/worker/deps/libwebrtc/libwebrtc/rtc_base/checks.h deleted file mode 100644 index dbdc004433..0000000000 --- a/worker/deps/libwebrtc/libwebrtc/rtc_base/checks.h +++ /dev/null @@ -1,434 +0,0 @@ -/* - * Copyright 2006 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef RTC_BASE_CHECKS_H_ -#define RTC_BASE_CHECKS_H_ - -// If you for some reson need to know if DCHECKs are on, test the value of -// RTC_DCHECK_IS_ON. (Test its value, not if it's defined; it'll always be -// defined, to either a true or a false value.) -#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON) -#define RTC_DCHECK_IS_ON 1 -#else -#define RTC_DCHECK_IS_ON 0 -#endif - -// Annotate a function that will not return control flow to the caller. -#if defined(_MSC_VER) -#define RTC_NORETURN __declspec(noreturn) -#elif defined(__GNUC__) -#define RTC_NORETURN __attribute__ ((__noreturn__)) -#else -#define RTC_NORETURN -#endif - -#ifdef __cplusplus -extern "C" { -#endif -RTC_NORETURN void rtc_FatalMessage(const char* file, int line, const char* msg); -#ifdef __cplusplus -} // extern "C" -#endif - -#ifdef __cplusplus -// C++ version. - -#include - -#include "absl/strings/string_view.h" -#include "rtc_base/numerics/safe_compare.h" -#include "rtc_base/system/inline.h" - -// The macros here print a message to stderr and abort under various -// conditions. All will accept additional stream messages. For example: -// RTC_DCHECK_EQ(foo, bar) << "I'm printed when foo != bar."; -// -// - RTC_CHECK(x) is an assertion that x is always true, and that if it isn't, -// it's better to terminate the process than to continue. During development, -// the reason that it's better to terminate might simply be that the error -// handling code isn't in place yet; in production, the reason might be that -// the author of the code truly believes that x will always be true, but that -// she recognizes that if she is wrong, abrupt and unpleasant process -// termination is still better than carrying on with the assumption violated. -// -// RTC_CHECK always evaluates its argument, so it's OK for x to have side -// effects. -// -// - RTC_DCHECK(x) is the same as RTC_CHECK(x)---an assertion that x is always -// true---except that x will only be evaluated in debug builds; in production -// builds, x is simply assumed to be true. This is useful if evaluating x is -// expensive and the expected cost of failing to detect the violated -// assumption is acceptable. You should not handle cases where a production -// build fails to spot a violated condition, even those that would result in -// crashes. If the code needs to cope with the error, make it cope, but don't -// call RTC_DCHECK; if the condition really can't occur, but you'd sleep -// better at night knowing that the process will suicide instead of carrying -// on in case you were wrong, use RTC_CHECK instead of RTC_DCHECK. -// -// RTC_DCHECK only evaluates its argument in debug builds, so if x has visible -// side effects, you need to write e.g. -// bool w = x; RTC_DCHECK(w); -// -// - RTC_CHECK_EQ, _NE, _GT, ..., and RTC_DCHECK_EQ, _NE, _GT, ... are -// specialized variants of RTC_CHECK and RTC_DCHECK that print prettier -// messages if the condition doesn't hold. Prefer them to raw RTC_CHECK and -// RTC_DCHECK. -// -// - FATAL() aborts unconditionally. -// -// TODO(ajm): Ideally, checks.h would be combined with logging.h, but -// consolidation with system_wrappers/logging.h should happen first. - -namespace rtc { -namespace webrtc_checks_impl { -enum class CheckArgType : int8_t { - kEnd = 0, - kInt, - kLong, - kLongLong, - kUInt, - kULong, - kULongLong, - kDouble, - kLongDouble, - kCharP, - kStdString, - kStringView, - kVoidP, - - // kCheckOp doesn't represent an argument type. Instead, it is sent as the - // first argument from RTC_CHECK_OP to make FatalLog use the next two - // arguments to build the special CHECK_OP error message - // (the "a == b (1 vs. 2)" bit). - kCheckOp, -}; - -RTC_NORETURN void FatalLog(const char* file, - int line, - const char* message, - const CheckArgType* fmt, - ...); - -// Wrapper for log arguments. Only ever make values of this type with the -// MakeVal() functions. -template -struct Val { - static constexpr CheckArgType Type() { return N; } - T GetVal() const { return val; } - T val; -}; - -// Case for when we need to construct a temp string and then print that. -// (We can't use Val -// because we need somewhere to store the temp string.) -struct ToStringVal { - static constexpr CheckArgType Type() { return CheckArgType::kStdString; } - const std::string* GetVal() const { return &val; } - std::string val; -}; - -inline Val MakeVal(int x) { - return {x}; -} -inline Val MakeVal(long x) { - return {x}; -} -inline Val MakeVal(long long x) { - return {x}; -} -inline Val MakeVal(unsigned int x) { - return {x}; -} -inline Val MakeVal(unsigned long x) { - return {x}; -} -inline Val MakeVal( - unsigned long long x) { - return {x}; -} - -inline Val MakeVal(double x) { - return {x}; -} -inline Val MakeVal(long double x) { - return {x}; -} - -inline Val MakeVal(const char* x) { - return {x}; -} -inline Val MakeVal( - const std::string& x) { - return {&x}; -} -inline Val MakeVal( - const absl::string_view& x) { - return {&x}; -} - -inline Val MakeVal(const void* x) { - return {x}; -} - -// The enum class types are not implicitly convertible to arithmetic types. -template < - typename T, - typename std::enable_if::value && - !std::is_arithmetic::value>::type* = nullptr> -inline decltype(MakeVal(std::declval::type>())) -MakeVal(T x) { - return {static_cast::type>(x)}; -} - -template ::type, - typename T2 = decltype(ToLogString(std::declval())), - typename std::enable_if::value>::type* = - nullptr> -ToStringVal MakeVal(const T& x) { - return {ToLogString(x)}; -} - -// Ephemeral type that represents the result of the logging << operator. -template -class LogStreamer; - -// Base case: Before the first << argument. -template <> -class LogStreamer<> final { - public: - template ::value || - std::is_enum::value>::type* = nullptr> - RTC_FORCE_INLINE LogStreamer()))> operator<<( - U arg) const { - return LogStreamer()))>(MakeVal(arg), - this); - } - - template ::value && - !std::is_enum::value>::type* = nullptr> - RTC_FORCE_INLINE LogStreamer()))> operator<<( - const U& arg) const { - return LogStreamer()))>(MakeVal(arg), - this); - } - - template - RTC_NORETURN RTC_FORCE_INLINE static void Call(const char* file, - const int line, - const char* message, - const Us&... args) { - static constexpr CheckArgType t[] = {Us::Type()..., CheckArgType::kEnd}; - FatalLog(file, line, message, t, args.GetVal()...); - } - - template - RTC_NORETURN RTC_FORCE_INLINE static void CallCheckOp(const char* file, - const int line, - const char* message, - const Us&... args) { - static constexpr CheckArgType t[] = {CheckArgType::kCheckOp, Us::Type()..., - CheckArgType::kEnd}; - FatalLog(file, line, message, t, args.GetVal()...); - } -}; - -// Inductive case: We've already seen at least one << argument. The most recent -// one had type `T`, and the earlier ones had types `Ts`. -template -class LogStreamer final { - public: - RTC_FORCE_INLINE LogStreamer(T arg, const LogStreamer* prior) - : arg_(arg), prior_(prior) {} - - template ::value || - std::is_enum::value>::type* = nullptr> - RTC_FORCE_INLINE LogStreamer())), T, Ts...> - operator<<(U arg) const { - return LogStreamer())), T, Ts...>( - MakeVal(arg), this); - } - - template ::value && - !std::is_enum::value>::type* = nullptr> - RTC_FORCE_INLINE LogStreamer())), T, Ts...> - operator<<(const U& arg) const { - return LogStreamer())), T, Ts...>( - MakeVal(arg), this); - } - - template - RTC_NORETURN RTC_FORCE_INLINE void Call(const char* file, - const int line, - const char* message, - const Us&... args) const { - prior_->Call(file, line, message, arg_, args...); - } - - template - RTC_NORETURN RTC_FORCE_INLINE void CallCheckOp(const char* file, - const int line, - const char* message, - const Us&... args) const { - prior_->CallCheckOp(file, line, message, arg_, args...); - } - - private: - // The most recent argument. - T arg_; - - // Earlier arguments. - const LogStreamer* prior_; -}; - -template -class FatalLogCall final { - public: - FatalLogCall(const char* file, int line, const char* message) - : file_(file), line_(line), message_(message) {} - - // This can be any binary operator with precedence lower than <<. - template - RTC_NORETURN RTC_FORCE_INLINE void operator&( - const LogStreamer& streamer) { - isCheckOp ? streamer.CallCheckOp(file_, line_, message_) - : streamer.Call(file_, line_, message_); - } - - private: - const char* file_; - int line_; - const char* message_; -}; -} // namespace webrtc_checks_impl - -// The actual stream used isn't important. We reference |ignored| in the code -// but don't evaluate it; this is to avoid "unused variable" warnings (we do so -// in a particularly convoluted way with an extra ?: because that appears to be -// the simplest construct that keeps Visual Studio from complaining about -// condition being unused). -#define RTC_EAT_STREAM_PARAMETERS(ignored) \ - (true ? true : ((void)(ignored), true)) \ - ? static_cast(0) \ - : rtc::webrtc_checks_impl::FatalLogCall("", 0, "") & \ - rtc::webrtc_checks_impl::LogStreamer<>() - -// Call RTC_EAT_STREAM_PARAMETERS with an argument that fails to compile if -// values of the same types as |a| and |b| can't be compared with the given -// operation, and that would evaluate |a| and |b| if evaluated. -#define RTC_EAT_STREAM_PARAMETERS_OP(op, a, b) \ - RTC_EAT_STREAM_PARAMETERS(((void)rtc::Safe##op(a, b))) - -// RTC_CHECK dies with a fatal error if condition is not true. It is *not* -// controlled by NDEBUG or anything else, so the check will be executed -// regardless of compilation mode. -// -// We make sure RTC_CHECK et al. always evaluates |condition|, as -// doing RTC_CHECK(FunctionWithSideEffect()) is a common idiom. -#define RTC_CHECK(condition) \ - while (!(condition)) \ - rtc::webrtc_checks_impl::FatalLogCall(__FILE__, __LINE__, \ - #condition) & \ - rtc::webrtc_checks_impl::LogStreamer<>() - -// Helper macro for binary operators. -// Don't use this macro directly in your code, use RTC_CHECK_EQ et al below. -#define RTC_CHECK_OP(name, op, val1, val2) \ - while (!rtc::Safe##name((val1), (val2))) \ - rtc::webrtc_checks_impl::FatalLogCall(__FILE__, __LINE__, \ - #val1 " " #op " " #val2) & \ - rtc::webrtc_checks_impl::LogStreamer<>() << (val1) << (val2) - -#define RTC_CHECK_EQ(val1, val2) RTC_CHECK_OP(Eq, ==, val1, val2) -#define RTC_CHECK_NE(val1, val2) RTC_CHECK_OP(Ne, !=, val1, val2) -#define RTC_CHECK_LE(val1, val2) RTC_CHECK_OP(Le, <=, val1, val2) -#define RTC_CHECK_LT(val1, val2) RTC_CHECK_OP(Lt, <, val1, val2) -#define RTC_CHECK_GE(val1, val2) RTC_CHECK_OP(Ge, >=, val1, val2) -#define RTC_CHECK_GT(val1, val2) RTC_CHECK_OP(Gt, >, val1, val2) - -// The RTC_DCHECK macro is equivalent to RTC_CHECK except that it only generates -// code in debug builds. It does reference the condition parameter in all cases, -// though, so callers won't risk getting warnings about unused variables. -#if RTC_DCHECK_IS_ON -#define RTC_DCHECK(condition) RTC_CHECK(condition) -#define RTC_DCHECK_EQ(v1, v2) RTC_CHECK_EQ(v1, v2) -#define RTC_DCHECK_NE(v1, v2) RTC_CHECK_NE(v1, v2) -#define RTC_DCHECK_LE(v1, v2) RTC_CHECK_LE(v1, v2) -#define RTC_DCHECK_LT(v1, v2) RTC_CHECK_LT(v1, v2) -#define RTC_DCHECK_GE(v1, v2) RTC_CHECK_GE(v1, v2) -#define RTC_DCHECK_GT(v1, v2) RTC_CHECK_GT(v1, v2) -#else -#define RTC_DCHECK(condition) RTC_EAT_STREAM_PARAMETERS(condition) -#define RTC_DCHECK_EQ(v1, v2) RTC_EAT_STREAM_PARAMETERS_OP(Eq, v1, v2) -#define RTC_DCHECK_NE(v1, v2) RTC_EAT_STREAM_PARAMETERS_OP(Ne, v1, v2) -#define RTC_DCHECK_LE(v1, v2) RTC_EAT_STREAM_PARAMETERS_OP(Le, v1, v2) -#define RTC_DCHECK_LT(v1, v2) RTC_EAT_STREAM_PARAMETERS_OP(Lt, v1, v2) -#define RTC_DCHECK_GE(v1, v2) RTC_EAT_STREAM_PARAMETERS_OP(Ge, v1, v2) -#define RTC_DCHECK_GT(v1, v2) RTC_EAT_STREAM_PARAMETERS_OP(Gt, v1, v2) -#endif - -#define RTC_UNREACHABLE_CODE_HIT false -#define RTC_NOTREACHED() RTC_DCHECK(RTC_UNREACHABLE_CODE_HIT) - -// TODO(bugs.webrtc.org/8454): Add an RTC_ prefix or rename differently. -#define FATAL() \ - rtc::webrtc_checks_impl::FatalLogCall(__FILE__, __LINE__, \ - "FATAL()") & \ - rtc::webrtc_checks_impl::LogStreamer<>() - -// Performs the integer division a/b and returns the result. CHECKs that the -// remainder is zero. -template -inline T CheckedDivExact(T a, T b) { - RTC_CHECK_EQ(a % b, 0) << a << " is not evenly divisible by " << b; - return a / b; -} - -} // namespace rtc - -#else // __cplusplus not defined -// C version. Lacks many features compared to the C++ version, but usage -// guidelines are the same. - -#define RTC_CHECK(condition) \ - do { \ - if (!(condition)) { \ - rtc_FatalMessage(__FILE__, __LINE__, "CHECK failed: " #condition); \ - } \ - } while (0) - -#define RTC_CHECK_EQ(a, b) RTC_CHECK((a) == (b)) -#define RTC_CHECK_NE(a, b) RTC_CHECK((a) != (b)) -#define RTC_CHECK_LE(a, b) RTC_CHECK((a) <= (b)) -#define RTC_CHECK_LT(a, b) RTC_CHECK((a) < (b)) -#define RTC_CHECK_GE(a, b) RTC_CHECK((a) >= (b)) -#define RTC_CHECK_GT(a, b) RTC_CHECK((a) > (b)) - -#define RTC_DCHECK(condition) \ - do { \ - if (RTC_DCHECK_IS_ON && !(condition)) { \ - rtc_FatalMessage(__FILE__, __LINE__, "DCHECK failed: " #condition); \ - } \ - } while (0) - -#define RTC_DCHECK_EQ(a, b) RTC_DCHECK((a) == (b)) -#define RTC_DCHECK_NE(a, b) RTC_DCHECK((a) != (b)) -#define RTC_DCHECK_LE(a, b) RTC_DCHECK((a) <= (b)) -#define RTC_DCHECK_LT(a, b) RTC_DCHECK((a) < (b)) -#define RTC_DCHECK_GE(a, b) RTC_DCHECK((a) >= (b)) -#define RTC_DCHECK_GT(a, b) RTC_DCHECK((a) > (b)) - -#endif // __cplusplus - -#endif // RTC_BASE_CHECKS_H_ diff --git a/worker/deps/libwebrtc/libwebrtc/rtc_base/numerics/mod_ops.h b/worker/deps/libwebrtc/libwebrtc/rtc_base/numerics/mod_ops.h index 65618b4876..f1c8b677b2 100644 --- a/worker/deps/libwebrtc/libwebrtc/rtc_base/numerics/mod_ops.h +++ b/worker/deps/libwebrtc/libwebrtc/rtc_base/numerics/mod_ops.h @@ -14,13 +14,13 @@ #include #include -#include "rtc_base/checks.h" +// #include "rtc_base/checks.h" namespace webrtc { template // NOLINT inline unsigned long Add(unsigned long a, unsigned long b) { // NOLINT - RTC_DCHECK_LT(a, M); + // RTC_DCHECK_LT(a, M); unsigned long t = M - b % M; // NOLINT unsigned long res = a - t; // NOLINT if (t > a) @@ -30,7 +30,7 @@ inline unsigned long Add(unsigned long a, unsigned long b) { // NOLINT template // NOLINT inline unsigned long Subtract(unsigned long a, unsigned long b) { // NOLINT - RTC_DCHECK_LT(a, M); + // RTC_DCHECK_LT(a, M); unsigned long sub = b % M; // NOLINT if (a < sub) return M - (sub - a); @@ -65,8 +65,8 @@ template inline typename std::enable_if<(M > 0), T>::type ForwardDiff(T a, T b) { static_assert(std::is_unsigned::value, "Type must be an unsigned integer."); - RTC_DCHECK_LT(a, M); - RTC_DCHECK_LT(b, M); + // RTC_DCHECK_LT(a, M); + // RTC_DCHECK_LT(b, M); return a <= b ? b - a : M - (a - b); } @@ -110,8 +110,8 @@ template inline typename std::enable_if<(M > 0), T>::type ReverseDiff(T a, T b) { static_assert(std::is_unsigned::value, "Type must be an unsigned integer."); - RTC_DCHECK_LT(a, M); - RTC_DCHECK_LT(b, M); + // RTC_DCHECK_LT(a, M); + // RTC_DCHECK_LT(b, M); return b <= a ? a - b : M - (b - a); } diff --git a/worker/deps/libwebrtc/libwebrtc/rtc_base/numerics/sequence_number_util.h b/worker/deps/libwebrtc/libwebrtc/rtc_base/numerics/sequence_number_util.h index 57efb5128d..0fa689f9c7 100644 --- a/worker/deps/libwebrtc/libwebrtc/rtc_base/numerics/sequence_number_util.h +++ b/worker/deps/libwebrtc/libwebrtc/rtc_base/numerics/sequence_number_util.h @@ -16,7 +16,6 @@ #include #include "absl/types/optional.h" -#include "rtc_base/checks.h" #include "rtc_base/numerics/mod_ops.h" namespace webrtc { diff --git a/worker/deps/libwebrtc/libwebrtc/rtc_base/system/inline.h b/worker/deps/libwebrtc/libwebrtc/rtc_base/system/inline.h deleted file mode 100644 index f585d34ded..0000000000 --- a/worker/deps/libwebrtc/libwebrtc/rtc_base/system/inline.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef RTC_BASE_SYSTEM_INLINE_H_ -#define RTC_BASE_SYSTEM_INLINE_H_ - -#if defined(_MSC_VER) - -#define RTC_FORCE_INLINE __forceinline -#define RTC_NO_INLINE __declspec(noinline) - -#elif defined(__GNUC__) - -#define RTC_FORCE_INLINE __attribute__((__always_inline__)) -#define RTC_NO_INLINE __attribute__((__noinline__)) - -#else - -#define RTC_FORCE_INLINE -#define RTC_NO_INLINE - -#endif - -#endif // RTC_BASE_SYSTEM_INLINE_H_ diff --git a/worker/src/RTC/TransportCongestionControlServer.cpp b/worker/src/RTC/TransportCongestionControlServer.cpp index b168090435..c8d33229da 100644 --- a/worker/src/RTC/TransportCongestionControlServer.cpp +++ b/worker/src/RTC/TransportCongestionControlServer.cpp @@ -116,15 +116,20 @@ namespace RTC { if (arrival_time > kMaxTimeMs) { - MS_WARN_DEV("Arrival time out of bounds:%" PRIu64 "", arrival_time); + MS_WARN_DEV("arrival time out of bounds:%" PRIu64 "", arrival_time); + return; } + int64_t seq = this->unwrapper.Unwrap(sequence_number); + if (seq <= 0) { - MS_WARN_DEV("Invalid seq_num:%" PRIu16 ", unwrap-seq:%" PRId64 "", sequence_number, seq); + MS_WARN_DEV("invalid seq_num:%" PRIu16 ", unwrap-seq:%" PRId64 "", sequence_number, seq); + return; } + if ( this->periodicWindowStartSeq && this->packetArrivalTimes.lower_bound(*this->periodicWindowStartSeq) == @@ -146,12 +151,15 @@ namespace RTC // We are only interested in the first time a packet is received. if (this->packetArrivalTimes.find(seq) != this->packetArrivalTimes.end()) + { return; + } this->packetArrivalTimes[seq] = arrival_time; // Limit the range of sequence numbers to send feedback for. auto first_arrival_time_to_keep = this->packetArrivalTimes.lower_bound( this->packetArrivalTimes.rbegin()->first - kMaxNumberOfPackets); + if (first_arrival_time_to_keep != this->packetArrivalTimes.begin()) { this->packetArrivalTimes.erase(this->packetArrivalTimes.begin(), first_arrival_time_to_keep); @@ -169,7 +177,9 @@ namespace RTC // current feedback packet. Some older may still be in the map, in case a // reordering happens and we need to retransmit them. if (!this->periodicWindowStartSeq) + { return; + } for (auto begin_iterator = this->packetArrivalTimes.lower_bound(*this->periodicWindowStartSeq); begin_iterator != this->packetArrivalTimes.cend(); @@ -177,12 +187,14 @@ namespace RTC { int64_t next_sequence_number = BuildFeedbackPacket( *this->periodicWindowStartSeq, begin_iterator, this->packetArrivalTimes.cend()); + // If build feedback packet fail, it will not be sent. if (next_sequence_number < 0) { // Reset and create a new feedback packet for next periodic. this->transportCcFeedbackPacket.reset(new RTC::RTCP::FeedbackRtpTransportPacket( this->transportCcFeedbackSenderSsrc, this->transportCcFeedbackMediaSsrc)); + return; } @@ -208,17 +220,19 @@ namespace RTC // RTC_DCHECK(begin_iterator != end_iterator); int64_t next_sequence_number = base_sequence_number; + for (auto it = begin_iterator; it != end_iterator; ++it) { auto result = this->transportCcFeedbackPacket->AddPacket( static_cast(it->first & 0xFFFF), it->second, this->maxRtcpPacketLen); + if (RTC::RTCP::FeedbackRtpTransportPacket::AddPacketResult::SUCCESS != result) { // If we can't even add the first seq to the feedback packet, we won't be // able to build it at all. // RTC_CHECK(begin_iterator != it); MS_WARN_DEV( - "Add fail! result:%" PRIu32 ", cur-seq:%" PRId64 ", next-seq:%" PRId64 + "add fail! result:%" PRIu32 ", cur-seq:%" PRId64 ", next-seq:%" PRId64 ", base-seq:%" PRId64 "", static_cast(result), it->first, @@ -226,6 +240,7 @@ namespace RTC base_sequence_number); // When add not success then update startSeq to current seq. this->periodicWindowStartSeq = it->first; + // Could not add timestamp, feedback packet max size exceeded. Return and // try again with a fresh packet. if (RTC::RTCP::FeedbackRtpTransportPacket::AddPacketResult::MAX_SIZE_EXCEEDED == result) @@ -238,14 +253,18 @@ namespace RTC return -1; } } + next_sequence_number = it->first + 1; + // If the feedback packet is full, send it now. if (this->transportCcFeedbackPacket->IsFull()) { MS_DEBUG_DEV("transport-cc feedback packet is full, sending feedback now"); + break; } } + return next_sequence_number; }