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.
Files changed (213) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/node/lib/Consumer.d.ts.map +1 -1
  3. package/node/lib/Consumer.js +4 -51
  4. package/node/lib/Producer.d.ts.map +1 -1
  5. package/node/lib/Producer.js +4 -8
  6. package/node/lib/ProducerTypes.d.ts +4 -2
  7. package/node/lib/ProducerTypes.d.ts.map +1 -1
  8. package/node/lib/Router.d.ts.map +1 -1
  9. package/node/lib/Router.js +4 -0
  10. package/node/lib/Transport.d.ts.map +1 -1
  11. package/node/lib/Transport.js +7 -10
  12. package/node/lib/fbs/rtp-parameters/rtp-header-extension-uri.d.ts +3 -4
  13. package/node/lib/fbs/rtp-parameters/rtp-header-extension-uri.d.ts.map +1 -1
  14. package/node/lib/fbs/rtp-parameters/rtp-header-extension-uri.js +3 -4
  15. package/node/lib/ortc.d.ts +0 -2
  16. package/node/lib/ortc.d.ts.map +1 -1
  17. package/node/lib/ortc.js +11 -21
  18. package/node/lib/rtpMappingFbsUtils.d.ts +6 -0
  19. package/node/lib/rtpMappingFbsUtils.d.ts.map +1 -0
  20. package/node/lib/rtpMappingFbsUtils.js +65 -0
  21. package/node/lib/rtpParametersFbsUtils.d.ts.map +1 -1
  22. package/node/lib/rtpParametersFbsUtils.js +0 -6
  23. package/node/lib/rtpParametersTypes.d.ts +1 -1
  24. package/node/lib/rtpParametersTypes.d.ts.map +1 -1
  25. package/node/lib/rtpStreamFbsUtils.d.ts +4 -0
  26. package/node/lib/rtpStreamFbsUtils.d.ts.map +1 -0
  27. package/node/lib/rtpStreamFbsUtils.js +51 -0
  28. package/node/lib/supportedRtpCapabilities.d.ts.map +1 -1
  29. package/node/lib/supportedRtpCapabilities.js +6 -13
  30. package/node/lib/test/test-Consumer.js +1 -13
  31. package/node/lib/test/test-DataConsumer.js +9 -0
  32. package/node/lib/test/test-DataProducer.js +38 -0
  33. package/node/lib/test/test-PipeTransport.js +27 -29
  34. package/node/lib/test/test-Producer.js +97 -0
  35. package/node/lib/test/test-ortc.js +34 -14
  36. package/package.json +10 -10
  37. package/worker/fbs/FBS/meson.build +25 -0
  38. package/worker/fbs/meson.build +15 -18
  39. package/worker/fbs/rtpParameters.fbs +0 -1
  40. package/worker/fuzzer/src/FuzzerUtils.cpp +5 -3
  41. package/worker/fuzzer/src/RTC/RTP/FuzzerPacket.cpp +16 -2
  42. package/worker/include/DepLibUV.hpp +13 -0
  43. package/worker/include/RTC/BWE/AlrDetector.hpp +97 -0
  44. package/worker/include/RTC/BWE/BitrateProber.hpp +217 -0
  45. package/worker/include/RTC/BWE/BitrateUtils.hpp +39 -0
  46. package/worker/include/RTC/BWE/BweTypes.hpp +171 -3
  47. package/worker/include/RTC/BWE/FeedbackAdapter.hpp +0 -14
  48. package/worker/include/RTC/BWE/InterArrival.hpp +117 -0
  49. package/worker/include/RTC/BWE/IntervalBudget.hpp +81 -0
  50. package/worker/include/RTC/BWE/LossBasedController.hpp +625 -0
  51. package/worker/include/RTC/BWE/OveruseDetector.hpp +71 -0
  52. package/worker/include/RTC/BWE/OveruseEstimator.hpp +115 -0
  53. package/worker/include/RTC/BWE/ProbeBitrateEstimator.hpp +84 -0
  54. package/worker/include/RTC/BWE/ProbeController.hpp +379 -0
  55. package/worker/include/RTC/BWE/ProbePacketGenerator.hpp +130 -0
  56. package/worker/include/RTC/BWE/ProbingScheduler.hpp +187 -0
  57. package/worker/include/RTC/BWE/RembGenerator.hpp +96 -0
  58. package/worker/include/RTC/BWE/RemoteBitrateEstimatorAbsSendTime.hpp +237 -0
  59. package/worker/include/RTC/BWE/RobustThroughputEstimator.hpp +26 -0
  60. package/worker/include/RTC/BWE/SendPacketHistory.hpp +161 -25
  61. package/worker/include/RTC/BWE/TargetRateController.hpp +306 -0
  62. package/worker/include/RTC/BWE/TransportWideCcFeedbackGenerator.hpp +146 -0
  63. package/worker/include/RTC/BWE/TrendlineEstimator.hpp +73 -16
  64. package/worker/include/RTC/Consts.hpp +70 -0
  65. package/worker/include/RTC/DataConsumer.hpp +3 -5
  66. package/worker/include/RTC/DirectTransport.hpp +4 -5
  67. package/worker/include/RTC/PipeTransport.hpp +4 -5
  68. package/worker/include/RTC/PlainTransport.hpp +4 -5
  69. package/worker/include/RTC/RTCP/FeedbackPsRemb.hpp +6 -7
  70. package/worker/include/RTC/RTCP/FeedbackRtpTransport.hpp +3 -1
  71. package/worker/include/RTC/RTP/Codecs/Tools.hpp +1 -1
  72. package/worker/include/RTC/RTP/HeaderExtensionIds.hpp +0 -1
  73. package/worker/include/RTC/RTP/Packet.hpp +16 -4
  74. package/worker/include/RTC/RTP/ProbationGenerator.hpp +0 -8
  75. package/worker/include/RTC/RTP/RtpStream.hpp +12 -9
  76. package/worker/include/RTC/RTP/RtpStreamRecv.hpp +22 -4
  77. package/worker/include/RTC/RTP/RtpStreamSend.hpp +4 -2
  78. package/worker/include/RTC/RTP/RtxStream.hpp +10 -4
  79. package/worker/include/RTC/RateCalculator.hpp +103 -24
  80. package/worker/include/RTC/RemoteCaptureTimeEstimator.hpp +33 -3
  81. package/worker/include/RTC/{RtcLogger.hpp → RtcLogger/RtpPacket.hpp} +5 -3
  82. package/worker/include/RTC/RtcLogger/SendBurst.hpp +88 -0
  83. package/worker/include/RTC/RtpDictionaries.hpp +3 -4
  84. package/worker/include/RTC/SCTP/association/Association.hpp +1 -1
  85. package/worker/include/RTC/SCTP/association/StreamResetHandler.hpp +36 -0
  86. package/worker/include/RTC/SCTP/public/AssociationMetrics.hpp +0 -1
  87. package/worker/include/RTC/SCTP/public/SctpTypes.hpp +9 -9
  88. package/worker/include/RTC/SCTP/rx/DataTracker.hpp +1 -1
  89. package/worker/include/RTC/SCTP/rx/ReassemblyQueue.hpp +11 -1
  90. package/worker/include/RTC/SctpDictionaries.hpp +2 -2
  91. package/worker/include/RTC/TcpConnection.hpp +2 -1
  92. package/worker/include/RTC/Transport.hpp +23 -8
  93. package/worker/include/RTC/TransportTuple.hpp +61 -6
  94. package/worker/include/RTC/WebRtcTransport.hpp +4 -5
  95. package/worker/include/Shared.hpp +5 -0
  96. package/worker/include/SharedInterface.hpp +10 -0
  97. package/worker/include/Utils.hpp +72 -3
  98. package/worker/include/common.hpp +12 -4
  99. package/worker/include/handles/SendCallbacks.hpp +34 -0
  100. package/worker/include/handles/TcpConnectionHandle.hpp +4 -12
  101. package/worker/include/handles/UdpSocketHandle.hpp +4 -8
  102. package/worker/meson.build +45 -1
  103. package/worker/meson_options.txt +1 -0
  104. package/worker/mocks/include/MockShared.hpp +16 -2
  105. package/worker/mocks/include/handles/MockBackoffTimerHandle.hpp +1 -1
  106. package/worker/scripts/package-lock.json +6 -6
  107. package/worker/src/RTC/BWE/AimdRateControl.cpp +4 -5
  108. package/worker/src/RTC/BWE/AlrDetector.cpp +80 -0
  109. package/worker/src/RTC/BWE/BitrateProber.cpp +256 -0
  110. package/worker/src/RTC/BWE/BitrateUtils.cpp +54 -0
  111. package/worker/src/RTC/BWE/DelayBasedBwe.cpp +2 -2
  112. package/worker/src/RTC/BWE/FeedbackAdapter.cpp +20 -37
  113. package/worker/src/RTC/BWE/InterArrival.cpp +216 -0
  114. package/worker/src/RTC/BWE/IntervalBudget.cpp +93 -0
  115. package/worker/src/RTC/BWE/LossBasedController.cpp +1194 -0
  116. package/worker/src/RTC/BWE/OveruseDetector.cpp +128 -0
  117. package/worker/src/RTC/BWE/OveruseEstimator.cpp +166 -0
  118. package/worker/src/RTC/BWE/ProbeBitrateEstimator.cpp +222 -0
  119. package/worker/src/RTC/BWE/ProbeController.cpp +645 -0
  120. package/worker/src/RTC/BWE/ProbePacketGenerator.cpp +140 -0
  121. package/worker/src/RTC/BWE/ProbingScheduler.cpp +196 -0
  122. package/worker/src/RTC/BWE/RembGenerator.cpp +169 -0
  123. package/worker/src/RTC/BWE/RemoteBitrateEstimatorAbsSendTime.cpp +497 -0
  124. package/worker/src/RTC/BWE/RobustThroughputEstimator.cpp +47 -0
  125. package/worker/src/RTC/BWE/SendPacketHistory.cpp +173 -50
  126. package/worker/src/RTC/BWE/TargetRateController.cpp +433 -0
  127. package/worker/src/RTC/BWE/TransportWideCcFeedbackGenerator.cpp +377 -0
  128. package/worker/src/RTC/BWE/TrendlineEstimator.cpp +102 -5
  129. package/worker/src/RTC/Consumer.cpp +7 -5
  130. package/worker/src/RTC/DataConsumer.cpp +8 -10
  131. package/worker/src/RTC/DirectTransport.cpp +14 -8
  132. package/worker/src/RTC/DtlsTransport.cpp +8 -8
  133. package/worker/src/RTC/ICE/IceCandidate.cpp +4 -4
  134. package/worker/src/RTC/ICE/IceServer.cpp +1 -1
  135. package/worker/src/RTC/PipeTransport.cpp +13 -8
  136. package/worker/src/RTC/PlainTransport.cpp +13 -8
  137. package/worker/src/RTC/Producer.cpp +14 -31
  138. package/worker/src/RTC/RTCP/Bye.cpp +1 -1
  139. package/worker/src/RTC/RTCP/FeedbackPsRemb.cpp +18 -0
  140. package/worker/src/RTC/RTCP/FeedbackPsRpsi.cpp +2 -2
  141. package/worker/src/RTC/RTCP/FeedbackPsVbcm.cpp +2 -1
  142. package/worker/src/RTC/RTCP/FeedbackRtpTransport.cpp +2 -2
  143. package/worker/src/RTC/RTCP/Sdes.cpp +1 -1
  144. package/worker/src/RTC/RTP/Codecs/DependencyDescriptor.cpp +2 -1
  145. package/worker/src/RTC/RTP/Packet.cpp +26 -11
  146. package/worker/src/RTC/RTP/ProbationGenerator.cpp +5 -6
  147. package/worker/src/RTC/RTP/RtpStream.cpp +1 -1
  148. package/worker/src/RTC/RTP/RtpStreamRecv.cpp +69 -48
  149. package/worker/src/RTC/RTP/RtpStreamSend.cpp +31 -31
  150. package/worker/src/RTC/RTP/RtxStream.cpp +22 -7
  151. package/worker/src/RTC/RateCalculator.cpp +133 -28
  152. package/worker/src/RTC/RemoteCaptureTimeEstimator.cpp +56 -1
  153. package/worker/src/RTC/{RtcLogger.cpp → RtcLogger/RtpPacket.cpp} +2 -2
  154. package/worker/src/RTC/RtcLogger/SendBurst.cpp +124 -0
  155. package/worker/src/RTC/RtpDictionaries/RtpHeaderExtensionUri.cpp +2 -12
  156. package/worker/src/RTC/RtpDictionaries/RtpParameters.cpp +1 -1
  157. package/worker/src/RTC/SCTP/association/Association.cpp +16 -2
  158. package/worker/src/RTC/SCTP/association/StreamResetHandler.cpp +106 -1
  159. package/worker/src/RTC/SCTP/public/AssociationMetrics.cpp +1 -1
  160. package/worker/src/RTC/SCTP/rx/InterleavedReassemblyStreams.cpp +3 -3
  161. package/worker/src/RTC/SCTP/rx/ReassemblyQueue.cpp +2 -1
  162. package/worker/src/RTC/SCTP/rx/TraditionalReassemblyStreams.cpp +4 -4
  163. package/worker/src/RTC/SCTP/tx/RetransmissionTimeout.cpp +4 -4
  164. package/worker/src/RTC/SctpDictionaries/SctpStreamParameters.cpp +6 -10
  165. package/worker/src/RTC/SimulcastProducerStreamManager.cpp +2 -2
  166. package/worker/src/RTC/SrtpSession.cpp +2 -2
  167. package/worker/src/RTC/SvcProducerStreamManager.cpp +2 -2
  168. package/worker/src/RTC/TcpConnection.cpp +2 -2
  169. package/worker/src/RTC/Transport.cpp +112 -75
  170. package/worker/src/RTC/TransportTuple.cpp +4 -4
  171. package/worker/src/RTC/WebRtcServer.cpp +4 -3
  172. package/worker/src/RTC/WebRtcTransport.cpp +20 -13
  173. package/worker/src/Utils/BitStream.cpp +24 -0
  174. package/worker/src/handles/BackoffTimerHandle.cpp +1 -1
  175. package/worker/src/handles/TcpConnectionHandle.cpp +13 -23
  176. package/worker/src/handles/UdpSocketHandle.cpp +14 -21
  177. package/worker/tasks.py +43 -18
  178. package/worker/test/include/RTC/BWE/helpers/LinkSimulator.hpp +68 -14
  179. package/worker/test/include/RTC/BWE/helpers/RemoteBitrateEstimatorAbsSendTimeTestHelper.hpp +125 -0
  180. package/worker/test/src/RTC/BWE/TestAlrDetector.cpp +110 -0
  181. package/worker/test/src/RTC/BWE/TestBitrateProber.cpp +418 -0
  182. package/worker/test/src/RTC/BWE/TestBitrateUtils.cpp +61 -0
  183. package/worker/test/src/RTC/BWE/TestDelayBasedBwe.cpp +4 -4
  184. package/worker/test/src/RTC/BWE/TestFeedbackAdapter.cpp +53 -37
  185. package/worker/test/src/RTC/BWE/TestInterArrival.cpp +643 -0
  186. package/worker/test/src/RTC/BWE/TestIntervalBudget.cpp +130 -0
  187. package/worker/test/src/RTC/BWE/TestLossBasedController.cpp +1199 -0
  188. package/worker/test/src/RTC/BWE/TestOveruseDetector.cpp +519 -0
  189. package/worker/test/src/RTC/BWE/TestProbeBitrateEstimator.cpp +266 -0
  190. package/worker/test/src/RTC/BWE/TestProbeController.cpp +1682 -0
  191. package/worker/test/src/RTC/BWE/TestProbePacketGenerator.cpp +265 -0
  192. package/worker/test/src/RTC/BWE/TestProbingScheduler.cpp +260 -0
  193. package/worker/test/src/RTC/BWE/TestRembGenerator.cpp +285 -0
  194. package/worker/test/src/RTC/BWE/TestRemoteBitrateEstimatorAbsSendTime.cpp +414 -0
  195. package/worker/test/src/RTC/BWE/TestSendPacketHistory.cpp +296 -77
  196. package/worker/test/src/RTC/BWE/TestTargetRateController.cpp +337 -0
  197. package/worker/test/src/RTC/BWE/TestTransportWideCcFeedbackGenerator.cpp +578 -0
  198. package/worker/test/src/RTC/BWE/TestTrendlineEstimator.cpp +45 -0
  199. package/worker/test/src/RTC/BWE/helpers/LinkSimulator.cpp +133 -29
  200. package/worker/test/src/RTC/BWE/helpers/RemoteBitrateEstimatorAbsSendTimeTestHelper.cpp +625 -0
  201. package/worker/test/src/RTC/RTCP/TestFeedbackPsRemb.cpp +19 -0
  202. package/worker/test/src/RTC/RTP/TestPacket.cpp +58 -4
  203. package/worker/test/src/RTC/RTP/TestProbationGenerator.cpp +3 -2
  204. package/worker/test/src/RTC/RTP/TestRtpStreamRecv.cpp +50 -0
  205. package/worker/test/src/RTC/RTP/TestRtpStreamSend.cpp +59 -0
  206. package/worker/test/src/RTC/SCTP/association/TestStreamResetHandler.cpp +111 -0
  207. package/worker/test/src/RTC/TestRateCalculator.cpp +322 -60
  208. package/worker/test/src/RTC/TestRemoteCaptureTimeEstimator.cpp +95 -7
  209. package/worker/test/src/RTC/TestSimpleProducerStreamManager.cpp +34 -16
  210. package/worker/test/src/RTC/TestSimulcastProducerStreamManager.cpp +31 -13
  211. package/worker/test/src/RTC/TestSvcProducerStreamManager.cpp +37 -19
  212. package/worker/test/src/RTC/TestTransportCongestionControlServer.cpp +10 -10
  213. package/worker/test/src/Utils/TestTime.cpp +120 -21
