mediasoup 3.27.0 → 3.28.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 +19 -0
- package/node/lib/Consumer.d.ts.map +1 -1
- package/node/lib/Consumer.js +4 -51
- package/node/lib/Producer.d.ts.map +1 -1
- package/node/lib/Producer.js +4 -8
- package/node/lib/ProducerTypes.d.ts +4 -2
- package/node/lib/ProducerTypes.d.ts.map +1 -1
- package/node/lib/Router.d.ts.map +1 -1
- package/node/lib/Router.js +4 -0
- package/node/lib/Transport.d.ts.map +1 -1
- package/node/lib/Transport.js +7 -10
- package/node/lib/fbs/rtp-parameters/rtp-header-extension-uri.d.ts +3 -4
- package/node/lib/fbs/rtp-parameters/rtp-header-extension-uri.d.ts.map +1 -1
- package/node/lib/fbs/rtp-parameters/rtp-header-extension-uri.js +3 -4
- package/node/lib/ortc.d.ts +0 -2
- package/node/lib/ortc.d.ts.map +1 -1
- package/node/lib/ortc.js +11 -21
- package/node/lib/rtpMappingFbsUtils.d.ts +6 -0
- package/node/lib/rtpMappingFbsUtils.d.ts.map +1 -0
- package/node/lib/rtpMappingFbsUtils.js +65 -0
- package/node/lib/rtpParametersFbsUtils.d.ts.map +1 -1
- package/node/lib/rtpParametersFbsUtils.js +0 -6
- package/node/lib/rtpParametersTypes.d.ts +1 -1
- package/node/lib/rtpParametersTypes.d.ts.map +1 -1
- package/node/lib/rtpStreamFbsUtils.d.ts +4 -0
- package/node/lib/rtpStreamFbsUtils.d.ts.map +1 -0
- package/node/lib/rtpStreamFbsUtils.js +51 -0
- package/node/lib/supportedRtpCapabilities.d.ts.map +1 -1
- package/node/lib/supportedRtpCapabilities.js +6 -13
- package/node/lib/test/test-Consumer.js +1 -13
- package/node/lib/test/test-DataConsumer.js +9 -0
- package/node/lib/test/test-DataProducer.js +38 -0
- package/node/lib/test/test-PipeTransport.js +27 -29
- package/node/lib/test/test-Producer.js +97 -0
- package/node/lib/test/test-ortc.js +34 -14
- package/package.json +10 -10
- package/worker/fbs/FBS/meson.build +25 -0
- package/worker/fbs/meson.build +15 -18
- package/worker/fbs/rtpParameters.fbs +0 -1
- package/worker/fuzzer/src/FuzzerUtils.cpp +5 -3
- package/worker/fuzzer/src/RTC/RTP/FuzzerPacket.cpp +16 -2
- package/worker/include/DepLibUV.hpp +13 -0
- package/worker/include/RTC/BWE/AlrDetector.hpp +97 -0
- package/worker/include/RTC/BWE/BitrateProber.hpp +217 -0
- package/worker/include/RTC/BWE/BitrateUtils.hpp +39 -0
- package/worker/include/RTC/BWE/BweTypes.hpp +171 -3
- package/worker/include/RTC/BWE/FeedbackAdapter.hpp +0 -14
- package/worker/include/RTC/BWE/InterArrival.hpp +117 -0
- package/worker/include/RTC/BWE/IntervalBudget.hpp +81 -0
- package/worker/include/RTC/BWE/LossBasedController.hpp +625 -0
- package/worker/include/RTC/BWE/OveruseDetector.hpp +71 -0
- package/worker/include/RTC/BWE/OveruseEstimator.hpp +115 -0
- package/worker/include/RTC/BWE/ProbeBitrateEstimator.hpp +84 -0
- package/worker/include/RTC/BWE/ProbeController.hpp +379 -0
- package/worker/include/RTC/BWE/ProbePacketGenerator.hpp +130 -0
- package/worker/include/RTC/BWE/ProbingScheduler.hpp +187 -0
- package/worker/include/RTC/BWE/RembGenerator.hpp +96 -0
- package/worker/include/RTC/BWE/RemoteBitrateEstimatorAbsSendTime.hpp +237 -0
- package/worker/include/RTC/BWE/RobustThroughputEstimator.hpp +26 -0
- package/worker/include/RTC/BWE/SendPacketHistory.hpp +161 -25
- package/worker/include/RTC/BWE/TargetRateController.hpp +306 -0
- package/worker/include/RTC/BWE/TransportWideCcFeedbackGenerator.hpp +146 -0
- package/worker/include/RTC/BWE/TrendlineEstimator.hpp +73 -16
- package/worker/include/RTC/Consts.hpp +70 -0
- package/worker/include/RTC/DataConsumer.hpp +3 -5
- package/worker/include/RTC/DirectTransport.hpp +4 -5
- package/worker/include/RTC/PipeTransport.hpp +4 -5
- package/worker/include/RTC/PlainTransport.hpp +4 -5
- package/worker/include/RTC/RTCP/FeedbackPsRemb.hpp +6 -7
- package/worker/include/RTC/RTCP/FeedbackRtpTransport.hpp +3 -1
- package/worker/include/RTC/RTP/Codecs/Tools.hpp +1 -1
- package/worker/include/RTC/RTP/HeaderExtensionIds.hpp +0 -1
- package/worker/include/RTC/RTP/Packet.hpp +16 -4
- package/worker/include/RTC/RTP/ProbationGenerator.hpp +0 -8
- package/worker/include/RTC/RTP/RtpStream.hpp +12 -9
- package/worker/include/RTC/RTP/RtpStreamRecv.hpp +22 -4
- package/worker/include/RTC/RTP/RtpStreamSend.hpp +4 -2
- package/worker/include/RTC/RTP/RtxStream.hpp +10 -4
- package/worker/include/RTC/RateCalculator.hpp +103 -24
- package/worker/include/RTC/RemoteCaptureTimeEstimator.hpp +33 -3
- package/worker/include/RTC/{RtcLogger.hpp → RtcLogger/RtpPacket.hpp} +5 -3
- package/worker/include/RTC/RtcLogger/SendBurst.hpp +88 -0
- package/worker/include/RTC/RtpDictionaries.hpp +3 -4
- package/worker/include/RTC/SCTP/association/Association.hpp +1 -1
- package/worker/include/RTC/SCTP/association/StreamResetHandler.hpp +36 -0
- package/worker/include/RTC/SCTP/public/AssociationMetrics.hpp +0 -1
- package/worker/include/RTC/SCTP/public/SctpTypes.hpp +9 -9
- package/worker/include/RTC/SCTP/rx/DataTracker.hpp +1 -1
- package/worker/include/RTC/SCTP/rx/ReassemblyQueue.hpp +11 -1
- package/worker/include/RTC/SctpDictionaries.hpp +2 -2
- package/worker/include/RTC/TcpConnection.hpp +2 -1
- package/worker/include/RTC/Transport.hpp +23 -8
- package/worker/include/RTC/TransportTuple.hpp +61 -6
- package/worker/include/RTC/WebRtcTransport.hpp +4 -5
- package/worker/include/Shared.hpp +5 -0
- package/worker/include/SharedInterface.hpp +10 -0
- package/worker/include/Utils.hpp +72 -3
- package/worker/include/common.hpp +12 -4
- package/worker/include/handles/SendCallbacks.hpp +34 -0
- package/worker/include/handles/TcpConnectionHandle.hpp +4 -12
- package/worker/include/handles/UdpSocketHandle.hpp +4 -8
- package/worker/meson.build +45 -1
- package/worker/meson_options.txt +1 -0
- package/worker/mocks/include/MockShared.hpp +16 -2
- package/worker/mocks/include/handles/MockBackoffTimerHandle.hpp +1 -1
- package/worker/scripts/package-lock.json +6 -6
- package/worker/src/RTC/BWE/AimdRateControl.cpp +4 -5
- package/worker/src/RTC/BWE/AlrDetector.cpp +80 -0
- package/worker/src/RTC/BWE/BitrateProber.cpp +256 -0
- package/worker/src/RTC/BWE/BitrateUtils.cpp +54 -0
- package/worker/src/RTC/BWE/DelayBasedBwe.cpp +2 -2
- package/worker/src/RTC/BWE/FeedbackAdapter.cpp +20 -37
- package/worker/src/RTC/BWE/InterArrival.cpp +216 -0
- package/worker/src/RTC/BWE/IntervalBudget.cpp +93 -0
- package/worker/src/RTC/BWE/LossBasedController.cpp +1194 -0
- package/worker/src/RTC/BWE/OveruseDetector.cpp +128 -0
- package/worker/src/RTC/BWE/OveruseEstimator.cpp +166 -0
- package/worker/src/RTC/BWE/ProbeBitrateEstimator.cpp +222 -0
- package/worker/src/RTC/BWE/ProbeController.cpp +645 -0
- package/worker/src/RTC/BWE/ProbePacketGenerator.cpp +140 -0
- package/worker/src/RTC/BWE/ProbingScheduler.cpp +196 -0
- package/worker/src/RTC/BWE/RembGenerator.cpp +169 -0
- package/worker/src/RTC/BWE/RemoteBitrateEstimatorAbsSendTime.cpp +497 -0
- package/worker/src/RTC/BWE/RobustThroughputEstimator.cpp +47 -0
- package/worker/src/RTC/BWE/SendPacketHistory.cpp +173 -50
- package/worker/src/RTC/BWE/TargetRateController.cpp +433 -0
- package/worker/src/RTC/BWE/TransportWideCcFeedbackGenerator.cpp +377 -0
- package/worker/src/RTC/BWE/TrendlineEstimator.cpp +102 -5
- package/worker/src/RTC/Consumer.cpp +7 -5
- package/worker/src/RTC/DataConsumer.cpp +8 -10
- package/worker/src/RTC/DirectTransport.cpp +14 -8
- package/worker/src/RTC/DtlsTransport.cpp +8 -8
- package/worker/src/RTC/ICE/IceCandidate.cpp +4 -4
- package/worker/src/RTC/ICE/IceServer.cpp +1 -1
- package/worker/src/RTC/PipeTransport.cpp +13 -8
- package/worker/src/RTC/PlainTransport.cpp +13 -8
- package/worker/src/RTC/Producer.cpp +14 -31
- package/worker/src/RTC/RTCP/Bye.cpp +1 -1
- package/worker/src/RTC/RTCP/FeedbackPsRemb.cpp +18 -0
- package/worker/src/RTC/RTCP/FeedbackPsRpsi.cpp +2 -2
- package/worker/src/RTC/RTCP/FeedbackPsVbcm.cpp +2 -1
- package/worker/src/RTC/RTCP/FeedbackRtpTransport.cpp +2 -2
- package/worker/src/RTC/RTCP/Sdes.cpp +1 -1
- package/worker/src/RTC/RTP/Codecs/DependencyDescriptor.cpp +2 -1
- package/worker/src/RTC/RTP/Packet.cpp +26 -11
- package/worker/src/RTC/RTP/ProbationGenerator.cpp +5 -6
- package/worker/src/RTC/RTP/RtpStream.cpp +1 -1
- package/worker/src/RTC/RTP/RtpStreamRecv.cpp +69 -48
- package/worker/src/RTC/RTP/RtpStreamSend.cpp +31 -31
- package/worker/src/RTC/RTP/RtxStream.cpp +22 -7
- package/worker/src/RTC/RateCalculator.cpp +133 -28
- package/worker/src/RTC/RemoteCaptureTimeEstimator.cpp +56 -1
- package/worker/src/RTC/{RtcLogger.cpp → RtcLogger/RtpPacket.cpp} +2 -2
- package/worker/src/RTC/RtcLogger/SendBurst.cpp +124 -0
- package/worker/src/RTC/RtpDictionaries/RtpHeaderExtensionUri.cpp +2 -12
- package/worker/src/RTC/RtpDictionaries/RtpParameters.cpp +1 -1
- package/worker/src/RTC/SCTP/association/Association.cpp +16 -2
- package/worker/src/RTC/SCTP/association/StreamResetHandler.cpp +106 -1
- package/worker/src/RTC/SCTP/public/AssociationMetrics.cpp +1 -1
- package/worker/src/RTC/SCTP/rx/InterleavedReassemblyStreams.cpp +3 -3
- package/worker/src/RTC/SCTP/rx/ReassemblyQueue.cpp +2 -1
- package/worker/src/RTC/SCTP/rx/TraditionalReassemblyStreams.cpp +4 -4
- package/worker/src/RTC/SCTP/tx/RetransmissionTimeout.cpp +4 -4
- package/worker/src/RTC/SctpDictionaries/SctpStreamParameters.cpp +6 -10
- package/worker/src/RTC/SimulcastProducerStreamManager.cpp +2 -2
- package/worker/src/RTC/SrtpSession.cpp +2 -2
- package/worker/src/RTC/SvcProducerStreamManager.cpp +2 -2
- package/worker/src/RTC/TcpConnection.cpp +2 -2
- package/worker/src/RTC/Transport.cpp +112 -75
- package/worker/src/RTC/TransportTuple.cpp +4 -4
- package/worker/src/RTC/WebRtcServer.cpp +4 -3
- package/worker/src/RTC/WebRtcTransport.cpp +20 -13
- package/worker/src/Utils/BitStream.cpp +24 -0
- package/worker/src/handles/BackoffTimerHandle.cpp +1 -1
- package/worker/src/handles/TcpConnectionHandle.cpp +13 -23
- package/worker/src/handles/UdpSocketHandle.cpp +14 -21
- package/worker/tasks.py +43 -18
- package/worker/test/include/RTC/BWE/helpers/LinkSimulator.hpp +68 -14
- package/worker/test/include/RTC/BWE/helpers/RemoteBitrateEstimatorAbsSendTimeTestHelper.hpp +125 -0
- package/worker/test/src/RTC/BWE/TestAlrDetector.cpp +110 -0
- package/worker/test/src/RTC/BWE/TestBitrateProber.cpp +418 -0
- package/worker/test/src/RTC/BWE/TestBitrateUtils.cpp +61 -0
- package/worker/test/src/RTC/BWE/TestDelayBasedBwe.cpp +4 -4
- package/worker/test/src/RTC/BWE/TestFeedbackAdapter.cpp +53 -37
- package/worker/test/src/RTC/BWE/TestInterArrival.cpp +643 -0
- package/worker/test/src/RTC/BWE/TestIntervalBudget.cpp +130 -0
- package/worker/test/src/RTC/BWE/TestLossBasedController.cpp +1199 -0
- package/worker/test/src/RTC/BWE/TestOveruseDetector.cpp +519 -0
- package/worker/test/src/RTC/BWE/TestProbeBitrateEstimator.cpp +266 -0
- package/worker/test/src/RTC/BWE/TestProbeController.cpp +1682 -0
- package/worker/test/src/RTC/BWE/TestProbePacketGenerator.cpp +265 -0
- package/worker/test/src/RTC/BWE/TestProbingScheduler.cpp +260 -0
- package/worker/test/src/RTC/BWE/TestRembGenerator.cpp +285 -0
- package/worker/test/src/RTC/BWE/TestRemoteBitrateEstimatorAbsSendTime.cpp +414 -0
- package/worker/test/src/RTC/BWE/TestSendPacketHistory.cpp +296 -77
- package/worker/test/src/RTC/BWE/TestTargetRateController.cpp +337 -0
- package/worker/test/src/RTC/BWE/TestTransportWideCcFeedbackGenerator.cpp +578 -0
- package/worker/test/src/RTC/BWE/TestTrendlineEstimator.cpp +45 -0
- package/worker/test/src/RTC/BWE/helpers/LinkSimulator.cpp +133 -29
- package/worker/test/src/RTC/BWE/helpers/RemoteBitrateEstimatorAbsSendTimeTestHelper.cpp +625 -0
- package/worker/test/src/RTC/RTCP/TestFeedbackPsRemb.cpp +19 -0
- package/worker/test/src/RTC/RTP/TestPacket.cpp +58 -4
- package/worker/test/src/RTC/RTP/TestProbationGenerator.cpp +3 -2
- package/worker/test/src/RTC/RTP/TestRtpStreamRecv.cpp +50 -0
- package/worker/test/src/RTC/RTP/TestRtpStreamSend.cpp +59 -0
- package/worker/test/src/RTC/SCTP/association/TestStreamResetHandler.cpp +111 -0
- package/worker/test/src/RTC/TestRateCalculator.cpp +322 -60
- package/worker/test/src/RTC/TestRemoteCaptureTimeEstimator.cpp +95 -7
- package/worker/test/src/RTC/TestSimpleProducerStreamManager.cpp +34 -16
- package/worker/test/src/RTC/TestSimulcastProducerStreamManager.cpp +31 -13
- package/worker/test/src/RTC/TestSvcProducerStreamManager.cpp +37 -19
- package/worker/test/src/RTC/TestTransportCongestionControlServer.cpp +10 -10
- package/worker/test/src/Utils/TestTime.cpp +120 -21
|
@@ -8,12 +8,23 @@
|
|
|
8
8
|
|
|
9
9
|
namespace RTC
|
|
10
10
|
{
|
|
11
|
+
/* Static. */
|
|
12
|
+
|
|
13
|
+
// Factor of the window size within which the latest sample still counts as
|
|
14
|
+
// recent.
|
|
15
|
+
static constexpr double RecentSampleMarginFactor{ 1.5 };
|
|
16
|
+
|
|
17
|
+
/* Instance methods. */
|
|
18
|
+
|
|
11
19
|
RateCalculator::RateCalculator(int64_t windowSizeMs, float scale, uint16_t windowItems)
|
|
12
20
|
{
|
|
13
21
|
MS_TRACE();
|
|
14
22
|
|
|
15
23
|
// Clamp the given values so every derived value is safe to use.
|
|
16
|
-
|
|
24
|
+
// NOTE: The upper bound is what keeps one window and a half, which is the
|
|
25
|
+
// margin computed at the end, within an int64_t.
|
|
26
|
+
this->windowSizeMs =
|
|
27
|
+
std::clamp<int64_t>(windowSizeMs, 1, std::numeric_limits<int64_t>::max() / 2);
|
|
17
28
|
|
|
18
29
|
const int64_t items = std::max<int64_t>(windowItems, 1);
|
|
19
30
|
|
|
@@ -28,36 +39,73 @@ namespace RTC
|
|
|
28
39
|
this->buffer.resize(
|
|
29
40
|
static_cast<size_t>((this->windowSizeMs + this->itemSizeMs - 1) / this->itemSizeMs));
|
|
30
41
|
|
|
31
|
-
|
|
42
|
+
// NOTE: A negative scale would give negative rates, which whoever reads them
|
|
43
|
+
// takes as a count of bits.
|
|
44
|
+
this->scale = std::max(static_cast<double>(scale), 0.0);
|
|
45
|
+
|
|
46
|
+
this->recentSampleMarginMs =
|
|
47
|
+
static_cast<int64_t>(RecentSampleMarginFactor * static_cast<double>(this->windowSizeMs));
|
|
32
48
|
}
|
|
33
49
|
|
|
34
50
|
void RateCalculator::Update(size_t size, int64_t nowMs)
|
|
35
51
|
{
|
|
36
52
|
MS_TRACE();
|
|
37
53
|
|
|
38
|
-
//
|
|
54
|
+
// Whether the window still held data when this sample arrived, and the sample
|
|
55
|
+
// before it is recent enough for both to be taken as the same stretch of
|
|
56
|
+
// traffic.
|
|
57
|
+
// NOTE: Must be told before sliding the window, since sliding it is what
|
|
58
|
+
// expires that data.
|
|
59
|
+
const bool lastSampleIsRecent =
|
|
60
|
+
this->totalSamples != 0 && this->lastSampleTimeMs.has_value() &&
|
|
61
|
+
this->lastSampleTimeMs.value() > nowMs - this->recentSampleMarginMs;
|
|
62
|
+
|
|
63
|
+
// A sample whose instant lies before the whole window is still data that
|
|
64
|
+
// went through, so it is taken as if it had been given at the instant the
|
|
65
|
+
// newest item starts at. Dropping it would leave the meter reporting less
|
|
66
|
+
// than what flowed with nobody able to tell, while placing it at the wrong
|
|
67
|
+
// instant is an error bounded by the window.
|
|
39
68
|
if (!SlideWindow(nowMs))
|
|
40
69
|
{
|
|
41
|
-
MS_WARN_DEV("given nowMs is older than the current window,
|
|
70
|
+
MS_WARN_DEV("given nowMs is older than the current window, taking the data as newer");
|
|
71
|
+
|
|
72
|
+
nowMs = this->newestItemStartTimeMs;
|
|
73
|
+
}
|
|
42
74
|
|
|
43
|
-
|
|
75
|
+
// The very first sample starts the measured period, and so does one that
|
|
76
|
+
// finds the window empty after long enough without traffic. A stream that
|
|
77
|
+
// just sends less often than the window keeps the period it had, so that it
|
|
78
|
+
// is measured over the window instead of restarting at every sample and
|
|
79
|
+
// hence never being measured at all.
|
|
80
|
+
if (!this->firstSampleTimeMs.has_value() || (this->totalSamples == 0 && !lastSampleIsRecent))
|
|
81
|
+
{
|
|
82
|
+
this->firstSampleTimeMs = nowMs;
|
|
83
|
+
this->firstSampleCount = size;
|
|
44
84
|
}
|
|
45
85
|
|
|
46
|
-
this->buffer[this->newestItemIndex]
|
|
86
|
+
Item& item = this->buffer[this->newestItemIndex];
|
|
87
|
+
|
|
88
|
+
item.count += size;
|
|
89
|
+
item.samples++;
|
|
90
|
+
|
|
47
91
|
this->totalCount += size;
|
|
92
|
+
this->totalSamples++;
|
|
48
93
|
this->bytes += size;
|
|
94
|
+
this->lastSampleTimeMs = nowMs;
|
|
49
95
|
}
|
|
50
96
|
|
|
51
|
-
int64_t RateCalculator::GetRate(int64_t nowMs)
|
|
97
|
+
std::optional<int64_t> RateCalculator::GetRate(int64_t nowMs)
|
|
52
98
|
{
|
|
53
99
|
MS_TRACE();
|
|
54
100
|
|
|
55
|
-
// If
|
|
56
|
-
// function of
|
|
57
|
-
// pending: SlideWindow() already ran for this very `nowMs`
|
|
58
|
-
// `newestItemStartTimeMs` only moves forward afterwards, while the
|
|
59
|
-
// post Reset() state has an empty ring anyway.
|
|
60
|
-
if (
|
|
101
|
+
// If every key matches, the memoized rate is still exact. `lastRate` is a
|
|
102
|
+
// pure function of the state the keys cover, so the value is right, and no
|
|
103
|
+
// expiration can be pending: SlideWindow() already ran for this very `nowMs`
|
|
104
|
+
// and `newestItemStartTimeMs` only moves forward afterwards, while the
|
|
105
|
+
// initial and post Reset() state has an empty ring anyway.
|
|
106
|
+
if (
|
|
107
|
+
nowMs == this->lastTimeMs && this->totalCount == this->lastTotalCount &&
|
|
108
|
+
this->totalSamples == this->lastTotalSamples)
|
|
61
109
|
{
|
|
62
110
|
MS_DEBUG_DEV("nothing changed since the latest call, early return");
|
|
63
111
|
|
|
@@ -66,13 +114,61 @@ namespace RTC
|
|
|
66
114
|
|
|
67
115
|
SlideWindow(nowMs);
|
|
68
116
|
|
|
69
|
-
const double rate = std::trunc((static_cast<double>(this->totalCount) * this->rateScale) + 0.5);
|
|
70
|
-
|
|
71
117
|
// NOTE: Must be read after SlideWindow(), which may have expired data.
|
|
72
|
-
this->lastTotalCount
|
|
73
|
-
this->
|
|
74
|
-
this->
|
|
75
|
-
|
|
118
|
+
this->lastTotalCount = this->totalCount;
|
|
119
|
+
this->lastTotalSamples = this->totalSamples;
|
|
120
|
+
this->lastTimeMs = nowMs;
|
|
121
|
+
this->lastRate = std::nullopt;
|
|
122
|
+
|
|
123
|
+
// Either no sample has ever been taken, or none of them is still within the
|
|
124
|
+
// window.
|
|
125
|
+
if (!this->firstSampleTimeMs.has_value() || this->totalSamples == 0)
|
|
126
|
+
{
|
|
127
|
+
return this->lastRate;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Period the data within the window actually spans. The instant the first
|
|
131
|
+
// sample was taken at already counts as a millisecond, hence the increment,
|
|
132
|
+
// which is also what keeps this from ever being zero. And once the data
|
|
133
|
+
// reaches back beyond the window, the period is the window itself.
|
|
134
|
+
const int64_t periodMs =
|
|
135
|
+
std::clamp<int64_t>(nowMs - this->firstSampleTimeMs.value() + 1, 1, this->windowSizeMs);
|
|
136
|
+
|
|
137
|
+
// A single millisecond gives no duration to divide by, and a single sample
|
|
138
|
+
// says how much data was taken at an instant but nothing about how fast it
|
|
139
|
+
// is flowing, so neither is a measurement until the window has filled.
|
|
140
|
+
if (periodMs <= 1 || (this->totalSamples <= 1 && periodMs < this->windowSizeMs))
|
|
141
|
+
{
|
|
142
|
+
return this->lastRate;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// While the period is anchored to a sample, that sample sits at its very
|
|
146
|
+
// start, so the period does not cover the time that sample took to arrive and
|
|
147
|
+
// its data is not part of what flowed during it. Counting it would report a
|
|
148
|
+
// rate too high by as much as the ratio of samples to gaps between them,
|
|
149
|
+
// which is double with two samples and a tenth with eleven.
|
|
150
|
+
//
|
|
151
|
+
// NOTE: Once the period is the whole window it is no longer anchored to any
|
|
152
|
+
// sample, all of them fall inside it, and every one of them counts. And that
|
|
153
|
+
// is also the point at which the anchoring sample has left the window, so
|
|
154
|
+
// there is nothing of it left to leave out.
|
|
155
|
+
const uint64_t count =
|
|
156
|
+
periodMs < this->windowSizeMs ? this->totalCount - this->firstSampleCount : this->totalCount;
|
|
157
|
+
|
|
158
|
+
const double rate =
|
|
159
|
+
std::trunc(((static_cast<double>(count) * this->scale) / static_cast<double>(periodMs)) + 0.5);
|
|
160
|
+
|
|
161
|
+
// A rate that does not fit is no rate at all, which is better than the
|
|
162
|
+
// garbage that converting it would give.
|
|
163
|
+
// NOTE: The comparison is not a strict one because converting the maximum of
|
|
164
|
+
// int64_t to double rounds it up, so a rate equal to that value is already
|
|
165
|
+
// out of range.
|
|
166
|
+
if (rate >= static_cast<double>(std::numeric_limits<int64_t>::max()))
|
|
167
|
+
{
|
|
168
|
+
return this->lastRate;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
this->lastRate = static_cast<int64_t>(rate);
|
|
76
172
|
|
|
77
173
|
return this->lastRate;
|
|
78
174
|
}
|
|
@@ -81,14 +177,19 @@ namespace RTC
|
|
|
81
177
|
{
|
|
82
178
|
MS_TRACE();
|
|
83
179
|
|
|
84
|
-
std::ranges::fill(this->buffer,
|
|
180
|
+
std::ranges::fill(this->buffer, Item{});
|
|
85
181
|
|
|
182
|
+
this->firstSampleTimeMs.reset();
|
|
183
|
+
this->firstSampleCount = 0;
|
|
184
|
+
this->lastSampleTimeMs.reset();
|
|
86
185
|
this->newestItemIndex = 0;
|
|
87
186
|
this->newestItemStartTimeMs = 0;
|
|
88
187
|
this->totalCount = 0;
|
|
89
|
-
this->
|
|
188
|
+
this->totalSamples = 0;
|
|
189
|
+
this->lastRate = std::nullopt;
|
|
90
190
|
this->lastTimeMs = 0;
|
|
91
191
|
this->lastTotalCount = 0;
|
|
192
|
+
this->lastTotalSamples = 0;
|
|
92
193
|
}
|
|
93
194
|
|
|
94
195
|
/**
|
|
@@ -127,13 +228,14 @@ namespace RTC
|
|
|
127
228
|
{
|
|
128
229
|
MS_DEBUG_DEV("a whole window elapsed, resetting every item");
|
|
129
230
|
|
|
130
|
-
// NOTE:
|
|
131
|
-
// the ring is already
|
|
132
|
-
if (this->
|
|
231
|
+
// NOTE: totalSamples is the sum of the samples of every item, so a zero
|
|
232
|
+
// total means that the ring is already empty.
|
|
233
|
+
if (this->totalSamples != 0)
|
|
133
234
|
{
|
|
134
|
-
std::ranges::fill(this->buffer,
|
|
235
|
+
std::ranges::fill(this->buffer, Item{});
|
|
135
236
|
|
|
136
|
-
this->totalCount
|
|
237
|
+
this->totalCount = 0;
|
|
238
|
+
this->totalSamples = 0;
|
|
137
239
|
}
|
|
138
240
|
|
|
139
241
|
this->newestItemIndex = 0;
|
|
@@ -151,9 +253,12 @@ namespace RTC
|
|
|
151
253
|
this->newestItemIndex = 0;
|
|
152
254
|
}
|
|
153
255
|
|
|
154
|
-
|
|
256
|
+
Item& item = this->buffer[this->newestItemIndex];
|
|
257
|
+
|
|
258
|
+
this->totalCount -= item.count;
|
|
259
|
+
this->totalSamples -= item.samples;
|
|
155
260
|
|
|
156
|
-
|
|
261
|
+
item = Item{};
|
|
157
262
|
}
|
|
158
263
|
|
|
159
264
|
// Advance by whole items rather than jumping to `nowMs`. The window is
|
|
@@ -3,9 +3,18 @@
|
|
|
3
3
|
|
|
4
4
|
#include "RTC/RemoteCaptureTimeEstimator.hpp"
|
|
5
5
|
#include "Logger.hpp"
|
|
6
|
+
#include "Utils.hpp"
|
|
6
7
|
|
|
7
8
|
namespace RTC
|
|
8
9
|
{
|
|
10
|
+
/* Static. */
|
|
11
|
+
|
|
12
|
+
// How long a sender that negotiated 'abs-capture-time' may go without sending it
|
|
13
|
+
// before the capture instant is read from its Sender Reports instead. It only has
|
|
14
|
+
// to outlast the first packets of a sender that does send it, since the extension
|
|
15
|
+
// travels on some of them rather than on every one.
|
|
16
|
+
static constexpr int64_t AbsCaptureTimeTimeoutMs{ 5 * 1000 };
|
|
17
|
+
|
|
9
18
|
/* Instance methods. */
|
|
10
19
|
|
|
11
20
|
void RemoteCaptureTimeEstimator::UpdateSource(bool absCaptureTimeNegotiated)
|
|
@@ -34,6 +43,50 @@ namespace RTC
|
|
|
34
43
|
: "Sender Report");
|
|
35
44
|
}
|
|
36
45
|
|
|
46
|
+
void RemoteCaptureTimeEstimator::MayFallBackToSenderReport(
|
|
47
|
+
const RTC::RTP::RtpStreamRecv* rtpStream, int64_t nowUs)
|
|
48
|
+
{
|
|
49
|
+
MS_TRACE();
|
|
50
|
+
|
|
51
|
+
if (this->source != RemoteCaptureTimeEstimator::Source::ABS_CAPTURE_TIME)
|
|
52
|
+
{
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Some stream of this sender has carried the extension at some point, so it is
|
|
57
|
+
// being sent and whatever stream has none of it is just early.
|
|
58
|
+
if (this->absCaptureTimeReceived)
|
|
59
|
+
{
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (rtpStream->HasAbsCaptureTime())
|
|
64
|
+
{
|
|
65
|
+
this->absCaptureTimeReceived = true;
|
|
66
|
+
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (!this->firstPacketAtUs.has_value())
|
|
71
|
+
{
|
|
72
|
+
this->firstPacketAtUs = nowUs;
|
|
73
|
+
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (Utils::Time::TimeUsToMs(nowUs - this->firstPacketAtUs.value()) < AbsCaptureTimeTimeoutMs)
|
|
78
|
+
{
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
MS_WARN_2TAGS(
|
|
83
|
+
rtp,
|
|
84
|
+
rtcp,
|
|
85
|
+
"abs-capture-time negotiated but never received, reading the capture instant from Sender Reports instead");
|
|
86
|
+
|
|
87
|
+
this->source = RemoteCaptureTimeEstimator::Source::SENDER_REPORT;
|
|
88
|
+
}
|
|
89
|
+
|
|
37
90
|
void RemoteCaptureTimeEstimator::SenderReportReceived(const RTC::RTP::RtpStreamRecv* rtpStream)
|
|
38
91
|
{
|
|
39
92
|
MS_TRACE();
|
|
@@ -54,7 +107,7 @@ namespace RTC
|
|
|
54
107
|
}
|
|
55
108
|
|
|
56
109
|
std::optional<int64_t> RemoteCaptureTimeEstimator::GetLocalCaptureAtUs(
|
|
57
|
-
const RTC::RTP::RtpStreamRecv* rtpStream, uint32_t ts)
|
|
110
|
+
const RTC::RTP::RtpStreamRecv* rtpStream, uint32_t ts, int64_t nowUs)
|
|
58
111
|
{
|
|
59
112
|
MS_TRACE();
|
|
60
113
|
|
|
@@ -63,6 +116,8 @@ namespace RTC
|
|
|
63
116
|
return std::nullopt;
|
|
64
117
|
}
|
|
65
118
|
|
|
119
|
+
MayFallBackToSenderReport(rtpStream, nowUs);
|
|
120
|
+
|
|
66
121
|
const auto remoteCaptureAtUs = this->source == RemoteCaptureTimeEstimator::Source::ABS_CAPTURE_TIME
|
|
67
122
|
? rtpStream->GetRemoteCaptureAtUsFromAbsCaptureTime(ts)
|
|
68
123
|
: rtpStream->GetRemoteCaptureAtUsFromSenderReport(ts);
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
#define MS_CLASS "RTC::RtcLogger::SendBurst"
|
|
2
|
+
// #define MS_LOG_DEV_LEVEL 3
|
|
3
|
+
|
|
4
|
+
#include "RTC/RtcLogger/SendBurst.hpp"
|
|
5
|
+
#include "Logger.hpp"
|
|
6
|
+
#include <sstream>
|
|
7
|
+
|
|
8
|
+
namespace RTC
|
|
9
|
+
{
|
|
10
|
+
namespace RtcLogger
|
|
11
|
+
{
|
|
12
|
+
/* Instance methods. */
|
|
13
|
+
|
|
14
|
+
void SendBurst::Sent(uint64_t loopTimeMs, size_t length, bool isRetransmission, bool isProbation)
|
|
15
|
+
{
|
|
16
|
+
MS_TRACE();
|
|
17
|
+
|
|
18
|
+
if (loopTimeMs != this->loopTimeMs)
|
|
19
|
+
{
|
|
20
|
+
CloseBurst();
|
|
21
|
+
|
|
22
|
+
this->loopTimeMs = loopTimeMs;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
this->packets++;
|
|
26
|
+
this->bytes += length;
|
|
27
|
+
|
|
28
|
+
if (isRetransmission)
|
|
29
|
+
{
|
|
30
|
+
this->retransmissions++;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (isProbation)
|
|
34
|
+
{
|
|
35
|
+
this->probations++;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
void SendBurst::Log()
|
|
40
|
+
{
|
|
41
|
+
MS_TRACE();
|
|
42
|
+
|
|
43
|
+
// The iteration this runs in is not the one any burst belongs to, so whatever
|
|
44
|
+
// is in progress is already complete.
|
|
45
|
+
CloseBurst();
|
|
46
|
+
|
|
47
|
+
// Nothing has been sent since the last time, and a transport that sends
|
|
48
|
+
// nothing has nothing to say.
|
|
49
|
+
if (this->maxPackets == 0)
|
|
50
|
+
{
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
std::stringstream ss;
|
|
55
|
+
|
|
56
|
+
ss << "{";
|
|
57
|
+
ss << R"("transportId": ")" << this->transportId << "\"";
|
|
58
|
+
ss << ", \"maxPackets\": " << this->maxPackets;
|
|
59
|
+
ss << ", \"maxBytes\": " << this->maxBytes;
|
|
60
|
+
ss << ", \"bursts\": [";
|
|
61
|
+
|
|
62
|
+
bool first{ true };
|
|
63
|
+
|
|
64
|
+
for (const auto& kv : this->bursts)
|
|
65
|
+
{
|
|
66
|
+
const auto packets = kv.first;
|
|
67
|
+
const auto& counters = kv.second;
|
|
68
|
+
|
|
69
|
+
if (!first)
|
|
70
|
+
{
|
|
71
|
+
ss << ", ";
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
first = false;
|
|
75
|
+
|
|
76
|
+
ss << "{\"packets\": " << packets;
|
|
77
|
+
ss << ", \"count\": " << counters.count;
|
|
78
|
+
ss << ", \"retransmissions\": " << counters.retransmissions;
|
|
79
|
+
ss << ", \"probations\": " << counters.probations;
|
|
80
|
+
ss << "}";
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
ss << "]}";
|
|
84
|
+
|
|
85
|
+
MS_DUMP_CLEAN(0, "%s", ss.str().c_str());
|
|
86
|
+
|
|
87
|
+
Clear();
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
void SendBurst::CloseBurst()
|
|
91
|
+
{
|
|
92
|
+
MS_TRACE();
|
|
93
|
+
|
|
94
|
+
if (this->packets == 0)
|
|
95
|
+
{
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
auto& counters = this->bursts[this->packets];
|
|
100
|
+
|
|
101
|
+
counters.count++;
|
|
102
|
+
counters.retransmissions += this->retransmissions;
|
|
103
|
+
counters.probations += this->probations;
|
|
104
|
+
|
|
105
|
+
this->maxPackets = std::max(this->maxPackets, this->packets);
|
|
106
|
+
this->maxBytes = std::max(this->maxBytes, this->bytes);
|
|
107
|
+
|
|
108
|
+
this->packets = 0;
|
|
109
|
+
this->retransmissions = 0;
|
|
110
|
+
this->probations = 0;
|
|
111
|
+
this->bytes = 0;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
void SendBurst::Clear()
|
|
115
|
+
{
|
|
116
|
+
MS_TRACE();
|
|
117
|
+
|
|
118
|
+
this->bursts.clear();
|
|
119
|
+
|
|
120
|
+
this->maxPackets = 0;
|
|
121
|
+
this->maxBytes = 0;
|
|
122
|
+
}
|
|
123
|
+
} // namespace RtcLogger
|
|
124
|
+
} // namespace RTC
|
|
@@ -50,11 +50,6 @@ namespace RTC
|
|
|
50
50
|
return RtpHeaderExtensionUri::Type::VIDEO_ORIENTATION;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
case FBS::RtpParameters::RtpHeaderExtensionUri::TimeOffset:
|
|
54
|
-
{
|
|
55
|
-
return RtpHeaderExtensionUri::Type::TIME_OFFSET;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
53
|
case FBS::RtpParameters::RtpHeaderExtensionUri::PlayoutDelay:
|
|
59
54
|
{
|
|
60
55
|
return RtpHeaderExtensionUri::Type::PLAYOUT_DELAY;
|
|
@@ -75,7 +70,7 @@ namespace RTC
|
|
|
75
70
|
return RtpHeaderExtensionUri::Type::MEDIASOUP_PACKET_ID;
|
|
76
71
|
}
|
|
77
72
|
|
|
78
|
-
|
|
73
|
+
NO_DEFAULT();
|
|
79
74
|
}
|
|
80
75
|
}
|
|
81
76
|
|
|
@@ -126,11 +121,6 @@ namespace RTC
|
|
|
126
121
|
return FBS::RtpParameters::RtpHeaderExtensionUri::VideoOrientation;
|
|
127
122
|
}
|
|
128
123
|
|
|
129
|
-
case RtpHeaderExtensionUri::Type::TIME_OFFSET:
|
|
130
|
-
{
|
|
131
|
-
return FBS::RtpParameters::RtpHeaderExtensionUri::TimeOffset;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
124
|
case RtpHeaderExtensionUri::Type::ABS_CAPTURE_TIME:
|
|
135
125
|
{
|
|
136
126
|
return FBS::RtpParameters::RtpHeaderExtensionUri::AbsCaptureTime;
|
|
@@ -146,7 +136,7 @@ namespace RTC
|
|
|
146
136
|
return FBS::RtpParameters::RtpHeaderExtensionUri::MediasoupPacketId;
|
|
147
137
|
}
|
|
148
138
|
|
|
149
|
-
|
|
139
|
+
NO_DEFAULT();
|
|
150
140
|
}
|
|
151
141
|
}
|
|
152
142
|
|
|
@@ -107,7 +107,7 @@ namespace RTC
|
|
|
107
107
|
MS_TRACE();
|
|
108
108
|
|
|
109
109
|
const auto stateStringView = Association::StateToString(this->state);
|
|
110
|
-
const auto associationStateStringView = Types::
|
|
110
|
+
const auto associationStateStringView = Types::associationStateToString(GetAssociationState());
|
|
111
111
|
|
|
112
112
|
MS_DUMP_CLEAN(indentation, "<SCTP::Association>");
|
|
113
113
|
|
|
@@ -187,7 +187,7 @@ namespace RTC
|
|
|
187
187
|
return Types::AssociationState::SHUTTING_DOWN;
|
|
188
188
|
}
|
|
189
189
|
|
|
190
|
-
|
|
190
|
+
NO_DEFAULT();
|
|
191
191
|
}
|
|
192
192
|
}
|
|
193
193
|
|
|
@@ -608,6 +608,20 @@ namespace RTC
|
|
|
608
608
|
|
|
609
609
|
if (this->tcb)
|
|
610
610
|
{
|
|
611
|
+
// The cumulative ack TSN may have advanced while processing the chunks
|
|
612
|
+
// in this packet, which may be what deferred reset processing (if any)
|
|
613
|
+
// was waiting for.
|
|
614
|
+
if (this->tcb->GetStreamResetHandler().MayLeaveDeferredReset())
|
|
615
|
+
{
|
|
616
|
+
// There may be chunks to deliver that were queued while waiting for
|
|
617
|
+
// the streams to reset.
|
|
618
|
+
//
|
|
619
|
+
// NOTE: Both this and the above are done before sending the SACK chunk
|
|
620
|
+
// below so that its advertised receiver window credit accounts for the
|
|
621
|
+
// released and delivered data.
|
|
622
|
+
MayDeliverMessages();
|
|
623
|
+
}
|
|
624
|
+
|
|
611
625
|
this->tcb->GetDataTracker().ObservePacketEnd();
|
|
612
626
|
this->tcb->MaySendSackChunk();
|
|
613
627
|
}
|
|
@@ -143,6 +143,63 @@ namespace RTC
|
|
|
143
143
|
}
|
|
144
144
|
}
|
|
145
145
|
|
|
146
|
+
bool StreamResetHandler::MayLeaveDeferredReset()
|
|
147
|
+
{
|
|
148
|
+
MS_TRACE();
|
|
149
|
+
|
|
150
|
+
if (!this->deferredIncomingRequest.has_value())
|
|
151
|
+
{
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// https://tools.ietf.org/html/rfc6525#section-5.2.2
|
|
156
|
+
//
|
|
157
|
+
// "In this mode, any data arriving with a TSN larger than the Sender's
|
|
158
|
+
// Last Assigned TSN for the affected stream(s) MUST be queued locally and
|
|
159
|
+
// held until the cumulative acknowledgment point reaches the Sender's Last
|
|
160
|
+
// Assigned TSN."
|
|
161
|
+
//
|
|
162
|
+
// So deferred reset processing must end as soon as the cumulative ack TSN
|
|
163
|
+
// reaches the sender's last assigned TSN. Otherwise the queued data would
|
|
164
|
+
// be held (and accounted for) until the peer decides to retransmit its
|
|
165
|
+
// request, which it may never do.
|
|
166
|
+
if (this->dataTracker->IsLaterThanCumulativeAckedTsn(this->deferredIncomingRequest->senderLastAssignedTsn))
|
|
167
|
+
{
|
|
168
|
+
return false;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
MS_DEBUG_DEV(
|
|
172
|
+
"leaving deferred reset processing, sender last assigned tsn %" PRIu32 " reached",
|
|
173
|
+
this->deferredIncomingRequest->senderLastAssignedTsn);
|
|
174
|
+
|
|
175
|
+
// Remember the request being performed here. The peer was told "in
|
|
176
|
+
// progress" and will retry it with a new request sequence number, and that
|
|
177
|
+
// retry must not reset the very same streams a second time.
|
|
178
|
+
this->performedDeferredRequest = std::move(this->deferredIncomingRequest);
|
|
179
|
+
|
|
180
|
+
this->deferredIncomingRequest = std::nullopt;
|
|
181
|
+
|
|
182
|
+
// NOLINTNEXTLINE(bugprone-unchecked-optional-access)
|
|
183
|
+
const auto& streamIds = this->performedDeferredRequest.value().streamIds;
|
|
184
|
+
|
|
185
|
+
// https://tools.ietf.org/html/rfc6525#section-5.2.2
|
|
186
|
+
//
|
|
187
|
+
// E3) "If no stream numbers are listed in the parameter, then all incoming
|
|
188
|
+
// streams MUST be reset to 0 as the next expected SSN. If specific stream
|
|
189
|
+
// numbers are listed, then only these specific streams MUST be reset to 0,
|
|
190
|
+
// and all other non-listed SSNs remain unchanged." E4: "Any queued TSNs
|
|
191
|
+
// (queued at step E2) MUST now be released and processed normally."
|
|
192
|
+
this->reassemblyQueue->ResetStreamsAndLeaveDeferredReset(streamIds);
|
|
193
|
+
|
|
194
|
+
this->associationListenerDeferrer.OnAssociationInboundStreamsReset(streamIds);
|
|
195
|
+
|
|
196
|
+
// The request has now been performed, so a retransmission of it must get
|
|
197
|
+
// the final response rather than "in progress" again.
|
|
198
|
+
this->lastProcessedReqResult = ReconfigurationResponseParameter::Result::SUCCESS_PERFORMED;
|
|
199
|
+
|
|
200
|
+
return true;
|
|
201
|
+
}
|
|
202
|
+
|
|
146
203
|
bool StreamResetHandler::ValidateReceivedReConfigChunk(const ReConfigChunk* receivedReConfigChunk)
|
|
147
204
|
{
|
|
148
205
|
MS_TRACE();
|
|
@@ -284,6 +341,11 @@ namespace RTC
|
|
|
284
341
|
validationResult == ReqSeqNbrValidationResult::RETRANSMISSION &&
|
|
285
342
|
this->lastProcessedReqResult != ReconfigurationResponseParameter::Result::IN_PROGRESS)
|
|
286
343
|
{
|
|
344
|
+
// The peer is getting the final result of this request, so there is no
|
|
345
|
+
// longer a need to remember that it may have been performed when leaving
|
|
346
|
+
// deferred reset processing.
|
|
347
|
+
this->performedDeferredRequest = std::nullopt;
|
|
348
|
+
|
|
287
349
|
auto* reconfigurationResponseParameter =
|
|
288
350
|
reConfigChunk->BuildParameterInPlace<ReconfigurationResponseParameter>();
|
|
289
351
|
|
|
@@ -301,7 +363,33 @@ namespace RTC
|
|
|
301
363
|
// "In Progress" request. In all cases, re-evaluate the state.
|
|
302
364
|
this->lastProcessedReqSeqNbr = requestSn;
|
|
303
365
|
|
|
304
|
-
|
|
366
|
+
// This very same request may have already been performed when the
|
|
367
|
+
// cumulative ack TSN reached its sender's last assigned TSN. The peer was
|
|
368
|
+
// told "in progress" and doesn't know it yet, so it retries it with a new
|
|
369
|
+
// request sequence number. Resetting those streams again would set their
|
|
370
|
+
// next expected SSN back to 0 after post reset data may have already been
|
|
371
|
+
// received, so just reply the final result.
|
|
372
|
+
const bool alreadyPerformed =
|
|
373
|
+
this->performedDeferredRequest.has_value() &&
|
|
374
|
+
this->performedDeferredRequest->senderLastAssignedTsn ==
|
|
375
|
+
receivedOutgoingSsnResetRequestParameter->GetSenderLastAssignedTsn() &&
|
|
376
|
+
this->performedDeferredRequest->streamIds ==
|
|
377
|
+
receivedOutgoingSsnResetRequestParameter->GetStreamIds();
|
|
378
|
+
|
|
379
|
+
this->performedDeferredRequest = std::nullopt;
|
|
380
|
+
|
|
381
|
+
if (alreadyPerformed)
|
|
382
|
+
{
|
|
383
|
+
// Set the result again rather than relying on the one stored when the
|
|
384
|
+
// reset was performed, since a received incoming stream reset request
|
|
385
|
+
// may have overwritten it in the meantime.
|
|
386
|
+
this->lastProcessedReqResult = ReconfigurationResponseParameter::Result::SUCCESS_PERFORMED;
|
|
387
|
+
|
|
388
|
+
MS_DEBUG_DEV(
|
|
389
|
+
"reset outgoing already performed when leaving deferred reset processing, sender last assigned tsn %" PRIu32,
|
|
390
|
+
receivedOutgoingSsnResetRequestParameter->GetSenderLastAssignedTsn());
|
|
391
|
+
}
|
|
392
|
+
else if (
|
|
305
393
|
this->dataTracker->IsLaterThanCumulativeAckedTsn(
|
|
306
394
|
receivedOutgoingSsnResetRequestParameter->GetSenderLastAssignedTsn()))
|
|
307
395
|
{
|
|
@@ -314,6 +402,21 @@ namespace RTC
|
|
|
314
402
|
receivedOutgoingSsnResetRequestParameter->GetSenderLastAssignedTsn(),
|
|
315
403
|
receivedOutgoingSsnResetRequestParameter->GetStreamIds());
|
|
316
404
|
|
|
405
|
+
// Remember the request so that deferred reset processing can end as soon
|
|
406
|
+
// as the cumulative ack TSN reaches the sender's last assigned TSN,
|
|
407
|
+
// without depending on the peer retransmitting its request.
|
|
408
|
+
//
|
|
409
|
+
// NOTE: Just like ReassemblyQueue::EnterDeferredReset() does, a new
|
|
410
|
+
// request is ignored while already in deferred reset processing.
|
|
411
|
+
if (!this->deferredIncomingRequest.has_value())
|
|
412
|
+
{
|
|
413
|
+
this->deferredIncomingRequest = DeferredIncomingRequest{
|
|
414
|
+
.senderLastAssignedTsn =
|
|
415
|
+
receivedOutgoingSsnResetRequestParameter->GetSenderLastAssignedTsn(),
|
|
416
|
+
.streamIds = receivedOutgoingSsnResetRequestParameter->GetStreamIds(),
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
|
|
317
420
|
// "If the endpoint enters 'deferred reset processing', it MUST put a
|
|
318
421
|
// Re-configuration Response Parameter into a RE-CONFIG chunk indicating
|
|
319
422
|
// 'In progress' and MUST send the RE-CONFIG chunk.
|
|
@@ -335,6 +438,8 @@ namespace RTC
|
|
|
335
438
|
this->reassemblyQueue->ResetStreamsAndLeaveDeferredReset(
|
|
336
439
|
receivedOutgoingSsnResetRequestParameter->GetStreamIds());
|
|
337
440
|
|
|
441
|
+
this->deferredIncomingRequest = std::nullopt;
|
|
442
|
+
|
|
338
443
|
this->associationListenerDeferrer.OnAssociationInboundStreamsReset(
|
|
339
444
|
receivedOutgoingSsnResetRequestParameter->GetStreamIds());
|
|
340
445
|
|