xref: /aosp_15_r20/external/openscreen/cast/streaming/rtp_packet_parser_unittest.cc (revision 3f982cf4871df8771c9d4abe6e9a6f8d829b2736)
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/rtp_packet_parser.h"
6 
7 #include "cast/streaming/rtp_defines.h"
8 #include "gtest/gtest.h"
9 #include "util/big_endian.h"
10 
11 namespace openscreen {
12 namespace cast {
13 namespace {
14 
15 // Tests that a simple packet for a key frame can be parsed.
TEST(RtpPacketParserTest,ParsesPacketForKeyFrame)16 TEST(RtpPacketParserTest, ParsesPacketForKeyFrame) {
17   // clang-format off
18   const uint8_t kInput[] = {
19     0b10000000,  // Version/Padding byte.
20     96,  // Payload type byte.
21     0xbe, 0xef,  // Sequence number.
22     9, 8, 7, 6,  // RTP timestamp.
23     1, 2, 3, 4,  // SSRC.
24     0b10000000,  // Is key frame, no extensions.
25     5,  // Frame ID.
26     0xa, 0xb,  // Packet ID.
27     0xa, 0xc,  // Max packet ID.
28     0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8,  // Payload.
29   };
30   // clang-format on
31   const Ssrc kSenderSsrc = 0x01020304;
32 
33   RtpPacketParser parser(kSenderSsrc);
34   const auto result = parser.Parse(kInput);
35   ASSERT_TRUE(result);
36   EXPECT_EQ(RtpPayloadType::kAudioOpus, result->payload_type);
37   EXPECT_EQ(UINT16_C(0xbeef), result->sequence_number);
38   EXPECT_EQ(RtpTimeTicks() + RtpTimeDelta::FromTicks(0x09080706),
39             result->rtp_timestamp);
40   EXPECT_TRUE(result->is_key_frame);
41   EXPECT_EQ(FrameId::first() + 5, result->frame_id);
42   EXPECT_EQ(FramePacketId{0x0a0b}, result->packet_id);
43   EXPECT_EQ(FramePacketId{0x0a0c}, result->max_packet_id);
44   EXPECT_EQ(FrameId::first() + 5, result->referenced_frame_id);
45   EXPECT_EQ(0, result->new_playout_delay.count());
46   const absl::Span<const uint8_t> expected_payload(kInput + 18, 8);
47   ASSERT_EQ(expected_payload, result->payload);
48   EXPECT_TRUE(expected_payload == result->payload);
49 }
50 
51 // Tests that a packet which includes a "referenced frame ID" can be parsed.
TEST(RtpPacketParserTest,ParsesPacketForNonKeyFrameWithReferenceFrameId)52 TEST(RtpPacketParserTest, ParsesPacketForNonKeyFrameWithReferenceFrameId) {
53   // clang-format off
54   const uint8_t kInput[] = {
55     0b10000000,  // Version/Padding byte.
56     96,  // Payload type byte.
57     0xde, 0xad,  // Sequence number.
58     2, 4, 6, 8,  // RTP timestamp.
59     0, 0, 1, 1,  // SSRC.
60     0b01000000,  // Not a key frame, but has ref frame ID; no extensions.
61     42,  // Frame ID.
62     0x0, 0xb,  // Packet ID.
63     0x0, 0xc,  // Max packet ID.
64     39,  // Reference Frame ID.
65     1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29  // Payload.
66   };
67   // clang-format on
68   const Ssrc kSenderSsrc = 0x00000101;
69 
70   RtpPacketParser parser(kSenderSsrc);
71   const auto result = parser.Parse(kInput);
72   ASSERT_TRUE(result);
73   EXPECT_EQ(RtpPayloadType::kAudioOpus, result->payload_type);
74   EXPECT_EQ(UINT16_C(0xdead), result->sequence_number);
75   EXPECT_EQ(RtpTimeTicks() + RtpTimeDelta::FromTicks(0x02040608),
76             result->rtp_timestamp);
77   EXPECT_FALSE(result->is_key_frame);
78   EXPECT_EQ(FrameId::first() + 42, result->frame_id);
79   EXPECT_EQ(FramePacketId{0x000b}, result->packet_id);
80   EXPECT_EQ(FramePacketId{0x000c}, result->max_packet_id);
81   EXPECT_EQ(FrameId::first() + 39, result->referenced_frame_id);
82   EXPECT_EQ(0, result->new_playout_delay.count());
83   const absl::Span<const uint8_t> expected_payload(kInput + 19, 15);
84   ASSERT_EQ(expected_payload, result->payload);
85   EXPECT_TRUE(expected_payload == result->payload);
86 }
87 
88 // Tests that a packet which lacks a "referenced frame ID" field can be parsed,
89 // but the parser will provide the implied referenced_frame_id value in the
90 // result.
TEST(RtpPacketParserTest,ParsesPacketForNonKeyFrameWithoutReferenceFrameId)91 TEST(RtpPacketParserTest, ParsesPacketForNonKeyFrameWithoutReferenceFrameId) {
92   // clang-format off
93   const uint8_t kInput[] = {
94     0b10000000,  // Version/Padding byte.
95     96,  // Payload type byte.
96     0xde, 0xad,  // Sequence number.
97     2, 4, 6, 8,  // RTP timestamp.
98     0, 0, 1, 1,  // SSRC.
99     0b00000000,  // Not a key frame, no ref frame ID; no extensions.
100     42,  // Frame ID.
101     0x0, 0xb,  // Packet ID.
102     0x0, 0xc,  // Max packet ID.
103     1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29  // Payload.
104   };
105   // clang-format on
106   const Ssrc kSenderSsrc = 0x00000101;
107 
108   RtpPacketParser parser(kSenderSsrc);
109   const auto result = parser.Parse(kInput);
110   ASSERT_TRUE(result);
111   EXPECT_EQ(RtpPayloadType::kAudioOpus, result->payload_type);
112   EXPECT_EQ(UINT16_C(0xdead), result->sequence_number);
113   EXPECT_EQ(RtpTimeTicks() + RtpTimeDelta::FromTicks(0x02040608),
114             result->rtp_timestamp);
115   EXPECT_FALSE(result->is_key_frame);
116   EXPECT_EQ(FrameId::first() + 42, result->frame_id);
117   EXPECT_EQ(FramePacketId{0x000b}, result->packet_id);
118   EXPECT_EQ(FramePacketId{0x000c}, result->max_packet_id);
119   EXPECT_EQ(FrameId::first() + 41, result->referenced_frame_id);
120   EXPECT_EQ(0, result->new_playout_delay.count());
121   const absl::Span<const uint8_t> expected_payload(kInput + 18, 15);
122   ASSERT_EQ(expected_payload, result->payload);
123   EXPECT_TRUE(expected_payload == result->payload);
124 }
125 
126 // Tests that a packet indicating a new playout delay can be parsed.
TEST(RtpPacketParserTest,ParsesPacketWithAdaptiveLatencyExtension)127 TEST(RtpPacketParserTest, ParsesPacketWithAdaptiveLatencyExtension) {
128   // clang-format off
129   const uint8_t kInput[] = {
130     0b10000000,  // Version/Padding byte.
131     96,  // Payload type byte.
132     0xde, 0xad,  // Sequence number.
133     2, 4, 6, 8,  // RTP timestamp.
134     0, 0, 1, 1,  // SSRC.
135     0b11000001,  // Is key frame, has ref frame ID; has one extension.
136     64,  // Frame ID.
137     0x0, 0x0,  // Packet ID.
138     0x0, 0xc,  // Max packet ID.
139     64,  // Reference Frame ID.
140     4, 2, 1, 14,  // Cast Adaptive Latency Extension data.
141     1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29  // Payload.
142   };
143   // clang-format on
144   const Ssrc kSenderSsrc = 0x00000101;
145 
146   RtpPacketParser parser(kSenderSsrc);
147   const auto result = parser.Parse(kInput);
148   ASSERT_TRUE(result);
149   EXPECT_EQ(RtpPayloadType::kAudioOpus, result->payload_type);
150   EXPECT_EQ(UINT16_C(0xdead), result->sequence_number);
151   EXPECT_EQ(RtpTimeTicks() + RtpTimeDelta::FromTicks(0x02040608),
152             result->rtp_timestamp);
153   EXPECT_TRUE(result->is_key_frame);
154   EXPECT_EQ(FrameId::first() + 64, result->frame_id);
155   EXPECT_EQ(FramePacketId{0x0000}, result->packet_id);
156   EXPECT_EQ(FramePacketId{0x000c}, result->max_packet_id);
157   EXPECT_EQ(FrameId::first() + 64, result->referenced_frame_id);
158   EXPECT_EQ(270, result->new_playout_delay.count());
159   const absl::Span<const uint8_t> expected_payload(kInput + 23, 15);
160   ASSERT_EQ(expected_payload, result->payload);
161   EXPECT_TRUE(expected_payload == result->payload);
162 }
163 
164 // Tests that the parser can handle multiple Cast Header Extensions in a RTP
165 // packet, and ignores all but the one (Adaptive Latency) that it understands.
TEST(RtpPacketParserTest,ParsesPacketWithMultipleExtensions)166 TEST(RtpPacketParserTest, ParsesPacketWithMultipleExtensions) {
167   // clang-format off
168   const uint8_t kInput[] = {
169     0b10000000,  // Version/Padding byte.
170     96,  // Payload type byte.
171     0xde, 0xad,  // Sequence number.
172     2, 4, 6, 8,  // RTP timestamp.
173     0, 0, 1, 1,  // SSRC.
174     0b11000011,  // Is key frame, has ref frame ID; has 3 extensions.
175     64,  // Frame ID.
176     0x0, 0xb,  // Packet ID.
177     0x0, 0xc,  // Max packet ID.
178     64,  // Reference Frame ID.
179     8, 2, 0, 0,  // Unknown extension with 2 bytes of data.
180     4, 2, 1, 14,  // Cast Adaptive Latency Extension data.
181     16, 5, 0, 0, 0, 0, 0,  // Unknown extension with 5 bytes of data.
182     1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29  // Payload.
183   };
184   // clang-format on
185   const Ssrc kSenderSsrc = 0x00000101;
186 
187   RtpPacketParser parser(kSenderSsrc);
188   const auto result = parser.Parse(kInput);
189   ASSERT_TRUE(result);
190   EXPECT_EQ(RtpPayloadType::kAudioOpus, result->payload_type);
191   EXPECT_EQ(UINT16_C(0xdead), result->sequence_number);
192   EXPECT_EQ(RtpTimeTicks() + RtpTimeDelta::FromTicks(0x02040608),
193             result->rtp_timestamp);
194   EXPECT_TRUE(result->is_key_frame);
195   EXPECT_EQ(FrameId::first() + 64, result->frame_id);
196   EXPECT_EQ(FramePacketId{0x000b}, result->packet_id);
197   EXPECT_EQ(FramePacketId{0x000c}, result->max_packet_id);
198   EXPECT_EQ(FrameId::first() + 64, result->referenced_frame_id);
199   EXPECT_EQ(270, result->new_playout_delay.count());
200   const absl::Span<const uint8_t> expected_payload(kInput + 34, 15);
201   ASSERT_EQ(expected_payload, result->payload);
202   EXPECT_TRUE(expected_payload == result->payload);
203 }
204 
205 // Tests that the parser ignores packets from an unknown source.
TEST(RtpPacketParserTest,IgnoresPacketWithWrongSsrc)206 TEST(RtpPacketParserTest, IgnoresPacketWithWrongSsrc) {
207   // clang-format off
208   const uint8_t kInput[] = {
209     0b10000000,  // Version/Padding byte.
210     96,  // Payload type byte.
211     0xbe, 0xef,  // Sequence number.
212     9, 8, 7, 6,  // RTP timestamp.
213     4, 3, 2, 1,  // SSRC.
214     0b10000000,  // Is key frame, no extensions.
215     5,  // Frame ID.
216     0xa, 0xb,  // Packet ID.
217     0xa, 0xc,  // Max packet ID.
218     0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8,  // Payload.
219   };
220   // clang-format on
221   const Ssrc kSenderSsrc = 0x01020304;
222 
223   RtpPacketParser parser(kSenderSsrc);
224   const auto result = parser.Parse(kInput);
225   ASSERT_FALSE(result);
226 }
227 
228 // Tests that unexpected truncations in the RTP packets does not crash the
229 // parser, and that it correctly errors-out.
TEST(RtpPacketParserTest,RejectsTruncatedPackets)230 TEST(RtpPacketParserTest, RejectsTruncatedPackets) {
231   // clang-format off
232   const uint8_t kInput[] = {
233     0b10000000,  // Version/Padding byte.
234     96,  // Payload type byte.
235     0xde, 0xad,  // Sequence number.
236     2, 4, 6, 8,  // RTP timestamp.
237     0, 0, 1, 1,  // SSRC.
238     0b11000011,  // Is key frame, has ref frame ID; has 3 extensions.
239     64,  // Frame ID.
240     0x0, 0xb,  // Packet ID.
241     0x0, 0xc,  // Max packet ID.
242     64,  // Reference Frame ID.
243     8, 2, 0, 0,  // Unknown extension with 2 bytes of data.
244     4, 2, 1, 14,  // Cast Adaptive Latency Extension data.
245     16, 5, 0, 0, 0, 0, 0,  // Unknown extension with 5 bytes of data.
246     1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29  // Payload.
247   };
248   // clang-format on
249   const Ssrc kSenderSsrc = 0x00000101;
250 
251   RtpPacketParser parser(kSenderSsrc);
252   ASSERT_FALSE(parser.Parse(absl::Span<const uint8_t>(kInput, 1)));
253   ASSERT_FALSE(parser.Parse(absl::Span<const uint8_t>(kInput, 18)));
254   ASSERT_FALSE(parser.Parse(absl::Span<const uint8_t>(kInput, 22)));
255   ASSERT_FALSE(parser.Parse(absl::Span<const uint8_t>(kInput, 33)));
256 
257   // When truncated to 34 bytes, the parser should see it as a packet with zero
258   // payload bytes.
259   const auto result_without_payload =
260       parser.Parse(absl::Span<const uint8_t>(kInput, 34));
261   ASSERT_TRUE(result_without_payload);
262   EXPECT_TRUE(result_without_payload->payload.empty());
263 
264   // And, of course, with the entire kInput available, the parser should see it
265   // as a packet with 15 bytes of payload.
266   const auto result_with_payload =
267       parser.Parse(absl::Span<const uint8_t>(kInput, sizeof(kInput)));
268   ASSERT_TRUE(result_with_payload);
269   EXPECT_EQ(size_t{15}, result_with_payload->payload.size());
270 }
271 
272 // Tests that the parser rejects invalid packet ID values.
TEST(RtpPacketParserTest,RejectsPacketWithBadFramePacketIds)273 TEST(RtpPacketParserTest, RejectsPacketWithBadFramePacketIds) {
274   // clang-format off
275   const uint8_t kInput[] = {
276     0b10000000,  // Version/Padding byte.
277     96,  // Payload type byte.
278     0xbe, 0xef,  // Sequence number.
279     9, 8, 7, 6,  // RTP timestamp.
280     1, 2, 3, 4,  // SSRC.
281     0b10000000,  // Is key frame, no extensions.
282     5,  // Frame ID.
283     0xa, 0xb,  // Packet ID (which is GREATER than the max packet ID).
284     0x0, 0x1,  // Max packet ID.
285     0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8,  // Payload.
286   };
287   // clang-format on
288   const Ssrc kSenderSsrc = 0x01020304;
289 
290   // The parser should reject the packet because its packet ID field is greater
291   // than the max packet ID.
292   RtpPacketParser parser(kSenderSsrc);
293   ASSERT_FALSE(parser.Parse(kInput));
294 
295   // Now, modify the packet such that its "max packet ID" field is set to the
296   // special "all packets lost" value. This makes the "packet ID" field valid,
297   // because it is less than the "max packet ID", but the "max packet ID" value
298   // itself is invalid.
299   uint8_t input_with_bad_max_packet_id[sizeof(kInput)];
300   memcpy(input_with_bad_max_packet_id, kInput, sizeof(kInput));
301   WriteBigEndian<uint16_t>(kAllPacketsLost, &input_with_bad_max_packet_id[16]);
302   const uint16_t packet_id =
303       ReadBigEndian<uint16_t>(&input_with_bad_max_packet_id[14]);
304   ASSERT_LE(packet_id, kAllPacketsLost);
305   ASSERT_FALSE(parser.Parse(input_with_bad_max_packet_id));
306 }
307 
308 }  // namespace
309 }  // namespace cast
310 }  // namespace openscreen
311