@@ -0,0 +1,377 @@
1
+ #define MS_CLASS "RTC::BWE::TransportWideCcFeedbackGenerator"
2
+ // #define MS_LOG_DEV_LEVEL 3
3
+
4
+ #include "RTC/BWE/TransportWideCcFeedbackGenerator.hpp"
5
+ #include "Logger.hpp"
6
+
7
+ namespace RTC
8
+ {
9
+ namespace BWE
10
+ {
11
+ /* Static. */
12
+
13
+ // Shortest and longest a feedback may be waited for (ms), and what is emitted
14
+ // until there is a measurement to decide with.
15
+ static constexpr int64_t MinSendIntervalMs{ 50 };
16
+ static constexpr int64_t MaxSendIntervalMs{ 250 };
17
+ static constexpr int64_t DefaultSendIntervalMs{ 100 };
18
+ // What a feedback packet costs regardless of how many packets it reports on
19
+ // (bytes): IPv4 20, UDP 8, SRTP 10 and an average report of 30.
20
+ static constexpr int64_t FeedbackPacketOverhead{ 20 + 8 + 10 + 30 };
21
+ // Share of the bitrate coming in that reporting it back is allowed to cost.
22
+ static constexpr double FeedbackBitrateFraction{ 0.05 };
23
+ // Window of the meter of incoming data. It measures what feedback is emitted
24
+ // for, and a stream falling quiet for a moment must not lengthen the interval,
25
+ // so it is long enough to only follow the sustained bitrate.
26
+ static constexpr int64_t IncomingBitrateWindowMs{ 2500 };
27
+ // How far back the arrival times are kept.
28
+ static constexpr int64_t PacketArrivalTimestampWindowUs{ 500 * 1000 };
29
+
30
+ /* Instance methods. */
31
+
32
+ TransportWideCcFeedbackGenerator::TransportWideCcFeedbackGenerator(
33
+ Listener* listener, SharedInterface* shared, size_t maxRtcpPacketLen)
34
+ : maxRtcpPacketLen(maxRtcpPacketLen),
35
+ listener(listener),
36
+ shared(shared),
37
+ sendPeriodicTimer(shared->CreateTimer(this, "transport-wide-cc-feedback-generator-send")),
38
+ incomingDataCounter(shared, /*ignorePaddingOnlyPackets*/ false, IncomingBitrateWindowMs),
39
+ sendIntervalMs(DefaultSendIntervalMs)
40
+ {
41
+ MS_TRACE();
42
+
43
+ ResetFeedbackPacket(0);
44
+
45
+ this->sendPeriodicTimer->Start(this->sendIntervalMs, this->sendIntervalMs);
46
+ }
47
+
48
+ void TransportWideCcFeedbackGenerator::IncomingPacket(
49
+ int64_t arrivalTimeUs, const RTC::RTP::Packet* packet)
50
+ {
51
+ MS_TRACE();
52
+
53
+ uint16_t wideSeqNumber{ 0 };
54
+
55
+ if (!packet->ReadTransportWideCc01(wideSeqNumber))
56
+ {
57
+ return;
58
+ }
59
+
60
+ // NOTE: Done before taking note of this packet, so that what is still
61
+ // waiting to be reported is told apart from this very arrival.
62
+ MayDropOldPacketArrivalTimes(wideSeqNumber, arrivalTimeUs);
63
+
64
+ // Only take note of the packet the first time it's received.
65
+ if (!this->mapPacketArrivalTimes.try_emplace(wideSeqNumber, arrivalTimeUs).second)
66
+ {
67
+ return;
68
+ }
69
+
70
+ // A packet lower than the one the previous feedback started at may still
71
+ // arrive, and it may have been reported as lost already, so the next
72
+ // feedback has to start back there.
73
+ if (
74
+ !this->feedbackWideSeqNumStart.has_value() ||
75
+ RTC::SeqManager<uint16_t>::IsSeqLowerThan(
76
+ wideSeqNumber, this->feedbackWideSeqNumStart.value()))
77
+ {
78
+ this->feedbackWideSeqNumStart = wideSeqNumber;
79
+ }
80
+
81
+ // Sequences below the oldest arrival still kept cannot be reported on any
82
+ // more, so the next feedback starts no earlier than that one. Without this
83
+ // they would go out as lost when they have only been forgotten.
84
+ const uint16_t oldestSequenceNumber = this->mapPacketArrivalTimes.begin()->first;
85
+
86
+ if (RTC::SeqManager<uint16_t>::IsSeqLowerThan(this->feedbackWideSeqNumStart.value(), oldestSequenceNumber))
87
+ {
88
+ this->feedbackWideSeqNumStart = oldestSequenceNumber;
89
+ }
90
+
91
+ // The feedback reports on whoever sent last.
92
+ this->feedbackMediaSsrc = packet->GetSsrc();
93
+
94
+ this->incomingDataCounter.Update(packet);
95
+ }
96
+
97
+ void TransportWideCcFeedbackGenerator::FillAndSendFeedback()
98
+ {
99
+ MS_TRACE();
100
+
101
+ if (!this->feedbackWideSeqNumStart.has_value())
102
+ {
103
+ return;
104
+ }
105
+
106
+ auto it = this->mapPacketArrivalTimes.lower_bound(this->feedbackWideSeqNumStart.value());
107
+
108
+ // Everything known has already been reported, so there is nothing to
109
+ // build a feedback packet out of.
110
+ if (it == this->mapPacketArrivalTimes.end())
111
+ {
112
+ return;
113
+ }
114
+
115
+ while (it != this->mapPacketArrivalTimes.end())
116
+ {
117
+ const uint16_t sequenceNumber = it->first;
118
+ const int64_t timestampUs = it->second;
119
+ // Whether nothing has been added to the current feedback packet yet,
120
+ // which tells apart a packet that doesn't fit in what is left from one
121
+ // that doesn't fit in an empty packet either.
122
+ const bool feedbackPacketIsEmpty = !this->feedbackPacket->IsBaseSet();
123
+
124
+ // If the base is not set in this packet let's set it.
125
+ // NOTE: This may be needed many times during this loop, since the
126
+ // current feedback packet may be a fresh new one if the previous one was
127
+ // full (so already sent) or failed to be built.
128
+ if (feedbackPacketIsEmpty)
129
+ {
130
+ const uint16_t oldestReportableSequenceNumber =
131
+ sequenceNumber - RTC::RTCP::FeedbackRtpTransportPacket::maxMissingPackets;
132
+
133
+ // The base is where the report starts counting from, and every
134
+ // sequence between it and the first one actually received is reported
135
+ // as lost. Too long a run of those cannot be encoded, so the base is
136
+ // moved up rather than letting the packet fail to be built.
137
+ // NOTE: clang-tidy doesn't understand that this is guaranteed to have
138
+ // a value: the method returns above when it has none, and nothing
139
+ // takes it away afterwards, since SendFeedback() only ever assigns
140
+ // one.
141
+ // NOLINTNEXTLINE(bugprone-unchecked-optional-access)
142
+ uint16_t baseSequenceNumber = this->feedbackWideSeqNumStart.value();
143
+
144
+ if (RTC::SeqManager<uint16_t>::IsSeqLowerThan(baseSequenceNumber, oldestReportableSequenceNumber))
145
+ {
146
+ baseSequenceNumber = oldestReportableSequenceNumber;
147
+ }
148
+
149
+ this->feedbackPacket->SetBase(baseSequenceNumber, timestampUs);
150
+ }
151
+
152
+ const auto result =
153
+ this->feedbackPacket->AddPacket(sequenceNumber, timestampUs, this->maxRtcpPacketLen);
154
+
155
+ switch (result)
156
+ {
157
+ case RTC::RTCP::FeedbackRtpTransportPacket::AddPacketResult::SUCCESS:
158
+ {
159
+ // If the feedback packet is full, send it now.
160
+ if (this->feedbackPacket->IsFull())
161
+ {
162
+ MS_DEBUG_DEV("feedback packet is full, sending it now");
163
+
164
+ if (SendFeedback())
165
+ {
166
+ ++this->feedbackPacketCount;
167
+ }
168
+
169
+ ResetFeedbackPacket(this->feedbackPacketCount);
170
+ }
171
+
172
+ ++it;
173
+
174
+ break;
175
+ }
176
+
177
+ case RTC::RTCP::FeedbackRtpTransportPacket::AddPacketResult::MAX_SIZE_EXCEEDED:
178
+ {
179
+ if (SendFeedback())
180
+ {
181
+ ++this->feedbackPacketCount;
182
+ }
183
+
184
+ ResetFeedbackPacket(this->feedbackPacketCount);
185
+
186
+ // NOTE: The iterator is only advanced when the packet had a chance
187
+ // of fitting. If it didn't fit in a feedback packet that was
188
+ // already empty it will not fit in the fresh one either, and
189
+ // retrying it would loop forever.
190
+ if (feedbackPacketIsEmpty)
191
+ {
192
+ ++it;
193
+ }
194
+
195
+ break;
196
+ }
197
+
198
+ case RTC::RTCP::FeedbackRtpTransportPacket::AddPacketResult::FATAL:
199
+ {
200
+ // This packet cannot be expressed relative to the base and the
201
+ // reference time of the feedback packet being filled, so what is
202
+ // already in it goes out and a fresh one is started, whose base
203
+ // and reference time are taken from this very packet.
204
+ if (SendFeedback())
205
+ {
206
+ ++this->feedbackPacketCount;
207
+ }
208
+
209
+ ResetFeedbackPacket(this->feedbackPacketCount);
210
+
211
+ // NOTE: Same reasoning as above. If it didn't fit in a feedback
212
+ // packet that was already empty, a fresh one changes nothing.
213
+ if (feedbackPacketIsEmpty)
214
+ {
215
+ ++it;
216
+ }
217
+
218
+ break;
219
+ }
220
+ }
221
+ }
222
+
223
+ // The packet may hold nothing, but then SendFeedback() won't send it.
224
+ if (SendFeedback())
225
+ {
226
+ ++this->feedbackPacketCount;
227
+ }
228
+
229
+ ResetFeedbackPacket(this->feedbackPacketCount);
230
+ }
231
+
232
+ bool TransportWideCcFeedbackGenerator::SendFeedback()
233
+ {
234
+ MS_TRACE();
235
+
236
+ this->feedbackPacket->Finish();
237
+
238
+ if (!this->feedbackPacket->IsSerializable())
239
+ {
240
+ return false;
241
+ }
242
+
243
+ // The report is about whoever has sent last, which this packet could not
244
+ // be built with: it was started at the end of the previous round, when
245
+ // that may not have been known yet.
246
+ this->feedbackPacket->SetMediaSsrc(this->feedbackMediaSsrc);
247
+
248
+ const auto latestWideSeqNumber = this->feedbackPacket->GetLatestSequenceNumber();
249
+
250
+ this->listener->OnTransportWideCcFeedbackGeneratorSendRtcpPacket(
251
+ this, this->feedbackPacket.get());
252
+
253
+ this->feedbackWideSeqNumStart = latestWideSeqNumber + 1;
254
+
255
+ return true;
256
+ }
257
+
258
+ void TransportWideCcFeedbackGenerator::MayDropOldPacketArrivalTimes(
259
+ uint16_t seqNum, int64_t arrivalTimeUs)
260
+ {
261
+ MS_TRACE();
262
+
263
+ // Ignore the given instant if it's smaller than the window in order to
264
+ // avoid negative values (should never happen) and return early if the
265
+ // condition is met.
266
+ if (arrivalTimeUs < PacketArrivalTimestampWindowUs)
267
+ {
268
+ return;
269
+ }
270
+
271
+ if (!this->feedbackWideSeqNumStart.has_value() || this->mapPacketArrivalTimes.empty())
272
+ {
273
+ return;
274
+ }
275
+
276
+ const uint16_t feedbackWideSeqNumStart = this->feedbackWideSeqNumStart.value();
277
+ // Where a feedback that had reported everything known would start from.
278
+ const uint16_t endSequenceNumber = this->mapPacketArrivalTimes.rbegin()->first + 1;
279
+
280
+ // Nothing is forgotten while something already known is still waiting to
281
+ // be reported, since forgetting it would turn it into a loss.
282
+ if (RTC::SeqManager<uint16_t>::IsSeqLowerThan(feedbackWideSeqNumStart, endSequenceNumber))
283
+ {
284
+ return;
285
+ }
286
+
287
+ const int64_t expiryTimestampUs = arrivalTimeUs - PacketArrivalTimestampWindowUs;
288
+
289
+ auto it = this->mapPacketArrivalTimes.begin();
290
+
291
+ while (it != this->mapPacketArrivalTimes.end() && it->first != feedbackWideSeqNumStart &&
292
+ RTC::SeqManager<uint16_t>::IsSeqLowerThan(it->first, seqNum) &&
293
+ it->second <= expiryTimestampUs)
294
+ {
295
+ it = this->mapPacketArrivalTimes.erase(it);
296
+ }
297
+ }
298
+
299
+ void TransportWideCcFeedbackGenerator::ResetFeedbackPacket(uint8_t feedbackPacketCount)
300
+ {
301
+ MS_TRACE();
302
+
303
+ // NOTE: The media SSRC is left at zero here and filled in when the packet
304
+ // is about to go out, since who has sent last may still change while this
305
+ // one is being filled.
306
+ this->feedbackPacket = std::make_unique<RTC::RTCP::FeedbackRtpTransportPacket>(
307
+ /*senderSsrc*/ 0, /*mediaSsrc*/ 0);
308
+
309
+ this->feedbackPacket->SetFeedbackPacketCount(feedbackPacketCount);
310
+ }
311
+
312
+ int64_t TransportWideCcFeedbackGenerator::ComputeSendIntervalMs(int64_t incomingBitrate)
313
+ {
314
+ MS_TRACE();
315
+
316
+ // Bitrate the feedback is allowed to take, which is what decides how long
317
+ // its fixed cost may be spread over.
318
+ const double feedbackBitrate = static_cast<double>(incomingBitrate) * FeedbackBitrateFraction;
319
+ // NOTE: Checked against the bitrate rather than against the resulting
320
+ // interval, so that a bitrate of zero is not divided by.
321
+ const double minFeedbackBitrate = (static_cast<double>(FeedbackPacketOverhead) * 8 * 1000) /
322
+ static_cast<double>(MaxSendIntervalMs);
323
+
324
+ if (feedbackBitrate <= minFeedbackBitrate)
325
+ {
326
+ return MaxSendIntervalMs;
327
+ }
328
+
329
+ const auto intervalMs = static_cast<int64_t>(
330
+ (static_cast<double>(FeedbackPacketOverhead) * 8 * 1000) / feedbackBitrate);
331
+
332
+ return std::max(intervalMs, MinSendIntervalMs);
333
+ }
334
+
335
+ void TransportWideCcFeedbackGenerator::MayUpdateSendInterval(int64_t nowMs)
336
+ {
337
+ MS_TRACE();
338
+
339
+ const auto incomingBitrate = this->incomingDataCounter.GetBitrate(nowMs);
340
+
341
+ if (!incomingBitrate.has_value())
342
+ {
343
+ return;
344
+ }
345
+
346
+ const int64_t sendIntervalMs = ComputeSendIntervalMs(incomingBitrate.value());
347
+
348
+ if (sendIntervalMs == this->sendIntervalMs)
349
+ {
350
+ return;
351
+ }
352
+
353
+ MS_DEBUG_DEV(
354
+ "send interval changed [old:%" PRIi64 " ms, new:%" PRIi64 " ms, incomingBitrate:%" PRIi64
355
+ " bps]",
356
+ this->sendIntervalMs,
357
+ sendIntervalMs,
358
+ incomingBitrate.value());
359
+
360
+ this->sendIntervalMs = sendIntervalMs;
361
+
362
+ this->sendPeriodicTimer->Restart(this->sendIntervalMs, this->sendIntervalMs);
363
+ }
364
+
365
+ void TransportWideCcFeedbackGenerator::OnTimer(TimerHandleInterface* timer)
366
+ {
367
+ MS_TRACE();
368
+
369
+ if (timer == this->sendPeriodicTimer.get())
370
+ {
371
+ FillAndSendFeedback();
372
+
373
+ MayUpdateSendInterval(this->shared->GetTimeMs());
374
+ }
375
+ }
376
+ } // namespace BWE
377
+ } // namespace RTC
@@ -38,11 +38,27 @@ namespace RTC
38
38
 
