1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker * Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker *
4*d9f75844SAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker */
10*d9f75844SAndroid Build Coastguard Worker
11*d9f75844SAndroid Build Coastguard Worker #include "modules/pacing/pacing_controller.h"
12*d9f75844SAndroid Build Coastguard Worker
13*d9f75844SAndroid Build Coastguard Worker #include <algorithm>
14*d9f75844SAndroid Build Coastguard Worker #include <list>
15*d9f75844SAndroid Build Coastguard Worker #include <memory>
16*d9f75844SAndroid Build Coastguard Worker #include <string>
17*d9f75844SAndroid Build Coastguard Worker #include <utility>
18*d9f75844SAndroid Build Coastguard Worker #include <vector>
19*d9f75844SAndroid Build Coastguard Worker
20*d9f75844SAndroid Build Coastguard Worker #include "api/transport/network_types.h"
21*d9f75844SAndroid Build Coastguard Worker #include "api/units/data_rate.h"
22*d9f75844SAndroid Build Coastguard Worker #include "api/units/time_delta.h"
23*d9f75844SAndroid Build Coastguard Worker #include "modules/pacing/packet_router.h"
24*d9f75844SAndroid Build Coastguard Worker #include "system_wrappers/include/clock.h"
25*d9f75844SAndroid Build Coastguard Worker #include "test/explicit_key_value_config.h"
26*d9f75844SAndroid Build Coastguard Worker #include "test/gmock.h"
27*d9f75844SAndroid Build Coastguard Worker #include "test/gtest.h"
28*d9f75844SAndroid Build Coastguard Worker
29*d9f75844SAndroid Build Coastguard Worker using ::testing::_;
30*d9f75844SAndroid Build Coastguard Worker using ::testing::AnyNumber;
31*d9f75844SAndroid Build Coastguard Worker using ::testing::Field;
32*d9f75844SAndroid Build Coastguard Worker using ::testing::Pointee;
33*d9f75844SAndroid Build Coastguard Worker using ::testing::Property;
34*d9f75844SAndroid Build Coastguard Worker using ::testing::Return;
35*d9f75844SAndroid Build Coastguard Worker using ::testing::WithoutArgs;
36*d9f75844SAndroid Build Coastguard Worker
37*d9f75844SAndroid Build Coastguard Worker using ::webrtc::test::ExplicitKeyValueConfig;
38*d9f75844SAndroid Build Coastguard Worker
39*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
40*d9f75844SAndroid Build Coastguard Worker namespace {
41*d9f75844SAndroid Build Coastguard Worker constexpr DataRate kFirstClusterRate = DataRate::KilobitsPerSec(900);
42*d9f75844SAndroid Build Coastguard Worker constexpr DataRate kSecondClusterRate = DataRate::KilobitsPerSec(1800);
43*d9f75844SAndroid Build Coastguard Worker
44*d9f75844SAndroid Build Coastguard Worker // The error stems from truncating the time interval of probe packets to integer
45*d9f75844SAndroid Build Coastguard Worker // values. This results in probing slightly higher than the target bitrate.
46*d9f75844SAndroid Build Coastguard Worker // For 1.8 Mbps, this comes to be about 120 kbps with 1200 probe packets.
47*d9f75844SAndroid Build Coastguard Worker constexpr DataRate kProbingErrorMargin = DataRate::KilobitsPerSec(150);
48*d9f75844SAndroid Build Coastguard Worker
49*d9f75844SAndroid Build Coastguard Worker const float kPaceMultiplier = 2.5f;
50*d9f75844SAndroid Build Coastguard Worker
51*d9f75844SAndroid Build Coastguard Worker constexpr uint32_t kAudioSsrc = 12345;
52*d9f75844SAndroid Build Coastguard Worker constexpr uint32_t kVideoSsrc = 234565;
53*d9f75844SAndroid Build Coastguard Worker
54*d9f75844SAndroid Build Coastguard Worker constexpr DataRate kTargetRate = DataRate::KilobitsPerSec(800);
55*d9f75844SAndroid Build Coastguard Worker
BuildPacket(RtpPacketMediaType type,uint32_t ssrc,uint16_t sequence_number,int64_t capture_time_ms,size_t size)56*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<RtpPacketToSend> BuildPacket(RtpPacketMediaType type,
57*d9f75844SAndroid Build Coastguard Worker uint32_t ssrc,
58*d9f75844SAndroid Build Coastguard Worker uint16_t sequence_number,
59*d9f75844SAndroid Build Coastguard Worker int64_t capture_time_ms,
60*d9f75844SAndroid Build Coastguard Worker size_t size) {
61*d9f75844SAndroid Build Coastguard Worker auto packet = std::make_unique<RtpPacketToSend>(nullptr);
62*d9f75844SAndroid Build Coastguard Worker packet->set_packet_type(type);
63*d9f75844SAndroid Build Coastguard Worker packet->SetSsrc(ssrc);
64*d9f75844SAndroid Build Coastguard Worker packet->SetSequenceNumber(sequence_number);
65*d9f75844SAndroid Build Coastguard Worker packet->set_capture_time(Timestamp::Millis(capture_time_ms));
66*d9f75844SAndroid Build Coastguard Worker packet->SetPayloadSize(size);
67*d9f75844SAndroid Build Coastguard Worker return packet;
68*d9f75844SAndroid Build Coastguard Worker }
69*d9f75844SAndroid Build Coastguard Worker
70*d9f75844SAndroid Build Coastguard Worker class MediaStream {
71*d9f75844SAndroid Build Coastguard Worker public:
MediaStream(SimulatedClock & clock,RtpPacketMediaType type,uint32_t ssrc,size_t packet_size)72*d9f75844SAndroid Build Coastguard Worker MediaStream(SimulatedClock& clock,
73*d9f75844SAndroid Build Coastguard Worker RtpPacketMediaType type,
74*d9f75844SAndroid Build Coastguard Worker uint32_t ssrc,
75*d9f75844SAndroid Build Coastguard Worker size_t packet_size)
76*d9f75844SAndroid Build Coastguard Worker : clock_(clock), type_(type), ssrc_(ssrc), packet_size_(packet_size) {}
77*d9f75844SAndroid Build Coastguard Worker
BuildNextPacket()78*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<RtpPacketToSend> BuildNextPacket() {
79*d9f75844SAndroid Build Coastguard Worker return BuildPacket(type_, ssrc_, seq_num_++, clock_.TimeInMilliseconds(),
80*d9f75844SAndroid Build Coastguard Worker packet_size_);
81*d9f75844SAndroid Build Coastguard Worker }
BuildNextPacket(size_t size)82*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<RtpPacketToSend> BuildNextPacket(size_t size) {
83*d9f75844SAndroid Build Coastguard Worker return BuildPacket(type_, ssrc_, seq_num_++, clock_.TimeInMilliseconds(),
84*d9f75844SAndroid Build Coastguard Worker size);
85*d9f75844SAndroid Build Coastguard Worker }
86*d9f75844SAndroid Build Coastguard Worker
87*d9f75844SAndroid Build Coastguard Worker private:
88*d9f75844SAndroid Build Coastguard Worker SimulatedClock& clock_;
89*d9f75844SAndroid Build Coastguard Worker const RtpPacketMediaType type_;
90*d9f75844SAndroid Build Coastguard Worker const uint32_t ssrc_;
91*d9f75844SAndroid Build Coastguard Worker const size_t packet_size_;
92*d9f75844SAndroid Build Coastguard Worker uint16_t seq_num_ = 1000;
93*d9f75844SAndroid Build Coastguard Worker };
94*d9f75844SAndroid Build Coastguard Worker
95*d9f75844SAndroid Build Coastguard Worker // Mock callback proxy, where both new and old api redirects to common mock
96*d9f75844SAndroid Build Coastguard Worker // methods that focus on core aspects.
97*d9f75844SAndroid Build Coastguard Worker class MockPacingControllerCallback : public PacingController::PacketSender {
98*d9f75844SAndroid Build Coastguard Worker public:
SendPacket(std::unique_ptr<RtpPacketToSend> packet,const PacedPacketInfo & cluster_info)99*d9f75844SAndroid Build Coastguard Worker void SendPacket(std::unique_ptr<RtpPacketToSend> packet,
100*d9f75844SAndroid Build Coastguard Worker const PacedPacketInfo& cluster_info) override {
101*d9f75844SAndroid Build Coastguard Worker SendPacket(packet->Ssrc(), packet->SequenceNumber(),
102*d9f75844SAndroid Build Coastguard Worker packet->capture_time().ms(),
103*d9f75844SAndroid Build Coastguard Worker packet->packet_type() == RtpPacketMediaType::kRetransmission,
104*d9f75844SAndroid Build Coastguard Worker packet->packet_type() == RtpPacketMediaType::kPadding);
105*d9f75844SAndroid Build Coastguard Worker }
106*d9f75844SAndroid Build Coastguard Worker
GeneratePadding(DataSize target_size)107*d9f75844SAndroid Build Coastguard Worker std::vector<std::unique_ptr<RtpPacketToSend>> GeneratePadding(
108*d9f75844SAndroid Build Coastguard Worker DataSize target_size) override {
109*d9f75844SAndroid Build Coastguard Worker std::vector<std::unique_ptr<RtpPacketToSend>> ret;
110*d9f75844SAndroid Build Coastguard Worker size_t padding_size = SendPadding(target_size.bytes());
111*d9f75844SAndroid Build Coastguard Worker if (padding_size > 0) {
112*d9f75844SAndroid Build Coastguard Worker auto packet = std::make_unique<RtpPacketToSend>(nullptr);
113*d9f75844SAndroid Build Coastguard Worker packet->SetPayloadSize(padding_size);
114*d9f75844SAndroid Build Coastguard Worker packet->set_packet_type(RtpPacketMediaType::kPadding);
115*d9f75844SAndroid Build Coastguard Worker ret.emplace_back(std::move(packet));
116*d9f75844SAndroid Build Coastguard Worker }
117*d9f75844SAndroid Build Coastguard Worker return ret;
118*d9f75844SAndroid Build Coastguard Worker }
119*d9f75844SAndroid Build Coastguard Worker
120*d9f75844SAndroid Build Coastguard Worker MOCK_METHOD(void,
121*d9f75844SAndroid Build Coastguard Worker SendPacket,
122*d9f75844SAndroid Build Coastguard Worker (uint32_t ssrc,
123*d9f75844SAndroid Build Coastguard Worker uint16_t sequence_number,
124*d9f75844SAndroid Build Coastguard Worker int64_t capture_timestamp,
125*d9f75844SAndroid Build Coastguard Worker bool retransmission,
126*d9f75844SAndroid Build Coastguard Worker bool padding));
127*d9f75844SAndroid Build Coastguard Worker MOCK_METHOD(std::vector<std::unique_ptr<RtpPacketToSend>>,
128*d9f75844SAndroid Build Coastguard Worker FetchFec,
129*d9f75844SAndroid Build Coastguard Worker (),
130*d9f75844SAndroid Build Coastguard Worker (override));
131*d9f75844SAndroid Build Coastguard Worker MOCK_METHOD(size_t, SendPadding, (size_t target_size));
132*d9f75844SAndroid Build Coastguard Worker MOCK_METHOD(void,
133*d9f75844SAndroid Build Coastguard Worker OnAbortedRetransmissions,
134*d9f75844SAndroid Build Coastguard Worker (uint32_t, rtc::ArrayView<const uint16_t>),
135*d9f75844SAndroid Build Coastguard Worker (override));
136*d9f75844SAndroid Build Coastguard Worker MOCK_METHOD(absl::optional<uint32_t>,
137*d9f75844SAndroid Build Coastguard Worker GetRtxSsrcForMedia,
138*d9f75844SAndroid Build Coastguard Worker (uint32_t),
139*d9f75844SAndroid Build Coastguard Worker (const, override));
140*d9f75844SAndroid Build Coastguard Worker };
141*d9f75844SAndroid Build Coastguard Worker
142*d9f75844SAndroid Build Coastguard Worker // Mock callback implementing the raw api.
143*d9f75844SAndroid Build Coastguard Worker class MockPacketSender : public PacingController::PacketSender {
144*d9f75844SAndroid Build Coastguard Worker public:
145*d9f75844SAndroid Build Coastguard Worker MOCK_METHOD(void,
146*d9f75844SAndroid Build Coastguard Worker SendPacket,
147*d9f75844SAndroid Build Coastguard Worker (std::unique_ptr<RtpPacketToSend> packet,
148*d9f75844SAndroid Build Coastguard Worker const PacedPacketInfo& cluster_info),
149*d9f75844SAndroid Build Coastguard Worker (override));
150*d9f75844SAndroid Build Coastguard Worker MOCK_METHOD(std::vector<std::unique_ptr<RtpPacketToSend>>,
151*d9f75844SAndroid Build Coastguard Worker FetchFec,
152*d9f75844SAndroid Build Coastguard Worker (),
153*d9f75844SAndroid Build Coastguard Worker (override));
154*d9f75844SAndroid Build Coastguard Worker
155*d9f75844SAndroid Build Coastguard Worker MOCK_METHOD(std::vector<std::unique_ptr<RtpPacketToSend>>,
156*d9f75844SAndroid Build Coastguard Worker GeneratePadding,
157*d9f75844SAndroid Build Coastguard Worker (DataSize target_size),
158*d9f75844SAndroid Build Coastguard Worker (override));
159*d9f75844SAndroid Build Coastguard Worker MOCK_METHOD(void,
160*d9f75844SAndroid Build Coastguard Worker OnAbortedRetransmissions,
161*d9f75844SAndroid Build Coastguard Worker (uint32_t, rtc::ArrayView<const uint16_t>),
162*d9f75844SAndroid Build Coastguard Worker (override));
163*d9f75844SAndroid Build Coastguard Worker MOCK_METHOD(absl::optional<uint32_t>,
164*d9f75844SAndroid Build Coastguard Worker GetRtxSsrcForMedia,
165*d9f75844SAndroid Build Coastguard Worker (uint32_t),
166*d9f75844SAndroid Build Coastguard Worker (const, override));
167*d9f75844SAndroid Build Coastguard Worker };
168*d9f75844SAndroid Build Coastguard Worker
169*d9f75844SAndroid Build Coastguard Worker class PacingControllerPadding : public PacingController::PacketSender {
170*d9f75844SAndroid Build Coastguard Worker public:
171*d9f75844SAndroid Build Coastguard Worker static const size_t kPaddingPacketSize = 224;
172*d9f75844SAndroid Build Coastguard Worker
PacingControllerPadding()173*d9f75844SAndroid Build Coastguard Worker PacingControllerPadding() : padding_sent_(0), total_bytes_sent_(0) {}
174*d9f75844SAndroid Build Coastguard Worker
SendPacket(std::unique_ptr<RtpPacketToSend> packet,const PacedPacketInfo & pacing_info)175*d9f75844SAndroid Build Coastguard Worker void SendPacket(std::unique_ptr<RtpPacketToSend> packet,
176*d9f75844SAndroid Build Coastguard Worker const PacedPacketInfo& pacing_info) override {
177*d9f75844SAndroid Build Coastguard Worker total_bytes_sent_ += packet->payload_size();
178*d9f75844SAndroid Build Coastguard Worker }
179*d9f75844SAndroid Build Coastguard Worker
FetchFec()180*d9f75844SAndroid Build Coastguard Worker std::vector<std::unique_ptr<RtpPacketToSend>> FetchFec() override {
181*d9f75844SAndroid Build Coastguard Worker return {};
182*d9f75844SAndroid Build Coastguard Worker }
183*d9f75844SAndroid Build Coastguard Worker
GeneratePadding(DataSize target_size)184*d9f75844SAndroid Build Coastguard Worker std::vector<std::unique_ptr<RtpPacketToSend>> GeneratePadding(
185*d9f75844SAndroid Build Coastguard Worker DataSize target_size) override {
186*d9f75844SAndroid Build Coastguard Worker size_t num_packets =
187*d9f75844SAndroid Build Coastguard Worker (target_size.bytes() + kPaddingPacketSize - 1) / kPaddingPacketSize;
188*d9f75844SAndroid Build Coastguard Worker std::vector<std::unique_ptr<RtpPacketToSend>> packets;
189*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < num_packets; ++i) {
190*d9f75844SAndroid Build Coastguard Worker packets.emplace_back(std::make_unique<RtpPacketToSend>(nullptr));
191*d9f75844SAndroid Build Coastguard Worker packets.back()->SetPadding(kPaddingPacketSize);
192*d9f75844SAndroid Build Coastguard Worker packets.back()->set_packet_type(RtpPacketMediaType::kPadding);
193*d9f75844SAndroid Build Coastguard Worker padding_sent_ += kPaddingPacketSize;
194*d9f75844SAndroid Build Coastguard Worker }
195*d9f75844SAndroid Build Coastguard Worker return packets;
196*d9f75844SAndroid Build Coastguard Worker }
197*d9f75844SAndroid Build Coastguard Worker
OnAbortedRetransmissions(uint32_t,rtc::ArrayView<const uint16_t>)198*d9f75844SAndroid Build Coastguard Worker void OnAbortedRetransmissions(uint32_t,
199*d9f75844SAndroid Build Coastguard Worker rtc::ArrayView<const uint16_t>) override {}
GetRtxSsrcForMedia(uint32_t) const200*d9f75844SAndroid Build Coastguard Worker absl::optional<uint32_t> GetRtxSsrcForMedia(uint32_t) const override {
201*d9f75844SAndroid Build Coastguard Worker return absl::nullopt;
202*d9f75844SAndroid Build Coastguard Worker }
203*d9f75844SAndroid Build Coastguard Worker
padding_sent()204*d9f75844SAndroid Build Coastguard Worker size_t padding_sent() { return padding_sent_; }
total_bytes_sent()205*d9f75844SAndroid Build Coastguard Worker size_t total_bytes_sent() { return total_bytes_sent_; }
206*d9f75844SAndroid Build Coastguard Worker
207*d9f75844SAndroid Build Coastguard Worker private:
208*d9f75844SAndroid Build Coastguard Worker size_t padding_sent_;
209*d9f75844SAndroid Build Coastguard Worker size_t total_bytes_sent_;
210*d9f75844SAndroid Build Coastguard Worker };
211*d9f75844SAndroid Build Coastguard Worker
212*d9f75844SAndroid Build Coastguard Worker class PacingControllerProbing : public PacingController::PacketSender {
213*d9f75844SAndroid Build Coastguard Worker public:
PacingControllerProbing()214*d9f75844SAndroid Build Coastguard Worker PacingControllerProbing() : packets_sent_(0), padding_sent_(0) {}
215*d9f75844SAndroid Build Coastguard Worker
SendPacket(std::unique_ptr<RtpPacketToSend> packet,const PacedPacketInfo & pacing_info)216*d9f75844SAndroid Build Coastguard Worker void SendPacket(std::unique_ptr<RtpPacketToSend> packet,
217*d9f75844SAndroid Build Coastguard Worker const PacedPacketInfo& pacing_info) override {
218*d9f75844SAndroid Build Coastguard Worker if (packet->packet_type() != RtpPacketMediaType::kPadding) {
219*d9f75844SAndroid Build Coastguard Worker ++packets_sent_;
220*d9f75844SAndroid Build Coastguard Worker }
221*d9f75844SAndroid Build Coastguard Worker last_pacing_info_ = pacing_info;
222*d9f75844SAndroid Build Coastguard Worker }
223*d9f75844SAndroid Build Coastguard Worker
FetchFec()224*d9f75844SAndroid Build Coastguard Worker std::vector<std::unique_ptr<RtpPacketToSend>> FetchFec() override {
225*d9f75844SAndroid Build Coastguard Worker return {};
226*d9f75844SAndroid Build Coastguard Worker }
227*d9f75844SAndroid Build Coastguard Worker
GeneratePadding(DataSize target_size)228*d9f75844SAndroid Build Coastguard Worker std::vector<std::unique_ptr<RtpPacketToSend>> GeneratePadding(
229*d9f75844SAndroid Build Coastguard Worker DataSize target_size) override {
230*d9f75844SAndroid Build Coastguard Worker // From RTPSender:
231*d9f75844SAndroid Build Coastguard Worker // Max in the RFC 3550 is 255 bytes, we limit it to be modulus 32 for SRTP.
232*d9f75844SAndroid Build Coastguard Worker const DataSize kMaxPadding = DataSize::Bytes(224);
233*d9f75844SAndroid Build Coastguard Worker
234*d9f75844SAndroid Build Coastguard Worker std::vector<std::unique_ptr<RtpPacketToSend>> packets;
235*d9f75844SAndroid Build Coastguard Worker while (target_size > DataSize::Zero()) {
236*d9f75844SAndroid Build Coastguard Worker DataSize padding_size = std::min(kMaxPadding, target_size);
237*d9f75844SAndroid Build Coastguard Worker packets.emplace_back(std::make_unique<RtpPacketToSend>(nullptr));
238*d9f75844SAndroid Build Coastguard Worker packets.back()->SetPadding(padding_size.bytes());
239*d9f75844SAndroid Build Coastguard Worker packets.back()->set_packet_type(RtpPacketMediaType::kPadding);
240*d9f75844SAndroid Build Coastguard Worker padding_sent_ += padding_size.bytes();
241*d9f75844SAndroid Build Coastguard Worker target_size -= padding_size;
242*d9f75844SAndroid Build Coastguard Worker }
243*d9f75844SAndroid Build Coastguard Worker return packets;
244*d9f75844SAndroid Build Coastguard Worker }
245*d9f75844SAndroid Build Coastguard Worker
OnAbortedRetransmissions(uint32_t,rtc::ArrayView<const uint16_t>)246*d9f75844SAndroid Build Coastguard Worker void OnAbortedRetransmissions(uint32_t,
247*d9f75844SAndroid Build Coastguard Worker rtc::ArrayView<const uint16_t>) override {}
GetRtxSsrcForMedia(uint32_t) const248*d9f75844SAndroid Build Coastguard Worker absl::optional<uint32_t> GetRtxSsrcForMedia(uint32_t) const override {
249*d9f75844SAndroid Build Coastguard Worker return absl::nullopt;
250*d9f75844SAndroid Build Coastguard Worker }
251*d9f75844SAndroid Build Coastguard Worker
packets_sent() const252*d9f75844SAndroid Build Coastguard Worker int packets_sent() const { return packets_sent_; }
padding_sent() const253*d9f75844SAndroid Build Coastguard Worker int padding_sent() const { return padding_sent_; }
total_packets_sent() const254*d9f75844SAndroid Build Coastguard Worker int total_packets_sent() const { return packets_sent_ + padding_sent_; }
last_pacing_info() const255*d9f75844SAndroid Build Coastguard Worker PacedPacketInfo last_pacing_info() const { return last_pacing_info_; }
256*d9f75844SAndroid Build Coastguard Worker
257*d9f75844SAndroid Build Coastguard Worker private:
258*d9f75844SAndroid Build Coastguard Worker int packets_sent_;
259*d9f75844SAndroid Build Coastguard Worker int padding_sent_;
260*d9f75844SAndroid Build Coastguard Worker PacedPacketInfo last_pacing_info_;
261*d9f75844SAndroid Build Coastguard Worker };
262*d9f75844SAndroid Build Coastguard Worker
263*d9f75844SAndroid Build Coastguard Worker class PacingControllerTest : public ::testing::Test {
264*d9f75844SAndroid Build Coastguard Worker protected:
PacingControllerTest()265*d9f75844SAndroid Build Coastguard Worker PacingControllerTest() : clock_(123456), trials_("") {}
266*d9f75844SAndroid Build Coastguard Worker
SendAndExpectPacket(PacingController * pacer,RtpPacketMediaType type,uint32_t ssrc,uint16_t sequence_number,int64_t capture_time_ms,size_t size)267*d9f75844SAndroid Build Coastguard Worker void SendAndExpectPacket(PacingController* pacer,
268*d9f75844SAndroid Build Coastguard Worker RtpPacketMediaType type,
269*d9f75844SAndroid Build Coastguard Worker uint32_t ssrc,
270*d9f75844SAndroid Build Coastguard Worker uint16_t sequence_number,
271*d9f75844SAndroid Build Coastguard Worker int64_t capture_time_ms,
272*d9f75844SAndroid Build Coastguard Worker size_t size) {
273*d9f75844SAndroid Build Coastguard Worker pacer->EnqueuePacket(
274*d9f75844SAndroid Build Coastguard Worker BuildPacket(type, ssrc, sequence_number, capture_time_ms, size));
275*d9f75844SAndroid Build Coastguard Worker
276*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_,
277*d9f75844SAndroid Build Coastguard Worker SendPacket(ssrc, sequence_number, capture_time_ms,
278*d9f75844SAndroid Build Coastguard Worker type == RtpPacketMediaType::kRetransmission, false));
279*d9f75844SAndroid Build Coastguard Worker }
280*d9f75844SAndroid Build Coastguard Worker
AdvanceTimeUntil(webrtc::Timestamp time)281*d9f75844SAndroid Build Coastguard Worker void AdvanceTimeUntil(webrtc::Timestamp time) {
282*d9f75844SAndroid Build Coastguard Worker Timestamp now = clock_.CurrentTime();
283*d9f75844SAndroid Build Coastguard Worker clock_.AdvanceTime(std::max(TimeDelta::Zero(), time - now));
284*d9f75844SAndroid Build Coastguard Worker }
285*d9f75844SAndroid Build Coastguard Worker
ConsumeInitialBudget(PacingController * pacer)286*d9f75844SAndroid Build Coastguard Worker void ConsumeInitialBudget(PacingController* pacer) {
287*d9f75844SAndroid Build Coastguard Worker const uint32_t kSsrc = 54321;
288*d9f75844SAndroid Build Coastguard Worker uint16_t sequence_number = 1234;
289*d9f75844SAndroid Build Coastguard Worker int64_t capture_time_ms = clock_.TimeInMilliseconds();
290*d9f75844SAndroid Build Coastguard Worker const size_t kPacketSize = 250;
291*d9f75844SAndroid Build Coastguard Worker
292*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(pacer->OldestPacketEnqueueTime().IsInfinite());
293*d9f75844SAndroid Build Coastguard Worker
294*d9f75844SAndroid Build Coastguard Worker // Due to the multiplicative factor we can send 5 packets during a send
295*d9f75844SAndroid Build Coastguard Worker // interval. (network capacity * multiplier / (8 bits per byte *
296*d9f75844SAndroid Build Coastguard Worker // (packet size * #send intervals per second)
297*d9f75844SAndroid Build Coastguard Worker const size_t packets_to_send_per_interval =
298*d9f75844SAndroid Build Coastguard Worker kTargetRate.bps() * kPaceMultiplier / (8 * kPacketSize * 200);
299*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < packets_to_send_per_interval; ++i) {
300*d9f75844SAndroid Build Coastguard Worker SendAndExpectPacket(pacer, RtpPacketMediaType::kVideo, kSsrc,
301*d9f75844SAndroid Build Coastguard Worker sequence_number++, capture_time_ms, kPacketSize);
302*d9f75844SAndroid Build Coastguard Worker }
303*d9f75844SAndroid Build Coastguard Worker
304*d9f75844SAndroid Build Coastguard Worker while (pacer->QueueSizePackets() > 0) {
305*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer->NextSendTime());
306*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
307*d9f75844SAndroid Build Coastguard Worker }
308*d9f75844SAndroid Build Coastguard Worker }
309*d9f75844SAndroid Build Coastguard Worker
310*d9f75844SAndroid Build Coastguard Worker SimulatedClock clock_;
311*d9f75844SAndroid Build Coastguard Worker
312*d9f75844SAndroid Build Coastguard Worker MediaStream audio_ = MediaStream(clock_,
313*d9f75844SAndroid Build Coastguard Worker /*type*/ RtpPacketMediaType::kAudio,
314*d9f75844SAndroid Build Coastguard Worker /*ssrc*/ kAudioSsrc,
315*d9f75844SAndroid Build Coastguard Worker /*packet_size*/ 100);
316*d9f75844SAndroid Build Coastguard Worker MediaStream video_ = MediaStream(clock_,
317*d9f75844SAndroid Build Coastguard Worker /*type*/ RtpPacketMediaType::kVideo,
318*d9f75844SAndroid Build Coastguard Worker /*ssrc*/ kVideoSsrc,
319*d9f75844SAndroid Build Coastguard Worker /*packet_size*/ 1000);
320*d9f75844SAndroid Build Coastguard Worker
321*d9f75844SAndroid Build Coastguard Worker ::testing::NiceMock<MockPacingControllerCallback> callback_;
322*d9f75844SAndroid Build Coastguard Worker ExplicitKeyValueConfig trials_;
323*d9f75844SAndroid Build Coastguard Worker };
324*d9f75844SAndroid Build Coastguard Worker
TEST_F(PacingControllerTest,DefaultNoPaddingInSilence)325*d9f75844SAndroid Build Coastguard Worker TEST_F(PacingControllerTest, DefaultNoPaddingInSilence) {
326*d9f75844SAndroid Build Coastguard Worker const test::ExplicitKeyValueConfig trials("");
327*d9f75844SAndroid Build Coastguard Worker PacingController pacer(&clock_, &callback_, trials);
328*d9f75844SAndroid Build Coastguard Worker pacer.SetPacingRates(kTargetRate, DataRate::Zero());
329*d9f75844SAndroid Build Coastguard Worker // Video packet to reset last send time and provide padding data.
330*d9f75844SAndroid Build Coastguard Worker pacer.EnqueuePacket(video_.BuildNextPacket());
331*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPacket).Times(1);
332*d9f75844SAndroid Build Coastguard Worker clock_.AdvanceTimeMilliseconds(5);
333*d9f75844SAndroid Build Coastguard Worker pacer.ProcessPackets();
334*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPadding).Times(0);
335*d9f75844SAndroid Build Coastguard Worker // Waiting 500 ms should not trigger sending of padding.
336*d9f75844SAndroid Build Coastguard Worker clock_.AdvanceTimeMilliseconds(500);
337*d9f75844SAndroid Build Coastguard Worker pacer.ProcessPackets();
338*d9f75844SAndroid Build Coastguard Worker }
339*d9f75844SAndroid Build Coastguard Worker
TEST_F(PacingControllerTest,PaddingInSilenceWithTrial)340*d9f75844SAndroid Build Coastguard Worker TEST_F(PacingControllerTest, PaddingInSilenceWithTrial) {
341*d9f75844SAndroid Build Coastguard Worker const test::ExplicitKeyValueConfig trials(
342*d9f75844SAndroid Build Coastguard Worker "WebRTC-Pacer-PadInSilence/Enabled/");
343*d9f75844SAndroid Build Coastguard Worker PacingController pacer(&clock_, &callback_, trials);
344*d9f75844SAndroid Build Coastguard Worker pacer.SetPacingRates(kTargetRate, DataRate::Zero());
345*d9f75844SAndroid Build Coastguard Worker // Video packet to reset last send time and provide padding data.
346*d9f75844SAndroid Build Coastguard Worker pacer.EnqueuePacket(video_.BuildNextPacket());
347*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPacket).Times(2);
348*d9f75844SAndroid Build Coastguard Worker clock_.AdvanceTimeMilliseconds(5);
349*d9f75844SAndroid Build Coastguard Worker pacer.ProcessPackets();
350*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPadding).WillOnce(Return(1000));
351*d9f75844SAndroid Build Coastguard Worker // Waiting 500 ms should trigger sending of padding.
352*d9f75844SAndroid Build Coastguard Worker clock_.AdvanceTimeMilliseconds(500);
353*d9f75844SAndroid Build Coastguard Worker pacer.ProcessPackets();
354*d9f75844SAndroid Build Coastguard Worker }
355*d9f75844SAndroid Build Coastguard Worker
TEST_F(PacingControllerTest,CongestionWindowAffectsAudioInTrial)356*d9f75844SAndroid Build Coastguard Worker TEST_F(PacingControllerTest, CongestionWindowAffectsAudioInTrial) {
357*d9f75844SAndroid Build Coastguard Worker const test::ExplicitKeyValueConfig trials("WebRTC-Pacer-BlockAudio/Enabled/");
358*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPadding).Times(0);
359*d9f75844SAndroid Build Coastguard Worker PacingController pacer(&clock_, &callback_, trials);
360*d9f75844SAndroid Build Coastguard Worker pacer.SetPacingRates(DataRate::KilobitsPerSec(10000), DataRate::Zero());
361*d9f75844SAndroid Build Coastguard Worker // Video packet fills congestion window.
362*d9f75844SAndroid Build Coastguard Worker pacer.EnqueuePacket(video_.BuildNextPacket());
363*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPacket).Times(1);
364*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer.NextSendTime());
365*d9f75844SAndroid Build Coastguard Worker pacer.ProcessPackets();
366*d9f75844SAndroid Build Coastguard Worker pacer.SetCongested(true);
367*d9f75844SAndroid Build Coastguard Worker // Audio packet blocked due to congestion.
368*d9f75844SAndroid Build Coastguard Worker pacer.EnqueuePacket(audio_.BuildNextPacket());
369*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPacket).Times(0);
370*d9f75844SAndroid Build Coastguard Worker // Forward time to where we send keep-alive.
371*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPadding(1)).Times(2);
372*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer.NextSendTime());
373*d9f75844SAndroid Build Coastguard Worker pacer.ProcessPackets();
374*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer.NextSendTime());
375*d9f75844SAndroid Build Coastguard Worker pacer.ProcessPackets();
376*d9f75844SAndroid Build Coastguard Worker // Audio packet unblocked when congestion window clear.
377*d9f75844SAndroid Build Coastguard Worker ::testing::Mock::VerifyAndClearExpectations(&callback_);
378*d9f75844SAndroid Build Coastguard Worker pacer.SetCongested(false);
379*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPacket).Times(1);
380*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer.NextSendTime());
381*d9f75844SAndroid Build Coastguard Worker pacer.ProcessPackets();
382*d9f75844SAndroid Build Coastguard Worker }
383*d9f75844SAndroid Build Coastguard Worker
TEST_F(PacingControllerTest,DefaultCongestionWindowDoesNotAffectAudio)384*d9f75844SAndroid Build Coastguard Worker TEST_F(PacingControllerTest, DefaultCongestionWindowDoesNotAffectAudio) {
385*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPadding).Times(0);
386*d9f75844SAndroid Build Coastguard Worker const test::ExplicitKeyValueConfig trials("");
387*d9f75844SAndroid Build Coastguard Worker PacingController pacer(&clock_, &callback_, trials);
388*d9f75844SAndroid Build Coastguard Worker pacer.SetPacingRates(DataRate::BitsPerSec(10000000), DataRate::Zero());
389*d9f75844SAndroid Build Coastguard Worker // Video packet fills congestion window.
390*d9f75844SAndroid Build Coastguard Worker pacer.EnqueuePacket(video_.BuildNextPacket());
391*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPacket).Times(1);
392*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer.NextSendTime());
393*d9f75844SAndroid Build Coastguard Worker pacer.ProcessPackets();
394*d9f75844SAndroid Build Coastguard Worker pacer.SetCongested(true);
395*d9f75844SAndroid Build Coastguard Worker // Audio not blocked due to congestion.
396*d9f75844SAndroid Build Coastguard Worker pacer.EnqueuePacket(audio_.BuildNextPacket());
397*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPacket).Times(1);
398*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer.NextSendTime());
399*d9f75844SAndroid Build Coastguard Worker pacer.ProcessPackets();
400*d9f75844SAndroid Build Coastguard Worker }
401*d9f75844SAndroid Build Coastguard Worker
TEST_F(PacingControllerTest,BudgetAffectsAudioInTrial)402*d9f75844SAndroid Build Coastguard Worker TEST_F(PacingControllerTest, BudgetAffectsAudioInTrial) {
403*d9f75844SAndroid Build Coastguard Worker ExplicitKeyValueConfig trials("WebRTC-Pacer-BlockAudio/Enabled/");
404*d9f75844SAndroid Build Coastguard Worker PacingController pacer(&clock_, &callback_, trials);
405*d9f75844SAndroid Build Coastguard Worker const size_t kPacketSize = 1000;
406*d9f75844SAndroid Build Coastguard Worker const int kProcessIntervalsPerSecond = 1000 / 5;
407*d9f75844SAndroid Build Coastguard Worker DataRate pacing_rate =
408*d9f75844SAndroid Build Coastguard Worker DataRate::BitsPerSec(kPacketSize / 3 * 8 * kProcessIntervalsPerSecond);
409*d9f75844SAndroid Build Coastguard Worker pacer.SetPacingRates(pacing_rate, DataRate::Zero());
410*d9f75844SAndroid Build Coastguard Worker // Video fills budget for following process periods.
411*d9f75844SAndroid Build Coastguard Worker pacer.EnqueuePacket(video_.BuildNextPacket(kPacketSize));
412*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPacket).Times(1);
413*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer.NextSendTime());
414*d9f75844SAndroid Build Coastguard Worker pacer.ProcessPackets();
415*d9f75844SAndroid Build Coastguard Worker // Audio packet blocked due to budget limit.
416*d9f75844SAndroid Build Coastguard Worker pacer.EnqueuePacket(audio_.BuildNextPacket());
417*d9f75844SAndroid Build Coastguard Worker Timestamp wait_start_time = clock_.CurrentTime();
418*d9f75844SAndroid Build Coastguard Worker Timestamp wait_end_time = Timestamp::MinusInfinity();
419*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPacket).WillOnce(WithoutArgs([&]() {
420*d9f75844SAndroid Build Coastguard Worker wait_end_time = clock_.CurrentTime();
421*d9f75844SAndroid Build Coastguard Worker }));
422*d9f75844SAndroid Build Coastguard Worker while (!wait_end_time.IsFinite()) {
423*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer.NextSendTime());
424*d9f75844SAndroid Build Coastguard Worker pacer.ProcessPackets();
425*d9f75844SAndroid Build Coastguard Worker }
426*d9f75844SAndroid Build Coastguard Worker const TimeDelta expected_wait_time =
427*d9f75844SAndroid Build Coastguard Worker DataSize::Bytes(kPacketSize) / pacing_rate;
428*d9f75844SAndroid Build Coastguard Worker // Verify delay is near expectation, within timing margin.
429*d9f75844SAndroid Build Coastguard Worker EXPECT_LT(((wait_end_time - wait_start_time) - expected_wait_time).Abs(),
430*d9f75844SAndroid Build Coastguard Worker PacingController::kMinSleepTime);
431*d9f75844SAndroid Build Coastguard Worker }
432*d9f75844SAndroid Build Coastguard Worker
TEST_F(PacingControllerTest,DefaultBudgetDoesNotAffectAudio)433*d9f75844SAndroid Build Coastguard Worker TEST_F(PacingControllerTest, DefaultBudgetDoesNotAffectAudio) {
434*d9f75844SAndroid Build Coastguard Worker const size_t kPacketSize = 1000;
435*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPadding).Times(0);
436*d9f75844SAndroid Build Coastguard Worker const test::ExplicitKeyValueConfig trials("");
437*d9f75844SAndroid Build Coastguard Worker PacingController pacer(&clock_, &callback_, trials);
438*d9f75844SAndroid Build Coastguard Worker const int kProcessIntervalsPerSecond = 1000 / 5;
439*d9f75844SAndroid Build Coastguard Worker pacer.SetPacingRates(
440*d9f75844SAndroid Build Coastguard Worker DataRate::BitsPerSec(kPacketSize / 3 * 8 * kProcessIntervalsPerSecond),
441*d9f75844SAndroid Build Coastguard Worker DataRate::Zero());
442*d9f75844SAndroid Build Coastguard Worker // Video fills budget for following process periods.
443*d9f75844SAndroid Build Coastguard Worker pacer.EnqueuePacket(video_.BuildNextPacket(kPacketSize));
444*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPacket).Times(1);
445*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer.NextSendTime());
446*d9f75844SAndroid Build Coastguard Worker pacer.ProcessPackets();
447*d9f75844SAndroid Build Coastguard Worker // Audio packet not blocked due to budget limit.
448*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPacket).Times(1);
449*d9f75844SAndroid Build Coastguard Worker pacer.EnqueuePacket(audio_.BuildNextPacket());
450*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer.NextSendTime());
451*d9f75844SAndroid Build Coastguard Worker pacer.ProcessPackets();
452*d9f75844SAndroid Build Coastguard Worker }
453*d9f75844SAndroid Build Coastguard Worker
TEST_F(PacingControllerTest,FirstSentPacketTimeIsSet)454*d9f75844SAndroid Build Coastguard Worker TEST_F(PacingControllerTest, FirstSentPacketTimeIsSet) {
455*d9f75844SAndroid Build Coastguard Worker const Timestamp kStartTime = clock_.CurrentTime();
456*d9f75844SAndroid Build Coastguard Worker auto pacer = std::make_unique<PacingController>(&clock_, &callback_, trials_);
457*d9f75844SAndroid Build Coastguard Worker pacer->SetPacingRates(kTargetRate * kPaceMultiplier, DataRate::Zero());
458*d9f75844SAndroid Build Coastguard Worker
459*d9f75844SAndroid Build Coastguard Worker // No packet sent.
460*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(pacer->FirstSentPacketTime().has_value());
461*d9f75844SAndroid Build Coastguard Worker pacer->EnqueuePacket(video_.BuildNextPacket());
462*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer->NextSendTime());
463*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
464*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(kStartTime, pacer->FirstSentPacketTime());
465*d9f75844SAndroid Build Coastguard Worker }
466*d9f75844SAndroid Build Coastguard Worker
TEST_F(PacingControllerTest,QueueAndPacePackets)467*d9f75844SAndroid Build Coastguard Worker TEST_F(PacingControllerTest, QueueAndPacePackets) {
468*d9f75844SAndroid Build Coastguard Worker const uint32_t kSsrc = 12345;
469*d9f75844SAndroid Build Coastguard Worker uint16_t sequence_number = 1234;
470*d9f75844SAndroid Build Coastguard Worker const DataSize kPackeSize = DataSize::Bytes(250);
471*d9f75844SAndroid Build Coastguard Worker const TimeDelta kSendInterval = TimeDelta::Millis(5);
472*d9f75844SAndroid Build Coastguard Worker
473*d9f75844SAndroid Build Coastguard Worker // Due to the multiplicative factor we can send 5 packets during a 5ms send
474*d9f75844SAndroid Build Coastguard Worker // interval. (send interval * network capacity * multiplier / packet size)
475*d9f75844SAndroid Build Coastguard Worker const size_t kPacketsToSend = (kSendInterval * kTargetRate).bytes() *
476*d9f75844SAndroid Build Coastguard Worker kPaceMultiplier / kPackeSize.bytes();
477*d9f75844SAndroid Build Coastguard Worker auto pacer = std::make_unique<PacingController>(&clock_, &callback_, trials_);
478*d9f75844SAndroid Build Coastguard Worker pacer->SetPacingRates(kTargetRate * kPaceMultiplier, DataRate::Zero());
479*d9f75844SAndroid Build Coastguard Worker
480*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < kPacketsToSend; ++i) {
481*d9f75844SAndroid Build Coastguard Worker SendAndExpectPacket(pacer.get(), RtpPacketMediaType::kVideo, kSsrc,
482*d9f75844SAndroid Build Coastguard Worker sequence_number++, clock_.TimeInMilliseconds(),
483*d9f75844SAndroid Build Coastguard Worker kPackeSize.bytes());
484*d9f75844SAndroid Build Coastguard Worker }
485*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPadding).Times(0);
486*d9f75844SAndroid Build Coastguard Worker
487*d9f75844SAndroid Build Coastguard Worker // Enqueue one extra packet.
488*d9f75844SAndroid Build Coastguard Worker int64_t queued_packet_timestamp = clock_.TimeInMilliseconds();
489*d9f75844SAndroid Build Coastguard Worker pacer->EnqueuePacket(BuildPacket(RtpPacketMediaType::kVideo, kSsrc,
490*d9f75844SAndroid Build Coastguard Worker sequence_number, queued_packet_timestamp,
491*d9f75844SAndroid Build Coastguard Worker kPackeSize.bytes()));
492*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(kPacketsToSend + 1, pacer->QueueSizePackets());
493*d9f75844SAndroid Build Coastguard Worker
494*d9f75844SAndroid Build Coastguard Worker // Send packets until the initial kPacketsToSend packets are done.
495*d9f75844SAndroid Build Coastguard Worker Timestamp start_time = clock_.CurrentTime();
496*d9f75844SAndroid Build Coastguard Worker while (pacer->QueueSizePackets() > 1) {
497*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer->NextSendTime());
498*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
499*d9f75844SAndroid Build Coastguard Worker }
500*d9f75844SAndroid Build Coastguard Worker EXPECT_LT(clock_.CurrentTime() - start_time, kSendInterval);
501*d9f75844SAndroid Build Coastguard Worker
502*d9f75844SAndroid Build Coastguard Worker // Proceed till last packet can be sent.
503*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPacket(kSsrc, sequence_number,
504*d9f75844SAndroid Build Coastguard Worker queued_packet_timestamp, false, false))
505*d9f75844SAndroid Build Coastguard Worker .Times(1);
506*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer->NextSendTime());
507*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
508*d9f75844SAndroid Build Coastguard Worker EXPECT_GE(clock_.CurrentTime() - start_time, kSendInterval);
509*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(pacer->QueueSizePackets(), 0u);
510*d9f75844SAndroid Build Coastguard Worker }
511*d9f75844SAndroid Build Coastguard Worker
TEST_F(PacingControllerTest,PaceQueuedPackets)512*d9f75844SAndroid Build Coastguard Worker TEST_F(PacingControllerTest, PaceQueuedPackets) {
513*d9f75844SAndroid Build Coastguard Worker uint32_t ssrc = 12345;
514*d9f75844SAndroid Build Coastguard Worker uint16_t sequence_number = 1234;
515*d9f75844SAndroid Build Coastguard Worker const size_t kPacketSize = 250;
516*d9f75844SAndroid Build Coastguard Worker auto pacer = std::make_unique<PacingController>(&clock_, &callback_, trials_);
517*d9f75844SAndroid Build Coastguard Worker pacer->SetPacingRates(kTargetRate * kPaceMultiplier, DataRate::Zero());
518*d9f75844SAndroid Build Coastguard Worker
519*d9f75844SAndroid Build Coastguard Worker // Due to the multiplicative factor we can send 5 packets during a send
520*d9f75844SAndroid Build Coastguard Worker // interval. (network capacity * multiplier / (8 bits per byte *
521*d9f75844SAndroid Build Coastguard Worker // (packet size * #send intervals per second)
522*d9f75844SAndroid Build Coastguard Worker const size_t packets_to_send_per_interval =
523*d9f75844SAndroid Build Coastguard Worker kTargetRate.bps() * kPaceMultiplier / (8 * kPacketSize * 200);
524*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < packets_to_send_per_interval; ++i) {
525*d9f75844SAndroid Build Coastguard Worker SendAndExpectPacket(pacer.get(), RtpPacketMediaType::kVideo, ssrc,
526*d9f75844SAndroid Build Coastguard Worker sequence_number++, clock_.TimeInMilliseconds(),
527*d9f75844SAndroid Build Coastguard Worker kPacketSize);
528*d9f75844SAndroid Build Coastguard Worker }
529*d9f75844SAndroid Build Coastguard Worker
530*d9f75844SAndroid Build Coastguard Worker for (size_t j = 0; j < packets_to_send_per_interval * 10; ++j) {
531*d9f75844SAndroid Build Coastguard Worker pacer->EnqueuePacket(BuildPacket(RtpPacketMediaType::kVideo, ssrc,
532*d9f75844SAndroid Build Coastguard Worker sequence_number++,
533*d9f75844SAndroid Build Coastguard Worker clock_.TimeInMilliseconds(), kPacketSize));
534*d9f75844SAndroid Build Coastguard Worker }
535*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(packets_to_send_per_interval + packets_to_send_per_interval * 10,
536*d9f75844SAndroid Build Coastguard Worker pacer->QueueSizePackets());
537*d9f75844SAndroid Build Coastguard Worker
538*d9f75844SAndroid Build Coastguard Worker while (pacer->QueueSizePackets() > packets_to_send_per_interval * 10) {
539*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer->NextSendTime());
540*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
541*d9f75844SAndroid Build Coastguard Worker }
542*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(pacer->QueueSizePackets(), packets_to_send_per_interval * 10);
543*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPadding).Times(0);
544*d9f75844SAndroid Build Coastguard Worker
545*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPacket(ssrc, _, _, false, false))
546*d9f75844SAndroid Build Coastguard Worker .Times(pacer->QueueSizePackets());
547*d9f75844SAndroid Build Coastguard Worker const TimeDelta expected_pace_time =
548*d9f75844SAndroid Build Coastguard Worker DataSize::Bytes(pacer->QueueSizePackets() * kPacketSize) /
549*d9f75844SAndroid Build Coastguard Worker (kPaceMultiplier * kTargetRate);
550*d9f75844SAndroid Build Coastguard Worker Timestamp start_time = clock_.CurrentTime();
551*d9f75844SAndroid Build Coastguard Worker while (pacer->QueueSizePackets() > 0) {
552*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer->NextSendTime());
553*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
554*d9f75844SAndroid Build Coastguard Worker }
555*d9f75844SAndroid Build Coastguard Worker const TimeDelta actual_pace_time = clock_.CurrentTime() - start_time;
556*d9f75844SAndroid Build Coastguard Worker EXPECT_LT((actual_pace_time - expected_pace_time).Abs(),
557*d9f75844SAndroid Build Coastguard Worker PacingController::kMinSleepTime);
558*d9f75844SAndroid Build Coastguard Worker
559*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0u, pacer->QueueSizePackets());
560*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer->NextSendTime());
561*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0u, pacer->QueueSizePackets());
562*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
563*d9f75844SAndroid Build Coastguard Worker
564*d9f75844SAndroid Build Coastguard Worker // Send some more packet, just show that we can..?
565*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < packets_to_send_per_interval; ++i) {
566*d9f75844SAndroid Build Coastguard Worker SendAndExpectPacket(pacer.get(), RtpPacketMediaType::kVideo, ssrc,
567*d9f75844SAndroid Build Coastguard Worker sequence_number++, clock_.TimeInMilliseconds(), 250);
568*d9f75844SAndroid Build Coastguard Worker }
569*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(packets_to_send_per_interval, pacer->QueueSizePackets());
570*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < packets_to_send_per_interval; ++i) {
571*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer->NextSendTime());
572*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
573*d9f75844SAndroid Build Coastguard Worker }
574*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0u, pacer->QueueSizePackets());
575*d9f75844SAndroid Build Coastguard Worker }
576*d9f75844SAndroid Build Coastguard Worker
TEST_F(PacingControllerTest,RepeatedRetransmissionsAllowed)577*d9f75844SAndroid Build Coastguard Worker TEST_F(PacingControllerTest, RepeatedRetransmissionsAllowed) {
578*d9f75844SAndroid Build Coastguard Worker auto pacer = std::make_unique<PacingController>(&clock_, &callback_, trials_);
579*d9f75844SAndroid Build Coastguard Worker pacer->SetPacingRates(kTargetRate * kPaceMultiplier, DataRate::Zero());
580*d9f75844SAndroid Build Coastguard Worker
581*d9f75844SAndroid Build Coastguard Worker // Send one packet, then two retransmissions of that packet.
582*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < 3; i++) {
583*d9f75844SAndroid Build Coastguard Worker constexpr uint32_t ssrc = 333;
584*d9f75844SAndroid Build Coastguard Worker constexpr uint16_t sequence_number = 444;
585*d9f75844SAndroid Build Coastguard Worker constexpr size_t bytes = 250;
586*d9f75844SAndroid Build Coastguard Worker bool is_retransmission = (i != 0); // Original followed by retransmissions.
587*d9f75844SAndroid Build Coastguard Worker SendAndExpectPacket(pacer.get(),
588*d9f75844SAndroid Build Coastguard Worker is_retransmission ? RtpPacketMediaType::kRetransmission
589*d9f75844SAndroid Build Coastguard Worker : RtpPacketMediaType::kVideo,
590*d9f75844SAndroid Build Coastguard Worker ssrc, sequence_number, clock_.TimeInMilliseconds(),
591*d9f75844SAndroid Build Coastguard Worker bytes);
592*d9f75844SAndroid Build Coastguard Worker clock_.AdvanceTimeMilliseconds(5);
593*d9f75844SAndroid Build Coastguard Worker }
594*d9f75844SAndroid Build Coastguard Worker while (pacer->QueueSizePackets() > 0) {
595*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer->NextSendTime());
596*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
597*d9f75844SAndroid Build Coastguard Worker }
598*d9f75844SAndroid Build Coastguard Worker }
599*d9f75844SAndroid Build Coastguard Worker
TEST_F(PacingControllerTest,CanQueuePacketsWithSameSequenceNumberOnDifferentSsrcs)600*d9f75844SAndroid Build Coastguard Worker TEST_F(PacingControllerTest,
601*d9f75844SAndroid Build Coastguard Worker CanQueuePacketsWithSameSequenceNumberOnDifferentSsrcs) {
602*d9f75844SAndroid Build Coastguard Worker uint32_t ssrc = 12345;
603*d9f75844SAndroid Build Coastguard Worker uint16_t sequence_number = 1234;
604*d9f75844SAndroid Build Coastguard Worker auto pacer = std::make_unique<PacingController>(&clock_, &callback_, trials_);
605*d9f75844SAndroid Build Coastguard Worker pacer->SetPacingRates(kTargetRate * kPaceMultiplier, DataRate::Zero());
606*d9f75844SAndroid Build Coastguard Worker
607*d9f75844SAndroid Build Coastguard Worker SendAndExpectPacket(pacer.get(), RtpPacketMediaType::kVideo, ssrc,
608*d9f75844SAndroid Build Coastguard Worker sequence_number, clock_.TimeInMilliseconds(), 250);
609*d9f75844SAndroid Build Coastguard Worker
610*d9f75844SAndroid Build Coastguard Worker // Expect packet on second ssrc to be queued and sent as well.
611*d9f75844SAndroid Build Coastguard Worker SendAndExpectPacket(pacer.get(), RtpPacketMediaType::kVideo, ssrc + 1,
612*d9f75844SAndroid Build Coastguard Worker sequence_number, clock_.TimeInMilliseconds(), 250);
613*d9f75844SAndroid Build Coastguard Worker
614*d9f75844SAndroid Build Coastguard Worker clock_.AdvanceTimeMilliseconds(1000);
615*d9f75844SAndroid Build Coastguard Worker while (pacer->QueueSizePackets() > 0) {
616*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer->NextSendTime());
617*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
618*d9f75844SAndroid Build Coastguard Worker }
619*d9f75844SAndroid Build Coastguard Worker }
620*d9f75844SAndroid Build Coastguard Worker
TEST_F(PacingControllerTest,Padding)621*d9f75844SAndroid Build Coastguard Worker TEST_F(PacingControllerTest, Padding) {
622*d9f75844SAndroid Build Coastguard Worker uint32_t ssrc = 12345;
623*d9f75844SAndroid Build Coastguard Worker uint16_t sequence_number = 1234;
624*d9f75844SAndroid Build Coastguard Worker const size_t kPacketSize = 250;
625*d9f75844SAndroid Build Coastguard Worker auto pacer = std::make_unique<PacingController>(&clock_, &callback_, trials_);
626*d9f75844SAndroid Build Coastguard Worker pacer->SetPacingRates(kTargetRate * kPaceMultiplier, kTargetRate);
627*d9f75844SAndroid Build Coastguard Worker
628*d9f75844SAndroid Build Coastguard Worker const size_t kPacketsToSend = 20;
629*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < kPacketsToSend; ++i) {
630*d9f75844SAndroid Build Coastguard Worker SendAndExpectPacket(pacer.get(), RtpPacketMediaType::kVideo, ssrc,
631*d9f75844SAndroid Build Coastguard Worker sequence_number++, clock_.TimeInMilliseconds(),
632*d9f75844SAndroid Build Coastguard Worker kPacketSize);
633*d9f75844SAndroid Build Coastguard Worker }
634*d9f75844SAndroid Build Coastguard Worker const TimeDelta expected_pace_time =
635*d9f75844SAndroid Build Coastguard Worker DataSize::Bytes(pacer->QueueSizePackets() * kPacketSize) /
636*d9f75844SAndroid Build Coastguard Worker (kPaceMultiplier * kTargetRate);
637*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPadding).Times(0);
638*d9f75844SAndroid Build Coastguard Worker // Only the media packets should be sent.
639*d9f75844SAndroid Build Coastguard Worker Timestamp start_time = clock_.CurrentTime();
640*d9f75844SAndroid Build Coastguard Worker while (pacer->QueueSizePackets() > 0) {
641*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer->NextSendTime());
642*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
643*d9f75844SAndroid Build Coastguard Worker }
644*d9f75844SAndroid Build Coastguard Worker const TimeDelta actual_pace_time = clock_.CurrentTime() - start_time;
645*d9f75844SAndroid Build Coastguard Worker EXPECT_LE((actual_pace_time - expected_pace_time).Abs(),
646*d9f75844SAndroid Build Coastguard Worker PacingController::kMinSleepTime);
647*d9f75844SAndroid Build Coastguard Worker
648*d9f75844SAndroid Build Coastguard Worker // Pacing media happens at 2.5x, but padding was configured with 1.0x
649*d9f75844SAndroid Build Coastguard Worker // factor. We have to wait until the padding debt is gone before we start
650*d9f75844SAndroid Build Coastguard Worker // sending padding.
651*d9f75844SAndroid Build Coastguard Worker const TimeDelta time_to_padding_debt_free =
652*d9f75844SAndroid Build Coastguard Worker (expected_pace_time * kPaceMultiplier) - actual_pace_time;
653*d9f75844SAndroid Build Coastguard Worker clock_.AdvanceTime(time_to_padding_debt_free -
654*d9f75844SAndroid Build Coastguard Worker PacingController::kMinSleepTime);
655*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
656*d9f75844SAndroid Build Coastguard Worker
657*d9f75844SAndroid Build Coastguard Worker // Send 10 padding packets.
658*d9f75844SAndroid Build Coastguard Worker const size_t kPaddingPacketsToSend = 10;
659*d9f75844SAndroid Build Coastguard Worker DataSize padding_sent = DataSize::Zero();
660*d9f75844SAndroid Build Coastguard Worker size_t packets_sent = 0;
661*d9f75844SAndroid Build Coastguard Worker Timestamp first_send_time = Timestamp::MinusInfinity();
662*d9f75844SAndroid Build Coastguard Worker Timestamp last_send_time = Timestamp::MinusInfinity();
663*d9f75844SAndroid Build Coastguard Worker
664*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPadding)
665*d9f75844SAndroid Build Coastguard Worker .Times(kPaddingPacketsToSend)
666*d9f75844SAndroid Build Coastguard Worker .WillRepeatedly([&](size_t target_size) {
667*d9f75844SAndroid Build Coastguard Worker ++packets_sent;
668*d9f75844SAndroid Build Coastguard Worker if (packets_sent < kPaddingPacketsToSend) {
669*d9f75844SAndroid Build Coastguard Worker // Don't count bytes of last packet, instead just
670*d9f75844SAndroid Build Coastguard Worker // use this as the time the last packet finished
671*d9f75844SAndroid Build Coastguard Worker // sending.
672*d9f75844SAndroid Build Coastguard Worker padding_sent += DataSize::Bytes(target_size);
673*d9f75844SAndroid Build Coastguard Worker }
674*d9f75844SAndroid Build Coastguard Worker if (first_send_time.IsInfinite()) {
675*d9f75844SAndroid Build Coastguard Worker first_send_time = clock_.CurrentTime();
676*d9f75844SAndroid Build Coastguard Worker } else {
677*d9f75844SAndroid Build Coastguard Worker last_send_time = clock_.CurrentTime();
678*d9f75844SAndroid Build Coastguard Worker }
679*d9f75844SAndroid Build Coastguard Worker return target_size;
680*d9f75844SAndroid Build Coastguard Worker });
681*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPacket(_, _, _, false, true))
682*d9f75844SAndroid Build Coastguard Worker .Times(kPaddingPacketsToSend);
683*d9f75844SAndroid Build Coastguard Worker
684*d9f75844SAndroid Build Coastguard Worker while (packets_sent < kPaddingPacketsToSend) {
685*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer->NextSendTime());
686*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
687*d9f75844SAndroid Build Coastguard Worker }
688*d9f75844SAndroid Build Coastguard Worker
689*d9f75844SAndroid Build Coastguard Worker // Verify rate of sent padding.
690*d9f75844SAndroid Build Coastguard Worker TimeDelta padding_duration = last_send_time - first_send_time;
691*d9f75844SAndroid Build Coastguard Worker DataRate padding_rate = padding_sent / padding_duration;
692*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(padding_rate, kTargetRate);
693*d9f75844SAndroid Build Coastguard Worker }
694*d9f75844SAndroid Build Coastguard Worker
TEST_F(PacingControllerTest,NoPaddingBeforeNormalPacket)695*d9f75844SAndroid Build Coastguard Worker TEST_F(PacingControllerTest, NoPaddingBeforeNormalPacket) {
696*d9f75844SAndroid Build Coastguard Worker auto pacer = std::make_unique<PacingController>(&clock_, &callback_, trials_);
697*d9f75844SAndroid Build Coastguard Worker pacer->SetPacingRates(kTargetRate * kPaceMultiplier, kTargetRate);
698*d9f75844SAndroid Build Coastguard Worker
699*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPadding).Times(0);
700*d9f75844SAndroid Build Coastguard Worker
701*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
702*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer->NextSendTime());
703*d9f75844SAndroid Build Coastguard Worker
704*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
705*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer->NextSendTime());
706*d9f75844SAndroid Build Coastguard Worker
707*d9f75844SAndroid Build Coastguard Worker uint32_t ssrc = 12345;
708*d9f75844SAndroid Build Coastguard Worker uint16_t sequence_number = 1234;
709*d9f75844SAndroid Build Coastguard Worker int64_t capture_time_ms = 56789;
710*d9f75844SAndroid Build Coastguard Worker
711*d9f75844SAndroid Build Coastguard Worker SendAndExpectPacket(pacer.get(), RtpPacketMediaType::kVideo, ssrc,
712*d9f75844SAndroid Build Coastguard Worker sequence_number++, capture_time_ms, 250);
713*d9f75844SAndroid Build Coastguard Worker bool padding_sent = false;
714*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPadding).WillOnce([&](size_t padding) {
715*d9f75844SAndroid Build Coastguard Worker padding_sent = true;
716*d9f75844SAndroid Build Coastguard Worker return padding;
717*d9f75844SAndroid Build Coastguard Worker });
718*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPacket(_, _, _, _, true)).Times(1);
719*d9f75844SAndroid Build Coastguard Worker while (!padding_sent) {
720*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer->NextSendTime());
721*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
722*d9f75844SAndroid Build Coastguard Worker }
723*d9f75844SAndroid Build Coastguard Worker }
724*d9f75844SAndroid Build Coastguard Worker
TEST_F(PacingControllerTest,VerifyAverageBitrateVaryingMediaPayload)725*d9f75844SAndroid Build Coastguard Worker TEST_F(PacingControllerTest, VerifyAverageBitrateVaryingMediaPayload) {
726*d9f75844SAndroid Build Coastguard Worker uint32_t ssrc = 12345;
727*d9f75844SAndroid Build Coastguard Worker uint16_t sequence_number = 1234;
728*d9f75844SAndroid Build Coastguard Worker int64_t capture_time_ms = 56789;
729*d9f75844SAndroid Build Coastguard Worker const TimeDelta kAveragingWindowLength = TimeDelta::Seconds(10);
730*d9f75844SAndroid Build Coastguard Worker PacingControllerPadding callback;
731*d9f75844SAndroid Build Coastguard Worker auto pacer = std::make_unique<PacingController>(&clock_, &callback, trials_);
732*d9f75844SAndroid Build Coastguard Worker pacer->SetProbingEnabled(false);
733*d9f75844SAndroid Build Coastguard Worker pacer->SetPacingRates(kTargetRate * kPaceMultiplier, kTargetRate);
734*d9f75844SAndroid Build Coastguard Worker
735*d9f75844SAndroid Build Coastguard Worker Timestamp start_time = clock_.CurrentTime();
736*d9f75844SAndroid Build Coastguard Worker size_t media_bytes = 0;
737*d9f75844SAndroid Build Coastguard Worker while (clock_.CurrentTime() - start_time < kAveragingWindowLength) {
738*d9f75844SAndroid Build Coastguard Worker // Maybe add some new media packets corresponding to expected send rate.
739*d9f75844SAndroid Build Coastguard Worker int rand_value = rand(); // NOLINT (rand_r instead of rand)
740*d9f75844SAndroid Build Coastguard Worker while (
741*d9f75844SAndroid Build Coastguard Worker media_bytes <
742*d9f75844SAndroid Build Coastguard Worker (kTargetRate * (clock_.CurrentTime() - start_time)).bytes<size_t>()) {
743*d9f75844SAndroid Build Coastguard Worker size_t media_payload = rand_value % 400 + 800; // [400, 1200] bytes.
744*d9f75844SAndroid Build Coastguard Worker pacer->EnqueuePacket(BuildPacket(RtpPacketMediaType::kVideo, ssrc,
745*d9f75844SAndroid Build Coastguard Worker sequence_number++, capture_time_ms,
746*d9f75844SAndroid Build Coastguard Worker media_payload));
747*d9f75844SAndroid Build Coastguard Worker media_bytes += media_payload;
748*d9f75844SAndroid Build Coastguard Worker }
749*d9f75844SAndroid Build Coastguard Worker
750*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer->NextSendTime());
751*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
752*d9f75844SAndroid Build Coastguard Worker }
753*d9f75844SAndroid Build Coastguard Worker
754*d9f75844SAndroid Build Coastguard Worker EXPECT_NEAR(
755*d9f75844SAndroid Build Coastguard Worker kTargetRate.bps(),
756*d9f75844SAndroid Build Coastguard Worker (DataSize::Bytes(callback.total_bytes_sent()) / kAveragingWindowLength)
757*d9f75844SAndroid Build Coastguard Worker .bps(),
758*d9f75844SAndroid Build Coastguard Worker (kTargetRate * 0.01 /* 1% error marging */).bps());
759*d9f75844SAndroid Build Coastguard Worker }
760*d9f75844SAndroid Build Coastguard Worker
TEST_F(PacingControllerTest,Priority)761*d9f75844SAndroid Build Coastguard Worker TEST_F(PacingControllerTest, Priority) {
762*d9f75844SAndroid Build Coastguard Worker uint32_t ssrc_low_priority = 12345;
763*d9f75844SAndroid Build Coastguard Worker uint32_t ssrc = 12346;
764*d9f75844SAndroid Build Coastguard Worker uint16_t sequence_number = 1234;
765*d9f75844SAndroid Build Coastguard Worker int64_t capture_time_ms = 56789;
766*d9f75844SAndroid Build Coastguard Worker int64_t capture_time_ms_low_priority = 1234567;
767*d9f75844SAndroid Build Coastguard Worker auto pacer = std::make_unique<PacingController>(&clock_, &callback_, trials_);
768*d9f75844SAndroid Build Coastguard Worker pacer->SetPacingRates(kTargetRate * kPaceMultiplier, DataRate::Zero());
769*d9f75844SAndroid Build Coastguard Worker
770*d9f75844SAndroid Build Coastguard Worker ConsumeInitialBudget(pacer.get());
771*d9f75844SAndroid Build Coastguard Worker
772*d9f75844SAndroid Build Coastguard Worker // Expect normal and low priority to be queued and high to pass through.
773*d9f75844SAndroid Build Coastguard Worker pacer->EnqueuePacket(BuildPacket(RtpPacketMediaType::kVideo,
774*d9f75844SAndroid Build Coastguard Worker ssrc_low_priority, sequence_number++,
775*d9f75844SAndroid Build Coastguard Worker capture_time_ms_low_priority, 250));
776*d9f75844SAndroid Build Coastguard Worker
777*d9f75844SAndroid Build Coastguard Worker const size_t packets_to_send_per_interval =
778*d9f75844SAndroid Build Coastguard Worker kTargetRate.bps() * kPaceMultiplier / (8 * 250 * 200);
779*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < packets_to_send_per_interval; ++i) {
780*d9f75844SAndroid Build Coastguard Worker pacer->EnqueuePacket(BuildPacket(RtpPacketMediaType::kRetransmission, ssrc,
781*d9f75844SAndroid Build Coastguard Worker sequence_number++, capture_time_ms, 250));
782*d9f75844SAndroid Build Coastguard Worker }
783*d9f75844SAndroid Build Coastguard Worker pacer->EnqueuePacket(BuildPacket(RtpPacketMediaType::kAudio, ssrc,
784*d9f75844SAndroid Build Coastguard Worker sequence_number++, capture_time_ms, 250));
785*d9f75844SAndroid Build Coastguard Worker
786*d9f75844SAndroid Build Coastguard Worker // Expect all high and normal priority to be sent out first.
787*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPadding).Times(0);
788*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPacket(ssrc, _, capture_time_ms, _, _))
789*d9f75844SAndroid Build Coastguard Worker .Times(packets_to_send_per_interval + 1);
790*d9f75844SAndroid Build Coastguard Worker
791*d9f75844SAndroid Build Coastguard Worker while (pacer->QueueSizePackets() > 1) {
792*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer->NextSendTime());
793*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
794*d9f75844SAndroid Build Coastguard Worker }
795*d9f75844SAndroid Build Coastguard Worker
796*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1u, pacer->QueueSizePackets());
797*d9f75844SAndroid Build Coastguard Worker
798*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPacket(ssrc_low_priority, _,
799*d9f75844SAndroid Build Coastguard Worker capture_time_ms_low_priority, _, _));
800*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer->NextSendTime());
801*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
802*d9f75844SAndroid Build Coastguard Worker }
803*d9f75844SAndroid Build Coastguard Worker
TEST_F(PacingControllerTest,RetransmissionPriority)804*d9f75844SAndroid Build Coastguard Worker TEST_F(PacingControllerTest, RetransmissionPriority) {
805*d9f75844SAndroid Build Coastguard Worker uint32_t ssrc = 12345;
806*d9f75844SAndroid Build Coastguard Worker uint16_t sequence_number = 1234;
807*d9f75844SAndroid Build Coastguard Worker int64_t capture_time_ms = 45678;
808*d9f75844SAndroid Build Coastguard Worker int64_t capture_time_ms_retransmission = 56789;
809*d9f75844SAndroid Build Coastguard Worker auto pacer = std::make_unique<PacingController>(&clock_, &callback_, trials_);
810*d9f75844SAndroid Build Coastguard Worker pacer->SetPacingRates(kTargetRate * kPaceMultiplier, DataRate::Zero());
811*d9f75844SAndroid Build Coastguard Worker
812*d9f75844SAndroid Build Coastguard Worker // Due to the multiplicative factor we can send 5 packets during a send
813*d9f75844SAndroid Build Coastguard Worker // interval. (network capacity * multiplier / (8 bits per byte *
814*d9f75844SAndroid Build Coastguard Worker // (packet size * #send intervals per second)
815*d9f75844SAndroid Build Coastguard Worker const size_t packets_to_send_per_interval =
816*d9f75844SAndroid Build Coastguard Worker kTargetRate.bps() * kPaceMultiplier / (8 * 250 * 200);
817*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
818*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0u, pacer->QueueSizePackets());
819*d9f75844SAndroid Build Coastguard Worker
820*d9f75844SAndroid Build Coastguard Worker // Alternate retransmissions and normal packets.
821*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < packets_to_send_per_interval; ++i) {
822*d9f75844SAndroid Build Coastguard Worker pacer->EnqueuePacket(BuildPacket(RtpPacketMediaType::kVideo, ssrc,
823*d9f75844SAndroid Build Coastguard Worker sequence_number++, capture_time_ms, 250));
824*d9f75844SAndroid Build Coastguard Worker pacer->EnqueuePacket(BuildPacket(RtpPacketMediaType::kRetransmission, ssrc,
825*d9f75844SAndroid Build Coastguard Worker sequence_number++,
826*d9f75844SAndroid Build Coastguard Worker capture_time_ms_retransmission, 250));
827*d9f75844SAndroid Build Coastguard Worker }
828*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(2 * packets_to_send_per_interval, pacer->QueueSizePackets());
829*d9f75844SAndroid Build Coastguard Worker
830*d9f75844SAndroid Build Coastguard Worker // Expect all retransmissions to be sent out first despite having a later
831*d9f75844SAndroid Build Coastguard Worker // capture time.
832*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPadding).Times(0);
833*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPacket(_, _, _, false, _)).Times(0);
834*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_,
835*d9f75844SAndroid Build Coastguard Worker SendPacket(ssrc, _, capture_time_ms_retransmission, true, _))
836*d9f75844SAndroid Build Coastguard Worker .Times(packets_to_send_per_interval);
837*d9f75844SAndroid Build Coastguard Worker
838*d9f75844SAndroid Build Coastguard Worker while (pacer->QueueSizePackets() > packets_to_send_per_interval) {
839*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer->NextSendTime());
840*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
841*d9f75844SAndroid Build Coastguard Worker }
842*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(packets_to_send_per_interval, pacer->QueueSizePackets());
843*d9f75844SAndroid Build Coastguard Worker
844*d9f75844SAndroid Build Coastguard Worker // Expect the remaining (non-retransmission) packets to be sent.
845*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPadding).Times(0);
846*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPacket(_, _, _, true, _)).Times(0);
847*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPacket(ssrc, _, capture_time_ms, false, _))
848*d9f75844SAndroid Build Coastguard Worker .Times(packets_to_send_per_interval);
849*d9f75844SAndroid Build Coastguard Worker
850*d9f75844SAndroid Build Coastguard Worker while (pacer->QueueSizePackets() > 0) {
851*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer->NextSendTime());
852*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
853*d9f75844SAndroid Build Coastguard Worker }
854*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0u, pacer->QueueSizePackets());
855*d9f75844SAndroid Build Coastguard Worker }
856*d9f75844SAndroid Build Coastguard Worker
TEST_F(PacingControllerTest,HighPrioDoesntAffectBudget)857*d9f75844SAndroid Build Coastguard Worker TEST_F(PacingControllerTest, HighPrioDoesntAffectBudget) {
858*d9f75844SAndroid Build Coastguard Worker const size_t kPacketSize = 250;
859*d9f75844SAndroid Build Coastguard Worker uint32_t ssrc = 12346;
860*d9f75844SAndroid Build Coastguard Worker uint16_t sequence_number = 1234;
861*d9f75844SAndroid Build Coastguard Worker int64_t capture_time_ms = 56789;
862*d9f75844SAndroid Build Coastguard Worker auto pacer = std::make_unique<PacingController>(&clock_, &callback_, trials_);
863*d9f75844SAndroid Build Coastguard Worker pacer->SetPacingRates(kTargetRate * kPaceMultiplier, DataRate::Zero());
864*d9f75844SAndroid Build Coastguard Worker
865*d9f75844SAndroid Build Coastguard Worker // As high prio packets doesn't affect the budget, we should be able to send
866*d9f75844SAndroid Build Coastguard Worker // a high number of them at once.
867*d9f75844SAndroid Build Coastguard Worker const size_t kNumAudioPackets = 25;
868*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < kNumAudioPackets; ++i) {
869*d9f75844SAndroid Build Coastguard Worker SendAndExpectPacket(pacer.get(), RtpPacketMediaType::kAudio, ssrc,
870*d9f75844SAndroid Build Coastguard Worker sequence_number++, capture_time_ms, kPacketSize);
871*d9f75844SAndroid Build Coastguard Worker }
872*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
873*d9f75844SAndroid Build Coastguard Worker // Low prio packets does affect the budget.
874*d9f75844SAndroid Build Coastguard Worker // Due to the multiplicative factor we can send 5 packets during a send
875*d9f75844SAndroid Build Coastguard Worker // interval. (network capacity * multiplier / (8 bits per byte *
876*d9f75844SAndroid Build Coastguard Worker // (packet size * #send intervals per second)
877*d9f75844SAndroid Build Coastguard Worker const size_t kPacketsToSendPerInterval =
878*d9f75844SAndroid Build Coastguard Worker kTargetRate.bps() * kPaceMultiplier / (8 * kPacketSize * 200);
879*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < kPacketsToSendPerInterval; ++i) {
880*d9f75844SAndroid Build Coastguard Worker SendAndExpectPacket(pacer.get(), RtpPacketMediaType::kVideo, ssrc,
881*d9f75844SAndroid Build Coastguard Worker sequence_number++, clock_.TimeInMilliseconds(),
882*d9f75844SAndroid Build Coastguard Worker kPacketSize);
883*d9f75844SAndroid Build Coastguard Worker }
884*d9f75844SAndroid Build Coastguard Worker
885*d9f75844SAndroid Build Coastguard Worker // Send all packets and measure pace time.
886*d9f75844SAndroid Build Coastguard Worker Timestamp start_time = clock_.CurrentTime();
887*d9f75844SAndroid Build Coastguard Worker while (pacer->QueueSizePackets() > 0) {
888*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer->NextSendTime());
889*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
890*d9f75844SAndroid Build Coastguard Worker }
891*d9f75844SAndroid Build Coastguard Worker
892*d9f75844SAndroid Build Coastguard Worker // Measure pacing time. Expect only low-prio packets to affect this.
893*d9f75844SAndroid Build Coastguard Worker TimeDelta pacing_time = clock_.CurrentTime() - start_time;
894*d9f75844SAndroid Build Coastguard Worker TimeDelta expected_pacing_time =
895*d9f75844SAndroid Build Coastguard Worker DataSize::Bytes(kPacketsToSendPerInterval * kPacketSize) /
896*d9f75844SAndroid Build Coastguard Worker (kTargetRate * kPaceMultiplier);
897*d9f75844SAndroid Build Coastguard Worker EXPECT_NEAR(pacing_time.us<double>(), expected_pacing_time.us<double>(),
898*d9f75844SAndroid Build Coastguard Worker PacingController::kMinSleepTime.us<double>());
899*d9f75844SAndroid Build Coastguard Worker }
900*d9f75844SAndroid Build Coastguard Worker
TEST_F(PacingControllerTest,SendsOnlyPaddingWhenCongested)901*d9f75844SAndroid Build Coastguard Worker TEST_F(PacingControllerTest, SendsOnlyPaddingWhenCongested) {
902*d9f75844SAndroid Build Coastguard Worker uint32_t ssrc = 202020;
903*d9f75844SAndroid Build Coastguard Worker uint16_t sequence_number = 1000;
904*d9f75844SAndroid Build Coastguard Worker int kPacketSize = 250;
905*d9f75844SAndroid Build Coastguard Worker auto pacer = std::make_unique<PacingController>(&clock_, &callback_, trials_);
906*d9f75844SAndroid Build Coastguard Worker pacer->SetPacingRates(kTargetRate * kPaceMultiplier, DataRate::Zero());
907*d9f75844SAndroid Build Coastguard Worker
908*d9f75844SAndroid Build Coastguard Worker // Send an initial packet so we have a last send time.
909*d9f75844SAndroid Build Coastguard Worker SendAndExpectPacket(pacer.get(), RtpPacketMediaType::kVideo, ssrc,
910*d9f75844SAndroid Build Coastguard Worker sequence_number++, clock_.TimeInMilliseconds(),
911*d9f75844SAndroid Build Coastguard Worker kPacketSize);
912*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer->NextSendTime());
913*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
914*d9f75844SAndroid Build Coastguard Worker ::testing::Mock::VerifyAndClearExpectations(&callback_);
915*d9f75844SAndroid Build Coastguard Worker
916*d9f75844SAndroid Build Coastguard Worker // Set congested state, we should not send anything until the 500ms since
917*d9f75844SAndroid Build Coastguard Worker // last send time limit for keep-alives is triggered.
918*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPacket).Times(0);
919*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPadding).Times(0);
920*d9f75844SAndroid Build Coastguard Worker pacer->SetCongested(true);
921*d9f75844SAndroid Build Coastguard Worker size_t blocked_packets = 0;
922*d9f75844SAndroid Build Coastguard Worker int64_t expected_time_until_padding = 500;
923*d9f75844SAndroid Build Coastguard Worker while (expected_time_until_padding > 5) {
924*d9f75844SAndroid Build Coastguard Worker pacer->EnqueuePacket(BuildPacket(RtpPacketMediaType::kVideo, ssrc,
925*d9f75844SAndroid Build Coastguard Worker sequence_number++,
926*d9f75844SAndroid Build Coastguard Worker clock_.TimeInMilliseconds(), kPacketSize));
927*d9f75844SAndroid Build Coastguard Worker blocked_packets++;
928*d9f75844SAndroid Build Coastguard Worker clock_.AdvanceTimeMilliseconds(5);
929*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
930*d9f75844SAndroid Build Coastguard Worker expected_time_until_padding -= 5;
931*d9f75844SAndroid Build Coastguard Worker }
932*d9f75844SAndroid Build Coastguard Worker
933*d9f75844SAndroid Build Coastguard Worker ::testing::Mock::VerifyAndClearExpectations(&callback_);
934*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPadding(1)).WillOnce(Return(1));
935*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPacket(_, _, _, _, true)).Times(1);
936*d9f75844SAndroid Build Coastguard Worker clock_.AdvanceTimeMilliseconds(5);
937*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
938*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(blocked_packets, pacer->QueueSizePackets());
939*d9f75844SAndroid Build Coastguard Worker }
940*d9f75844SAndroid Build Coastguard Worker
TEST_F(PacingControllerTest,DoesNotAllowOveruseAfterCongestion)941*d9f75844SAndroid Build Coastguard Worker TEST_F(PacingControllerTest, DoesNotAllowOveruseAfterCongestion) {
942*d9f75844SAndroid Build Coastguard Worker uint32_t ssrc = 202020;
943*d9f75844SAndroid Build Coastguard Worker uint16_t seq_num = 1000;
944*d9f75844SAndroid Build Coastguard Worker int size = 1000;
945*d9f75844SAndroid Build Coastguard Worker auto now_ms = [this] { return clock_.TimeInMilliseconds(); };
946*d9f75844SAndroid Build Coastguard Worker auto pacer = std::make_unique<PacingController>(&clock_, &callback_, trials_);
947*d9f75844SAndroid Build Coastguard Worker pacer->SetPacingRates(kTargetRate * kPaceMultiplier, DataRate::Zero());
948*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPadding).Times(0);
949*d9f75844SAndroid Build Coastguard Worker // The pacing rate is low enough that the budget should not allow two packets
950*d9f75844SAndroid Build Coastguard Worker // to be sent in a row.
951*d9f75844SAndroid Build Coastguard Worker pacer->SetPacingRates(DataRate::BitsPerSec(400 * 8 * 1000 / 5),
952*d9f75844SAndroid Build Coastguard Worker DataRate::Zero());
953*d9f75844SAndroid Build Coastguard Worker // Not yet budget limited or congested, packet is sent.
954*d9f75844SAndroid Build Coastguard Worker pacer->EnqueuePacket(
955*d9f75844SAndroid Build Coastguard Worker BuildPacket(RtpPacketMediaType::kVideo, ssrc, seq_num++, now_ms(), size));
956*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPacket).Times(1);
957*d9f75844SAndroid Build Coastguard Worker clock_.AdvanceTimeMilliseconds(5);
958*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
959*d9f75844SAndroid Build Coastguard Worker // Packet blocked due to congestion.
960*d9f75844SAndroid Build Coastguard Worker pacer->SetCongested(true);
961*d9f75844SAndroid Build Coastguard Worker pacer->EnqueuePacket(
962*d9f75844SAndroid Build Coastguard Worker BuildPacket(RtpPacketMediaType::kVideo, ssrc, seq_num++, now_ms(), size));
963*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPacket).Times(0);
964*d9f75844SAndroid Build Coastguard Worker clock_.AdvanceTimeMilliseconds(5);
965*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
966*d9f75844SAndroid Build Coastguard Worker // Packet blocked due to congestion.
967*d9f75844SAndroid Build Coastguard Worker pacer->EnqueuePacket(
968*d9f75844SAndroid Build Coastguard Worker BuildPacket(RtpPacketMediaType::kVideo, ssrc, seq_num++, now_ms(), size));
969*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPacket).Times(0);
970*d9f75844SAndroid Build Coastguard Worker clock_.AdvanceTimeMilliseconds(5);
971*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
972*d9f75844SAndroid Build Coastguard Worker // Congestion removed and budget has recovered, packet is sent.
973*d9f75844SAndroid Build Coastguard Worker pacer->EnqueuePacket(
974*d9f75844SAndroid Build Coastguard Worker BuildPacket(RtpPacketMediaType::kVideo, ssrc, seq_num++, now_ms(), size));
975*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPacket).Times(1);
976*d9f75844SAndroid Build Coastguard Worker clock_.AdvanceTimeMilliseconds(5);
977*d9f75844SAndroid Build Coastguard Worker pacer->SetCongested(false);
978*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
979*d9f75844SAndroid Build Coastguard Worker // Should be blocked due to budget limitation as congestion has be removed.
980*d9f75844SAndroid Build Coastguard Worker pacer->EnqueuePacket(
981*d9f75844SAndroid Build Coastguard Worker BuildPacket(RtpPacketMediaType::kVideo, ssrc, seq_num++, now_ms(), size));
982*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPacket).Times(0);
983*d9f75844SAndroid Build Coastguard Worker clock_.AdvanceTimeMilliseconds(5);
984*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
985*d9f75844SAndroid Build Coastguard Worker }
986*d9f75844SAndroid Build Coastguard Worker
TEST_F(PacingControllerTest,Pause)987*d9f75844SAndroid Build Coastguard Worker TEST_F(PacingControllerTest, Pause) {
988*d9f75844SAndroid Build Coastguard Worker uint32_t ssrc_low_priority = 12345;
989*d9f75844SAndroid Build Coastguard Worker uint32_t ssrc = 12346;
990*d9f75844SAndroid Build Coastguard Worker uint32_t ssrc_high_priority = 12347;
991*d9f75844SAndroid Build Coastguard Worker uint16_t sequence_number = 1234;
992*d9f75844SAndroid Build Coastguard Worker auto pacer = std::make_unique<PacingController>(&clock_, &callback_, trials_);
993*d9f75844SAndroid Build Coastguard Worker pacer->SetPacingRates(kTargetRate * kPaceMultiplier, DataRate::Zero());
994*d9f75844SAndroid Build Coastguard Worker
995*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(pacer->OldestPacketEnqueueTime().IsInfinite());
996*d9f75844SAndroid Build Coastguard Worker
997*d9f75844SAndroid Build Coastguard Worker ConsumeInitialBudget(pacer.get());
998*d9f75844SAndroid Build Coastguard Worker
999*d9f75844SAndroid Build Coastguard Worker pacer->Pause();
1000*d9f75844SAndroid Build Coastguard Worker
1001*d9f75844SAndroid Build Coastguard Worker int64_t capture_time_ms = clock_.TimeInMilliseconds();
1002*d9f75844SAndroid Build Coastguard Worker const size_t packets_to_send_per_interval =
1003*d9f75844SAndroid Build Coastguard Worker kTargetRate.bps() * kPaceMultiplier / (8 * 250 * 200);
1004*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < packets_to_send_per_interval; ++i) {
1005*d9f75844SAndroid Build Coastguard Worker pacer->EnqueuePacket(BuildPacket(RtpPacketMediaType::kVideo,
1006*d9f75844SAndroid Build Coastguard Worker ssrc_low_priority, sequence_number++,
1007*d9f75844SAndroid Build Coastguard Worker capture_time_ms, 250));
1008*d9f75844SAndroid Build Coastguard Worker pacer->EnqueuePacket(BuildPacket(RtpPacketMediaType::kRetransmission, ssrc,
1009*d9f75844SAndroid Build Coastguard Worker sequence_number++, capture_time_ms, 250));
1010*d9f75844SAndroid Build Coastguard Worker pacer->EnqueuePacket(BuildPacket(RtpPacketMediaType::kAudio,
1011*d9f75844SAndroid Build Coastguard Worker ssrc_high_priority, sequence_number++,
1012*d9f75844SAndroid Build Coastguard Worker capture_time_ms, 250));
1013*d9f75844SAndroid Build Coastguard Worker }
1014*d9f75844SAndroid Build Coastguard Worker clock_.AdvanceTimeMilliseconds(10000);
1015*d9f75844SAndroid Build Coastguard Worker int64_t second_capture_time_ms = clock_.TimeInMilliseconds();
1016*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < packets_to_send_per_interval; ++i) {
1017*d9f75844SAndroid Build Coastguard Worker pacer->EnqueuePacket(BuildPacket(RtpPacketMediaType::kVideo,
1018*d9f75844SAndroid Build Coastguard Worker ssrc_low_priority, sequence_number++,
1019*d9f75844SAndroid Build Coastguard Worker second_capture_time_ms, 250));
1020*d9f75844SAndroid Build Coastguard Worker pacer->EnqueuePacket(BuildPacket(RtpPacketMediaType::kRetransmission, ssrc,
1021*d9f75844SAndroid Build Coastguard Worker sequence_number++, second_capture_time_ms,
1022*d9f75844SAndroid Build Coastguard Worker 250));
1023*d9f75844SAndroid Build Coastguard Worker pacer->EnqueuePacket(BuildPacket(RtpPacketMediaType::kAudio,
1024*d9f75844SAndroid Build Coastguard Worker ssrc_high_priority, sequence_number++,
1025*d9f75844SAndroid Build Coastguard Worker second_capture_time_ms, 250));
1026*d9f75844SAndroid Build Coastguard Worker }
1027*d9f75844SAndroid Build Coastguard Worker
1028*d9f75844SAndroid Build Coastguard Worker // Expect everything to be queued.
1029*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(capture_time_ms, pacer->OldestPacketEnqueueTime().ms());
1030*d9f75844SAndroid Build Coastguard Worker
1031*d9f75844SAndroid Build Coastguard Worker // Process triggers keep-alive packet.
1032*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPadding).WillOnce([](size_t padding) {
1033*d9f75844SAndroid Build Coastguard Worker return padding;
1034*d9f75844SAndroid Build Coastguard Worker });
1035*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPacket(_, _, _, _, true)).Times(1);
1036*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
1037*d9f75844SAndroid Build Coastguard Worker
1038*d9f75844SAndroid Build Coastguard Worker // Verify no packets sent for the rest of the paused process interval.
1039*d9f75844SAndroid Build Coastguard Worker const TimeDelta kProcessInterval = TimeDelta::Millis(5);
1040*d9f75844SAndroid Build Coastguard Worker TimeDelta expected_time_until_send = PacingController::kPausedProcessInterval;
1041*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPadding).Times(0);
1042*d9f75844SAndroid Build Coastguard Worker while (expected_time_until_send >= kProcessInterval) {
1043*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
1044*d9f75844SAndroid Build Coastguard Worker clock_.AdvanceTime(kProcessInterval);
1045*d9f75844SAndroid Build Coastguard Worker expected_time_until_send -= kProcessInterval;
1046*d9f75844SAndroid Build Coastguard Worker }
1047*d9f75844SAndroid Build Coastguard Worker
1048*d9f75844SAndroid Build Coastguard Worker // New keep-alive packet.
1049*d9f75844SAndroid Build Coastguard Worker ::testing::Mock::VerifyAndClearExpectations(&callback_);
1050*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPadding).WillOnce([](size_t padding) {
1051*d9f75844SAndroid Build Coastguard Worker return padding;
1052*d9f75844SAndroid Build Coastguard Worker });
1053*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPacket(_, _, _, _, true)).Times(1);
1054*d9f75844SAndroid Build Coastguard Worker clock_.AdvanceTime(kProcessInterval);
1055*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
1056*d9f75844SAndroid Build Coastguard Worker ::testing::Mock::VerifyAndClearExpectations(&callback_);
1057*d9f75844SAndroid Build Coastguard Worker
1058*d9f75844SAndroid Build Coastguard Worker // Expect high prio packets to come out first followed by normal
1059*d9f75844SAndroid Build Coastguard Worker // prio packets and low prio packets (all in capture order).
1060*d9f75844SAndroid Build Coastguard Worker {
1061*d9f75844SAndroid Build Coastguard Worker ::testing::InSequence sequence;
1062*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_,
1063*d9f75844SAndroid Build Coastguard Worker SendPacket(ssrc_high_priority, _, capture_time_ms, _, _))
1064*d9f75844SAndroid Build Coastguard Worker .Times(packets_to_send_per_interval);
1065*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_,
1066*d9f75844SAndroid Build Coastguard Worker SendPacket(ssrc_high_priority, _, second_capture_time_ms, _, _))
1067*d9f75844SAndroid Build Coastguard Worker .Times(packets_to_send_per_interval);
1068*d9f75844SAndroid Build Coastguard Worker
1069*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < packets_to_send_per_interval; ++i) {
1070*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPacket(ssrc, _, capture_time_ms, _, _))
1071*d9f75844SAndroid Build Coastguard Worker .Times(1);
1072*d9f75844SAndroid Build Coastguard Worker }
1073*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < packets_to_send_per_interval; ++i) {
1074*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPacket(ssrc, _, second_capture_time_ms, _, _))
1075*d9f75844SAndroid Build Coastguard Worker .Times(1);
1076*d9f75844SAndroid Build Coastguard Worker }
1077*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < packets_to_send_per_interval; ++i) {
1078*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_,
1079*d9f75844SAndroid Build Coastguard Worker SendPacket(ssrc_low_priority, _, capture_time_ms, _, _))
1080*d9f75844SAndroid Build Coastguard Worker .Times(1);
1081*d9f75844SAndroid Build Coastguard Worker }
1082*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < packets_to_send_per_interval; ++i) {
1083*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPacket(ssrc_low_priority, _,
1084*d9f75844SAndroid Build Coastguard Worker second_capture_time_ms, _, _))
1085*d9f75844SAndroid Build Coastguard Worker .Times(1);
1086*d9f75844SAndroid Build Coastguard Worker }
1087*d9f75844SAndroid Build Coastguard Worker }
1088*d9f75844SAndroid Build Coastguard Worker pacer->Resume();
1089*d9f75844SAndroid Build Coastguard Worker while (pacer->QueueSizePackets() > 0) {
1090*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer->NextSendTime());
1091*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
1092*d9f75844SAndroid Build Coastguard Worker }
1093*d9f75844SAndroid Build Coastguard Worker
1094*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(pacer->OldestPacketEnqueueTime().IsInfinite());
1095*d9f75844SAndroid Build Coastguard Worker }
1096*d9f75844SAndroid Build Coastguard Worker
TEST_F(PacingControllerTest,InactiveFromStart)1097*d9f75844SAndroid Build Coastguard Worker TEST_F(PacingControllerTest, InactiveFromStart) {
1098*d9f75844SAndroid Build Coastguard Worker // Recreate the pacer without the inital time forwarding.
1099*d9f75844SAndroid Build Coastguard Worker auto pacer = std::make_unique<PacingController>(&clock_, &callback_, trials_);
1100*d9f75844SAndroid Build Coastguard Worker pacer->SetProbingEnabled(false);
1101*d9f75844SAndroid Build Coastguard Worker pacer->SetPacingRates(kTargetRate * kPaceMultiplier, kTargetRate);
1102*d9f75844SAndroid Build Coastguard Worker
1103*d9f75844SAndroid Build Coastguard Worker // No packets sent, there should be no keep-alives sent either.
1104*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPadding).Times(0);
1105*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPacket).Times(0);
1106*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
1107*d9f75844SAndroid Build Coastguard Worker
1108*d9f75844SAndroid Build Coastguard Worker const Timestamp start_time = clock_.CurrentTime();
1109*d9f75844SAndroid Build Coastguard Worker
1110*d9f75844SAndroid Build Coastguard Worker // Determine the margin need so we can advance to the last possible moment
1111*d9f75844SAndroid Build Coastguard Worker // that will not cause a process event.
1112*d9f75844SAndroid Build Coastguard Worker const TimeDelta time_margin =
1113*d9f75844SAndroid Build Coastguard Worker PacingController::kMinSleepTime + TimeDelta::Micros(1);
1114*d9f75844SAndroid Build Coastguard Worker
1115*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(pacer->NextSendTime() - start_time,
1116*d9f75844SAndroid Build Coastguard Worker PacingController::kPausedProcessInterval);
1117*d9f75844SAndroid Build Coastguard Worker clock_.AdvanceTime(PacingController::kPausedProcessInterval - time_margin);
1118*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
1119*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(pacer->NextSendTime() - start_time,
1120*d9f75844SAndroid Build Coastguard Worker PacingController::kPausedProcessInterval);
1121*d9f75844SAndroid Build Coastguard Worker
1122*d9f75844SAndroid Build Coastguard Worker clock_.AdvanceTime(time_margin);
1123*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
1124*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(pacer->NextSendTime() - start_time,
1125*d9f75844SAndroid Build Coastguard Worker 2 * PacingController::kPausedProcessInterval);
1126*d9f75844SAndroid Build Coastguard Worker }
1127*d9f75844SAndroid Build Coastguard Worker
TEST_F(PacingControllerTest,QueueTimeGrowsOverTime)1128*d9f75844SAndroid Build Coastguard Worker TEST_F(PacingControllerTest, QueueTimeGrowsOverTime) {
1129*d9f75844SAndroid Build Coastguard Worker uint32_t ssrc = 12346;
1130*d9f75844SAndroid Build Coastguard Worker uint16_t sequence_number = 1234;
1131*d9f75844SAndroid Build Coastguard Worker auto pacer = std::make_unique<PacingController>(&clock_, &callback_, trials_);
1132*d9f75844SAndroid Build Coastguard Worker pacer->SetPacingRates(kTargetRate * kPaceMultiplier, DataRate::Zero());
1133*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(pacer->OldestPacketEnqueueTime().IsInfinite());
1134*d9f75844SAndroid Build Coastguard Worker
1135*d9f75844SAndroid Build Coastguard Worker pacer->SetPacingRates(DataRate::BitsPerSec(30000 * kPaceMultiplier),
1136*d9f75844SAndroid Build Coastguard Worker DataRate::Zero());
1137*d9f75844SAndroid Build Coastguard Worker SendAndExpectPacket(pacer.get(), RtpPacketMediaType::kVideo, ssrc,
1138*d9f75844SAndroid Build Coastguard Worker sequence_number, clock_.TimeInMilliseconds(), 1200);
1139*d9f75844SAndroid Build Coastguard Worker
1140*d9f75844SAndroid Build Coastguard Worker clock_.AdvanceTimeMilliseconds(500);
1141*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(clock_.TimeInMilliseconds() - 500,
1142*d9f75844SAndroid Build Coastguard Worker pacer->OldestPacketEnqueueTime().ms());
1143*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
1144*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(pacer->OldestPacketEnqueueTime().IsInfinite());
1145*d9f75844SAndroid Build Coastguard Worker }
1146*d9f75844SAndroid Build Coastguard Worker
TEST_F(PacingControllerTest,ProbingWithInsertedPackets)1147*d9f75844SAndroid Build Coastguard Worker TEST_F(PacingControllerTest, ProbingWithInsertedPackets) {
1148*d9f75844SAndroid Build Coastguard Worker const size_t kPacketSize = 1200;
1149*d9f75844SAndroid Build Coastguard Worker const int kInitialBitrateBps = 300000;
1150*d9f75844SAndroid Build Coastguard Worker uint32_t ssrc = 12346;
1151*d9f75844SAndroid Build Coastguard Worker uint16_t sequence_number = 1234;
1152*d9f75844SAndroid Build Coastguard Worker
1153*d9f75844SAndroid Build Coastguard Worker PacingControllerProbing packet_sender;
1154*d9f75844SAndroid Build Coastguard Worker auto pacer =
1155*d9f75844SAndroid Build Coastguard Worker std::make_unique<PacingController>(&clock_, &packet_sender, trials_);
1156*d9f75844SAndroid Build Coastguard Worker std::vector<ProbeClusterConfig> probe_clusters = {
1157*d9f75844SAndroid Build Coastguard Worker {.at_time = clock_.CurrentTime(),
1158*d9f75844SAndroid Build Coastguard Worker .target_data_rate = kFirstClusterRate,
1159*d9f75844SAndroid Build Coastguard Worker .target_duration = TimeDelta::Millis(15),
1160*d9f75844SAndroid Build Coastguard Worker .target_probe_count = 5,
1161*d9f75844SAndroid Build Coastguard Worker .id = 0},
1162*d9f75844SAndroid Build Coastguard Worker {.at_time = clock_.CurrentTime(),
1163*d9f75844SAndroid Build Coastguard Worker .target_data_rate = kSecondClusterRate,
1164*d9f75844SAndroid Build Coastguard Worker .target_duration = TimeDelta::Millis(15),
1165*d9f75844SAndroid Build Coastguard Worker .target_probe_count = 5,
1166*d9f75844SAndroid Build Coastguard Worker .id = 1}};
1167*d9f75844SAndroid Build Coastguard Worker pacer->CreateProbeClusters(probe_clusters);
1168*d9f75844SAndroid Build Coastguard Worker pacer->SetPacingRates(
1169*d9f75844SAndroid Build Coastguard Worker DataRate::BitsPerSec(kInitialBitrateBps * kPaceMultiplier),
1170*d9f75844SAndroid Build Coastguard Worker DataRate::Zero());
1171*d9f75844SAndroid Build Coastguard Worker
1172*d9f75844SAndroid Build Coastguard Worker for (int i = 0; i < 10; ++i) {
1173*d9f75844SAndroid Build Coastguard Worker pacer->EnqueuePacket(BuildPacket(RtpPacketMediaType::kVideo, ssrc,
1174*d9f75844SAndroid Build Coastguard Worker sequence_number++,
1175*d9f75844SAndroid Build Coastguard Worker clock_.TimeInMilliseconds(), kPacketSize));
1176*d9f75844SAndroid Build Coastguard Worker }
1177*d9f75844SAndroid Build Coastguard Worker
1178*d9f75844SAndroid Build Coastguard Worker int64_t start = clock_.TimeInMilliseconds();
1179*d9f75844SAndroid Build Coastguard Worker while (packet_sender.packets_sent() < 5) {
1180*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer->NextSendTime());
1181*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
1182*d9f75844SAndroid Build Coastguard Worker }
1183*d9f75844SAndroid Build Coastguard Worker int packets_sent = packet_sender.packets_sent();
1184*d9f75844SAndroid Build Coastguard Worker // Validate first cluster bitrate. Note that we have to account for number
1185*d9f75844SAndroid Build Coastguard Worker // of intervals and hence (packets_sent - 1) on the first cluster.
1186*d9f75844SAndroid Build Coastguard Worker EXPECT_NEAR((packets_sent - 1) * kPacketSize * 8000 /
1187*d9f75844SAndroid Build Coastguard Worker (clock_.TimeInMilliseconds() - start),
1188*d9f75844SAndroid Build Coastguard Worker kFirstClusterRate.bps(), kProbingErrorMargin.bps());
1189*d9f75844SAndroid Build Coastguard Worker // Probing always starts with a small padding packet.
1190*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, packet_sender.padding_sent());
1191*d9f75844SAndroid Build Coastguard Worker
1192*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer->NextSendTime());
1193*d9f75844SAndroid Build Coastguard Worker start = clock_.TimeInMilliseconds();
1194*d9f75844SAndroid Build Coastguard Worker while (packet_sender.packets_sent() < 10) {
1195*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer->NextSendTime());
1196*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
1197*d9f75844SAndroid Build Coastguard Worker }
1198*d9f75844SAndroid Build Coastguard Worker packets_sent = packet_sender.packets_sent() - packets_sent;
1199*d9f75844SAndroid Build Coastguard Worker // Validate second cluster bitrate.
1200*d9f75844SAndroid Build Coastguard Worker EXPECT_NEAR((packets_sent - 1) * kPacketSize * 8000 /
1201*d9f75844SAndroid Build Coastguard Worker (clock_.TimeInMilliseconds() - start),
1202*d9f75844SAndroid Build Coastguard Worker kSecondClusterRate.bps(), kProbingErrorMargin.bps());
1203*d9f75844SAndroid Build Coastguard Worker }
1204*d9f75844SAndroid Build Coastguard Worker
TEST_F(PacingControllerTest,SkipsProbesWhenProcessIntervalTooLarge)1205*d9f75844SAndroid Build Coastguard Worker TEST_F(PacingControllerTest, SkipsProbesWhenProcessIntervalTooLarge) {
1206*d9f75844SAndroid Build Coastguard Worker const size_t kPacketSize = 1200;
1207*d9f75844SAndroid Build Coastguard Worker const int kInitialBitrateBps = 300000;
1208*d9f75844SAndroid Build Coastguard Worker const uint32_t ssrc = 12346;
1209*d9f75844SAndroid Build Coastguard Worker const int kProbeClusterId = 3;
1210*d9f75844SAndroid Build Coastguard Worker
1211*d9f75844SAndroid Build Coastguard Worker uint16_t sequence_number = 1234;
1212*d9f75844SAndroid Build Coastguard Worker
1213*d9f75844SAndroid Build Coastguard Worker PacingControllerProbing packet_sender;
1214*d9f75844SAndroid Build Coastguard Worker
1215*d9f75844SAndroid Build Coastguard Worker const test::ExplicitKeyValueConfig trials(
1216*d9f75844SAndroid Build Coastguard Worker "WebRTC-Bwe-ProbingBehavior/max_probe_delay:2ms/");
1217*d9f75844SAndroid Build Coastguard Worker auto pacer =
1218*d9f75844SAndroid Build Coastguard Worker std::make_unique<PacingController>(&clock_, &packet_sender, trials);
1219*d9f75844SAndroid Build Coastguard Worker pacer->SetPacingRates(
1220*d9f75844SAndroid Build Coastguard Worker DataRate::BitsPerSec(kInitialBitrateBps * kPaceMultiplier),
1221*d9f75844SAndroid Build Coastguard Worker DataRate::BitsPerSec(kInitialBitrateBps));
1222*d9f75844SAndroid Build Coastguard Worker
1223*d9f75844SAndroid Build Coastguard Worker for (int i = 0; i < 10; ++i) {
1224*d9f75844SAndroid Build Coastguard Worker pacer->EnqueuePacket(BuildPacket(RtpPacketMediaType::kVideo, ssrc,
1225*d9f75844SAndroid Build Coastguard Worker sequence_number++,
1226*d9f75844SAndroid Build Coastguard Worker clock_.TimeInMilliseconds(), kPacketSize));
1227*d9f75844SAndroid Build Coastguard Worker }
1228*d9f75844SAndroid Build Coastguard Worker while (pacer->QueueSizePackets() > 0) {
1229*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer->NextSendTime());
1230*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
1231*d9f75844SAndroid Build Coastguard Worker }
1232*d9f75844SAndroid Build Coastguard Worker
1233*d9f75844SAndroid Build Coastguard Worker // Probe at a very high rate.
1234*d9f75844SAndroid Build Coastguard Worker std::vector<ProbeClusterConfig> probe_clusters = {
1235*d9f75844SAndroid Build Coastguard Worker {.at_time = clock_.CurrentTime(),
1236*d9f75844SAndroid Build Coastguard Worker .target_data_rate = DataRate::KilobitsPerSec(10000), // 10 Mbps,
1237*d9f75844SAndroid Build Coastguard Worker .target_duration = TimeDelta::Millis(15),
1238*d9f75844SAndroid Build Coastguard Worker .target_probe_count = 5,
1239*d9f75844SAndroid Build Coastguard Worker .id = kProbeClusterId}};
1240*d9f75844SAndroid Build Coastguard Worker pacer->CreateProbeClusters(probe_clusters);
1241*d9f75844SAndroid Build Coastguard Worker
1242*d9f75844SAndroid Build Coastguard Worker // We need one packet to start the probe.
1243*d9f75844SAndroid Build Coastguard Worker pacer->EnqueuePacket(BuildPacket(RtpPacketMediaType::kVideo, ssrc,
1244*d9f75844SAndroid Build Coastguard Worker sequence_number++,
1245*d9f75844SAndroid Build Coastguard Worker clock_.TimeInMilliseconds(), kPacketSize));
1246*d9f75844SAndroid Build Coastguard Worker const int packets_sent_before_probe = packet_sender.packets_sent();
1247*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer->NextSendTime());
1248*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
1249*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(packet_sender.packets_sent(), packets_sent_before_probe + 1);
1250*d9f75844SAndroid Build Coastguard Worker
1251*d9f75844SAndroid Build Coastguard Worker // Figure out how long between probe packets.
1252*d9f75844SAndroid Build Coastguard Worker Timestamp start_time = clock_.CurrentTime();
1253*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer->NextSendTime());
1254*d9f75844SAndroid Build Coastguard Worker TimeDelta time_between_probes = clock_.CurrentTime() - start_time;
1255*d9f75844SAndroid Build Coastguard Worker // Advance that distance again + 1ms.
1256*d9f75844SAndroid Build Coastguard Worker clock_.AdvanceTime(time_between_probes);
1257*d9f75844SAndroid Build Coastguard Worker
1258*d9f75844SAndroid Build Coastguard Worker // Send second probe packet.
1259*d9f75844SAndroid Build Coastguard Worker pacer->EnqueuePacket(BuildPacket(RtpPacketMediaType::kVideo, ssrc,
1260*d9f75844SAndroid Build Coastguard Worker sequence_number++,
1261*d9f75844SAndroid Build Coastguard Worker clock_.TimeInMilliseconds(), kPacketSize));
1262*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
1263*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(packet_sender.packets_sent(), packets_sent_before_probe + 2);
1264*d9f75844SAndroid Build Coastguard Worker PacedPacketInfo last_pacing_info = packet_sender.last_pacing_info();
1265*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(last_pacing_info.probe_cluster_id, kProbeClusterId);
1266*d9f75844SAndroid Build Coastguard Worker
1267*d9f75844SAndroid Build Coastguard Worker // We're exactly where we should be for the next probe.
1268*d9f75844SAndroid Build Coastguard Worker const Timestamp probe_time = clock_.CurrentTime();
1269*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(pacer->NextSendTime(), clock_.CurrentTime());
1270*d9f75844SAndroid Build Coastguard Worker
1271*d9f75844SAndroid Build Coastguard Worker BitrateProberConfig probing_config(&trials);
1272*d9f75844SAndroid Build Coastguard Worker EXPECT_GT(probing_config.max_probe_delay.Get(), TimeDelta::Zero());
1273*d9f75844SAndroid Build Coastguard Worker // Advance to within max probe delay, should still return same target.
1274*d9f75844SAndroid Build Coastguard Worker clock_.AdvanceTime(probing_config.max_probe_delay.Get());
1275*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(pacer->NextSendTime(), probe_time);
1276*d9f75844SAndroid Build Coastguard Worker
1277*d9f75844SAndroid Build Coastguard Worker // Too high probe delay, drop it!
1278*d9f75844SAndroid Build Coastguard Worker clock_.AdvanceTime(TimeDelta::Micros(1));
1279*d9f75844SAndroid Build Coastguard Worker
1280*d9f75844SAndroid Build Coastguard Worker int packets_sent_before_timeout = packet_sender.total_packets_sent();
1281*d9f75844SAndroid Build Coastguard Worker // Expected next process time is unchanged, but calling should not
1282*d9f75844SAndroid Build Coastguard Worker // generate new packets.
1283*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(pacer->NextSendTime(), probe_time);
1284*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
1285*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(packet_sender.total_packets_sent(), packets_sent_before_timeout);
1286*d9f75844SAndroid Build Coastguard Worker
1287*d9f75844SAndroid Build Coastguard Worker // Next packet sent is not part of probe.
1288*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer->NextSendTime());
1289*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
1290*d9f75844SAndroid Build Coastguard Worker const int expected_probe_id = PacedPacketInfo::kNotAProbe;
1291*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(packet_sender.last_pacing_info().probe_cluster_id,
1292*d9f75844SAndroid Build Coastguard Worker expected_probe_id);
1293*d9f75844SAndroid Build Coastguard Worker }
1294*d9f75844SAndroid Build Coastguard Worker
TEST_F(PacingControllerTest,ProbingWithPaddingSupport)1295*d9f75844SAndroid Build Coastguard Worker TEST_F(PacingControllerTest, ProbingWithPaddingSupport) {
1296*d9f75844SAndroid Build Coastguard Worker const size_t kPacketSize = 1200;
1297*d9f75844SAndroid Build Coastguard Worker const int kInitialBitrateBps = 300000;
1298*d9f75844SAndroid Build Coastguard Worker uint32_t ssrc = 12346;
1299*d9f75844SAndroid Build Coastguard Worker uint16_t sequence_number = 1234;
1300*d9f75844SAndroid Build Coastguard Worker
1301*d9f75844SAndroid Build Coastguard Worker PacingControllerProbing packet_sender;
1302*d9f75844SAndroid Build Coastguard Worker auto pacer =
1303*d9f75844SAndroid Build Coastguard Worker std::make_unique<PacingController>(&clock_, &packet_sender, trials_);
1304*d9f75844SAndroid Build Coastguard Worker std::vector<ProbeClusterConfig> probe_clusters = {
1305*d9f75844SAndroid Build Coastguard Worker {.at_time = clock_.CurrentTime(),
1306*d9f75844SAndroid Build Coastguard Worker .target_data_rate = kFirstClusterRate,
1307*d9f75844SAndroid Build Coastguard Worker .target_duration = TimeDelta::Millis(15),
1308*d9f75844SAndroid Build Coastguard Worker .target_probe_count = 5,
1309*d9f75844SAndroid Build Coastguard Worker .id = 0}};
1310*d9f75844SAndroid Build Coastguard Worker pacer->CreateProbeClusters(probe_clusters);
1311*d9f75844SAndroid Build Coastguard Worker
1312*d9f75844SAndroid Build Coastguard Worker pacer->SetPacingRates(
1313*d9f75844SAndroid Build Coastguard Worker DataRate::BitsPerSec(kInitialBitrateBps * kPaceMultiplier),
1314*d9f75844SAndroid Build Coastguard Worker DataRate::Zero());
1315*d9f75844SAndroid Build Coastguard Worker
1316*d9f75844SAndroid Build Coastguard Worker for (int i = 0; i < 3; ++i) {
1317*d9f75844SAndroid Build Coastguard Worker pacer->EnqueuePacket(BuildPacket(RtpPacketMediaType::kVideo, ssrc,
1318*d9f75844SAndroid Build Coastguard Worker sequence_number++,
1319*d9f75844SAndroid Build Coastguard Worker clock_.TimeInMilliseconds(), kPacketSize));
1320*d9f75844SAndroid Build Coastguard Worker }
1321*d9f75844SAndroid Build Coastguard Worker
1322*d9f75844SAndroid Build Coastguard Worker int64_t start = clock_.TimeInMilliseconds();
1323*d9f75844SAndroid Build Coastguard Worker int process_count = 0;
1324*d9f75844SAndroid Build Coastguard Worker while (process_count < 5) {
1325*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer->NextSendTime());
1326*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
1327*d9f75844SAndroid Build Coastguard Worker ++process_count;
1328*d9f75844SAndroid Build Coastguard Worker }
1329*d9f75844SAndroid Build Coastguard Worker int packets_sent = packet_sender.packets_sent();
1330*d9f75844SAndroid Build Coastguard Worker int padding_sent = packet_sender.padding_sent();
1331*d9f75844SAndroid Build Coastguard Worker EXPECT_GT(packets_sent, 0);
1332*d9f75844SAndroid Build Coastguard Worker EXPECT_GT(padding_sent, 0);
1333*d9f75844SAndroid Build Coastguard Worker // Note that the number of intervals here for kPacketSize is
1334*d9f75844SAndroid Build Coastguard Worker // packets_sent due to padding in the same cluster.
1335*d9f75844SAndroid Build Coastguard Worker EXPECT_NEAR((packets_sent * kPacketSize * 8000 + padding_sent) /
1336*d9f75844SAndroid Build Coastguard Worker (clock_.TimeInMilliseconds() - start),
1337*d9f75844SAndroid Build Coastguard Worker kFirstClusterRate.bps(), kProbingErrorMargin.bps());
1338*d9f75844SAndroid Build Coastguard Worker }
1339*d9f75844SAndroid Build Coastguard Worker
TEST_F(PacingControllerTest,PaddingOveruse)1340*d9f75844SAndroid Build Coastguard Worker TEST_F(PacingControllerTest, PaddingOveruse) {
1341*d9f75844SAndroid Build Coastguard Worker uint32_t ssrc = 12346;
1342*d9f75844SAndroid Build Coastguard Worker uint16_t sequence_number = 1234;
1343*d9f75844SAndroid Build Coastguard Worker const size_t kPacketSize = 1200;
1344*d9f75844SAndroid Build Coastguard Worker auto pacer = std::make_unique<PacingController>(&clock_, &callback_, trials_);
1345*d9f75844SAndroid Build Coastguard Worker pacer->SetPacingRates(kTargetRate * kPaceMultiplier, DataRate::Zero());
1346*d9f75844SAndroid Build Coastguard Worker
1347*d9f75844SAndroid Build Coastguard Worker // Initially no padding rate.
1348*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
1349*d9f75844SAndroid Build Coastguard Worker pacer->SetPacingRates(DataRate::BitsPerSec(60000 * kPaceMultiplier),
1350*d9f75844SAndroid Build Coastguard Worker DataRate::Zero());
1351*d9f75844SAndroid Build Coastguard Worker
1352*d9f75844SAndroid Build Coastguard Worker SendAndExpectPacket(pacer.get(), RtpPacketMediaType::kVideo, ssrc,
1353*d9f75844SAndroid Build Coastguard Worker sequence_number++, clock_.TimeInMilliseconds(),
1354*d9f75844SAndroid Build Coastguard Worker kPacketSize);
1355*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
1356*d9f75844SAndroid Build Coastguard Worker
1357*d9f75844SAndroid Build Coastguard Worker // Add 30kbit padding. When increasing budget, media budget will increase from
1358*d9f75844SAndroid Build Coastguard Worker // negative (overuse) while padding budget will increase from 0.
1359*d9f75844SAndroid Build Coastguard Worker clock_.AdvanceTimeMilliseconds(5);
1360*d9f75844SAndroid Build Coastguard Worker pacer->SetPacingRates(DataRate::BitsPerSec(60000 * kPaceMultiplier),
1361*d9f75844SAndroid Build Coastguard Worker DataRate::BitsPerSec(30000));
1362*d9f75844SAndroid Build Coastguard Worker
1363*d9f75844SAndroid Build Coastguard Worker SendAndExpectPacket(pacer.get(), RtpPacketMediaType::kVideo, ssrc,
1364*d9f75844SAndroid Build Coastguard Worker sequence_number++, clock_.TimeInMilliseconds(),
1365*d9f75844SAndroid Build Coastguard Worker kPacketSize);
1366*d9f75844SAndroid Build Coastguard Worker EXPECT_LT(TimeDelta::Millis(5), pacer->ExpectedQueueTime());
1367*d9f75844SAndroid Build Coastguard Worker // Don't send padding if queue is non-empty, even if padding budget > 0.
1368*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPadding).Times(0);
1369*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer->NextSendTime());
1370*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
1371*d9f75844SAndroid Build Coastguard Worker }
1372*d9f75844SAndroid Build Coastguard Worker
TEST_F(PacingControllerTest,ProbeClusterId)1373*d9f75844SAndroid Build Coastguard Worker TEST_F(PacingControllerTest, ProbeClusterId) {
1374*d9f75844SAndroid Build Coastguard Worker MockPacketSender callback;
1375*d9f75844SAndroid Build Coastguard Worker uint32_t ssrc = 12346;
1376*d9f75844SAndroid Build Coastguard Worker uint16_t sequence_number = 1234;
1377*d9f75844SAndroid Build Coastguard Worker const size_t kPacketSize = 1200;
1378*d9f75844SAndroid Build Coastguard Worker
1379*d9f75844SAndroid Build Coastguard Worker auto pacer = std::make_unique<PacingController>(&clock_, &callback, trials_);
1380*d9f75844SAndroid Build Coastguard Worker pacer->CreateProbeClusters(std::vector<ProbeClusterConfig>(
1381*d9f75844SAndroid Build Coastguard Worker {{.at_time = clock_.CurrentTime(),
1382*d9f75844SAndroid Build Coastguard Worker .target_data_rate = kFirstClusterRate,
1383*d9f75844SAndroid Build Coastguard Worker .target_duration = TimeDelta::Millis(15),
1384*d9f75844SAndroid Build Coastguard Worker .target_probe_count = 5,
1385*d9f75844SAndroid Build Coastguard Worker .id = 0},
1386*d9f75844SAndroid Build Coastguard Worker {.at_time = clock_.CurrentTime(),
1387*d9f75844SAndroid Build Coastguard Worker .target_data_rate = kSecondClusterRate,
1388*d9f75844SAndroid Build Coastguard Worker .target_duration = TimeDelta::Millis(15),
1389*d9f75844SAndroid Build Coastguard Worker .target_probe_count = 5,
1390*d9f75844SAndroid Build Coastguard Worker .id = 1}}));
1391*d9f75844SAndroid Build Coastguard Worker pacer->SetPacingRates(kTargetRate * kPaceMultiplier, kTargetRate);
1392*d9f75844SAndroid Build Coastguard Worker pacer->SetProbingEnabled(true);
1393*d9f75844SAndroid Build Coastguard Worker for (int i = 0; i < 10; ++i) {
1394*d9f75844SAndroid Build Coastguard Worker pacer->EnqueuePacket(BuildPacket(RtpPacketMediaType::kVideo, ssrc,
1395*d9f75844SAndroid Build Coastguard Worker sequence_number++,
1396*d9f75844SAndroid Build Coastguard Worker clock_.TimeInMilliseconds(), kPacketSize));
1397*d9f75844SAndroid Build Coastguard Worker }
1398*d9f75844SAndroid Build Coastguard Worker
1399*d9f75844SAndroid Build Coastguard Worker // First probing cluster.
1400*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback,
1401*d9f75844SAndroid Build Coastguard Worker SendPacket(_, Field(&PacedPacketInfo::probe_cluster_id, 0)))
1402*d9f75844SAndroid Build Coastguard Worker .Times(5);
1403*d9f75844SAndroid Build Coastguard Worker
1404*d9f75844SAndroid Build Coastguard Worker for (int i = 0; i < 5; ++i) {
1405*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer->NextSendTime());
1406*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
1407*d9f75844SAndroid Build Coastguard Worker }
1408*d9f75844SAndroid Build Coastguard Worker
1409*d9f75844SAndroid Build Coastguard Worker // Second probing cluster.
1410*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback,
1411*d9f75844SAndroid Build Coastguard Worker SendPacket(_, Field(&PacedPacketInfo::probe_cluster_id, 1)))
1412*d9f75844SAndroid Build Coastguard Worker .Times(5);
1413*d9f75844SAndroid Build Coastguard Worker
1414*d9f75844SAndroid Build Coastguard Worker for (int i = 0; i < 5; ++i) {
1415*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer->NextSendTime());
1416*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
1417*d9f75844SAndroid Build Coastguard Worker }
1418*d9f75844SAndroid Build Coastguard Worker
1419*d9f75844SAndroid Build Coastguard Worker // Needed for the Field comparer below.
1420*d9f75844SAndroid Build Coastguard Worker const int kNotAProbe = PacedPacketInfo::kNotAProbe;
1421*d9f75844SAndroid Build Coastguard Worker // No more probing packets.
1422*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback, GeneratePadding).WillOnce([&](DataSize padding_size) {
1423*d9f75844SAndroid Build Coastguard Worker std::vector<std::unique_ptr<RtpPacketToSend>> padding_packets;
1424*d9f75844SAndroid Build Coastguard Worker padding_packets.emplace_back(
1425*d9f75844SAndroid Build Coastguard Worker BuildPacket(RtpPacketMediaType::kPadding, ssrc, sequence_number++,
1426*d9f75844SAndroid Build Coastguard Worker clock_.TimeInMilliseconds(), padding_size.bytes()));
1427*d9f75844SAndroid Build Coastguard Worker return padding_packets;
1428*d9f75844SAndroid Build Coastguard Worker });
1429*d9f75844SAndroid Build Coastguard Worker bool non_probe_packet_seen = false;
1430*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback, SendPacket)
1431*d9f75844SAndroid Build Coastguard Worker .WillOnce([&](std::unique_ptr<RtpPacketToSend> packet,
1432*d9f75844SAndroid Build Coastguard Worker const PacedPacketInfo& cluster_info) {
1433*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(cluster_info.probe_cluster_id, kNotAProbe);
1434*d9f75844SAndroid Build Coastguard Worker non_probe_packet_seen = true;
1435*d9f75844SAndroid Build Coastguard Worker });
1436*d9f75844SAndroid Build Coastguard Worker while (!non_probe_packet_seen) {
1437*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer->NextSendTime());
1438*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
1439*d9f75844SAndroid Build Coastguard Worker }
1440*d9f75844SAndroid Build Coastguard Worker }
1441*d9f75844SAndroid Build Coastguard Worker
TEST_F(PacingControllerTest,OwnedPacketPrioritizedOnType)1442*d9f75844SAndroid Build Coastguard Worker TEST_F(PacingControllerTest, OwnedPacketPrioritizedOnType) {
1443*d9f75844SAndroid Build Coastguard Worker MockPacketSender callback;
1444*d9f75844SAndroid Build Coastguard Worker uint32_t ssrc = 123;
1445*d9f75844SAndroid Build Coastguard Worker
1446*d9f75844SAndroid Build Coastguard Worker auto pacer = std::make_unique<PacingController>(&clock_, &callback, trials_);
1447*d9f75844SAndroid Build Coastguard Worker pacer->SetPacingRates(kTargetRate * kPaceMultiplier, DataRate::Zero());
1448*d9f75844SAndroid Build Coastguard Worker
1449*d9f75844SAndroid Build Coastguard Worker // Insert a packet of each type, from low to high priority. Since priority
1450*d9f75844SAndroid Build Coastguard Worker // is weighted higher than insert order, these should come out of the pacer
1451*d9f75844SAndroid Build Coastguard Worker // in backwards order with the exception of FEC and Video.
1452*d9f75844SAndroid Build Coastguard Worker
1453*d9f75844SAndroid Build Coastguard Worker for (RtpPacketMediaType type :
1454*d9f75844SAndroid Build Coastguard Worker {RtpPacketMediaType::kPadding,
1455*d9f75844SAndroid Build Coastguard Worker RtpPacketMediaType::kForwardErrorCorrection, RtpPacketMediaType::kVideo,
1456*d9f75844SAndroid Build Coastguard Worker RtpPacketMediaType::kRetransmission, RtpPacketMediaType::kAudio}) {
1457*d9f75844SAndroid Build Coastguard Worker pacer->EnqueuePacket(BuildPacket(type, ++ssrc, /*sequence_number=*/123,
1458*d9f75844SAndroid Build Coastguard Worker clock_.TimeInMilliseconds(),
1459*d9f75844SAndroid Build Coastguard Worker /*size=*/150));
1460*d9f75844SAndroid Build Coastguard Worker }
1461*d9f75844SAndroid Build Coastguard Worker
1462*d9f75844SAndroid Build Coastguard Worker ::testing::InSequence seq;
1463*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback,
1464*d9f75844SAndroid Build Coastguard Worker SendPacket(Pointee(Property(&RtpPacketToSend::packet_type,
1465*d9f75844SAndroid Build Coastguard Worker RtpPacketMediaType::kAudio)),
1466*d9f75844SAndroid Build Coastguard Worker _));
1467*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback,
1468*d9f75844SAndroid Build Coastguard Worker SendPacket(Pointee(Property(&RtpPacketToSend::packet_type,
1469*d9f75844SAndroid Build Coastguard Worker RtpPacketMediaType::kRetransmission)),
1470*d9f75844SAndroid Build Coastguard Worker _));
1471*d9f75844SAndroid Build Coastguard Worker
1472*d9f75844SAndroid Build Coastguard Worker // FEC and video actually have the same priority, so will come out in
1473*d9f75844SAndroid Build Coastguard Worker // insertion order.
1474*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(
1475*d9f75844SAndroid Build Coastguard Worker callback,
1476*d9f75844SAndroid Build Coastguard Worker SendPacket(Pointee(Property(&RtpPacketToSend::packet_type,
1477*d9f75844SAndroid Build Coastguard Worker RtpPacketMediaType::kForwardErrorCorrection)),
1478*d9f75844SAndroid Build Coastguard Worker _));
1479*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback,
1480*d9f75844SAndroid Build Coastguard Worker SendPacket(Pointee(Property(&RtpPacketToSend::packet_type,
1481*d9f75844SAndroid Build Coastguard Worker RtpPacketMediaType::kVideo)),
1482*d9f75844SAndroid Build Coastguard Worker _));
1483*d9f75844SAndroid Build Coastguard Worker
1484*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback,
1485*d9f75844SAndroid Build Coastguard Worker SendPacket(Pointee(Property(&RtpPacketToSend::packet_type,
1486*d9f75844SAndroid Build Coastguard Worker RtpPacketMediaType::kPadding)),
1487*d9f75844SAndroid Build Coastguard Worker _));
1488*d9f75844SAndroid Build Coastguard Worker
1489*d9f75844SAndroid Build Coastguard Worker while (pacer->QueueSizePackets() > 0) {
1490*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer->NextSendTime());
1491*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
1492*d9f75844SAndroid Build Coastguard Worker }
1493*d9f75844SAndroid Build Coastguard Worker }
1494*d9f75844SAndroid Build Coastguard Worker
TEST_F(PacingControllerTest,SmallFirstProbePacket)1495*d9f75844SAndroid Build Coastguard Worker TEST_F(PacingControllerTest, SmallFirstProbePacket) {
1496*d9f75844SAndroid Build Coastguard Worker MockPacketSender callback;
1497*d9f75844SAndroid Build Coastguard Worker auto pacer = std::make_unique<PacingController>(&clock_, &callback, trials_);
1498*d9f75844SAndroid Build Coastguard Worker std::vector<ProbeClusterConfig> probe_clusters = {
1499*d9f75844SAndroid Build Coastguard Worker {.at_time = clock_.CurrentTime(),
1500*d9f75844SAndroid Build Coastguard Worker .target_data_rate = kFirstClusterRate,
1501*d9f75844SAndroid Build Coastguard Worker .target_duration = TimeDelta::Millis(15),
1502*d9f75844SAndroid Build Coastguard Worker .target_probe_count = 5,
1503*d9f75844SAndroid Build Coastguard Worker .id = 0}};
1504*d9f75844SAndroid Build Coastguard Worker pacer->CreateProbeClusters(probe_clusters);
1505*d9f75844SAndroid Build Coastguard Worker
1506*d9f75844SAndroid Build Coastguard Worker pacer->SetPacingRates(kTargetRate * kPaceMultiplier, DataRate::Zero());
1507*d9f75844SAndroid Build Coastguard Worker
1508*d9f75844SAndroid Build Coastguard Worker // Add high prio media.
1509*d9f75844SAndroid Build Coastguard Worker pacer->EnqueuePacket(audio_.BuildNextPacket(234));
1510*d9f75844SAndroid Build Coastguard Worker
1511*d9f75844SAndroid Build Coastguard Worker // Expect small padding packet to be requested.
1512*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback, GeneratePadding(DataSize::Bytes(1)))
1513*d9f75844SAndroid Build Coastguard Worker .WillOnce([&](DataSize padding_size) {
1514*d9f75844SAndroid Build Coastguard Worker std::vector<std::unique_ptr<RtpPacketToSend>> padding_packets;
1515*d9f75844SAndroid Build Coastguard Worker padding_packets.emplace_back(
1516*d9f75844SAndroid Build Coastguard Worker BuildPacket(RtpPacketMediaType::kPadding, kAudioSsrc, 1,
1517*d9f75844SAndroid Build Coastguard Worker clock_.TimeInMilliseconds(), 1));
1518*d9f75844SAndroid Build Coastguard Worker return padding_packets;
1519*d9f75844SAndroid Build Coastguard Worker });
1520*d9f75844SAndroid Build Coastguard Worker
1521*d9f75844SAndroid Build Coastguard Worker size_t packets_sent = 0;
1522*d9f75844SAndroid Build Coastguard Worker bool media_seen = false;
1523*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback, SendPacket)
1524*d9f75844SAndroid Build Coastguard Worker .Times(AnyNumber())
1525*d9f75844SAndroid Build Coastguard Worker .WillRepeatedly([&](std::unique_ptr<RtpPacketToSend> packet,
1526*d9f75844SAndroid Build Coastguard Worker const PacedPacketInfo& cluster_info) {
1527*d9f75844SAndroid Build Coastguard Worker if (packets_sent == 0) {
1528*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(packet->packet_type(), RtpPacketMediaType::kPadding);
1529*d9f75844SAndroid Build Coastguard Worker } else {
1530*d9f75844SAndroid Build Coastguard Worker if (packet->packet_type() == RtpPacketMediaType::kAudio) {
1531*d9f75844SAndroid Build Coastguard Worker media_seen = true;
1532*d9f75844SAndroid Build Coastguard Worker }
1533*d9f75844SAndroid Build Coastguard Worker }
1534*d9f75844SAndroid Build Coastguard Worker packets_sent++;
1535*d9f75844SAndroid Build Coastguard Worker });
1536*d9f75844SAndroid Build Coastguard Worker while (!media_seen) {
1537*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
1538*d9f75844SAndroid Build Coastguard Worker clock_.AdvanceTimeMilliseconds(5);
1539*d9f75844SAndroid Build Coastguard Worker }
1540*d9f75844SAndroid Build Coastguard Worker }
1541*d9f75844SAndroid Build Coastguard Worker
TEST_F(PacingControllerTest,TaskLate)1542*d9f75844SAndroid Build Coastguard Worker TEST_F(PacingControllerTest, TaskLate) {
1543*d9f75844SAndroid Build Coastguard Worker // Set a low send rate to more easily test timing issues.
1544*d9f75844SAndroid Build Coastguard Worker DataRate kSendRate = DataRate::KilobitsPerSec(30);
1545*d9f75844SAndroid Build Coastguard Worker auto pacer = std::make_unique<PacingController>(&clock_, &callback_, trials_);
1546*d9f75844SAndroid Build Coastguard Worker pacer->SetPacingRates(kSendRate, DataRate::Zero());
1547*d9f75844SAndroid Build Coastguard Worker
1548*d9f75844SAndroid Build Coastguard Worker // Add four packets of equal size and priority.
1549*d9f75844SAndroid Build Coastguard Worker pacer->EnqueuePacket(video_.BuildNextPacket(1000));
1550*d9f75844SAndroid Build Coastguard Worker pacer->EnqueuePacket(video_.BuildNextPacket(1000));
1551*d9f75844SAndroid Build Coastguard Worker pacer->EnqueuePacket(video_.BuildNextPacket(1000));
1552*d9f75844SAndroid Build Coastguard Worker pacer->EnqueuePacket(video_.BuildNextPacket(1000));
1553*d9f75844SAndroid Build Coastguard Worker
1554*d9f75844SAndroid Build Coastguard Worker // Process packets, only first should be sent.
1555*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPacket).Times(1);
1556*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
1557*d9f75844SAndroid Build Coastguard Worker
1558*d9f75844SAndroid Build Coastguard Worker Timestamp next_send_time = pacer->NextSendTime();
1559*d9f75844SAndroid Build Coastguard Worker // Determine time between packets (ca 62ms)
1560*d9f75844SAndroid Build Coastguard Worker const TimeDelta time_between_packets = next_send_time - clock_.CurrentTime();
1561*d9f75844SAndroid Build Coastguard Worker
1562*d9f75844SAndroid Build Coastguard Worker // Simulate a late process call, executed just before we allow sending the
1563*d9f75844SAndroid Build Coastguard Worker // fourth packet.
1564*d9f75844SAndroid Build Coastguard Worker const TimeDelta kOffset = TimeDelta::Millis(1);
1565*d9f75844SAndroid Build Coastguard Worker clock_.AdvanceTime((time_between_packets * 3) - kOffset);
1566*d9f75844SAndroid Build Coastguard Worker
1567*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPacket).Times(2);
1568*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
1569*d9f75844SAndroid Build Coastguard Worker
1570*d9f75844SAndroid Build Coastguard Worker // Check that next scheduled send time is in ca 1ms.
1571*d9f75844SAndroid Build Coastguard Worker next_send_time = pacer->NextSendTime();
1572*d9f75844SAndroid Build Coastguard Worker const TimeDelta time_left = next_send_time - clock_.CurrentTime();
1573*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(time_left.RoundTo(TimeDelta::Millis(1)), kOffset);
1574*d9f75844SAndroid Build Coastguard Worker
1575*d9f75844SAndroid Build Coastguard Worker clock_.AdvanceTime(time_left);
1576*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPacket);
1577*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
1578*d9f75844SAndroid Build Coastguard Worker }
1579*d9f75844SAndroid Build Coastguard Worker
TEST_F(PacingControllerTest,NoProbingWhilePaused)1580*d9f75844SAndroid Build Coastguard Worker TEST_F(PacingControllerTest, NoProbingWhilePaused) {
1581*d9f75844SAndroid Build Coastguard Worker uint32_t ssrc = 12345;
1582*d9f75844SAndroid Build Coastguard Worker uint16_t sequence_number = 1234;
1583*d9f75844SAndroid Build Coastguard Worker auto pacer = std::make_unique<PacingController>(&clock_, &callback_, trials_);
1584*d9f75844SAndroid Build Coastguard Worker pacer->SetProbingEnabled(true);
1585*d9f75844SAndroid Build Coastguard Worker pacer->SetPacingRates(kTargetRate * kPaceMultiplier, DataRate::Zero());
1586*d9f75844SAndroid Build Coastguard Worker pacer->CreateProbeClusters(std::vector<ProbeClusterConfig>(
1587*d9f75844SAndroid Build Coastguard Worker {{.at_time = clock_.CurrentTime(),
1588*d9f75844SAndroid Build Coastguard Worker .target_data_rate = kFirstClusterRate,
1589*d9f75844SAndroid Build Coastguard Worker .target_duration = TimeDelta::Millis(15),
1590*d9f75844SAndroid Build Coastguard Worker .target_probe_count = 5,
1591*d9f75844SAndroid Build Coastguard Worker .id = 0},
1592*d9f75844SAndroid Build Coastguard Worker {.at_time = clock_.CurrentTime(),
1593*d9f75844SAndroid Build Coastguard Worker .target_data_rate = kSecondClusterRate,
1594*d9f75844SAndroid Build Coastguard Worker .target_duration = TimeDelta::Millis(15),
1595*d9f75844SAndroid Build Coastguard Worker .target_probe_count = 5,
1596*d9f75844SAndroid Build Coastguard Worker .id = 1}}));
1597*d9f75844SAndroid Build Coastguard Worker
1598*d9f75844SAndroid Build Coastguard Worker // Send at least one packet so probing can initate.
1599*d9f75844SAndroid Build Coastguard Worker SendAndExpectPacket(pacer.get(), RtpPacketMediaType::kVideo, ssrc,
1600*d9f75844SAndroid Build Coastguard Worker sequence_number, clock_.TimeInMilliseconds(), 250);
1601*d9f75844SAndroid Build Coastguard Worker while (pacer->QueueSizePackets() > 0) {
1602*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer->NextSendTime());
1603*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
1604*d9f75844SAndroid Build Coastguard Worker }
1605*d9f75844SAndroid Build Coastguard Worker
1606*d9f75844SAndroid Build Coastguard Worker // Trigger probing.
1607*d9f75844SAndroid Build Coastguard Worker std::vector<ProbeClusterConfig> probe_clusters = {
1608*d9f75844SAndroid Build Coastguard Worker {.at_time = clock_.CurrentTime(),
1609*d9f75844SAndroid Build Coastguard Worker .target_data_rate = DataRate::KilobitsPerSec(10000), // 10 Mbps.
1610*d9f75844SAndroid Build Coastguard Worker .target_duration = TimeDelta::Millis(15),
1611*d9f75844SAndroid Build Coastguard Worker .target_probe_count = 5,
1612*d9f75844SAndroid Build Coastguard Worker .id = 3}};
1613*d9f75844SAndroid Build Coastguard Worker pacer->CreateProbeClusters(probe_clusters);
1614*d9f75844SAndroid Build Coastguard Worker
1615*d9f75844SAndroid Build Coastguard Worker // Time to next send time should be small.
1616*d9f75844SAndroid Build Coastguard Worker EXPECT_LT(pacer->NextSendTime() - clock_.CurrentTime(),
1617*d9f75844SAndroid Build Coastguard Worker PacingController::kPausedProcessInterval);
1618*d9f75844SAndroid Build Coastguard Worker
1619*d9f75844SAndroid Build Coastguard Worker // Pause pacer, time to next send time should now be the pause process
1620*d9f75844SAndroid Build Coastguard Worker // interval.
1621*d9f75844SAndroid Build Coastguard Worker pacer->Pause();
1622*d9f75844SAndroid Build Coastguard Worker
1623*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(pacer->NextSendTime() - clock_.CurrentTime(),
1624*d9f75844SAndroid Build Coastguard Worker PacingController::kPausedProcessInterval);
1625*d9f75844SAndroid Build Coastguard Worker }
1626*d9f75844SAndroid Build Coastguard Worker
TEST_F(PacingControllerTest,AudioNotPacedEvenWhenAccountedFor)1627*d9f75844SAndroid Build Coastguard Worker TEST_F(PacingControllerTest, AudioNotPacedEvenWhenAccountedFor) {
1628*d9f75844SAndroid Build Coastguard Worker const uint32_t kSsrc = 12345;
1629*d9f75844SAndroid Build Coastguard Worker uint16_t sequence_number = 1234;
1630*d9f75844SAndroid Build Coastguard Worker const size_t kPacketSize = 123;
1631*d9f75844SAndroid Build Coastguard Worker auto pacer = std::make_unique<PacingController>(&clock_, &callback_, trials_);
1632*d9f75844SAndroid Build Coastguard Worker
1633*d9f75844SAndroid Build Coastguard Worker // Account for audio - so that audio packets can cause pushback on other
1634*d9f75844SAndroid Build Coastguard Worker // types such as video. Audio packet should still be immediated passed
1635*d9f75844SAndroid Build Coastguard Worker // through though ("WebRTC-Pacer-BlockAudio" needs to be enabled in order
1636*d9f75844SAndroid Build Coastguard Worker // to pace audio packets).
1637*d9f75844SAndroid Build Coastguard Worker pacer->SetAccountForAudioPackets(true);
1638*d9f75844SAndroid Build Coastguard Worker
1639*d9f75844SAndroid Build Coastguard Worker // Set pacing rate to 1 packet/s, no padding.
1640*d9f75844SAndroid Build Coastguard Worker pacer->SetPacingRates(DataSize::Bytes(kPacketSize) / TimeDelta::Seconds(1),
1641*d9f75844SAndroid Build Coastguard Worker DataRate::Zero());
1642*d9f75844SAndroid Build Coastguard Worker
1643*d9f75844SAndroid Build Coastguard Worker // Add and send an audio packet.
1644*d9f75844SAndroid Build Coastguard Worker SendAndExpectPacket(pacer.get(), RtpPacketMediaType::kAudio, kSsrc,
1645*d9f75844SAndroid Build Coastguard Worker sequence_number++, clock_.TimeInMilliseconds(),
1646*d9f75844SAndroid Build Coastguard Worker kPacketSize);
1647*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
1648*d9f75844SAndroid Build Coastguard Worker
1649*d9f75844SAndroid Build Coastguard Worker // Advance time, add another audio packet and process. It should be sent
1650*d9f75844SAndroid Build Coastguard Worker // immediately.
1651*d9f75844SAndroid Build Coastguard Worker clock_.AdvanceTimeMilliseconds(5);
1652*d9f75844SAndroid Build Coastguard Worker SendAndExpectPacket(pacer.get(), RtpPacketMediaType::kAudio, kSsrc,
1653*d9f75844SAndroid Build Coastguard Worker sequence_number++, clock_.TimeInMilliseconds(),
1654*d9f75844SAndroid Build Coastguard Worker kPacketSize);
1655*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
1656*d9f75844SAndroid Build Coastguard Worker }
1657*d9f75844SAndroid Build Coastguard Worker
TEST_F(PacingControllerTest,PaddingResumesAfterSaturationEvenWithConcurrentAudio)1658*d9f75844SAndroid Build Coastguard Worker TEST_F(PacingControllerTest,
1659*d9f75844SAndroid Build Coastguard Worker PaddingResumesAfterSaturationEvenWithConcurrentAudio) {
1660*d9f75844SAndroid Build Coastguard Worker const uint32_t kSsrc = 12345;
1661*d9f75844SAndroid Build Coastguard Worker const DataRate kPacingDataRate = DataRate::KilobitsPerSec(125);
1662*d9f75844SAndroid Build Coastguard Worker const DataRate kPaddingDataRate = DataRate::KilobitsPerSec(100);
1663*d9f75844SAndroid Build Coastguard Worker const TimeDelta kMaxBufferInTime = TimeDelta::Millis(500);
1664*d9f75844SAndroid Build Coastguard Worker const DataSize kPacketSize = DataSize::Bytes(130);
1665*d9f75844SAndroid Build Coastguard Worker const TimeDelta kAudioPacketInterval = TimeDelta::Millis(20);
1666*d9f75844SAndroid Build Coastguard Worker
1667*d9f75844SAndroid Build Coastguard Worker // In this test, we fist send a burst of video in order to saturate the
1668*d9f75844SAndroid Build Coastguard Worker // padding debt level.
1669*d9f75844SAndroid Build Coastguard Worker // We then proceed to send audio at a bitrate that is slightly lower than
1670*d9f75844SAndroid Build Coastguard Worker // the padding rate, meaning there will be a period with audio but no
1671*d9f75844SAndroid Build Coastguard Worker // padding sent while the debt is draining, then audio and padding will
1672*d9f75844SAndroid Build Coastguard Worker // be interlieved.
1673*d9f75844SAndroid Build Coastguard Worker
1674*d9f75844SAndroid Build Coastguard Worker // Verify both with and without accounting for audio.
1675*d9f75844SAndroid Build Coastguard Worker for (bool account_for_audio : {false, true}) {
1676*d9f75844SAndroid Build Coastguard Worker uint16_t sequence_number = 1234;
1677*d9f75844SAndroid Build Coastguard Worker MockPacketSender callback;
1678*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback, SendPacket).Times(AnyNumber());
1679*d9f75844SAndroid Build Coastguard Worker auto pacer =
1680*d9f75844SAndroid Build Coastguard Worker std::make_unique<PacingController>(&clock_, &callback, trials_);
1681*d9f75844SAndroid Build Coastguard Worker pacer->SetAccountForAudioPackets(account_for_audio);
1682*d9f75844SAndroid Build Coastguard Worker
1683*d9f75844SAndroid Build Coastguard Worker // First, saturate the padding budget.
1684*d9f75844SAndroid Build Coastguard Worker pacer->SetPacingRates(kPacingDataRate, kPaddingDataRate);
1685*d9f75844SAndroid Build Coastguard Worker
1686*d9f75844SAndroid Build Coastguard Worker const TimeDelta kPaddingSaturationTime =
1687*d9f75844SAndroid Build Coastguard Worker kMaxBufferInTime * kPaddingDataRate /
1688*d9f75844SAndroid Build Coastguard Worker (kPacingDataRate - kPaddingDataRate);
1689*d9f75844SAndroid Build Coastguard Worker const DataSize kVideoToSend = kPaddingSaturationTime * kPacingDataRate;
1690*d9f75844SAndroid Build Coastguard Worker const DataSize kVideoPacketSize = DataSize::Bytes(1200);
1691*d9f75844SAndroid Build Coastguard Worker DataSize video_sent = DataSize::Zero();
1692*d9f75844SAndroid Build Coastguard Worker while (video_sent < kVideoToSend) {
1693*d9f75844SAndroid Build Coastguard Worker pacer->EnqueuePacket(
1694*d9f75844SAndroid Build Coastguard Worker BuildPacket(RtpPacketMediaType::kVideo, kSsrc, sequence_number++,
1695*d9f75844SAndroid Build Coastguard Worker clock_.TimeInMilliseconds(), kVideoPacketSize.bytes()));
1696*d9f75844SAndroid Build Coastguard Worker video_sent += kVideoPacketSize;
1697*d9f75844SAndroid Build Coastguard Worker }
1698*d9f75844SAndroid Build Coastguard Worker while (pacer->QueueSizePackets() > 0) {
1699*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer->NextSendTime());
1700*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
1701*d9f75844SAndroid Build Coastguard Worker }
1702*d9f75844SAndroid Build Coastguard Worker
1703*d9f75844SAndroid Build Coastguard Worker // Add a stream of audio packets at a rate slightly lower than the padding
1704*d9f75844SAndroid Build Coastguard Worker // rate, once the padding debt is paid off we expect padding to be
1705*d9f75844SAndroid Build Coastguard Worker // generated.
1706*d9f75844SAndroid Build Coastguard Worker pacer->SetPacingRates(kPacingDataRate, kPaddingDataRate);
1707*d9f75844SAndroid Build Coastguard Worker bool padding_seen = false;
1708*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback, GeneratePadding).WillOnce([&](DataSize padding_size) {
1709*d9f75844SAndroid Build Coastguard Worker padding_seen = true;
1710*d9f75844SAndroid Build Coastguard Worker std::vector<std::unique_ptr<RtpPacketToSend>> padding_packets;
1711*d9f75844SAndroid Build Coastguard Worker padding_packets.emplace_back(
1712*d9f75844SAndroid Build Coastguard Worker BuildPacket(RtpPacketMediaType::kPadding, kSsrc, sequence_number++,
1713*d9f75844SAndroid Build Coastguard Worker clock_.TimeInMilliseconds(), padding_size.bytes()));
1714*d9f75844SAndroid Build Coastguard Worker return padding_packets;
1715*d9f75844SAndroid Build Coastguard Worker });
1716*d9f75844SAndroid Build Coastguard Worker
1717*d9f75844SAndroid Build Coastguard Worker Timestamp start_time = clock_.CurrentTime();
1718*d9f75844SAndroid Build Coastguard Worker Timestamp last_audio_time = start_time;
1719*d9f75844SAndroid Build Coastguard Worker while (!padding_seen) {
1720*d9f75844SAndroid Build Coastguard Worker Timestamp now = clock_.CurrentTime();
1721*d9f75844SAndroid Build Coastguard Worker Timestamp next_send_time = pacer->NextSendTime();
1722*d9f75844SAndroid Build Coastguard Worker TimeDelta sleep_time =
1723*d9f75844SAndroid Build Coastguard Worker std::min(next_send_time, last_audio_time + kAudioPacketInterval) -
1724*d9f75844SAndroid Build Coastguard Worker now;
1725*d9f75844SAndroid Build Coastguard Worker clock_.AdvanceTime(sleep_time);
1726*d9f75844SAndroid Build Coastguard Worker while (clock_.CurrentTime() >= last_audio_time + kAudioPacketInterval) {
1727*d9f75844SAndroid Build Coastguard Worker pacer->EnqueuePacket(
1728*d9f75844SAndroid Build Coastguard Worker BuildPacket(RtpPacketMediaType::kAudio, kSsrc, sequence_number++,
1729*d9f75844SAndroid Build Coastguard Worker clock_.TimeInMilliseconds(), kPacketSize.bytes()));
1730*d9f75844SAndroid Build Coastguard Worker last_audio_time += kAudioPacketInterval;
1731*d9f75844SAndroid Build Coastguard Worker }
1732*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
1733*d9f75844SAndroid Build Coastguard Worker }
1734*d9f75844SAndroid Build Coastguard Worker
1735*d9f75844SAndroid Build Coastguard Worker // Verify how long it took to drain the padding debt. Allow 2% error margin.
1736*d9f75844SAndroid Build Coastguard Worker const DataRate kAudioDataRate = kPacketSize / kAudioPacketInterval;
1737*d9f75844SAndroid Build Coastguard Worker const TimeDelta expected_drain_time =
1738*d9f75844SAndroid Build Coastguard Worker account_for_audio ? (kMaxBufferInTime * kPaddingDataRate /
1739*d9f75844SAndroid Build Coastguard Worker (kPaddingDataRate - kAudioDataRate))
1740*d9f75844SAndroid Build Coastguard Worker : kMaxBufferInTime;
1741*d9f75844SAndroid Build Coastguard Worker const TimeDelta actual_drain_time = clock_.CurrentTime() - start_time;
1742*d9f75844SAndroid Build Coastguard Worker EXPECT_NEAR(actual_drain_time.ms(), expected_drain_time.ms(),
1743*d9f75844SAndroid Build Coastguard Worker expected_drain_time.ms() * 0.02)
1744*d9f75844SAndroid Build Coastguard Worker << " where account_for_audio = "
1745*d9f75844SAndroid Build Coastguard Worker << (account_for_audio ? "true" : "false");
1746*d9f75844SAndroid Build Coastguard Worker }
1747*d9f75844SAndroid Build Coastguard Worker }
1748*d9f75844SAndroid Build Coastguard Worker
TEST_F(PacingControllerTest,AccountsForAudioEnqueueTime)1749*d9f75844SAndroid Build Coastguard Worker TEST_F(PacingControllerTest, AccountsForAudioEnqueueTime) {
1750*d9f75844SAndroid Build Coastguard Worker const uint32_t kSsrc = 12345;
1751*d9f75844SAndroid Build Coastguard Worker const DataRate kPacingDataRate = DataRate::KilobitsPerSec(125);
1752*d9f75844SAndroid Build Coastguard Worker const DataRate kPaddingDataRate = DataRate::Zero();
1753*d9f75844SAndroid Build Coastguard Worker const DataSize kPacketSize = DataSize::Bytes(130);
1754*d9f75844SAndroid Build Coastguard Worker const TimeDelta kPacketPacingTime = kPacketSize / kPacingDataRate;
1755*d9f75844SAndroid Build Coastguard Worker uint32_t sequnce_number = 1;
1756*d9f75844SAndroid Build Coastguard Worker auto pacer = std::make_unique<PacingController>(&clock_, &callback_, trials_);
1757*d9f75844SAndroid Build Coastguard Worker // Audio not paced, but still accounted for in budget.
1758*d9f75844SAndroid Build Coastguard Worker pacer->SetAccountForAudioPackets(true);
1759*d9f75844SAndroid Build Coastguard Worker pacer->SetPacingRates(kPacingDataRate, kPaddingDataRate);
1760*d9f75844SAndroid Build Coastguard Worker
1761*d9f75844SAndroid Build Coastguard Worker // Enqueue two audio packets, advance clock to where one packet
1762*d9f75844SAndroid Build Coastguard Worker // should have drained the buffer already, has they been sent
1763*d9f75844SAndroid Build Coastguard Worker // immediately.
1764*d9f75844SAndroid Build Coastguard Worker SendAndExpectPacket(pacer.get(), RtpPacketMediaType::kAudio, kSsrc,
1765*d9f75844SAndroid Build Coastguard Worker sequnce_number++, clock_.TimeInMilliseconds(),
1766*d9f75844SAndroid Build Coastguard Worker kPacketSize.bytes());
1767*d9f75844SAndroid Build Coastguard Worker SendAndExpectPacket(pacer.get(), RtpPacketMediaType::kAudio, kSsrc,
1768*d9f75844SAndroid Build Coastguard Worker sequnce_number++, clock_.TimeInMilliseconds(),
1769*d9f75844SAndroid Build Coastguard Worker kPacketSize.bytes());
1770*d9f75844SAndroid Build Coastguard Worker clock_.AdvanceTime(kPacketPacingTime);
1771*d9f75844SAndroid Build Coastguard Worker // Now process and make sure both packets were sent.
1772*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
1773*d9f75844SAndroid Build Coastguard Worker ::testing::Mock::VerifyAndClearExpectations(&callback_);
1774*d9f75844SAndroid Build Coastguard Worker
1775*d9f75844SAndroid Build Coastguard Worker // Add a video packet. I can't be sent until debt from audio
1776*d9f75844SAndroid Build Coastguard Worker // packets have been drained.
1777*d9f75844SAndroid Build Coastguard Worker pacer->EnqueuePacket(
1778*d9f75844SAndroid Build Coastguard Worker BuildPacket(RtpPacketMediaType::kVideo, kSsrc + 1, sequnce_number++,
1779*d9f75844SAndroid Build Coastguard Worker clock_.TimeInMilliseconds(), kPacketSize.bytes()));
1780*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(pacer->NextSendTime() - clock_.CurrentTime(), kPacketPacingTime);
1781*d9f75844SAndroid Build Coastguard Worker }
1782*d9f75844SAndroid Build Coastguard Worker
TEST_F(PacingControllerTest,NextSendTimeAccountsForPadding)1783*d9f75844SAndroid Build Coastguard Worker TEST_F(PacingControllerTest, NextSendTimeAccountsForPadding) {
1784*d9f75844SAndroid Build Coastguard Worker const uint32_t kSsrc = 12345;
1785*d9f75844SAndroid Build Coastguard Worker const DataRate kPacingDataRate = DataRate::KilobitsPerSec(125);
1786*d9f75844SAndroid Build Coastguard Worker const DataSize kPacketSize = DataSize::Bytes(130);
1787*d9f75844SAndroid Build Coastguard Worker const TimeDelta kPacketPacingTime = kPacketSize / kPacingDataRate;
1788*d9f75844SAndroid Build Coastguard Worker uint32_t sequnce_number = 1;
1789*d9f75844SAndroid Build Coastguard Worker auto pacer = std::make_unique<PacingController>(&clock_, &callback_, trials_);
1790*d9f75844SAndroid Build Coastguard Worker
1791*d9f75844SAndroid Build Coastguard Worker // Start with no padding.
1792*d9f75844SAndroid Build Coastguard Worker pacer->SetPacingRates(kPacingDataRate, DataRate::Zero());
1793*d9f75844SAndroid Build Coastguard Worker
1794*d9f75844SAndroid Build Coastguard Worker // Send a single packet.
1795*d9f75844SAndroid Build Coastguard Worker SendAndExpectPacket(pacer.get(), RtpPacketMediaType::kVideo, kSsrc,
1796*d9f75844SAndroid Build Coastguard Worker sequnce_number++, clock_.TimeInMilliseconds(),
1797*d9f75844SAndroid Build Coastguard Worker kPacketSize.bytes());
1798*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
1799*d9f75844SAndroid Build Coastguard Worker ::testing::Mock::VerifyAndClearExpectations(&callback_);
1800*d9f75844SAndroid Build Coastguard Worker
1801*d9f75844SAndroid Build Coastguard Worker // With current conditions, no need to wake until next keep-alive.
1802*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(pacer->NextSendTime() - clock_.CurrentTime(),
1803*d9f75844SAndroid Build Coastguard Worker PacingController::kPausedProcessInterval);
1804*d9f75844SAndroid Build Coastguard Worker
1805*d9f75844SAndroid Build Coastguard Worker // Enqueue a new packet, that can't be sent until previous buffer has
1806*d9f75844SAndroid Build Coastguard Worker // drained.
1807*d9f75844SAndroid Build Coastguard Worker SendAndExpectPacket(pacer.get(), RtpPacketMediaType::kVideo, kSsrc,
1808*d9f75844SAndroid Build Coastguard Worker sequnce_number++, clock_.TimeInMilliseconds(),
1809*d9f75844SAndroid Build Coastguard Worker kPacketSize.bytes());
1810*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(pacer->NextSendTime() - clock_.CurrentTime(), kPacketPacingTime);
1811*d9f75844SAndroid Build Coastguard Worker clock_.AdvanceTime(kPacketPacingTime);
1812*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
1813*d9f75844SAndroid Build Coastguard Worker ::testing::Mock::VerifyAndClearExpectations(&callback_);
1814*d9f75844SAndroid Build Coastguard Worker
1815*d9f75844SAndroid Build Coastguard Worker // With current conditions, again no need to wake until next keep-alive.
1816*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(pacer->NextSendTime() - clock_.CurrentTime(),
1817*d9f75844SAndroid Build Coastguard Worker PacingController::kPausedProcessInterval);
1818*d9f75844SAndroid Build Coastguard Worker
1819*d9f75844SAndroid Build Coastguard Worker // Set a non-zero padding rate. Padding also can't be sent until
1820*d9f75844SAndroid Build Coastguard Worker // previous debt has cleared. Since padding was disabled before, there
1821*d9f75844SAndroid Build Coastguard Worker // currently is no padding debt.
1822*d9f75844SAndroid Build Coastguard Worker pacer->SetPacingRates(kPacingDataRate, kPacingDataRate / 2);
1823*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(pacer->NextSendTime() - clock_.CurrentTime(), kPacketPacingTime);
1824*d9f75844SAndroid Build Coastguard Worker
1825*d9f75844SAndroid Build Coastguard Worker // Advance time, expect padding.
1826*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPadding).WillOnce(Return(kPacketSize.bytes()));
1827*d9f75844SAndroid Build Coastguard Worker clock_.AdvanceTime(kPacketPacingTime);
1828*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
1829*d9f75844SAndroid Build Coastguard Worker ::testing::Mock::VerifyAndClearExpectations(&callback_);
1830*d9f75844SAndroid Build Coastguard Worker
1831*d9f75844SAndroid Build Coastguard Worker // Since padding rate is half of pacing rate, next time we can send
1832*d9f75844SAndroid Build Coastguard Worker // padding is double the packet pacing time.
1833*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(pacer->NextSendTime() - clock_.CurrentTime(),
1834*d9f75844SAndroid Build Coastguard Worker kPacketPacingTime * 2);
1835*d9f75844SAndroid Build Coastguard Worker
1836*d9f75844SAndroid Build Coastguard Worker // Insert a packet to be sent, this take precedence again.
1837*d9f75844SAndroid Build Coastguard Worker pacer->EnqueuePacket(
1838*d9f75844SAndroid Build Coastguard Worker BuildPacket(RtpPacketMediaType::kVideo, kSsrc, sequnce_number++,
1839*d9f75844SAndroid Build Coastguard Worker clock_.TimeInMilliseconds(), kPacketSize.bytes()));
1840*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(pacer->NextSendTime() - clock_.CurrentTime(), kPacketPacingTime);
1841*d9f75844SAndroid Build Coastguard Worker }
1842*d9f75844SAndroid Build Coastguard Worker
TEST_F(PacingControllerTest,PaddingTargetAccountsForPaddingRate)1843*d9f75844SAndroid Build Coastguard Worker TEST_F(PacingControllerTest, PaddingTargetAccountsForPaddingRate) {
1844*d9f75844SAndroid Build Coastguard Worker // Target size for a padding packet is 5ms * padding rate.
1845*d9f75844SAndroid Build Coastguard Worker const TimeDelta kPaddingTarget = TimeDelta::Millis(5);
1846*d9f75844SAndroid Build Coastguard Worker srand(0);
1847*d9f75844SAndroid Build Coastguard Worker // Need to initialize PacingController after we initialize clock.
1848*d9f75844SAndroid Build Coastguard Worker auto pacer = std::make_unique<PacingController>(&clock_, &callback_, trials_);
1849*d9f75844SAndroid Build Coastguard Worker
1850*d9f75844SAndroid Build Coastguard Worker const uint32_t kSsrc = 12345;
1851*d9f75844SAndroid Build Coastguard Worker const DataRate kPacingDataRate = DataRate::KilobitsPerSec(125);
1852*d9f75844SAndroid Build Coastguard Worker const DataSize kPacketSize = DataSize::Bytes(130);
1853*d9f75844SAndroid Build Coastguard Worker
1854*d9f75844SAndroid Build Coastguard Worker uint32_t sequnce_number = 1;
1855*d9f75844SAndroid Build Coastguard Worker
1856*d9f75844SAndroid Build Coastguard Worker // Start with pacing and padding rate equal.
1857*d9f75844SAndroid Build Coastguard Worker pacer->SetPacingRates(kPacingDataRate, kPacingDataRate);
1858*d9f75844SAndroid Build Coastguard Worker
1859*d9f75844SAndroid Build Coastguard Worker // Send a single packet.
1860*d9f75844SAndroid Build Coastguard Worker SendAndExpectPacket(pacer.get(), RtpPacketMediaType::kVideo, kSsrc,
1861*d9f75844SAndroid Build Coastguard Worker sequnce_number++, clock_.TimeInMilliseconds(),
1862*d9f75844SAndroid Build Coastguard Worker kPacketSize.bytes());
1863*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer->NextSendTime());
1864*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
1865*d9f75844SAndroid Build Coastguard Worker ::testing::Mock::VerifyAndClearExpectations(&callback_);
1866*d9f75844SAndroid Build Coastguard Worker
1867*d9f75844SAndroid Build Coastguard Worker size_t expected_padding_target_bytes =
1868*d9f75844SAndroid Build Coastguard Worker (kPaddingTarget * kPacingDataRate).bytes();
1869*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPadding(expected_padding_target_bytes))
1870*d9f75844SAndroid Build Coastguard Worker .WillOnce(Return(expected_padding_target_bytes));
1871*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer->NextSendTime());
1872*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
1873*d9f75844SAndroid Build Coastguard Worker
1874*d9f75844SAndroid Build Coastguard Worker // Half the padding rate - expect half the padding target.
1875*d9f75844SAndroid Build Coastguard Worker pacer->SetPacingRates(kPacingDataRate, kPacingDataRate / 2);
1876*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPadding(expected_padding_target_bytes / 2))
1877*d9f75844SAndroid Build Coastguard Worker .WillOnce(Return(expected_padding_target_bytes / 2));
1878*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer->NextSendTime());
1879*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
1880*d9f75844SAndroid Build Coastguard Worker }
1881*d9f75844SAndroid Build Coastguard Worker
TEST_F(PacingControllerTest,SendsFecPackets)1882*d9f75844SAndroid Build Coastguard Worker TEST_F(PacingControllerTest, SendsFecPackets) {
1883*d9f75844SAndroid Build Coastguard Worker const uint32_t kSsrc = 12345;
1884*d9f75844SAndroid Build Coastguard Worker const uint32_t kFlexSsrc = 54321;
1885*d9f75844SAndroid Build Coastguard Worker uint16_t sequence_number = 1234;
1886*d9f75844SAndroid Build Coastguard Worker uint16_t flexfec_sequence_number = 4321;
1887*d9f75844SAndroid Build Coastguard Worker const size_t kPacketSize = 123;
1888*d9f75844SAndroid Build Coastguard Worker auto pacer = std::make_unique<PacingController>(&clock_, &callback_, trials_);
1889*d9f75844SAndroid Build Coastguard Worker
1890*d9f75844SAndroid Build Coastguard Worker // Set pacing rate to 1000 packet/s, no padding.
1891*d9f75844SAndroid Build Coastguard Worker pacer->SetPacingRates(
1892*d9f75844SAndroid Build Coastguard Worker DataSize::Bytes(1000 * kPacketSize) / TimeDelta::Seconds(1),
1893*d9f75844SAndroid Build Coastguard Worker DataRate::Zero());
1894*d9f75844SAndroid Build Coastguard Worker
1895*d9f75844SAndroid Build Coastguard Worker int64_t now = clock_.TimeInMilliseconds();
1896*d9f75844SAndroid Build Coastguard Worker pacer->EnqueuePacket(BuildPacket(RtpPacketMediaType::kVideo, kSsrc,
1897*d9f75844SAndroid Build Coastguard Worker sequence_number, now, kPacketSize));
1898*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPacket(kSsrc, sequence_number, now, false, false));
1899*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, FetchFec).WillOnce([&]() {
1900*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPacket(kFlexSsrc, flexfec_sequence_number, now,
1901*d9f75844SAndroid Build Coastguard Worker false, false));
1902*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, FetchFec);
1903*d9f75844SAndroid Build Coastguard Worker std::vector<std::unique_ptr<RtpPacketToSend>> fec_packets;
1904*d9f75844SAndroid Build Coastguard Worker fec_packets.push_back(
1905*d9f75844SAndroid Build Coastguard Worker BuildPacket(RtpPacketMediaType::kForwardErrorCorrection, kFlexSsrc,
1906*d9f75844SAndroid Build Coastguard Worker flexfec_sequence_number, now, kPacketSize));
1907*d9f75844SAndroid Build Coastguard Worker return fec_packets;
1908*d9f75844SAndroid Build Coastguard Worker });
1909*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer->NextSendTime());
1910*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
1911*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer->NextSendTime());
1912*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
1913*d9f75844SAndroid Build Coastguard Worker }
1914*d9f75844SAndroid Build Coastguard Worker
TEST_F(PacingControllerTest,GapInPacingDoesntAccumulateBudget)1915*d9f75844SAndroid Build Coastguard Worker TEST_F(PacingControllerTest, GapInPacingDoesntAccumulateBudget) {
1916*d9f75844SAndroid Build Coastguard Worker const uint32_t kSsrc = 12345;
1917*d9f75844SAndroid Build Coastguard Worker uint16_t sequence_number = 1234;
1918*d9f75844SAndroid Build Coastguard Worker const DataSize kPackeSize = DataSize::Bytes(250);
1919*d9f75844SAndroid Build Coastguard Worker const TimeDelta kPacketSendTime = TimeDelta::Millis(15);
1920*d9f75844SAndroid Build Coastguard Worker auto pacer = std::make_unique<PacingController>(&clock_, &callback_, trials_);
1921*d9f75844SAndroid Build Coastguard Worker
1922*d9f75844SAndroid Build Coastguard Worker pacer->SetPacingRates(kPackeSize / kPacketSendTime,
1923*d9f75844SAndroid Build Coastguard Worker /*padding_rate=*/DataRate::Zero());
1924*d9f75844SAndroid Build Coastguard Worker
1925*d9f75844SAndroid Build Coastguard Worker // Send an initial packet.
1926*d9f75844SAndroid Build Coastguard Worker SendAndExpectPacket(pacer.get(), RtpPacketMediaType::kVideo, kSsrc,
1927*d9f75844SAndroid Build Coastguard Worker sequence_number++, clock_.TimeInMilliseconds(),
1928*d9f75844SAndroid Build Coastguard Worker kPackeSize.bytes());
1929*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
1930*d9f75844SAndroid Build Coastguard Worker ::testing::Mock::VerifyAndClearExpectations(&callback_);
1931*d9f75844SAndroid Build Coastguard Worker
1932*d9f75844SAndroid Build Coastguard Worker // Advance time kPacketSendTime past where the media debt should be 0.
1933*d9f75844SAndroid Build Coastguard Worker clock_.AdvanceTime(2 * kPacketSendTime);
1934*d9f75844SAndroid Build Coastguard Worker
1935*d9f75844SAndroid Build Coastguard Worker // Enqueue two new packets. Expect only one to be sent one ProcessPackets().
1936*d9f75844SAndroid Build Coastguard Worker pacer->EnqueuePacket(
1937*d9f75844SAndroid Build Coastguard Worker BuildPacket(RtpPacketMediaType::kVideo, kSsrc, sequence_number + 1,
1938*d9f75844SAndroid Build Coastguard Worker clock_.TimeInMilliseconds(), kPackeSize.bytes()));
1939*d9f75844SAndroid Build Coastguard Worker pacer->EnqueuePacket(
1940*d9f75844SAndroid Build Coastguard Worker BuildPacket(RtpPacketMediaType::kVideo, kSsrc, sequence_number + 2,
1941*d9f75844SAndroid Build Coastguard Worker clock_.TimeInMilliseconds(), kPackeSize.bytes()));
1942*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPacket(kSsrc, sequence_number + 1,
1943*d9f75844SAndroid Build Coastguard Worker clock_.TimeInMilliseconds(), false, false));
1944*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
1945*d9f75844SAndroid Build Coastguard Worker }
1946*d9f75844SAndroid Build Coastguard Worker
TEST_F(PacingControllerTest,HandlesSubMicrosecondSendIntervals)1947*d9f75844SAndroid Build Coastguard Worker TEST_F(PacingControllerTest, HandlesSubMicrosecondSendIntervals) {
1948*d9f75844SAndroid Build Coastguard Worker static constexpr DataSize kPacketSize = DataSize::Bytes(1);
1949*d9f75844SAndroid Build Coastguard Worker static constexpr TimeDelta kPacketSendTime = TimeDelta::Micros(1);
1950*d9f75844SAndroid Build Coastguard Worker auto pacer = std::make_unique<PacingController>(&clock_, &callback_, trials_);
1951*d9f75844SAndroid Build Coastguard Worker
1952*d9f75844SAndroid Build Coastguard Worker // Set pacing rate such that a packet is sent in 0.5us.
1953*d9f75844SAndroid Build Coastguard Worker pacer->SetPacingRates(/*pacing_rate=*/2 * kPacketSize / kPacketSendTime,
1954*d9f75844SAndroid Build Coastguard Worker /*padding_rate=*/DataRate::Zero());
1955*d9f75844SAndroid Build Coastguard Worker
1956*d9f75844SAndroid Build Coastguard Worker // Enqueue three packets, the first two should be sent immediately - the third
1957*d9f75844SAndroid Build Coastguard Worker // should cause a non-zero delta to the next process time.
1958*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPacket).Times(2);
1959*d9f75844SAndroid Build Coastguard Worker for (int i = 0; i < 3; ++i) {
1960*d9f75844SAndroid Build Coastguard Worker pacer->EnqueuePacket(BuildPacket(
1961*d9f75844SAndroid Build Coastguard Worker RtpPacketMediaType::kVideo, /*ssrc=*/12345, /*sequence_number=*/i,
1962*d9f75844SAndroid Build Coastguard Worker clock_.TimeInMilliseconds(), kPacketSize.bytes()));
1963*d9f75844SAndroid Build Coastguard Worker }
1964*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
1965*d9f75844SAndroid Build Coastguard Worker
1966*d9f75844SAndroid Build Coastguard Worker EXPECT_GT(pacer->NextSendTime(), clock_.CurrentTime());
1967*d9f75844SAndroid Build Coastguard Worker }
1968*d9f75844SAndroid Build Coastguard Worker
TEST_F(PacingControllerTest,HandlesSubMicrosecondPaddingInterval)1969*d9f75844SAndroid Build Coastguard Worker TEST_F(PacingControllerTest, HandlesSubMicrosecondPaddingInterval) {
1970*d9f75844SAndroid Build Coastguard Worker static constexpr DataSize kPacketSize = DataSize::Bytes(1);
1971*d9f75844SAndroid Build Coastguard Worker static constexpr TimeDelta kPacketSendTime = TimeDelta::Micros(1);
1972*d9f75844SAndroid Build Coastguard Worker auto pacer = std::make_unique<PacingController>(&clock_, &callback_, trials_);
1973*d9f75844SAndroid Build Coastguard Worker
1974*d9f75844SAndroid Build Coastguard Worker // Set both pacing and padding rates to 1 byte per 0.5us.
1975*d9f75844SAndroid Build Coastguard Worker pacer->SetPacingRates(/*pacing_rate=*/2 * kPacketSize / kPacketSendTime,
1976*d9f75844SAndroid Build Coastguard Worker /*padding_rate=*/2 * kPacketSize / kPacketSendTime);
1977*d9f75844SAndroid Build Coastguard Worker
1978*d9f75844SAndroid Build Coastguard Worker // Enqueue and send one packet.
1979*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPacket);
1980*d9f75844SAndroid Build Coastguard Worker pacer->EnqueuePacket(BuildPacket(
1981*d9f75844SAndroid Build Coastguard Worker RtpPacketMediaType::kVideo, /*ssrc=*/12345, /*sequence_number=*/1234,
1982*d9f75844SAndroid Build Coastguard Worker clock_.TimeInMilliseconds(), kPacketSize.bytes()));
1983*d9f75844SAndroid Build Coastguard Worker pacer->ProcessPackets();
1984*d9f75844SAndroid Build Coastguard Worker
1985*d9f75844SAndroid Build Coastguard Worker // The padding debt is now 1 byte, and the pacing time for that is lower than
1986*d9f75844SAndroid Build Coastguard Worker // the precision of a TimeStamp tick. Make sure the pacer still indicates a
1987*d9f75844SAndroid Build Coastguard Worker // non-zero sleep time is needed until the next process.
1988*d9f75844SAndroid Build Coastguard Worker EXPECT_GT(pacer->NextSendTime(), clock_.CurrentTime());
1989*d9f75844SAndroid Build Coastguard Worker }
1990*d9f75844SAndroid Build Coastguard Worker
TEST_F(PacingControllerTest,SendsPacketsInBurstImmediately)1991*d9f75844SAndroid Build Coastguard Worker TEST_F(PacingControllerTest, SendsPacketsInBurstImmediately) {
1992*d9f75844SAndroid Build Coastguard Worker constexpr TimeDelta kMaxDelay = TimeDelta::Millis(20);
1993*d9f75844SAndroid Build Coastguard Worker PacingController pacer(&clock_, &callback_, trials_);
1994*d9f75844SAndroid Build Coastguard Worker pacer.SetSendBurstInterval(kMaxDelay);
1995*d9f75844SAndroid Build Coastguard Worker pacer.SetPacingRates(DataRate::BytesPerSec(10000), DataRate::Zero());
1996*d9f75844SAndroid Build Coastguard Worker
1997*d9f75844SAndroid Build Coastguard Worker // Max allowed send burst size is 100000*20/1000) = 200byte
1998*d9f75844SAndroid Build Coastguard Worker pacer.EnqueuePacket(video_.BuildNextPacket(100));
1999*d9f75844SAndroid Build Coastguard Worker pacer.EnqueuePacket(video_.BuildNextPacket(100));
2000*d9f75844SAndroid Build Coastguard Worker pacer.EnqueuePacket(video_.BuildNextPacket(100));
2001*d9f75844SAndroid Build Coastguard Worker pacer.ProcessPackets();
2002*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(pacer.QueueSizePackets(), 1u);
2003*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(pacer.NextSendTime(), clock_.CurrentTime() + kMaxDelay);
2004*d9f75844SAndroid Build Coastguard Worker
2005*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer.NextSendTime());
2006*d9f75844SAndroid Build Coastguard Worker pacer.ProcessPackets();
2007*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(pacer.QueueSizePackets(), 0u);
2008*d9f75844SAndroid Build Coastguard Worker }
2009*d9f75844SAndroid Build Coastguard Worker
TEST_F(PacingControllerTest,SendsPacketsInBurstEvenIfNotEnqueedAtSameTime)2010*d9f75844SAndroid Build Coastguard Worker TEST_F(PacingControllerTest, SendsPacketsInBurstEvenIfNotEnqueedAtSameTime) {
2011*d9f75844SAndroid Build Coastguard Worker constexpr TimeDelta kMaxDelay = TimeDelta::Millis(20);
2012*d9f75844SAndroid Build Coastguard Worker PacingController pacer(&clock_, &callback_, trials_);
2013*d9f75844SAndroid Build Coastguard Worker pacer.SetSendBurstInterval(kMaxDelay);
2014*d9f75844SAndroid Build Coastguard Worker pacer.SetPacingRates(DataRate::BytesPerSec(10000), DataRate::Zero());
2015*d9f75844SAndroid Build Coastguard Worker pacer.EnqueuePacket(video_.BuildNextPacket(200));
2016*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(pacer.NextSendTime(), clock_.CurrentTime());
2017*d9f75844SAndroid Build Coastguard Worker pacer.ProcessPackets();
2018*d9f75844SAndroid Build Coastguard Worker clock_.AdvanceTime(TimeDelta::Millis(1));
2019*d9f75844SAndroid Build Coastguard Worker pacer.EnqueuePacket(video_.BuildNextPacket(200));
2020*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(pacer.NextSendTime(), clock_.CurrentTime());
2021*d9f75844SAndroid Build Coastguard Worker pacer.ProcessPackets();
2022*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(pacer.QueueSizePackets(), 0u);
2023*d9f75844SAndroid Build Coastguard Worker }
2024*d9f75844SAndroid Build Coastguard Worker
TEST_F(PacingControllerTest,RespectsTargetRateWhenSendingPacketsInBursts)2025*d9f75844SAndroid Build Coastguard Worker TEST_F(PacingControllerTest, RespectsTargetRateWhenSendingPacketsInBursts) {
2026*d9f75844SAndroid Build Coastguard Worker PacingController pacer(&clock_, &callback_, trials_);
2027*d9f75844SAndroid Build Coastguard Worker pacer.SetSendBurstInterval(TimeDelta::Millis(20));
2028*d9f75844SAndroid Build Coastguard Worker pacer.SetAccountForAudioPackets(true);
2029*d9f75844SAndroid Build Coastguard Worker pacer.SetPacingRates(DataRate::KilobitsPerSec(1000), DataRate::Zero());
2030*d9f75844SAndroid Build Coastguard Worker Timestamp start_time = clock_.CurrentTime();
2031*d9f75844SAndroid Build Coastguard Worker // Inject 100 packets, with size 1000bytes over 100ms.
2032*d9f75844SAndroid Build Coastguard Worker // Expect only 1Mbps / (8*1000) / 10 = 12 packets to be sent.
2033*d9f75844SAndroid Build Coastguard Worker // Packets are sent in burst. Each burst is then 3 packets * 1000bytes at
2034*d9f75844SAndroid Build Coastguard Worker // 1Mbits = 24ms long. Thus, expect 4 bursts.
2035*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPacket).Times(12);
2036*d9f75844SAndroid Build Coastguard Worker int number_of_bursts = 0;
2037*d9f75844SAndroid Build Coastguard Worker while (clock_.CurrentTime() < start_time + TimeDelta::Millis(100)) {
2038*d9f75844SAndroid Build Coastguard Worker pacer.EnqueuePacket(video_.BuildNextPacket(1000));
2039*d9f75844SAndroid Build Coastguard Worker pacer.EnqueuePacket(video_.BuildNextPacket(1000));
2040*d9f75844SAndroid Build Coastguard Worker pacer.EnqueuePacket(video_.BuildNextPacket(1000));
2041*d9f75844SAndroid Build Coastguard Worker pacer.EnqueuePacket(video_.BuildNextPacket(1000));
2042*d9f75844SAndroid Build Coastguard Worker pacer.EnqueuePacket(video_.BuildNextPacket(1000));
2043*d9f75844SAndroid Build Coastguard Worker if (pacer.NextSendTime() <= clock_.CurrentTime()) {
2044*d9f75844SAndroid Build Coastguard Worker pacer.ProcessPackets();
2045*d9f75844SAndroid Build Coastguard Worker ++number_of_bursts;
2046*d9f75844SAndroid Build Coastguard Worker }
2047*d9f75844SAndroid Build Coastguard Worker clock_.AdvanceTime(TimeDelta::Millis(5));
2048*d9f75844SAndroid Build Coastguard Worker }
2049*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(pacer.QueueSizePackets(), 88u);
2050*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(number_of_bursts, 4);
2051*d9f75844SAndroid Build Coastguard Worker }
2052*d9f75844SAndroid Build Coastguard Worker
TEST_F(PacingControllerTest,RespectsQueueTimeLimit)2053*d9f75844SAndroid Build Coastguard Worker TEST_F(PacingControllerTest, RespectsQueueTimeLimit) {
2054*d9f75844SAndroid Build Coastguard Worker static constexpr DataSize kPacketSize = DataSize::Bytes(100);
2055*d9f75844SAndroid Build Coastguard Worker static constexpr DataRate kNominalPacingRate = DataRate::KilobitsPerSec(200);
2056*d9f75844SAndroid Build Coastguard Worker static constexpr TimeDelta kPacketPacingTime =
2057*d9f75844SAndroid Build Coastguard Worker kPacketSize / kNominalPacingRate;
2058*d9f75844SAndroid Build Coastguard Worker static constexpr TimeDelta kQueueTimeLimit = TimeDelta::Millis(1000);
2059*d9f75844SAndroid Build Coastguard Worker
2060*d9f75844SAndroid Build Coastguard Worker PacingController pacer(&clock_, &callback_, trials_);
2061*d9f75844SAndroid Build Coastguard Worker pacer.SetPacingRates(kNominalPacingRate, /*padding_rate=*/DataRate::Zero());
2062*d9f75844SAndroid Build Coastguard Worker pacer.SetQueueTimeLimit(kQueueTimeLimit);
2063*d9f75844SAndroid Build Coastguard Worker
2064*d9f75844SAndroid Build Coastguard Worker // Fill pacer up to queue time limit.
2065*d9f75844SAndroid Build Coastguard Worker static constexpr int kNumPackets = kQueueTimeLimit / kPacketPacingTime;
2066*d9f75844SAndroid Build Coastguard Worker for (int i = 0; i < kNumPackets; ++i) {
2067*d9f75844SAndroid Build Coastguard Worker pacer.EnqueuePacket(video_.BuildNextPacket(kPacketSize.bytes()));
2068*d9f75844SAndroid Build Coastguard Worker }
2069*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(pacer.ExpectedQueueTime(), kQueueTimeLimit);
2070*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(pacer.pacing_rate(), kNominalPacingRate);
2071*d9f75844SAndroid Build Coastguard Worker
2072*d9f75844SAndroid Build Coastguard Worker // Double the amount of packets in the queue, the queue time limit should
2073*d9f75844SAndroid Build Coastguard Worker // effectively double the pacing rate in response.
2074*d9f75844SAndroid Build Coastguard Worker for (int i = 0; i < kNumPackets; ++i) {
2075*d9f75844SAndroid Build Coastguard Worker pacer.EnqueuePacket(video_.BuildNextPacket(kPacketSize.bytes()));
2076*d9f75844SAndroid Build Coastguard Worker }
2077*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(pacer.ExpectedQueueTime(), kQueueTimeLimit);
2078*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(pacer.pacing_rate(), 2 * kNominalPacingRate);
2079*d9f75844SAndroid Build Coastguard Worker
2080*d9f75844SAndroid Build Coastguard Worker // Send all the packets, should take as long as the queue time limit.
2081*d9f75844SAndroid Build Coastguard Worker Timestamp start_time = clock_.CurrentTime();
2082*d9f75844SAndroid Build Coastguard Worker while (pacer.QueueSizePackets() > 0) {
2083*d9f75844SAndroid Build Coastguard Worker AdvanceTimeUntil(pacer.NextSendTime());
2084*d9f75844SAndroid Build Coastguard Worker pacer.ProcessPackets();
2085*d9f75844SAndroid Build Coastguard Worker }
2086*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(clock_.CurrentTime() - start_time, kQueueTimeLimit);
2087*d9f75844SAndroid Build Coastguard Worker
2088*d9f75844SAndroid Build Coastguard Worker // We're back in a normal state - pacing rate should be back to previous
2089*d9f75844SAndroid Build Coastguard Worker // levels.
2090*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(pacer.pacing_rate(), kNominalPacingRate);
2091*d9f75844SAndroid Build Coastguard Worker }
2092*d9f75844SAndroid Build Coastguard Worker
TEST_F(PacingControllerTest,BudgetDoesNotAffectRetransmissionInsTrial)2093*d9f75844SAndroid Build Coastguard Worker TEST_F(PacingControllerTest, BudgetDoesNotAffectRetransmissionInsTrial) {
2094*d9f75844SAndroid Build Coastguard Worker const DataSize kPacketSize = DataSize::Bytes(1000);
2095*d9f75844SAndroid Build Coastguard Worker
2096*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPadding).Times(0);
2097*d9f75844SAndroid Build Coastguard Worker const test::ExplicitKeyValueConfig trials(
2098*d9f75844SAndroid Build Coastguard Worker "WebRTC-Pacer-FastRetransmissions/Enabled/");
2099*d9f75844SAndroid Build Coastguard Worker PacingController pacer(&clock_, &callback_, trials);
2100*d9f75844SAndroid Build Coastguard Worker pacer.SetPacingRates(kTargetRate, /*padding_rate=*/DataRate::Zero());
2101*d9f75844SAndroid Build Coastguard Worker
2102*d9f75844SAndroid Build Coastguard Worker // Send a video packet so that we have a bit debt.
2103*d9f75844SAndroid Build Coastguard Worker pacer.EnqueuePacket(BuildPacket(RtpPacketMediaType::kVideo, kVideoSsrc,
2104*d9f75844SAndroid Build Coastguard Worker /*sequence_number=*/1,
2105*d9f75844SAndroid Build Coastguard Worker /*capture_time=*/1, kPacketSize.bytes()));
2106*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPacket);
2107*d9f75844SAndroid Build Coastguard Worker pacer.ProcessPackets();
2108*d9f75844SAndroid Build Coastguard Worker EXPECT_GT(pacer.NextSendTime(), clock_.CurrentTime());
2109*d9f75844SAndroid Build Coastguard Worker
2110*d9f75844SAndroid Build Coastguard Worker // A retransmission packet should still be immediately processed.
2111*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPacket);
2112*d9f75844SAndroid Build Coastguard Worker pacer.EnqueuePacket(BuildPacket(RtpPacketMediaType::kRetransmission,
2113*d9f75844SAndroid Build Coastguard Worker kVideoSsrc,
2114*d9f75844SAndroid Build Coastguard Worker /*sequence_number=*/1,
2115*d9f75844SAndroid Build Coastguard Worker /*capture_time=*/1, kPacketSize.bytes()));
2116*d9f75844SAndroid Build Coastguard Worker pacer.ProcessPackets();
2117*d9f75844SAndroid Build Coastguard Worker }
2118*d9f75844SAndroid Build Coastguard Worker
TEST_F(PacingControllerTest,AbortsAfterReachingCircuitBreakLimit)2119*d9f75844SAndroid Build Coastguard Worker TEST_F(PacingControllerTest, AbortsAfterReachingCircuitBreakLimit) {
2120*d9f75844SAndroid Build Coastguard Worker const DataSize kPacketSize = DataSize::Bytes(1000);
2121*d9f75844SAndroid Build Coastguard Worker
2122*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPadding).Times(0);
2123*d9f75844SAndroid Build Coastguard Worker PacingController pacer(&clock_, &callback_, trials_);
2124*d9f75844SAndroid Build Coastguard Worker pacer.SetPacingRates(kTargetRate, /*padding_rate=*/DataRate::Zero());
2125*d9f75844SAndroid Build Coastguard Worker
2126*d9f75844SAndroid Build Coastguard Worker // Set the circuit breaker to abort after one iteration of the main
2127*d9f75844SAndroid Build Coastguard Worker // sending loop.
2128*d9f75844SAndroid Build Coastguard Worker pacer.SetCircuitBreakerThreshold(1);
2129*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(callback_, SendPacket).Times(1);
2130*d9f75844SAndroid Build Coastguard Worker
2131*d9f75844SAndroid Build Coastguard Worker // Send two packets.
2132*d9f75844SAndroid Build Coastguard Worker pacer.EnqueuePacket(BuildPacket(RtpPacketMediaType::kVideo, kVideoSsrc,
2133*d9f75844SAndroid Build Coastguard Worker /*sequence_number=*/1,
2134*d9f75844SAndroid Build Coastguard Worker /*capture_time=*/1, kPacketSize.bytes()));
2135*d9f75844SAndroid Build Coastguard Worker pacer.EnqueuePacket(BuildPacket(RtpPacketMediaType::kVideo, kVideoSsrc,
2136*d9f75844SAndroid Build Coastguard Worker /*sequence_number=*/2,
2137*d9f75844SAndroid Build Coastguard Worker /*capture_time=*/2, kPacketSize.bytes()));
2138*d9f75844SAndroid Build Coastguard Worker
2139*d9f75844SAndroid Build Coastguard Worker // Advance time to way past where both should be eligible for sending.
2140*d9f75844SAndroid Build Coastguard Worker clock_.AdvanceTime(TimeDelta::Seconds(1));
2141*d9f75844SAndroid Build Coastguard Worker
2142*d9f75844SAndroid Build Coastguard Worker pacer.ProcessPackets();
2143*d9f75844SAndroid Build Coastguard Worker }
2144*d9f75844SAndroid Build Coastguard Worker
TEST_F(PacingControllerTest,DoesNotPadIfProcessThreadIsBorked)2145*d9f75844SAndroid Build Coastguard Worker TEST_F(PacingControllerTest, DoesNotPadIfProcessThreadIsBorked) {
2146*d9f75844SAndroid Build Coastguard Worker PacingControllerPadding callback;
2147*d9f75844SAndroid Build Coastguard Worker PacingController pacer(&clock_, &callback, trials_);
2148*d9f75844SAndroid Build Coastguard Worker
2149*d9f75844SAndroid Build Coastguard Worker // Set both pacing and padding rate to be non-zero.
2150*d9f75844SAndroid Build Coastguard Worker pacer.SetPacingRates(kTargetRate, /*padding_rate=*/kTargetRate);
2151*d9f75844SAndroid Build Coastguard Worker
2152*d9f75844SAndroid Build Coastguard Worker // Add one packet to the queue, but do not send it yet.
2153*d9f75844SAndroid Build Coastguard Worker pacer.EnqueuePacket(BuildPacket(RtpPacketMediaType::kVideo, kVideoSsrc,
2154*d9f75844SAndroid Build Coastguard Worker /*sequence_number=*/1,
2155*d9f75844SAndroid Build Coastguard Worker /*capture_time=*/1,
2156*d9f75844SAndroid Build Coastguard Worker /*size=*/1000));
2157*d9f75844SAndroid Build Coastguard Worker
2158*d9f75844SAndroid Build Coastguard Worker // Advance time to waaay after the packet should have been sent.
2159*d9f75844SAndroid Build Coastguard Worker clock_.AdvanceTime(TimeDelta::Seconds(42));
2160*d9f75844SAndroid Build Coastguard Worker
2161*d9f75844SAndroid Build Coastguard Worker // `ProcessPackets()` should send the delayed packet, followed by a small
2162*d9f75844SAndroid Build Coastguard Worker // amount of missed padding.
2163*d9f75844SAndroid Build Coastguard Worker pacer.ProcessPackets();
2164*d9f75844SAndroid Build Coastguard Worker
2165*d9f75844SAndroid Build Coastguard Worker // The max padding window is the max replay duration + the target padding
2166*d9f75844SAndroid Build Coastguard Worker // duration.
2167*d9f75844SAndroid Build Coastguard Worker const DataSize kMaxPadding = (PacingController::kMaxPaddingReplayDuration +
2168*d9f75844SAndroid Build Coastguard Worker PacingController::kTargetPaddingDuration) *
2169*d9f75844SAndroid Build Coastguard Worker kTargetRate;
2170*d9f75844SAndroid Build Coastguard Worker
2171*d9f75844SAndroid Build Coastguard Worker EXPECT_LE(callback.padding_sent(), kMaxPadding.bytes<size_t>());
2172*d9f75844SAndroid Build Coastguard Worker }
2173*d9f75844SAndroid Build Coastguard Worker
2174*d9f75844SAndroid Build Coastguard Worker } // namespace
2175*d9f75844SAndroid Build Coastguard Worker } // namespace webrtc
2176