1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "cast/streaming/compound_rtcp_parser.h"
6
7 #include <chrono>
8 #include <cmath>
9
10 #include "cast/streaming/mock_compound_rtcp_parser_client.h"
11 #include "cast/streaming/rtcp_session.h"
12 #include "gmock/gmock.h"
13 #include "gtest/gtest.h"
14 #include "platform/api/time.h"
15 #include "util/chrono_helpers.h"
16
17 using testing::_;
18 using testing::Mock;
19 using testing::SaveArg;
20 using testing::StrictMock;
21
22 namespace openscreen {
23 namespace cast {
24 namespace {
25
26 constexpr Ssrc kSenderSsrc{1};
27 constexpr Ssrc kReceiverSsrc{2};
28
29 class CompoundRtcpParserTest : public testing::Test {
30 public:
session()31 RtcpSession* session() { return &session_; }
client()32 StrictMock<MockCompoundRtcpParserClient>* client() { return &client_; }
parser()33 CompoundRtcpParser* parser() { return &parser_; }
34
35 private:
36 RtcpSession session_{kSenderSsrc, kReceiverSsrc, Clock::now()};
37 StrictMock<MockCompoundRtcpParserClient> client_;
38 CompoundRtcpParser parser_{&session_, &client_};
39 };
40
TEST_F(CompoundRtcpParserTest,ProcessesEmptyPacket)41 TEST_F(CompoundRtcpParserTest, ProcessesEmptyPacket) {
42 const uint8_t kEmpty[0] = {};
43 // Expect NO calls to mock client.
44 EXPECT_TRUE(
45 parser()->Parse(absl::Span<const uint8_t>(kEmpty, 0), FrameId::first()));
46 }
47
TEST_F(CompoundRtcpParserTest,ReturnsErrorForGarbage)48 TEST_F(CompoundRtcpParserTest, ReturnsErrorForGarbage) {
49 const uint8_t kGarbage[] = {
50 0x42, 0x61, 0x16, 0x17, 0x26, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69,
51 0x6e, 0x67, 0x2f, 0x63, 0x61, 0x73, 0x74, 0x2f, 0x63, 0x6f, 0x6d, 0x70,
52 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x72, 0x74, 0x63, 0x70, 0x5f};
53 // Expect NO calls to mock client.
54 EXPECT_FALSE(parser()->Parse(kGarbage, FrameId::first()));
55 }
56
TEST_F(CompoundRtcpParserTest,ParsesReceiverReportWithoutReportBlock)57 TEST_F(CompoundRtcpParserTest, ParsesReceiverReportWithoutReportBlock) {
58 // clang-format off
59 const uint8_t kReceiverReportWithoutReportBlock[] = {
60 0b10000000, // Version=2, Padding=no, ReportCount=0.
61 201, // RTCP Packet type byte.
62 0x00, 0x01, // Length of remainder of packet, in 32-bit words.
63 0x00, 0x00, 0x00, 0x02, // Receiver SSRC.
64 };
65 // clang-format on
66
67 // Expect NO calls to mock client.
68 EXPECT_TRUE(
69 parser()->Parse(kReceiverReportWithoutReportBlock, FrameId::first()));
70 }
71
TEST_F(CompoundRtcpParserTest,ParsesReceiverReportWithReportBlock)72 TEST_F(CompoundRtcpParserTest, ParsesReceiverReportWithReportBlock) {
73 // clang-format off
74 const uint8_t kReceiverReportWithReportBlock[] = {
75 0b10000001, // Version=2, Padding=no, ReportCount=1.
76 201, // RTCP Packet type byte.
77 0x00, 0x07, // Length of remainder of packet, in 32-bit words.
78 0x00, 0x00, 0x00, 0x02, // Receiver SSRC.
79
80 // Report block:
81 0x00, 0x00, 0x00, 0x01, // Sender SSRC.
82 0x05, // Fraction Lost.
83 0x01, 0x02, 0x03, // Cumulative # packets lost.
84 0x09, 0x09, 0x09, 0x02, // Highest sequence number.
85 0x00, 0x00, 0x00, 0xaa, // Interarrival Jitter.
86 0x0b, 0x0c, 0x8f, 0xed, // Sender Report ID.
87 0x00, 0x01, 0x00, 0x00, // Delay since last sender report.
88 };
89 // clang-format on
90
91 RtcpReportBlock block;
92 EXPECT_CALL(*(client()), OnReceiverReport(_)).WillOnce(SaveArg<0>(&block));
93 EXPECT_TRUE(
94 parser()->Parse(kReceiverReportWithReportBlock, FrameId::first()));
95 Mock::VerifyAndClearExpectations(client());
96 EXPECT_EQ(kSenderSsrc, block.ssrc);
97 EXPECT_EQ(uint8_t{5}, block.packet_fraction_lost_numerator);
98 EXPECT_EQ(0x010203, block.cumulative_packets_lost);
99 EXPECT_EQ(uint32_t{0x09090902}, block.extended_high_sequence_number);
100 EXPECT_EQ(RtpTimeDelta::FromTicks(170), block.jitter);
101 EXPECT_EQ(StatusReportId{0x0b0c8fed}, block.last_status_report_id);
102 EXPECT_EQ(RtcpReportBlock::Delay(65536), block.delay_since_last_report);
103 }
104
TEST_F(CompoundRtcpParserTest,ParsesPictureLossIndicatorMessage)105 TEST_F(CompoundRtcpParserTest, ParsesPictureLossIndicatorMessage) {
106 // clang-format off
107 const uint8_t kPictureLossIndicatorPacket[] = {
108 0b10000000 | 1, // Version=2, Padding=no, Subtype=PLI.
109 206, // RTCP Packet type byte.
110 0x00, 0x02, // Length of remainder of packet, in 32-bit words.
111 0x00, 0x00, 0x00, 0x02, // Receiver SSRC.
112 0x00, 0x00, 0x00, 0x01, // Sender SSRC.
113 };
114
115 const uint8_t kPictureLossIndicatorPacketWithWrongReceiverSsrc[] = {
116 0b10000000 | 1, // Version=2, Padding=no, Subtype=PLI.
117 206, // RTCP Packet type byte.
118 0x00, 0x02, // Length of remainder of packet, in 32-bit words.
119 0x00, 0x00, 0x00, 0x03, // WRONG Receiver SSRC.
120 0x00, 0x00, 0x00, 0x01, // Sender SSRC.
121 };
122
123 const uint8_t kPictureLossIndicatorPacketWithWrongSenderSsrc[] = {
124 0b10000000 | 1, // Version=2, Padding=no, Subtype=PLI.
125 206, // RTCP Packet type byte.
126 0x00, 0x02, // Length of remainder of packet, in 32-bit words.
127 0x00, 0x00, 0x00, 0x02, // Receiver SSRC.
128 0x00, 0x00, 0x00, 0x03, // WRONG Sender SSRC.
129 };
130 // clang-format on
131
132 // The mock client should get a PLI notification when the packet is valid and
133 // contains the correct SSRCs.
134 EXPECT_CALL(*(client()), OnReceiverIndicatesPictureLoss());
135 EXPECT_TRUE(parser()->Parse(kPictureLossIndicatorPacket, FrameId::first()));
136 Mock::VerifyAndClearExpectations(client());
137
138 // The mock client should get no PLI notifications when either of the SSRCs is
139 // incorrect.
140 EXPECT_CALL(*(client()), OnReceiverIndicatesPictureLoss()).Times(0);
141 EXPECT_TRUE(parser()->Parse(kPictureLossIndicatorPacketWithWrongReceiverSsrc,
142 FrameId::first()));
143 Mock::VerifyAndClearExpectations(client());
144 EXPECT_CALL(*(client()), OnReceiverIndicatesPictureLoss()).Times(0);
145 EXPECT_TRUE(parser()->Parse(kPictureLossIndicatorPacketWithWrongSenderSsrc,
146 FrameId::first()));
147 Mock::VerifyAndClearExpectations(client());
148 }
149
150 // Tests that RTCP packets containing chronologically-old data are ignored. This
151 // test's methodology simulates a real-world possibility: A receiver sends a
152 // "Picture Loss Indicator" in one RTCP packet, and then it sends another packet
153 // ~1 second later without the PLI, indicating the problem has been resolved.
154 // However, the packets are delivered out-of-order by the network. In this case,
155 // the CompoundRtcpParser should ignore the stale packet containing the PLI.
TEST_F(CompoundRtcpParserTest,IgnoresStalePackets)156 TEST_F(CompoundRtcpParserTest, IgnoresStalePackets) {
157 // clang-format off
158 const uint8_t kNotStaleCompoundPacket[] = {
159 // Receiver report:
160 0b10000000, // Version=2, Padding=no, ReportCount=0.
161 201, // RTCP Packet type byte.
162 0x00, 0x01, // Length of remainder of packet, in 32-bit words.
163 0x00, 0x00, 0x00, 0x02, // Receiver SSRC.
164
165 // Receiver reference time report:
166 0b10000000, // Version=2, Padding=no.
167 207, // RTCP Packet type byte.
168 0x00, 0x04, // Length of remainder of packet, in 32-bit words.
169 0x00, 0x00, 0x00, 0x02, // Receiver SSRC.
170 0x04, // Block type = Receiver Reference Time Report
171 0x00, // Reserved byte.
172 0x00, 0x02, // Block length = 2.
173 0xe0, 0x73, 0x2e, 0x54, // NTP Timestamp (late evening on 2019-04-30).
174 0x80, 0x00, 0x00, 0x00,
175 };
176
177 const uint8_t kStaleCompoundPacketWithPli[] = {
178 // Picture loss indicator:
179 0b10000000 | 1, // Version=2, Padding=no, Subtype=PLI.
180 206, // RTCP Packet type byte.
181 0x00, 0x02, // Length of remainder of packet, in 32-bit words.
182 0x00, 0x00, 0x00, 0x02, // Receiver SSRC.
183 0x00, 0x00, 0x00, 0x01, // Sender SSRC.
184
185 // Receiver reference time report:
186 0b10000000, // Version=2, Padding=no.
187 207, // RTCP Packet type byte.
188 0x00, 0x04, // Length of remainder of packet, in 32-bit words.
189 0x00, 0x00, 0x00, 0x02, // Receiver SSRC.
190 0x04, // Block type = Receiver Reference Time Report
191 0x00, // Reserved byte.
192 0x00, 0x02, // Block length = 2.
193 0xe0, 0x73, 0x2e, 0x53, // NTP Timestamp (late evening on 2019-04-30).
194 0x42, 0x31, 0x20, 0x00,
195 };
196 // clang-format on
197
198 const auto expected_timestamp =
199 session()->ntp_converter().ToLocalTime(NtpTimestamp{0xe0732e5480000000});
200 EXPECT_CALL(*(client()), OnReceiverReferenceTimeAdvanced(expected_timestamp));
201 EXPECT_CALL(*(client()), OnReceiverIndicatesPictureLoss()).Times(0);
202 EXPECT_TRUE(parser()->Parse(kNotStaleCompoundPacket, FrameId::first()));
203 EXPECT_TRUE(parser()->Parse(kStaleCompoundPacketWithPli, FrameId::first()));
204 }
205
206 // Tests that unknown RTCP extended reports are ignored, but known ones are
207 // still parsed when sent alongside the unknown ones.
TEST_F(CompoundRtcpParserTest,IgnoresUnknownExtendedReports)208 TEST_F(CompoundRtcpParserTest, IgnoresUnknownExtendedReports) {
209 // clang-format off
210 const uint8_t kPacketWithThreeExtendedReports[] = {
211 0b10000000, // Version=2, Padding=no.
212 207, // RTCP Packet type byte.
213 0x00, 0x0c, // Length of remainder of packet, in 32-bit words.
214 0x00, 0x00, 0x00, 0x02, // Receiver SSRC.
215
216 // Unknown extended report:
217 0x02, // Block type = unknown (2)
218 0x00, // Reserved byte.
219 0x00, 0x06, // Block length = 6 words.
220 0x01, 0x01, 0x01, 0x01,
221 0x02, 0x02, 0x02, 0x02,
222 0x03, 0x03, 0x03, 0x03,
223 0x04, 0x04, 0x04, 0x04,
224 0x05, 0x05, 0x05, 0x05,
225 0x06, 0x06, 0x06, 0x06,
226
227 // Receiver Reference Time Report:
228 0x04, // Block type = RRTR
229 0x00, // Reserved byte.
230 0x00, 0x02, // Block length = 2 words.
231 0xe0, 0x73, 0x2e, 0x55, // NTP Timestamp (late evening on 2019-04-30).
232 0x00, 0x00, 0x00, 0x00,
233
234 // Another unknown extended report:
235 0x00, // Block type = unknown (0)
236 0x00, // Reserved byte.
237 0x00, 0x00, // Block length = 0 words.
238 };
239 // clang-format on
240
241 const auto expected_timestamp =
242 session()->ntp_converter().ToLocalTime(NtpTimestamp{0xe0732e5500000000});
243 EXPECT_CALL(*(client()), OnReceiverReferenceTimeAdvanced(expected_timestamp));
244 EXPECT_TRUE(
245 parser()->Parse(kPacketWithThreeExtendedReports, FrameId::first()));
246 }
247
248 // Tests that a simple Cast Feedback packet is parsed, and the checkpoint frame
249 // ID is properly bit-extended, based on the current state of the Sender.
TEST_F(CompoundRtcpParserTest,ParsesSimpleFeedback)250 TEST_F(CompoundRtcpParserTest, ParsesSimpleFeedback) {
251 // clang-format off
252 const uint8_t kFeedbackPacket[] = {
253 0b10000000 | 15, // Version=2, Padding=no, Subtype=Feedback.
254 206, // RTCP Packet type byte.
255 0x00, 0x04, // Length of remainder of packet, in 32-bit words.
256 0x00, 0x00, 0x00, 0x02, // Receiver SSRC.
257 0x00, 0x00, 0x00, 0x01, // Sender SSRC.
258 'C', 'A', 'S', 'T',
259 0x0a, // Checkpoint Frame ID = 10.
260 0x00, // No NACKs.
261 0x02, 0x26, // Playout delay = 550 ms.
262 };
263 // clang-format on
264
265 // First scenario: Valid range of FrameIds is [0,42].
266 const auto kMaxFeedbackFrameId0 = FrameId::first() + 42;
267 const auto expected_frame_id0 = FrameId::first() + 10;
268 const auto expected_playout_delay = milliseconds(550);
269 EXPECT_CALL(*(client()),
270 OnReceiverCheckpoint(expected_frame_id0, expected_playout_delay));
271 EXPECT_TRUE(parser()->Parse(kFeedbackPacket, kMaxFeedbackFrameId0));
272 Mock::VerifyAndClearExpectations(client());
273
274 // Second scenario: Valid range of FrameIds is [299,554]. Note: 544 == 0x22a.
275 const auto kMaxFeedbackFrameId1 = FrameId::first() + 0x22a;
276 const auto expected_frame_id1 = FrameId::first() + 0x20a;
277 EXPECT_CALL(*(client()),
278 OnReceiverCheckpoint(expected_frame_id1, expected_playout_delay));
279 EXPECT_TRUE(parser()->Parse(kFeedbackPacket, kMaxFeedbackFrameId1));
280 Mock::VerifyAndClearExpectations(client());
281 }
282
283 // Tests NACK feedback parsing, and that redundant NACKs are de-duped, and that
284 // the results are delivered to the client sorted.
TEST_F(CompoundRtcpParserTest,ParsesFeedbackWithNacks)285 TEST_F(CompoundRtcpParserTest, ParsesFeedbackWithNacks) {
286 // clang-format off
287 const uint8_t kFeedbackPacket[] = {
288 0b10000000 | 15, // Version=2, Padding=no, Subtype=Feedback.
289 206, // RTCP Packet type byte.
290 0x00, 0x0b, // Length of remainder of packet, in 32-bit words.
291 0x00, 0x00, 0x00, 0x02, // Receiver SSRC.
292 0x00, 0x00, 0x00, 0x01, // Sender SSRC.
293 'C', 'A', 'S', 'T',
294 0x0a, // Checkpoint Frame ID = 10.
295 0x07, // Seven NACKs.
296 0x02, 0x28, // Playout delay = 552 ms.
297 0x0b, 0x00, 0x03, 0b00000000, // NACK Packet 3 in Frame 11.
298 0x0b, 0x00, 0x07, 0b10001101, // NACK Packet 7-8, 10-11, 15 in Frame 11.
299 0x0d, 0xff, 0xff, 0b00000000, // NACK all packets in Frame 13.
300 0x0b, 0x00, 0x0b, 0b00000000, // Redundant: NACK packet 11 in Frame 11.
301 0x0c, 0xff, 0xff, 0b00000000, // NACK all packets in Frame 12.
302 0x0d, 0x00, 0x01, 0b00000000, // Redundant: NACK packet 1 in Frame 13.
303 0x0e, 0x00, 0x00, 0b01000010, // NACK packets 0, 2, 7 in Frame 14.
304 };
305 // clang-format on
306
307 // The de-duped and sorted list of the frame/packet NACKs expected when
308 // parsing kFeedbackPacket:
309 const std::vector<PacketNack> kMissingPackets = {
310 {FrameId::first() + 11, 3},
311 {FrameId::first() + 11, 7},
312 {FrameId::first() + 11, 8},
313 {FrameId::first() + 11, 10},
314 {FrameId::first() + 11, 11},
315 {FrameId::first() + 11, 15},
316 {FrameId::first() + 12, kAllPacketsLost},
317 {FrameId::first() + 13, kAllPacketsLost},
318 {FrameId::first() + 14, 0},
319 {FrameId::first() + 14, 2},
320 {FrameId::first() + 14, 7},
321 };
322
323 const auto kMaxFeedbackFrameId = FrameId::first() + 42;
324 const auto expected_frame_id = FrameId::first() + 10;
325 const auto expected_playout_delay = milliseconds(552);
326 EXPECT_CALL(*(client()),
327 OnReceiverCheckpoint(expected_frame_id, expected_playout_delay));
328 EXPECT_CALL(*(client()), OnReceiverIsMissingPackets(kMissingPackets));
329 EXPECT_TRUE(parser()->Parse(kFeedbackPacket, kMaxFeedbackFrameId));
330 }
331
332 // Tests the CST2 "later frame ACK" parsing: Both the common "2 bytes of bit
333 // vector" case, and a "multiple words of bit vector" case.
TEST_F(CompoundRtcpParserTest,ParsesFeedbackWithAcks)334 TEST_F(CompoundRtcpParserTest, ParsesFeedbackWithAcks) {
335 // clang-format off
336 const uint8_t kSmallerFeedbackPacket[] = {
337 0b10000000 | 15, // Version=2, Padding=no, Subtype=Feedback.
338 206, // RTCP Packet type byte.
339 0x00, 0x07, // Length of remainder of packet, in 32-bit words.
340 0x00, 0x00, 0x00, 0x02, // Receiver SSRC.
341 0x00, 0x00, 0x00, 0x01, // Sender SSRC.
342 'C', 'A', 'S', 'T',
343 0x0a, // Checkpoint Frame ID = 10.
344 0x01, // One NACK.
345 0x01, 0x26, // Playout delay = 294 ms.
346 0x0b, 0x00, 0x03, 0b00000000, // NACK Packet 3 in Frame 11.
347 'C', 'S', 'T', '2',
348 0x99, // Feedback counter.
349 0x02, // 2 bytes of ACK bit vector.
350 0b00000010, 0b00000000, // ACK only frame 13.
351 };
352
353 const uint8_t kLargerFeedbackPacket[] = {
354 0b10000000 | 15, // Version=2, Padding=no, Subtype=Feedback.
355 206, // RTCP Packet type byte.
356 0x00, 0x08, // Length of remainder of packet, in 32-bit words.
357 0x00, 0x00, 0x00, 0x02, // Receiver SSRC.
358 0x00, 0x00, 0x00, 0x01, // Sender SSRC.
359 'C', 'A', 'S', 'T',
360 0x0a, // Checkpoint Frame ID = 10.
361 0x00, // Zero NACKs.
362 0x01, 0x26, // Playout delay = 294 ms.
363 'C', 'S', 'T', '2',
364 0x99, // Feedback counter.
365 0x0a, // 10 bytes of ACK bit vector.
366 0b11111111, 0b11111111, // ACK frames 12-27.
367 0b00000000, 0b00000001, 0b00000000, 0b00000000, // ACK frame 36.
368 0b00000000, 0b00000000, 0b00000000, 0b10000000, // ACK frame 91.
369 };
370 // clang-format on
371
372 // From the smaller packet: The single frame ACK and single packet NACK.
373 const std::vector<FrameId> kFrame13Only = {FrameId::first() + 13};
374 const std::vector<PacketNack> kFrame11Packet3Only = {
375 {FrameId::first() + 11, 3}};
376
377 // From the larger packet: Many frame ACKs.
378 const std::vector<FrameId> kManyFrames = {
379 FrameId::first() + 12, FrameId::first() + 13, FrameId::first() + 14,
380 FrameId::first() + 15, FrameId::first() + 16, FrameId::first() + 17,
381 FrameId::first() + 18, FrameId::first() + 19, FrameId::first() + 20,
382 FrameId::first() + 21, FrameId::first() + 22, FrameId::first() + 23,
383 FrameId::first() + 24, FrameId::first() + 25, FrameId::first() + 26,
384 FrameId::first() + 27, FrameId::first() + 36, FrameId::first() + 91,
385 };
386
387 // Test the smaller packet.
388 const auto kMaxFeedbackFrameId = FrameId::first() + 100;
389 const auto expected_frame_id = FrameId::first() + 10;
390 const auto expected_playout_delay = milliseconds(294);
391 EXPECT_CALL(*(client()),
392 OnReceiverCheckpoint(expected_frame_id, expected_playout_delay));
393 EXPECT_CALL(*(client()), OnReceiverHasFrames(kFrame13Only));
394 EXPECT_CALL(*(client()), OnReceiverIsMissingPackets(kFrame11Packet3Only));
395 EXPECT_TRUE(parser()->Parse(kSmallerFeedbackPacket, kMaxFeedbackFrameId));
396 Mock::VerifyAndClearExpectations(client());
397
398 // Test the larger ACK packet.
399 EXPECT_CALL(*(client()),
400 OnReceiverCheckpoint(expected_frame_id, expected_playout_delay));
401 EXPECT_CALL(*(client()), OnReceiverHasFrames(kManyFrames));
402 EXPECT_TRUE(parser()->Parse(kLargerFeedbackPacket, kMaxFeedbackFrameId));
403 Mock::VerifyAndClearExpectations(client());
404 }
405
406 } // namespace
407 } // namespace cast
408 } // namespace openscreen
409