39
39
  /* Instance methods. */
40
40
 
41
- TrendlineEstimator::TrendlineEstimator(size_t windowSize) : windowSize(windowSize)
41
+ TrendlineEstimator::TrendlineEstimator() : TrendlineEstimator(TrendlineEstimatorOptions{})
42
42
  {
43
43
  MS_TRACE();
44
+ }
45
+
46
+ TrendlineEstimator::TrendlineEstimator(TrendlineEstimatorOptions options) : options(options)
47
+ {
48
+ MS_TRACE();
49
+
50
+ MS_ASSERT(
51
+ this->options.windowSize >= 2,
52
+ "window size must be at least 2 [windowSize:%zu]",
53
+ this->options.windowSize);
44
54
 
45
- MS_ASSERT(windowSize >= 2, "window size must be at least 2 [windowSize:%zu]", windowSize);
55
+ // NOTE: The slope cap looks at both ends of the window without them
56
+ // overlapping, and each end needs at least one sample.
57
+ MS_ASSERT(
58
+ !this->options.enableCap ||
59
+ (this->options.beginningPackets >= 1 && this->options.endPackets >= 1 &&
60
+ this->options.beginningPackets + this->options.endPackets <= this->options.windowSize),
61
+ "both ends of the slope cap must fit within the window");
46
62
  }
