Skip to content
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

Open
wants to merge 3 commits into
base: v3
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
142 changes: 142 additions & 0 deletions worker/deps/libwebrtc/libwebrtc/rtc_base/numerics/mod_ops.h
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.");
Comment on lines +66 to +67
Copy link
Member

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:

Suggested change
static_assert(std::is_unsigned<T>::value,
"Type must be an unsigned integer.");
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_
15 changes: 15 additions & 0 deletions worker/include/RTC/TransportCongestionControlServer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down Expand Up @@ -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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't use such a |xxxx| anywhere. Also, variables in mediasoup must be in lowcase.

Suggested change
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.
std::map<int64_t, uint64_t>::const_iterator beginIterator, // It is inclusive.
std::map<int64_t, uint64_t>::const_iterator endIterator // It is exclusive.

);
Comment on lines +64 to +70
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In mediasoup we use camelCase for variables and function arguments.

  • sequence_number => sequenceNumber
  • etc


/* Pure virtual methods inherited from webrtc::RemoteBitrateEstimator::Listener. */
public:
Expand Down Expand Up @@ -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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dot at the end of comments.

Suggested change
// Use buffer policy similar to webrtc
// Use buffer policy similar to webrtc.

bool useBufferPolicy{ true };
};
} // namespace RTC

Expand Down