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,265 @@
1
+ #include "common.hpp"
2
+ #include "RTC/BWE/ProbePacketGenerator.hpp"
3
+ #include "RTC/Consts.hpp"
4
+ #include "RTC/RTP/Packet.hpp"
5
+ #include "Utils.hpp"
6
+ #include <catch2/catch_test_macros.hpp>
7
+ #include <limits>
8
+ #include <string>
9
+ #include <vector>
10
+
11
+ SCENARIO("BWE ProbePacketGenerator", "[bwe][probepacketgenerator]")
12
+ {
13
+ // What a packet of a burst was when it was handed over, kept by value because
14
+ // every one of them is the very same instance.
15
+ struct HandedPacket
16
+ {
17
+ size_t length{ 0 };
18
+ uint16_t sequenceNumber{ 0 };
19
+ uint32_t timestamp{ 0 };
20
+ uint32_t ssrc{ 0 };
21
+ uint8_t payloadType{ 0 };
22
+ std::string mid;
23
+ bool hasAbsSendTime{ false };
24
+ bool hasTransportWideCc01{ false };
25
+ bool isPaddedTo4Bytes{ false };
26
+ };
27
+
28
+ class TestProbePacketGeneratorListener : public RTC::BWE::ProbePacketGenerator::Listener
29
+ {
30
+ public:
31
+ bool OnProbePacketGeneratorSendRtpPacket(
32
+ RTC::BWE::ProbePacketGenerator* /*probePacketGenerator*/, RTC::RTP::Packet* packet) override
33
+ {
34
+ HandedPacket handedPacket;
35
+
36
+ handedPacket.length = packet->GetLength();
37
+ handedPacket.sequenceNumber = packet->GetSequenceNumber();
38
+ handedPacket.timestamp = packet->GetTimestamp();
39
+ handedPacket.ssrc = packet->GetSsrc();
40
+ handedPacket.payloadType = packet->GetPayloadType();
41
+
42
+ packet->ReadMid(handedPacket.mid);
43
+
44
+ uint32_t absSendTime;
45
+ uint16_t wideSeqNumber;
46
+
47
+ handedPacket.hasAbsSendTime = packet->ReadAbsSendTime(absSendTime);
48
+ handedPacket.hasTransportWideCc01 = packet->ReadTransportWideCc01(wideSeqNumber);
49
+ handedPacket.isPaddedTo4Bytes = packet->IsPaddedTo4Bytes();
50
+
51
+ this->handedPackets.push_back(handedPacket);
52
+
53
+ return this->handedPackets.size() < this->stopAfter;
54
+ }
55
+
56
+ public:
57
+ std::vector<HandedPacket> handedPackets;
58
+ // Packets after which the burst is given up on.
59
+ size_t stopAfter{ std::numeric_limits<size_t>::max() };
60
+ };
61
+
62
+ // How far the sequence number moved between two packets.
63
+ //
64
+ // NOTE: The subtraction is done back in 16 bits because the two operands are
65
+ // promoted to int, and the sequence number starts at a random value, so one
66
+ // run in every 65536 has it wrapping around right here.
67
+ const auto sequenceNumberDelta = [](const HandedPacket& from, const HandedPacket& to) -> uint16_t
68
+ {
69
+ return static_cast<uint16_t>(to.sequenceNumber - from.sequenceNumber);
70
+ };
71
+
72
+ // Total of what the given packets carried.
73
+ const auto totalLength = [](const std::vector<HandedPacket>& handedPackets) -> size_t
74
+ {
75
+ size_t total{ 0 };
76
+
77
+ for (const auto& handedPacket : handedPackets)
78
+ {
79
+ total += handedPacket.length;
80
+ }
81
+
82
+ return total;
83
+ };
84
+
85
+ TestProbePacketGeneratorListener listener;
86
+ RTC::BWE::ProbePacketGenerator probePacketGenerator(std::addressof(listener));
87
+
88
+ SECTION("a packet carries what makes it reportable")
89
+ {
90
+ probePacketGenerator.GeneratePackets(1);
91
+
92
+ REQUIRE(listener.handedPackets.size() == 1);
93
+
94
+ const auto& handedPacket = listener.handedPackets.at(0);
95
+
96
+ REQUIRE(handedPacket.ssrc == RTC::Consts::BweProbeRtpSsrc);
97
+ REQUIRE(handedPacket.payloadType == RTC::Consts::BweProbeRtpPayloadType);
98
+ REQUIRE(handedPacket.mid == RTC::Consts::BweProbeRtpMid);
99
+ REQUIRE(handedPacket.hasAbsSendTime);
100
+ REQUIRE(handedPacket.hasTransportWideCc01);
101
+ }
102
+
103
+ SECTION("and the room it leaves for them is one the sender can write into")
104
+ {
105
+ class WritingListener : public RTC::BWE::ProbePacketGenerator::Listener
106
+ {
107
+ public:
108
+ bool OnProbePacketGeneratorSendRtpPacket(
109
+ RTC::BWE::ProbePacketGenerator* /*probePacketGenerator*/, RTC::RTP::Packet* packet) override
110
+ {
111
+ this->sentAtUs += 1000;
112
+ this->wideSeqNumber++;
113
+
114
+ REQUIRE(packet->UpdateAbsSendTime(Utils::Time::TimeUsToAbsSendTime(this->sentAtUs)));
115
+ REQUIRE(packet->UpdateTransportWideCc01(this->wideSeqNumber));
116
+
117
+ uint32_t readAbsSendTime;
118
+ uint16_t readWideSeqNumber;
119
+
120
+ REQUIRE(packet->ReadAbsSendTime(readAbsSendTime));
121
+ REQUIRE(readAbsSendTime == Utils::Time::TimeUsToAbsSendTime(this->sentAtUs));
122
+
123
+ REQUIRE(packet->ReadTransportWideCc01(readWideSeqNumber));
124
+ REQUIRE(readWideSeqNumber == this->wideSeqNumber);
125
+
126
+ return true;
127
+ }
128
+
129
+ public:
130
+ int64_t sentAtUs{ 100000000 };
131
+ uint16_t wideSeqNumber{ 0 };
132
+ };
133
+
134
+ WritingListener writingListener;
135
+ RTC::BWE::ProbePacketGenerator writingProbePacketGenerator(std::addressof(writingListener));
136
+
137
+ writingProbePacketGenerator.GeneratePackets(5000);
138
+
139
+ REQUIRE(writingListener.wideSeqNumber > 1);
140
+ }
141
+
142
+ SECTION("and is padded to 4 bytes whatever its size")
143
+ {
144
+ probePacketGenerator.GeneratePackets(5000);
145
+
146
+ REQUIRE(listener.handedPackets.size() > 1);
147
+
148
+ for (const auto& handedPacket : listener.handedPackets)
149
+ {
150
+ REQUIRE(handedPacket.isPaddedTo4Bytes);
151
+ }
152
+ }
153
+
154
+ SECTION("a burst that fits in one packet is exactly as long as it was asked for")
155
+ {
156
+ probePacketGenerator.GeneratePackets(1000);
157
+
158
+ REQUIRE(listener.handedPackets.size() == 1);
159
+ REQUIRE(listener.handedPackets.at(0).length == 1000);
160
+ }
161
+
162
+ SECTION("asking for less than a header still sends a whole one")
163
+ {
164
+ probePacketGenerator.GeneratePackets(1);
165
+
166
+ REQUIRE(listener.handedPackets.size() == 1);
167
+ REQUIRE(listener.handedPackets.at(0).length > 1);
168
+ }
169
+
170
+ SECTION("asking for nothing sends nothing")
171
+ {
172
+ probePacketGenerator.GeneratePackets(0);
173
+
174
+ REQUIRE(listener.handedPackets.empty());
175
+ }
176
+
177
+ SECTION("what is asked for is split into packets that carry at least that much")
178
+ {
179
+ constexpr size_t Size{ 5000 };
180
+
181
+ probePacketGenerator.GeneratePackets(Size);
182
+
183
+ REQUIRE(listener.handedPackets.size() > 1);
184
+ REQUIRE(totalLength(listener.handedPackets) >= Size);
185
+
186
+ for (const auto& handedPacket : listener.handedPackets)
187
+ {
188
+ REQUIRE(handedPacket.length <= RTC::BWE::ProbePacketGenerator::MaxPacketLength);
189
+ }
190
+ }
191
+
192
+ SECTION("and one that no burst could ever be is brought down to something sendable")
193
+ {
194
+ probePacketGenerator.GeneratePackets(std::numeric_limits<size_t>::max());
195
+
196
+ REQUIRE(!listener.handedPackets.empty());
197
+ REQUIRE(
198
+ totalLength(listener.handedPackets) <= RTC::BWE::ProbePacketGenerator::MaxGeneratePacketsSize +
199
+ RTC::BWE::ProbePacketGenerator::MaxPacketLength);
200
+ }
201
+
202
+ SECTION("and a burst of a single packet is not split")
203
+ {
204
+ probePacketGenerator.GeneratePackets(RTC::BWE::ProbePacketGenerator::MaxPacketLength);
205
+
206
+ REQUIRE(listener.handedPackets.size() == 1);
207
+ REQUIRE(listener.handedPackets.at(0).length == RTC::BWE::ProbePacketGenerator::MaxPacketLength);
208
+ }
209
+
210
+ SECTION("every packet moves the sequence number and the timestamp on")
211
+ {
212
+ probePacketGenerator.GeneratePackets(5000);
213
+
214
+ REQUIRE(listener.handedPackets.size() > 1);
215
+
216
+ for (size_t i{ 1 }; i < listener.handedPackets.size(); ++i)
217
+ {
218
+ const auto& previous = listener.handedPackets.at(i - 1);
219
+ const auto& current = listener.handedPackets.at(i);
220
+
221
+ REQUIRE(sequenceNumberDelta(previous, current) == 1);
222
+ REQUIRE(current.timestamp != previous.timestamp);
223
+ }
224
+ }
225
+
226
+ SECTION("and the ones of a later burst carry on from the ones before")
227
+ {
228
+ probePacketGenerator.GeneratePackets(1);
229
+ probePacketGenerator.GeneratePackets(1);
230
+
231
+ REQUIRE(listener.handedPackets.size() == 2);
232
+
233
+ const auto& first = listener.handedPackets.at(0);
234
+ const auto& second = listener.handedPackets.at(1);
235
+
236
+ REQUIRE(sequenceNumberDelta(first, second) == 1);
237
+ }
238
+
239
+ SECTION("and two of them count their own packets rather than each other's")
240
+ {
241
+ TestProbePacketGeneratorListener otherListener;
242
+ RTC::BWE::ProbePacketGenerator otherProbePacketGenerator(std::addressof(otherListener));
243
+
244
+ probePacketGenerator.GeneratePackets(1);
245
+ otherProbePacketGenerator.GeneratePackets(1);
246
+ probePacketGenerator.GeneratePackets(1);
247
+ otherProbePacketGenerator.GeneratePackets(1);
248
+
249
+ REQUIRE(listener.handedPackets.size() == 2);
250
+ REQUIRE(otherListener.handedPackets.size() == 2);
251
+
252
+ REQUIRE(sequenceNumberDelta(listener.handedPackets.at(0), listener.handedPackets.at(1)) == 1);
253
+ REQUIRE(
254
+ sequenceNumberDelta(otherListener.handedPackets.at(0), otherListener.handedPackets.at(1)) == 1);
255
+ }
256
+
257
+ SECTION("a packet that cannot be sent stops the ones behind it")
258
+ {
259
+ listener.stopAfter = 2;
260
+
261
+ probePacketGenerator.GeneratePackets(50000);
262
+
263
+ REQUIRE(listener.handedPackets.size() == 2);
264
+ }
265
+ }
@@ -0,0 +1,260 @@
1
+ #include "common.hpp"
2
+ #include "RTC/BWE/BweTypes.hpp"
3
+ #include "RTC/BWE/ProbingScheduler.hpp"
4
+ #include "mocks/include/MockShared.hpp"
5
+ #include <catch2/catch_test_macros.hpp>
6
+ #include <string_view>
7
+ #include <vector>
8
+
9
+ SCENARIO("BWE ProbingScheduler", "[bwe][probingscheduler]")
10
+ {
11
+ // The clock starts well away from zero so that a mistake taking a time for a
12
+ // duration doesn't go unnoticed.
13
+ constexpr int64_t InitialTimeUs{ 100000000 };
14
+ constexpr std::string_view TimerLabel{ "probing-scheduler-next-probe" };
15
+
16
+ int64_t nowUs{ InitialTimeUs };
17
+
18
+ mocks::MockShared shared(/*getTimeUs*/
19
+ [&nowUs]() -> int64_t
20
+ {
21
+ return nowUs;
22
+ });
23
+
24
+ class TestProbingSchedulerListener : public RTC::BWE::ProbingScheduler::Listener
25
+ {
26
+ public:
27
+ bool OnProbingSchedulerSendRtpPacket(
28
+ RTC::BWE::ProbingScheduler* /*probingScheduler*/,
29
+ RTC::RTP::Packet* packet,
30
+ const RTC::BWE::Types::ProbeCluster& probeCluster) override
31
+ {
32
+ if (!this->sendPackets)
33
+ {
34
+ return false;
35
+ }
36
+
37
+ this->sentLengths.push_back(packet->GetLength());
38
+ this->sentClusterIds.push_back(probeCluster.id);
39
+
40
+ return true;
41
+ }
42
+
43
+ size_t GetSentBytes() const
44
+ {
45
+ size_t sentBytes{ 0 };
46
+
47
+ for (const auto length : this->sentLengths)
48
+ {
49
+ sentBytes += length;
50
+ }
51
+
52
+ return sentBytes;
53
+ }
54
+
55
+ public:
56
+ std::vector<size_t> sentLengths;
57
+ // The burst each of those packets was handed over as part of.
58
+ std::vector<int64_t> sentClusterIds;
59
+ bool sendPackets{ true };
60
+ };
61
+
62
+ TestProbingSchedulerListener listener;
63
+
64
+ const auto makeClusterConfig = [](
65
+ int64_t id,
66
+ int64_t atUs,
67
+ int64_t targetBitrate,
68
+ int64_t minProbeDeltaUs) -> RTC::BWE::Types::ProbeClusterConfig
69
+ {
70
+ return RTC::BWE::Types::ProbeClusterConfig{ .id = id,
71
+ .atUs = atUs,
72
+ .targetBitrate = targetBitrate,
73
+ .targetDurationUs = 15 * 1000,
74
+ .minProbeDeltaUs = minProbeDeltaUs,
75
+ .targetProbeCount = 5 };
76
+ };
77
+
78
+ // Move the clock to when the next shot is due and let it out. Answers whether
79
+ // there was one to begin with.
80
+ const auto emitNextShot = [&nowUs, &shared, TimerLabel]() -> bool
81
+ {
82
+ auto* timer = shared.GetTimer(TimerLabel);
83
+
84
+ if (!timer->IsActive())
85
+ {
86
+ return false;
87
+ }
88
+
89
+ nowUs = std::max(nowUs, timer->GetExpiresAtMs() * 1000);
90
+
91
+ return timer->EvaluateHasExpired();
92
+ };
93
+
94
+ SECTION("a burst is emitted on the turn of the loop that follows asking for it")
95
+ {
96
+ RTC::BWE::ProbingScheduler probingScheduler(std::addressof(listener), std::addressof(shared));
97
+
98
+ REQUIRE(!probingScheduler.IsProbing());
99
+ REQUIRE(listener.sentLengths.empty());
100
+
101
+ probingScheduler.CreateProbeClusters({ makeClusterConfig(0, nowUs, 900000, 2 * 1000) });
102
+
103
+ auto* timer = shared.GetTimer(TimerLabel);
104
+
105
+ REQUIRE(timer != nullptr);
106
+ // Asking for it doesn't put the send path in the caller's stack.
107
+ REQUIRE(listener.sentLengths.empty());
108
+ // But nothing is waited for either: it's due right away.
109
+ REQUIRE(timer->IsActive());
110
+ REQUIRE(timer->GetTimeoutMs() == 0);
111
+
112
+ REQUIRE(emitNextShot());
113
+
114
+ REQUIRE(!listener.sentLengths.empty());
115
+ REQUIRE(probingScheduler.IsProbing());
116
+ // Every packet is handed over as part of the burst it belongs to.
117
+ REQUIRE(listener.sentClusterIds.front() == 0);
118
+ }
119
+
120
+ SECTION("a burst goes out in as many shots as it was asked for")
121
+ {
122
+ constexpr int64_t TestBitrate{ 900000 };
123
+ constexpr int64_t MinProbeDeltaUs{ 2 * 1000 };
124
+ // What the burst is meant to carry, which is its bitrate held for the time
125
+ // it is meant to last, rounded to the nearest byte.
126
+ constexpr size_t MinBytes{ ((TestBitrate * (15 * 1000)) + 4000000) / (8 * 1000000) };
127
+
128
+ RTC::BWE::ProbingScheduler probingScheduler(std::addressof(listener), std::addressof(shared));
129
+
130
+ probingScheduler.CreateProbeClusters(
131
+ { makeClusterConfig(0, nowUs, TestBitrate, MinProbeDeltaUs) });
132
+
133
+ size_t shots{ 0 };
134
+
135
+ while (emitNextShot())
136
+ {
137
+ ++shots;
138
+ }
139
+
140
+ // Both counts have to be reached, since a burst of too few packets says
141
+ // nothing however many bytes it carried, and the other way round.
142
+ REQUIRE(shots >= 5);
143
+ REQUIRE(listener.GetSentBytes() >= MinBytes);
144
+
145
+ // And once it is done there is nothing left running.
146
+ REQUIRE(!probingScheduler.IsProbing());
147
+ REQUIRE(!shared.GetTimer(TimerLabel)->IsActive());
148
+ }
149
+
150
+ SECTION("the shots that piled up while the loop was held up go out together")
151
+ {
152
+ constexpr int64_t TestBitrate{ 900000 };
153
+ constexpr int64_t MinProbeDeltaUs{ 2 * 1000 };
154
+
155
+ RTC::BWE::ProbingScheduler probingScheduler(std::addressof(listener), std::addressof(shared));
156
+
157
+ probingScheduler.CreateProbeClusters(
158
+ { makeClusterConfig(0, nowUs, TestBitrate, MinProbeDeltaUs) });
159
+
160
+ REQUIRE(emitNextShot());
161
+
162
+ const size_t packetsAfterFirstShot = listener.sentLengths.size();
163
+
164
+ REQUIRE(packetsAfterFirstShot > 0);
165
+
166
+ // The loop gives no sign of life for the time of several shots.
167
+ //
168
+ // NOTE: The span has to sit between two bounds, which is the only window
169
+ // where piling up happens at all. Below the time between two shots nothing
170
+ // piles up, and above `BitrateProberOptions::maxProbeDelayUs`, which
171
+ // defaults to 10 ms, the burst is given up on rather than emitted late, so
172
+ // there would be nothing left to send. Six milliseconds is inside both.
173
+ nowUs += 3 * MinProbeDeltaUs;
174
+
175
+ auto* timer = shared.GetTimer(TimerLabel);
176
+
177
+ REQUIRE(timer->IsActive());
178
+ REQUIRE(timer->EvaluateHasExpired());
179
+
180
+ // All of them went out on that single tick instead of one per turn of the
181
+ // loop, which would have stretched the burst well below its bitrate.
182
+ REQUIRE(listener.sentLengths.size() > packetsAfterFirstShot + 1);
183
+ }
184
+
185
+ SECTION("the shots of a burst are spaced by the time it asked for")
186
+ {
187
+ constexpr int64_t TestBitrate{ 900000 };
188
+ constexpr int64_t MinProbeDeltaUs{ 10 * 1000 };
189
+
190
+ RTC::BWE::ProbingScheduler probingScheduler(std::addressof(listener), std::addressof(shared));
191
+
192
+ probingScheduler.CreateProbeClusters(
193
+ { makeClusterConfig(0, nowUs, TestBitrate, MinProbeDeltaUs) });
194
+
195
+ REQUIRE(emitNextShot());
196
+
197
+ // The burst is measured from when its first packet went out.
198
+ const int64_t startTimeUs = nowUs;
199
+ auto* timer = shared.GetTimer(TimerLabel);
200
+
201
+ // The next shot is due once the bytes already gone out have been carried at
202
+ // the bitrate asked for, measured from the start of the burst.
203
+ const int64_t expectedNextUs =
204
+ startTimeUs + ((static_cast<int64_t>(listener.GetSentBytes()) * 8 * 1000000) / TestBitrate);
205
+
206
+ REQUIRE(timer->IsActive());
207
+ // The tick lands just before the shot is due rather than just after, since
208
+ // what is left of the wait by then is under a millisecond and goes out
209
+ // anyway. A burst whose shots all left late would measure a bitrate below
210
+ // the one it was asked for.
211
+ REQUIRE(timer->GetExpiresAtMs() * 1000 <= expectedNextUs);
212
+ REQUIRE(expectedNextUs - (timer->GetExpiresAtMs() * 1000) < 1000);
213
+ }
214
+
215
+ SECTION("a listener that cannot send stops the burst")
216
+ {
217
+ RTC::BWE::ProbingScheduler probingScheduler(std::addressof(listener), std::addressof(shared));
218
+
219
+ listener.sendPackets = false;
220
+
221
+ probingScheduler.CreateProbeClusters({ makeClusterConfig(0, nowUs, 900000, 2 * 1000) });
222
+
223
+ REQUIRE(emitNextShot());
224
+ REQUIRE(listener.sentLengths.empty());
225
+
226
+ // Nothing went out, so there is no reason to believe that trying again
227
+ // would do any better.
228
+ REQUIRE(!shared.GetTimer(TimerLabel)->IsActive());
229
+ }
230
+
231
+ SECTION("a burst asked for while another one is being emitted waits for it")
232
+ {
233
+ constexpr int64_t TestBitrate{ 900000 };
234
+
235
+ RTC::BWE::ProbingScheduler probingScheduler(std::addressof(listener), std::addressof(shared));
236
+
237
+ // Both at once, which is what the controller does when it asks for the two
238
+ // bursts the connection opens with.
239
+ probingScheduler.CreateProbeClusters(
240
+ { makeClusterConfig(0, nowUs, TestBitrate, 2 * 1000),
241
+ makeClusterConfig(1, nowUs, TestBitrate, 2 * 1000) });
242
+
243
+ while (emitNextShot())
244
+ {
245
+ // Nothing to do, the shots go out on their own.
246
+ }
247
+
248
+ // Two whole bursts went out, not one.
249
+ constexpr size_t MinBytes{ ((TestBitrate * (15 * 1000)) + 4000000) / (8 * 1000000) };
250
+
251
+ REQUIRE(listener.GetSentBytes() >= 2 * MinBytes);
252
+ REQUIRE(!probingScheduler.IsProbing());
253
+
254
+ // And each of them was handed over as its own, in the order they were asked
255
+ // for and without mixing their packets.
256
+ REQUIRE(listener.sentClusterIds.front() == 0);
257
+ REQUIRE(listener.sentClusterIds.back() == 1);
258
+ REQUIRE(std::ranges::is_sorted(listener.sentClusterIds));
259
+ }
260
+ }