47
63
 
48
64
  void TrendlineEstimator::Update(int64_t sendDeltaUs, int64_t arrivalDeltaUs, int64_t arrivalTimeUs)
@@ -67,9 +83,21 @@ namespace RTC
67
83
  // the window did, in which case the regression just gets a negative x.
68
84
  const auto elapsedUs = static_cast<double>(arrivalTimeUs - this->firstArrivalTimeUs.value());
69
85
 
70
- this->delayHist.push_back({ elapsedUs, this->smoothedDelayUs });
86
+ this->delayHist.push_back({ elapsedUs, this->smoothedDelayUs, this->accumulatedDelayUs });
87
+
88
+ // Feedback should already give the groups in order, so this is a safety
89
+ // net against a source that doesn't.
90
+ if (this->options.enableSort)
91
+ {
92
+ for (size_t idx{ this->delayHist.size() - 1 };
93
+ idx > 0 && this->delayHist[idx].arrivalTimeUs < this->delayHist[idx - 1].arrivalTimeUs;
94
+ --idx)
95
+ {
96
+ std::swap(this->delayHist[idx], this->delayHist[idx - 1]);
97
+ }
98
+ }
71
99
 
72
- if (this->delayHist.size() > this->windowSize)
100
+ if (this->delayHist.size() > this->options.windowSize)
73
101
  {
74
102
  this->delayHist.pop_front();
75
103
  }
