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