• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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