@@ -81,15 +109,84 @@ namespace RTC
81
109
  // trend < 0 -> the delay decreases, queues are being emptied.
82
110
  double trend = this->prevTrend;
83
111
 
84
- if (this->delayHist.size() == this->windowSize)
112
+ if (this->delayHist.size() == this->options.windowSize)
85
113
  {
86
114
  // Keep the previous trend if the line cannot be fitted.
87
115
  trend = GetLinearFitSlope().value_or(trend);
116
+
117
+ if (this->options.enableCap)
118
+ {
119
+ const auto cap = GetSlopeCap();
120
+
121
+ // The cap only filters out overuse detections, it doesn't turn a
122
+ // growing queue into an emptying one.
123
+ if (trend >= 0 && cap.has_value() && trend > cap.value())
124
+ {
125
+ trend = cap.value();
126
+ }
127
+ }
88
128
  }
89
129
 
90
130
  Detect(trend, static_cast<double>(sendDeltaUs), arrivalTimeUs);
91
131
  }
92
132
 
133
+ std::optional<double> TrendlineEstimator::GetSlopeCap() const
134
+ {
135
+ MS_TRACE();
136
+
137
+ // NOTE: Both counts come from the options this was built with, never from
138
+ // anything received, so a window they don't fit in is a programming error.
139
+ MS_ASSERT(
140
+ this->options.beginningPackets >= 1 && this->options.beginningPackets < this->delayHist.size(),
141
+ "beginning packets don't fit in the window [beginningPackets:%zu, window:%zu]",
142
+ this->options.beginningPackets,
143
+ this->delayHist.size());
144
+ MS_ASSERT(
145
+ this->options.endPackets >= 1 && this->options.endPackets < this->delayHist.size(),
146
+ "end packets don't fit in the window [endPackets:%zu, window:%zu]",
147
+ this->options.endPackets,
148
+ this->delayHist.size());
149
+ MS_ASSERT(
150
+ this->options.beginningPackets + this->options.endPackets <= this->delayHist.size(),
151
+ "beginning and end packets overlap [beginningPackets:%zu, endPackets:%zu, window:%zu]",
152
+ this->options.beginningPackets,
153
+ this->options.endPackets,
154
+ this->delayHist.size());
155
+
156
+ // The least delayed sample of the beginning of the window.
157
+ PacketTiming early = this->delayHist[0];
158
+
159
+ for (size_t idx{ 1 }; idx < this->options.beginningPackets; ++idx)
160
+ {
161
+ if (this->delayHist[idx].rawDelayUs < early.rawDelayUs)
162
+ {
163
+ early = this->delayHist[idx];
164
+ }
165
+ }
166
+
167
+ const size_t lateStart = this->delayHist.size() - this->options.endPackets;
168
+
169
+ // The least delayed sample of the end of the window.
170
+ PacketTiming late = this->delayHist[lateStart];
171
+
172
+ for (size_t idx{ lateStart + 1 }; idx < this->delayHist.size(); ++idx)
173
+ {
174
+ if (this->delayHist[idx].rawDelayUs < late.rawDelayUs)
175
+ {
176
+ late = this->delayHist[idx];
177
+ }
178
+ }
179
+
180
+ // Too close in time for a slope between them to say anything.
181
+ if (late.arrivalTimeUs - early.arrivalTimeUs < 1000)
182
+ {
183
+ return std::nullopt;
184
+ }
185
+
186
+ return ((late.rawDelayUs - early.rawDelayUs) / (late.arrivalTimeUs - early.arrivalTimeUs)) +
187
+ this->options.capUncertainty;
188
+ }
189
+
93
190
  std::optional<double> TrendlineEstimator::GetLinearFitSlope() const
