-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add webrtc transport-cc feedback mechanism #1115
base: v3
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 <algorithm> | ||
#include <type_traits> | ||
|
||
// #include "rtc_base/checks.h" | ||
|
||
namespace webrtc { | ||
|
||
template <unsigned long M> // 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 <unsigned long M> // 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 <typename T, T M> | ||
inline typename std::enable_if<(M > 0), T>::type ForwardDiff(T a, T b) { | ||
static_assert(std::is_unsigned<T>::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 <typename T, T M> | ||
inline typename std::enable_if<(M == 0), T>::type ForwardDiff(T a, T b) { | ||
static_assert(std::is_unsigned<T>::value, | ||
"Type must be an unsigned integer."); | ||
return b - a; | ||
} | ||
|
||
template <typename T> | ||
inline T ForwardDiff(T a, T b) { | ||
return ForwardDiff<T, 0>(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 <typename T, T M> | ||
inline typename std::enable_if<(M > 0), T>::type ReverseDiff(T a, T b) { | ||
static_assert(std::is_unsigned<T>::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 <typename T, T M> | ||
inline typename std::enable_if<(M == 0), T>::type ReverseDiff(T a, T b) { | ||
static_assert(std::is_unsigned<T>::value, | ||
"Type must be an unsigned integer."); | ||
return a - b; | ||
} | ||
|
||
template <typename T> | ||
inline T ReverseDiff(T a, T b) { | ||
return ReverseDiff<T, 0>(a, b); | ||
} | ||
|
||
// Calculates the minimum distance between to wrapping numbers. | ||
// | ||
// The minimum distance is defined as min(ForwardDiff(a, b), ReverseDiff(a, b)) | ||
template <typename T, T M = 0> | ||
inline T MinDiff(T a, T b) { | ||
static_assert(std::is_unsigned<T>::value, | ||
"Type must be an unsigned integer."); | ||
return std::min(ForwardDiff<T, M>(a, b), ReverseDiff<T, M>(a, b)); | ||
} | ||
|
||
} // namespace webrtc | ||
|
||
#endif // RTC_BASE_NUMERICS_MOD_OPS_H_ |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
/* | ||
* 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 <stdint.h> | ||
#include <limits> | ||
#include <type_traits> | ||
|
||
#include "absl/types/optional.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 <typename T, T M> | ||
inline typename std::enable_if<(M > 0), bool>::type AheadOrAt(T a, T b) { | ||
static_assert(std::is_unsigned<T>::value, | ||
"Type must be an unsigned integer."); | ||
const T maxDist = M / 2; | ||
if (!(M & 1) && MinDiff<T, M>(a, b) == maxDist) | ||
return b < a; | ||
return ForwardDiff<T, M>(b, a) <= maxDist; | ||
} | ||
|
||
template <typename T, T M> | ||
inline typename std::enable_if<(M == 0), bool>::type AheadOrAt(T a, T b) { | ||
static_assert(std::is_unsigned<T>::value, | ||
"Type must be an unsigned integer."); | ||
const T maxDist = std::numeric_limits<T>::max() / 2 + T(1); | ||
if (a - b == maxDist) | ||
return b < a; | ||
return ForwardDiff(b, a) < maxDist; | ||
} | ||
|
||
template <typename T> | ||
inline bool AheadOrAt(T a, T b) { | ||
return AheadOrAt<T, 0>(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 <typename T, T M = 0> | ||
inline bool AheadOf(T a, T b) { | ||
static_assert(std::is_unsigned<T>::value, | ||
"Type must be an unsigned integer."); | ||
return a != b && AheadOrAt<T, M>(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 <typename T, T M = 0> | ||
struct AscendingSeqNumComp { | ||
bool operator()(T a, T b) const { return AheadOf<T, M>(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 <typename T, T M = 0> | ||
struct DescendingSeqNumComp { | ||
bool operator()(T a, T b) const { return AheadOf<T, M>(b, a); } | ||
}; | ||
|
||
// A sequence number unwrapper where the first unwrapped value equals the | ||
// first value being unwrapped. | ||
template <typename T, T M = 0> | ||
class SeqNumUnwrapper { | ||
static_assert( | ||
std::is_unsigned<T>::value && | ||
std::numeric_limits<T>::max() < std::numeric_limits<int64_t>::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<T, M>(*last_value_, value); | ||
|
||
if (!AheadOrAt<T, M>(value, *last_value_)) { | ||
constexpr int64_t kBackwardAdjustment = | ||
M == 0 ? int64_t{std::numeric_limits<T>::max()} + 1 : M; | ||
last_unwrapped_ -= kBackwardAdjustment; | ||
} | ||
} | ||
|
||
last_value_ = value; | ||
return last_unwrapped_; | ||
} | ||
|
||
private: | ||
int64_t last_unwrapped_ = 0; | ||
absl::optional<T> last_value_; | ||
}; | ||
|
||
} // namespace webrtc | ||
|
||
#endif // RTC_BASE_NUMERICS_SEQUENCE_NUMBER_UTIL_H_ |
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
@@ -8,7 +8,9 @@ | |||||||||
#include "RTC/RtpPacket.hpp" | ||||||||||
#include "handles/Timer.hpp" | ||||||||||
#include <libwebrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.h> | ||||||||||
#include <libwebrtc/rtc_base/numerics/sequence_number_util.h> | ||||||||||
#include <deque> | ||||||||||
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<int64_t, uint64_t>::const_iterator begin_iterator, // |begin_iterator| is inclusive. | ||||||||||
std::map<int64_t, uint64_t>::const_iterator end_iterator // |end_iterator| is exclusive. | ||||||||||
Comment on lines
+68
to
+69
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We don't use such a
Suggested change
|
||||||||||
); | ||||||||||
Comment on lines
+64
to
+70
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In mediasoup we use camelCase for variables and function arguments.
|
||||||||||
|
||||||||||
/* Pure virtual methods inherited from webrtc::RemoteBitrateEstimator::Listener. */ | ||||||||||
public: | ||||||||||
|
@@ -89,6 +98,12 @@ namespace RTC | |||||||||
uint8_t unlimitedRembCounter{ 0u }; | ||||||||||
std::deque<double> packetLossHistory; | ||||||||||
double packetLoss{ 0 }; | ||||||||||
SeqNumUnwrapper<uint16_t> unwrapper; | ||||||||||
absl::optional<int64_t> periodicWindowStartSeq; | ||||||||||
// Map unwrapped seq -> time. | ||||||||||
std::map<int64_t, uint64_t> packetArrivalTimes; | ||||||||||
// Use buffer policy similar to webrtc | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Dot at the end of comments.
Suggested change
|
||||||||||
bool useBufferPolicy{ true }; | ||||||||||
}; | ||||||||||
} // namespace RTC | ||||||||||
|
||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Logs in mediasoup (even in libwebrtc imported code) must adhere to the project syntax (must start with lowcase letter and must not include dot at the end). This change must be done in many files in this PR: