blob: 9ed19642c742033f2c85cfff026b7934fd4b78d2 [file] [log] [blame]
Erik Språngb73c0582022-05-02 19:18:081/*
2 * Copyright (c) 2022 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "modules/pacing/prioritized_packet_queue.h"
12
13#include <utility>
14
15#include "api/units/time_delta.h"
Henrik Boströmef241162022-06-06 14:19:1116#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
Erik Språngb73c0582022-05-02 19:18:0817#include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
18#include "rtc_base/checks.h"
19#include "test/gmock.h"
20#include "test/gtest.h"
21
22namespace webrtc {
23namespace {
24
25constexpr uint32_t kDefaultSsrc = 123;
26constexpr int kDefaultPayloadSize = 789;
27
28std::unique_ptr<RtpPacketToSend> CreatePacket(RtpPacketMediaType type,
29 uint16_t sequence_number,
Erik Språngaab1bde2023-04-06 13:47:0730 uint32_t ssrc = kDefaultSsrc,
31 bool is_key_frame = false) {
Erik Språngb73c0582022-05-02 19:18:0832 auto packet = std::make_unique<RtpPacketToSend>(/*extensions=*/nullptr);
33 packet->set_packet_type(type);
34 packet->SetSsrc(ssrc);
35 packet->SetSequenceNumber(sequence_number);
36 packet->SetPayloadSize(kDefaultPayloadSize);
Erik Språngaab1bde2023-04-06 13:47:0737 packet->set_is_key_frame(is_key_frame);
Erik Språngb73c0582022-05-02 19:18:0838 return packet;
39}
40
41} // namespace
42
43TEST(PrioritizedPacketQueue, ReturnsPacketsInPrioritizedOrder) {
44 Timestamp now = Timestamp::Zero();
45 PrioritizedPacketQueue queue(now);
46
47 // Add packets in low to high packet order.
48 queue.Push(now, CreatePacket(RtpPacketMediaType::kPadding, /*seq=*/1));
49 queue.Push(now, CreatePacket(RtpPacketMediaType::kVideo, /*seq=*/2));
50 queue.Push(now, CreatePacket(RtpPacketMediaType::kForwardErrorCorrection,
51 /*seq=*/3));
52 queue.Push(now, CreatePacket(RtpPacketMediaType::kRetransmission, /*seq=*/4));
53 queue.Push(now, CreatePacket(RtpPacketMediaType::kAudio, /*seq=*/5));
54
55 // Packets should be returned in high to low order.
56 EXPECT_EQ(queue.Pop()->SequenceNumber(), 5);
57 EXPECT_EQ(queue.Pop()->SequenceNumber(), 4);
58 // Video and FEC prioritized equally - but video was enqueued first.
59 EXPECT_EQ(queue.Pop()->SequenceNumber(), 2);
60 EXPECT_EQ(queue.Pop()->SequenceNumber(), 3);
61 EXPECT_EQ(queue.Pop()->SequenceNumber(), 1);
62}
63
64TEST(PrioritizedPacketQueue, ReturnsEqualPrioPacketsInRoundRobinOrder) {
65 Timestamp now = Timestamp::Zero();
66 PrioritizedPacketQueue queue(now);
67
68 // Insert video packets (prioritized equally), simulating a simulcast-type use
69 // case.
70 queue.Push(now,
71 CreatePacket(RtpPacketMediaType::kVideo, /*seq=*/1, /*ssrc=*/100));
72
73 queue.Push(now,
74 CreatePacket(RtpPacketMediaType::kVideo, /*seq=*/2, /*ssrc=*/101));
75 queue.Push(now,
76 CreatePacket(RtpPacketMediaType::kVideo, /*seq=*/3, /*ssrc=*/101));
77
78 queue.Push(now,
79 CreatePacket(RtpPacketMediaType::kVideo, /*seq=*/4, /*ssrc=*/102));
80 queue.Push(now,
81 CreatePacket(RtpPacketMediaType::kVideo, /*seq=*/5, /*ssrc=*/102));
82 queue.Push(now,
83 CreatePacket(RtpPacketMediaType::kVideo, /*seq=*/6, /*ssrc=*/102));
84 queue.Push(now,
85 CreatePacket(RtpPacketMediaType::kVideo, /*seq=*/7, /*ssrc=*/102));
86
87 // First packet from each SSRC.
88 EXPECT_EQ(queue.Pop()->SequenceNumber(), 1);
89 EXPECT_EQ(queue.Pop()->SequenceNumber(), 2);
90 EXPECT_EQ(queue.Pop()->SequenceNumber(), 4);
91
92 // Second packets from streams that have packets left.
93 EXPECT_EQ(queue.Pop()->SequenceNumber(), 3);
94 EXPECT_EQ(queue.Pop()->SequenceNumber(), 5);
95
96 // Only packets from last stream remaining.
97 EXPECT_EQ(queue.Pop()->SequenceNumber(), 6);
98 EXPECT_EQ(queue.Pop()->SequenceNumber(), 7);
99}
100
101TEST(PrioritizedPacketQueue, ReportsSizeInPackets) {
102 PrioritizedPacketQueue queue(/*creation_time=*/Timestamp::Zero());
103 EXPECT_EQ(queue.SizeInPackets(), 0);
104
105 queue.Push(/*enqueue_time=*/Timestamp::Zero(),
106 CreatePacket(RtpPacketMediaType::kVideo,
107 /*seq_no=*/1));
108 EXPECT_EQ(queue.SizeInPackets(), 1);
109
110 queue.Pop();
111 EXPECT_EQ(queue.SizeInPackets(), 0);
112}
113
114TEST(PrioritizedPacketQueue, ReportsPayloadSize) {
115 PrioritizedPacketQueue queue(/*creation_time=*/Timestamp::Zero());
116 EXPECT_EQ(queue.SizeInPayloadBytes(), DataSize::Zero());
117
118 queue.Push(/*enqueue_time=*/Timestamp::Zero(),
119 CreatePacket(RtpPacketMediaType::kVideo,
120 /*seq_no=*/1));
121 EXPECT_EQ(queue.SizeInPayloadBytes(), DataSize::Bytes(kDefaultPayloadSize));
122
123 queue.Pop();
124 EXPECT_EQ(queue.SizeInPayloadBytes(), DataSize::Zero());
125}
126
127TEST(PrioritizedPacketQueue, ReportsPaddingSize) {
128 PrioritizedPacketQueue queue(/*creation_time=*/Timestamp::Zero());
129 EXPECT_EQ(queue.SizeInPayloadBytes(), DataSize::Zero());
130 static constexpr DataSize kPaddingSize = DataSize::Bytes(190);
131
132 auto packet = std::make_unique<RtpPacketToSend>(/*extensions=*/nullptr);
133 packet->set_packet_type(RtpPacketMediaType::kPadding);
134 packet->SetSsrc(kDefaultSsrc);
135 packet->SetSequenceNumber(/*seq=*/1);
136 packet->SetPadding(kPaddingSize.bytes());
137 queue.Push(/*enqueue_time=*/Timestamp::Zero(), std::move(packet));
138 EXPECT_EQ(queue.SizeInPayloadBytes(), kPaddingSize);
139
140 queue.Pop();
141 EXPECT_EQ(queue.SizeInPayloadBytes(), DataSize::Zero());
142}
143
144TEST(PrioritizedPacketQueue, ReportsOldestEnqueueTime) {
145 PrioritizedPacketQueue queue(/*creation_time=*/Timestamp::Zero());
146 EXPECT_EQ(queue.OldestEnqueueTime(), Timestamp::MinusInfinity());
147
148 // Add three packets, with the middle packet having higher prio.
149 queue.Push(Timestamp::Millis(10),
150 CreatePacket(RtpPacketMediaType::kPadding, /*seq=*/1));
151 queue.Push(Timestamp::Millis(20),
152 CreatePacket(RtpPacketMediaType::kVideo, /*seq=*/2));
153 queue.Push(Timestamp::Millis(30),
154 CreatePacket(RtpPacketMediaType::kPadding, /*seq=*/3));
155 EXPECT_EQ(queue.OldestEnqueueTime(), Timestamp::Millis(10));
156
157 queue.Pop(); // Pop packet with enqueue time 20.
158 EXPECT_EQ(queue.OldestEnqueueTime(), Timestamp::Millis(10));
159
160 queue.Pop(); // Pop packet with enqueue time 10.
161 EXPECT_EQ(queue.OldestEnqueueTime(), Timestamp::Millis(30));
162
163 queue.Pop(); // Pop packet with enqueue time 30, queue empty again.
164 EXPECT_EQ(queue.OldestEnqueueTime(), Timestamp::MinusInfinity());
165}
166
167TEST(PrioritizedPacketQueue, ReportsAverageQueueTime) {
168 PrioritizedPacketQueue queue(/*creation_time=*/Timestamp::Zero());
169 EXPECT_EQ(queue.AverageQueueTime(), TimeDelta::Zero());
170
171 // Add three packets, with the middle packet having higher prio.
172 queue.Push(Timestamp::Millis(10),
173 CreatePacket(RtpPacketMediaType::kPadding, /*seq=*/1));
174 queue.Push(Timestamp::Millis(20),
175 CreatePacket(RtpPacketMediaType::kVideo, /*seq=*/2));
176 queue.Push(Timestamp::Millis(30),
177 CreatePacket(RtpPacketMediaType::kPadding, /*seq=*/3));
178
179 queue.UpdateAverageQueueTime(Timestamp::Millis(40));
180 // Packets have waited 30, 20, 10 ms -> average = 20ms.
181 EXPECT_EQ(queue.AverageQueueTime(), TimeDelta::Millis(20));
182
183 queue.Pop(); // Pop packet with enqueue time 20.
184 EXPECT_EQ(queue.AverageQueueTime(), TimeDelta::Millis(20));
185
186 queue.Pop(); // Pop packet with enqueue time 10.
187 EXPECT_EQ(queue.AverageQueueTime(), TimeDelta::Millis(10));
188
189 queue.Pop(); // Pop packet with enqueue time 30, queue empty again.
190 EXPECT_EQ(queue.AverageQueueTime(), TimeDelta::Zero());
191}
192
193TEST(PrioritizedPacketQueue, SubtractsPusedTimeFromAverageQueueTime) {
194 PrioritizedPacketQueue queue(/*creation_time=*/Timestamp::Zero());
195 EXPECT_EQ(queue.AverageQueueTime(), TimeDelta::Zero());
196
197 // Add a packet and then enable paused state.
198 queue.Push(Timestamp::Millis(100),
199 CreatePacket(RtpPacketMediaType::kPadding, /*seq=*/1));
200 queue.SetPauseState(true, Timestamp::Millis(600));
201 EXPECT_EQ(queue.AverageQueueTime(), TimeDelta::Millis(500));
202
203 // Enqueue a packet 500ms into the paused state. Queue time of
204 // original packet is still seen as 500ms and new one has 0ms giving
205 // an average of 250ms.
206 queue.Push(Timestamp::Millis(1100),
207 CreatePacket(RtpPacketMediaType::kVideo, /*seq=*/2));
208 EXPECT_EQ(queue.AverageQueueTime(), TimeDelta::Millis(250));
209
210 // Unpause some time later, queue time still unchanged.
211 queue.SetPauseState(false, Timestamp::Millis(1600));
212 EXPECT_EQ(queue.AverageQueueTime(), TimeDelta::Millis(250));
213
214 // Update queue time 500ms after pause state ended.
215 queue.UpdateAverageQueueTime(Timestamp::Millis(2100));
216 EXPECT_EQ(queue.AverageQueueTime(), TimeDelta::Millis(750));
217}
218
Erik Språngc18a8fd2022-08-20 12:34:20219TEST(PrioritizedPacketQueue, ReportsLeadingPacketEnqueueTime) {
Erik Språngb73c0582022-05-02 19:18:08220 PrioritizedPacketQueue queue(/*creation_time=*/Timestamp::Zero());
Erik Språngc18a8fd2022-08-20 12:34:20221 EXPECT_EQ(queue.LeadingPacketEnqueueTime(RtpPacketMediaType::kAudio),
222 Timestamp::MinusInfinity());
223 EXPECT_EQ(queue.LeadingPacketEnqueueTime(RtpPacketMediaType::kVideo),
224 Timestamp::MinusInfinity());
Erik Språngb73c0582022-05-02 19:18:08225
226 queue.Push(Timestamp::Millis(10),
227 CreatePacket(RtpPacketMediaType::kVideo, /*seq=*/1));
Erik Språngc18a8fd2022-08-20 12:34:20228 EXPECT_EQ(queue.LeadingPacketEnqueueTime(RtpPacketMediaType::kAudio),
229 Timestamp::MinusInfinity());
230 EXPECT_EQ(queue.LeadingPacketEnqueueTime(RtpPacketMediaType::kVideo),
231 Timestamp::Millis(10));
Erik Språngb73c0582022-05-02 19:18:08232
233 queue.Push(Timestamp::Millis(20),
234 CreatePacket(RtpPacketMediaType::kAudio, /*seq=*/2));
235
Erik Språngc18a8fd2022-08-20 12:34:20236 EXPECT_EQ(queue.LeadingPacketEnqueueTime(RtpPacketMediaType::kAudio),
237 Timestamp::Millis(20));
238 EXPECT_EQ(queue.LeadingPacketEnqueueTime(RtpPacketMediaType::kVideo),
239 Timestamp::Millis(10));
Erik Språngb73c0582022-05-02 19:18:08240
241 queue.Pop(); // Pop audio packet.
Erik Språngc18a8fd2022-08-20 12:34:20242 EXPECT_EQ(queue.LeadingPacketEnqueueTime(RtpPacketMediaType::kAudio),
243 Timestamp::MinusInfinity());
244 EXPECT_EQ(queue.LeadingPacketEnqueueTime(RtpPacketMediaType::kVideo),
245 Timestamp::Millis(10));
246
247 queue.Pop(); // Pop video packet.
248 EXPECT_EQ(queue.LeadingPacketEnqueueTime(RtpPacketMediaType::kAudio),
249 Timestamp::MinusInfinity());
250 EXPECT_EQ(queue.LeadingPacketEnqueueTime(RtpPacketMediaType::kVideo),
251 Timestamp::MinusInfinity());
Erik Språngb73c0582022-05-02 19:18:08252}
253
Henrik Boströmef241162022-06-06 14:19:11254TEST(PrioritizedPacketQueue,
255 PushAndPopUpdatesSizeInPacketsPerRtpPacketMediaType) {
256 Timestamp now = Timestamp::Zero();
257 PrioritizedPacketQueue queue(now);
258
259 // Initially all sizes are zero.
260 for (size_t i = 0; i < kNumMediaTypes; ++i) {
261 EXPECT_EQ(queue.SizeInPacketsPerRtpPacketMediaType()[i], 0);
262 }
263
264 // Push packets.
265 queue.Push(now, CreatePacket(RtpPacketMediaType::kAudio, 1));
266 EXPECT_EQ(queue.SizeInPacketsPerRtpPacketMediaType()[static_cast<size_t>(
267 RtpPacketMediaType::kAudio)],
268 1);
269
270 queue.Push(now, CreatePacket(RtpPacketMediaType::kVideo, 2));
271 EXPECT_EQ(queue.SizeInPacketsPerRtpPacketMediaType()[static_cast<size_t>(
272 RtpPacketMediaType::kVideo)],
273 1);
274
275 queue.Push(now, CreatePacket(RtpPacketMediaType::kRetransmission, 3));
276 EXPECT_EQ(queue.SizeInPacketsPerRtpPacketMediaType()[static_cast<size_t>(
277 RtpPacketMediaType::kRetransmission)],
278 1);
279
280 queue.Push(now, CreatePacket(RtpPacketMediaType::kForwardErrorCorrection, 4));
281 EXPECT_EQ(queue.SizeInPacketsPerRtpPacketMediaType()[static_cast<size_t>(
282 RtpPacketMediaType::kForwardErrorCorrection)],
283 1);
284
285 queue.Push(now, CreatePacket(RtpPacketMediaType::kPadding, 5));
286 EXPECT_EQ(queue.SizeInPacketsPerRtpPacketMediaType()[static_cast<size_t>(
287 RtpPacketMediaType::kPadding)],
288 1);
289
290 // Now all sizes are 1.
291 for (size_t i = 0; i < kNumMediaTypes; ++i) {
292 EXPECT_EQ(queue.SizeInPacketsPerRtpPacketMediaType()[i], 1);
293 }
294
295 // Popping happens in a priority order based on media type. This test does not
296 // assert what this order is, only that the counter for the popped packet's
297 // media type is decremented.
298 for (size_t i = 0; i < kNumMediaTypes; ++i) {
299 auto popped_packet = queue.Pop();
300 EXPECT_EQ(queue.SizeInPacketsPerRtpPacketMediaType()[static_cast<size_t>(
301 popped_packet->packet_type().value())],
302 0);
303 }
304
305 // We've popped all packets, so all sizes are zero.
306 for (size_t i = 0; i < kNumMediaTypes; ++i) {
307 EXPECT_EQ(queue.SizeInPacketsPerRtpPacketMediaType()[i], 0);
308 }
309}
310
Erik Språng1b11b582022-12-09 20:38:44311TEST(PrioritizedPacketQueue, ClearsPackets) {
312 Timestamp now = Timestamp::Zero();
313 PrioritizedPacketQueue queue(now);
314 const uint32_t kSsrc = 1;
315
316 // Add two packets of each type, all using the same SSRC.
317 int sequence_number = 0;
318 for (size_t i = 0; i < kNumMediaTypes; ++i) {
319 queue.Push(now, CreatePacket(static_cast<RtpPacketMediaType>(i),
320 sequence_number++, kSsrc));
321 queue.Push(now, CreatePacket(static_cast<RtpPacketMediaType>(i),
322 sequence_number++, kSsrc));
323 }
324 EXPECT_EQ(queue.SizeInPackets(), 2 * int{kNumMediaTypes});
325
326 // Remove all of them.
327 queue.RemovePacketsForSsrc(kSsrc);
328 EXPECT_TRUE(queue.Empty());
329}
330
331TEST(PrioritizedPacketQueue, ClearPacketsAffectsOnlySpecifiedSsrc) {
332 Timestamp now = Timestamp::Zero();
333 PrioritizedPacketQueue queue(now);
334 const uint32_t kRemovingSsrc = 1;
335 const uint32_t kStayingSsrc = 2;
336
337 // Add an audio packet and a retransmission for the SSRC we will remove,
338 // ensuring they are first in line.
339 queue.Push(
340 now, CreatePacket(RtpPacketMediaType::kAudio, /*seq=*/1, kRemovingSsrc));
341 queue.Push(now, CreatePacket(RtpPacketMediaType::kRetransmission, /*seq=*/2,
342 kRemovingSsrc));
343
344 // Add a video packet and a retransmission for the SSRC that will remain.
345 // The retransmission packets now both have pointers to their respective qeues
346 // from the same prio level.
347 queue.Push(now,
348 CreatePacket(RtpPacketMediaType::kVideo, /*seq=*/3, kStayingSsrc));
349 queue.Push(now, CreatePacket(RtpPacketMediaType::kRetransmission, /*seq=*/4,
350 kStayingSsrc));
351
352 EXPECT_EQ(queue.SizeInPackets(), 4);
353
354 // Clear the first two packets.
355 queue.RemovePacketsForSsrc(kRemovingSsrc);
356 EXPECT_EQ(queue.SizeInPackets(), 2);
357
358 // We should get the single remaining retransmission first, then the video
359 // packet.
360 EXPECT_EQ(queue.Pop()->SequenceNumber(), 4);
361 EXPECT_EQ(queue.Pop()->SequenceNumber(), 3);
362 EXPECT_TRUE(queue.Empty());
363}
364
Erik Språngaab1bde2023-04-06 13:47:07365TEST(PrioritizedPacketQueue, ReportsKeyframePackets) {
366 Timestamp now = Timestamp::Zero();
367 PrioritizedPacketQueue queue(now);
368 const uint32_t kVideoSsrc1 = 1234;
369 const uint32_t kVideoSsrc2 = 2345;
370
371 EXPECT_FALSE(queue.HasKeyframePackets(kVideoSsrc1));
372 EXPECT_FALSE(queue.HasKeyframePackets(kVideoSsrc2));
373
374 queue.Push(now, CreatePacket(RtpPacketMediaType::kVideo, /*seq=*/1,
375 kVideoSsrc1, /*is_key_frame=*/true));
376 queue.Push(now, CreatePacket(RtpPacketMediaType::kVideo, /*seq=*/11,
377 kVideoSsrc2, /*is_key_frame=*/false));
378
379 EXPECT_TRUE(queue.HasKeyframePackets(kVideoSsrc1));
380 EXPECT_FALSE(queue.HasKeyframePackets(kVideoSsrc2));
381
382 queue.Push(now, CreatePacket(RtpPacketMediaType::kVideo, /*seq=*/2,
383 kVideoSsrc1, /*is_key_frame=*/true));
384 queue.Push(now, CreatePacket(RtpPacketMediaType::kVideo, /*seq=*/12,
385 kVideoSsrc2, /*is_key_frame=*/true));
386
387 EXPECT_TRUE(queue.HasKeyframePackets(kVideoSsrc1));
388 EXPECT_TRUE(queue.HasKeyframePackets(kVideoSsrc2));
389
390 queue.Push(now, CreatePacket(RtpPacketMediaType::kVideo, /*seq=*/3,
391 kVideoSsrc1, /*is_key_frame=*/false));
392 queue.Push(now, CreatePacket(RtpPacketMediaType::kVideo, /*seq=*/13,
393 kVideoSsrc2, /*is_key_frame=*/true));
394
395 EXPECT_TRUE(queue.HasKeyframePackets(kVideoSsrc1));
396 EXPECT_TRUE(queue.HasKeyframePackets(kVideoSsrc2));
397
398 EXPECT_EQ(queue.Pop()->SequenceNumber(), 1);
399 EXPECT_EQ(queue.Pop()->SequenceNumber(), 11);
400
401 EXPECT_TRUE(queue.HasKeyframePackets(kVideoSsrc1));
402 EXPECT_TRUE(queue.HasKeyframePackets(kVideoSsrc2));
403
404 EXPECT_EQ(queue.Pop()->SequenceNumber(), 2);
405 EXPECT_EQ(queue.Pop()->SequenceNumber(), 12);
406
407 EXPECT_FALSE(queue.HasKeyframePackets(kVideoSsrc1));
408 EXPECT_TRUE(queue.HasKeyframePackets(kVideoSsrc2));
409
410 queue.RemovePacketsForSsrc(kVideoSsrc2);
411
412 EXPECT_FALSE(queue.HasKeyframePackets(kVideoSsrc1));
413 EXPECT_FALSE(queue.HasKeyframePackets(kVideoSsrc2));
414}
415
Erik Språngb73c0582022-05-02 19:18:08416} // namespace webrtc