94
191
  {
95
192
  MS_TRACE();
@@ -11,7 +11,7 @@
11
11
  #include "RTC/SvcProducerStreamManager.hpp"
12
12
  #include "Utils.hpp"
13
13
  #ifdef MS_RTC_LOGGER_RTP
14
- #include "RTC/RtcLogger.hpp"
14
+ #include "RTC/RtcLogger/RtpPacket.hpp"
15
15
  #endif
16
16
  #include <limits> // std::numeric_limits
17
17
 
@@ -717,9 +717,11 @@ namespace RTC
717
717
  newPreferredLayers.temporal,
718
718
  this->id.c_str());
719
719
 
720
- preferredTemporalLayer = newPreferredLayers.temporal;
720
+ preferredTemporalLayer = static_cast<uint8_t>(newPreferredLayers.temporal);
721
721
  auto preferredLayersOffset = FBS::Consumer::CreateConsumerLayers(
722
- request->GetBufferBuilder(), newPreferredLayers.spatial, preferredTemporalLayer);
722
+ request->GetBufferBuilder(),
723
+ static_cast<uint8_t>(newPreferredLayers.spatial),
724
+ preferredTemporalLayer);
723
725
  auto responseOffset = FBS::Consumer::CreateSetPreferredLayersResponse(
724
726
  request->GetBufferBuilder(), preferredLayersOffset);
