mediasoup 3.27.1 → 3.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/node/lib/Consumer.d.ts.map +1 -1
- package/node/lib/Consumer.js +4 -51
- package/node/lib/Producer.d.ts.map +1 -1
- package/node/lib/Producer.js +4 -8
- package/node/lib/ProducerTypes.d.ts +4 -2
- package/node/lib/ProducerTypes.d.ts.map +1 -1
- package/node/lib/Router.d.ts.map +1 -1
- package/node/lib/Router.js +4 -0
- package/node/lib/Transport.d.ts.map +1 -1
- package/node/lib/Transport.js +7 -10
- package/node/lib/fbs/rtp-parameters/rtp-header-extension-uri.d.ts +3 -4
- package/node/lib/fbs/rtp-parameters/rtp-header-extension-uri.d.ts.map +1 -1
- package/node/lib/fbs/rtp-parameters/rtp-header-extension-uri.js +3 -4
- package/node/lib/ortc.d.ts +0 -2
- package/node/lib/ortc.d.ts.map +1 -1
- package/node/lib/ortc.js +11 -21
- package/node/lib/rtpMappingFbsUtils.d.ts +6 -0
- package/node/lib/rtpMappingFbsUtils.d.ts.map +1 -0
- package/node/lib/rtpMappingFbsUtils.js +65 -0
- package/node/lib/rtpParametersFbsUtils.d.ts.map +1 -1
- package/node/lib/rtpParametersFbsUtils.js +0 -6
- package/node/lib/rtpParametersTypes.d.ts +1 -1
- package/node/lib/rtpParametersTypes.d.ts.map +1 -1
- package/node/lib/rtpStreamFbsUtils.d.ts +4 -0
- package/node/lib/rtpStreamFbsUtils.d.ts.map +1 -0
- package/node/lib/rtpStreamFbsUtils.js +51 -0
- package/node/lib/supportedRtpCapabilities.d.ts.map +1 -1
- package/node/lib/supportedRtpCapabilities.js +6 -13
- package/node/lib/test/test-Consumer.js +1 -13
- package/node/lib/test/test-DataConsumer.js +9 -0
- package/node/lib/test/test-DataProducer.js +38 -0
- package/node/lib/test/test-PipeTransport.js +27 -29
- package/node/lib/test/test-Producer.js +97 -0
- package/node/lib/test/test-ortc.js +34 -14
- package/package.json +10 -10
- package/worker/fbs/rtpParameters.fbs +0 -1
- package/worker/fuzzer/src/FuzzerUtils.cpp +5 -3
- package/worker/fuzzer/src/RTC/RTP/FuzzerPacket.cpp +16 -2
- package/worker/include/DepLibUV.hpp +13 -0
- package/worker/include/RTC/BWE/AlrDetector.hpp +97 -0
- package/worker/include/RTC/BWE/BitrateProber.hpp +217 -0
- package/worker/include/RTC/BWE/{Utils.hpp → BitrateUtils.hpp} +3 -3
- package/worker/include/RTC/BWE/BweTypes.hpp +170 -2
- package/worker/include/RTC/BWE/FeedbackAdapter.hpp +0 -14
- package/worker/include/RTC/BWE/InterArrival.hpp +117 -0
- package/worker/include/RTC/BWE/IntervalBudget.hpp +81 -0
- package/worker/include/RTC/BWE/LossBasedController.hpp +105 -0
- package/worker/include/RTC/BWE/OveruseDetector.hpp +71 -0
- package/worker/include/RTC/BWE/OveruseEstimator.hpp +115 -0
- package/worker/include/RTC/BWE/ProbeBitrateEstimator.hpp +84 -0
- package/worker/include/RTC/BWE/ProbeController.hpp +379 -0
- package/worker/include/RTC/BWE/ProbePacketGenerator.hpp +130 -0
- package/worker/include/RTC/BWE/ProbingScheduler.hpp +187 -0
- package/worker/include/RTC/BWE/RembGenerator.hpp +96 -0
- package/worker/include/RTC/BWE/RemoteBitrateEstimatorAbsSendTime.hpp +237 -0
- package/worker/include/RTC/BWE/RobustThroughputEstimator.hpp +26 -0
- package/worker/include/RTC/BWE/SendPacketHistory.hpp +161 -25
- package/worker/include/RTC/BWE/TransportWideCcFeedbackGenerator.hpp +146 -0
- package/worker/include/RTC/BWE/TrendlineEstimator.hpp +15 -0
- package/worker/include/RTC/Consts.hpp +70 -0
- package/worker/include/RTC/DataConsumer.hpp +3 -5
- package/worker/include/RTC/DirectTransport.hpp +4 -5
- package/worker/include/RTC/PipeTransport.hpp +4 -5
- package/worker/include/RTC/PlainTransport.hpp +4 -5
- package/worker/include/RTC/RTCP/FeedbackPsRemb.hpp +6 -7
- package/worker/include/RTC/RTCP/FeedbackRtpTransport.hpp +3 -1
- package/worker/include/RTC/RTP/Codecs/Tools.hpp +1 -1
- package/worker/include/RTC/RTP/HeaderExtensionIds.hpp +0 -1
- package/worker/include/RTC/RTP/Packet.hpp +16 -4
- package/worker/include/RTC/RTP/ProbationGenerator.hpp +0 -8
- package/worker/include/RTC/RTP/RtpStream.hpp +12 -9
- package/worker/include/RTC/RTP/RtpStreamRecv.hpp +22 -4
- package/worker/include/RTC/RTP/RtpStreamSend.hpp +4 -2
- package/worker/include/RTC/RTP/RtxStream.hpp +10 -4
- package/worker/include/RTC/RateCalculator.hpp +103 -24
- package/worker/include/RTC/RemoteCaptureTimeEstimator.hpp +33 -3
- package/worker/include/RTC/{RtcLogger.hpp → RtcLogger/RtpPacket.hpp} +5 -3
- package/worker/include/RTC/RtcLogger/SendBurst.hpp +88 -0
- package/worker/include/RTC/RtpDictionaries.hpp +3 -4
- package/worker/include/RTC/SCTP/association/Association.hpp +1 -1
- package/worker/include/RTC/SCTP/public/AssociationMetrics.hpp +0 -1
- package/worker/include/RTC/SCTP/public/SctpTypes.hpp +4 -4
- package/worker/include/RTC/SCTP/rx/DataTracker.hpp +1 -1
- package/worker/include/RTC/SCTP/rx/ReassemblyQueue.hpp +1 -1
- package/worker/include/RTC/SctpDictionaries.hpp +2 -2
- package/worker/include/RTC/TcpConnection.hpp +2 -1
- package/worker/include/RTC/Transport.hpp +23 -8
- package/worker/include/RTC/TransportTuple.hpp +61 -6
- package/worker/include/RTC/WebRtcTransport.hpp +4 -5
- package/worker/include/Shared.hpp +5 -0
- package/worker/include/SharedInterface.hpp +10 -0
- package/worker/include/Utils.hpp +72 -3
- package/worker/include/common.hpp +12 -4
- package/worker/include/handles/SendCallbacks.hpp +34 -0
- package/worker/include/handles/TcpConnectionHandle.hpp +4 -12
- package/worker/include/handles/UdpSocketHandle.hpp +4 -8
- package/worker/meson.build +41 -3
- package/worker/meson_options.txt +1 -0
- package/worker/mocks/include/MockShared.hpp +16 -2
- package/worker/mocks/include/handles/MockBackoffTimerHandle.hpp +1 -1
- package/worker/scripts/package-lock.json +6 -6
- package/worker/src/RTC/BWE/AimdRateControl.cpp +4 -5
- package/worker/src/RTC/BWE/AlrDetector.cpp +80 -0
- package/worker/src/RTC/BWE/BitrateProber.cpp +256 -0
- package/worker/src/RTC/BWE/{Utils.cpp → BitrateUtils.cpp} +4 -4
- package/worker/src/RTC/BWE/DelayBasedBwe.cpp +2 -2
- package/worker/src/RTC/BWE/FeedbackAdapter.cpp +20 -37
- package/worker/src/RTC/BWE/InterArrival.cpp +216 -0
- package/worker/src/RTC/BWE/IntervalBudget.cpp +93 -0
- package/worker/src/RTC/BWE/LossBasedController.cpp +189 -41
- package/worker/src/RTC/BWE/OveruseDetector.cpp +128 -0
- package/worker/src/RTC/BWE/OveruseEstimator.cpp +166 -0
- package/worker/src/RTC/BWE/ProbeBitrateEstimator.cpp +222 -0
- package/worker/src/RTC/BWE/ProbeController.cpp +645 -0
- package/worker/src/RTC/BWE/ProbePacketGenerator.cpp +140 -0
- package/worker/src/RTC/BWE/ProbingScheduler.cpp +196 -0
- package/worker/src/RTC/BWE/RembGenerator.cpp +169 -0
- package/worker/src/RTC/BWE/RemoteBitrateEstimatorAbsSendTime.cpp +497 -0
- package/worker/src/RTC/BWE/RobustThroughputEstimator.cpp +47 -0
- package/worker/src/RTC/BWE/SendPacketHistory.cpp +173 -50
- package/worker/src/RTC/BWE/TargetRateController.cpp +12 -14
- package/worker/src/RTC/BWE/TransportWideCcFeedbackGenerator.cpp +377 -0
- package/worker/src/RTC/BWE/TrendlineEstimator.cpp +19 -0
- package/worker/src/RTC/Consumer.cpp +7 -5
- package/worker/src/RTC/DataConsumer.cpp +8 -10
- package/worker/src/RTC/DirectTransport.cpp +14 -8
- package/worker/src/RTC/DtlsTransport.cpp +8 -8
- package/worker/src/RTC/ICE/IceCandidate.cpp +4 -4
- package/worker/src/RTC/ICE/IceServer.cpp +1 -1
- package/worker/src/RTC/PipeTransport.cpp +13 -8
- package/worker/src/RTC/PlainTransport.cpp +13 -8
- package/worker/src/RTC/Producer.cpp +14 -31
- package/worker/src/RTC/RTCP/Bye.cpp +1 -1
- package/worker/src/RTC/RTCP/FeedbackPsRemb.cpp +18 -0
- package/worker/src/RTC/RTCP/FeedbackPsRpsi.cpp +2 -2
- package/worker/src/RTC/RTCP/FeedbackPsVbcm.cpp +2 -1
- package/worker/src/RTC/RTCP/FeedbackRtpTransport.cpp +2 -2
- package/worker/src/RTC/RTCP/Sdes.cpp +1 -1
- package/worker/src/RTC/RTP/Codecs/DependencyDescriptor.cpp +2 -1
- package/worker/src/RTC/RTP/Packet.cpp +26 -11
- package/worker/src/RTC/RTP/ProbationGenerator.cpp +5 -6
- package/worker/src/RTC/RTP/RtpStream.cpp +1 -1
- package/worker/src/RTC/RTP/RtpStreamRecv.cpp +69 -48
- package/worker/src/RTC/RTP/RtpStreamSend.cpp +31 -31
- package/worker/src/RTC/RTP/RtxStream.cpp +22 -7
- package/worker/src/RTC/RateCalculator.cpp +133 -28
- package/worker/src/RTC/RemoteCaptureTimeEstimator.cpp +56 -1
- package/worker/src/RTC/{RtcLogger.cpp → RtcLogger/RtpPacket.cpp} +2 -2
- package/worker/src/RTC/RtcLogger/SendBurst.cpp +124 -0
- package/worker/src/RTC/RtpDictionaries/RtpHeaderExtensionUri.cpp +2 -12
- package/worker/src/RTC/RtpDictionaries/RtpParameters.cpp +1 -1
- package/worker/src/RTC/SCTP/association/Association.cpp +1 -1
- package/worker/src/RTC/SCTP/rx/InterleavedReassemblyStreams.cpp +3 -3
- package/worker/src/RTC/SCTP/rx/ReassemblyQueue.cpp +2 -1
- package/worker/src/RTC/SCTP/rx/TraditionalReassemblyStreams.cpp +4 -4
- package/worker/src/RTC/SCTP/tx/RetransmissionTimeout.cpp +4 -4
- package/worker/src/RTC/SctpDictionaries/SctpStreamParameters.cpp +6 -10
- package/worker/src/RTC/SimulcastProducerStreamManager.cpp +2 -2
- package/worker/src/RTC/SrtpSession.cpp +2 -2
- package/worker/src/RTC/SvcProducerStreamManager.cpp +2 -2
- package/worker/src/RTC/TcpConnection.cpp +2 -2
- package/worker/src/RTC/Transport.cpp +111 -93
- package/worker/src/RTC/TransportTuple.cpp +4 -4
- package/worker/src/RTC/WebRtcServer.cpp +4 -3
- package/worker/src/RTC/WebRtcTransport.cpp +20 -13
- package/worker/src/Utils/BitStream.cpp +24 -0
- package/worker/src/handles/BackoffTimerHandle.cpp +1 -1
- package/worker/src/handles/TcpConnectionHandle.cpp +13 -23
- package/worker/src/handles/UdpSocketHandle.cpp +14 -21
- package/worker/test/include/RTC/BWE/helpers/LinkSimulator.hpp +68 -14
- package/worker/test/include/RTC/BWE/helpers/RemoteBitrateEstimatorAbsSendTimeTestHelper.hpp +125 -0
- package/worker/test/src/RTC/BWE/TestAlrDetector.cpp +110 -0
- package/worker/test/src/RTC/BWE/TestBitrateProber.cpp +418 -0
- package/worker/test/src/RTC/BWE/TestBitrateUtils.cpp +61 -0
- package/worker/test/src/RTC/BWE/TestDelayBasedBwe.cpp +4 -4
- package/worker/test/src/RTC/BWE/TestFeedbackAdapter.cpp +53 -37
- package/worker/test/src/RTC/BWE/TestInterArrival.cpp +643 -0
- package/worker/test/src/RTC/BWE/TestIntervalBudget.cpp +130 -0
- package/worker/test/src/RTC/BWE/TestOveruseDetector.cpp +519 -0
- package/worker/test/src/RTC/BWE/TestProbeBitrateEstimator.cpp +266 -0
- package/worker/test/src/RTC/BWE/TestProbeController.cpp +1682 -0
- package/worker/test/src/RTC/BWE/TestProbePacketGenerator.cpp +265 -0
- package/worker/test/src/RTC/BWE/TestProbingScheduler.cpp +260 -0
- package/worker/test/src/RTC/BWE/TestRembGenerator.cpp +285 -0
- package/worker/test/src/RTC/BWE/TestRemoteBitrateEstimatorAbsSendTime.cpp +414 -0
- package/worker/test/src/RTC/BWE/TestSendPacketHistory.cpp +296 -77
- package/worker/test/src/RTC/BWE/TestTransportWideCcFeedbackGenerator.cpp +578 -0
- package/worker/test/src/RTC/BWE/helpers/LinkSimulator.cpp +133 -29
- package/worker/test/src/RTC/BWE/helpers/RemoteBitrateEstimatorAbsSendTimeTestHelper.cpp +625 -0
- package/worker/test/src/RTC/RTCP/TestFeedbackPsRemb.cpp +19 -0
- package/worker/test/src/RTC/RTP/TestPacket.cpp +58 -4
- package/worker/test/src/RTC/RTP/TestProbationGenerator.cpp +3 -2
- package/worker/test/src/RTC/RTP/TestRtpStreamRecv.cpp +50 -0
- package/worker/test/src/RTC/RTP/TestRtpStreamSend.cpp +59 -0
- package/worker/test/src/RTC/TestRateCalculator.cpp +322 -60
- package/worker/test/src/RTC/TestRemoteCaptureTimeEstimator.cpp +95 -7
- package/worker/test/src/RTC/TestSimpleProducerStreamManager.cpp +34 -16
- package/worker/test/src/RTC/TestSimulcastProducerStreamManager.cpp +31 -13
- package/worker/test/src/RTC/TestSvcProducerStreamManager.cpp +37 -19
- package/worker/test/src/RTC/TestTransportCongestionControlServer.cpp +10 -10
- package/worker/test/src/Utils/TestTime.cpp +120 -21
- package/worker/test/src/RTC/BWE/TestUtils.cpp +0 -61
|
@@ -0,0 +1,1682 @@
|
|
|
1
|
+
#include "common.hpp"
|
|
2
|
+
#include "RTC/BWE/ProbeController.hpp"
|
|
3
|
+
#include <catch2/catch_test_macros.hpp>
|
|
4
|
+
|
|
5
|
+
SCENARIO("BWE ProbeController", "[bwe][probecontroller]")
|
|
6
|
+
{
|
|
7
|
+
// The clock starts well away from zero so that a mistake taking a time for a
|
|
8
|
+
// duration doesn't go unnoticed.
|
|
9
|
+
constexpr int64_t InitialTimeUs{ 100000000 };
|
|
10
|
+
constexpr int64_t MinBitrate{ 100 };
|
|
11
|
+
constexpr int64_t StartBitrate{ 300 };
|
|
12
|
+
constexpr int64_t MaxBitrate{ 10000 };
|
|
13
|
+
// Long enough for the climbing that follows the first burst to give up.
|
|
14
|
+
constexpr int64_t ExponentialProbingTimeoutUs{ 5 * 1000 * 1000 };
|
|
15
|
+
|
|
16
|
+
int64_t nowUs{ InitialTimeUs };
|
|
17
|
+
|
|
18
|
+
SECTION("the first bursts go out once there is a bitrate to start from")
|
|
19
|
+
{
|
|
20
|
+
RTC::BWE::ProbeController probeController;
|
|
21
|
+
|
|
22
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs).empty());
|
|
23
|
+
|
|
24
|
+
const auto probes = probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate, nowUs);
|
|
25
|
+
|
|
26
|
+
REQUIRE(probes.size() >= 2);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
SECTION("and they wait for the network if it isn't there yet")
|
|
30
|
+
{
|
|
31
|
+
RTC::BWE::ProbeController probeController;
|
|
32
|
+
|
|
33
|
+
REQUIRE(probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate, nowUs).empty());
|
|
34
|
+
|
|
35
|
+
const auto probes = probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs);
|
|
36
|
+
|
|
37
|
+
REQUIRE(probes.size() >= 2);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
SECTION("a burst lasts and carries what the options say")
|
|
41
|
+
{
|
|
42
|
+
RTC::BWE::ProbeController probeController;
|
|
43
|
+
|
|
44
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs).empty());
|
|
45
|
+
|
|
46
|
+
const auto probes = probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate, nowUs);
|
|
47
|
+
|
|
48
|
+
REQUIRE(probes.size() >= 2);
|
|
49
|
+
REQUIRE(probes[0].targetDurationUs == 15 * 1000);
|
|
50
|
+
REQUIRE(probes[0].targetProbeCount == 5);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
SECTION("and both can be configured")
|
|
54
|
+
{
|
|
55
|
+
const RTC::BWE::ProbeController::ProbeControllerOptions options{ .minProbePacketsSent = 2,
|
|
56
|
+
.minProbeDurationUs =
|
|
57
|
+
123 * 1000 };
|
|
58
|
+
|
|
59
|
+
RTC::BWE::ProbeController probeController(options);
|
|
60
|
+
|
|
61
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs).empty());
|
|
62
|
+
|
|
63
|
+
const auto probes = probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate, nowUs);
|
|
64
|
+
|
|
65
|
+
REQUIRE(probes.size() >= 2);
|
|
66
|
+
REQUIRE(probes[0].targetDurationUs == 123 * 1000);
|
|
67
|
+
REQUIRE(probes[0].targetProbeCount == 2);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
SECTION("nothing is probed while the network is down")
|
|
71
|
+
{
|
|
72
|
+
RTC::BWE::ProbeController probeController;
|
|
73
|
+
|
|
74
|
+
auto probes = probeController.OnNetworkAvailability(/*networkAvailable*/ false, nowUs);
|
|
75
|
+
|
|
76
|
+
probes = probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate, nowUs);
|
|
77
|
+
|
|
78
|
+
REQUIRE(probes.empty());
|
|
79
|
+
|
|
80
|
+
probes = probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs);
|
|
81
|
+
|
|
82
|
+
REQUIRE(probes.size() >= 2);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
SECTION("the factors of the first bursts can be configured")
|
|
86
|
+
{
|
|
87
|
+
const RTC::BWE::ProbeController::ProbeControllerOptions options{
|
|
88
|
+
.firstExponentialProbeScale = 2.0, .secondExponentialProbeScale = 3.0
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
RTC::BWE::ProbeController probeController(options);
|
|
92
|
+
|
|
93
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs).empty());
|
|
94
|
+
|
|
95
|
+
const auto probes = probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate, nowUs);
|
|
96
|
+
|
|
97
|
+
REQUIRE(probes.size() == 2);
|
|
98
|
+
REQUIRE(probes[0].targetBitrate == StartBitrate * 2);
|
|
99
|
+
REQUIRE(probes[1].targetBitrate == StartBitrate * 3);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
SECTION("and a factor of zero leaves just the first one")
|
|
103
|
+
{
|
|
104
|
+
const RTC::BWE::ProbeController::ProbeControllerOptions options{
|
|
105
|
+
.firstExponentialProbeScale = 2.0, .secondExponentialProbeScale = 0.0
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
RTC::BWE::ProbeController probeController(options);
|
|
109
|
+
|
|
110
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs).empty());
|
|
111
|
+
|
|
112
|
+
const auto probes = probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate, nowUs);
|
|
113
|
+
|
|
114
|
+
REQUIRE(probes.size() == 1);
|
|
115
|
+
REQUIRE(probes[0].targetBitrate == StartBitrate * 2);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
SECTION("raising the maximum is room that hasn't been looked for yet")
|
|
119
|
+
{
|
|
120
|
+
RTC::BWE::ProbeController probeController;
|
|
121
|
+
|
|
122
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs).empty());
|
|
123
|
+
|
|
124
|
+
auto probes = probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate, nowUs);
|
|
125
|
+
|
|
126
|
+
nowUs += ExponentialProbingTimeoutUs;
|
|
127
|
+
|
|
128
|
+
probes = probeController.SetEstimatedBitrate(
|
|
129
|
+
StartBitrate, RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED, nowUs);
|
|
130
|
+
probes = probeController.Process(nowUs);
|
|
131
|
+
probes = probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate + 100, nowUs);
|
|
132
|
+
|
|
133
|
+
REQUIRE(probes.size() == 1);
|
|
134
|
+
REQUIRE(probes[0].targetBitrate == MaxBitrate + 100);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
SECTION("asking for more is probed while not filling the link even when told not to otherwise")
|
|
138
|
+
{
|
|
139
|
+
const RTC::BWE::ProbeController::ProbeControllerOptions options{
|
|
140
|
+
.probeOnMaxAllocatedBitrateChangeWithoutAlr = false
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
RTC::BWE::ProbeController probeController(options);
|
|
144
|
+
|
|
145
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs).empty());
|
|
146
|
+
|
|
147
|
+
auto probes = probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate, nowUs);
|
|
148
|
+
|
|
149
|
+
probes = probeController.SetEstimatedBitrate(
|
|
150
|
+
MaxBitrate - 1, RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED, nowUs);
|
|
151
|
+
|
|
152
|
+
nowUs += ExponentialProbingTimeoutUs;
|
|
153
|
+
|
|
154
|
+
probes = probeController.Process(nowUs);
|
|
155
|
+
|
|
156
|
+
REQUIRE(probes.empty());
|
|
157
|
+
|
|
158
|
+
probeController.SetAlrStartTimeUs(nowUs);
|
|
159
|
+
|
|
160
|
+
probes = probeController.OnMaxTotalAllocatedBitrate(MaxBitrate + 1, nowUs);
|
|
161
|
+
|
|
162
|
+
REQUIRE(probes.size() == 2);
|
|
163
|
+
REQUIRE(probes.at(0).targetBitrate == MaxBitrate);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
SECTION("and while filling it too, by default")
|
|
167
|
+
{
|
|
168
|
+
constexpr int64_t TransportMaxBitrate{ 10000000 };
|
|
169
|
+
constexpr int64_t EstimatedAfterInitialProbing{ 300000 };
|
|
170
|
+
constexpr int64_t ScreenShareMaxBitrate{ 3500000 };
|
|
171
|
+
|
|
172
|
+
RTC::BWE::ProbeController probeController;
|
|
173
|
+
|
|
174
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs).empty());
|
|
175
|
+
|
|
176
|
+
auto probes = probeController.SetBitrates(MinBitrate, StartBitrate, TransportMaxBitrate, nowUs);
|
|
177
|
+
|
|
178
|
+
probes = probeController.SetEstimatedBitrate(
|
|
179
|
+
EstimatedAfterInitialProbing,
|
|
180
|
+
RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED,
|
|
181
|
+
nowUs);
|
|
182
|
+
|
|
183
|
+
nowUs += ExponentialProbingTimeoutUs;
|
|
184
|
+
|
|
185
|
+
probes = probeController.Process(nowUs);
|
|
186
|
+
|
|
187
|
+
REQUIRE(probes.empty());
|
|
188
|
+
|
|
189
|
+
probeController.SetAlrStartTimeUs(std::nullopt);
|
|
190
|
+
|
|
191
|
+
probes = probeController.OnMaxTotalAllocatedBitrate(ScreenShareMaxBitrate, nowUs);
|
|
192
|
+
|
|
193
|
+
REQUIRE(probes.size() == 1);
|
|
194
|
+
REQUIRE(probes.at(0).targetBitrate == 2 * EstimatedAfterInitialProbing);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
SECTION("unless it is told not to")
|
|
198
|
+
{
|
|
199
|
+
constexpr int64_t TransportMaxBitrate{ 10000000 };
|
|
200
|
+
constexpr int64_t EstimatedAfterInitialProbing{ 300000 };
|
|
201
|
+
constexpr int64_t ScreenShareMaxBitrate{ 3500000 };
|
|
202
|
+
|
|
203
|
+
const RTC::BWE::ProbeController::ProbeControllerOptions options{
|
|
204
|
+
.probeOnMaxAllocatedBitrateChangeWithoutAlr = false
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
RTC::BWE::ProbeController probeController(options);
|
|
208
|
+
|
|
209
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs).empty());
|
|
210
|
+
|
|
211
|
+
auto probes = probeController.SetBitrates(MinBitrate, StartBitrate, TransportMaxBitrate, nowUs);
|
|
212
|
+
|
|
213
|
+
probes = probeController.SetEstimatedBitrate(
|
|
214
|
+
EstimatedAfterInitialProbing,
|
|
215
|
+
RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED,
|
|
216
|
+
nowUs);
|
|
217
|
+
|
|
218
|
+
nowUs += ExponentialProbingTimeoutUs;
|
|
219
|
+
|
|
220
|
+
probes = probeController.Process(nowUs);
|
|
221
|
+
|
|
222
|
+
REQUIRE(probes.empty());
|
|
223
|
+
|
|
224
|
+
probeController.SetAlrStartTimeUs(std::nullopt);
|
|
225
|
+
|
|
226
|
+
REQUIRE(probeController.OnMaxTotalAllocatedBitrate(ScreenShareMaxBitrate, nowUs).empty());
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
SECTION("asking for less is not probed, but asking for more again is")
|
|
230
|
+
{
|
|
231
|
+
RTC::BWE::ProbeController probeController;
|
|
232
|
+
|
|
233
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs).empty());
|
|
234
|
+
|
|
235
|
+
auto probes = probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate, nowUs);
|
|
236
|
+
|
|
237
|
+
REQUIRE(!probes.empty());
|
|
238
|
+
|
|
239
|
+
// The first allocation arrives while the initial bursts are still going.
|
|
240
|
+
REQUIRE(probeController.OnMaxTotalAllocatedBitrate(MaxBitrate, nowUs).empty());
|
|
241
|
+
|
|
242
|
+
probes = probeController.SetEstimatedBitrate(
|
|
243
|
+
StartBitrate, RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED, nowUs);
|
|
244
|
+
|
|
245
|
+
nowUs += ExponentialProbingTimeoutUs;
|
|
246
|
+
|
|
247
|
+
REQUIRE(probeController.Process(nowUs).empty());
|
|
248
|
+
|
|
249
|
+
// Asking for less moves the limit without looking for anything.
|
|
250
|
+
REQUIRE(probeController.OnMaxTotalAllocatedBitrate(MaxBitrate / 2, nowUs).empty());
|
|
251
|
+
|
|
252
|
+
probes = probeController.OnMaxTotalAllocatedBitrate(MaxBitrate * 3 / 4, nowUs);
|
|
253
|
+
|
|
254
|
+
REQUIRE(!probes.empty());
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
SECTION("what is asked for is bounded by the current estimate")
|
|
258
|
+
{
|
|
259
|
+
RTC::BWE::ProbeController probeController;
|
|
260
|
+
|
|
261
|
+
REQUIRE(MaxBitrate > 1.5 * StartBitrate);
|
|
262
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs).empty());
|
|
263
|
+
|
|
264
|
+
auto probes = probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate, nowUs);
|
|
265
|
+
|
|
266
|
+
probes = probeController.SetEstimatedBitrate(
|
|
267
|
+
StartBitrate, RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED, nowUs);
|
|
268
|
+
|
|
269
|
+
nowUs += ExponentialProbingTimeoutUs;
|
|
270
|
+
|
|
271
|
+
probes = probeController.Process(nowUs);
|
|
272
|
+
|
|
273
|
+
REQUIRE(probes.empty());
|
|
274
|
+
|
|
275
|
+
probeController.SetAlrStartTimeUs(nowUs);
|
|
276
|
+
|
|
277
|
+
probes = probeController.OnMaxTotalAllocatedBitrate(MaxBitrate, nowUs);
|
|
278
|
+
|
|
279
|
+
REQUIRE(probes.size() == 1);
|
|
280
|
+
REQUIRE(probes.at(0).targetBitrate == 2 * StartBitrate);
|
|
281
|
+
|
|
282
|
+
// A burst that worked out leads to another one.
|
|
283
|
+
probes = probeController.SetEstimatedBitrate(
|
|
284
|
+
(3 * StartBitrate) / 2,
|
|
285
|
+
RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED,
|
|
286
|
+
nowUs);
|
|
287
|
+
|
|
288
|
+
REQUIRE(probes.size() == 1);
|
|
289
|
+
REQUIRE(probes.at(0).targetBitrate > (3 * StartBitrate) / 2);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
SECTION("probing what is asked for can be turned off")
|
|
293
|
+
{
|
|
294
|
+
const RTC::BWE::ProbeController::ProbeControllerOptions options{
|
|
295
|
+
.probeOnMaxAllocatedBitrateChange = false
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
RTC::BWE::ProbeController probeController(options);
|
|
299
|
+
|
|
300
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs).empty());
|
|
301
|
+
|
|
302
|
+
auto probes = probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate, nowUs);
|
|
303
|
+
|
|
304
|
+
probes = probeController.SetEstimatedBitrate(
|
|
305
|
+
MaxBitrate - 1, RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED, nowUs);
|
|
306
|
+
|
|
307
|
+
nowUs += ExponentialProbingTimeoutUs;
|
|
308
|
+
|
|
309
|
+
probes = probeController.Process(nowUs);
|
|
310
|
+
|
|
311
|
+
REQUIRE(probes.empty());
|
|
312
|
+
|
|
313
|
+
probeController.SetAlrStartTimeUs(nowUs);
|
|
314
|
+
|
|
315
|
+
probes = probeController.OnMaxTotalAllocatedBitrate(MaxBitrate + 1, nowUs);
|
|
316
|
+
|
|
317
|
+
REQUIRE(probes.empty());
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
SECTION("raising the maximum is probed even while sitting at the previous one")
|
|
321
|
+
{
|
|
322
|
+
RTC::BWE::ProbeController probeController;
|
|
323
|
+
|
|
324
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs).empty());
|
|
325
|
+
|
|
326
|
+
auto probes = probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate, nowUs);
|
|
327
|
+
|
|
328
|
+
nowUs += ExponentialProbingTimeoutUs;
|
|
329
|
+
|
|
330
|
+
probes = probeController.SetEstimatedBitrate(
|
|
331
|
+
StartBitrate, RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED, nowUs);
|
|
332
|
+
probes = probeController.Process(nowUs);
|
|
333
|
+
probes = probeController.SetEstimatedBitrate(
|
|
334
|
+
MaxBitrate, RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED, nowUs);
|
|
335
|
+
probes = probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate + 100, nowUs);
|
|
336
|
+
|
|
337
|
+
REQUIRE(probes.size() == 1);
|
|
338
|
+
REQUIRE(probes[0].targetBitrate == MaxBitrate + 100);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
SECTION("each burst leads to the next one only once its result is good enough")
|
|
342
|
+
{
|
|
343
|
+
RTC::BWE::ProbeController probeController;
|
|
344
|
+
|
|
345
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs).empty());
|
|
346
|
+
|
|
347
|
+
auto probes = probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate, nowUs);
|
|
348
|
+
|
|
349
|
+
// Another one only follows once the estimate climbs above 0.7 of what the
|
|
350
|
+
// last one aimed for, which is 0.7 * 6 * 300.
|
|
351
|
+
probes = probeController.SetEstimatedBitrate(
|
|
352
|
+
1000, RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED, nowUs);
|
|
353
|
+
|
|
354
|
+
REQUIRE(probes.empty());
|
|
355
|
+
|
|
356
|
+
probes = probeController.SetEstimatedBitrate(
|
|
357
|
+
1800, RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED, nowUs);
|
|
358
|
+
|
|
359
|
+
REQUIRE(probes.size() == 1);
|
|
360
|
+
REQUIRE(probes[0].targetBitrate == 2 * 1800);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
SECTION("and stops climbing once the maximum is already reached")
|
|
364
|
+
{
|
|
365
|
+
const RTC::BWE::ProbeController::ProbeControllerOptions options{
|
|
366
|
+
.abortFurtherProbeIfMaxLowerThanCurrent = true
|
|
367
|
+
};
|
|
368
|
+
|
|
369
|
+
RTC::BWE::ProbeController probeController(options);
|
|
370
|
+
|
|
371
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs).empty());
|
|
372
|
+
|
|
373
|
+
auto probes = probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate, nowUs);
|
|
374
|
+
|
|
375
|
+
REQUIRE(!probes.empty());
|
|
376
|
+
|
|
377
|
+
probes = probeController.SetBitrates(MinBitrate, StartBitrate, StartBitrate, nowUs);
|
|
378
|
+
|
|
379
|
+
REQUIRE(probes.empty());
|
|
380
|
+
|
|
381
|
+
probes = probeController.SetEstimatedBitrate(
|
|
382
|
+
1800, RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED, nowUs);
|
|
383
|
+
|
|
384
|
+
REQUIRE(probes.empty());
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
SECTION("or once what is asked for is already reached")
|
|
388
|
+
{
|
|
389
|
+
const RTC::BWE::ProbeController::ProbeControllerOptions options{
|
|
390
|
+
.abortFurtherProbeIfMaxLowerThanCurrent = true
|
|
391
|
+
};
|
|
392
|
+
|
|
393
|
+
RTC::BWE::ProbeController probeController(options);
|
|
394
|
+
|
|
395
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs).empty());
|
|
396
|
+
|
|
397
|
+
auto probes = probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate, nowUs);
|
|
398
|
+
|
|
399
|
+
REQUIRE(!probes.empty());
|
|
400
|
+
|
|
401
|
+
probes = probeController.OnMaxTotalAllocatedBitrate(StartBitrate, nowUs);
|
|
402
|
+
|
|
403
|
+
REQUIRE(probes.empty());
|
|
404
|
+
|
|
405
|
+
probes = probeController.SetEstimatedBitrate(
|
|
406
|
+
1800, RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED, nowUs);
|
|
407
|
+
|
|
408
|
+
REQUIRE(probes.empty());
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
SECTION("without that option the next burst aims at twice what is asked for")
|
|
412
|
+
{
|
|
413
|
+
RTC::BWE::ProbeController probeController;
|
|
414
|
+
|
|
415
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs).empty());
|
|
416
|
+
|
|
417
|
+
auto probes = probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate, nowUs);
|
|
418
|
+
|
|
419
|
+
REQUIRE(!probes.empty());
|
|
420
|
+
|
|
421
|
+
probes = probeController.OnMaxTotalAllocatedBitrate(StartBitrate, nowUs);
|
|
422
|
+
|
|
423
|
+
REQUIRE(probes.empty());
|
|
424
|
+
|
|
425
|
+
probes = probeController.SetEstimatedBitrate(
|
|
426
|
+
1800, RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED, nowUs);
|
|
427
|
+
|
|
428
|
+
REQUIRE(probes.size() == 1);
|
|
429
|
+
REQUIRE(probes[0].targetBitrate == 2 * StartBitrate);
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
SECTION("a burst whose result never arrives is given up on")
|
|
433
|
+
{
|
|
434
|
+
RTC::BWE::ProbeController probeController;
|
|
435
|
+
|
|
436
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs).empty());
|
|
437
|
+
|
|
438
|
+
auto probes = probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate, nowUs);
|
|
439
|
+
|
|
440
|
+
REQUIRE(!probes.empty());
|
|
441
|
+
|
|
442
|
+
nowUs += ExponentialProbingTimeoutUs;
|
|
443
|
+
|
|
444
|
+
probes = probeController.Process(nowUs);
|
|
445
|
+
|
|
446
|
+
REQUIRE(probes.empty());
|
|
447
|
+
|
|
448
|
+
probes = probeController.SetEstimatedBitrate(
|
|
449
|
+
1800, RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED, nowUs);
|
|
450
|
+
|
|
451
|
+
REQUIRE(probes.empty());
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
SECTION("the initial bursts are repeated for a while when told to")
|
|
455
|
+
{
|
|
456
|
+
RTC::BWE::ProbeController probeController;
|
|
457
|
+
|
|
458
|
+
probeController.EnableRepeatedInitialProbing(true);
|
|
459
|
+
|
|
460
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs).empty());
|
|
461
|
+
|
|
462
|
+
auto probes = probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate, nowUs);
|
|
463
|
+
|
|
464
|
+
REQUIRE(!probes.empty());
|
|
465
|
+
|
|
466
|
+
const int64_t startTimeUs = nowUs;
|
|
467
|
+
int64_t lastProbeAtUs = nowUs;
|
|
468
|
+
|
|
469
|
+
while (nowUs < startTimeUs + (5 * 1000 * 1000))
|
|
470
|
+
{
|
|
471
|
+
nowUs += 100 * 1000;
|
|
472
|
+
|
|
473
|
+
probes = probeController.Process(nowUs);
|
|
474
|
+
|
|
475
|
+
if (!probes.empty())
|
|
476
|
+
{
|
|
477
|
+
// One every second, noticed at the granularity this is asked at.
|
|
478
|
+
REQUIRE(nowUs - lastProbeAtUs == 1100 * 1000);
|
|
479
|
+
REQUIRE(probes[0].minProbeDeltaUs == 20 * 1000);
|
|
480
|
+
REQUIRE(probes[0].targetDurationUs == 100 * 1000);
|
|
481
|
+
|
|
482
|
+
lastProbeAtUs = nowUs;
|
|
483
|
+
}
|
|
484
|
+
else
|
|
485
|
+
{
|
|
486
|
+
REQUIRE(nowUs - lastProbeAtUs < 1100 * 1000);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
nowUs += 1000 * 1000;
|
|
491
|
+
|
|
492
|
+
REQUIRE(probeController.Process(nowUs).empty());
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
SECTION("and stop as soon as there is traffic of its own to measure")
|
|
496
|
+
{
|
|
497
|
+
RTC::BWE::ProbeController probeController;
|
|
498
|
+
|
|
499
|
+
probeController.EnableRepeatedInitialProbing(true);
|
|
500
|
+
|
|
501
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs).empty());
|
|
502
|
+
|
|
503
|
+
auto probes = probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate, nowUs);
|
|
504
|
+
|
|
505
|
+
REQUIRE(!probes.empty());
|
|
506
|
+
|
|
507
|
+
nowUs += 1100 * 1000;
|
|
508
|
+
|
|
509
|
+
probes = probeController.Process(nowUs);
|
|
510
|
+
|
|
511
|
+
REQUIRE(probes.size() == 1);
|
|
512
|
+
|
|
513
|
+
probes = probeController.OnMaxTotalAllocatedBitrate(MinBitrate, nowUs);
|
|
514
|
+
|
|
515
|
+
nowUs += 1100 * 1000;
|
|
516
|
+
|
|
517
|
+
probes = probeController.Process(nowUs);
|
|
518
|
+
|
|
519
|
+
REQUIRE(probes.empty());
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
SECTION("a large drop is checked with one burst while not filling the link")
|
|
523
|
+
{
|
|
524
|
+
RTC::BWE::ProbeController probeController;
|
|
525
|
+
|
|
526
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs).empty());
|
|
527
|
+
|
|
528
|
+
auto probes = probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate, nowUs);
|
|
529
|
+
|
|
530
|
+
REQUIRE(probes.size() >= 2);
|
|
531
|
+
|
|
532
|
+
probes = probeController.SetEstimatedBitrate(
|
|
533
|
+
500, RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED, nowUs);
|
|
534
|
+
|
|
535
|
+
probeController.SetAlrStartTimeUs(nowUs);
|
|
536
|
+
|
|
537
|
+
nowUs += (5 * 1000 * 1000) + 1000;
|
|
538
|
+
|
|
539
|
+
probes = probeController.Process(nowUs);
|
|
540
|
+
probes = probeController.SetEstimatedBitrate(
|
|
541
|
+
250, RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED, nowUs);
|
|
542
|
+
probes = probeController.RequestProbe(nowUs);
|
|
543
|
+
|
|
544
|
+
// 0.85 of what the estimate was worth before the drop.
|
|
545
|
+
REQUIRE(probes.size() == 1);
|
|
546
|
+
REQUIRE(probes[0].targetBitrate == 425);
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
SECTION("and also just after it starts filling it again")
|
|
550
|
+
{
|
|
551
|
+
RTC::BWE::ProbeController probeController;
|
|
552
|
+
|
|
553
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs).empty());
|
|
554
|
+
|
|
555
|
+
auto probes = probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate, nowUs);
|
|
556
|
+
|
|
557
|
+
REQUIRE(probes.size() == 2);
|
|
558
|
+
|
|
559
|
+
probes = probeController.SetEstimatedBitrate(
|
|
560
|
+
500, RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED, nowUs);
|
|
561
|
+
|
|
562
|
+
probeController.SetAlrStartTimeUs(std::nullopt);
|
|
563
|
+
|
|
564
|
+
nowUs += (5 * 1000 * 1000) + 1000;
|
|
565
|
+
|
|
566
|
+
probes = probeController.Process(nowUs);
|
|
567
|
+
probes = probeController.SetEstimatedBitrate(
|
|
568
|
+
250, RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED, nowUs);
|
|
569
|
+
|
|
570
|
+
probeController.SetAlrEndedTimeUs(nowUs);
|
|
571
|
+
|
|
572
|
+
nowUs += (3 * 1000 * 1000) - 1000;
|
|
573
|
+
|
|
574
|
+
probes = probeController.RequestProbe(nowUs);
|
|
575
|
+
|
|
576
|
+
REQUIRE(probes.size() == 1);
|
|
577
|
+
REQUIRE(probes[0].targetBitrate == 425);
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
SECTION("but not once it has been filling it for a while")
|
|
581
|
+
{
|
|
582
|
+
RTC::BWE::ProbeController probeController;
|
|
583
|
+
|
|
584
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs).empty());
|
|
585
|
+
|
|
586
|
+
auto probes = probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate, nowUs);
|
|
587
|
+
|
|
588
|
+
REQUIRE(probes.size() == 2);
|
|
589
|
+
|
|
590
|
+
probes = probeController.SetEstimatedBitrate(
|
|
591
|
+
500, RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED, nowUs);
|
|
592
|
+
|
|
593
|
+
probeController.SetAlrStartTimeUs(std::nullopt);
|
|
594
|
+
|
|
595
|
+
nowUs += (5 * 1000 * 1000) + 1000;
|
|
596
|
+
|
|
597
|
+
probes = probeController.Process(nowUs);
|
|
598
|
+
probes = probeController.SetEstimatedBitrate(
|
|
599
|
+
250, RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED, nowUs);
|
|
600
|
+
|
|
601
|
+
probeController.SetAlrEndedTimeUs(nowUs);
|
|
602
|
+
|
|
603
|
+
nowUs += (3 * 1000 * 1000) + 1000;
|
|
604
|
+
|
|
605
|
+
probes = probeController.RequestProbe(nowUs);
|
|
606
|
+
|
|
607
|
+
REQUIRE(probes.empty());
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
SECTION("nor long after the drop happened")
|
|
611
|
+
{
|
|
612
|
+
RTC::BWE::ProbeController probeController;
|
|
613
|
+
|
|
614
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs).empty());
|
|
615
|
+
|
|
616
|
+
auto probes = probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate, nowUs);
|
|
617
|
+
|
|
618
|
+
REQUIRE(probes.size() == 2);
|
|
619
|
+
|
|
620
|
+
probes = probeController.SetEstimatedBitrate(
|
|
621
|
+
500, RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED, nowUs);
|
|
622
|
+
|
|
623
|
+
probeController.SetAlrStartTimeUs(nowUs);
|
|
624
|
+
|
|
625
|
+
nowUs += (5 * 1000 * 1000) + 1000;
|
|
626
|
+
|
|
627
|
+
probes = probeController.Process(nowUs);
|
|
628
|
+
probes = probeController.SetEstimatedBitrate(
|
|
629
|
+
250, RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED, nowUs);
|
|
630
|
+
|
|
631
|
+
nowUs += (5 * 1000 * 1000) + 1000;
|
|
632
|
+
|
|
633
|
+
probes = probeController.RequestProbe(nowUs);
|
|
634
|
+
|
|
635
|
+
REQUIRE(probes.empty());
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
SECTION("while not filling the link a burst goes out every five seconds")
|
|
639
|
+
{
|
|
640
|
+
RTC::BWE::ProbeController probeController;
|
|
641
|
+
|
|
642
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs).empty());
|
|
643
|
+
|
|
644
|
+
probeController.EnablePeriodicAlrProbing(true);
|
|
645
|
+
|
|
646
|
+
auto probes = probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate, nowUs);
|
|
647
|
+
|
|
648
|
+
REQUIRE(probes.size() == 2);
|
|
649
|
+
|
|
650
|
+
probes = probeController.SetEstimatedBitrate(
|
|
651
|
+
500, RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED, nowUs);
|
|
652
|
+
|
|
653
|
+
const int64_t startTimeUs = nowUs;
|
|
654
|
+
|
|
655
|
+
probeController.SetAlrStartTimeUs(startTimeUs);
|
|
656
|
+
|
|
657
|
+
nowUs += 5 * 1000 * 1000;
|
|
658
|
+
|
|
659
|
+
probes = probeController.Process(nowUs);
|
|
660
|
+
|
|
661
|
+
REQUIRE(probes.size() == 1);
|
|
662
|
+
REQUIRE(probes[0].targetBitrate == 1000);
|
|
663
|
+
|
|
664
|
+
probes = probeController.SetEstimatedBitrate(
|
|
665
|
+
500, RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED, nowUs);
|
|
666
|
+
|
|
667
|
+
// The next one is due ten seconds into the state, not five after this one.
|
|
668
|
+
probeController.SetAlrStartTimeUs(startTimeUs);
|
|
669
|
+
|
|
670
|
+
nowUs += 4 * 1000 * 1000;
|
|
671
|
+
|
|
672
|
+
probes = probeController.Process(nowUs);
|
|
673
|
+
probes = probeController.SetEstimatedBitrate(
|
|
674
|
+
500, RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED, nowUs);
|
|
675
|
+
|
|
676
|
+
REQUIRE(probes.empty());
|
|
677
|
+
|
|
678
|
+
probeController.SetAlrStartTimeUs(startTimeUs);
|
|
679
|
+
|
|
680
|
+
nowUs += 1000 * 1000;
|
|
681
|
+
|
|
682
|
+
probes = probeController.Process(nowUs);
|
|
683
|
+
|
|
684
|
+
REQUIRE(probes.size() == 1);
|
|
685
|
+
|
|
686
|
+
probes = probeController.SetEstimatedBitrate(
|
|
687
|
+
500, RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED, nowUs);
|
|
688
|
+
|
|
689
|
+
REQUIRE(probes.empty());
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
SECTION("and starting over leaves nothing to probe until there are bitrates again")
|
|
693
|
+
{
|
|
694
|
+
RTC::BWE::ProbeController probeController;
|
|
695
|
+
|
|
696
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs).empty());
|
|
697
|
+
|
|
698
|
+
probeController.SetAlrStartTimeUs(nowUs);
|
|
699
|
+
probeController.EnablePeriodicAlrProbing(true);
|
|
700
|
+
|
|
701
|
+
auto probes = probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate, nowUs);
|
|
702
|
+
|
|
703
|
+
probeController.Reset(nowUs);
|
|
704
|
+
|
|
705
|
+
nowUs += 10 * 1000 * 1000;
|
|
706
|
+
|
|
707
|
+
probes = probeController.Process(nowUs);
|
|
708
|
+
|
|
709
|
+
REQUIRE(probes.empty());
|
|
710
|
+
|
|
711
|
+
probes = probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate, nowUs);
|
|
712
|
+
|
|
713
|
+
REQUIRE(probes.size() == 2);
|
|
714
|
+
|
|
715
|
+
// The bitrate to start from is what stands in for the estimate until one
|
|
716
|
+
// is fed.
|
|
717
|
+
nowUs += 10 * 1000 * 1000;
|
|
718
|
+
|
|
719
|
+
probes = probeController.Process(nowUs);
|
|
720
|
+
|
|
721
|
+
REQUIRE(probes.size() == 1);
|
|
722
|
+
REQUIRE(probes[0].targetBitrate == StartBitrate * 2);
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
SECTION("nothing is probed while nothing can be sent")
|
|
726
|
+
{
|
|
727
|
+
RTC::BWE::ProbeController probeController;
|
|
728
|
+
|
|
729
|
+
probeController.EnablePeriodicAlrProbing(true);
|
|
730
|
+
|
|
731
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ false, nowUs).empty());
|
|
732
|
+
REQUIRE(probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate, nowUs).empty());
|
|
733
|
+
|
|
734
|
+
nowUs += 10 * 1000 * 1000;
|
|
735
|
+
|
|
736
|
+
REQUIRE(probeController.Process(nowUs).empty());
|
|
737
|
+
|
|
738
|
+
// Starting over after a route change doesn't make it probe either, since
|
|
739
|
+
// nothing can be sent until the handshake is done, even though the bounds
|
|
740
|
+
// may well change meanwhile.
|
|
741
|
+
probeController.Reset(nowUs);
|
|
742
|
+
|
|
743
|
+
REQUIRE(
|
|
744
|
+
probeController.SetBitrates(2 * MinBitrate, 2 * StartBitrate, 2 * MaxBitrate, nowUs).empty());
|
|
745
|
+
|
|
746
|
+
nowUs += 10 * 1000 * 1000;
|
|
747
|
+
|
|
748
|
+
REQUIRE(probeController.Process(nowUs).empty());
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
SECTION("no burst ever aims above what the application allows")
|
|
752
|
+
{
|
|
753
|
+
RTC::BWE::ProbeController probeController;
|
|
754
|
+
|
|
755
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs).empty());
|
|
756
|
+
|
|
757
|
+
auto probes = probeController.SetBitrates(MinBitrate, 10000000, 100000000, nowUs);
|
|
758
|
+
|
|
759
|
+
probes = probeController.SetEstimatedBitrate(
|
|
760
|
+
60000000, RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED, nowUs);
|
|
761
|
+
|
|
762
|
+
REQUIRE(probes.size() == 1);
|
|
763
|
+
REQUIRE(probes[0].targetBitrate == 100000000);
|
|
764
|
+
|
|
765
|
+
// And once there, there is nothing left to climb towards.
|
|
766
|
+
probes = probeController.SetEstimatedBitrate(
|
|
767
|
+
100000000, RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED, nowUs);
|
|
768
|
+
|
|
769
|
+
REQUIRE(probes.empty());
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
SECTION("nor above twice what the application wants to send")
|
|
773
|
+
{
|
|
774
|
+
RTC::BWE::ProbeController probeController;
|
|
775
|
+
|
|
776
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs).empty());
|
|
777
|
+
|
|
778
|
+
auto probes = probeController.SetBitrates(MinBitrate, 10000000, 100000000, nowUs);
|
|
779
|
+
|
|
780
|
+
probeController.EnablePeriodicAlrProbing(true);
|
|
781
|
+
probeController.SetAlrStartTimeUs(nowUs);
|
|
782
|
+
|
|
783
|
+
probes = probeController.SetEstimatedBitrate(
|
|
784
|
+
10000000, RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED, nowUs);
|
|
785
|
+
|
|
786
|
+
// Asking for less than is already being sent is nothing to probe about.
|
|
787
|
+
probes = probeController.OnMaxTotalAllocatedBitrate(9000000, nowUs);
|
|
788
|
+
|
|
789
|
+
REQUIRE(probes.empty());
|
|
790
|
+
|
|
791
|
+
nowUs += 5 * 1000 * 1000;
|
|
792
|
+
|
|
793
|
+
probes = probeController.Process(nowUs);
|
|
794
|
+
|
|
795
|
+
REQUIRE(probes.size() == 1);
|
|
796
|
+
REQUIRE(probes[0].targetBitrate == 2 * 9000000);
|
|
797
|
+
|
|
798
|
+
// With nothing asked for, the estimate is what bounds the burst again.
|
|
799
|
+
REQUIRE(probeController.OnMaxTotalAllocatedBitrate(0, nowUs).empty());
|
|
800
|
+
|
|
801
|
+
nowUs += 5 * 1000 * 1000;
|
|
802
|
+
|
|
803
|
+
probes = probeController.Process(nowUs);
|
|
804
|
+
|
|
805
|
+
REQUIRE(probes.size() == 1);
|
|
806
|
+
REQUIRE(probes[0].targetBitrate == 2 * 10000000);
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
SECTION("every factor and count that shapes a burst can be set")
|
|
810
|
+
{
|
|
811
|
+
const RTC::BWE::ProbeController::ProbeControllerOptions options{
|
|
812
|
+
.firstExponentialProbeScale = 2.0,
|
|
813
|
+
.secondExponentialProbeScale = 5.0,
|
|
814
|
+
.furtherExponentialProbeScale = 3.0,
|
|
815
|
+
.furtherProbeThreshold = 0.8,
|
|
816
|
+
.firstAllocationProbeScale = 2.0,
|
|
817
|
+
.secondAllocationProbeScale = std::nullopt,
|
|
818
|
+
.allocationProbeLimitByCurrentScale = 1000.0,
|
|
819
|
+
.minProbePacketsSent = 2
|
|
820
|
+
};
|
|
821
|
+
|
|
822
|
+
RTC::BWE::ProbeController probeController(options);
|
|
823
|
+
|
|
824
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs).empty());
|
|
825
|
+
|
|
826
|
+
auto probes = probeController.SetBitrates(MinBitrate, StartBitrate, 5000000, nowUs);
|
|
827
|
+
|
|
828
|
+
REQUIRE(probes.size() == 2);
|
|
829
|
+
REQUIRE(probes[0].targetBitrate == 600);
|
|
830
|
+
REQUIRE(probes[0].targetProbeCount == 2);
|
|
831
|
+
REQUIRE(probes[1].targetBitrate == 1500);
|
|
832
|
+
REQUIRE(probes[1].targetProbeCount == 2);
|
|
833
|
+
|
|
834
|
+
// Another burst only follows one whose result got above 0.8 of what it
|
|
835
|
+
// aimed for.
|
|
836
|
+
probes = probeController.SetEstimatedBitrate(
|
|
837
|
+
1100, RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED, nowUs);
|
|
838
|
+
|
|
839
|
+
REQUIRE(probes.empty());
|
|
840
|
+
|
|
841
|
+
probes = probeController.SetEstimatedBitrate(
|
|
842
|
+
1250, RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED, nowUs);
|
|
843
|
+
|
|
844
|
+
REQUIRE(probes.size() == 1);
|
|
845
|
+
REQUIRE(probes[0].targetBitrate == 3 * 1250);
|
|
846
|
+
|
|
847
|
+
nowUs += 5 * 1000 * 1000;
|
|
848
|
+
|
|
849
|
+
probes = probeController.Process(nowUs);
|
|
850
|
+
|
|
851
|
+
probeController.SetAlrStartTimeUs(nowUs);
|
|
852
|
+
|
|
853
|
+
probes = probeController.OnMaxTotalAllocatedBitrate(200000, nowUs);
|
|
854
|
+
|
|
855
|
+
REQUIRE(probes.size() == 1);
|
|
856
|
+
REQUIRE(probes[0].targetBitrate == 400000);
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
SECTION("while loss is what holds the estimate back a burst barely goes above it")
|
|
860
|
+
{
|
|
861
|
+
RTC::BWE::ProbeController probeController;
|
|
862
|
+
|
|
863
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs).empty());
|
|
864
|
+
|
|
865
|
+
probeController.EnablePeriodicAlrProbing(true);
|
|
866
|
+
|
|
867
|
+
auto probes = probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate, nowUs);
|
|
868
|
+
|
|
869
|
+
probes = probeController.SetEstimatedBitrate(
|
|
870
|
+
500, RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED, nowUs);
|
|
871
|
+
|
|
872
|
+
probeController.SetAlrStartTimeUs(nowUs);
|
|
873
|
+
|
|
874
|
+
nowUs += 5 * 1000 * 1000;
|
|
875
|
+
|
|
876
|
+
probes = probeController.Process(nowUs);
|
|
877
|
+
|
|
878
|
+
REQUIRE(probes.size() == 1);
|
|
879
|
+
|
|
880
|
+
probes = probeController.SetEstimatedBitrate(
|
|
881
|
+
500, RTC::BWE::ProbeController::BandwidthLimitedCause::LOSS_LIMITED_BWE_INCREASING, nowUs);
|
|
882
|
+
|
|
883
|
+
nowUs += 6 * 1000 * 1000;
|
|
884
|
+
|
|
885
|
+
probes = probeController.Process(nowUs);
|
|
886
|
+
|
|
887
|
+
REQUIRE(probes.size() == 1);
|
|
888
|
+
REQUIRE(probes[0].targetBitrate == 750);
|
|
889
|
+
|
|
890
|
+
// And once loss is no longer what holds it back, the usual factor applies
|
|
891
|
+
// again.
|
|
892
|
+
probes = probeController.SetEstimatedBitrate(
|
|
893
|
+
750, RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED, nowUs);
|
|
894
|
+
|
|
895
|
+
nowUs += 6 * 1000 * 1000;
|
|
896
|
+
|
|
897
|
+
probes = probeController.Process(nowUs);
|
|
898
|
+
|
|
899
|
+
REQUIRE(!probes.empty());
|
|
900
|
+
REQUIRE(probes[0].targetBitrate > 1125);
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
SECTION("a known upper bound of the link capacity is probed periodically")
|
|
904
|
+
{
|
|
905
|
+
const RTC::BWE::ProbeController::ProbeControllerOptions options{
|
|
906
|
+
.networkStateEstimateProbingIntervalUs = 5 * 1000 * 1000
|
|
907
|
+
};
|
|
908
|
+
|
|
909
|
+
RTC::BWE::ProbeController probeController(options);
|
|
910
|
+
|
|
911
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs).empty());
|
|
912
|
+
|
|
913
|
+
auto probes = probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate, nowUs);
|
|
914
|
+
|
|
915
|
+
probes = probeController.SetEstimatedBitrate(
|
|
916
|
+
5000, RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED, nowUs);
|
|
917
|
+
|
|
918
|
+
probeController.SetLinkCapacityUpperBound(6000);
|
|
919
|
+
|
|
920
|
+
nowUs += 5 * 1000 * 1000;
|
|
921
|
+
|
|
922
|
+
probes = probeController.Process(nowUs);
|
|
923
|
+
|
|
924
|
+
REQUIRE(probes.size() == 1);
|
|
925
|
+
REQUIRE(probes[0].targetBitrate == 6000);
|
|
926
|
+
|
|
927
|
+
nowUs += 5 * 1000 * 1000;
|
|
928
|
+
|
|
929
|
+
probes = probeController.Process(nowUs);
|
|
930
|
+
|
|
931
|
+
REQUIRE(probes.size() == 1);
|
|
932
|
+
REQUIRE(probes[0].targetBitrate == 6000);
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
SECTION("and it's what bounds the burst when loss holds the estimate back")
|
|
936
|
+
{
|
|
937
|
+
const RTC::BWE::ProbeController::ProbeControllerOptions options{
|
|
938
|
+
.networkStateEstimateProbingIntervalUs = 5 * 1000 * 1000
|
|
939
|
+
};
|
|
940
|
+
|
|
941
|
+
RTC::BWE::ProbeController probeController(options);
|
|
942
|
+
|
|
943
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs).empty());
|
|
944
|
+
|
|
945
|
+
auto probes = probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate, nowUs);
|
|
946
|
+
|
|
947
|
+
probes = probeController.SetEstimatedBitrate(
|
|
948
|
+
500, RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED, nowUs);
|
|
949
|
+
|
|
950
|
+
probeController.SetLinkCapacityUpperBound(700);
|
|
951
|
+
|
|
952
|
+
nowUs += 5 * 1000 * 1000;
|
|
953
|
+
|
|
954
|
+
probes = probeController.Process(nowUs);
|
|
955
|
+
|
|
956
|
+
REQUIRE(probes.size() == 1);
|
|
957
|
+
|
|
958
|
+
probes = probeController.SetEstimatedBitrate(
|
|
959
|
+
500, RTC::BWE::ProbeController::BandwidthLimitedCause::LOSS_LIMITED_BWE_INCREASING, nowUs);
|
|
960
|
+
|
|
961
|
+
nowUs += 5 * 1000 * 1000;
|
|
962
|
+
|
|
963
|
+
probes = probeController.Process(nowUs);
|
|
964
|
+
|
|
965
|
+
REQUIRE(!probes.empty());
|
|
966
|
+
REQUIRE(probes[0].targetBitrate == 700);
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
SECTION("and it bounds the periodic bursts as soon as there is one")
|
|
970
|
+
{
|
|
971
|
+
const RTC::BWE::ProbeController::ProbeControllerOptions options{
|
|
972
|
+
.networkStateEstimateProbingIntervalUs = 5 * 1000 * 1000
|
|
973
|
+
};
|
|
974
|
+
|
|
975
|
+
RTC::BWE::ProbeController probeController(options);
|
|
976
|
+
|
|
977
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs).empty());
|
|
978
|
+
|
|
979
|
+
probeController.EnablePeriodicAlrProbing(true);
|
|
980
|
+
|
|
981
|
+
auto probes = probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate, nowUs);
|
|
982
|
+
|
|
983
|
+
probes = probeController.SetEstimatedBitrate(
|
|
984
|
+
6000, RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED, nowUs);
|
|
985
|
+
|
|
986
|
+
probeController.SetAlrStartTimeUs(nowUs);
|
|
987
|
+
|
|
988
|
+
// Twice the estimate is above the maximum, so the maximum is what it aims
|
|
989
|
+
// for while nothing measured the link.
|
|
990
|
+
nowUs += 5 * 1000 * 1000;
|
|
991
|
+
|
|
992
|
+
probes = probeController.Process(nowUs);
|
|
993
|
+
|
|
994
|
+
REQUIRE(probes.size() == 1);
|
|
995
|
+
REQUIRE(probes[0].targetBitrate == MaxBitrate);
|
|
996
|
+
|
|
997
|
+
probeController.SetLinkCapacityUpperBound(8000);
|
|
998
|
+
|
|
999
|
+
nowUs += 5 * 1000 * 1000;
|
|
1000
|
+
|
|
1001
|
+
probes = probeController.Process(nowUs);
|
|
1002
|
+
|
|
1003
|
+
REQUIRE(probes.size() == 1);
|
|
1004
|
+
REQUIRE(probes[0].targetBitrate == 8000);
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
SECTION("and those bursts may be told to last longer than the usual ones")
|
|
1008
|
+
{
|
|
1009
|
+
const RTC::BWE::ProbeController::ProbeControllerOptions options{
|
|
1010
|
+
.networkStateEstimateProbingIntervalUs = 5 * 1000 * 1000, .networkStateProbeDurationUs = 100 * 1000
|
|
1011
|
+
};
|
|
1012
|
+
|
|
1013
|
+
RTC::BWE::ProbeController probeController(options);
|
|
1014
|
+
|
|
1015
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs).empty());
|
|
1016
|
+
|
|
1017
|
+
auto probes = probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate, nowUs);
|
|
1018
|
+
|
|
1019
|
+
probes = probeController.SetEstimatedBitrate(
|
|
1020
|
+
5000, RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED, nowUs);
|
|
1021
|
+
|
|
1022
|
+
REQUIRE(!probes.empty());
|
|
1023
|
+
REQUIRE(probes[0].targetDurationUs < 100 * 1000);
|
|
1024
|
+
|
|
1025
|
+
probeController.SetLinkCapacityUpperBound(6000);
|
|
1026
|
+
|
|
1027
|
+
nowUs += 5 * 1000 * 1000;
|
|
1028
|
+
|
|
1029
|
+
probes = probeController.Process(nowUs);
|
|
1030
|
+
|
|
1031
|
+
REQUIRE(probes.size() == 1);
|
|
1032
|
+
REQUIRE(probes[0].targetDurationUs == 100 * 1000);
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
SECTION("loss growing back while not filling the link is worth a burst")
|
|
1036
|
+
{
|
|
1037
|
+
RTC::BWE::ProbeController probeController;
|
|
1038
|
+
|
|
1039
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs).empty());
|
|
1040
|
+
|
|
1041
|
+
auto probes = probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate, nowUs);
|
|
1042
|
+
|
|
1043
|
+
probeController.EnablePeriodicAlrProbing(true);
|
|
1044
|
+
|
|
1045
|
+
probes = probeController.SetEstimatedBitrate(
|
|
1046
|
+
StartBitrate,
|
|
1047
|
+
RTC::BWE::ProbeController::BandwidthLimitedCause::LOSS_LIMITED_BWE_INCREASING,
|
|
1048
|
+
nowUs);
|
|
1049
|
+
|
|
1050
|
+
nowUs += ExponentialProbingTimeoutUs;
|
|
1051
|
+
|
|
1052
|
+
probes = probeController.Process(nowUs);
|
|
1053
|
+
|
|
1054
|
+
REQUIRE(probes.empty());
|
|
1055
|
+
|
|
1056
|
+
probeController.SetAlrStartTimeUs(nowUs);
|
|
1057
|
+
|
|
1058
|
+
nowUs += (5 * 1000 * 1000) + 1000;
|
|
1059
|
+
|
|
1060
|
+
probes = probeController.Process(nowUs);
|
|
1061
|
+
|
|
1062
|
+
REQUIRE(probes.size() == 1);
|
|
1063
|
+
REQUIRE(probes.at(0).targetBitrate == 450);
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
SECTION("but loss that isn't growing back is not")
|
|
1067
|
+
{
|
|
1068
|
+
RTC::BWE::ProbeController probeController;
|
|
1069
|
+
|
|
1070
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs).empty());
|
|
1071
|
+
|
|
1072
|
+
auto probes = probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate, nowUs);
|
|
1073
|
+
|
|
1074
|
+
probeController.EnablePeriodicAlrProbing(true);
|
|
1075
|
+
|
|
1076
|
+
probes = probeController.SetEstimatedBitrate(
|
|
1077
|
+
StartBitrate, RTC::BWE::ProbeController::BandwidthLimitedCause::LOSS_LIMITED_BWE, nowUs);
|
|
1078
|
+
|
|
1079
|
+
nowUs += ExponentialProbingTimeoutUs;
|
|
1080
|
+
|
|
1081
|
+
probes = probeController.Process(nowUs);
|
|
1082
|
+
|
|
1083
|
+
REQUIRE(probes.empty());
|
|
1084
|
+
|
|
1085
|
+
probeController.SetAlrStartTimeUs(nowUs);
|
|
1086
|
+
|
|
1087
|
+
nowUs += (5 * 1000 * 1000) + 1000;
|
|
1088
|
+
|
|
1089
|
+
probes = probeController.Process(nowUs);
|
|
1090
|
+
|
|
1091
|
+
REQUIRE(probes.empty());
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
SECTION("nor is it worth one while the link is being filled")
|
|
1095
|
+
{
|
|
1096
|
+
RTC::BWE::ProbeController probeController;
|
|
1097
|
+
|
|
1098
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs).empty());
|
|
1099
|
+
|
|
1100
|
+
auto probes = probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate, nowUs);
|
|
1101
|
+
|
|
1102
|
+
probeController.EnablePeriodicAlrProbing(true);
|
|
1103
|
+
|
|
1104
|
+
probes = probeController.SetEstimatedBitrate(
|
|
1105
|
+
StartBitrate,
|
|
1106
|
+
RTC::BWE::ProbeController::BandwidthLimitedCause::LOSS_LIMITED_BWE_INCREASING,
|
|
1107
|
+
nowUs);
|
|
1108
|
+
|
|
1109
|
+
nowUs += ExponentialProbingTimeoutUs;
|
|
1110
|
+
|
|
1111
|
+
probes = probeController.Process(nowUs);
|
|
1112
|
+
|
|
1113
|
+
REQUIRE(probes.empty());
|
|
1114
|
+
|
|
1115
|
+
probeController.SetAlrStartTimeUs(std::nullopt);
|
|
1116
|
+
|
|
1117
|
+
nowUs += (5 * 1000 * 1000) + 1000;
|
|
1118
|
+
|
|
1119
|
+
probes = probeController.Process(nowUs);
|
|
1120
|
+
|
|
1121
|
+
REQUIRE(probes.empty());
|
|
1122
|
+
}
|
|
1123
|
+
|
|
1124
|
+
SECTION("a burst that stays below the measured link capacity leads to another one")
|
|
1125
|
+
{
|
|
1126
|
+
const RTC::BWE::ProbeController::ProbeControllerOptions options{
|
|
1127
|
+
.networkStateEstimateProbingIntervalUs = 5 * 1000 * 1000
|
|
1128
|
+
};
|
|
1129
|
+
|
|
1130
|
+
RTC::BWE::ProbeController probeController(options);
|
|
1131
|
+
|
|
1132
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs).empty());
|
|
1133
|
+
|
|
1134
|
+
auto probes = probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate, nowUs);
|
|
1135
|
+
|
|
1136
|
+
REQUIRE(!probes.empty());
|
|
1137
|
+
|
|
1138
|
+
// A second has to pass before another burst can be asked for.
|
|
1139
|
+
nowUs += 1100 * 1000;
|
|
1140
|
+
|
|
1141
|
+
probes = probeController.Process(nowUs);
|
|
1142
|
+
|
|
1143
|
+
REQUIRE(probes.empty());
|
|
1144
|
+
|
|
1145
|
+
probeController.SetLinkCapacityUpperBound(5 * StartBitrate);
|
|
1146
|
+
|
|
1147
|
+
nowUs += 5 * 1000 * 1000;
|
|
1148
|
+
|
|
1149
|
+
probes = probeController.Process(nowUs);
|
|
1150
|
+
|
|
1151
|
+
REQUIRE(!probes.empty());
|
|
1152
|
+
REQUIRE(probes[0].targetBitrate < 5 * StartBitrate);
|
|
1153
|
+
|
|
1154
|
+
const auto probeTargetBitrate = probes[0].targetBitrate;
|
|
1155
|
+
|
|
1156
|
+
// The estimate reaching exactly what the burst aimed for is a result good
|
|
1157
|
+
// enough to keep climbing.
|
|
1158
|
+
probes = probeController.SetEstimatedBitrate(
|
|
1159
|
+
probeTargetBitrate, RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED, nowUs);
|
|
1160
|
+
|
|
1161
|
+
REQUIRE(!probes.empty());
|
|
1162
|
+
REQUIRE(probes[0].targetBitrate == 2 * probeTargetBitrate);
|
|
1163
|
+
}
|
|
1164
|
+
|
|
1165
|
+
SECTION("an estimate far below the measured link capacity is probed more often")
|
|
1166
|
+
{
|
|
1167
|
+
const RTC::BWE::ProbeController::ProbeControllerOptions options{
|
|
1168
|
+
.probeIfEstimateLowerThanNetworkStateEstimateRatio = 0.5,
|
|
1169
|
+
.estimateLowerThanNetworkStateEstimateProbingIntervalUs = 1000 * 1000
|
|
1170
|
+
};
|
|
1171
|
+
|
|
1172
|
+
RTC::BWE::ProbeController probeController(options);
|
|
1173
|
+
|
|
1174
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs).empty());
|
|
1175
|
+
|
|
1176
|
+
auto probes = probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate, nowUs);
|
|
1177
|
+
|
|
1178
|
+
probes = probeController.SetEstimatedBitrate(
|
|
1179
|
+
StartBitrate, RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED, nowUs);
|
|
1180
|
+
|
|
1181
|
+
// A second has to pass before another burst can be asked for.
|
|
1182
|
+
nowUs += 1100 * 1000;
|
|
1183
|
+
|
|
1184
|
+
probes = probeController.Process(nowUs);
|
|
1185
|
+
|
|
1186
|
+
REQUIRE(probes.empty());
|
|
1187
|
+
|
|
1188
|
+
// The estimate is not below half of what was measured, so there is nothing
|
|
1189
|
+
// to look for.
|
|
1190
|
+
probeController.SetLinkCapacityUpperBound(StartBitrate);
|
|
1191
|
+
|
|
1192
|
+
probes = probeController.Process(nowUs);
|
|
1193
|
+
|
|
1194
|
+
REQUIRE(probes.empty());
|
|
1195
|
+
|
|
1196
|
+
probeController.SetLinkCapacityUpperBound(StartBitrate * 3);
|
|
1197
|
+
|
|
1198
|
+
probes = probeController.Process(nowUs);
|
|
1199
|
+
|
|
1200
|
+
REQUIRE(probes.size() == 1);
|
|
1201
|
+
REQUIRE(probes[0].targetBitrate > StartBitrate);
|
|
1202
|
+
|
|
1203
|
+
// And it keeps going while the estimate stays that low.
|
|
1204
|
+
nowUs += 1100 * 1000;
|
|
1205
|
+
|
|
1206
|
+
probes = probeController.Process(nowUs);
|
|
1207
|
+
|
|
1208
|
+
REQUIRE(!probes.empty());
|
|
1209
|
+
|
|
1210
|
+
// Once the estimate comes up, the periodic bursts stop, even though the
|
|
1211
|
+
// result of this one may still lead to another.
|
|
1212
|
+
probes = probeController.SetEstimatedBitrate(
|
|
1213
|
+
2 * StartBitrate, RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED, nowUs);
|
|
1214
|
+
|
|
1215
|
+
nowUs += 1100 * 1000;
|
|
1216
|
+
|
|
1217
|
+
probes = probeController.Process(nowUs);
|
|
1218
|
+
|
|
1219
|
+
REQUIRE(probes.empty());
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
SECTION("a good result leads to another burst only while loss isn't the limit")
|
|
1223
|
+
{
|
|
1224
|
+
const RTC::BWE::ProbeController::ProbeControllerOptions options{
|
|
1225
|
+
.networkStateEstimateProbingIntervalUs = 5 * 1000 * 1000
|
|
1226
|
+
};
|
|
1227
|
+
|
|
1228
|
+
RTC::BWE::ProbeController probeController(options);
|
|
1229
|
+
|
|
1230
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs).empty());
|
|
1231
|
+
|
|
1232
|
+
auto probes = probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate, nowUs);
|
|
1233
|
+
|
|
1234
|
+
REQUIRE(!probes.empty());
|
|
1235
|
+
|
|
1236
|
+
// A second has to pass before another burst can be asked for.
|
|
1237
|
+
nowUs += 1100 * 1000;
|
|
1238
|
+
|
|
1239
|
+
probes = probeController.Process(nowUs);
|
|
1240
|
+
|
|
1241
|
+
REQUIRE(probes.empty());
|
|
1242
|
+
|
|
1243
|
+
probeController.SetLinkCapacityUpperBound(3 * StartBitrate);
|
|
1244
|
+
|
|
1245
|
+
nowUs += 5 * 1000 * 1000;
|
|
1246
|
+
|
|
1247
|
+
probes = probeController.Process(nowUs);
|
|
1248
|
+
|
|
1249
|
+
REQUIRE(!probes.empty());
|
|
1250
|
+
REQUIRE(probes[0].targetBitrate < 3 * StartBitrate);
|
|
1251
|
+
|
|
1252
|
+
probes = probeController.SetEstimatedBitrate(
|
|
1253
|
+
probes[0].targetBitrate,
|
|
1254
|
+
RTC::BWE::ProbeController::BandwidthLimitedCause::LOSS_LIMITED_BWE,
|
|
1255
|
+
nowUs);
|
|
1256
|
+
|
|
1257
|
+
REQUIRE(probes.empty());
|
|
1258
|
+
}
|
|
1259
|
+
|
|
1260
|
+
SECTION("and while the delay is, it climbs up to what was measured")
|
|
1261
|
+
{
|
|
1262
|
+
const RTC::BWE::ProbeController::ProbeControllerOptions options{
|
|
1263
|
+
.networkStateEstimateProbingIntervalUs = 5 * 1000 * 1000
|
|
1264
|
+
};
|
|
1265
|
+
|
|
1266
|
+
RTC::BWE::ProbeController probeController(options);
|
|
1267
|
+
|
|
1268
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs).empty());
|
|
1269
|
+
|
|
1270
|
+
auto probes = probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate, nowUs);
|
|
1271
|
+
|
|
1272
|
+
REQUIRE(!probes.empty());
|
|
1273
|
+
|
|
1274
|
+
// A second has to pass before another burst can be asked for.
|
|
1275
|
+
nowUs += 1100 * 1000;
|
|
1276
|
+
|
|
1277
|
+
probes = probeController.Process(nowUs);
|
|
1278
|
+
|
|
1279
|
+
REQUIRE(probes.empty());
|
|
1280
|
+
|
|
1281
|
+
probeController.SetLinkCapacityUpperBound(3 * StartBitrate);
|
|
1282
|
+
|
|
1283
|
+
nowUs += 5 * 1000 * 1000;
|
|
1284
|
+
|
|
1285
|
+
probes = probeController.Process(nowUs);
|
|
1286
|
+
|
|
1287
|
+
REQUIRE(!probes.empty());
|
|
1288
|
+
REQUIRE(probes[0].targetBitrate < 3 * StartBitrate);
|
|
1289
|
+
|
|
1290
|
+
probes = probeController.SetEstimatedBitrate(
|
|
1291
|
+
probes[0].targetBitrate,
|
|
1292
|
+
RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED,
|
|
1293
|
+
nowUs);
|
|
1294
|
+
|
|
1295
|
+
REQUIRE(!probes.empty());
|
|
1296
|
+
REQUIRE(probes[0].targetBitrate == 3 * StartBitrate);
|
|
1297
|
+
}
|
|
1298
|
+
|
|
1299
|
+
SECTION("room appearing while a burst is in flight is looked for once it times out")
|
|
1300
|
+
{
|
|
1301
|
+
const RTC::BWE::ProbeController::ProbeControllerOptions options{
|
|
1302
|
+
.networkStateEstimateProbingIntervalUs = 5 * 1000 * 1000,
|
|
1303
|
+
.probeIfEstimateLowerThanNetworkStateEstimateRatio = 0.7,
|
|
1304
|
+
.estimateLowerThanNetworkStateEstimateProbingIntervalUs = 3 * 1000 * 1000
|
|
1305
|
+
};
|
|
1306
|
+
|
|
1307
|
+
RTC::BWE::ProbeController probeController(options);
|
|
1308
|
+
|
|
1309
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs).empty());
|
|
1310
|
+
|
|
1311
|
+
auto probes = probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate, nowUs);
|
|
1312
|
+
|
|
1313
|
+
REQUIRE(!probes.empty());
|
|
1314
|
+
|
|
1315
|
+
const auto firstProbeBitrate = probes[0].targetBitrate;
|
|
1316
|
+
|
|
1317
|
+
probeController.SetLinkCapacityUpperBound((firstProbeBitrate * 12 / 10) / 2);
|
|
1318
|
+
|
|
1319
|
+
// Half of what the burst aimed for is too poor a result to keep climbing
|
|
1320
|
+
// right away.
|
|
1321
|
+
probes = probeController.SetEstimatedBitrate(
|
|
1322
|
+
firstProbeBitrate / 2,
|
|
1323
|
+
RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED,
|
|
1324
|
+
nowUs);
|
|
1325
|
+
|
|
1326
|
+
REQUIRE(probes.empty());
|
|
1327
|
+
|
|
1328
|
+
nowUs += 5 * 1000 * 1000;
|
|
1329
|
+
|
|
1330
|
+
probes = probeController.Process(nowUs);
|
|
1331
|
+
|
|
1332
|
+
REQUIRE(!probes.empty());
|
|
1333
|
+
REQUIRE(probes[0].targetBitrate <= (firstProbeBitrate * 12 / 10) / 2);
|
|
1334
|
+
|
|
1335
|
+
// The link turning out to be wider than thought is worth looking into even
|
|
1336
|
+
// before this burst's result arrives, once its own interval has passed.
|
|
1337
|
+
probeController.SetLinkCapacityUpperBound(3 * StartBitrate);
|
|
1338
|
+
|
|
1339
|
+
probes = probeController.SetEstimatedBitrate(
|
|
1340
|
+
probes[0].targetBitrate,
|
|
1341
|
+
RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED,
|
|
1342
|
+
nowUs);
|
|
1343
|
+
|
|
1344
|
+
REQUIRE(probes.empty());
|
|
1345
|
+
|
|
1346
|
+
nowUs += 3 * 1000 * 1000;
|
|
1347
|
+
|
|
1348
|
+
probes = probeController.Process(nowUs);
|
|
1349
|
+
|
|
1350
|
+
REQUIRE(!probes.empty());
|
|
1351
|
+
|
|
1352
|
+
// And once the estimate is close to what was measured there is nothing
|
|
1353
|
+
// left to look for.
|
|
1354
|
+
probes = probeController.SetEstimatedBitrate(
|
|
1355
|
+
(3 * StartBitrate * 9) / 10,
|
|
1356
|
+
RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED,
|
|
1357
|
+
nowUs);
|
|
1358
|
+
|
|
1359
|
+
REQUIRE(probes.empty());
|
|
1360
|
+
}
|
|
1361
|
+
|
|
1362
|
+
SECTION("having already aimed at the maximum, another burst waits its turn")
|
|
1363
|
+
{
|
|
1364
|
+
const RTC::BWE::ProbeController::ProbeControllerOptions options{
|
|
1365
|
+
.networkStateEstimateProbingIntervalUs = 2 * 1000 * 1000,
|
|
1366
|
+
.skipIfEstimateLargerThanFractionOfMax = 0.9
|
|
1367
|
+
};
|
|
1368
|
+
|
|
1369
|
+
RTC::BWE::ProbeController probeController(options);
|
|
1370
|
+
|
|
1371
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs).empty());
|
|
1372
|
+
|
|
1373
|
+
auto probes = probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate, nowUs);
|
|
1374
|
+
|
|
1375
|
+
REQUIRE(!probes.empty());
|
|
1376
|
+
|
|
1377
|
+
probeController.SetLinkCapacityUpperBound(2 * MaxBitrate);
|
|
1378
|
+
|
|
1379
|
+
probes = probeController.SetEstimatedBitrate(
|
|
1380
|
+
(MaxBitrate * 8) / 10,
|
|
1381
|
+
RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED,
|
|
1382
|
+
nowUs);
|
|
1383
|
+
|
|
1384
|
+
REQUIRE(!probes.empty());
|
|
1385
|
+
REQUIRE(probes[0].targetBitrate == MaxBitrate);
|
|
1386
|
+
|
|
1387
|
+
// Its result arriving changes nothing, since there is nothing above the
|
|
1388
|
+
// maximum to aim at.
|
|
1389
|
+
probes = probeController.SetEstimatedBitrate(
|
|
1390
|
+
(MaxBitrate * 8) / 10,
|
|
1391
|
+
RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED,
|
|
1392
|
+
nowUs);
|
|
1393
|
+
|
|
1394
|
+
REQUIRE(probes.empty());
|
|
1395
|
+
|
|
1396
|
+
nowUs += 1000 * 1000;
|
|
1397
|
+
|
|
1398
|
+
probes = probeController.Process(nowUs);
|
|
1399
|
+
|
|
1400
|
+
REQUIRE(probes.empty());
|
|
1401
|
+
|
|
1402
|
+
nowUs += 1000 * 1000;
|
|
1403
|
+
|
|
1404
|
+
probes = probeController.Process(nowUs);
|
|
1405
|
+
|
|
1406
|
+
REQUIRE(!probes.empty());
|
|
1407
|
+
}
|
|
1408
|
+
|
|
1409
|
+
SECTION("what the application wants to send survives starting over")
|
|
1410
|
+
{
|
|
1411
|
+
RTC::BWE::ProbeController probeController;
|
|
1412
|
+
|
|
1413
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs).empty());
|
|
1414
|
+
|
|
1415
|
+
auto probes = probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate, nowUs);
|
|
1416
|
+
|
|
1417
|
+
REQUIRE(!probes.empty());
|
|
1418
|
+
|
|
1419
|
+
probes = probeController.OnMaxTotalAllocatedBitrate(StartBitrate / 4, nowUs);
|
|
1420
|
+
|
|
1421
|
+
probeController.Reset(nowUs);
|
|
1422
|
+
|
|
1423
|
+
probes = probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate, nowUs);
|
|
1424
|
+
|
|
1425
|
+
REQUIRE(!probes.empty());
|
|
1426
|
+
REQUIRE(probes[0].targetBitrate == StartBitrate / 4 * 2);
|
|
1427
|
+
}
|
|
1428
|
+
|
|
1429
|
+
SECTION("an estimate already close to the maximum is not worth a burst")
|
|
1430
|
+
{
|
|
1431
|
+
const RTC::BWE::ProbeController::ProbeControllerOptions options{
|
|
1432
|
+
.skipIfEstimateLargerThanFractionOfMax = 0.9
|
|
1433
|
+
};
|
|
1434
|
+
|
|
1435
|
+
RTC::BWE::ProbeController probeController(options);
|
|
1436
|
+
|
|
1437
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs).empty());
|
|
1438
|
+
|
|
1439
|
+
probeController.EnablePeriodicAlrProbing(true);
|
|
1440
|
+
|
|
1441
|
+
auto probes = probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate, nowUs);
|
|
1442
|
+
|
|
1443
|
+
REQUIRE(!probes.empty());
|
|
1444
|
+
|
|
1445
|
+
probes = probeController.SetEstimatedBitrate(
|
|
1446
|
+
MaxBitrate, RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED, nowUs);
|
|
1447
|
+
|
|
1448
|
+
REQUIRE(probes.empty());
|
|
1449
|
+
|
|
1450
|
+
probeController.SetAlrStartTimeUs(nowUs);
|
|
1451
|
+
|
|
1452
|
+
nowUs += 10 * 1000 * 1000;
|
|
1453
|
+
|
|
1454
|
+
probes = probeController.Process(nowUs);
|
|
1455
|
+
|
|
1456
|
+
REQUIRE(probes.empty());
|
|
1457
|
+
|
|
1458
|
+
// Until the maximum goes up and there is room above it again.
|
|
1459
|
+
probes = probeController.SetBitrates(MinBitrate, StartBitrate, 2 * MaxBitrate, nowUs);
|
|
1460
|
+
|
|
1461
|
+
REQUIRE(!probes.empty());
|
|
1462
|
+
}
|
|
1463
|
+
|
|
1464
|
+
SECTION("and neither is one already close to what the application wants to send")
|
|
1465
|
+
{
|
|
1466
|
+
const RTC::BWE::ProbeController::ProbeControllerOptions options{
|
|
1467
|
+
.skipIfEstimateLargerThanFractionOfMax = 1.0
|
|
1468
|
+
};
|
|
1469
|
+
|
|
1470
|
+
RTC::BWE::ProbeController probeController(options);
|
|
1471
|
+
|
|
1472
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs).empty());
|
|
1473
|
+
|
|
1474
|
+
probeController.EnablePeriodicAlrProbing(true);
|
|
1475
|
+
|
|
1476
|
+
auto probes = probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate, nowUs);
|
|
1477
|
+
|
|
1478
|
+
REQUIRE(!probes.empty());
|
|
1479
|
+
|
|
1480
|
+
probes = probeController.SetEstimatedBitrate(
|
|
1481
|
+
MaxBitrate / 2, RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED, nowUs);
|
|
1482
|
+
|
|
1483
|
+
nowUs += 10 * 1000 * 1000;
|
|
1484
|
+
|
|
1485
|
+
probeController.SetAlrStartTimeUs(nowUs);
|
|
1486
|
+
|
|
1487
|
+
probes = probeController.OnMaxTotalAllocatedBitrate(MaxBitrate / 2, nowUs);
|
|
1488
|
+
|
|
1489
|
+
REQUIRE(probes.empty());
|
|
1490
|
+
|
|
1491
|
+
nowUs += 2 * 1000 * 1000;
|
|
1492
|
+
|
|
1493
|
+
probes = probeController.Process(nowUs);
|
|
1494
|
+
|
|
1495
|
+
REQUIRE(probes.empty());
|
|
1496
|
+
|
|
1497
|
+
// Until it wants a single bit more than is already being sent.
|
|
1498
|
+
probes = probeController.OnMaxTotalAllocatedBitrate((MaxBitrate / 2) + 1, nowUs);
|
|
1499
|
+
|
|
1500
|
+
REQUIRE(!probes.empty());
|
|
1501
|
+
}
|
|
1502
|
+
|
|
1503
|
+
SECTION("nor is the burst that a measured link capacity would be worth")
|
|
1504
|
+
{
|
|
1505
|
+
const RTC::BWE::ProbeController::ProbeControllerOptions options{
|
|
1506
|
+
.networkStateEstimateProbingIntervalUs = 2 * 1000 * 1000,
|
|
1507
|
+
.skipIfEstimateLargerThanFractionOfMax = 0.9
|
|
1508
|
+
};
|
|
1509
|
+
|
|
1510
|
+
RTC::BWE::ProbeController probeController(options);
|
|
1511
|
+
|
|
1512
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs).empty());
|
|
1513
|
+
|
|
1514
|
+
auto probes = probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate, nowUs);
|
|
1515
|
+
|
|
1516
|
+
REQUIRE(!probes.empty());
|
|
1517
|
+
|
|
1518
|
+
probeController.SetLinkCapacityUpperBound(2 * MaxBitrate);
|
|
1519
|
+
|
|
1520
|
+
probes = probeController.SetEstimatedBitrate(
|
|
1521
|
+
MaxBitrate, RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED, nowUs);
|
|
1522
|
+
|
|
1523
|
+
REQUIRE(probes.empty());
|
|
1524
|
+
|
|
1525
|
+
nowUs += 10 * 1000 * 1000;
|
|
1526
|
+
|
|
1527
|
+
probes = probeController.Process(nowUs);
|
|
1528
|
+
|
|
1529
|
+
REQUIRE(probes.empty());
|
|
1530
|
+
}
|
|
1531
|
+
|
|
1532
|
+
SECTION("but one that stays under the measured link capacity is, and lasts longer")
|
|
1533
|
+
{
|
|
1534
|
+
const RTC::BWE::ProbeController::ProbeControllerOptions options{
|
|
1535
|
+
.networkStateEstimateProbingIntervalUs = 2 * 1000 * 1000,
|
|
1536
|
+
.networkStateProbeDurationUs = 100 * 1000,
|
|
1537
|
+
.networkStateMinProbeDeltaUs = 20 * 1000,
|
|
1538
|
+
.skipIfEstimateLargerThanFractionOfMax = 0.9
|
|
1539
|
+
};
|
|
1540
|
+
|
|
1541
|
+
RTC::BWE::ProbeController probeController(options);
|
|
1542
|
+
|
|
1543
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs).empty());
|
|
1544
|
+
|
|
1545
|
+
auto probes = probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate, nowUs);
|
|
1546
|
+
|
|
1547
|
+
REQUIRE(!probes.empty());
|
|
1548
|
+
|
|
1549
|
+
probeController.SetLinkCapacityUpperBound(2 * MaxBitrate);
|
|
1550
|
+
|
|
1551
|
+
probes = probeController.SetEstimatedBitrate(
|
|
1552
|
+
MaxBitrate, RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED, nowUs);
|
|
1553
|
+
|
|
1554
|
+
REQUIRE(probes.empty());
|
|
1555
|
+
|
|
1556
|
+
// Two seconds have to pass before another burst can be asked for.
|
|
1557
|
+
nowUs += 2100 * 1000;
|
|
1558
|
+
|
|
1559
|
+
probes = probeController.SetEstimatedBitrate(
|
|
1560
|
+
StartBitrate, RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED, nowUs);
|
|
1561
|
+
|
|
1562
|
+
REQUIRE(probes.empty());
|
|
1563
|
+
|
|
1564
|
+
probeController.SetLinkCapacityUpperBound(2 * StartBitrate);
|
|
1565
|
+
|
|
1566
|
+
probes = probeController.Process(nowUs);
|
|
1567
|
+
|
|
1568
|
+
REQUIRE(!probes.empty());
|
|
1569
|
+
REQUIRE(probes[0].targetBitrate <= 2 * StartBitrate);
|
|
1570
|
+
REQUIRE(probes[0].minProbeDeltaUs == 20 * 1000);
|
|
1571
|
+
REQUIRE(probes[0].targetDurationUs == 100 * 1000);
|
|
1572
|
+
}
|
|
1573
|
+
|
|
1574
|
+
SECTION("a measured link capacity below the estimate doesn't bring the burst down")
|
|
1575
|
+
{
|
|
1576
|
+
const RTC::BWE::ProbeController::ProbeControllerOptions options{
|
|
1577
|
+
.networkStateEstimateProbingIntervalUs = 5 * 1000 * 1000,
|
|
1578
|
+
.networkStateProbeDurationUs = 100 * 1000,
|
|
1579
|
+
.networkStateMinProbeDeltaUs = 20 * 1000
|
|
1580
|
+
};
|
|
1581
|
+
|
|
1582
|
+
RTC::BWE::ProbeController probeController(options);
|
|
1583
|
+
|
|
1584
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs).empty());
|
|
1585
|
+
|
|
1586
|
+
probeController.EnablePeriodicAlrProbing(true);
|
|
1587
|
+
|
|
1588
|
+
auto probes = probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate, nowUs);
|
|
1589
|
+
|
|
1590
|
+
probes = probeController.SetEstimatedBitrate(
|
|
1591
|
+
StartBitrate, RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED, nowUs);
|
|
1592
|
+
|
|
1593
|
+
probeController.SetLinkCapacityUpperBound(StartBitrate);
|
|
1594
|
+
|
|
1595
|
+
// A second has to pass before another burst can be asked for.
|
|
1596
|
+
nowUs += 1100 * 1000;
|
|
1597
|
+
|
|
1598
|
+
probes = probeController.Process(nowUs);
|
|
1599
|
+
|
|
1600
|
+
REQUIRE(probes.empty());
|
|
1601
|
+
|
|
1602
|
+
probeController.SetAlrStartTimeUs(nowUs);
|
|
1603
|
+
probeController.SetLinkCapacityUpperBound(StartBitrate / 2);
|
|
1604
|
+
|
|
1605
|
+
nowUs += 6 * 1000 * 1000;
|
|
1606
|
+
|
|
1607
|
+
probes = probeController.Process(nowUs);
|
|
1608
|
+
|
|
1609
|
+
REQUIRE(!probes.empty());
|
|
1610
|
+
REQUIRE(probes[0].targetBitrate == StartBitrate);
|
|
1611
|
+
|
|
1612
|
+
// And since it isn't what bounds the burst, neither are its durations.
|
|
1613
|
+
REQUIRE(probes[0].minProbeDeltaUs == 2 * 1000);
|
|
1614
|
+
REQUIRE(probes[0].targetDurationUs == 15 * 1000);
|
|
1615
|
+
}
|
|
1616
|
+
|
|
1617
|
+
SECTION("a delay that is growing right now is no moment to probe")
|
|
1618
|
+
{
|
|
1619
|
+
RTC::BWE::ProbeController probeController;
|
|
1620
|
+
|
|
1621
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs).empty());
|
|
1622
|
+
|
|
1623
|
+
auto probes = probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate, nowUs);
|
|
1624
|
+
|
|
1625
|
+
REQUIRE(!probes.empty());
|
|
1626
|
+
|
|
1627
|
+
// A second has to pass before another burst can be asked for.
|
|
1628
|
+
nowUs += 1100 * 1000;
|
|
1629
|
+
|
|
1630
|
+
probes = probeController.Process(nowUs);
|
|
1631
|
+
|
|
1632
|
+
REQUIRE(probes.empty());
|
|
1633
|
+
|
|
1634
|
+
probeController.SetLinkCapacityUpperBound(3 * StartBitrate);
|
|
1635
|
+
|
|
1636
|
+
probes = probeController.SetEstimatedBitrate(
|
|
1637
|
+
StartBitrate,
|
|
1638
|
+
RTC::BWE::ProbeController::BandwidthLimitedCause::DELAY_BASED_LIMITED_DELAY_INCREASED,
|
|
1639
|
+
nowUs);
|
|
1640
|
+
|
|
1641
|
+
REQUIRE(probes.empty());
|
|
1642
|
+
|
|
1643
|
+
nowUs += 5 * 1000 * 1000;
|
|
1644
|
+
|
|
1645
|
+
probes = probeController.Process(nowUs);
|
|
1646
|
+
|
|
1647
|
+
REQUIRE(probes.empty());
|
|
1648
|
+
}
|
|
1649
|
+
|
|
1650
|
+
SECTION("and neither is a round trip time long enough to mean full queues")
|
|
1651
|
+
{
|
|
1652
|
+
RTC::BWE::ProbeController probeController;
|
|
1653
|
+
|
|
1654
|
+
REQUIRE(probeController.OnNetworkAvailability(/*networkAvailable*/ true, nowUs).empty());
|
|
1655
|
+
|
|
1656
|
+
auto probes = probeController.SetBitrates(MinBitrate, StartBitrate, MaxBitrate, nowUs);
|
|
1657
|
+
|
|
1658
|
+
REQUIRE(!probes.empty());
|
|
1659
|
+
|
|
1660
|
+
// A second has to pass before another burst can be asked for.
|
|
1661
|
+
nowUs += 1100 * 1000;
|
|
1662
|
+
|
|
1663
|
+
probes = probeController.Process(nowUs);
|
|
1664
|
+
|
|
1665
|
+
REQUIRE(probes.empty());
|
|
1666
|
+
|
|
1667
|
+
probeController.SetLinkCapacityUpperBound(3 * StartBitrate);
|
|
1668
|
+
|
|
1669
|
+
probes = probeController.SetEstimatedBitrate(
|
|
1670
|
+
StartBitrate,
|
|
1671
|
+
RTC::BWE::ProbeController::BandwidthLimitedCause::RTT_BASED_BACK_OFF_HIGH_RTT,
|
|
1672
|
+
nowUs);
|
|
1673
|
+
|
|
1674
|
+
REQUIRE(probes.empty());
|
|
1675
|
+
|
|
1676
|
+
nowUs += 5 * 1000 * 1000;
|
|
1677
|
+
|
|
1678
|
+
probes = probeController.Process(nowUs);
|
|
1679
|
+
|
|
1680
|
+
REQUIRE(probes.empty());
|
|
1681
|
+
}
|
|
1682
|
+
}
|