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,497 @@
1
+ #define MS_CLASS "RTC::BWE::RemoteBitrateEstimatorAbsSendTime"
2
+ // #define MS_LOG_DEV_LEVEL 3
3
+
4
+ #include "RTC/BWE/RemoteBitrateEstimatorAbsSendTime.hpp"
5
+ #include "Logger.hpp"
6
+ #include "Utils.hpp"
7
+ #include <cstdlib> // std::abs()
8
+
9
+ namespace RTC
10
+ {
11
+ namespace BWE
12
+ {
13
+ /* Static. */
14
+
15
+ // Shortest gap between two probes for it to be taken as measurable rather
16
+ // than as two packets that left together.
17
+ static constexpr int64_t MinClusterDeltaUs{ 1000 };
18
+ // How long after the first packet bursts are still looked for even though
19
+ // there already is an estimation.
20
+ static constexpr int64_t InitialProbingIntervalUs{ 2 * 1000 * 1000 };
21
+ // Every packet whose send timestamp is within this many milliseconds of the
22
+ // first one of a group belongs to that group.
23
+ static constexpr int64_t TimestampGroupLengthMs{ 5 };
24
+ // The 'abs-send-time' extension carries 24 bits with 18 of fraction, and it
25
+ // is shifted up so that it fills the 32 bits the inter arrival works with and
26
+ // wraps the way they do.
27
+ static constexpr uint32_t AbsSendTimeFraction{ 18 };
28
+ static constexpr uint32_t AbsSendTimeInterArrivalUpshift{ 8 };
29
+ static constexpr uint32_t InterArrivalShift{ AbsSendTimeFraction +
30
+ AbsSendTimeInterArrivalUpshift };
31
+ // Microseconds a single tick of those shifted timestamps is worth.
32
+ static constexpr double TimestampToUs{ 1000000.0 / static_cast<double>(1 << InterArrivalShift) };
33
+ // Fewest probes a run must hold to be taken as a burst.
34
+ static constexpr int MinClusterSize{ 4 };
35
+ // Most probes kept while looking for a burst.
36
+ static constexpr size_t MaxProbePackets{ 15 };
37
+ // How many runs are enough to give up on the probes seen so far.
38
+ static constexpr size_t ExpectedNumberOfProbes{ 3 };
39
+ // Smallest packet taken as paced by the sender, since anything smaller is
40
+ // likely audio, which is not.
41
+ static constexpr size_t MinProbePacketSize{ 200 };
42
+ // How long a stream may be silent before it stops counting.
43
+ static constexpr int64_t StreamTimeOutUs{ 2 * 1000 * 1000 };
44
+ // Window of the meter of incoming data.
45
+ static constexpr int64_t IncomingBitrateWindowMs{ 1000 };
46
+ // Number of items that meter splits its window into, one per millisecond of
47
+ // it. The rate it reports is what the estimation drops to on an overuse, so
48
+ // a coarser item makes the edge of the window take in or let go of a whole
49
+ // frame of the measured stream several milliseconds off, which moves the
50
+ // estimation by as much as that frame is worth.
51
+ static constexpr uint16_t IncomingBitrateWindowItems{ 1000 };
52
+ // Widest gap between a send delta and the mean of the run it is compared
53
+ // against for both to be taken as the same burst.
54
+ static constexpr int64_t MaxClusterDeviationUs{ 2500 };
55
+ // How much longer the arrival deltas of a burst may be than its send deltas,
56
+ // and how much shorter, for the burst to say anything about the link.
57
+ static constexpr int64_t MaxReceiveDeltaExcessUs{ 2000 };
58
+ static constexpr int64_t MaxSendDeltaExcessUs{ 5000 };
59
+
60
+ static_assert(
61
+ IncomingBitrateWindowItems == IncomingBitrateWindowMs,
62
+ "the meter of incoming data needs one item per millisecond of its window");
63
+
64
+ /* Instance methods. */
65
+
66
+ RemoteBitrateEstimatorAbsSendTime::RemoteBitrateEstimatorAbsSendTime(Listener* listener)
67
+ : listener(listener),
68
+ incomingRateCalculator(
69
+ IncomingBitrateWindowMs, RTC::RateCalculator::DefaultBpsScale, IncomingBitrateWindowItems)
70
+ {
71
+ MS_TRACE();
72
+ }
73
+
74
+ void RemoteBitrateEstimatorAbsSendTime::IncomingPacket(
75
+ const RTC::RTP::Packet* packet, int64_t arrivalTimeUs, int64_t nowUs)
76
+ {
77
+ MS_TRACE();
78
+
79
+ uint32_t sendTime24bits{ 0 };
80
+
81
+ if (!packet->ReadAbsSendTime(sendTime24bits))
82
+ {
83
+ MS_WARN_DEV("packet is missing the abs-send-time extension, ignoring it");
84
+
85
+ return;
86
+ }
87
+
88
+ const size_t payloadSize = packet->GetPayloadLength() + packet->GetPaddingLength();
89
+
90
+ // Shift up the send time to use the full 32 bits the inter arrival works
91
+ // with, so that wrapping works properly.
92
+ const uint32_t timestamp = sendTime24bits << AbsSendTimeInterArrivalUpshift;
93
+
94
+ // NOTE: Truncated rather than rounded, which is not a slip. A tick of this
95
+ // field is 3.8 us, so a burst whose packets left exactly a millisecond
96
+ // apart gives deltas that land a hair under or over it. Truncating leaves
97
+ // enough of them at or above the millisecond for the burst to be taken as
98
+ // one, and rounding does not.
99
+ const auto sendTimeUs = static_cast<int64_t>(static_cast<double>(timestamp) * TimestampToUs);
100
+
101
+ // Tell whether the meter of incoming data still has something to say, and
102
+ // start it over when it doesn't.
103
+ const auto incomingBitrateValue = this->incomingRateCalculator.GetRate(arrivalTimeUs / 1000);
104
+
105
+ if (incomingBitrateValue.has_value())
106
+ {
107
+ this->incomingBitrateInitialized = true;
108
+ }
109
+ else if (this->incomingBitrateInitialized)
110
+ {
111
+ // It had a valid value before, but there are no longer enough samples
112
+ // within its window. Start it over so that the window only holds new
113
+ // data.
114
+ this->incomingRateCalculator.Reset();
115
+
116
+ this->incomingBitrateInitialized = false;
117
+ }
118
+
119
+ this->incomingRateCalculator.Update(payloadSize, arrivalTimeUs / 1000);
120
+
121
+ if (!this->firstPacketTimeUs.has_value())
122
+ {
123
+ this->firstPacketTimeUs = nowUs;
124
+ }
125
+
126
+ bool updateEstimate{ false };
127
+ int64_t targetBitrate{ 0 };
128
+
129
+ TimeoutStreams(nowUs);
130
+
131
+ // NOTE: Guaranteed by the call right above, which creates both whenever no
132
+ // stream is left. The very first call always finds none, since the only
133
+ // place a stream is put into the map is below this point, and no path ever
134
+ // gives either of them up afterwards.
135
+ MS_ASSERT(this->interArrival, "no inter arrival");
136
+ MS_ASSERT(this->overuseEstimator, "no overuse estimator");
137
+
138
+ this->ssrcs.insert_or_assign(packet->GetSsrc(), nowUs);
139
+
140
+ // For now only try to detect bursts while there is no valid estimation. It
141
+ // is assumed that only packets larger than 200 bytes are paced by the
142
+ // sender.
143
+ if (
144
+ payloadSize > MinProbePacketSize &&
145
+ (!this->remoteRateControl.IsValidEstimate() ||
146
+ // NOTE: It was given a value right above if it had none, which the
147
+ // checker cannot tell.
148
+ // NOLINTNEXTLINE(bugprone-unchecked-optional-access)
149
+ nowUs - this->firstPacketTimeUs.value() < InitialProbingIntervalUs))
150
+ {
151
+ this->probes.push_back(
152
+ Probe{
153
+ .sendTimeUs = sendTimeUs, .receiveTimeUs = arrivalTimeUs, .payloadSize = payloadSize });
154
+
155
+ // Make sure that a burst which updated the estimation right away has an
156
+ // effect, by telling the listener about it.
157
+ if (ProcessClusters(nowUs) == ProbeResult::BITRATE_UPDATED)
158
+ {
159
+ updateEstimate = true;
160
+ }
161
+ }
162
+
163
+ const auto deltas =
164
+ this->interArrival->ComputeDeltas(timestamp, arrivalTimeUs, nowUs, payloadSize);
165
+
166
+ if (deltas.has_value())
167
+ {
168
+ const auto sendDeltaMs = (1000.0 * static_cast<double>(deltas.value().timestampDelta)) /
169
+ static_cast<double>(1 << InterArrivalShift);
170
+ const auto arrivalDeltaMs = static_cast<double>(deltas.value().arrivalDeltaUs) / 1000.0;
171
+
172
+ this->overuseEstimator->Update(
173
+ arrivalDeltaMs, sendDeltaMs, deltas.value().sizeDelta, this->overuseDetector.GetState());
174
+
175
+ this->overuseDetector.Detect(
176
+ this->overuseEstimator->GetOffsetMs(),
177
+ sendDeltaMs,
178
+ this->overuseEstimator->GetNumOfDeltas(),
179
+ arrivalTimeUs);
180
+ }
181
+
182
+ if (!updateEstimate)
183
+ {
184
+ // Tell whether it's time for a periodic update, or whether there is an
185
+ // overuse to react to right away.
186
+ //
187
+ // NOTE: The wait is measured in whole milliseconds, which is the
188
+ // resolution the interval is expressed in. Microseconds would not be
189
+ // more precise here but a different rule: this is a threshold being
190
+ // crossed, and packets do not arrive on whole milliseconds, so moving
191
+ // the boundary within a millisecond changes which packet crosses it.
192
+ if (
193
+ !this->lastUpdateUs.has_value() ||
194
+ Utils::Time::TimeUsToMs(nowUs) - Utils::Time::TimeUsToMs(this->lastUpdateUs.value()) >
195
+ Utils::Time::TimeUsToMs(this->remoteRateControl.GetFeedbackIntervalUs()))
196
+ {
197
+ updateEstimate = true;
198
+ }
199
+ else if (this->overuseDetector.GetState() == Types::BandwidthUsage::OVERUSING)
200
+ {
201
+ const auto incomingRate = this->incomingRateCalculator.GetRate(arrivalTimeUs / 1000);
202
+
203
+ if (
204
+ incomingRate.has_value() &&
205
+ this->remoteRateControl.IsTimeToReduceFurther(nowUs, incomingRate.value()))
206
+ {
207
+ updateEstimate = true;
208
+ }
209
+ }
210
+ }
211
+
212
+ if (updateEstimate)
213
+ {
214
+ // The first overuse triggers a new estimation right away, and so does
215
+ // being in overuse with an estimation far above what is coming in.
216
+ const Types::RateControlInput input{
217
+ .bandwidthUsage = this->overuseDetector.GetState(),
218
+ .estimatedThroughput = this->incomingRateCalculator.GetRate(arrivalTimeUs / 1000)
219
+ };
220
+
221
+ targetBitrate = this->remoteRateControl.Update(input, nowUs);
222
+ updateEstimate = this->remoteRateControl.IsValidEstimate();
223
+ }
224
+
225
+ if (updateEstimate)
226
+ {
227
+ this->lastUpdateUs = nowUs;
228
+
229
+ std::vector<uint32_t> ssrcs;
230
+
231
+ ssrcs.reserve(this->ssrcs.size());
232
+
233
+ for (const auto& kv : this->ssrcs)
234
+ {
235
+ const uint32_t ssrc = kv.first;
236
+
237
+ ssrcs.push_back(ssrc);
238
+ }
239
+
240
+ this->listener->OnRemoteBitrateEstimatorAbsSendTimeBitrateChanged(this, ssrcs, targetBitrate);
241
+ }
242
+ }
243
+
244
+ void RemoteBitrateEstimatorAbsSendTime::OnRttUpdate(int64_t avgRttUs)
245
+ {
246
+ MS_TRACE();
247
+
248
+ this->remoteRateControl.SetRttUs(avgRttUs);
249
+ }
250
+
251
+ void RemoteBitrateEstimatorAbsSendTime::RemoveStream(uint32_t ssrc)
252
+ {
253
+ MS_TRACE();
254
+
255
+ this->ssrcs.erase(ssrc);
256
+ }
257
+
258
+ int64_t RemoteBitrateEstimatorAbsSendTime::GetLatestEstimate() const
259
+ {
260
+ MS_TRACE();
261
+
262
+ if (!this->remoteRateControl.IsValidEstimate() || this->ssrcs.empty())
263
+ {
264
+ return 0;
265
+ }
266
+
267
+ return this->remoteRateControl.GetLatestEstimate();
268
+ }
269
+
270
+ bool RemoteBitrateEstimatorAbsSendTime::IsWithinClusterBounds(
271
+ int64_t sendDeltaUs, const Cluster& clusterAggregate)
272
+ {
273
+ MS_TRACE();
274
+
275
+ if (clusterAggregate.count == 0)
276
+ {
277
+ return true;
278
+ }
279
+
280
+ const int64_t clusterMeanUs = clusterAggregate.sendMeanUs / clusterAggregate.count;
281
+
282
+ return std::abs(sendDeltaUs - clusterMeanUs) < MaxClusterDeviationUs;
283
+ }
284
+
285
+ void RemoteBitrateEstimatorAbsSendTime::MaybeAddCluster(
286
+ const Cluster& clusterAggregate, std::list<Cluster>& clusters)
287
+ {
288
+ MS_TRACE();
289
+
290
+ if (
291
+ clusterAggregate.count < MinClusterSize || clusterAggregate.sendMeanUs <= 0 ||
292
+ clusterAggregate.receiveMeanUs <= 0)
293
+ {
294
+ return;
295
+ }
296
+
297
+ clusters.push_back(
298
+ Cluster{ .sendMeanUs = clusterAggregate.sendMeanUs / clusterAggregate.count,
299
+ .receiveMeanUs = clusterAggregate.receiveMeanUs / clusterAggregate.count,
300
+ .meanSize = clusterAggregate.meanSize / clusterAggregate.count,
301
+ .count = clusterAggregate.count,
302
+ .numAboveMinDelta = clusterAggregate.numAboveMinDelta });
303
+ }
304
+
305
+ std::list<RemoteBitrateEstimatorAbsSendTime::Cluster> RemoteBitrateEstimatorAbsSendTime::ComputeClusters() const
306
+ {
307
+ MS_TRACE();
308
+
309
+ std::list<Cluster> clusters;
310
+ Cluster clusterAggregate;
311
+ // NOTE: The two instants a delta is taken against always come from the
312
+ // very same probe, so they are held as one rather than as two values that
313
+ // could tell a different story from each other.
314
+ const Probe* prevProbe{ nullptr };
315
+
316
+ for (const auto& probe : this->probes)
317
+ {
318
+ if (prevProbe)
319
+ {
320
+ const int64_t sendDeltaUs = probe.sendTimeUs - prevProbe->sendTimeUs;
321
+ const int64_t receiveDeltaUs = probe.receiveTimeUs - prevProbe->receiveTimeUs;
322
+
323
+ if (sendDeltaUs >= MinClusterDeltaUs && receiveDeltaUs >= MinClusterDeltaUs)
324
+ {
325
+ clusterAggregate.numAboveMinDelta++;
326
+ }
327
+
328
+ if (!IsWithinClusterBounds(sendDeltaUs, clusterAggregate))
329
+ {
330
+ MaybeAddCluster(clusterAggregate, clusters);
331
+
332
+ clusterAggregate = Cluster();
333
+ }
334
+
335
+ clusterAggregate.sendMeanUs += sendDeltaUs;
336
+ clusterAggregate.receiveMeanUs += receiveDeltaUs;
337
+ clusterAggregate.meanSize += probe.payloadSize;
338
+ clusterAggregate.count++;
339
+ }
340
+
341
+ prevProbe = std::addressof(probe);
342
+ }
343
+
344
+ MaybeAddCluster(clusterAggregate, clusters);
345
+
346
+ return clusters;
347
+ }
348
+
349
+ const RemoteBitrateEstimatorAbsSendTime::Cluster* RemoteBitrateEstimatorAbsSendTime::FindBestProbe(
350
+ const std::list<Cluster>& clusters) const
351
+ {
352
+ MS_TRACE();
353
+
354
+ int64_t highestProbeBitrate{ 0 };
355
+ const Cluster* best{ nullptr };
356
+
357
+ for (const auto& cluster : clusters)
358
+ {
359
+ // NOTE: This is not redundant with the check MaybeAddCluster() does.
360
+ // That one requires the sums to be positive, but what is stored is
361
+ // their integer division by the number of probes, and a small enough
362
+ // sum over four probes or more gives a mean of zero. This is what keeps
363
+ // the rates below from dividing by it.
364
+ if (cluster.sendMeanUs == 0 || cluster.receiveMeanUs == 0)
365
+ {
366
+ continue;
367
+ }
368
+
369
+ if (
370
+ cluster.numAboveMinDelta > cluster.count / 2 &&
371
+ (cluster.receiveMeanUs - cluster.sendMeanUs <= MaxReceiveDeltaExcessUs &&
372
+ cluster.sendMeanUs - cluster.receiveMeanUs <= MaxSendDeltaExcessUs))
373
+ {
374
+ const int64_t probeBitrate =
375
+ std::min(cluster.GetSendBitrate(), cluster.GetReceiveBitrate());
376
+
377
+ if (probeBitrate > highestProbeBitrate)
378
+ {
379
+ highestProbeBitrate = probeBitrate;
380
+ best = std::addressof(cluster);
381
+ }
382
+ }
383
+ else
384
+ {
385
+ MS_DEBUG_DEV(
386
+ "burst failed [sendBitrate:%" PRIi64 " bps, receiveBitrate:%" PRIi64
387
+ " bps, sendMean:%" PRIi64 " us, receiveMean:%" PRIi64 " us, numProbes:%d]",
388
+ cluster.GetSendBitrate(),
389
+ cluster.GetReceiveBitrate(),
390
+ cluster.sendMeanUs,
391
+ cluster.receiveMeanUs,
392
+ cluster.count);
393
+
394
+ break;
395
+ }
396
+ }
397
+
398
+ return best;
399
+ }
400
+
401
+ RemoteBitrateEstimatorAbsSendTime::ProbeResult RemoteBitrateEstimatorAbsSendTime::ProcessClusters(
402
+ int64_t nowUs)
403
+ {
404
+ MS_TRACE();
405
+
406
+ const std::list<Cluster> clusters = ComputeClusters();
407
+
408
+ if (clusters.empty())
409
+ {
410
+ // The most probes that are kept have been reached and still no run came
411
+ // out of them, so the oldest one is dropped.
412
+ if (this->probes.size() >= MaxProbePackets)
413
+ {
414
+ this->probes.pop_front();
415
+ }
416
+
417
+ return ProbeResult::NO_UPDATE;
418
+ }
419
+
420
+ const auto* best = FindBestProbe(clusters);
421
+
422
+ if (best)
423
+ {
424
+ const int64_t probeBitrate = std::min(best->GetSendBitrate(), best->GetReceiveBitrate());
425
+
426
+ // Make sure that a burst sent at a lower rate than the estimation cannot
427
+ // bring it down.
428
+ if (IsBitrateImproving(probeBitrate))
429
+ {
430
+ MS_DEBUG_DEV(
431
+ "burst successful [sendBitrate:%" PRIi64 " bps, receiveBitrate:%" PRIi64
432
+ " bps, sendMean:%" PRIi64 " us, receiveMean:%" PRIi64 " us, numProbes:%d]",
433
+ best->GetSendBitrate(),
434
+ best->GetReceiveBitrate(),
435
+ best->sendMeanUs,
436
+ best->receiveMeanUs,
437
+ best->count);
438
+
439
+ this->remoteRateControl.SetEstimate(probeBitrate, nowUs);
440
+
441
+ return ProbeResult::BITRATE_UPDATED;
442
+ }
443
+ }
444
+
445
+ // Either not bursting and a regular packet came in, or done with the
446
+ // current set of probes.
447
+ if (clusters.size() >= ExpectedNumberOfProbes)
448
+ {
449
+ this->probes.clear();
450
+ }
451
+
452
+ return ProbeResult::NO_UPDATE;
453
+ }
454
+
455
+ bool RemoteBitrateEstimatorAbsSendTime::IsBitrateImproving(int64_t probeBitrate) const
456
+ {
457
+ MS_TRACE();
458
+
459
+ const bool initialProbe = !this->remoteRateControl.IsValidEstimate() && probeBitrate > 0;
460
+ const bool bitrateAboveEstimate = this->remoteRateControl.IsValidEstimate() &&
461
+ probeBitrate > this->remoteRateControl.GetLatestEstimate();
462
+
463
+ return initialProbe || bitrateAboveEstimate;
464
+ }
465
+
466
+ void RemoteBitrateEstimatorAbsSendTime::TimeoutStreams(int64_t nowUs)
467
+ {
468
+ MS_TRACE();
469
+
470
+ for (auto it = this->ssrcs.begin(); it != this->ssrcs.end();)
471
+ {
472
+ const int64_t lastSeenUs = it->second;
473
+
474
+ if (nowUs - lastSeenUs > StreamTimeOutUs)
475
+ {
476
+ it = this->ssrcs.erase(it);
477
+ }
478
+ else
479
+ {
480
+ ++it;
481
+ }
482
+ }
483
+
484
+ if (this->ssrcs.empty())
485
+ {
486
+ // The estimation cannot be updated without an active stream, so the
487
+ // delay based detection starts over.
488
+ //
489
+ // NOTE: The instant of the first packet is deliberately not reset, since
490
+ // bursts are only looked for at the beginning of a call.
491
+ this->interArrival = std::make_unique<InterArrival>(
492
+ static_cast<uint32_t>((TimestampGroupLengthMs << InterArrivalShift) / 1000), TimestampToUs);
493
+ this->overuseEstimator = std::make_unique<OveruseEstimator>();
494
+ }
495
+ }
496
+ } // namespace BWE
497
+ } // namespace RTC
@@ -30,6 +30,53 @@ namespace RTC
30
30
  : options(options)