725
727
 
@@ -1823,8 +1825,8 @@ namespace RTC
1823
1825
  {
1824
1826
  layersOffset = FBS::Consumer::CreateConsumerLayers(
1825
1827
  this->shared->GetChannelNotifier()->GetBufferBuilder(),
1826
- this->producerStreamManager->GetCurrentSpatialLayer(),
1827
- this->producerStreamManager->GetCurrentTemporalLayer());
1828
+ static_cast<uint8_t>(this->producerStreamManager->GetCurrentSpatialLayer()),
1829
+ static_cast<uint8_t>(this->producerStreamManager->GetCurrentTemporalLayer()));
1828
1830
  }
1829
1831
 
1830
1832
  auto notificationOffset = FBS::Consumer::CreateLayersChangeNotification(
@@ -284,8 +284,8 @@ namespace RTC
284
284
  // NOTE: Capturing `this` and `request` (by reference) is safe here because the
285
285
  // callback is always invoked synchronously within this same call stack (never
286
286
  // deferred).
287
- const auto* cb = new onQueuedCallback(
288
- [this, &request](bool queued, bool sctpSendBufferFull)
287
+ onMessageQueuedCallback cb(
288
+ [this, &request](bool queued, bool isSendBufferFull)
289
289
  {
290
290
  if (queued)
291
291
  {
@@ -300,7 +300,7 @@ namespace RTC
300
300
  }
301
301
  else
302
302
  {
303
- request->Error(sctpSendBufferFull ? "sctpsendbufferfull" : "message send failed");
303
+ request->Error(isSendBufferFull ? "sctpsendbufferfull" : "message send failed");
304
304
  }
305
305
  });
306
306
 
@@ -313,7 +313,7 @@ namespace RTC
313
313
  // move the message and pass its ownership to the SCTP stack.
314
314
  RTC::SCTP::Message message(streamId, body->ppid(), std::vector<uint8_t>(data, data + len));
315
315
 
316
- SendMessage(std::move(message), emptySubchannels, std::nullopt, std::nullopt, cb);
316
+ SendMessage(std::move(message), emptySubchannels, std::nullopt, std::nullopt, std::move(cb));
317
317
 
318
318
  break;
319
319
  }
@@ -545,7 +545,7 @@ namespace RTC
545
545
  std::vector<uint16_t>& subchannels,
546
546
  std::optional<uint16_t> requiredSubchannel,
547
547
  std::optional<uint16_t> ignoredSubchannel,
548
- const onQueuedCallback* cb)
548
+ onMessageQueuedCallback cb)
549
549
  {
550
550
  MS_TRACE();
551
551
 
@@ -553,8 +553,7 @@ namespace RTC
553
553
  {
554
554
  if (cb)
555
555
  {
556
- (*cb)(false, false);
557
- delete cb;
556
+ cb(false, /*isSendBufferFull*/ false);
558
557
  }
559
558
 
560
559
  return false;
@@ -604,8 +603,7 @@ namespace RTC
604
603
 
605
604
  if (cb)
606
605
  {
607
- (*cb)(false, false);
608
- delete cb;
606
+ cb(false, /*isSendBufferFull*/ false);
609
607
  }
610
608
 
611
609
  return false;
@@ -614,7 +612,7 @@ namespace RTC
614
612
  this->messagesSent++;
615
613
  this->bytesSent += messageLen;
616
614
 
617
- this->listener->OnDataConsumerSendMessage(this, std::move(message), cb);
615
+ this->listener->OnDataConsumerSendMessage(this, std::move(message), std::move(cb));
618
616
 
619
617
  return true;
620
618
  }
@@ -145,8 +145,17 @@ namespace RTC
145
145
  return true;
146
146
  }
