mirror of
https://github.com/kunkundi/crossdesk.git
synced 2025-10-27 04:35:34 +08:00
[feat] implementation for qos module
This commit is contained in:
@@ -90,10 +90,10 @@ class ArrayView final : public array_view_internal::ArrayViewBase<T, Size> {
|
||||
template <typename U>
|
||||
ArrayView(U* data, size_t size)
|
||||
: array_view_internal::ArrayViewBase<T, Size>::ArrayViewBase(data, size) {
|
||||
RTC_DCHECK_EQ(size == 0 ? nullptr : data, this->data());
|
||||
RTC_DCHECK_EQ(size, this->size());
|
||||
RTC_DCHECK_EQ(!this->data(),
|
||||
this->size() == 0); // data is null iff size == 0.
|
||||
// RTC_DCHECK_EQ(size == 0 ? nullptr : data, this->data());
|
||||
// RTC_DCHECK_EQ(size, this->size());
|
||||
// RTC_DCHECK_EQ(!this->data(),
|
||||
// this->size() == 0); // data is null iff size == 0.
|
||||
}
|
||||
|
||||
// Construct an empty ArrayView. Note that fixed-size ArrayViews of size > 0
|
||||
@@ -105,7 +105,7 @@ class ArrayView final : public array_view_internal::ArrayViewBase<T, Size> {
|
||||
: ArrayView(static_cast<T*>(nullptr), size) {
|
||||
static_assert(Size == 0 || Size == array_view_internal::kArrayViewVarSize,
|
||||
"");
|
||||
RTC_DCHECK_EQ(0, size);
|
||||
// RTC_DCHECK_EQ(0, size);
|
||||
}
|
||||
|
||||
// Construct an ArrayView from a C-style array.
|
||||
@@ -182,8 +182,8 @@ class ArrayView final : public array_view_internal::ArrayViewBase<T, Size> {
|
||||
// const, because the ArrayView doesn't own the array. (To prevent mutation,
|
||||
// use a const element type.)
|
||||
T& operator[](size_t idx) const {
|
||||
RTC_DCHECK_LT(idx, this->size());
|
||||
RTC_DCHECK(this->data());
|
||||
// RTC_DCHECK_LT(idx, this->size());
|
||||
// RTC_DCHECK(this->data());
|
||||
return this->data()[idx];
|
||||
}
|
||||
T* begin() const { return this->data(); }
|
||||
|
||||
31
src/common/enc_mark.h
Normal file
31
src/common/enc_mark.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* @Author: DI JUNKUN
|
||||
* @Date: 2025-01-08
|
||||
* Copyright (c) 2025 by DI JUNKUN, All Rights Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _ENC_MARK_H_
|
||||
#define _ENC_MARK_H_
|
||||
|
||||
// L4S Explicit Congestion Notification (ECN) .
|
||||
// https://www.rfc-editor.org/rfc/rfc9331.html ECT stands for ECN-Capable
|
||||
// Transport and CE stands for Congestion Experienced.
|
||||
|
||||
// RFC-3168, Section 5
|
||||
// +-----+-----+
|
||||
// | ECN FIELD |
|
||||
// +-----+-----+
|
||||
// ECT CE [Obsolete] RFC 2481 names for the ECN bits.
|
||||
// 0 0 Not-ECT
|
||||
// 0 1 ECT(1)
|
||||
// 1 0 ECT(0)
|
||||
// 1 1 CE
|
||||
|
||||
enum class EcnMarking {
|
||||
kNotEct = 0, // Not ECN-Capable Transport
|
||||
kEct1 = 1, // ECN-Capable Transport
|
||||
kEct0 = 2, // Not used by L4s (or webrtc.)
|
||||
kCe = 3, // Congestion experienced
|
||||
};
|
||||
|
||||
#endif
|
||||
130
src/common/mod_ops.h
Normal file
130
src/common/mod_ops.h
Normal file
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* @Author: DI JUNKUN
|
||||
* @Date: 2025-01-08
|
||||
* Copyright (c) 2025 by DI JUNKUN, All Rights Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _MOD_OPS_H_
|
||||
#define _MOD_OPS_H_
|
||||
|
||||
#include <algorithm>
|
||||
#include <type_traits>
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
#endif
|
||||
73
src/common/sequence_number_unwrapper.h
Normal file
73
src/common/sequence_number_unwrapper.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* @Author: DI JUNKUN
|
||||
* @Date: 2025-01-08
|
||||
* Copyright (c) 2025 by DI JUNKUN, All Rights Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _SEQUENCE_NUMBER_UNWRAPPER_H_
|
||||
#define _SEQUENCE_NUMBER_UNWRAPPER_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <limits>
|
||||
#include <optional>
|
||||
#include <type_traits>
|
||||
|
||||
#include "sequence_number_util.h"
|
||||
|
||||
// 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:
|
||||
// Unwraps `value` and updates the internal state of the unwrapper.
|
||||
int64_t Unwrap(T value) {
|
||||
if (!last_value_) {
|
||||
last_unwrapped_ = {value};
|
||||
} else {
|
||||
last_unwrapped_ += Delta(*last_value_, value);
|
||||
}
|
||||
|
||||
last_value_ = value;
|
||||
return last_unwrapped_;
|
||||
}
|
||||
|
||||
// Returns the `value` without updating the internal state of the unwrapper.
|
||||
int64_t PeekUnwrap(T value) const {
|
||||
if (!last_value_) {
|
||||
return value;
|
||||
}
|
||||
return last_unwrapped_ + Delta(*last_value_, value);
|
||||
}
|
||||
|
||||
// Resets the unwrapper to its initial state. Unwrapped sequence numbers will
|
||||
// being at 0 after resetting.
|
||||
void Reset() {
|
||||
last_unwrapped_ = 0;
|
||||
last_value_.reset();
|
||||
}
|
||||
|
||||
private:
|
||||
static int64_t Delta(T last_value, T new_value) {
|
||||
constexpr int64_t kBackwardAdjustment =
|
||||
M == 0 ? int64_t{std::numeric_limits<T>::max()} + 1 : M;
|
||||
int64_t result = ForwardDiff<T, M>(last_value, new_value);
|
||||
if (!AheadOrAt<T, M>(new_value, last_value)) {
|
||||
result -= kBackwardAdjustment;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int64_t last_unwrapped_ = 0;
|
||||
std::optional<T> last_value_;
|
||||
};
|
||||
|
||||
using RtpTimestampUnwrapper = SeqNumUnwrapper<uint32_t>;
|
||||
using RtpSequenceNumberUnwrapper = SeqNumUnwrapper<uint16_t>;
|
||||
|
||||
#endif
|
||||
73
src/common/sequence_number_util.h
Normal file
73
src/common/sequence_number_util.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* @Author: DI JUNKUN
|
||||
* @Date: 2025-01-08
|
||||
* Copyright (c) 2025 by DI JUNKUN, All Rights Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _SEQUENCE_NUMBER_UTIL_H_
|
||||
#define _SEQUENCE_NUMBER_UTIL_H_
|
||||
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
|
||||
#include "mod_ops.h"
|
||||
|
||||
// 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); }
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user