31
31
  {
32
32
  MS_TRACE();
33
+
34
+ // NOTE: Every option below is set from C++ alone, never from the network
35
+ // nor from the API, so a value out of range can only be a programming
36
+ // error. Without them a window that requires no packets would reach the
37
+ // send rate with no send time to compute it from.
38
+ MS_ASSERT(
39
+ this->options.windowPackets >= 10 && this->options.windowPackets <= 1000,
40
+ "window size must be between 10 and 1000 packets [value:%zu]",
41
+ this->options.windowPackets);
42
+ MS_ASSERT(
43
+ this->options.maxWindowPackets >= 10 && this->options.maxWindowPackets <= 1000,
44
+ "max window size must be between 10 and 1000 packets [value:%zu]",
45
+ this->options.maxWindowPackets);
46
+ MS_ASSERT(
47
+ this->options.maxWindowPackets >= this->options.windowPackets,
48
+ "max window size is below the window size [maxWindowPackets:%zu, windowPackets:%zu]",
49
+ this->options.maxWindowPackets,
50
+ this->options.windowPackets);
51
+ MS_ASSERT(
52
+ this->options.requiredPackets >= 10 && this->options.requiredPackets <= 1000,
53
+ "required number of packets must be between 10 and 1000 [value:%zu]",
54
+ this->options.requiredPackets);
55
+ MS_ASSERT(
56
+ this->options.requiredPackets <= this->options.windowPackets,
57
+ "more packets are required than the window holds [requiredPackets:%zu, windowPackets:%zu]",
58
+ this->options.requiredPackets,
59
+ this->options.windowPackets);
60
+ MS_ASSERT(
61
+ this->options.minWindowDurationUs >= 100 * 1000 &&
62
+ this->options.minWindowDurationUs <= 3000 * 1000,
63
+ "window duration must be between 100 and 3000 ms [value:%" PRIi64 "]",
64
+ this->options.minWindowDurationUs);
65
+ MS_ASSERT(
66
+ this->options.maxWindowDurationUs >= 1000 * 1000 &&
67
+ this->options.maxWindowDurationUs <= 15 * 1000 * 1000,
68
+ "max window duration must be between 1 and 15 s [value:%" PRIi64 "]",
69
+ this->options.maxWindowDurationUs);
70
+ MS_ASSERT(
71
+ this->options.maxWindowDurationUs >= this->options.minWindowDurationUs,
72
+ "max window duration is below the window duration [maxWindowDurationUs:%" PRIi64
73
+ ", minWindowDurationUs:%" PRIi64 "]",
74
+ this->options.maxWindowDurationUs,
75
+ this->options.minWindowDurationUs);
76
+ MS_ASSERT(
77
+ this->options.unackedWeight >= 0.0 && this->options.unackedWeight <= 1.0,
78
+ "weight for the prior unacked size must be in [0, 1] [value:%f]",
79
+ this->options.unackedWeight);
33
80
  }
34
81
 
35
82
  void RobustThroughputEstimator::IncomingPacketFeedbackVector(