147
147
 
148
+ inline size_t DirectTransport::GetPacketOverhead() const
149
+ {
150
+ MS_TRACE();
151
+
152
+ // Nothing sent through this reaches a socket, so there is no network to
153
+ // carry anything on top of the packet.
154
+ return 0;
155
+ }
156
+
148
157
  void DirectTransport::SendRtpPacket(
149
- RTC::Consumer* consumer, RTC::RTP::Packet* packet, const RTC::Transport::onSendCallback* cb)
158
+ RTC::Consumer* consumer, RTC::RTP::Packet* packet, onSendCallback cb)
150
159
  {
151
160
  MS_TRACE();
152
161
 
@@ -156,8 +165,7 @@ namespace RTC
156
165
 
157
166
  if (cb)
158
167
  {
159
- (*cb)(false);
160
- delete cb;
168
+ cb(false);
161
169
  }
162
170
 
163
171
  return;
@@ -177,8 +185,7 @@ namespace RTC
177
185
 
178
186
  if (cb)
179
187
  {
180
- (*cb)(true);
181
- delete cb;
188
+ cb(true);
182
189
  }
183
190
 
184
191
  // Increase send transmission.
@@ -226,7 +233,7 @@ namespace RTC
226
233
  }
227
234
 
228
235
  void DirectTransport::SendMessage(
229
- RTC::DataConsumer* dataConsumer, RTC::SCTP::Message message, onQueuedCallback* cb)
236
+ RTC::DataConsumer* dataConsumer, RTC::SCTP::Message message, onMessageQueuedCallback cb)
230
237
  {
231
238
  MS_TRACE();
232
239
 
@@ -245,8 +252,7 @@ namespace RTC
245
252
 
246
253
  if (cb)
247
254
  {
248
- (*cb)(true, false);
249
- delete cb;
255
+ cb(true, /*isSendBufferFull*/ false);
250
256
  }
251
257
 
252
258
  // Increase send transmission.