mediasoup 3.28.0 → 3.29.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/node/lib/PipeTransportTypes.d.ts +6 -1
- package/node/lib/PipeTransportTypes.d.ts.map +1 -1
- package/node/lib/PlainTransportTypes.d.ts +6 -1
- package/node/lib/PlainTransportTypes.d.ts.map +1 -1
- package/node/lib/Router.d.ts +4 -4
- package/node/lib/Router.d.ts.map +1 -1
- package/node/lib/Router.js +10 -7
- package/node/lib/RouterTypes.d.ts +7 -1
- package/node/lib/RouterTypes.d.ts.map +1 -1
- package/node/lib/Transport.d.ts +2 -1
- package/node/lib/Transport.d.ts.map +1 -1
- package/node/lib/Transport.js +17 -6
- package/node/lib/TransportTypes.d.ts +12 -2
- package/node/lib/TransportTypes.d.ts.map +1 -1
- package/node/lib/WebRtcTransportTypes.d.ts +6 -1
- package/node/lib/WebRtcTransportTypes.d.ts.map +1 -1
- package/node/lib/fbs/transport/options.d.ts +6 -2
- package/node/lib/fbs/transport/options.d.ts.map +1 -1
- package/node/lib/fbs/transport/options.js +19 -7
- package/node/lib/fbs/transport/sctp-zero-checksum.d.ts +6 -0
- package/node/lib/fbs/transport/sctp-zero-checksum.d.ts.map +1 -0
- package/node/lib/fbs/transport/sctp-zero-checksum.js +11 -0
- package/node/lib/fbs/transport/stats.d.ts +2 -8
- package/node/lib/fbs/transport/stats.d.ts.map +1 -1
- package/node/lib/fbs/transport/stats.js +5 -29
- package/node/lib/fbs/transport.d.ts +1 -0
- package/node/lib/fbs/transport.d.ts.map +1 -1
- package/node/lib/fbs/transport.js +4 -2
- package/npm-scripts.mjs +35 -44
- package/package.json +10 -6
- package/worker/fbs/transport.fbs +9 -2
- package/worker/fuzzer/src/RTC/RTP/FuzzerRetransmissionBuffer.cpp +14 -1
- package/worker/fuzzer/src/RTC/RTP/FuzzerRtpStreamSend.cpp +17 -4
- package/worker/include/RTC/BWE/AimdRateControl.hpp +9 -9
- package/worker/include/RTC/BWE/BweTypes.hpp +54 -17
- package/worker/include/RTC/BWE/DelayBasedBwe.hpp +3 -3
- package/worker/include/RTC/BWE/FeedbackAdapter.hpp +2 -2
- package/worker/include/RTC/BWE/LossBasedController.hpp +4 -4
- package/worker/include/RTC/BWE/OveruseDetector.hpp +5 -4
- package/worker/include/RTC/BWE/ProbeBitrateEstimator.hpp +1 -1
- package/worker/include/RTC/BWE/ProbeController.hpp +6 -6
- package/worker/include/RTC/BWE/ProbePacketGenerator.hpp +2 -6
- package/worker/include/RTC/BWE/ProbingScheduler.hpp +3 -7
- package/worker/include/RTC/BWE/ReceiverTransportCongestionController.hpp +148 -0
- package/worker/include/RTC/BWE/RembGenerator.hpp +4 -3
- package/worker/include/RTC/BWE/RemoteBitrateEstimatorAbsSendTime.hpp +1 -1
- package/worker/include/RTC/BWE/SenderTransportCongestionController.hpp +343 -0
- package/worker/include/RTC/BWE/TargetRateController.hpp +4 -1
- package/worker/include/RTC/BWE/TransportWideCcFeedbackGenerator.hpp +5 -4
- package/worker/include/RTC/BWE/TrendlineEstimator.hpp +3 -3
- package/worker/include/RTC/Consumer.hpp +8 -1
- package/worker/include/RTC/RTP/RetransmissionBuffer.hpp +36 -10
- package/worker/include/RTC/RTP/RtpStream.hpp +21 -0
- package/worker/include/RTC/RTP/RtpStreamRecv.hpp +1 -0
- package/worker/include/RTC/RTP/RtpStreamSend.hpp +122 -9
- package/worker/include/RTC/SCTP/packet/parameters/ZeroChecksumAcceptableParameter.hpp +12 -3
- package/worker/include/RTC/TransportCongestionControlClient.hpp +0 -5
- package/worker/include/RTC/TransportCongestionControlServer.hpp +0 -5
- package/worker/include/Utils.hpp +9 -2
- package/worker/meson.build +4 -0
- package/worker/src/RTC/BWE/AimdRateControl.cpp +22 -22
- package/worker/src/RTC/BWE/DelayBasedBwe.cpp +16 -20
- package/worker/src/RTC/BWE/FeedbackAdapter.cpp +1 -1
- package/worker/src/RTC/BWE/OveruseDetector.cpp +8 -8
- package/worker/src/RTC/BWE/ProbeBitrateEstimator.cpp +2 -2
- package/worker/src/RTC/BWE/ProbeController.cpp +1 -1
- package/worker/src/RTC/BWE/ProbePacketGenerator.cpp +1 -6
- package/worker/src/RTC/BWE/ProbingScheduler.cpp +2 -7
- package/worker/src/RTC/BWE/ReceiverTransportCongestionController.cpp +207 -0
- package/worker/src/RTC/BWE/RembGenerator.cpp +1 -1
- package/worker/src/RTC/BWE/RemoteBitrateEstimatorAbsSendTime.cpp +1 -1
- package/worker/src/RTC/BWE/SenderTransportCongestionController.cpp +599 -0
- package/worker/src/RTC/BWE/TransportWideCcFeedbackGenerator.cpp +2 -3
- package/worker/src/RTC/BWE/TrendlineEstimator.cpp +5 -5
- package/worker/src/RTC/Consumer.cpp +3 -2
- package/worker/src/RTC/DataConsumer.cpp +2 -2
- package/worker/src/RTC/RTP/RetransmissionBuffer.cpp +21 -8
- package/worker/src/RTC/RTP/RtpStream.cpp +0 -3
- package/worker/src/RTC/RTP/RtpStreamRecv.cpp +57 -71
- package/worker/src/RTC/RTP/RtpStreamSend.cpp +428 -244
- package/worker/src/RTC/RTP/RtxStream.cpp +14 -19
- package/worker/src/RTC/SCTP/association/Association.cpp +3 -2
- package/worker/src/RTC/SCTP/association/StateCookie.cpp +26 -6
- package/worker/src/RTC/SCTP/packet/parameters/ZeroChecksumAcceptableParameter.cpp +4 -3
- package/worker/src/RTC/SCTP/rx/ReassemblyQueue.cpp +2 -1
- package/worker/src/RTC/SCTP/tx/RetransmissionQueue.cpp +4 -2
- package/worker/src/RTC/Transport.cpp +49 -20
- package/worker/src/RTC/TransportCongestionControlClient.cpp +0 -66
- package/worker/src/RTC/TransportCongestionControlServer.cpp +0 -55
- package/worker/src/Utils/Crypto.cpp +114 -98
- package/worker/subprojects/catch2.wrap +6 -6
- package/worker/subprojects/openssl.wrap +11 -12
- package/worker/subprojects/packagefiles/ankerl-unordered-dense/meson.build +1 -1
- package/worker/subprojects/unordered-dense.wrap +4 -4
- package/worker/test/src/RTC/BWE/TestDelayBasedBwe.cpp +5 -5
- package/worker/test/src/RTC/BWE/TestFeedbackAdapter.cpp +26 -23
- package/worker/test/src/RTC/BWE/TestInterArrivalDelta.cpp +8 -8
- package/worker/test/src/RTC/BWE/TestOveruseDetector.cpp +4 -4
- package/worker/test/src/RTC/BWE/TestProbeController.cpp +35 -32
- package/worker/test/src/RTC/BWE/TestProbePacketGenerator.cpp +2 -17
- package/worker/test/src/RTC/BWE/TestProbingScheduler.cpp +1 -25
- package/worker/test/src/RTC/BWE/TestReceiverTransportCongestionController.cpp +346 -0
- package/worker/test/src/RTC/BWE/TestRembGenerator.cpp +1 -1
- package/worker/test/src/RTC/BWE/TestRemoteBitrateEstimatorAbsSendTime.cpp +9 -9
- package/worker/test/src/RTC/BWE/TestSenderTransportCongestionController.cpp +510 -0
- package/worker/test/src/RTC/BWE/TestTransportWideCcFeedbackGenerator.cpp +16 -14
- package/worker/test/src/RTC/BWE/TestTrendlineEstimator.cpp +6 -6
- package/worker/test/src/RTC/BWE/helpers/RemoteBitrateEstimatorAbsSendTimeTestHelper.cpp +1 -2
- package/worker/test/src/RTC/RTCP/TestBye.cpp +1 -1
- package/worker/test/src/RTC/RTCP/TestFeedbackPsAfb.cpp +1 -1
- package/worker/test/src/RTC/RTCP/TestFeedbackPsFir.cpp +1 -1
- package/worker/test/src/RTC/RTCP/TestFeedbackPsLei.cpp +1 -1
- package/worker/test/src/RTC/RTCP/TestFeedbackPsPli.cpp +1 -1
- package/worker/test/src/RTC/RTCP/TestFeedbackPsRemb.cpp +1 -1
- package/worker/test/src/RTC/RTCP/TestFeedbackPsRpsi.cpp +1 -1
- package/worker/test/src/RTC/RTCP/TestFeedbackPsSli.cpp +1 -1
- package/worker/test/src/RTC/RTCP/TestFeedbackPsTst.cpp +1 -1
- package/worker/test/src/RTC/RTCP/TestFeedbackPsVbcm.cpp +1 -1
- package/worker/test/src/RTC/RTCP/TestFeedbackRtpEcn.cpp +1 -1
- package/worker/test/src/RTC/RTCP/TestFeedbackRtpNack.cpp +1 -1
- package/worker/test/src/RTC/RTCP/TestFeedbackRtpSrReq.cpp +1 -1
- package/worker/test/src/RTC/RTCP/TestFeedbackRtpTllei.cpp +1 -1
- package/worker/test/src/RTC/RTCP/TestFeedbackRtpTmmb.cpp +1 -1
- package/worker/test/src/RTC/RTCP/TestFeedbackRtpTransport.cpp +1 -1
- package/worker/test/src/RTC/RTCP/TestReceiverReport.cpp +1 -1
- package/worker/test/src/RTC/RTCP/TestSenderReport.cpp +1 -1
- package/worker/test/src/RTC/RTP/TestRetransmissionBuffer.cpp +60 -28
- package/worker/test/src/RTC/RTP/TestRtpStreamRecv.cpp +1 -1
- package/worker/test/src/RTC/RTP/TestRtpStreamSend.cpp +746 -24
- package/worker/test/src/RTC/RTP/TestSharedPacket.cpp +1 -1
- package/worker/test/src/RTC/SCTP/association/TestAssociation.cpp +42 -0
- package/worker/test/src/RTC/SCTP/association/TestNegotiatedCapabilities.cpp +54 -5
- package/worker/test/src/RTC/SCTP/association/TestStateCookie.cpp +80 -15
- package/worker/test/src/RTC/SCTP/association/TestStreamResetHandler.cpp +410 -3
- package/worker/test/src/RTC/SCTP/association/TestTransmissionControlBlock.cpp +1 -1
- package/worker/test/src/RTC/SCTP/packet/parameters/TestZeroChecksumAcceptableParameter.cpp +37 -5
- package/worker/test/src/RTC/SCTP/rx/TestDataTracker.cpp +5 -4
- package/worker/test/src/RTC/SCTP/rx/TestInterleavedReassemblyStreams.cpp +1 -1
- package/worker/test/src/RTC/SCTP/rx/TestReassemblyQueue.cpp +1 -1
- package/worker/test/src/RTC/SCTP/rx/TestTraditionalReassemblyStreams.cpp +1 -1
- package/worker/test/src/RTC/SCTP/tx/TestOutstandingData.cpp +1 -1
- package/worker/test/src/RTC/SCTP/tx/TestRetransmissionQueue.cpp +11 -10
- package/worker/test/src/RTC/SCTP/tx/TestRetransmissionTimeout.cpp +1 -1
- package/worker/test/src/RTC/TestNackGenerator.cpp +1 -1
- package/worker/test/src/RTC/TestPortManager.cpp +2 -2
- package/worker/test/src/RTC/TestRateCalculator.cpp +1 -1
- package/worker/test/src/RTC/TestRemoteCaptureTimeEstimator.cpp +21 -15
- package/worker/test/src/RTC/TestRemoteClockOffsetEstimator.cpp +13 -13
- package/worker/test/src/RTC/TestRtpEncodingParameters.cpp +1 -1
- package/worker/test/src/RTC/TestSubchannelsCodec.cpp +2 -2
- package/worker/test/src/RTC/TestTransportCongestionControlServer.cpp +1 -1
- package/worker/test/src/RTC/TestTransportTuple.cpp +3 -2
- package/worker/test/src/Utils/TestCrypto.cpp +71 -2
- package/worker/test/src/Utils/TestTime.cpp +2 -2
|
@@ -0,0 +1,599 @@
|
|
|
1
|
+
#define MS_CLASS "RTC::BWE::SenderTransportCongestionController"
|
|
2
|
+
// #define MS_LOG_DEV_LEVEL 3
|
|
3
|
+
|
|
4
|
+
#include "RTC/BWE/SenderTransportCongestionController.hpp"
|
|
5
|
+
#include "Logger.hpp"
|
|
6
|
+
#include "RTC/BWE/BitrateUtils.hpp"
|
|
7
|
+
|
|
8
|
+
namespace RTC
|
|
9
|
+
{
|
|
10
|
+
namespace BWE
|
|
11
|
+
{
|
|
12
|
+
/* Static. */
|
|
13
|
+
|
|
14
|
+
// How often everything that depends on time rather than on an arrival is run.
|
|
15
|
+
// The shortest deadline it has to meet is the interval the loss based
|
|
16
|
+
// controller waits before lowering the target again, so it is a good deal
|
|
17
|
+
// finer than that.
|
|
18
|
+
static constexpr int64_t ProcessIntervalMs{ 100 };
|
|
19
|
+
// How far below the throughput a probe result may drag the estimate. A probe
|
|
20
|
+
// far below what is already acknowledged is unlikely to be measuring the
|
|
21
|
+
// link, but dropping to slightly below the throughput is what drains the
|
|
22
|
+
// queues when there really is an overuse.
|
|
23
|
+
static constexpr double ProbeDropThroughputFraction{ 0.85 };
|
|
24
|
+
|
|
25
|
+
/* Static methods. */
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* What is holding the target back, which is what tells the probe controller
|
|
29
|
+
* whether a probe would make any sense right now.
|
|
30
|
+
*/
|
|
31
|
+
static ProbeController::BandwidthLimitedCause getBandwidthLimitedCause(
|
|
32
|
+
LossBasedController::State lossBasedState,
|
|
33
|
+
bool isRttAboveLimit,
|
|
34
|
+
Types::BandwidthUsage bandwidthUsage)
|
|
35
|
+
{
|
|
36
|
+
if (bandwidthUsage == Types::BandwidthUsage::OVERUSING || bandwidthUsage == Types::BandwidthUsage::UNDERUSING)
|
|
37
|
+
{
|
|
38
|
+
return ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED_DELAY_INCREASED;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (isRttAboveLimit)
|
|
42
|
+
{
|
|
43
|
+
return ProbeController::BandwidthLimitedCause::RTT_BASED_BACK_OFF_HIGH_RTT;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
switch (lossBasedState)
|
|
47
|
+
{
|
|
48
|
+
case LossBasedController::State::DECREASING:
|
|
49
|
+
{
|
|
50
|
+
// No probe is sent in this state.
|
|
51
|
+
return ProbeController::BandwidthLimitedCause::LOSS_LIMITED_BWE;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
case LossBasedController::State::INCREASING:
|
|
55
|
+
{
|
|
56
|
+
// Probes may be sent in this state.
|
|
57
|
+
return ProbeController::BandwidthLimitedCause::LOSS_LIMITED_BWE_INCREASING;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
case LossBasedController::State::DELAY_BASED_ESTIMATE:
|
|
61
|
+
{
|
|
62
|
+
return ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
NO_DEFAULT();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/* Instance methods. */
|
|
70
|
+
|
|
71
|
+
SenderTransportCongestionController::SenderTransportCongestionController(
|
|
72
|
+
Listener* listener, SharedInterface* shared, SenderTransportCongestionControllerOptions options)
|
|
73
|
+
: listener(listener),
|
|
74
|
+
shared(shared),
|
|
75
|
+
processTimer(shared->CreateTimer(this, "sender-transport-congestion-controller-process")),
|
|
76
|
+
feedbackAdapter(std::addressof(this->sendPacketHistory)),
|
|
77
|
+
alrDetector(shared),
|
|
78
|
+
// An SFU forwards what others produce and cannot make more of it, so it
|
|
79
|
+
// spends most of its time not filling the link. Without probing there, the
|
|
80
|
+
// target would only grow when the traffic being forwarded happens to fill
|
|
81
|
+
// it, and after a quiet spell the first stream admitted would be measured
|
|
82
|
+
// against a figure from long ago.
|
|
83
|
+
probeController({ .enablePeriodicAlrProbing = true }),
|
|
84
|
+
probingScheduler(this, shared),
|
|
85
|
+
startBitrate(options.startBitrate)
|
|
86
|
+
{
|
|
87
|
+
MS_TRACE();
|
|
88
|
+
|
|
89
|
+
this->minBitrate = options.minBitrate;
|
|
90
|
+
this->maxBitrate = options.maxBitrate;
|
|
91
|
+
|
|
92
|
+
ResetConstraints(this->shared->GetTimeUs(), /*applyStartBitrate*/ true);
|
|
93
|
+
|
|
94
|
+
// NOTE: Safe to apply from a constructor, where the listener must not be
|
|
95
|
+
// called: the only thing that can be pending at this point is a burst,
|
|
96
|
+
// which goes to a member of this class, since `MayNotifyTargetBitrate()`
|
|
97
|
+
// is not called from here and so there is no target to announce.
|
|
98
|
+
ApplyPendingUpdate();
|
|
99
|
+
|
|
100
|
+
this->processTimer->Start(ProcessIntervalMs, ProcessIntervalMs);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
void SenderTransportCongestionController::SetNetworkAvailable(bool networkAvailable)
|
|
104
|
+
{
|
|
105
|
+
MS_TRACE();
|
|
106
|
+
|
|
107
|
+
const int64_t nowUs = this->shared->GetTimeUs();
|
|
108
|
+
|
|
109
|
+
AddProbeClusters(this->probeController.OnNetworkAvailability(networkAvailable, nowUs));
|
|
110
|
+
|
|
111
|
+
ApplyPendingUpdate();
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
std::optional<int64_t> SenderTransportCongestionController::OnRtpPacketToBeSent(
|
|
115
|
+
RTC::RTP::Packet* packet, const RtpPacketToBeSentOptions& options)
|
|
116
|
+
{
|
|
117
|
+
MS_TRACE();
|
|
118
|
+
|
|
119
|
+
return AddRtpPacket(packet, options, /*probeCluster*/ std::nullopt);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
void SenderTransportCongestionController::OnRtpPacketSent(
|
|
123
|
+
std::optional<int64_t> sequenceNumber, size_t size, int64_t sentAtUs)
|
|
124
|
+
{
|
|
125
|
+
MS_TRACE();
|
|
126
|
+
|
|
127
|
+
// A packet that was never taken note of still took room in the link, so its
|
|
128
|
+
// bytes are attributed to the next one that does carry a sequence number.
|
|
129
|
+
if (!sequenceNumber.has_value())
|
|
130
|
+
{
|
|
131
|
+
this->sendPacketHistory.ProcessSentUntrackedPacket(size + this->packetOverhead, sentAtUs);
|
|
132
|
+
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const auto sentPacket =
|
|
137
|
+
this->sendPacketHistory.ProcessSentPacket(sequenceNumber.value(), sentAtUs);
|
|
138
|
+
|
|
139
|
+
// Nothing is known about a packet the history does not hold, so there is
|
|
140
|
+
// nothing to tell anybody about it either.
|
|
141
|
+
if (!sentPacket.has_value())
|
|
142
|
+
{
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const auto& sentPacketValue = sentPacket.value();
|
|
147
|
+
|
|
148
|
+
this->alrDetector.OnBytesSent(static_cast<int64_t>(sentPacketValue.size), sentAtUs);
|
|
149
|
+
this->acknowledgedBitrateEstimator.SetAlr(this->alrDetector.GetAlrStartTimeUs().has_value());
|
|
150
|
+
|
|
151
|
+
if (!this->firstPacketSent)
|
|
152
|
+
{
|
|
153
|
+
this->firstPacketSent = true;
|
|
154
|
+
|
|
155
|
+
// Until a feedback arrives there is no round trip to measure, so the
|
|
156
|
+
// instant the first packet left is taken as the start of one. Without
|
|
157
|
+
// this the backoff by round trip time would have nothing to work with
|
|
158
|
+
// during the first seconds.
|
|
159
|
+
this->targetRateController.UpdatePropagationRtt(0, sentAtUs);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
this->targetRateController.OnPacketSent(sentAtUs);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
void SenderTransportCongestionController::ReceiveTransportWideCcFeedback(
|
|
166
|
+
const RTC::RTCP::FeedbackRtpTransportPacket* feedback, int64_t receivedAtUs)
|
|
167
|
+
{
|
|
168
|
+
MS_TRACE();
|
|
169
|
+
|
|
170
|
+
const auto processedFeedback =
|
|
171
|
+
this->feedbackAdapter.ProcessTransportWideCcFeedback(feedback, receivedAtUs);
|
|
172
|
+
|
|
173
|
+
if (!processedFeedback.has_value())
|
|
174
|
+
{
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const auto& transportPacketsFeedback = processedFeedback.value();
|
|
179
|
+
|
|
180
|
+
if (transportPacketsFeedback.packetFeedbacks.empty())
|
|
181
|
+
{
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Something reports back, so the estimation is ours to do and not the
|
|
186
|
+
// remote endpoint's.
|
|
187
|
+
this->firstTransportFeedbackReceived = true;
|
|
188
|
+
|
|
189
|
+
const int64_t feedbackTimeUs = transportPacketsFeedback.feedbackTimeUs;
|
|
190
|
+
const auto receivedWithSendInfo = transportPacketsFeedback.ReceivedWithSendInfo();
|
|
191
|
+
|
|
192
|
+
// The round trip of the whole feedback is the time since the oldest packet
|
|
193
|
+
// it reports on left, minus how long the rest of them waited at the remote
|
|
194
|
+
// endpoint before it decided to report. Taking the smallest of those is
|
|
195
|
+
// what leaves the propagation alone, without the wait.
|
|
196
|
+
//
|
|
197
|
+
// NOTE: Every packet below has an arrival time, since only the ones that
|
|
198
|
+
// were received are in `ReceivedWithSendInfo()`.
|
|
199
|
+
int64_t minPropagationRttUs{ Types::TimeUsInfinite };
|
|
200
|
+
int64_t maxReceiveTimeUs{ 0 };
|
|
201
|
+
|
|
202
|
+
for (const auto& packetResult : receivedWithSendInfo)
|
|
203
|
+
{
|
|
204
|
+
// NOLINTNEXTLINE(bugprone-unchecked-optional-access)
|
|
205
|
+
maxReceiveTimeUs = std::max(maxReceiveTimeUs, packetResult.receiveTimeUs.value());
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
for (const auto& packetResult : receivedWithSendInfo)
|
|
209
|
+
{
|
|
210
|
+
// NOLINTNEXTLINE(bugprone-unchecked-optional-access)
|
|
211
|
+
const int64_t receiveTimeUs = packetResult.receiveTimeUs.value();
|
|
212
|
+
const int64_t feedbackRttUs = feedbackTimeUs - packetResult.sentPacket.sendTimeUs;
|
|
213
|
+
const int64_t minPendingTimeUs = maxReceiveTimeUs - receiveTimeUs;
|
|
214
|
+
const int64_t propagationRttUs = feedbackRttUs - minPendingTimeUs;
|
|
215
|
+
|
|
216
|
+
minPropagationRttUs = std::min(minPropagationRttUs, propagationRttUs);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (!receivedWithSendInfo.empty())
|
|
220
|
+
{
|
|
221
|
+
this->targetRateController.UpdatePropagationRtt(minPropagationRttUs, feedbackTimeUs);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const auto alrStartTimeUs = this->alrDetector.GetAlrStartTimeUs();
|
|
225
|
+
|
|
226
|
+
// Leaving the state has to be told to both of them, since each one holds
|
|
227
|
+
// its own idea of when it ended.
|
|
228
|
+
if (this->previouslyInAlr && !alrStartTimeUs.has_value())
|
|
229
|
+
{
|
|
230
|
+
this->acknowledgedBitrateEstimator.SetAlrEndedTimeUs(feedbackTimeUs);
|
|
231
|
+
this->probeController.SetAlrEndedTimeUs(feedbackTimeUs);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
this->previouslyInAlr = alrStartTimeUs.has_value();
|
|
235
|
+
|
|
236
|
+
this->acknowledgedBitrateEstimator.IncomingPacketFeedbackVector(
|
|
237
|
+
transportPacketsFeedback.SortedByReceiveTime());
|
|
238
|
+
|
|
239
|
+
const auto acknowledgedBitrate = this->acknowledgedBitrateEstimator.GetBitrate();
|
|
240
|
+
|
|
241
|
+
this->targetRateController.SetAcknowledgedBitrate(
|
|
242
|
+
acknowledgedBitrate.value_or(Types::BitrateInfinite));
|
|
243
|
+
|
|
244
|
+
for (const auto& packetResult : transportPacketsFeedback.SortedByReceiveTime())
|
|
245
|
+
{
|
|
246
|
+
if (packetResult.sentPacket.probeCluster.has_value())
|
|
247
|
+
{
|
|
248
|
+
this->probeBitrateEstimator.HandleProbeAndEstimateBitrate(packetResult);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
auto probeBitrate = this->probeBitrateEstimator.FetchAndResetLastEstimatedBitrate();
|
|
253
|
+
|
|
254
|
+
// A probe that measured far below what is already acknowledged is not
|
|
255
|
+
// measuring the link, so the drop it would cause is bounded.
|
|
256
|
+
if (probeBitrate.has_value() && acknowledgedBitrate.has_value())
|
|
257
|
+
{
|
|
258
|
+
const int64_t limit = std::min(
|
|
259
|
+
this->delayBasedBwe.GetLastEstimate(),
|
|
260
|
+
BitrateUtils::ApplyBitrateFactor(acknowledgedBitrate.value(), ProbeDropThroughputFraction));
|
|
261
|
+
|
|
262
|
+
probeBitrate = std::max(probeBitrate.value(), limit);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
const auto result = this->delayBasedBwe.IncomingPacketFeedbackVector(
|
|
266
|
+
transportPacketsFeedback,
|
|
267
|
+
acknowledgedBitrate,
|
|
268
|
+
probeBitrate,
|
|
269
|
+
/*networkEstimate*/ std::nullopt,
|
|
270
|
+
alrStartTimeUs.has_value());
|
|
271
|
+
|
|
272
|
+
if (result.updated)
|
|
273
|
+
{
|
|
274
|
+
// A probe result replaces the estimate instead of nudging it, and that
|
|
275
|
+
// has to happen before the delay based estimate is handed over, since
|
|
276
|
+
// setting it clears what the delay based path had.
|
|
277
|
+
if (result.probe)
|
|
278
|
+
{
|
|
279
|
+
this->targetRateController.SetSendBitrate(result.targetBitrate);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
this->targetRateController.SetDelayBasedEstimate(result.targetBitrate);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
this->targetRateController.UpdateLossBasedController(
|
|
286
|
+
transportPacketsFeedback.packetFeedbacks, alrStartTimeUs.has_value(), feedbackTimeUs);
|
|
287
|
+
|
|
288
|
+
if (result.updated)
|
|
289
|
+
{
|
|
290
|
+
MayNotifyTargetBitrate(feedbackTimeUs);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// Coming out of an overuse is the one moment where a probe is worth it
|
|
294
|
+
// without waiting for anything else.
|
|
295
|
+
if (result.recoveredFromOveruse)
|
|
296
|
+
{
|
|
297
|
+
this->probeController.SetAlrStartTimeUs(alrStartTimeUs);
|
|
298
|
+
|
|
299
|
+
AddProbeClusters(this->probeController.RequestProbe(feedbackTimeUs));
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
ApplyPendingUpdate();
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
void SenderTransportCongestionController::ReceiveRtcpReceiverReport(
|
|
306
|
+
int64_t lostPackets, int64_t expectedPackets)
|
|
307
|
+
{
|
|
308
|
+
MS_TRACE();
|
|
309
|
+
|
|
310
|
+
// Nothing moved since the previous report, so there is no stretch of the
|
|
311
|
+
// stream to work a loss ratio out of.
|
|
312
|
+
if (expectedPackets < 1)
|
|
313
|
+
{
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// Not a single packet got through. That is not a loss ratio of one but a
|
|
318
|
+
// stretch the remote endpoint could not report on, so it is left out rather
|
|
319
|
+
// than fed as the worst possible measurement.
|
|
320
|
+
if (expectedPackets - lostPackets < 1)
|
|
321
|
+
{
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
this->targetRateController.UpdatePacketsLost(
|
|
326
|
+
lostPackets, expectedPackets, this->shared->GetTimeUs());
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
void SenderTransportCongestionController::ReceiveEstimatedBitrate(int64_t bitrate)
|
|
330
|
+
{
|
|
331
|
+
MS_TRACE();
|
|
332
|
+
|
|
333
|
+
this->targetRateController.SetReceiverEstimate(bitrate);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
void SenderTransportCongestionController::OnRttUpdate(int64_t rttUs)
|
|
337
|
+
{
|
|
338
|
+
MS_TRACE();
|
|
339
|
+
|
|
340
|
+
// NOTE: The round trip is taken in whole milliseconds, which is the
|
|
341
|
+
// resolution the thresholds it is compared against are expressed in.
|
|
342
|
+
const int64_t roundedRttUs = Utils::Time::TimeUsToMs(rttUs) * 1000;
|
|
343
|
+
|
|
344
|
+
if (roundedRttUs == 0)
|
|
345
|
+
{
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
this->delayBasedBwe.OnRttUpdate(roundedRttUs);
|
|
350
|
+
this->targetRateController.UpdateRtt(roundedRttUs);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
void SenderTransportCongestionController::SetBitrateLimits(int64_t minBitrate, int64_t maxBitrate)
|
|
354
|
+
{
|
|
355
|
+
MS_TRACE();
|
|
356
|
+
|
|
357
|
+
const int64_t nowUs = this->shared->GetTimeUs();
|
|
358
|
+
|
|
359
|
+
this->minBitrate = minBitrate;
|
|
360
|
+
this->maxBitrate = maxBitrate;
|
|
361
|
+
|
|
362
|
+
ResetConstraints(nowUs, /*applyStartBitrate*/ false);
|
|
363
|
+
|
|
364
|
+
MayNotifyTargetBitrate(nowUs);
|
|
365
|
+
|
|
366
|
+
ApplyPendingUpdate();
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
void SenderTransportCongestionController::SetDesiredBitrate(int64_t desiredBitrate)
|
|
370
|
+
{
|
|
371
|
+
MS_TRACE();
|
|
372
|
+
|
|
373
|
+
const int64_t nowUs = this->shared->GetTimeUs();
|
|
374
|
+
|
|
375
|
+
AddProbeClusters(this->probeController.OnMaxTotalAllocatedBitrate(desiredBitrate, nowUs));
|
|
376
|
+
|
|
377
|
+
ApplyPendingUpdate();
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
void SenderTransportCongestionController::SetPacketOverhead(size_t packetOverhead)
|
|
381
|
+
{
|
|
382
|
+
MS_TRACE();
|
|
383
|
+
|
|
384
|
+
this->packetOverhead = packetOverhead;
|
|
385
|
+
|
|
386
|
+
this->probingScheduler.SetPacketOverhead(packetOverhead);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
int64_t SenderTransportCongestionController::GetAvailableBitrate() const
|
|
390
|
+
{
|
|
391
|
+
MS_TRACE();
|
|
392
|
+
|
|
393
|
+
return this->targetRateController.GetTargetBitrate();
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
void SenderTransportCongestionController::OnProbingSchedulerSendRtpPacket(
|
|
397
|
+
ProbingScheduler* /*probingScheduler*/,
|
|
398
|
+
RTC::RTP::Packet* packet,
|
|
399
|
+
const Types::ProbeCluster& probeCluster)
|
|
400
|
+
{
|
|
401
|
+
MS_TRACE();
|
|
402
|
+
|
|
403
|
+
// The generator leaves room for both extensions but writes neither, and
|
|
404
|
+
// since it reuses a single packet what is left unwritten is whatever the
|
|
405
|
+
// previous one carried.
|
|
406
|
+
const auto sequenceNumber = AddRtpPacket(packet, RtpPacketToBeSentOptions{}, probeCluster);
|
|
407
|
+
|
|
408
|
+
// The generator builds every packet with room for both extensions, so
|
|
409
|
+
// there is always a sequence number to hand over.
|
|
410
|
+
MS_ASSERT(sequenceNumber.has_value(), "probe packet has no transport wide sequence number");
|
|
411
|
+
|
|
412
|
+
this->listener->OnSenderTransportCongestionControllerSendRtpProbePacket(
|
|
413
|
+
this, packet, sequenceNumber.value());
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
void SenderTransportCongestionController::OnTimer(TimerHandleInterface* timer)
|
|
417
|
+
{
|
|
418
|
+
MS_TRACE();
|
|
419
|
+
|
|
420
|
+
if (timer == this->processTimer.get())
|
|
421
|
+
{
|
|
422
|
+
Process();
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
std::optional<int64_t> SenderTransportCongestionController::AddRtpPacket(
|
|
427
|
+
RTC::RTP::Packet* packet,
|
|
428
|
+
const RtpPacketToBeSentOptions& options,
|
|
429
|
+
std::optional<Types::ProbeCluster> probeCluster)
|
|
430
|
+
{
|
|
431
|
+
MS_TRACE();
|
|
432
|
+
|
|
433
|
+
// Whatever the packet carries there now, which is only read to find out
|
|
434
|
+
// whether it has room for the sequence number at all. Without it the
|
|
435
|
+
// remote endpoint cannot report on this packet, so taking note of it
|
|
436
|
+
// would only fill the history with entries no feedback can ever name.
|
|
437
|
+
uint16_t previousWideSeqNumber{ 0 };
|
|
438
|
+
|
|
439
|
+
if (!packet->ReadTransportWideCc01(previousWideSeqNumber))
|
|
440
|
+
{
|
|
441
|
+
return std::nullopt;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
const int64_t nowUs = this->shared->GetTimeUs();
|
|
445
|
+
|
|
446
|
+
const int64_t sequenceNumber = this->sendPacketHistory.AddPacket(
|
|
447
|
+
SendPacketHistory::AddPacketOptions{
|
|
448
|
+
.ssrc = packet->GetSsrc(),
|
|
449
|
+
.seq = packet->GetSequenceNumber(),
|
|
450
|
+
// What the link carries is the packet plus everything below RTP, so
|
|
451
|
+
// that is what the rate control has to reason about.
|
|
452
|
+
.size = packet->GetLength() + this->packetOverhead,
|
|
453
|
+
.isAudio = options.isAudio,
|
|
454
|
+
.isRetransmission = options.isRetransmission,
|
|
455
|
+
.originalSsrc = options.originalSsrc,
|
|
456
|
+
.probeCluster = probeCluster,
|
|
457
|
+
.createdAtUs = nowUs });
|
|
458
|
+
|
|
459
|
+
packet->UpdateTransportWideCc01(static_cast<uint16_t>(sequenceNumber));
|
|
460
|
+
packet->UpdateAbsSendTime(Utils::Time::TimeUsToAbsSendTime(nowUs));
|
|
461
|
+
|
|
462
|
+
return sequenceNumber;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
void SenderTransportCongestionController::Process()
|
|
466
|
+
{
|
|
467
|
+
MS_TRACE();
|
|
468
|
+
|
|
469
|
+
const int64_t nowUs = this->shared->GetTimeUs();
|
|
470
|
+
|
|
471
|
+
this->targetRateController.Update(nowUs);
|
|
472
|
+
|
|
473
|
+
// Probing while the remote endpoint is the one estimating would be probing
|
|
474
|
+
// something nobody is measuring, so it waits for the first feedback.
|
|
475
|
+
this->probeController.SetAlrStartTimeUs(
|
|
476
|
+
this->firstTransportFeedbackReceived ? this->alrDetector.GetAlrStartTimeUs() : std::nullopt);
|
|
477
|
+
|
|
478
|
+
AddProbeClusters(this->probeController.Process(nowUs));
|
|
479
|
+
|
|
480
|
+
MayNotifyTargetBitrate(nowUs);
|
|
481
|
+
|
|
482
|
+
ApplyPendingUpdate();
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
void SenderTransportCongestionController::AddProbeClusters(
|
|
486
|
+
const std::vector<Types::ProbeClusterConfig>& clusterConfigs)
|
|
487
|
+
{
|
|
488
|
+
MS_TRACE();
|
|
489
|
+
|
|
490
|
+
this->pendingUpdate.probeClusterConfigs.insert(
|
|
491
|
+
this->pendingUpdate.probeClusterConfigs.end(), clusterConfigs.begin(), clusterConfigs.end());
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
void SenderTransportCongestionController::ApplyPendingUpdate()
|
|
495
|
+
{
|
|
496
|
+
MS_TRACE();
|
|
497
|
+
|
|
498
|
+
// Taken out before anything leaves this class, so that a listener calling
|
|
499
|
+
// back in starts a cycle of its own instead of finding this one half
|
|
500
|
+
// applied.
|
|
501
|
+
const auto probeClusterConfigs = std::move(this->pendingUpdate.probeClusterConfigs);
|
|
502
|
+
const auto targetBitrateToNotify = this->pendingUpdate.targetBitrateToNotify;
|
|
503
|
+
|
|
504
|
+
this->pendingUpdate = {};
|
|
505
|
+
|
|
506
|
+
if (!probeClusterConfigs.empty())
|
|
507
|
+
{
|
|
508
|
+
this->probingScheduler.CreateProbeClusters(probeClusterConfigs);
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
if (targetBitrateToNotify.has_value())
|
|
512
|
+
{
|
|
513
|
+
this->listener->OnSenderTransportCongestionControllerTargetBitrate(
|
|
514
|
+
this, targetBitrateToNotify.value());
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
void SenderTransportCongestionController::MayNotifyTargetBitrate(int64_t nowUs)
|
|
519
|
+
{
|
|
520
|
+
MS_TRACE();
|
|
521
|
+
|
|
522
|
+
const int64_t targetBitrate = this->targetRateController.GetTargetBitrate();
|
|
523
|
+
const uint8_t fractionLost = this->targetRateController.GetFractionLost();
|
|
524
|
+
const int64_t rttUs = this->targetRateController.GetRttUs();
|
|
525
|
+
const LossBasedController::State lossBasedState =
|
|
526
|
+
this->targetRateController.GetLossBasedState();
|
|
527
|
+
// Not filling the link is not the same as not being able to fill it, and
|
|
528
|
+
// what is announced is whether the link is what holds the sender back.
|
|
529
|
+
const bool isBandwidthLimited = !this->alrDetector.GetAlrStartTimeUs().has_value();
|
|
530
|
+
|
|
531
|
+
// Everything the listener reasons about is compared, since a reallocation
|
|
532
|
+
// is far more expensive than this comparison.
|
|
533
|
+
if (
|
|
534
|
+
this->lastTargetBitrate.has_value() && targetBitrate == this->lastTargetBitrate.value() &&
|
|
535
|
+
fractionLost == this->lastFractionLost && rttUs == this->lastRttUs &&
|
|
536
|
+
lossBasedState == this->lastLossBasedState &&
|
|
537
|
+
isBandwidthLimited == this->lastIsBandwidthLimited)
|
|
538
|
+
{
|
|
539
|
+
return;
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
this->lastTargetBitrate = targetBitrate;
|
|
543
|
+
this->lastFractionLost = fractionLost;
|
|
544
|
+
this->lastRttUs = rttUs;
|
|
545
|
+
this->lastLossBasedState = lossBasedState;
|
|
546
|
+
this->lastIsBandwidthLimited = isBandwidthLimited;
|
|
547
|
+
|
|
548
|
+
this->alrDetector.SetEstimatedBitrate(targetBitrate);
|
|
549
|
+
|
|
550
|
+
AddProbeClusters(this->probeController.SetEstimatedBitrate(
|
|
551
|
+
targetBitrate,
|
|
552
|
+
getBandwidthLimitedCause(
|
|
553
|
+
lossBasedState,
|
|
554
|
+
this->targetRateController.IsRttAboveLimit(),
|
|
555
|
+
this->delayBasedBwe.GetLastState()),
|
|
556
|
+
nowUs));
|
|
557
|
+
|
|
558
|
+
this->pendingUpdate.targetBitrateToNotify = targetBitrate;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
void SenderTransportCongestionController::ResetConstraints(int64_t nowUs, bool applyStartBitrate)
|
|
562
|
+
{
|
|
563
|
+
MS_TRACE();
|
|
564
|
+
|
|
565
|
+
// Nothing below may be driven to a bitrate it treats as none at all, since
|
|
566
|
+
// with nothing going out there would be nothing left to measure.
|
|
567
|
+
this->minBitrate = std::max(this->minBitrate, RTC::Consts::BweMinBitrate);
|
|
568
|
+
|
|
569
|
+
if (this->maxBitrate < this->minBitrate)
|
|
570
|
+
{
|
|
571
|
+
MS_WARN_TAG(
|
|
572
|
+
bwe,
|
|
573
|
+
"max bitrate is lower than min bitrate [maxBitrate:%" PRIi64 ", minBitrate:%" PRIi64 "]",
|
|
574
|
+
this->maxBitrate,
|
|
575
|
+
this->minBitrate);
|
|
576
|
+
|
|
577
|
+
this->maxBitrate = this->minBitrate;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
// NOTE: Raised here and not where it is kept, so that the member stays
|
|
581
|
+
// what was configured.
|
|
582
|
+
const int64_t startBitrate =
|
|
583
|
+
applyStartBitrate ? std::max(this->startBitrate, this->minBitrate) : 0;
|
|
584
|
+
|
|
585
|
+
this->targetRateController.SetBitrateLimits(this->minBitrate, this->maxBitrate);
|
|
586
|
+
|
|
587
|
+
this->delayBasedBwe.SetMinBitrate(this->minBitrate);
|
|
588
|
+
|
|
589
|
+
if (applyStartBitrate)
|
|
590
|
+
{
|
|
591
|
+
this->targetRateController.SetSendBitrate(startBitrate);
|
|
592
|
+
this->delayBasedBwe.SetStartBitrate(startBitrate);
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
AddProbeClusters(
|
|
596
|
+
this->probeController.SetBitrates(this->minBitrate, startBitrate, this->maxBitrate, nowUs));
|
|
597
|
+
}
|
|
598
|
+
} // namespace BWE
|
|
599
|
+
} // namespace RTC
|
|
@@ -45,7 +45,7 @@ namespace RTC
|
|
|
45
45
|
this->sendPeriodicTimer->Start(this->sendIntervalMs, this->sendIntervalMs);
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
void TransportWideCcFeedbackGenerator::
|
|
48
|
+
void TransportWideCcFeedbackGenerator::ReceiveRtpPacket(
|
|
49
49
|
int64_t arrivalTimeUs, const RTC::RTP::Packet* packet)
|
|
50
50
|
{
|
|
51
51
|
MS_TRACE();
|
|
@@ -247,8 +247,7 @@ namespace RTC
|
|
|
247
247
|
|
|
248
248
|
const auto latestWideSeqNumber = this->feedbackPacket->GetLatestSequenceNumber();
|
|
249
249
|
|
|
250
|
-
this->listener->
|
|
251
|
-
this, this->feedbackPacket.get());
|
|
250
|
+
this->listener->OnTransportWideCcFeedbackGeneratorSendPacket(this, this->feedbackPacket.get());
|
|
252
251
|
|
|
253
252
|
this->feedbackWideSeqNumStart = latestWideSeqNumber + 1;
|
|
254
253
|
|
|
@@ -297,16 +297,16 @@ namespace RTC
|
|
|
297
297
|
{
|
|
298
298
|
MS_TRACE();
|
|
299
299
|
|
|
300
|
-
if (!this->
|
|
300
|
+
if (!this->lastSampleArrivalTimeUs.has_value())
|
|
301
301
|
{
|
|
302
|
-
this->
|
|
302
|
+
this->lastSampleArrivalTimeUs = arrivalTimeUs;
|
|
303
303
|
}
|
|
304
304
|
|
|
305
305
|
// Avoid adapting the threshold to big latency spikes, caused for instance
|
|
306
306
|
// by a sudden capacity drop.
|
|
307
307
|
if (std::fabs(modifiedTrend) > this->threshold + MaxAdaptOffset)
|
|
308
308
|
{
|
|
309
|
-
this->
|
|
309
|
+
this->lastSampleArrivalTimeUs = arrivalTimeUs;
|
|
310
310
|
|
|
311
311
|
return;
|
|
312
312
|
}
|
|
@@ -318,13 +318,13 @@ namespace RTC
|
|
|
318
318
|
// NOTE: The coefficients above are rates per millisecond, so the step is
|
|
319
319
|
// expressed in those units no matter that the instants are microseconds.
|
|
320
320
|
const double elapsedMs = std::min(
|
|
321
|
-
static_cast<double>(arrivalTimeUs - this->
|
|
321
|
+
static_cast<double>(arrivalTimeUs - this->lastSampleArrivalTimeUs.value()) / 1000.0,
|
|
322
322
|
static_cast<double>(MaxThresholdUpdateDeltaMs));
|
|
323
323
|
|
|
324
324
|
this->threshold += coef * (std::fabs(modifiedTrend) - this->threshold) * elapsedMs;
|
|
325
325
|
this->threshold = std::clamp(this->threshold, ThresholdMin, ThresholdMax);
|
|
326
326
|
|
|
327
|
-
this->
|
|
327
|
+
this->lastSampleArrivalTimeUs = arrivalTimeUs;
|
|
328
328
|
}
|
|
329
329
|
} // namespace BWE
|
|
330
330
|
} // namespace RTC
|
|
@@ -1526,13 +1526,14 @@ namespace RTC
|
|
|
1526
1526
|
}
|
|
1527
1527
|
}
|
|
1528
1528
|
|
|
1529
|
-
|
|
1529
|
+
std::optional<RTC::RTP::RtpStreamSend::Loss> Consumer::ReceiveRtcpReceiverReport(
|
|
1530
|
+
RTC::RTCP::ReceiverReport* report, int64_t receivedAtUs)
|
|
1530
1531
|
{
|
|
1531
1532
|
MS_TRACE();
|
|
1532
1533
|
|
|
1533
1534
|
auto* rtpStream = this->mapSsrcRtpStream.at(report->GetSsrc());
|
|
1534
1535
|
|
|
1535
|
-
rtpStream->ReceiveRtcpReceiverReport(report, receivedAtUs);
|
|
1536
|
+
return rtpStream->ReceiveRtcpReceiverReport(report, receivedAtUs);
|
|
1536
1537
|
}
|
|
1537
1538
|
|
|
1538
1539
|
void Consumer::ReceiveRtcpXrReceiverReferenceTime(
|