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,519 @@
1
+ #include "common.hpp"
2
+ #include "RTC/BWE/InterArrival.hpp"
3
+ #include "RTC/BWE/OveruseDetector.hpp"
4
+ #include "RTC/BWE/OveruseEstimator.hpp"
5
+ #include <catch2/catch_test_macros.hpp>
6
+ #include <cmath>
7
+ #include <numbers>
8
+
9
+ SCENARIO("BWE OveruseDetector", "[bwe][overusedetector]")
10
+ {
11
+ // Ticks of a 90 kHz clock, which is what the timestamps of this test are.
12
+ constexpr double RtpTimestampToUs{ 1000.0 / 90.0 };
13
+ constexpr size_t PacketSize{ 1200 };
14
+
15
+ /**
16
+ * Pseudo random generator with a fixed seed, used to add jitter to the
17
+ * arrival times of the cases below.
18
+ *
19
+ * It's a xorshift of 64 bits scaled by a constant, plus a normal
20
+ * distribution built out of two of its outputs by the Box-Muller transform.
21
+ *
22
+ * @remarks
23
+ * - It's copied from `Random` in `rtc_base/random.{h,cc}` of libwebrtc, and
24
+ * that is the whole point of it: the cases below assert after how many
25
+ * frames congestion is detected, and those counts come from
26
+ * `overuse_detector_unittest.cc`, where they were produced by this exact
27
+ * generator seeded with this exact value. Any other sequence of jitter
28
+ * yields other counts.
29
+ */
30
+ class TestRandom
31
+ {
32
+ public:
33
+ explicit TestRandom(uint64_t seed) : state(seed)
34
+ {
35
+ }
36
+
37
+ /**
38
+ * Uniformly distributed within [low, high].
39
+ */
40
+ int64_t Rand(int64_t low, int64_t high)
41
+ {
42
+ const auto t = static_cast<uint32_t>(high - low);
43
+ const auto x = static_cast<uint32_t>(NextOutput());
44
+ const uint64_t result = (static_cast<uint64_t>(x) * (static_cast<uint64_t>(t) + 1)) >> 32;
45
+
46
+ return static_cast<int64_t>(result) + low;
47
+ }
48
+
49
+ double Gaussian(double mean, double standardDeviation)
50
+ {
51
+ const double u1 = static_cast<double>(NextOutput()) / static_cast<double>(0xFFFFFFFFFFFFFFFF);
52
+ const double u2 = static_cast<double>(NextOutput()) / static_cast<double>(0xFFFFFFFFFFFFFFFF);
53
+
54
+ return mean + (standardDeviation * std::sqrt(-2 * std::log(u1)) *
55
+ std::cos(2 * std::numbers::pi * u2));
56
+ }
57
+
58
+ private:
59
+ uint64_t NextOutput()
60
+ {
61
+ this->state ^= this->state >> 12;
62
+ this->state ^= this->state << 25;
63
+ this->state ^= this->state >> 27;
64
+
65
+ return this->state * 2685821657736338717ULL;
66
+ }
67
+
68
+ private:
69
+ uint64_t state;
70
+ };
71
+
72
+ int64_t nowMs{ 0 };
73
+ int64_t receiveTimeMs{ 0 };
74
+ uint32_t rtpTimestamp{ 10 * 90 };
75
+
76
+ RTC::BWE::OveruseDetector overuseDetector;
77
+ RTC::BWE::OveruseEstimator overuseEstimator;
78
+ RTC::BWE::InterArrival interArrival(5 * 90, RtpTimestampToUs);
79
+ TestRandom random(123456789);
80
+
81
+ // Feed one packet through the whole chain, which is what this test drives:
82
+ // the grouping, the estimate and the detection.
83
+ const auto updateDetector = [&interArrival, &overuseEstimator, &overuseDetector](
84
+ uint32_t rtpTimestamp, int64_t receiveTimeMs, size_t packetSize) -> void
85
+ {
86
+ const auto deltas = interArrival.ComputeDeltas(
87
+ rtpTimestamp, receiveTimeMs * 1000, receiveTimeMs * 1000, packetSize);
88
+
89
+ if (!deltas.has_value())
90
+ {
91
+ return;
92
+ }
93
+
94
+ // NOLINTNEXTLINE(bugprone-unchecked-optional-access)
95
+ const auto& value = deltas.value();
96
+ const double sendDeltaMs = value.timestampDelta / 90.0;
97
+
98
+ overuseEstimator.Update(
99
+ static_cast<double>(value.arrivalDeltaUs) / 1000.0,
100
+ sendDeltaMs,
101
+ value.sizeDelta,
102
+ overuseDetector.GetState());
103
+ overuseDetector.Detect(
104
+ overuseEstimator.GetOffsetMs(),
105
+ sendDeltaMs,
106
+ overuseEstimator.GetNumOfDeltas(),
107
+ receiveTimeMs * 1000);
108
+ };
109
+
110
+ // Run a long steady stream and count how many separate times congestion was
111
+ // declared, which for a stream that isn't congested must be none.
112
+ const auto run100000Samples =
113
+ [&nowMs, &receiveTimeMs, &rtpTimestamp, &overuseDetector, &random, &updateDetector](
114
+ int64_t packetsPerFrame, size_t packetSize, int64_t meanMs, int64_t standardDeviationMs) -> int64_t
115
+ {
116
+ int64_t uniqueOveruse{ 0 };
117
+ int64_t lastOveruse{ -1 };
118
+
119
+ for (int64_t i{ 0 }; i < 100000; ++i)
120
+ {
121
+ for (int64_t j{ 0 }; j < packetsPerFrame; ++j)
122
+ {
123
+ updateDetector(rtpTimestamp, receiveTimeMs, packetSize);
124
+ }
125
+
126
+ rtpTimestamp += meanMs * 90;
127
+ nowMs += meanMs;
128
+ const double jitter = random.Gaussian(0, static_cast<double>(standardDeviationMs));
129
+ // NOTE: Truncated towards zero rather than rounded with std::llround(),
130
+ // which rounds away from it. Half of these samples are negative, so the
131
+ // two disagree on them and the counts asserted below would no longer
132
+ // hold.
133
+ // NOLINTNEXTLINE(bugprone-incorrect-roundings)
134
+ const auto jitterMs = static_cast<int64_t>(jitter + 0.5);
135
+
136
+ receiveTimeMs = std::max<int64_t>(receiveTimeMs, nowMs + jitterMs);
137
+
138
+ if (overuseDetector.GetState() == RTC::BWE::Types::BandwidthUsage::OVERUSING)
139
+ {
140
+ if (lastOveruse + 1 != i)
141
+ {
142
+ uniqueOveruse++;
143
+ }
144
+
145
+ lastOveruse = i;
146
+ }
147
+ }
148
+
149
+ return uniqueOveruse;
150
+ };
151
+
152
+ // Send faster than the link takes and answer after how many frames it was
153
+ // noticed, or -1 if it never was.
154
+ const auto runUntilOveruse =
155
+ [&nowMs, &receiveTimeMs, &rtpTimestamp, &overuseDetector, &random, &updateDetector](
156
+ int64_t packetsPerFrame,
157
+ size_t packetSize,
158
+ int64_t meanMs,
159
+ int64_t standardDeviationMs,
160
+ int64_t driftPerFrameMs) -> int64_t
161
+ {
162
+ for (int64_t i{ 0 }; i < 1000; ++i)
163
+ {
164
+ for (int64_t j{ 0 }; j < packetsPerFrame; ++j)
165
+ {
166
+ updateDetector(rtpTimestamp, receiveTimeMs, packetSize);
167
+ }
168
+
169
+ rtpTimestamp += meanMs * 90;
170
+ nowMs += meanMs + driftPerFrameMs;
171
+ const double jitter = random.Gaussian(0, static_cast<double>(standardDeviationMs));
172
+ // NOTE: Truncated towards zero rather than rounded with std::llround(),
173
+ // which rounds away from it. Half of these samples are negative, so the
174
+ // two disagree on them and the counts asserted below would no longer
175
+ // hold.
176
+ // NOLINTNEXTLINE(bugprone-incorrect-roundings)
177
+ const auto jitterMs = static_cast<int64_t>(jitter + 0.5);
178
+
179
+ receiveTimeMs = std::max<int64_t>(receiveTimeMs, nowMs + jitterMs);
180
+
181
+ if (overuseDetector.GetState() == RTC::BWE::Types::BandwidthUsage::OVERUSING)
182
+ {
183
+ return i + 1;
184
+ }
185
+ }
186
+
187
+ return -1;
188
+ };
189
+
190
+ // What every case below does: run a steady stream that must never be called
191
+ // congested, then add a drift and check after how many frames it is.
192
+ const auto expectNoOveruseThenOveruseAfter = [&run100000Samples, &runUntilOveruse](
193
+ int64_t packetsPerFrame,
194
+ int64_t frameDurationMs,
195
+ int64_t driftPerFrameMs,
196
+ int64_t sigmaMs,
197
+ int64_t expectedFramesUntilOveruse) -> void
198
+ {
199
+ REQUIRE(run100000Samples(packetsPerFrame, PacketSize, frameDurationMs, sigmaMs) == 0);
200
+ REQUIRE(
201
+ runUntilOveruse(packetsPerFrame, PacketSize, frameDurationMs, sigmaMs, driftPerFrameMs) ==
202
+ expectedFramesUntilOveruse);
203
+ };
204
+
205
+ SECTION("a steady 30 fps stream with no variance is never called congested")
206
+ {
207
+ constexpr uint32_t FrameDurationMs{ 33 };
208
+
209
+ uint32_t timestamp = 10 * 90;
210
+
211
+ for (int64_t i{ 0 }; i < 1000; ++i)
212
+ {
213
+ updateDetector(timestamp, nowMs, PacketSize);
214
+
215
+ nowMs += FrameDurationMs;
216
+ timestamp += FrameDurationMs * 90;
217
+
218
+ REQUIRE(overuseDetector.GetState() == RTC::BWE::Types::BandwidthUsage::NORMAL);
219
+ }
220
+ }
221
+
222
+ SECTION("nor is one whose packets arrive a few milliseconds early and late")
223
+ {
224
+ constexpr uint32_t FrameDurationMs{ 10 };
225
+
226
+ uint32_t timestamp = 10 * 90;
227
+
228
+ for (int64_t i{ 0 }; i < 1000; ++i)
229
+ {
230
+ updateDetector(timestamp, nowMs, PacketSize);
231
+
232
+ timestamp += FrameDurationMs * 90;
233
+
234
+ if (i % 2 != 0)
235
+ {
236
+ nowMs += FrameDurationMs - 5;
237
+ }
238
+ else
239
+ {
240
+ nowMs += FrameDurationMs + 5;
241
+ }
242
+
243
+ REQUIRE(overuseDetector.GetState() == RTC::BWE::Types::BandwidthUsage::NORMAL);
244
+ }
245
+ }
246
+
247
+ SECTION("nor one whose timestamps are the ones moving early and late")
248
+ {
249
+ constexpr uint32_t FrameDurationMs{ 10 };
250
+
251
+ uint32_t timestamp = 10 * 90;
252
+
253
+ for (int64_t i{ 0 }; i < 1000; ++i)
254
+ {
255
+ updateDetector(timestamp, nowMs, PacketSize);
256
+
257
+ nowMs += FrameDurationMs;
258
+
259
+ if (i % 2 != 0)
260
+ {
261
+ timestamp += (FrameDurationMs - 5) * 90;
262
+ }
263
+ else
264
+ {
265
+ timestamp += (FrameDurationMs + 5) * 90;
266
+ }
267
+
268
+ REQUIRE(overuseDetector.GetState() == RTC::BWE::Types::BandwidthUsage::NORMAL);
269
+ }
270
+ }
271
+
272
+ SECTION("2000 kbps at 30 fps with no variance")
273
+ {
274
+ expectNoOveruseThenOveruseAfter(6, 33, 1, 0, 7);
275
+ }
276
+
277
+ SECTION("100 kbps at 10 fps with no variance")
278
+ {
279
+ expectNoOveruseThenOveruseAfter(1, 100, 1, 0, 7);
280
+ }
281
+
282
+ SECTION("a delay that builds up over a few frames is noticed on the last one")
283
+ {
284
+ constexpr uint32_t FrameDurationMs{ 33 };
285
+ constexpr uint32_t DriftPerFrameMs{ 1 };
286
+
287
+ uint32_t timestamp = FrameDurationMs * 90;
288
+ int64_t offset{ 0 };
289
+
290
+ // Run enough samples to reach a steady state.
291
+ for (int64_t i{ 0 }; i < 1000; ++i)
292
+ {
293
+ for (int64_t j{ 0 }; j < 6; ++j)
294
+ {
295
+ updateDetector(timestamp, nowMs, PacketSize);
296
+ }
297
+
298
+ timestamp += FrameDurationMs * 90;
299
+
300
+ if (i % 2 != 0)
301
+ {
302
+ offset = random.Rand(0, 1);
303
+ nowMs += FrameDurationMs - offset;
304
+ }
305
+ else
306
+ {
307
+ nowMs += FrameDurationMs + offset;
308
+ }
309
+
310
+ REQUIRE(overuseDetector.GetState() == RTC::BWE::Types::BandwidthUsage::NORMAL);
311
+ }
312
+
313
+ // Now send faster than the link takes, building up 30 ms in total.
314
+ for (int64_t j{ 0 }; j < 3; ++j)
315
+ {
316
+ for (int64_t k{ 0 }; k < 6; ++k)
317
+ {
318
+ updateDetector(timestamp, nowMs, PacketSize);
319
+ }
320
+
321
+ nowMs += FrameDurationMs + (DriftPerFrameMs * 6);
322
+ timestamp += FrameDurationMs * 90;
323
+
324
+ REQUIRE(overuseDetector.GetState() == RTC::BWE::Types::BandwidthUsage::NORMAL);
325
+ }
326
+
327
+ updateDetector(timestamp, nowMs, PacketSize);
328
+
329
+ REQUIRE(overuseDetector.GetState() == RTC::BWE::Types::BandwidthUsage::OVERUSING);
330
+ }
331
+
332
+ SECTION("30 kbps at 3 fps with low variance")
333
+ {
334
+ expectNoOveruseThenOveruseAfter(1, 333, 1, 3, 20);
335
+ }
336
+
337
+ SECTION("30 kbps at 3 fps with low variance and a fast drift")
338
+ {
339
+ expectNoOveruseThenOveruseAfter(1, 333, 100, 3, 4);
340
+ }
341
+
342
+ SECTION("30 kbps at 3 fps with high variance")
343
+ {
344
+ expectNoOveruseThenOveruseAfter(1, 333, 1, 10, 44);
345
+ }
346
+
347
+ SECTION("30 kbps at 3 fps with high variance and a fast drift")
348
+ {
349
+ expectNoOveruseThenOveruseAfter(1, 333, 100, 10, 4);
350
+ }
351
+
352
+ SECTION("100 kbps at 5 fps with low variance")
353
+ {
354
+ expectNoOveruseThenOveruseAfter(2, 200, 1, 3, 20);
355
+ }
356
+
357
+ SECTION("100 kbps at 5 fps with high variance")
358
+ {
359
+ expectNoOveruseThenOveruseAfter(2, 200, 1, 10, 44);
360
+ }
361
+
362
+ SECTION("100 kbps at 10 fps with low variance")
363
+ {
364
+ expectNoOveruseThenOveruseAfter(1, 100, 1, 3, 20);
365
+ }
366
+
367
+ SECTION("100 kbps at 10 fps with high variance")
368
+ {
369
+ expectNoOveruseThenOveruseAfter(1, 100, 1, 10, 44);
370
+ }
371
+
372
+ SECTION("300 kbps at 30 fps with low variance")
373
+ {
374
+ expectNoOveruseThenOveruseAfter(1, 33, 1, 3, 19);
375
+ }
376
+
377
+ SECTION("300 kbps at 30 fps with low variance and a fast drift")
378
+ {
379
+ expectNoOveruseThenOveruseAfter(1, 33, 10, 3, 5);
380
+ }
381
+
382
+ SECTION("300 kbps at 30 fps with high variance")
383
+ {
384
+ expectNoOveruseThenOveruseAfter(1, 33, 1, 10, 44);
385
+ }
386
+
387
+ SECTION("300 kbps at 30 fps with high variance and a fast drift")
388
+ {
389
+ expectNoOveruseThenOveruseAfter(1, 33, 10, 10, 10);
390
+ }
391
+
392
+ SECTION("1000 kbps at 30 fps with low variance")
393
+ {
394
+ expectNoOveruseThenOveruseAfter(3, 33, 1, 3, 19);
395
+ }
396
+
397
+ SECTION("1000 kbps at 30 fps with low variance and a fast drift")
398
+ {
399
+ expectNoOveruseThenOveruseAfter(3, 33, 10, 3, 5);
400
+ }
401
+
402
+ SECTION("1000 kbps at 30 fps with high variance")
403
+ {
404
+ expectNoOveruseThenOveruseAfter(3, 33, 1, 10, 44);
405
+ }
406
+
407
+ SECTION("1000 kbps at 30 fps with high variance and a fast drift")
408
+ {
409
+ expectNoOveruseThenOveruseAfter(3, 33, 10, 10, 10);
410
+ }
411
+
412
+ SECTION("2000 kbps at 30 fps with low variance")
413
+ {
414
+ expectNoOveruseThenOveruseAfter(6, 33, 1, 3, 19);
415
+ }
416
+
417
+ SECTION("2000 kbps at 30 fps with low variance and a fast drift")
418
+ {
419
+ expectNoOveruseThenOveruseAfter(6, 33, 10, 3, 5);
420
+ }
421
+
422
+ SECTION("2000 kbps at 30 fps with high variance")
423
+ {
424
+ expectNoOveruseThenOveruseAfter(6, 33, 1, 10, 44);
425
+ }
426
+
427
+ SECTION("2000 kbps at 30 fps with high variance and a fast drift")
428
+ {
429
+ expectNoOveruseThenOveruseAfter(6, 33, 10, 10, 10);
430
+ }
431
+
432
+ SECTION("the threshold adapts to what it keeps being shown")
433
+ {
434
+ constexpr double Offset{ 0.21 };
435
+ constexpr double TsDeltaMs{ 3000.0 };
436
+ constexpr int64_t BatchLength{ 10 };
437
+
438
+ int64_t nowUs{ 0 };
439
+ int64_t numDeltas{ 60 };
440
+
441
+ // Whether congestion was declared at any point of the batch, which is what
442
+ // every step below looks at.
443
+ const auto runBatch = [&overuseDetector, &nowUs, &numDeltas](
444
+ int64_t batchLength, double offsetMs) -> bool
445
+ {
446
+ bool overuseDetected{ false };
447
+
448
+ for (int64_t i{ 0 }; i < batchLength; ++i)
449
+ {
450
+ if (overuseDetector.Detect(offsetMs, TsDeltaMs, numDeltas, nowUs) == RTC::BWE::Types::BandwidthUsage::OVERUSING)
451
+ {
452
+ overuseDetected = true;
453
+ }
454
+
455
+ ++numDeltas;
456
+ nowUs += 5 * 1000;
457
+ }
458
+
459
+ return overuseDetected;
460
+ };
461
+
462
+ // A positive offset triggers congestion.
463
+ REQUIRE(runBatch(BatchLength, Offset));
464
+
465
+ // A higher one forces the threshold up, and triggers it too.
466
+ REQUIRE(runBatch(BatchLength, 1.1 * Offset));
467
+
468
+ // So the one that triggered it at first no longer does.
469
+ REQUIRE(!runBatch(BatchLength, Offset));
470
+
471
+ // A low offset shown for long enough brings the threshold back down.
472
+ REQUIRE(!runBatch(15 * BatchLength, 0.7 * Offset));
473
+
474
+ // And then the original offset triggers it again.
475
+ REQUIRE(runBatch(BatchLength, Offset));
476
+ }
477
+
478
+ SECTION("the threshold doesn't adapt to an isolated spike")
479
+ {
480
+ constexpr double Offset{ 1.0 };
481
+ constexpr double LargeOffset{ 20.0 };
482
+ constexpr double TsDeltaMs{ 3000.0 };
483
+ constexpr int64_t BatchLength{ 10 };
484
+ constexpr int64_t ShortBatchLength{ 3 };
485
+
486
+ int64_t nowUs{ 0 };
487
+ int64_t numDeltas{ 60 };
488
+
489
+ const auto runBatch = [&overuseDetector, &nowUs, &numDeltas](
490
+ int64_t batchLength, double offsetMs) -> bool
491
+ {
492
+ bool overuseDetected{ false };
493
+
494
+ for (int64_t i{ 0 }; i < batchLength; ++i)
495
+ {
496
+ if (overuseDetector.Detect(offsetMs, TsDeltaMs, numDeltas, nowUs) == RTC::BWE::Types::BandwidthUsage::OVERUSING)
497
+ {
498
+ overuseDetected = true;
499
+ }
500
+
501
+ ++numDeltas;
502
+ nowUs += 5 * 1000;
503
+ }
504
+
505
+ return overuseDetected;
506
+ };
507
+
508
+ // A positive offset triggers congestion.
509
+ runBatch(BatchLength, Offset);
510
+
511
+ // A far larger one triggers it too, without moving the threshold much.
512
+ nowUs += 100 * 1000;
513
+
514
+ REQUIRE(runBatch(ShortBatchLength, LargeOffset));
515
+
516
+ // So the ordinary offset still triggers it.
517
+ REQUIRE(runBatch(BatchLength, Offset));
518
+ }
519
+ }