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