1 /*
2 * Copyright (c) 2019 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/rtp_rtcp/source/video_rtp_depacketizer_av1.h"
12
13 #include "test/gmock.h"
14 #include "test/gtest.h"
15
16 namespace webrtc {
17 namespace {
18
19 using ::testing::ElementsAre;
20
21 // Signals number of the OBU (fragments) in the packet.
22 constexpr uint8_t kObuCountOne = 0b00'01'0000;
23
24 constexpr uint8_t kObuHeaderSequenceHeader = 0b0'0001'000;
25 constexpr uint8_t kObuHeaderFrame = 0b0'0110'000;
26
27 constexpr uint8_t kObuHeaderHasSize = 0b0'0000'010;
28
TEST(VideoRtpDepacketizerAv1Test,ParsePassFullRtpPayloadAsCodecPayload)29 TEST(VideoRtpDepacketizerAv1Test, ParsePassFullRtpPayloadAsCodecPayload) {
30 const uint8_t packet[] = {(uint8_t{1} << 7) | kObuCountOne, 1, 2, 3, 4};
31 rtc::CopyOnWriteBuffer rtp_payload(packet);
32 VideoRtpDepacketizerAv1 depacketizer;
33 absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> parsed =
34 depacketizer.Parse(rtp_payload);
35 ASSERT_TRUE(parsed);
36 EXPECT_EQ(parsed->video_payload.size(), sizeof(packet));
37 EXPECT_TRUE(parsed->video_payload.cdata() == rtp_payload.cdata());
38 }
39
TEST(VideoRtpDepacketizerAv1Test,ParseTreatsContinuationFlagAsNotBeginningOfFrame)40 TEST(VideoRtpDepacketizerAv1Test,
41 ParseTreatsContinuationFlagAsNotBeginningOfFrame) {
42 const uint8_t packet[] = {
43 (uint8_t{1} << 7) | kObuCountOne,
44 kObuHeaderFrame}; // Value doesn't matter since it is a
45 // continuation of the OBU from previous packet.
46 VideoRtpDepacketizerAv1 depacketizer;
47 absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> parsed =
48 depacketizer.Parse(rtc::CopyOnWriteBuffer(packet));
49 ASSERT_TRUE(parsed);
50 EXPECT_FALSE(parsed->video_header.is_first_packet_in_frame);
51 }
52
TEST(VideoRtpDepacketizerAv1Test,ParseTreatsNoContinuationFlagAsBeginningOfFrame)53 TEST(VideoRtpDepacketizerAv1Test,
54 ParseTreatsNoContinuationFlagAsBeginningOfFrame) {
55 const uint8_t packet[] = {(uint8_t{0} << 7) | kObuCountOne, kObuHeaderFrame};
56 VideoRtpDepacketizerAv1 depacketizer;
57 absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> parsed =
58 depacketizer.Parse(rtc::CopyOnWriteBuffer(packet));
59 ASSERT_TRUE(parsed);
60 EXPECT_TRUE(parsed->video_header.is_first_packet_in_frame);
61 }
62
TEST(VideoRtpDepacketizerAv1Test,ParseTreatsWillContinueFlagAsNotEndOfFrame)63 TEST(VideoRtpDepacketizerAv1Test, ParseTreatsWillContinueFlagAsNotEndOfFrame) {
64 const uint8_t packet[] = {(uint8_t{1} << 6) | kObuCountOne, kObuHeaderFrame};
65 rtc::CopyOnWriteBuffer rtp_payload(packet);
66 VideoRtpDepacketizerAv1 depacketizer;
67 absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> parsed =
68 depacketizer.Parse(rtp_payload);
69 ASSERT_TRUE(parsed);
70 EXPECT_FALSE(parsed->video_header.is_last_packet_in_frame);
71 }
72
TEST(VideoRtpDepacketizerAv1Test,ParseTreatsNoWillContinueFlagAsEndOfFrame)73 TEST(VideoRtpDepacketizerAv1Test, ParseTreatsNoWillContinueFlagAsEndOfFrame) {
74 const uint8_t packet[] = {(uint8_t{0} << 6) | kObuCountOne, kObuHeaderFrame};
75 VideoRtpDepacketizerAv1 depacketizer;
76 absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> parsed =
77 depacketizer.Parse(rtc::CopyOnWriteBuffer(packet));
78 ASSERT_TRUE(parsed);
79 EXPECT_TRUE(parsed->video_header.is_last_packet_in_frame);
80 }
81
TEST(VideoRtpDepacketizerAv1Test,ParseUsesNewCodedVideoSequenceBitAsKeyFrameIndidcator)82 TEST(VideoRtpDepacketizerAv1Test,
83 ParseUsesNewCodedVideoSequenceBitAsKeyFrameIndidcator) {
84 const uint8_t packet[] = {(uint8_t{1} << 3) | kObuCountOne,
85 kObuHeaderSequenceHeader};
86 VideoRtpDepacketizerAv1 depacketizer;
87 absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> parsed =
88 depacketizer.Parse(rtc::CopyOnWriteBuffer(packet));
89 ASSERT_TRUE(parsed);
90 EXPECT_TRUE(parsed->video_header.is_first_packet_in_frame);
91 EXPECT_TRUE(parsed->video_header.frame_type ==
92 VideoFrameType::kVideoFrameKey);
93 }
94
TEST(VideoRtpDepacketizerAv1Test,ParseUsesUnsetNewCodedVideoSequenceBitAsDeltaFrameIndidcator)95 TEST(VideoRtpDepacketizerAv1Test,
96 ParseUsesUnsetNewCodedVideoSequenceBitAsDeltaFrameIndidcator) {
97 const uint8_t packet[] = {(uint8_t{0} << 3) | kObuCountOne,
98 kObuHeaderSequenceHeader};
99 VideoRtpDepacketizerAv1 depacketizer;
100 absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> parsed =
101 depacketizer.Parse(rtc::CopyOnWriteBuffer(packet));
102 ASSERT_TRUE(parsed);
103 EXPECT_TRUE(parsed->video_header.is_first_packet_in_frame);
104 EXPECT_TRUE(parsed->video_header.frame_type ==
105 VideoFrameType::kVideoFrameDelta);
106 }
107
TEST(VideoRtpDepacketizerAv1Test,ParseRejectsPacketWithNewCVSAndContinuationFlagsBothSet)108 TEST(VideoRtpDepacketizerAv1Test,
109 ParseRejectsPacketWithNewCVSAndContinuationFlagsBothSet) {
110 const uint8_t packet[] = {0b10'00'1000 | kObuCountOne,
111 kObuHeaderSequenceHeader};
112 VideoRtpDepacketizerAv1 depacketizer;
113 ASSERT_FALSE(depacketizer.Parse(rtc::CopyOnWriteBuffer(packet)));
114 }
115
TEST(VideoRtpDepacketizerAv1Test,AssembleFrameSetsOBUPayloadSizeWhenAbsent)116 TEST(VideoRtpDepacketizerAv1Test, AssembleFrameSetsOBUPayloadSizeWhenAbsent) {
117 const uint8_t payload1[] = {0b00'01'0000, // aggregation header
118 0b0'0110'000, // / Frame
119 20, 30, 40}; // \ OBU
120 rtc::ArrayView<const uint8_t> payloads[] = {payload1};
121 auto frame = VideoRtpDepacketizerAv1().AssembleFrame(payloads);
122 ASSERT_TRUE(frame);
123 rtc::ArrayView<const uint8_t> frame_view(*frame);
124 EXPECT_TRUE(frame_view[0] & kObuHeaderHasSize);
125 EXPECT_EQ(frame_view[1], 3);
126 }
127
TEST(VideoRtpDepacketizerAv1Test,AssembleFrameSetsOBUPayloadSizeWhenPresent)128 TEST(VideoRtpDepacketizerAv1Test, AssembleFrameSetsOBUPayloadSizeWhenPresent) {
129 const uint8_t payload1[] = {0b00'01'0000, // aggregation header
130 0b0'0110'010, // / Frame OBU header
131 3, // obu_size
132 20,
133 30,
134 40}; // \ obu_payload
135 rtc::ArrayView<const uint8_t> payloads[] = {payload1};
136 auto frame = VideoRtpDepacketizerAv1().AssembleFrame(payloads);
137 ASSERT_TRUE(frame);
138 rtc::ArrayView<const uint8_t> frame_view(*frame);
139 EXPECT_TRUE(frame_view[0] & kObuHeaderHasSize);
140 EXPECT_EQ(frame_view[1], 3);
141 }
142
TEST(VideoRtpDepacketizerAv1Test,AssembleFrameSetsOBUPayloadSizeAfterExtensionWhenAbsent)143 TEST(VideoRtpDepacketizerAv1Test,
144 AssembleFrameSetsOBUPayloadSizeAfterExtensionWhenAbsent) {
145 const uint8_t payload1[] = {0b00'01'0000, // aggregation header
146 0b0'0110'100, // / Frame
147 0b010'01'000, // | extension_header
148 20, 30, 40}; // \ OBU
149 rtc::ArrayView<const uint8_t> payloads[] = {payload1};
150 auto frame = VideoRtpDepacketizerAv1().AssembleFrame(payloads);
151 ASSERT_TRUE(frame);
152 rtc::ArrayView<const uint8_t> frame_view(*frame);
153 EXPECT_TRUE(frame_view[0] & kObuHeaderHasSize);
154 EXPECT_EQ(frame_view[2], 3);
155 }
156
TEST(VideoRtpDepacketizerAv1Test,AssembleFrameSetsOBUPayloadSizeAfterExtensionWhenPresent)157 TEST(VideoRtpDepacketizerAv1Test,
158 AssembleFrameSetsOBUPayloadSizeAfterExtensionWhenPresent) {
159 const uint8_t payload1[] = {0b00'01'0000, // aggregation header
160 0b0'0110'110, // / Frame OBU header
161 0b010'01'000, // | extension_header
162 3, // | obu_size
163 20,
164 30,
165 40}; // \ obu_payload
166 rtc::ArrayView<const uint8_t> payloads[] = {payload1};
167 auto frame = VideoRtpDepacketizerAv1().AssembleFrame(payloads);
168 ASSERT_TRUE(frame);
169 rtc::ArrayView<const uint8_t> frame_view(*frame);
170 EXPECT_TRUE(frame_view[0] & kObuHeaderHasSize);
171 EXPECT_EQ(frame_view[2], 3);
172 }
173
TEST(VideoRtpDepacketizerAv1Test,AssembleFrameFromOnePacketWithOneObu)174 TEST(VideoRtpDepacketizerAv1Test, AssembleFrameFromOnePacketWithOneObu) {
175 const uint8_t payload1[] = {0b00'01'0000, // aggregation header
176 0b0'0110'000, // / Frame
177 20}; // \ OBU
178 rtc::ArrayView<const uint8_t> payloads[] = {payload1};
179 auto frame = VideoRtpDepacketizerAv1().AssembleFrame(payloads);
180 ASSERT_TRUE(frame);
181 EXPECT_THAT(rtc::ArrayView<const uint8_t>(*frame),
182 ElementsAre(0b0'0110'010, 1, 20));
183 }
184
TEST(VideoRtpDepacketizerAv1Test,AssembleFrameFromOnePacketWithTwoObus)185 TEST(VideoRtpDepacketizerAv1Test, AssembleFrameFromOnePacketWithTwoObus) {
186 const uint8_t payload1[] = {0b00'10'0000, // aggregation header
187 2, // / Sequence
188 0b0'0001'000, // | Header
189 10, // \ OBU
190 0b0'0110'000, // / Frame
191 20}; // \ OBU
192 rtc::ArrayView<const uint8_t> payloads[] = {payload1};
193 auto frame = VideoRtpDepacketizerAv1().AssembleFrame(payloads);
194 ASSERT_TRUE(frame);
195 EXPECT_THAT(rtc::ArrayView<const uint8_t>(*frame),
196 ElementsAre(0b0'0001'010, 1, 10, // Sequence Header OBU
197 0b0'0110'010, 1, 20)); // Frame OBU
198 }
199
TEST(VideoRtpDepacketizerAv1Test,AssembleFrameFromTwoPacketsWithOneObu)200 TEST(VideoRtpDepacketizerAv1Test, AssembleFrameFromTwoPacketsWithOneObu) {
201 const uint8_t payload1[] = {0b01'01'0000, // aggregation header
202 0b0'0110'000, 20, 30};
203 const uint8_t payload2[] = {0b10'01'0000, // aggregation header
204 40};
205 rtc::ArrayView<const uint8_t> payloads[] = {payload1, payload2};
206 auto frame = VideoRtpDepacketizerAv1().AssembleFrame(payloads);
207 ASSERT_TRUE(frame);
208 EXPECT_THAT(rtc::ArrayView<const uint8_t>(*frame),
209 ElementsAre(0b0'0110'010, 3, 20, 30, 40));
210 }
211
TEST(VideoRtpDepacketizerAv1Test,AssembleFrameFromTwoPacketsWithTwoObu)212 TEST(VideoRtpDepacketizerAv1Test, AssembleFrameFromTwoPacketsWithTwoObu) {
213 const uint8_t payload1[] = {0b01'10'0000, // aggregation header
214 2, // / Sequence
215 0b0'0001'000, // | Header
216 10, // \ OBU
217 0b0'0110'000, //
218 20,
219 30}; //
220 const uint8_t payload2[] = {0b10'01'0000, // aggregation header
221 40}; //
222 rtc::ArrayView<const uint8_t> payloads[] = {payload1, payload2};
223 auto frame = VideoRtpDepacketizerAv1().AssembleFrame(payloads);
224 ASSERT_TRUE(frame);
225 EXPECT_THAT(rtc::ArrayView<const uint8_t>(*frame),
226 ElementsAre(0b0'0001'010, 1, 10, // SH
227 0b0'0110'010, 3, 20, 30, 40)); // Frame
228 }
229
TEST(VideoRtpDepacketizerAv1Test,AssembleFrameFromTwoPacketsWithManyObusSomeWithExtensions)230 TEST(VideoRtpDepacketizerAv1Test,
231 AssembleFrameFromTwoPacketsWithManyObusSomeWithExtensions) {
232 const uint8_t payload1[] = {0b01'00'0000, // aggregation header
233 2, // /
234 0b0'0001'000, // | Sequence Header
235 10, // \ OBU
236 2, // /
237 0b0'0101'000, // | Metadata OBU
238 20, // \ without extension
239 4, // /
240 0b0'0101'100, // | Metadata OBU
241 0b001'10'000, // | with extension
242 20, // |
243 30, // \ metadata payload
244 5, // /
245 0b0'0110'100, // | Frame OBU
246 0b001'10'000, // | with extension
247 40, // |
248 50, // |
249 60}; // |
250 const uint8_t payload2[] = {0b10'01'0000, // aggregation header
251 70, 80, 90}; // \ tail of the frame OBU
252
253 rtc::ArrayView<const uint8_t> payloads[] = {payload1, payload2};
254 auto frame = VideoRtpDepacketizerAv1().AssembleFrame(payloads);
255 ASSERT_TRUE(frame);
256 EXPECT_THAT(rtc::ArrayView<const uint8_t>(*frame),
257 ElementsAre( // Sequence header OBU
258 0b0'0001'010, 1, 10,
259 // Metadata OBU without extension
260 0b0'0101'010, 1, 20,
261 // Metadata OBU with extenion
262 0b0'0101'110, 0b001'10'000, 2, 20, 30,
263 // Frame OBU with extension
264 0b0'0110'110, 0b001'10'000, 6, 40, 50, 60, 70, 80, 90));
265 }
266
TEST(VideoRtpDepacketizerAv1Test,AssembleFrameWithOneObuFromManyPackets)267 TEST(VideoRtpDepacketizerAv1Test, AssembleFrameWithOneObuFromManyPackets) {
268 const uint8_t payload1[] = {0b01'01'0000, // aggregation header
269 0b0'0110'000, 11, 12};
270 const uint8_t payload2[] = {0b11'01'0000, // aggregation header
271 13, 14};
272 const uint8_t payload3[] = {0b11'01'0000, // aggregation header
273 15, 16, 17};
274 const uint8_t payload4[] = {0b10'01'0000, // aggregation header
275 18};
276
277 rtc::ArrayView<const uint8_t> payloads[] = {payload1, payload2, payload3,
278 payload4};
279 auto frame = VideoRtpDepacketizerAv1().AssembleFrame(payloads);
280 ASSERT_TRUE(frame);
281 EXPECT_THAT(rtc::ArrayView<const uint8_t>(*frame),
282 ElementsAre(0b0'0110'010, 8, 11, 12, 13, 14, 15, 16, 17, 18));
283 }
284
TEST(VideoRtpDepacketizerAv1Test,AssembleFrameFromManyPacketsWithSomeObuBorderAligned)285 TEST(VideoRtpDepacketizerAv1Test,
286 AssembleFrameFromManyPacketsWithSomeObuBorderAligned) {
287 const uint8_t payload1[] = {0b01'10'0000, // aggregation header
288 3, // size of the 1st fragment
289 0b0'0011'000, // Frame header OBU
290 11,
291 12,
292 0b0'0100'000, // Tile group OBU
293 21,
294 22,
295 23};
296 const uint8_t payload2[] = {0b10'01'0000, // aggregation header
297 24, 25, 26, 27};
298 // payload2 ends an OBU, payload3 starts a new one.
299 const uint8_t payload3[] = {0b01'10'0000, // aggregation header
300 3, // size of the 1st fragment
301 0b0'0111'000, // Redundant frame header OBU
302 11,
303 12,
304 0b0'0100'000, // Tile group OBU
305 31,
306 32};
307 const uint8_t payload4[] = {0b10'01'0000, // aggregation header
308 33, 34, 35, 36};
309 rtc::ArrayView<const uint8_t> payloads[] = {payload1, payload2, payload3,
310 payload4};
311 auto frame = VideoRtpDepacketizerAv1().AssembleFrame(payloads);
312 ASSERT_TRUE(frame);
313 EXPECT_THAT(rtc::ArrayView<const uint8_t>(*frame),
314 ElementsAre(0b0'0011'010, 2, 11, 12, // Frame header
315 0b0'0100'010, 7, 21, 22, 23, 24, 25, 26, 27, //
316 0b0'0111'010, 2, 11, 12, //
317 0b0'0100'010, 6, 31, 32, 33, 34, 35, 36));
318 }
319
TEST(VideoRtpDepacketizerAv1Test,AssembleFrameFromOnePacketsOneObuPayloadSize127Bytes)320 TEST(VideoRtpDepacketizerAv1Test,
321 AssembleFrameFromOnePacketsOneObuPayloadSize127Bytes) {
322 uint8_t payload1[4 + 127];
323 memset(payload1, 0, sizeof(payload1));
324 payload1[0] = 0b00'00'0000; // aggregation header
325 payload1[1] = 0x80; // leb128 encoded size of 128 bytes
326 payload1[2] = 0x01; // in two bytes
327 payload1[3] = 0b0'0110'000; // obu_header with size and extension bits unset.
328 payload1[4 + 42] = 0x42;
329 rtc::ArrayView<const uint8_t> payloads[] = {payload1};
330 auto frame = VideoRtpDepacketizerAv1().AssembleFrame(payloads);
331 ASSERT_TRUE(frame);
332 EXPECT_EQ(frame->size(), 2 + 127u);
333 rtc::ArrayView<const uint8_t> frame_view(*frame);
334 EXPECT_EQ(frame_view[0], 0b0'0110'010); // obu_header with size bit set.
335 EXPECT_EQ(frame_view[1], 127); // obu payload size, 1 byte enough to encode.
336 // Check 'random' byte from the payload is at the same 'random' offset.
337 EXPECT_EQ(frame_view[2 + 42], 0x42);
338 }
339
TEST(VideoRtpDepacketizerAv1Test,AssembleFrameFromTwoPacketsOneObuPayloadSize128Bytes)340 TEST(VideoRtpDepacketizerAv1Test,
341 AssembleFrameFromTwoPacketsOneObuPayloadSize128Bytes) {
342 uint8_t payload1[3 + 32];
343 memset(payload1, 0, sizeof(payload1));
344 payload1[0] = 0b01'00'0000; // aggregation header
345 payload1[1] = 33; // leb128 encoded size of 33 bytes in one byte
346 payload1[2] = 0b0'0110'000; // obu_header with size and extension bits unset.
347 payload1[3 + 10] = 0x10;
348 uint8_t payload2[2 + 96];
349 memset(payload2, 0, sizeof(payload2));
350 payload2[0] = 0b10'00'0000; // aggregation header
351 payload2[1] = 96; // leb128 encoded size of 96 bytes in one byte
352 payload2[2 + 20] = 0x20;
353
354 rtc::ArrayView<const uint8_t> payloads[] = {payload1, payload2};
355 auto frame = VideoRtpDepacketizerAv1().AssembleFrame(payloads);
356 ASSERT_TRUE(frame);
357 EXPECT_EQ(frame->size(), 3 + 128u);
358 rtc::ArrayView<const uint8_t> frame_view(*frame);
359 EXPECT_EQ(frame_view[0], 0b0'0110'010); // obu_header with size bit set.
360 EXPECT_EQ(frame_view[1], 0x80); // obu payload size of 128 bytes.
361 EXPECT_EQ(frame_view[2], 0x01); // encoded in two byes
362 // Check two 'random' byte from the payload is at the same 'random' offset.
363 EXPECT_EQ(frame_view[3 + 10], 0x10);
364 EXPECT_EQ(frame_view[3 + 32 + 20], 0x20);
365 }
366
TEST(VideoRtpDepacketizerAv1Test,AssembleFrameFromAlmostEmptyPacketStartingAnOBU)367 TEST(VideoRtpDepacketizerAv1Test,
368 AssembleFrameFromAlmostEmptyPacketStartingAnOBU) {
369 const uint8_t payload1[] = {0b01'01'0000};
370 const uint8_t payload2[] = {0b10'01'0000, 0b0'0110'000, 10, 20, 30};
371 rtc::ArrayView<const uint8_t> payloads[] = {payload1, payload2};
372
373 auto frame = VideoRtpDepacketizerAv1().AssembleFrame(payloads);
374 ASSERT_TRUE(frame);
375 EXPECT_THAT(rtc::ArrayView<const uint8_t>(*frame),
376 ElementsAre(0b0'0110'010, 3, 10, 20, 30));
377 }
378
TEST(VideoRtpDepacketizerAv1Test,AssembleFrameFromAlmostEmptyPacketFinishingAnOBU)379 TEST(VideoRtpDepacketizerAv1Test,
380 AssembleFrameFromAlmostEmptyPacketFinishingAnOBU) {
381 const uint8_t payload1[] = {0b01'01'0000, 0b0'0110'000, 10, 20, 30};
382 const uint8_t payload2[] = {0b10'01'0000};
383 rtc::ArrayView<const uint8_t> payloads[] = {payload1, payload2};
384
385 auto frame = VideoRtpDepacketizerAv1().AssembleFrame(payloads);
386 ASSERT_TRUE(frame);
387 EXPECT_THAT(rtc::ArrayView<const uint8_t>(*frame),
388 ElementsAre(0b0'0110'010, 3, 10, 20, 30));
389 }
390
391 } // namespace
392 } // namespace webrtc
393