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
|
@@ -3,11 +3,10 @@
|
|
|
3
3
|
|
|
4
4
|
#include "RTC/RTP/RtpStreamSend.hpp"
|
|
5
5
|
#include "Logger.hpp"
|
|
6
|
-
#include "RTC/RTCP/FeedbackPsFir.hpp"
|
|
7
|
-
#include "RTC/RTCP/FeedbackPsPli.hpp"
|
|
8
6
|
#include "RTC/RtpDictionaries.hpp"
|
|
9
7
|
#include "Utils.hpp"
|
|
10
|
-
#include <
|
|
8
|
+
#include <cmath> // std::pow(), std::round()
|
|
9
|
+
#include <limits>
|
|
11
10
|
|
|
12
11
|
namespace RTC
|
|
13
12
|
{
|
|
@@ -16,12 +15,12 @@ namespace RTC
|
|
|
16
15
|
/* Static. */
|
|
17
16
|
|
|
18
17
|
// Limit max number of items in the retransmission buffer.
|
|
19
|
-
static constexpr size_t RetransmissionBufferMaxItems{
|
|
20
|
-
// 17: 16 bit mask + the initial sequence number.
|
|
21
|
-
static constexpr size_t MaxRequestedPackets{ 17 };
|
|
22
|
-
static thread_local std::vector<RTP::RetransmissionBuffer::Item*> RetransmissionContainer(
|
|
23
|
-
MaxRequestedPackets + 1);
|
|
18
|
+
static constexpr size_t RetransmissionBufferMaxItems{ 3000 };
|
|
24
19
|
static constexpr int64_t DefaultRttMs{ 100 };
|
|
20
|
+
// Interval between consecutive iterations of pending retransmissions.
|
|
21
|
+
static constexpr int64_t RetransmissionIntervalMs{ 10 };
|
|
22
|
+
// Maximum number of packets retransmitted in each iteration.
|
|
23
|
+
static constexpr size_t MaxRetransmittedPacketsPerIteration{ 2 };
|
|
25
24
|
|
|
26
25
|
/* Instance methods. */
|
|
27
26
|
|
|
@@ -32,7 +31,9 @@ namespace RTC
|
|
|
32
31
|
std::string& mid)
|
|
33
32
|
: RTP::RtpStream::RtpStream(listener, shared, params, 10),
|
|
34
33
|
mid(mid),
|
|
35
|
-
transmissionCounter(shared, /*ignorePaddingOnlyPackets*/ true)
|
|
34
|
+
transmissionCounter(shared, /*ignorePaddingOnlyPackets*/ true),
|
|
35
|
+
retransmissionTimer(
|
|
36
|
+
params.useNack ? shared->CreateTimer(this, "rtp-stream-send-retransmissions") : nullptr)
|
|
36
37
|
{
|
|
37
38
|
MS_TRACE();
|
|
38
39
|
|
|
@@ -112,6 +113,8 @@ namespace RTC
|
|
|
112
113
|
return ReceivePacketResult::DISCARDED;
|
|
113
114
|
}
|
|
114
115
|
|
|
116
|
+
UpdateUnsentSeqNumbers(packet->GetSequenceNumber());
|
|
117
|
+
|
|
115
118
|
bool stored{ false };
|
|
116
119
|
|
|
117
120
|
// If NACK is enabled, store the packet into the buffer.
|
|
@@ -132,7 +135,7 @@ namespace RTC
|
|
|
132
135
|
return ReceivePacketResult::DISCARDED;
|
|
133
136
|
}
|
|
134
137
|
|
|
135
|
-
stored = this->retransmissionBuffer->Insert(packet, sharedPacket);
|
|
138
|
+
stored = this->retransmissionBuffer->Insert(packet, sharedPacket, this->shared->GetTimeMs());
|
|
136
139
|
}
|
|
137
140
|
|
|
138
141
|
// Increase transmission counter.
|
|
@@ -150,101 +153,61 @@ namespace RTC
|
|
|
150
153
|
|
|
151
154
|
for (auto it = nackPacket->Begin(); it != nackPacket->End(); ++it)
|
|
152
155
|
{
|
|
153
|
-
const RTC::RTCP::FeedbackRtpNackItem*
|
|
154
|
-
|
|
155
|
-
this->nackPacketCount += item->CountRequestedPackets();
|
|
156
|
+
const RTC::RTCP::FeedbackRtpNackItem* nackItem = *it;
|
|
156
157
|
|
|
157
|
-
|
|
158
|
+
this->nackPacketCount += nackItem->CountRequestedPackets();
|
|
158
159
|
|
|
159
|
-
|
|
160
|
+
if (!this->retransmissionBuffer)
|
|
160
161
|
{
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
break;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
MS_ASSERT(
|
|
167
|
-
item->sharedPacket.HasPacket(),
|
|
168
|
-
"item in retransmission container doesn't contain a packet [ssrc:%" PRIu32
|
|
169
|
-
", seq:%" PRIu16 ", timestamp:%" PRIu32 "]",
|
|
170
|
-
item->ssrc,
|
|
171
|
-
item->sequenceNumber,
|
|
172
|
-
item->timestamp);
|
|
173
|
-
|
|
174
|
-
auto* packet = item->sharedPacket.GetPacket();
|
|
175
|
-
|
|
176
|
-
// Keep the values of the original packet received by the Consumer.
|
|
177
|
-
auto origSsrc = packet->GetSsrc();
|
|
178
|
-
auto origSeq = packet->GetSequenceNumber();
|
|
179
|
-
auto origTimestamp = packet->GetTimestamp();
|
|
180
|
-
auto origMarker = packet->HasMarker();
|
|
181
|
-
std::string origMid;
|
|
182
|
-
|
|
183
|
-
// Put correct info into the packet.
|
|
184
|
-
packet->SetSsrc(item->ssrc);
|
|
185
|
-
packet->SetSequenceNumber(item->sequenceNumber);
|
|
186
|
-
packet->SetTimestamp(item->timestamp);
|
|
187
|
-
packet->SetMarker(item->marker);
|
|
188
|
-
|
|
189
|
-
if (item->encoder != nullptr)
|
|
190
|
-
{
|
|
191
|
-
packet->EncodePayload(item->encoder.get());
|
|
192
|
-
}
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
193
164
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
165
|
+
// Queue the requested packets in the order they are requested: first the
|
|
166
|
+
// one in the packet id and then those in the bitmask. A packet already
|
|
167
|
+
// pending is not queued again since it will be retransmitted anyway.
|
|
168
|
+
uint16_t seq = nackItem->GetPacketId();
|
|
169
|
+
uint16_t bitmask = nackItem->GetLostPacketBitmask();
|
|
170
|
+
bool requested{ true };
|
|
200
171
|
|
|
201
|
-
|
|
202
|
-
|
|
172
|
+
while (requested || bitmask != 0)
|
|
173
|
+
{
|
|
174
|
+
if (requested)
|
|
203
175
|
{
|
|
204
|
-
|
|
205
|
-
this->rtxSeq++;
|
|
176
|
+
const bool inserted = this->pendingRetransmissionsSet.insert(seq).second;
|
|
206
177
|
|
|
207
|
-
|
|
178
|
+
if (inserted)
|
|
179
|
+
{
|
|
180
|
+
this->pendingRetransmissionsQueue.push_back(seq);
|
|
181
|
+
}
|
|
208
182
|
}
|
|
209
183
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
RTP::RtpStream::PacketRetransmitted(packet);
|
|
184
|
+
requested = (bitmask & 1) != 0;
|
|
185
|
+
bitmask >>= 1;
|
|
186
|
+
seq++;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
216
189
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
}
|
|
190
|
+
// If NACK is not supported, exit.
|
|
191
|
+
if (!this->retransmissionBuffer)
|
|
192
|
+
{
|
|
193
|
+
MS_WARN_TAG(rtx, "NACK not supported");
|
|
222
194
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
{
|
|
226
|
-
// Restore the packet.
|
|
227
|
-
packet->RtxDecode(RtpStream::GetPayloadType(), item->ssrc);
|
|
228
|
-
}
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
229
197
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
198
|
+
// If a retransmission iteration is already scheduled, nothing else to do.
|
|
199
|
+
if (this->retransmissionTimer->IsActive())
|
|
200
|
+
{
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
235
203
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
packet->RestorePayload();
|
|
240
|
-
}
|
|
204
|
+
// Otherwise retransmit the first pending packets right away and schedule
|
|
205
|
+
// the next iteration if there are retransmissions left.
|
|
206
|
+
RetransmitPendingPackets();
|
|
241
207
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
packet->SetTimestamp(origTimestamp);
|
|
246
|
-
packet->SetMarker(origMarker);
|
|
247
|
-
}
|
|
208
|
+
if (!this->pendingRetransmissionsQueue.empty())
|
|
209
|
+
{
|
|
210
|
+
this->retransmissionTimer->Start(RetransmissionIntervalMs);
|
|
248
211
|
}
|
|
249
212
|
}
|
|
250
213
|
|
|
@@ -272,7 +235,8 @@ namespace RTC
|
|
|
272
235
|
}
|
|
273
236
|
}
|
|
274
237
|
|
|
275
|
-
|
|
238
|
+
std::optional<RtpStreamSend::Loss> RtpStreamSend::ReceiveRtcpReceiverReport(
|
|
239
|
+
RTC::RTCP::ReceiverReport* report, int64_t receivedAtUs)
|
|
276
240
|
{
|
|
277
241
|
MS_TRACE();
|
|
278
242
|
|
|
@@ -301,12 +265,91 @@ namespace RTC
|
|
|
301
265
|
static_cast<float>(Utils::Time::CompactNtpRttToTimeUs(compactNtp - dlsr - lastSr)) / 1000;
|
|
302
266
|
}
|
|
303
267
|
|
|
304
|
-
this->
|
|
305
|
-
|
|
306
|
-
|
|
268
|
+
this->jitter = static_cast<float>(report->GetJitter());
|
|
269
|
+
|
|
270
|
+
// Work out how much of what it reports as lost really was lost on the way
|
|
271
|
+
// to it, which is the only part this link is answerable for.
|
|
272
|
+
const auto loss = UpdateSendLoss(report);
|
|
307
273
|
|
|
308
274
|
// Update the score with the received RR.
|
|
309
|
-
UpdateScore(
|
|
275
|
+
UpdateScore(loss);
|
|
276
|
+
|
|
277
|
+
return loss;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
std::optional<RtpStreamSend::Loss> RtpStreamSend::UpdateSendLoss(RTC::RTCP::ReceiverReport* report)
|
|
281
|
+
{
|
|
282
|
+
MS_TRACE();
|
|
283
|
+
|
|
284
|
+
// Not a single packet has been sent, so there is no stretch of the stream
|
|
285
|
+
// this report can be measuring.
|
|
286
|
+
if (!this->lastRrSeq.has_value())
|
|
287
|
+
{
|
|
288
|
+
return std::nullopt;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// The remote endpoint counts its cycles from the first packet it saw, so
|
|
292
|
+
// the extended value it reports is not in our numbering. Only the 16 bits
|
|
293
|
+
// that travelled on the wire are, and this places them where they belong
|
|
294
|
+
// without disturbing what the unwrapper knows.
|
|
295
|
+
const int64_t rrSeq =
|
|
296
|
+
this->seqUnwrapper.PeekUnwrap(static_cast<uint16_t>(report->GetLastSeq())).GetValue();
|
|
297
|
+
// NOTE: It is signed and may go down, since a duplicate counts as a packet
|
|
298
|
+
// received twice.
|
|
299
|
+
const int32_t totalLost = std::max<int32_t>(report->GetTotalLost(), 0);
|
|
300
|
+
|
|
301
|
+
// A report that goes backwards is one that got reordered. Taking it would
|
|
302
|
+
// move the mark back and count a stretch of the stream twice.
|
|
303
|
+
if (rrSeq <= this->lastRrSeq.value())
|
|
304
|
+
{
|
|
305
|
+
return std::nullopt;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// What was never sent within the interval is what the remote endpoint
|
|
309
|
+
// counts as lost without this link having lost it.
|
|
310
|
+
const auto beginSeq = this->unsentSeqs.upper_bound(this->lastRrSeq.value());
|
|
311
|
+
const auto endSeq = this->unsentSeqs.upper_bound(rrSeq);
|
|
312
|
+
const auto unsentSeqCount = static_cast<int64_t>(std::distance(beginSeq, endSeq));
|
|
313
|
+
|
|
314
|
+
// Everything up to what this report has seen is settled.
|
|
315
|
+
this->unsentSeqs.erase(this->unsentSeqs.begin(), endSeq);
|
|
316
|
+
|
|
317
|
+
// The numbering was reset and the remote endpoint went on counting over the
|
|
318
|
+
// whole session, so there is nothing this report can be compared against. It
|
|
319
|
+
// only leaves the marks for the next one.
|
|
320
|
+
if (!this->lastRrTotalLost.has_value())
|
|
321
|
+
{
|
|
322
|
+
this->lastRrSeq = rrSeq;
|
|
323
|
+
this->lastRrTotalLost = totalLost;
|
|
324
|
+
|
|
325
|
+
return std::nullopt;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
const int64_t expectedPackets = (rrSeq - this->lastRrSeq.value()) - unsentSeqCount;
|
|
329
|
+
// A hole already counted by a previous report and filled in since makes
|
|
330
|
+
// the remote endpoint report fewer lost packets than before, so the
|
|
331
|
+
// difference may well come out negative.
|
|
332
|
+
const int64_t lostPackets =
|
|
333
|
+
int64_t{ totalLost } - this->lastRrTotalLost.value() - unsentSeqCount;
|
|
334
|
+
// What is reported cannot go backwards, so it takes the count held between
|
|
335
|
+
// nothing lost and everything expected lost.
|
|
336
|
+
const int64_t reportedLostPackets = std::clamp<int64_t>(lostPackets, 0, expectedPackets);
|
|
337
|
+
|
|
338
|
+
this->lastRrSeq = rrSeq;
|
|
339
|
+
this->lastRrTotalLost = totalLost;
|
|
340
|
+
|
|
341
|
+
// NOTE: It is a count over the whole life of the stream, so it is held below
|
|
342
|
+
// the maximum of its type rather than let overflow.
|
|
343
|
+
this->packetsLost = static_cast<int32_t>(std::min<int64_t>(
|
|
344
|
+
int64_t{ this->packetsLost } + reportedLostPackets, std::numeric_limits<int32_t>::max()));
|
|
345
|
+
// NOTE: The fraction is in 1/256 units, hence the shift, which is the
|
|
346
|
+
// scale a Receiver Report uses for its own.
|
|
347
|
+
this->fractionLost =
|
|
348
|
+
expectedPackets > 0
|
|
349
|
+
? static_cast<uint8_t>(std::min<int64_t>((reportedLostPackets << 8) / expectedPackets, 255))
|
|
350
|
+
: 0;
|
|
351
|
+
|
|
352
|
+
return Loss{ .lostPackets = lostPackets, .expectedPackets = expectedPackets };
|
|
310
353
|
}
|
|
311
354
|
|
|
312
355
|
void RtpStreamSend::ReceiveRtcpXrReceiverReferenceTime(
|
|
@@ -423,8 +466,22 @@ namespace RTC
|
|
|
423
466
|
this->retransmissionBuffer->Clear();
|
|
424
467
|
}
|
|
425
468
|
|
|
469
|
+
// Discard pending retransmissions.
|
|
470
|
+
this->pendingRetransmissionsQueue.clear();
|
|
471
|
+
this->pendingRetransmissionsSet.clear();
|
|
472
|
+
|
|
473
|
+
if (this->retransmissionTimer)
|
|
474
|
+
{
|
|
475
|
+
this->retransmissionTimer->Stop();
|
|
476
|
+
}
|
|
477
|
+
|
|
426
478
|
// Reset jitter.
|
|
427
479
|
this->jitter = 0;
|
|
480
|
+
|
|
481
|
+
// Nothing is being measured while the stream is paused, and the numbering
|
|
482
|
+
// goes on where it was once it resumes, so the marks the next Receiver
|
|
483
|
+
// Report is measured against are left alone.
|
|
484
|
+
this->fractionLost = 0;
|
|
428
485
|
}
|
|
429
486
|
|
|
430
487
|
void RtpStreamSend::Resume()
|
|
@@ -432,6 +489,58 @@ namespace RTC
|
|
|
432
489
|
MS_TRACE();
|
|
433
490
|
}
|
|
434
491
|
|
|
492
|
+
void RtpStreamSend::UpdateUnsentSeqNumbers(uint16_t seq)
|
|
493
|
+
{
|
|
494
|
+
MS_TRACE();
|
|
495
|
+
|
|
496
|
+
const int64_t unwrappedSeq = this->seqUnwrapper.Unwrap(seq).GetValue();
|
|
497
|
+
|
|
498
|
+
// Nothing was sent before this one, so it leaves nothing behind. It is also
|
|
499
|
+
// where the interval of the first Receiver Report starts, so that the first
|
|
500
|
+
// one measures from here rather than from nowhere.
|
|
501
|
+
if (!this->highestSentSeq.has_value())
|
|
502
|
+
{
|
|
503
|
+
this->highestSentSeq = unwrappedSeq;
|
|
504
|
+
this->lastRrSeq = unwrappedSeq - 1;
|
|
505
|
+
|
|
506
|
+
return;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
// It arrived late and fills in one that was taken for never sent.
|
|
510
|
+
if (unwrappedSeq <= this->highestSentSeq.value())
|
|
511
|
+
{
|
|
512
|
+
this->unsentSeqs.erase(unwrappedSeq);
|
|
513
|
+
|
|
514
|
+
return;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
// Whatever it skipped was never handed to this stream and never will be:
|
|
518
|
+
// it is what the uplink of the Producer lost and nobody could forward.
|
|
519
|
+
//
|
|
520
|
+
// NOTE: Only the most recent ones are taken, since anything older than that
|
|
521
|
+
// is what the bound below would drop right away anyway, and a numbering
|
|
522
|
+
// that jumps far ahead must not cost a walk over half the sequence number
|
|
523
|
+
// space.
|
|
524
|
+
const int64_t firstUnsentSeq = std::max<int64_t>(
|
|
525
|
+
this->highestSentSeq.value() + 1,
|
|
526
|
+
unwrappedSeq - static_cast<int64_t>(RtpStreamSend::MaxUnsentSeqNumbers));
|
|
527
|
+
|
|
528
|
+
for (int64_t unsentSeq{ firstUnsentSeq }; unsentSeq < unwrappedSeq; ++unsentSeq)
|
|
529
|
+
{
|
|
530
|
+
this->unsentSeqs.insert(unsentSeq);
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
this->highestSentSeq = unwrappedSeq;
|
|
534
|
+
|
|
535
|
+
// Only a Receiver Report drains this, so a remote endpoint that stops
|
|
536
|
+
// reporting must not make it grow without end. The oldest ones go, which
|
|
537
|
+
// are the ones the next report is least likely to name.
|
|
538
|
+
while (this->unsentSeqs.size() > RtpStreamSend::MaxUnsentSeqNumbers)
|
|
539
|
+
{
|
|
540
|
+
this->unsentSeqs.erase(this->unsentSeqs.begin());
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
|
|
435
544
|
int64_t RtpStreamSend::GetBitrate(
|
|
436
545
|
int64_t /*nowMs*/, uint8_t /*spatialLayer*/, uint8_t /*temporalLayer*/)
|
|
437
546
|
{
|
|
@@ -455,221 +564,245 @@ namespace RTC
|
|
|
455
564
|
MS_ABORT("invalid method call");
|
|
456
565
|
}
|
|
457
566
|
|
|
458
|
-
// This method
|
|
459
|
-
//
|
|
567
|
+
// This method takes pending retransmissions from the front of the queue and
|
|
568
|
+
// retransmits their packets until MaxRetransmittedPacketsPerIteration packets
|
|
569
|
+
// have been retransmitted or the queue is empty. Pending retransmissions whose
|
|
570
|
+
// packet is not retransmitted don't count.
|
|
460
571
|
//
|
|
461
|
-
// If RTX is used the stored packet will be RTX encoded now
|
|
462
|
-
|
|
463
|
-
//
|
|
464
|
-
// NOTE: This method doesn't verify whether requested stored packet is too
|
|
465
|
-
// old, why? Because, if we verified it, we would do it by comparing its
|
|
466
|
-
// timestamp with the newest one in the retransmission buffer. However we
|
|
467
|
-
// already clean old packets upon receipt of any new packet (see Insert()
|
|
468
|
-
// method in RetransmissionBuffer class).
|
|
469
|
-
void RtpStreamSend::FillRetransmissionContainer(uint16_t seq, uint16_t bitmask)
|
|
572
|
+
// If RTX is used the stored packet will be RTX encoded now.
|
|
573
|
+
void RtpStreamSend::RetransmitPendingPackets()
|
|
470
574
|
{
|
|
471
575
|
MS_TRACE();
|
|
472
576
|
|
|
473
|
-
|
|
474
|
-
|
|
577
|
+
const int64_t nowMs = this->shared->GetTimeMs();
|
|
578
|
+
const int64_t rttMs = (this->rttMs > 0.0f ? static_cast<int64_t>(this->rttMs) : DefaultRttMs);
|
|
579
|
+
|
|
580
|
+
size_t numRetransmittedPackets{ 0 };
|
|
475
581
|
|
|
476
|
-
|
|
477
|
-
|
|
582
|
+
while (!this->pendingRetransmissionsQueue.empty() &&
|
|
583
|
+
numRetransmittedPackets < MaxRetransmittedPacketsPerIteration)
|
|
478
584
|
{
|
|
479
|
-
|
|
585
|
+
const uint16_t seq = this->pendingRetransmissionsQueue.front();
|
|
480
586
|
|
|
481
|
-
|
|
482
|
-
|
|
587
|
+
this->pendingRetransmissionsQueue.pop_front();
|
|
588
|
+
this->pendingRetransmissionsSet.erase(seq);
|
|
483
589
|
|
|
484
|
-
|
|
485
|
-
const int64_t nowMs = this->shared->GetTimeMs();
|
|
486
|
-
const int64_t rttMs = (this->rttMs > 0.0f ? static_cast<int64_t>(this->rttMs) : DefaultRttMs);
|
|
487
|
-
uint16_t currentSeq = seq;
|
|
488
|
-
bool requested{ true };
|
|
489
|
-
size_t containerIdx{ 0 };
|
|
490
|
-
|
|
491
|
-
// Variables for debugging.
|
|
492
|
-
const uint16_t origBitmask = bitmask;
|
|
493
|
-
uint16_t sentBitmask{ 0b0000000000000000 };
|
|
494
|
-
bool isFirstPacket{ true };
|
|
495
|
-
bool firstPacketSent{ false };
|
|
496
|
-
uint8_t bitmaskCounter{ 0 };
|
|
497
|
-
|
|
498
|
-
while (requested || bitmask != 0)
|
|
499
|
-
{
|
|
500
|
-
bool sent = false;
|
|
590
|
+
RTP::RetransmissionBuffer::Item* const item = this->retransmissionBuffer->Get(seq);
|
|
501
591
|
|
|
502
|
-
|
|
592
|
+
// Packet not found.
|
|
593
|
+
if (!item)
|
|
503
594
|
{
|
|
504
|
-
|
|
595
|
+
MS_DEBUG_DEV("ignoring retransmission for a packet not stored [seq:%" PRIu16 "]", seq);
|
|
505
596
|
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
597
|
+
continue;
|
|
598
|
+
}
|
|
599
|
+
// Don't resend the packet if it was stored too long ago.
|
|
600
|
+
else if (this->retransmissionBuffer->IsTooOld(item, nowMs))
|
|
601
|
+
{
|
|
602
|
+
MS_DEBUG_DEV(
|
|
603
|
+
"ignoring retransmission for a packet stored too long ago [seq:%" PRIu16
|
|
604
|
+
", stored:%" PRIi64 " ms ago]",
|
|
605
|
+
seq,
|
|
606
|
+
nowMs - item->storedAtMs);
|
|
607
|
+
|
|
608
|
+
continue;
|
|
609
|
+
}
|
|
610
|
+
// Don't resend the packet if it was resent in the last RTT ms.
|
|
611
|
+
else if (item->resentAtMs != 0 && nowMs - item->resentAtMs <= rttMs)
|
|
612
|
+
{
|
|
613
|
+
MS_DEBUG_TAG(
|
|
614
|
+
rtx,
|
|
615
|
+
"ignoring retransmission for a packet already resent in the last RTT ms "
|
|
616
|
+
"[seq:%" PRIu16 ", rtt:%" PRIi64 " ms]",
|
|
617
|
+
item->sequenceNumber,
|
|
618
|
+
rttMs);
|
|
526
619
|
|
|
527
|
-
|
|
528
|
-
|
|
620
|
+
continue;
|
|
621
|
+
}
|
|
529
622
|
|
|
530
|
-
|
|
531
|
-
|
|
623
|
+
// Save when this packet was resent.
|
|
624
|
+
item->resentAtMs = nowMs;
|
|
532
625
|
|
|
533
|
-
|
|
626
|
+
// Increase the number of times this packet was sent.
|
|
627
|
+
item->sentTimes++;
|
|
534
628
|
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
629
|
+
MS_ASSERT(
|
|
630
|
+
item->sharedPacket.HasPacket(),
|
|
631
|
+
"stored item doesn't contain a packet [ssrc:%" PRIu32 ", seq:%" PRIu16
|
|
632
|
+
", timestamp:%" PRIu32 "]",
|
|
633
|
+
item->ssrc,
|
|
634
|
+
item->sequenceNumber,
|
|
635
|
+
item->timestamp);
|
|
636
|
+
|
|
637
|
+
auto* const packet = item->sharedPacket.GetPacket();
|
|
638
|
+
|
|
639
|
+
// Keep the values of the original packet received by the Consumer.
|
|
640
|
+
const auto origSsrc = packet->GetSsrc();
|
|
641
|
+
const auto origSeq = packet->GetSequenceNumber();
|
|
642
|
+
const auto origTimestamp = packet->GetTimestamp();
|
|
643
|
+
const auto origMarker = packet->HasMarker();
|
|
541
644
|
|
|
542
|
-
|
|
543
|
-
bitmask >>= 1;
|
|
544
|
-
currentSeq++;
|
|
645
|
+
std::string origMid;
|
|
545
646
|
|
|
546
|
-
|
|
647
|
+
// Put correct info into the packet.
|
|
648
|
+
packet->SetSsrc(item->ssrc);
|
|
649
|
+
packet->SetSequenceNumber(item->sequenceNumber);
|
|
650
|
+
packet->SetTimestamp(item->timestamp);
|
|
651
|
+
packet->SetMarker(item->marker);
|
|
652
|
+
|
|
653
|
+
if (item->encoder != nullptr)
|
|
547
654
|
{
|
|
548
|
-
|
|
549
|
-
bitmaskCounter++;
|
|
655
|
+
packet->EncodePayload(item->encoder.get());
|
|
550
656
|
}
|
|
551
|
-
|
|
657
|
+
|
|
658
|
+
// Update MID RTP extension value.
|
|
659
|
+
if (!this->mid.empty())
|
|
552
660
|
{
|
|
553
|
-
|
|
661
|
+
packet->ReadMid(origMid);
|
|
662
|
+
packet->UpdateMid(this->mid);
|
|
554
663
|
}
|
|
555
|
-
}
|
|
556
664
|
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
", first:%s, "
|
|
563
|
-
"bitmask:" MS_UINT16_TO_BINARY_PATTERN ", sent bitmask:" MS_UINT16_TO_BINARY_PATTERN "]",
|
|
564
|
-
seq,
|
|
565
|
-
firstPacketSent ? "yes" : "no",
|
|
566
|
-
MS_UINT16_TO_BINARY(origBitmask),
|
|
567
|
-
MS_UINT16_TO_BINARY(sentBitmask));
|
|
568
|
-
}
|
|
569
|
-
else
|
|
570
|
-
{
|
|
571
|
-
MS_DEBUG_DEV(
|
|
572
|
-
"all packets resent [seq:%" PRIu16 ", bitmask:" MS_UINT16_TO_BINARY_PATTERN "]",
|
|
573
|
-
seq,
|
|
574
|
-
MS_UINT16_TO_BINARY(origBitmask));
|
|
575
|
-
}
|
|
665
|
+
// If we use RTX, encode it.
|
|
666
|
+
if (HasRtx())
|
|
667
|
+
{
|
|
668
|
+
// Increment RTX seq.
|
|
669
|
+
this->rtxSeq++;
|
|
576
670
|
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
}
|
|
671
|
+
packet->RtxEncode(this->params.rtxPayloadType, this->params.rtxSsrc, this->rtxSeq);
|
|
672
|
+
}
|
|
580
673
|
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
674
|
+
// Retransmit the packet.
|
|
675
|
+
static_cast<RTP::RtpStreamSend::Listener*>(this->listener)
|
|
676
|
+
->OnRtpStreamRetransmitRtpPacket(this, packet);
|
|
584
677
|
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
const auto sent = totalSent - this->sentPriorScore;
|
|
678
|
+
// Mark the packet as retransmitted.
|
|
679
|
+
RTP::RtpStream::PacketRetransmitted(packet);
|
|
588
680
|
|
|
589
|
-
|
|
681
|
+
// Mark the packet as repaired (only if this is the first retransmission).
|
|
682
|
+
if (item->sentTimes == 1)
|
|
683
|
+
{
|
|
684
|
+
RTP::RtpStream::PacketRepaired(packet);
|
|
685
|
+
}
|
|
590
686
|
|
|
591
|
-
|
|
592
|
-
|
|
687
|
+
// If we use RTX, restore it.
|
|
688
|
+
if (HasRtx())
|
|
689
|
+
{
|
|
690
|
+
// Restore the packet.
|
|
691
|
+
packet->RtxDecode(RtpStream::GetPayloadType(), item->ssrc);
|
|
692
|
+
}
|
|
593
693
|
|
|
594
|
-
|
|
694
|
+
// Restore MID.
|
|
695
|
+
if (!this->mid.empty())
|
|
696
|
+
{
|
|
697
|
+
packet->UpdateMid(origMid);
|
|
698
|
+
}
|
|
595
699
|
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
{
|
|
602
|
-
lost = totalLost - this->lostPriorScore;
|
|
603
|
-
}
|
|
700
|
+
// Restore payload.
|
|
701
|
+
if (item->encoder != nullptr)
|
|
702
|
+
{
|
|
703
|
+
packet->RestorePayload();
|
|
704
|
+
}
|
|
604
705
|
|
|
605
|
-
|
|
706
|
+
// Restore RTP header fields.
|
|
707
|
+
packet->SetSsrc(origSsrc);
|
|
708
|
+
packet->SetSequenceNumber(origSeq);
|
|
709
|
+
packet->SetTimestamp(origTimestamp);
|
|
710
|
+
packet->SetMarker(origMarker);
|
|
606
711
|
|
|
607
|
-
|
|
608
|
-
|
|
712
|
+
numRetransmittedPackets++;
|
|
713
|
+
}
|
|
714
|
+
}
|
|
609
715
|
|
|
610
|
-
|
|
716
|
+
void RtpStreamSend::UpdateScore(const std::optional<Loss>& loss)
|
|
717
|
+
{
|
|
718
|
+
MS_TRACE();
|
|
611
719
|
|
|
612
|
-
this
|
|
720
|
+
// Calculate the packets of this interval, which is what each counter has
|
|
721
|
+
// grown by since the previous score update.
|
|
722
|
+
const auto totalSentPackets = this->transmissionCounter.GetPacketCount();
|
|
723
|
+
const auto totalRepairedPackets = this->packetsRepaired;
|
|
724
|
+
const auto totalRetransmittedPackets = this->packetsRetransmitted;
|
|
725
|
+
const auto sentPackets = totalSentPackets - this->sentPriorScore;
|
|
726
|
+
const auto retransmittedPackets = totalRetransmittedPackets - this->retransmittedPriorScore;
|
|
613
727
|
|
|
614
|
-
|
|
615
|
-
const auto totatRetransmitted = this->packetsRetransmitted;
|
|
616
|
-
const auto retransmitted = totatRetransmitted - this->retransmittedPriorScore;
|
|
728
|
+
auto repairedPackets = totalRepairedPackets - this->repairedPriorScore;
|
|
617
729
|
|
|
618
|
-
this->
|
|
730
|
+
this->sentPriorScore = totalSentPackets;
|
|
731
|
+
this->repairedPriorScore = totalRepairedPackets;
|
|
732
|
+
this->retransmittedPriorScore = totalRetransmittedPackets;
|
|
733
|
+
|
|
734
|
+
// The Receiver Report measured no stretch of the stream, so there is nothing
|
|
735
|
+
// to say about this interval. The counters above have been taken anyway, so
|
|
736
|
+
// that the next one is measured over what it really covers.
|
|
737
|
+
if (!loss.has_value())
|
|
738
|
+
{
|
|
739
|
+
return;
|
|
740
|
+
}
|
|
619
741
|
|
|
620
742
|
// We didn't send any packet.
|
|
621
|
-
if (
|
|
743
|
+
if (sentPackets == 0)
|
|
622
744
|
{
|
|
623
745
|
RTP::RtpStream::UpdateScore(10);
|
|
624
746
|
|
|
625
747
|
return;
|
|
626
748
|
}
|
|
627
749
|
|
|
628
|
-
lost
|
|
629
|
-
|
|
750
|
+
// Number of packets lost in this interval, which is what this link really
|
|
751
|
+
// lost and not what the remote endpoint reported, since that one also
|
|
752
|
+
// counts the sequence numbers that were never sent.
|
|
753
|
+
//
|
|
754
|
+
// NOTE: A report that gives back what a previous one was overcharged leaves
|
|
755
|
+
// this interval with nothing lost.
|
|
756
|
+
auto lostPackets = static_cast<uint64_t>(std::max<int64_t>(loss.value().lostPackets, 0));
|
|
757
|
+
|
|
758
|
+
lostPackets = std::min(lostPackets, sentPackets);
|
|
759
|
+
repairedPackets = std::min(repairedPackets, lostPackets);
|
|
630
760
|
|
|
631
761
|
#if MS_LOG_DEV_LEVEL == 3
|
|
632
762
|
MS_DEBUG_TAG(
|
|
633
763
|
score,
|
|
634
|
-
"[
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
764
|
+
"[totalSentPackets:%" PRIu64 ", totalLostPackets:%" PRIi32 ", totalRepairedPackets:%" PRIu64,
|
|
765
|
+
totalSentPackets,
|
|
766
|
+
this->packetsLost,
|
|
767
|
+
totalRepairedPackets);
|
|
638
768
|
|
|
639
769
|
MS_DEBUG_TAG(
|
|
640
770
|
score,
|
|
641
|
-
"fixed values [
|
|
642
|
-
",
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
771
|
+
"fixed values [sentPackets:%" PRIu64 ", lostPackets:%" PRIu64 ", repairedPackets:%" PRIu64
|
|
772
|
+
", retransmittedPackets:%" PRIu64,
|
|
773
|
+
sentPackets,
|
|
774
|
+
lostPackets,
|
|
775
|
+
repairedPackets,
|
|
776
|
+
retransmittedPackets);
|
|
647
777
|
#endif
|
|
648
778
|
|
|
649
|
-
auto repairedRatio = static_cast<float>(
|
|
779
|
+
auto repairedRatio = static_cast<float>(repairedPackets) / static_cast<float>(sentPackets);
|
|
650
780
|
auto repairedWeight = std::pow(1 / (repairedRatio + 1), 4);
|
|
651
781
|
|
|
652
|
-
MS_ASSERT(
|
|
782
|
+
MS_ASSERT(
|
|
783
|
+
retransmittedPackets >= repairedPackets,
|
|
784
|
+
"repaired packets cannot be more than retransmitted ones");
|
|
653
785
|
|
|
654
|
-
if (
|
|
786
|
+
if (retransmittedPackets > 0)
|
|
655
787
|
{
|
|
656
|
-
repairedWeight *= static_cast<float>(
|
|
788
|
+
repairedWeight *= static_cast<float>(repairedPackets) / retransmittedPackets;
|
|
657
789
|
}
|
|
658
790
|
|
|
659
|
-
|
|
791
|
+
lostPackets = static_cast<uint64_t>(lostPackets - (repairedPackets * repairedWeight));
|
|
660
792
|
|
|
661
|
-
auto deliveredRatio =
|
|
662
|
-
|
|
793
|
+
auto deliveredRatio =
|
|
794
|
+
static_cast<float>(sentPackets - lostPackets) / static_cast<float>(sentPackets);
|
|
795
|
+
auto score = static_cast<uint8_t>(std::round(std::pow(deliveredRatio, 4) * 10));
|
|
663
796
|
|
|
664
797
|
#if MS_LOG_DEV_LEVEL == 3
|
|
665
798
|
MS_DEBUG_TAG(
|
|
666
799
|
score,
|
|
667
|
-
"[deliveredRatio:%f, repairedRatio:%f, repairedWeight:%f, new
|
|
800
|
+
"[deliveredRatio:%f, repairedRatio:%f, repairedWeight:%f, new lostPackets:%" PRIu64
|
|
668
801
|
", score:%" PRIu8 "]",
|
|
669
802
|
deliveredRatio,
|
|
670
803
|
repairedRatio,
|
|
671
804
|
repairedWeight,
|
|
672
|
-
|
|
805
|
+
lostPackets,
|
|
673
806
|
score);
|
|
674
807
|
#endif
|
|
675
808
|
|
|
@@ -686,6 +819,57 @@ namespace RTC
|
|
|
686
819
|
{
|
|
687
820
|
this->retransmissionBuffer->Clear();
|
|
688
821
|
}
|
|
822
|
+
|
|
823
|
+
// Discard pending retransmissions, since their sequence numbers belong to
|
|
824
|
+
// the previous numbering.
|
|
825
|
+
this->pendingRetransmissionsQueue.clear();
|
|
826
|
+
this->pendingRetransmissionsSet.clear();
|
|
827
|
+
|
|
828
|
+
if (this->retransmissionTimer)
|
|
829
|
+
{
|
|
830
|
+
this->retransmissionTimer->Stop();
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
ResetSendLoss();
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
void RtpStreamSend::ResetSendLoss()
|
|
837
|
+
{
|
|
838
|
+
MS_TRACE();
|
|
839
|
+
|
|
840
|
+
// What was never sent belongs to a numbering that is not in use anymore,
|
|
841
|
+
// and so does the mark the next Receiver Report would be measured against.
|
|
842
|
+
this->seqUnwrapper.Reset();
|
|
843
|
+
this->unsentSeqs.clear();
|
|
844
|
+
this->highestSentSeq.reset();
|
|
845
|
+
this->lastRrSeq.reset();
|
|
846
|
+
// The remote endpoint counts what it has lost over the whole session and
|
|
847
|
+
// does not reset along with us, so the next Receiver Report cannot be a
|
|
848
|
+
// difference against anything and can only become the new mark.
|
|
849
|
+
this->lastRrTotalLost.reset();
|
|
850
|
+
// Nothing has been measured over this numbering, and holding on to what
|
|
851
|
+
// was measured over the previous one would keep reporting it for as long
|
|
852
|
+
// as the stream stays quiet.
|
|
853
|
+
//
|
|
854
|
+
// NOTE: The total of lost packets is not cleared, being a count over the
|
|
855
|
+
// whole life of the stream rather than a measure of its current state.
|
|
856
|
+
this->fractionLost = 0;
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
void RtpStreamSend::OnTimer(TimerHandleInterface* timer)
|
|
860
|
+
{
|
|
861
|
+
MS_TRACE();
|
|
862
|
+
|
|
863
|
+
if (timer == this->retransmissionTimer.get())
|
|
864
|
+
{
|
|
865
|
+
RetransmitPendingPackets();
|
|
866
|
+
|
|
867
|
+
// Schedule the next iteration if there are retransmissions left.
|
|
868
|
+
if (!this->pendingRetransmissionsQueue.empty())
|
|
869
|
+
{
|
|
870
|
+
this->retransmissionTimer->Start(RetransmissionIntervalMs);
|
|
871
|
+
}
|
|
872
|
+
}
|
|
689
873
|
}
|
|
690
874
|
} // namespace RTP
|
|
691
875
|
} // namespace RTC
|