1 /*
2  *  Copyright (c) 2012 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 /*
12  * This file includes unit tests for the VP8 packetizer.
13  */
14 
15 #include "testing/gmock/include/gmock/gmock.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 #include "webrtc/modules/rtp_rtcp/source/rtp_format_vp8.h"
18 #include "webrtc/modules/rtp_rtcp/source/rtp_format_vp8_test_helper.h"
19 #include "webrtc/typedefs.h"
20 
21 #define CHECK_ARRAY_SIZE(expected_size, array)                     \
22   static_assert(expected_size == sizeof(array) / sizeof(array[0]), \
23                 "check array size");
24 
25 namespace webrtc {
26 namespace {
27 // Payload descriptor
28 //       0 1 2 3 4 5 6 7
29 //      +-+-+-+-+-+-+-+-+
30 //      |X|R|N|S|PartID | (REQUIRED)
31 //      +-+-+-+-+-+-+-+-+
32 // X:   |I|L|T|K|  RSV  | (OPTIONAL)
33 //      +-+-+-+-+-+-+-+-+
34 // I:   |   PictureID   | (OPTIONAL)
35 //      +-+-+-+-+-+-+-+-+
36 // L:   |   TL0PICIDX   | (OPTIONAL)
37 //      +-+-+-+-+-+-+-+-+
38 // T/K: |TID:Y| KEYIDX  | (OPTIONAL)
39 //      +-+-+-+-+-+-+-+-+
40 //
41 // Payload header
42 //       0 1 2 3 4 5 6 7
43 //      +-+-+-+-+-+-+-+-+
44 //      |Size0|H| VER |P|
45 //      +-+-+-+-+-+-+-+-+
46 //      |     Size1     |
47 //      +-+-+-+-+-+-+-+-+
48 //      |     Size2     |
49 //      +-+-+-+-+-+-+-+-+
50 //      | Bytes 4..N of |
51 //      | VP8 payload   |
52 //      :               :
53 //      +-+-+-+-+-+-+-+-+
54 //      | OPTIONAL RTP  |
55 //      | padding       |
56 //      :               :
57 //      +-+-+-+-+-+-+-+-+
VerifyBasicHeader(RTPTypeHeader * type,bool N,bool S,int part_id)58 void VerifyBasicHeader(RTPTypeHeader* type, bool N, bool S, int part_id) {
59   ASSERT_TRUE(type != NULL);
60   EXPECT_EQ(N, type->Video.codecHeader.VP8.nonReference);
61   EXPECT_EQ(S, type->Video.codecHeader.VP8.beginningOfPartition);
62   EXPECT_EQ(part_id, type->Video.codecHeader.VP8.partitionId);
63 }
64 
VerifyExtensions(RTPTypeHeader * type,int16_t picture_id,int16_t tl0_pic_idx,uint8_t temporal_idx,int key_idx)65 void VerifyExtensions(RTPTypeHeader* type,
66                       int16_t picture_id,   /* I */
67                       int16_t tl0_pic_idx,  /* L */
68                       uint8_t temporal_idx, /* T */
69                       int key_idx /* K */) {
70   ASSERT_TRUE(type != NULL);
71   EXPECT_EQ(picture_id, type->Video.codecHeader.VP8.pictureId);
72   EXPECT_EQ(tl0_pic_idx, type->Video.codecHeader.VP8.tl0PicIdx);
73   EXPECT_EQ(temporal_idx, type->Video.codecHeader.VP8.temporalIdx);
74   EXPECT_EQ(key_idx, type->Video.codecHeader.VP8.keyIdx);
75 }
76 }  // namespace
77 
78 class RtpPacketizerVp8Test : public ::testing::Test {
79  protected:
RtpPacketizerVp8Test()80   RtpPacketizerVp8Test() : helper_(NULL) {}
TearDown()81   virtual void TearDown() { delete helper_; }
Init(const size_t * partition_sizes,size_t num_partitions)82   bool Init(const size_t* partition_sizes, size_t num_partitions) {
83     hdr_info_.pictureId = kNoPictureId;
84     hdr_info_.nonReference = false;
85     hdr_info_.temporalIdx = kNoTemporalIdx;
86     hdr_info_.layerSync = false;
87     hdr_info_.tl0PicIdx = kNoTl0PicIdx;
88     hdr_info_.keyIdx = kNoKeyIdx;
89     if (helper_ != NULL)
90       return false;
91     helper_ = new test::RtpFormatVp8TestHelper(&hdr_info_);
92     return helper_->Init(partition_sizes, num_partitions);
93   }
94 
95   RTPVideoHeaderVP8 hdr_info_;
96   test::RtpFormatVp8TestHelper* helper_;
97 };
98 
TEST_F(RtpPacketizerVp8Test,TestStrictMode)99 TEST_F(RtpPacketizerVp8Test, TestStrictMode) {
100   const size_t kSizeVector[] = {10, 8, 27};
101   const size_t kNumPartitions = GTEST_ARRAY_SIZE_(kSizeVector);
102   ASSERT_TRUE(Init(kSizeVector, kNumPartitions));
103 
104   hdr_info_.pictureId = 200;  // > 0x7F should produce 2-byte PictureID.
105   const size_t kMaxSize = 13;
106   RtpPacketizerVp8 packetizer(hdr_info_, kMaxSize, kStrict);
107   packetizer.SetPayloadData(helper_->payload_data(),
108                             helper_->payload_size(),
109                             helper_->fragmentation());
110 
111   // The expected sizes are obtained by running a verified good implementation.
112   const size_t kExpectedSizes[] = {9, 9, 12, 11, 11, 11, 10};
113   const int kExpectedPart[] = {0, 0, 1, 2, 2, 2, 2};
114   const bool kExpectedFragStart[] = {true,  false, true, true,
115                                      false, false, false};
116   const size_t kExpectedNum = GTEST_ARRAY_SIZE_(kExpectedSizes);
117   CHECK_ARRAY_SIZE(kExpectedNum, kExpectedPart);
118   CHECK_ARRAY_SIZE(kExpectedNum, kExpectedFragStart);
119 
120   helper_->GetAllPacketsAndCheck(&packetizer,
121                                  kExpectedSizes,
122                                  kExpectedPart,
123                                  kExpectedFragStart,
124                                  kExpectedNum);
125 }
126 
127 // Verify that we get a minimal number of packets if the partition plus header
128 // size fits exactly in the maximum packet size.
129 // Test is disabled: https://code.google.com/p/webrtc/issues/detail?id=4019.
TEST_F(RtpPacketizerVp8Test,DISABLED_TestStrictEqualTightPartitions)130 TEST_F(RtpPacketizerVp8Test, DISABLED_TestStrictEqualTightPartitions) {
131   const size_t kSizeVector[] = {10, 10, 10};
132   const size_t kNumPartitions = GTEST_ARRAY_SIZE_(kSizeVector);
133   ASSERT_TRUE(Init(kSizeVector, kNumPartitions));
134 
135   hdr_info_.pictureId = 200;  // > 0x7F should produce 2-byte PictureID.
136   const int kMaxSize = 14;
137   RtpPacketizerVp8 packetizer(hdr_info_, kMaxSize, kStrict);
138   packetizer.SetPayloadData(helper_->payload_data(), helper_->payload_size(),
139                             helper_->fragmentation());
140 
141   // The expected sizes are obtained by running a verified good implementation.
142   const size_t kExpectedSizes[] = {14, 14, 14};
143   const int kExpectedPart[] = {0, 1, 2};
144   const bool kExpectedFragStart[] = {true, true, true};
145   const size_t kExpectedNum = GTEST_ARRAY_SIZE_(kExpectedSizes);
146   CHECK_ARRAY_SIZE(kExpectedNum, kExpectedPart);
147   CHECK_ARRAY_SIZE(kExpectedNum, kExpectedFragStart);
148 
149   helper_->GetAllPacketsAndCheck(&packetizer, kExpectedSizes, kExpectedPart,
150                                  kExpectedFragStart, kExpectedNum);
151 }
152 
TEST_F(RtpPacketizerVp8Test,TestAggregateMode)153 TEST_F(RtpPacketizerVp8Test, TestAggregateMode) {
154   const size_t kSizeVector[] = {60, 10, 10};
155   const size_t kNumPartitions = GTEST_ARRAY_SIZE_(kSizeVector);
156   ASSERT_TRUE(Init(kSizeVector, kNumPartitions));
157 
158   hdr_info_.pictureId = 20;  // <= 0x7F should produce 1-byte PictureID.
159   const size_t kMaxSize = 25;
160   RtpPacketizerVp8 packetizer(hdr_info_, kMaxSize, kAggregate);
161   packetizer.SetPayloadData(helper_->payload_data(),
162                             helper_->payload_size(),
163                             helper_->fragmentation());
164 
165   // The expected sizes are obtained by running a verified good implementation.
166   const size_t kExpectedSizes[] = {23, 23, 23, 23};
167   const int kExpectedPart[] = {0, 0, 0, 1};
168   const bool kExpectedFragStart[] = {true, false, false, true};
169   const size_t kExpectedNum = GTEST_ARRAY_SIZE_(kExpectedSizes);
170   CHECK_ARRAY_SIZE(kExpectedNum, kExpectedPart);
171   CHECK_ARRAY_SIZE(kExpectedNum, kExpectedFragStart);
172 
173   helper_->GetAllPacketsAndCheck(&packetizer,
174                                  kExpectedSizes,
175                                  kExpectedPart,
176                                  kExpectedFragStart,
177                                  kExpectedNum);
178 }
179 
TEST_F(RtpPacketizerVp8Test,TestAggregateModeManyPartitions1)180 TEST_F(RtpPacketizerVp8Test, TestAggregateModeManyPartitions1) {
181   const size_t kSizeVector[] = {1600, 200, 200, 200, 200, 200, 200, 200, 200};
182   const size_t kNumPartitions = GTEST_ARRAY_SIZE_(kSizeVector);
183   ASSERT_TRUE(Init(kSizeVector, kNumPartitions));
184 
185   hdr_info_.pictureId = 20;  // <= 0x7F should produce 1-byte PictureID.
186   const size_t kMaxSize = 1500;
187   RtpPacketizerVp8 packetizer(hdr_info_, kMaxSize, kAggregate);
188   packetizer.SetPayloadData(helper_->payload_data(),
189                             helper_->payload_size(),
190                             helper_->fragmentation());
191 
192   // The expected sizes are obtained by running a verified good implementation.
193   const size_t kExpectedSizes[] = {803, 803, 803, 803};
194   const int kExpectedPart[] = {0, 0, 1, 5};
195   const bool kExpectedFragStart[] = {true, false, true, true};
196   const size_t kExpectedNum = GTEST_ARRAY_SIZE_(kExpectedSizes);
197   CHECK_ARRAY_SIZE(kExpectedNum, kExpectedPart);
198   CHECK_ARRAY_SIZE(kExpectedNum, kExpectedFragStart);
199 
200   helper_->GetAllPacketsAndCheck(&packetizer,
201                                  kExpectedSizes,
202                                  kExpectedPart,
203                                  kExpectedFragStart,
204                                  kExpectedNum);
205 }
206 
TEST_F(RtpPacketizerVp8Test,TestAggregateModeManyPartitions2)207 TEST_F(RtpPacketizerVp8Test, TestAggregateModeManyPartitions2) {
208   const size_t kSizeVector[] = {1599, 200, 200, 200, 1600, 200, 200, 200, 200};
209   const size_t kNumPartitions = GTEST_ARRAY_SIZE_(kSizeVector);
210   ASSERT_TRUE(Init(kSizeVector, kNumPartitions));
211 
212   hdr_info_.pictureId = 20;  // <= 0x7F should produce 1-byte PictureID.
213   const size_t kMaxSize = 1500;
214   RtpPacketizerVp8 packetizer(hdr_info_, kMaxSize, kAggregate);
215   packetizer.SetPayloadData(helper_->payload_data(),
216                             helper_->payload_size(),
217                             helper_->fragmentation());
218 
219   // The expected sizes are obtained by running a verified good implementation.
220   const size_t kExpectedSizes[] = {803, 802, 603, 803, 803, 803};
221   const int kExpectedPart[] = {0, 0, 1, 4, 4, 5};
222   const bool kExpectedFragStart[] = {true, false, true, true, false, true};
223   const size_t kExpectedNum = GTEST_ARRAY_SIZE_(kExpectedSizes);
224   CHECK_ARRAY_SIZE(kExpectedNum, kExpectedPart);
225   CHECK_ARRAY_SIZE(kExpectedNum, kExpectedFragStart);
226 
227   helper_->GetAllPacketsAndCheck(&packetizer,
228                                  kExpectedSizes,
229                                  kExpectedPart,
230                                  kExpectedFragStart,
231                                  kExpectedNum);
232 }
233 
TEST_F(RtpPacketizerVp8Test,TestAggregateModeTwoLargePartitions)234 TEST_F(RtpPacketizerVp8Test, TestAggregateModeTwoLargePartitions) {
235   const size_t kSizeVector[] = {1654, 2268};
236   const size_t kNumPartitions = GTEST_ARRAY_SIZE_(kSizeVector);
237   ASSERT_TRUE(Init(kSizeVector, kNumPartitions));
238 
239   hdr_info_.pictureId = 20;  // <= 0x7F should produce 1-byte PictureID.
240   const size_t kMaxSize = 1460;
241   RtpPacketizerVp8 packetizer(hdr_info_, kMaxSize, kAggregate);
242   packetizer.SetPayloadData(helper_->payload_data(),
243                             helper_->payload_size(),
244                             helper_->fragmentation());
245 
246   // The expected sizes are obtained by running a verified good implementation.
247   const size_t kExpectedSizes[] = {830, 830, 1137, 1137};
248   const int kExpectedPart[] = {0, 0, 1, 1};
249   const bool kExpectedFragStart[] = {true, false, true, false};
250   const size_t kExpectedNum = GTEST_ARRAY_SIZE_(kExpectedSizes);
251   CHECK_ARRAY_SIZE(kExpectedNum, kExpectedPart);
252   CHECK_ARRAY_SIZE(kExpectedNum, kExpectedFragStart);
253 
254   helper_->GetAllPacketsAndCheck(&packetizer,
255                                  kExpectedSizes,
256                                  kExpectedPart,
257                                  kExpectedFragStart,
258                                  kExpectedNum);
259 }
260 
261 // Verify that EqualSize mode is forced if fragmentation info is missing.
TEST_F(RtpPacketizerVp8Test,TestEqualSizeModeFallback)262 TEST_F(RtpPacketizerVp8Test, TestEqualSizeModeFallback) {
263   const size_t kSizeVector[] = {10, 10, 10};
264   const size_t kNumPartitions = GTEST_ARRAY_SIZE_(kSizeVector);
265   ASSERT_TRUE(Init(kSizeVector, kNumPartitions));
266 
267   hdr_info_.pictureId = 200;   // > 0x7F should produce 2-byte PictureID
268   const size_t kMaxSize = 12;  // Small enough to produce 4 packets.
269   RtpPacketizerVp8 packetizer(hdr_info_, kMaxSize);
270   packetizer.SetPayloadData(
271       helper_->payload_data(), helper_->payload_size(), NULL);
272 
273   // Expecting three full packets, and one with the remainder.
274   const size_t kExpectedSizes[] = {12, 11, 12, 11};
275   const int kExpectedPart[] = {0, 0, 0, 0};  // Always 0 for equal size mode.
276   // Frag start only true for first packet in equal size mode.
277   const bool kExpectedFragStart[] = {true, false, false, false};
278   const size_t kExpectedNum = GTEST_ARRAY_SIZE_(kExpectedSizes);
279   CHECK_ARRAY_SIZE(kExpectedNum, kExpectedPart);
280   CHECK_ARRAY_SIZE(kExpectedNum, kExpectedFragStart);
281 
282   helper_->set_sloppy_partitioning(true);
283   helper_->GetAllPacketsAndCheck(&packetizer,
284                                  kExpectedSizes,
285                                  kExpectedPart,
286                                  kExpectedFragStart,
287                                  kExpectedNum);
288 }
289 
290 // Verify that non-reference bit is set. EqualSize mode fallback is expected.
TEST_F(RtpPacketizerVp8Test,TestNonReferenceBit)291 TEST_F(RtpPacketizerVp8Test, TestNonReferenceBit) {
292   const size_t kSizeVector[] = {10, 10, 10};
293   const size_t kNumPartitions = GTEST_ARRAY_SIZE_(kSizeVector);
294   ASSERT_TRUE(Init(kSizeVector, kNumPartitions));
295 
296   hdr_info_.nonReference = true;
297   const size_t kMaxSize = 25;  // Small enough to produce two packets.
298   RtpPacketizerVp8 packetizer(hdr_info_, kMaxSize);
299   packetizer.SetPayloadData(
300       helper_->payload_data(), helper_->payload_size(), NULL);
301 
302   // EqualSize mode => First packet full; other not.
303   const size_t kExpectedSizes[] = {16, 16};
304   const int kExpectedPart[] = {0, 0};  // Always 0 for equal size mode.
305   // Frag start only true for first packet in equal size mode.
306   const bool kExpectedFragStart[] = {true, false};
307   const size_t kExpectedNum = GTEST_ARRAY_SIZE_(kExpectedSizes);
308   CHECK_ARRAY_SIZE(kExpectedNum, kExpectedPart);
309   CHECK_ARRAY_SIZE(kExpectedNum, kExpectedFragStart);
310 
311   helper_->set_sloppy_partitioning(true);
312   helper_->GetAllPacketsAndCheck(&packetizer,
313                                  kExpectedSizes,
314                                  kExpectedPart,
315                                  kExpectedFragStart,
316                                  kExpectedNum);
317 }
318 
319 // Verify Tl0PicIdx and TID fields, and layerSync bit.
TEST_F(RtpPacketizerVp8Test,TestTl0PicIdxAndTID)320 TEST_F(RtpPacketizerVp8Test, TestTl0PicIdxAndTID) {
321   const size_t kSizeVector[] = {10, 10, 10};
322   const size_t kNumPartitions = GTEST_ARRAY_SIZE_(kSizeVector);
323   ASSERT_TRUE(Init(kSizeVector, kNumPartitions));
324 
325   hdr_info_.tl0PicIdx = 117;
326   hdr_info_.temporalIdx = 2;
327   hdr_info_.layerSync = true;
328   // kMaxSize is only limited by allocated buffer size.
329   const size_t kMaxSize = helper_->buffer_size();
330   RtpPacketizerVp8 packetizer(hdr_info_, kMaxSize, kAggregate);
331   packetizer.SetPayloadData(helper_->payload_data(),
332                             helper_->payload_size(),
333                             helper_->fragmentation());
334 
335   // Expect one single packet of payload_size() + 4 bytes header.
336   const size_t kExpectedSizes[1] = {helper_->payload_size() + 4};
337   const int kExpectedPart[1] = {0};  // Packet starts with partition 0.
338   const bool kExpectedFragStart[1] = {true};
339   const size_t kExpectedNum = GTEST_ARRAY_SIZE_(kExpectedSizes);
340   CHECK_ARRAY_SIZE(kExpectedNum, kExpectedPart);
341   CHECK_ARRAY_SIZE(kExpectedNum, kExpectedFragStart);
342 
343   helper_->GetAllPacketsAndCheck(&packetizer,
344                                  kExpectedSizes,
345                                  kExpectedPart,
346                                  kExpectedFragStart,
347                                  kExpectedNum);
348 }
349 
350 // Verify KeyIdx field.
TEST_F(RtpPacketizerVp8Test,TestKeyIdx)351 TEST_F(RtpPacketizerVp8Test, TestKeyIdx) {
352   const size_t kSizeVector[] = {10, 10, 10};
353   const size_t kNumPartitions = GTEST_ARRAY_SIZE_(kSizeVector);
354   ASSERT_TRUE(Init(kSizeVector, kNumPartitions));
355 
356   hdr_info_.keyIdx = 17;
357   // kMaxSize is only limited by allocated buffer size.
358   const size_t kMaxSize = helper_->buffer_size();
359   RtpPacketizerVp8 packetizer(hdr_info_, kMaxSize, kAggregate);
360   packetizer.SetPayloadData(helper_->payload_data(),
361                             helper_->payload_size(),
362                             helper_->fragmentation());
363 
364   // Expect one single packet of payload_size() + 3 bytes header.
365   const size_t kExpectedSizes[1] = {helper_->payload_size() + 3};
366   const int kExpectedPart[1] = {0};  // Packet starts with partition 0.
367   const bool kExpectedFragStart[1] = {true};
368   const size_t kExpectedNum = GTEST_ARRAY_SIZE_(kExpectedSizes);
369   CHECK_ARRAY_SIZE(kExpectedNum, kExpectedPart);
370   CHECK_ARRAY_SIZE(kExpectedNum, kExpectedFragStart);
371 
372   helper_->GetAllPacketsAndCheck(&packetizer,
373                                  kExpectedSizes,
374                                  kExpectedPart,
375                                  kExpectedFragStart,
376                                  kExpectedNum);
377 }
378 
379 // Verify TID field and KeyIdx field in combination.
TEST_F(RtpPacketizerVp8Test,TestTIDAndKeyIdx)380 TEST_F(RtpPacketizerVp8Test, TestTIDAndKeyIdx) {
381   const size_t kSizeVector[] = {10, 10, 10};
382   const size_t kNumPartitions = GTEST_ARRAY_SIZE_(kSizeVector);
383   ASSERT_TRUE(Init(kSizeVector, kNumPartitions));
384 
385   hdr_info_.temporalIdx = 1;
386   hdr_info_.keyIdx = 5;
387   // kMaxSize is only limited by allocated buffer size.
388   const size_t kMaxSize = helper_->buffer_size();
389   RtpPacketizerVp8 packetizer(hdr_info_, kMaxSize, kAggregate);
390   packetizer.SetPayloadData(helper_->payload_data(),
391                             helper_->payload_size(),
392                             helper_->fragmentation());
393 
394   // Expect one single packet of payload_size() + 3 bytes header.
395   const size_t kExpectedSizes[1] = {helper_->payload_size() + 3};
396   const int kExpectedPart[1] = {0};  // Packet starts with partition 0.
397   const bool kExpectedFragStart[1] = {true};
398   const size_t kExpectedNum = GTEST_ARRAY_SIZE_(kExpectedSizes);
399   CHECK_ARRAY_SIZE(kExpectedNum, kExpectedPart);
400   CHECK_ARRAY_SIZE(kExpectedNum, kExpectedFragStart);
401 
402   helper_->GetAllPacketsAndCheck(&packetizer,
403                                  kExpectedSizes,
404                                  kExpectedPart,
405                                  kExpectedFragStart,
406                                  kExpectedNum);
407 }
408 
409 class RtpDepacketizerVp8Test : public ::testing::Test {
410  protected:
RtpDepacketizerVp8Test()411   RtpDepacketizerVp8Test()
412       : depacketizer_(RtpDepacketizer::Create(kRtpVideoVp8)) {}
413 
ExpectPacket(RtpDepacketizer::ParsedPayload * parsed_payload,const uint8_t * data,size_t length)414   void ExpectPacket(RtpDepacketizer::ParsedPayload* parsed_payload,
415                     const uint8_t* data,
416                     size_t length) {
417     ASSERT_TRUE(parsed_payload != NULL);
418     EXPECT_THAT(std::vector<uint8_t>(
419                     parsed_payload->payload,
420                     parsed_payload->payload + parsed_payload->payload_length),
421                 ::testing::ElementsAreArray(data, length));
422   }
423 
424   rtc::scoped_ptr<RtpDepacketizer> depacketizer_;
425 };
426 
TEST_F(RtpDepacketizerVp8Test,BasicHeader)427 TEST_F(RtpDepacketizerVp8Test, BasicHeader) {
428   const uint8_t kHeaderLength = 1;
429   uint8_t packet[4] = {0};
430   packet[0] = 0x14;  // Binary 0001 0100; S = 1, PartID = 4.
431   packet[1] = 0x01;  // P frame.
432   RtpDepacketizer::ParsedPayload payload;
433 
434   ASSERT_TRUE(depacketizer_->Parse(&payload, packet, sizeof(packet)));
435   ExpectPacket(
436       &payload, packet + kHeaderLength, sizeof(packet) - kHeaderLength);
437   EXPECT_EQ(kVideoFrameDelta, payload.frame_type);
438   EXPECT_EQ(kRtpVideoVp8, payload.type.Video.codec);
439   VerifyBasicHeader(&payload.type, 0, 1, 4);
440   VerifyExtensions(
441       &payload.type, kNoPictureId, kNoTl0PicIdx, kNoTemporalIdx, kNoKeyIdx);
442 }
443 
TEST_F(RtpDepacketizerVp8Test,PictureID)444 TEST_F(RtpDepacketizerVp8Test, PictureID) {
445   const uint8_t kHeaderLength1 = 3;
446   const uint8_t kHeaderLength2 = 4;
447   const uint8_t kPictureId = 17;
448   uint8_t packet[10] = {0};
449   packet[0] = 0xA0;
450   packet[1] = 0x80;
451   packet[2] = kPictureId;
452   RtpDepacketizer::ParsedPayload payload;
453 
454   ASSERT_TRUE(depacketizer_->Parse(&payload, packet, sizeof(packet)));
455   ExpectPacket(
456       &payload, packet + kHeaderLength1, sizeof(packet) - kHeaderLength1);
457   EXPECT_EQ(kVideoFrameDelta, payload.frame_type);
458   EXPECT_EQ(kRtpVideoVp8, payload.type.Video.codec);
459   VerifyBasicHeader(&payload.type, 1, 0, 0);
460   VerifyExtensions(
461       &payload.type, kPictureId, kNoTl0PicIdx, kNoTemporalIdx, kNoKeyIdx);
462 
463   // Re-use packet, but change to long PictureID.
464   packet[2] = 0x80 | kPictureId;
465   packet[3] = kPictureId;
466 
467   payload = RtpDepacketizer::ParsedPayload();
468   ASSERT_TRUE(depacketizer_->Parse(&payload, packet, sizeof(packet)));
469   ExpectPacket(
470       &payload, packet + kHeaderLength2, sizeof(packet) - kHeaderLength2);
471   VerifyBasicHeader(&payload.type, 1, 0, 0);
472   VerifyExtensions(&payload.type,
473                    (kPictureId << 8) + kPictureId,
474                    kNoTl0PicIdx,
475                    kNoTemporalIdx,
476                    kNoKeyIdx);
477 }
478 
TEST_F(RtpDepacketizerVp8Test,Tl0PicIdx)479 TEST_F(RtpDepacketizerVp8Test, Tl0PicIdx) {
480   const uint8_t kHeaderLength = 3;
481   const uint8_t kTl0PicIdx = 17;
482   uint8_t packet[13] = {0};
483   packet[0] = 0x90;
484   packet[1] = 0x40;
485   packet[2] = kTl0PicIdx;
486   RtpDepacketizer::ParsedPayload payload;
487 
488   ASSERT_TRUE(depacketizer_->Parse(&payload, packet, sizeof(packet)));
489   ExpectPacket(
490       &payload, packet + kHeaderLength, sizeof(packet) - kHeaderLength);
491   EXPECT_EQ(kVideoFrameKey, payload.frame_type);
492   EXPECT_EQ(kRtpVideoVp8, payload.type.Video.codec);
493   VerifyBasicHeader(&payload.type, 0, 1, 0);
494   VerifyExtensions(
495       &payload.type, kNoPictureId, kTl0PicIdx, kNoTemporalIdx, kNoKeyIdx);
496 }
497 
TEST_F(RtpDepacketizerVp8Test,TIDAndLayerSync)498 TEST_F(RtpDepacketizerVp8Test, TIDAndLayerSync) {
499   const uint8_t kHeaderLength = 3;
500   uint8_t packet[10] = {0};
501   packet[0] = 0x88;
502   packet[1] = 0x20;
503   packet[2] = 0x80;  // TID(2) + LayerSync(false)
504   RtpDepacketizer::ParsedPayload payload;
505 
506   ASSERT_TRUE(depacketizer_->Parse(&payload, packet, sizeof(packet)));
507   ExpectPacket(
508       &payload, packet + kHeaderLength, sizeof(packet) - kHeaderLength);
509   EXPECT_EQ(kVideoFrameDelta, payload.frame_type);
510   EXPECT_EQ(kRtpVideoVp8, payload.type.Video.codec);
511   VerifyBasicHeader(&payload.type, 0, 0, 8);
512   VerifyExtensions(&payload.type, kNoPictureId, kNoTl0PicIdx, 2, kNoKeyIdx);
513   EXPECT_FALSE(payload.type.Video.codecHeader.VP8.layerSync);
514 }
515 
TEST_F(RtpDepacketizerVp8Test,KeyIdx)516 TEST_F(RtpDepacketizerVp8Test, KeyIdx) {
517   const uint8_t kHeaderLength = 3;
518   const uint8_t kKeyIdx = 17;
519   uint8_t packet[10] = {0};
520   packet[0] = 0x88;
521   packet[1] = 0x10;  // K = 1.
522   packet[2] = kKeyIdx;
523   RtpDepacketizer::ParsedPayload payload;
524 
525   ASSERT_TRUE(depacketizer_->Parse(&payload, packet, sizeof(packet)));
526   ExpectPacket(
527       &payload, packet + kHeaderLength, sizeof(packet) - kHeaderLength);
528   EXPECT_EQ(kVideoFrameDelta, payload.frame_type);
529   EXPECT_EQ(kRtpVideoVp8, payload.type.Video.codec);
530   VerifyBasicHeader(&payload.type, 0, 0, 8);
531   VerifyExtensions(
532       &payload.type, kNoPictureId, kNoTl0PicIdx, kNoTemporalIdx, kKeyIdx);
533 }
534 
TEST_F(RtpDepacketizerVp8Test,MultipleExtensions)535 TEST_F(RtpDepacketizerVp8Test, MultipleExtensions) {
536   const uint8_t kHeaderLength = 6;
537   uint8_t packet[10] = {0};
538   packet[0] = 0x88;
539   packet[1] = 0x80 | 0x40 | 0x20 | 0x10;
540   packet[2] = 0x80 | 17;           // PictureID, high 7 bits.
541   packet[3] = 17;                  // PictureID, low 8 bits.
542   packet[4] = 42;                  // Tl0PicIdx.
543   packet[5] = 0x40 | 0x20 | 0x11;  // TID(1) + LayerSync(true) + KEYIDX(17).
544   RtpDepacketizer::ParsedPayload payload;
545 
546   ASSERT_TRUE(depacketizer_->Parse(&payload, packet, sizeof(packet)));
547   ExpectPacket(
548       &payload, packet + kHeaderLength, sizeof(packet) - kHeaderLength);
549   EXPECT_EQ(kVideoFrameDelta, payload.frame_type);
550   EXPECT_EQ(kRtpVideoVp8, payload.type.Video.codec);
551   VerifyBasicHeader(&payload.type, 0, 0, 8);
552   VerifyExtensions(&payload.type, (17 << 8) + 17, 42, 1, 17);
553 }
554 
TEST_F(RtpDepacketizerVp8Test,TooShortHeader)555 TEST_F(RtpDepacketizerVp8Test, TooShortHeader) {
556   uint8_t packet[4] = {0};
557   packet[0] = 0x88;
558   packet[1] = 0x80 | 0x40 | 0x20 | 0x10;  // All extensions are enabled...
559   packet[2] = 0x80 | 17;  // ... but only 2 bytes PictureID is provided.
560   packet[3] = 17;         // PictureID, low 8 bits.
561   RtpDepacketizer::ParsedPayload payload;
562 
563   EXPECT_FALSE(depacketizer_->Parse(&payload, packet, sizeof(packet)));
564 }
565 
TEST_F(RtpDepacketizerVp8Test,TestWithPacketizer)566 TEST_F(RtpDepacketizerVp8Test, TestWithPacketizer) {
567   const uint8_t kHeaderLength = 5;
568   uint8_t data[10] = {0};
569   uint8_t packet[20] = {0};
570   RTPVideoHeaderVP8 input_header;
571   input_header.nonReference = true;
572   input_header.pictureId = 300;
573   input_header.temporalIdx = 1;
574   input_header.layerSync = false;
575   input_header.tl0PicIdx = kNoTl0PicIdx;  // Disable.
576   input_header.keyIdx = 31;
577   RtpPacketizerVp8 packetizer(input_header, 20);
578   packetizer.SetPayloadData(data, 10, NULL);
579   bool last;
580   size_t send_bytes;
581   ASSERT_TRUE(packetizer.NextPacket(packet, &send_bytes, &last));
582   ASSERT_TRUE(last);
583   RtpDepacketizer::ParsedPayload payload;
584 
585   ASSERT_TRUE(depacketizer_->Parse(&payload, packet, sizeof(packet)));
586   ExpectPacket(
587       &payload, packet + kHeaderLength, sizeof(packet) - kHeaderLength);
588   EXPECT_EQ(kVideoFrameKey, payload.frame_type);
589   EXPECT_EQ(kRtpVideoVp8, payload.type.Video.codec);
590   VerifyBasicHeader(&payload.type, 1, 1, 0);
591   VerifyExtensions(&payload.type,
592                    input_header.pictureId,
593                    input_header.tl0PicIdx,
594                    input_header.temporalIdx,
595                    input_header.keyIdx);
596   EXPECT_EQ(payload.type.Video.codecHeader.VP8.layerSync,
597             input_header.layerSync);
598 }
599 
TEST_F(RtpDepacketizerVp8Test,TestEmptyPayload)600 TEST_F(RtpDepacketizerVp8Test, TestEmptyPayload) {
601   // Using a wild pointer to crash on accesses from inside the depacketizer.
602   uint8_t* garbage_ptr = reinterpret_cast<uint8_t*>(0x4711);
603   RtpDepacketizer::ParsedPayload payload;
604   EXPECT_FALSE(depacketizer_->Parse(&payload, garbage_ptr, 0));
605 }
606 }  // namespace webrtc
607