Index: webrtc/modules/rtp_rtcp/source/rtp_format_vp9_unittest.cc |
diff --git a/webrtc/modules/rtp_rtcp/source/rtp_format_vp9_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtp_format_vp9_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..242b38efb3b925d659a1492871882489bda48987 |
--- /dev/null |
+++ b/webrtc/modules/rtp_rtcp/source/rtp_format_vp9_unittest.cc |
@@ -0,0 +1,632 @@ |
+/* |
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. |
+ * |
+ * Use of this source code is governed by a BSD-style license |
+ * that can be found in the LICENSE file in the root of the source |
+ * tree. An additional intellectual property rights grant can be found |
+ * in the file PATENTS. All contributing project authors may |
+ * be found in the AUTHORS file in the root of the source tree. |
+ */ |
+ |
+#include <vector> |
+ |
+#include "testing/gmock/include/gmock/gmock.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+#include "webrtc/modules/rtp_rtcp/source/rtp_format_vp9.h" |
+#include "webrtc/typedefs.h" |
+ |
+namespace webrtc { |
+namespace { |
+void VerifyHeader(const RTPVideoHeaderVP9& expected, |
+ const RTPVideoHeaderVP9& actual) { |
+ EXPECT_EQ(expected.interLayerPredicted, actual.interLayerPredicted); |
+ EXPECT_EQ(expected.interPicPredicted, actual.interPicPredicted); |
+ EXPECT_EQ(expected.flexibleMode, actual.flexibleMode); |
+ EXPECT_EQ(expected.beginningOfFrame, actual.beginningOfFrame); |
+ EXPECT_EQ(expected.endOfFrame, actual.endOfFrame); |
+ EXPECT_EQ(expected.ssDataAvailable, actual.ssDataAvailable); |
+ EXPECT_EQ(expected.pictureId, actual.pictureId); |
+ EXPECT_EQ(expected.maxPictureId, actual.maxPictureId); |
+ EXPECT_EQ(expected.temporalIdx == kNoTemporalIdx ? 0 : expected.temporalIdx, |
+ actual.temporalIdx); |
+ EXPECT_EQ(expected.spatialIdx == kNoSpatialIdx ? 0 : expected.spatialIdx, |
+ actual.spatialIdx); |
+ EXPECT_EQ(expected.gofIdx, actual.gofIdx); |
+ EXPECT_EQ(expected.tl0PicIdx, actual.tl0PicIdx); |
+ EXPECT_EQ(expected.temporalUpSwitch, actual.temporalUpSwitch); |
+ |
+ EXPECT_EQ(expected.numRefPics, actual.numRefPics); |
+ for (uint8_t i = 0; i < expected.numRefPics; ++i) { |
+ EXPECT_EQ(expected.pidDiff[i], actual.pidDiff[i]); |
+ } |
+ if (expected.ssDataAvailable) { |
+ EXPECT_EQ(expected.spatialLayerResolutionPresent, |
+ actual.spatialLayerResolutionPresent); |
+ EXPECT_EQ(expected.numSpatialLayers, actual.numSpatialLayers); |
+ if (expected.spatialLayerResolutionPresent) { |
+ for (size_t i = 0; i < expected.numSpatialLayers; i++) { |
+ EXPECT_EQ(expected.width[i], actual.width[i]); |
+ EXPECT_EQ(expected.height[i], actual.height[i]); |
+ } |
+ } |
+ EXPECT_EQ(expected.gof.numFramesInGof, actual.gof.numFramesInGof); |
+ for (size_t i = 0; i < expected.gof.numFramesInGof; i++) { |
+ EXPECT_EQ(expected.gof.temporalUpSwitch[i], |
+ actual.gof.temporalUpSwitch[i]); |
+ EXPECT_EQ(expected.gof.temporalIdx[i], actual.gof.temporalIdx[i]); |
+ EXPECT_EQ(expected.gof.numRefPics[i], actual.gof.numRefPics[i]); |
+ for (size_t j = 0; j < expected.gof.numRefPics[i]; j++) { |
+ EXPECT_EQ(expected.gof.pidDiff[i][j], actual.gof.pidDiff[i][j]); |
+ } |
+ } |
+ } |
+} |
+ |
+void VerifyPayload(const RtpDepacketizer::ParsedPayload& parsed, |
+ const uint8_t* payload, |
+ size_t payload_length) { |
+ EXPECT_EQ(payload, parsed.payload); |
+ EXPECT_EQ(payload_length, parsed.payload_length); |
+ EXPECT_THAT(std::vector<uint8_t>(parsed.payload, |
+ parsed.payload + parsed.payload_length), |
+ ::testing::ElementsAreArray(payload, payload_length)); |
+} |
+ |
+void ParseAndCheckPacket(const uint8_t* packet, |
+ const RTPVideoHeaderVP9& expected, |
+ size_t expected_hdr_length, |
+ size_t expected_length) { |
+ rtc::scoped_ptr<RtpDepacketizer> depacketizer(new RtpDepacketizerVp9()); |
+ RtpDepacketizer::ParsedPayload parsed; |
+ ASSERT_TRUE(depacketizer->Parse(&parsed, packet, expected_length)); |
+ // TODO(asapersson): Add when type is added. |
+ // EXPECT_EQ(kRtpVideoVp9, parsed.type.Video.codec); |
+ VerifyHeader(expected, parsed.type.Video.codecHeader.VP9); |
+ const size_t kExpectedPayloadLength = expected_length - expected_hdr_length; |
+ VerifyPayload(parsed, packet + expected_hdr_length, kExpectedPayloadLength); |
+} |
+} // namespace |
+ |
+// Payload descriptor for flexible mode |
+// 0 1 2 3 4 5 6 7 |
+// +-+-+-+-+-+-+-+-+ |
+// |I|P|L|F|B|E|V|-| (REQUIRED) |
+// +-+-+-+-+-+-+-+-+ |
+// I: |M| PICTURE ID | (RECOMMENDED) |
+// +-+-+-+-+-+-+-+-+ |
+// M: | EXTENDED PID | (RECOMMENDED) |
+// +-+-+-+-+-+-+-+-+ |
+// L: | T |U| S |D| (CONDITIONALLY RECOMMENDED) |
+// +-+-+-+-+-+-+-+-+ -| |
+// P,F: | P_DIFF |X|N| (CONDITIONALLY RECOMMENDED) . |
+// +-+-+-+-+-+-+-+-+ . up to 3 times |
+// X: |EXTENDED P_DIFF| (OPTIONAL) . |
+// +-+-+-+-+-+-+-+-+ -| |
+// V: | SS | |
+// | .. | |
+// +-+-+-+-+-+-+-+-+ |
+// |
+// Payload descriptor for non-flexible mode |
+// 0 1 2 3 4 5 6 7 |
+// +-+-+-+-+-+-+-+-+ |
+// |I|P|L|F|B|E|V|-| (REQUIRED) |
+// +-+-+-+-+-+-+-+-+ |
+// I: |M| PICTURE ID | (RECOMMENDED) |
+// +-+-+-+-+-+-+-+-+ |
+// M: | EXTENDED PID | (RECOMMENDED) |
+// +-+-+-+-+-+-+-+-+ |
+// L: |GOF_IDX| S |D| (CONDITIONALLY RECOMMENDED) |
+// +-+-+-+-+-+-+-+-+ |
+// | TL0PICIDX | (CONDITIONALLY REQUIRED) |
+// +-+-+-+-+-+-+-+-+ |
+// V: | SS | |
+// | .. | |
+// +-+-+-+-+-+-+-+-+ |
+ |
+class RtpPacketizerVp9Test : public ::testing::Test { |
+ protected: |
+ RtpPacketizerVp9Test() {} |
+ virtual void SetUp() { |
+ expected_.InitRTPVideoHeaderVP9(); |
+ // Always input one layer frame at a time. |
+ expected_.beginningOfFrame = true; |
+ expected_.endOfFrame = true; |
+ } |
+ |
+ rtc::scoped_ptr<uint8_t[]> packet_; |
+ rtc::scoped_ptr<uint8_t[]> payload_; |
+ size_t payload_size_; |
+ size_t payload_pos_; |
+ RTPVideoHeaderVP9 expected_; |
+ rtc::scoped_ptr<RtpPacketizerVp9> packetizer_; |
+ |
+ void Init(size_t payload_size, size_t packet_size) { |
+ payload_.reset(new uint8_t[payload_size]); |
+ memset(payload_.get(), 7, payload_size); |
+ payload_size_ = payload_size; |
+ payload_pos_ = 0; |
+ packetizer_.reset(new RtpPacketizerVp9(expected_, packet_size)); |
+ packetizer_->SetPayloadData(payload_.get(), payload_size_, NULL); |
+ |
+ const int kMaxPayloadDescriptorLength = 100; |
+ packet_.reset(new uint8_t[payload_size_ + kMaxPayloadDescriptorLength]); |
+ } |
+ |
+ void CheckPayload(const uint8_t* packet, |
+ size_t start_pos, |
+ size_t end_pos, |
+ bool last) { |
+ for (size_t i = start_pos; i < end_pos; ++i) { |
+ EXPECT_EQ(packet[i], payload_[payload_pos_++]); |
+ } |
+ EXPECT_EQ(last, payload_pos_ == payload_size_); |
+ } |
+ |
+ void CreateParseAndCheckPackets(const size_t* expected_hdr_sizes, |
+ const size_t* expected_sizes, |
+ size_t expected_num_packets) { |
+ ASSERT_TRUE(packetizer_.get() != NULL); |
+ size_t length = 0; |
+ bool last = false; |
+ if (expected_num_packets == 0) { |
+ EXPECT_FALSE(packetizer_->NextPacket(packet_.get(), &length, &last)); |
+ return; |
+ } |
+ for (size_t i = 0; i < expected_num_packets; ++i) { |
+ EXPECT_TRUE(packetizer_->NextPacket(packet_.get(), &length, &last)); |
+ EXPECT_EQ(expected_sizes[i], length); |
+ RTPVideoHeaderVP9 hdr = expected_; |
+ hdr.beginningOfFrame = (i == 0); |
+ hdr.endOfFrame = last; |
+ ParseAndCheckPacket(packet_.get(), hdr, expected_hdr_sizes[i], length); |
+ CheckPayload(packet_.get(), expected_hdr_sizes[i], length, last); |
+ } |
+ EXPECT_TRUE(last); |
+ } |
+}; |
+ |
+TEST_F(RtpPacketizerVp9Test, TestEqualSizedMode_OnePacket) { |
+ const size_t kFrameSize = 25; |
+ const size_t kPacketSize = 26; |
+ Init(kFrameSize, kPacketSize); |
+ |
+ // One packet: |
+ // I:0, P:0, L:0, F:0, B:1, E:1, V:0 (1hdr + 25 payload) |
+ const size_t kExpectedHdrSizes[] = {1}; |
+ const size_t kExpectedSizes[] = {26}; |
+ const size_t kExpectedNum = GTEST_ARRAY_SIZE_(kExpectedSizes); |
+ CreateParseAndCheckPackets(kExpectedHdrSizes, kExpectedSizes, kExpectedNum); |
+} |
+ |
+TEST_F(RtpPacketizerVp9Test, TestEqualSizedMode_TwoPackets) { |
+ const size_t kFrameSize = 27; |
+ const size_t kPacketSize = 27; |
+ Init(kFrameSize, kPacketSize); |
+ |
+ // Two packets: |
+ // I:0, P:0, L:0, F:0, B:1, E:0, V:0 (1hdr + 14 payload) |
+ // I:0, P:0, L:0, F:0, B:0, E:1, V:0 (1hdr + 13 payload) |
+ const size_t kExpectedHdrSizes[] = {1, 1}; |
+ const size_t kExpectedSizes[] = {15, 14}; |
+ const size_t kExpectedNum = GTEST_ARRAY_SIZE_(kExpectedSizes); |
+ CreateParseAndCheckPackets(kExpectedHdrSizes, kExpectedSizes, kExpectedNum); |
+} |
+ |
+TEST_F(RtpPacketizerVp9Test, TestTooShortBufferToFitPayload) { |
+ const size_t kFrameSize = 1; |
+ const size_t kPacketSize = 1; |
+ Init(kFrameSize, kPacketSize); // 1hdr + 1 payload |
+ |
+ const size_t kExpectedNum = 0; |
+ CreateParseAndCheckPackets(NULL, NULL, kExpectedNum); |
+} |
+ |
+TEST_F(RtpPacketizerVp9Test, TestOneBytePictureId) { |
+ const size_t kFrameSize = 30; |
+ const size_t kPacketSize = 12; |
+ |
+ expected_.pictureId = kMaxOneBytePictureId; // 2 byte payload descriptor |
+ expected_.maxPictureId = kMaxOneBytePictureId; |
+ Init(kFrameSize, kPacketSize); |
+ |
+ // Three packets: |
+ // I:1, P:0, L:0, F:0, B:1, E:0, V:0 (2hdr + 10 payload) |
+ // I:1, P:0, L:0, F:0, B:0, E:0, V:0 (2hdr + 10 payload) |
+ // I:1, P:0, L:0, F:0, B:0, E:1, V:0 (2hdr + 10 payload) |
+ const size_t kExpectedHdrSizes[] = {2, 2, 2}; |
+ const size_t kExpectedSizes[] = {12, 12, 12}; |
+ const size_t kExpectedNum = GTEST_ARRAY_SIZE_(kExpectedSizes); |
+ CreateParseAndCheckPackets(kExpectedHdrSizes, kExpectedSizes, kExpectedNum); |
+} |
+ |
+TEST_F(RtpPacketizerVp9Test, TestTwoBytePictureId) { |
+ const size_t kFrameSize = 31; |
+ const size_t kPacketSize = 13; |
+ |
+ expected_.pictureId = kMaxTwoBytePictureId; // 3 byte payload descriptor |
+ Init(kFrameSize, kPacketSize); |
+ |
+ // Four packets: |
+ // I:1, P:0, L:0, F:0, B:1, E:0, V:0 (3hdr + 8 payload) |
+ // I:1, P:0, L:0, F:0, B:0, E:0, V:0 (3hdr + 8 payload) |
+ // I:1, P:0, L:0, F:0, B:0, E:0, V:0 (3hdr + 8 payload) |
+ // I:1, P:0, L:0, F:0, B:0, E:1, V:0 (3hdr + 7 payload) |
+ const size_t kExpectedHdrSizes[] = {3, 3, 3, 3}; |
+ const size_t kExpectedSizes[] = {11, 11, 11, 10}; |
+ const size_t kExpectedNum = GTEST_ARRAY_SIZE_(kExpectedSizes); |
+ CreateParseAndCheckPackets(kExpectedHdrSizes, kExpectedSizes, kExpectedNum); |
+} |
+ |
+TEST_F(RtpPacketizerVp9Test, TestLayerInfoWithNonFlexibleMode) { |
+ const size_t kFrameSize = 30; |
+ const size_t kPacketSize = 25; |
+ |
+ expected_.gofIdx = 3; |
+ expected_.spatialIdx = 2; |
+ expected_.interLayerPredicted = true; // D |
+ expected_.tl0PicIdx = 117; |
+ Init(kFrameSize, kPacketSize); |
+ |
+ // Two packets: |
+ // | I:0, P:0, L:1, F:0, B:1, E:0, V:0 | (3hdr + 15 payload) |
+ // L: | GOF_IDX:3, S:2, D:1 | TL0PICIDX:117 | |
+ // | I:0, P:0, L:1, F:0, B:0, E:1, V:0 | (3hdr + 15 payload) |
+ // L: | GOF_IDX:3, S:2, D:1 | TL0PICIDX:117 | |
+ const size_t kExpectedHdrSizes[] = {3, 3}; |
+ const size_t kExpectedSizes[] = {18, 18}; |
+ const size_t kExpectedNum = GTEST_ARRAY_SIZE_(kExpectedSizes); |
+ CreateParseAndCheckPackets(kExpectedHdrSizes, kExpectedSizes, kExpectedNum); |
+} |
+ |
+TEST_F(RtpPacketizerVp9Test, TestLayerInfoWithFlexibleMode) { |
+ const size_t kFrameSize = 21; |
+ const size_t kPacketSize = 23; |
+ |
+ expected_.flexibleMode = true; |
+ expected_.temporalIdx = 3; |
+ expected_.temporalUpSwitch = true; // U |
+ expected_.spatialIdx = 2; |
+ expected_.interLayerPredicted = false; // D |
+ Init(kFrameSize, kPacketSize); |
+ |
+ // One packet: |
+ // I:0, P:0, L:1, F:1, B:1, E:1, V:0 (2hdr + 21 payload) |
+ // L: T:3, U:1, S:2, D:0 |
+ const size_t kExpectedHdrSizes[] = {2}; |
+ const size_t kExpectedSizes[] = {23}; |
+ const size_t kExpectedNum = GTEST_ARRAY_SIZE_(kExpectedSizes); |
+ CreateParseAndCheckPackets(kExpectedHdrSizes, kExpectedSizes, kExpectedNum); |
+} |
+ |
+TEST_F(RtpPacketizerVp9Test, TestRefIdx) { |
+ const size_t kFrameSize = 16; |
+ const size_t kPacketSize = 22; |
+ |
+ expected_.interPicPredicted = true; // P |
+ expected_.flexibleMode = true; // F |
+ expected_.pictureId = 100; |
+ expected_.numRefPics = 2; |
+ expected_.pidDiff[0] = 3; |
+ expected_.pidDiff[1] = 1171; |
+ Init(kFrameSize, kPacketSize); |
+ |
+ // Two packets: |
+ // I:1, P:1, L:0, F:1, B:1, E:1, V:0 (6hdr + 16 payload) |
+ // I: 100 (2 bytes) |
+ // P,F: P_DIFF:3, X:0, N:1 |
+ // P_DIFF:1171, X:1, N:0 (2 bytes) |
+ const size_t kExpectedHdrSizes[] = {6}; |
+ const size_t kExpectedSizes[] = {22}; |
+ const size_t kExpectedNum = GTEST_ARRAY_SIZE_(kExpectedSizes); |
+ CreateParseAndCheckPackets(kExpectedHdrSizes, kExpectedSizes, kExpectedNum); |
+} |
+ |
+TEST_F(RtpPacketizerVp9Test, TestRefIdxFailsWithoutPictureId) { |
+ const size_t kFrameSize = 16; |
+ const size_t kPacketSize = 22; |
+ |
+ expected_.interPicPredicted = true; |
+ expected_.flexibleMode = true; |
+ expected_.numRefPics = 1; |
+ expected_.pidDiff[0] = 3; |
+ Init(kFrameSize, kPacketSize); |
+ |
+ const size_t kExpectedNum = 0; |
+ CreateParseAndCheckPackets(NULL, NULL, kExpectedNum); |
+} |
+ |
+TEST_F(RtpPacketizerVp9Test, TestSsDataWithoutSpatialResolutionPresent) { |
+ const size_t kFrameSize = 21; |
+ const size_t kPacketSize = 25; |
+ |
+ expected_.ssDataAvailable = true; |
+ expected_.numSpatialLayers = 1; |
+ expected_.spatialLayerResolutionPresent = false; |
+ expected_.gof.numFramesInGof = 1; |
+ expected_.gof.temporalIdx[0] = 0; |
+ expected_.gof.temporalUpSwitch[0] = true; |
+ expected_.gof.numRefPics[0] = 1; |
+ expected_.gof.pidDiff[0][0] = 4; |
+ Init(kFrameSize, kPacketSize); |
+ |
+ // One packet: |
+ // I:0, P:0, L:0, F:0, B:1, E:1, V:1 (4hdr + 21 payload) |
+ // N_S:0, Y:0, N_G:0 |
+ // T:0, U:1, R:1 | P_DIFF[0][0]:4 |
+ const size_t kExpectedHdrSizes[] = {4}; |
+ const size_t kExpectedSizes[] = {25}; |
+ const size_t kExpectedNum = GTEST_ARRAY_SIZE_(kExpectedSizes); |
+ CreateParseAndCheckPackets(kExpectedHdrSizes, kExpectedSizes, kExpectedNum); |
+} |
+ |
+TEST_F(RtpPacketizerVp9Test, TestSsData) { |
+ const size_t kFrameSize = 21; |
+ const size_t kPacketSize = 39; |
+ |
+ expected_.ssDataAvailable = true; |
+ expected_.numSpatialLayers = 2; |
+ expected_.spatialLayerResolutionPresent = true; |
+ expected_.width[0] = 640; |
+ expected_.width[1] = 1280; |
+ expected_.height[0] = 360; |
+ expected_.height[1] = 720; |
+ expected_.gof.numFramesInGof = 3; |
+ expected_.gof.temporalIdx[0] = 0; |
+ expected_.gof.temporalIdx[1] = 1; |
+ expected_.gof.temporalIdx[2] = 2; |
+ expected_.gof.temporalUpSwitch[0] = true; |
+ expected_.gof.temporalUpSwitch[1] = true; |
+ expected_.gof.temporalUpSwitch[2] = false; |
+ expected_.gof.numRefPics[0] = 0; |
+ expected_.gof.numRefPics[1] = 3; |
+ expected_.gof.numRefPics[2] = 2; |
+ expected_.gof.pidDiff[1][0] = 5; |
+ expected_.gof.pidDiff[1][1] = 6; |
+ expected_.gof.pidDiff[1][2] = 7; |
+ expected_.gof.pidDiff[2][0] = 8; |
+ expected_.gof.pidDiff[2][1] = 9; |
+ Init(kFrameSize, kPacketSize); |
+ |
+ // One packet: |
+ // I:0, P:0, L:0, F:0, B:1, E:1, V:1 (18hdr + 21 payload) |
+ // N_S:1, Y:1, N_G:2 |
+ // WIDTH:640 // 2 bytes |
+ // HEIGHT:360 // 2 bytes |
+ // WIDTH:1280 // 2 bytes |
+ // HEIGHT:720 // 2 bytes |
+ // T:0, U:1, R:0 |
+ // T:1, U:1, R:3 | P_DIFF[1][0]:5 | P_DIFF[1][1]:6 | P_DIFF[1][2]:7 |
+ // T:2, U:0, R:2 | P_DIFF[2][0]:8 | P_DIFF[2][0]:9 |
+ const size_t kExpectedHdrSizes[] = {18}; |
+ const size_t kExpectedSizes[] = {39}; |
+ const size_t kExpectedNum = GTEST_ARRAY_SIZE_(kExpectedSizes); |
+ CreateParseAndCheckPackets(kExpectedHdrSizes, kExpectedSizes, kExpectedNum); |
+} |
+ |
+ |
+class RtpDepacketizerVp9Test : public ::testing::Test { |
+ protected: |
+ RtpDepacketizerVp9Test() |
+ : depacketizer_(new RtpDepacketizerVp9()) {} |
+ |
+ virtual void SetUp() { |
+ expected_.InitRTPVideoHeaderVP9(); |
+ } |
+ |
+ RTPVideoHeaderVP9 expected_; |
+ rtc::scoped_ptr<RtpDepacketizer> depacketizer_; |
+}; |
+ |
+TEST_F(RtpDepacketizerVp9Test, ParseBasicHeader) { |
+ const uint8_t kHeaderLength = 1; |
+ uint8_t packet[4] = {0}; |
+ packet[0] = 0x0C; // I:0 P:0 L:0 F:0 B:1 E:1 V:0 R:0 |
+ expected_.beginningOfFrame = true; |
+ expected_.endOfFrame = true; |
+ ParseAndCheckPacket(packet, expected_, kHeaderLength, sizeof(packet)); |
+} |
+ |
+TEST_F(RtpDepacketizerVp9Test, ParseOneBytePictureId) { |
+ const uint8_t kHeaderLength = 2; |
+ uint8_t packet[10] = {0}; |
+ packet[0] = 0x80; // I:1 P:0 L:0 F:0 B:0 E:0 V:0 R:0 |
+ packet[1] = kMaxOneBytePictureId; |
+ |
+ expected_.pictureId = kMaxOneBytePictureId; |
+ expected_.maxPictureId = kMaxOneBytePictureId; |
+ ParseAndCheckPacket(packet, expected_, kHeaderLength, sizeof(packet)); |
+} |
+ |
+TEST_F(RtpDepacketizerVp9Test, ParseTwoBytePictureId) { |
+ const uint8_t kHeaderLength = 3; |
+ uint8_t packet[10] = {0}; |
+ packet[0] = 0x80; // I:1 P:0 L:0 F:0 B:0 E:0 V:0 R:0 |
+ packet[1] = 0x80 | ((kMaxTwoBytePictureId >> 8) & 0x7F); |
+ packet[2] = kMaxTwoBytePictureId & 0xFF; |
+ |
+ expected_.pictureId = kMaxTwoBytePictureId; |
+ expected_.maxPictureId = kMaxTwoBytePictureId; |
+ ParseAndCheckPacket(packet, expected_, kHeaderLength, sizeof(packet)); |
+} |
+ |
+TEST_F(RtpDepacketizerVp9Test, ParseLayerInfoWithNonFlexibleMode) { |
+ const uint8_t kHeaderLength = 3; |
+ const uint8_t kGofIdx = 7; |
+ const uint8_t kSpatialIdx = 1; |
+ const uint8_t kDbit = 1; |
+ const uint8_t kTl0PicIdx = 17; |
+ uint8_t packet[13] = {0}; |
+ packet[0] = 0x20; // I:0 P:0 L:1 F:0 B:0 E:0 V:0 R:0 |
+ packet[1] = (kGofIdx << 4) | (kSpatialIdx << 1) | kDbit; // GOF_IDX:7 S:1 D:1 |
+ packet[2] = kTl0PicIdx; // TL0PICIDX:17 |
+ |
+ expected_.gofIdx = kGofIdx; |
+ expected_.spatialIdx = kSpatialIdx; |
+ expected_.interLayerPredicted = kDbit ? true : false; |
+ expected_.tl0PicIdx = kTl0PicIdx; |
+ ParseAndCheckPacket(packet, expected_, kHeaderLength, sizeof(packet)); |
+} |
+ |
+TEST_F(RtpDepacketizerVp9Test, ParseLayerInfoWithFlexibleMode) { |
+ const uint8_t kHeaderLength = 2; |
+ const uint8_t kTemporalIdx = 2; |
+ const uint8_t kUbit = 1; |
+ const uint8_t kSpatialIdx = 0; |
+ const uint8_t kDbit = 0; |
+ uint8_t packet[13] = {0}; |
+ packet[0] = 0x38; // I:0 P:0 L:1 F:1 B:1 E:0 V:0 R:0 |
+ packet[1] = (kTemporalIdx << 5) | (kUbit << 4) | (kSpatialIdx << 1) | kDbit; |
+ |
+ // I:0 P:0 L:1 F:1 B:1 E:0 V:0 |
+ // L: T:2 U:1 S:0 D:0 |
+ expected_.beginningOfFrame = true; |
+ expected_.flexibleMode = true; |
+ expected_.temporalIdx = kTemporalIdx; |
+ expected_.temporalUpSwitch = kUbit ? true : false; |
+ expected_.spatialIdx = kSpatialIdx; |
+ expected_.interLayerPredicted = kDbit ? true : false; |
+ ParseAndCheckPacket(packet, expected_, kHeaderLength, sizeof(packet)); |
+} |
+ |
+TEST_F(RtpDepacketizerVp9Test, ParseRefIdx) { |
+ const uint8_t kHeaderLength = 7; |
+ const int16_t kPictureId = 17; |
+ const int16_t kPdiff1 = 17; |
+ const int16_t kPdiff2 = 18; |
+ const int16_t kExtPdiff3 = 2171; |
+ uint8_t packet[13] = {0}; |
+ packet[0] = 0xD8; // I:1 P:1 L:0 F:1 B:1 E:0 V:0 R:0 |
+ packet[1] = 0x80 | ((kPictureId >> 8) & 0x7F); // Two byte pictureID. |
+ packet[2] = kPictureId; |
+ packet[3] = (kPdiff1 << 2) | (0 << 1) | 1; // P_DIFF X:0 N:1 |
+ packet[4] = (kPdiff2 << 2) | (0 << 1) | 1; // P_DIFF X:0 N:1 |
+ packet[5] = ((kExtPdiff3 >> 8) << 2) | (1 << 1) | 0; // P_DIFF X:1 N:0 |
+ packet[6] = kExtPdiff3 & 0xff; // EXTENDED P_DIFF |
+ |
+ // I:1 P:1 L:0 F:1 B:1 E:0 V:0 |
+ // I: PICTURE ID:17 |
+ // I: |
+ // P,F: P_DIFF:17 X:0 N:1 => refPictureId = 17 - 17 = 0 |
+ // P,F: P_DIFF:18 X:0 N:1 => refPictureId = 0x7FFF + 1 + 17 - 18 = 0x7FFF |
+ // P,F: P_DIFF:2171 X:1 N:0 => refPictureId = 0x7FFF + 1 + 17 - 2171 = 30614 |
+ expected_.beginningOfFrame = true; |
+ expected_.interPicPredicted = true; |
+ expected_.flexibleMode = true; |
+ expected_.pictureId = kPictureId; |
+ expected_.numRefPics = 3; |
+ expected_.pidDiff[0] = kPdiff1; |
+ expected_.pidDiff[1] = kPdiff2; |
+ expected_.pidDiff[2] = kExtPdiff3; |
+ expected_.refPictureId[0] = 0; |
+ expected_.refPictureId[1] = 0x7FFF; |
+ expected_.refPictureId[2] = 30614; |
+ ParseAndCheckPacket(packet, expected_, kHeaderLength, sizeof(packet)); |
+} |
+ |
+TEST_F(RtpDepacketizerVp9Test, ParseRefIdxFailsWithNoPictureId) { |
+ const int16_t kPdiff = 3; |
+ uint8_t packet[13] = {0}; |
+ packet[0] = 0x58; // I:0 P:1 L:0 F:1 B:1 E:0 V:0 R:0 |
+ packet[1] = (kPdiff << 2) | (0 << 1) | 0; // P,F: P_DIFF:3 X:0 N:0 |
+ |
+ RtpDepacketizer::ParsedPayload parsed; |
+ EXPECT_FALSE(depacketizer_->Parse(&parsed, packet, sizeof(packet))); |
+} |
+ |
+TEST_F(RtpDepacketizerVp9Test, ParseRefIdxFailsWithTooManyRefPics) { |
+ const int16_t kPdiff = 3; |
+ uint8_t packet[13] = {0}; |
+ packet[0] = 0xD8; // I:1 P:1 L:0 F:1 B:1 E:0 V:0 R:0 |
+ packet[1] = kMaxOneBytePictureId; // I: PICTURE ID:127 |
+ packet[2] = (kPdiff << 2) | (0 << 1) | 1; // P,F: P_DIFF:3 X:0 N:1 |
+ packet[3] = (kPdiff << 2) | (0 << 1) | 1; // P,F: P_DIFF:3 X:0 N:1 |
+ packet[4] = (kPdiff << 2) | (0 << 1) | 1; // P,F: P_DIFF:3 X:0 N:1 |
+ packet[5] = (kPdiff << 2) | (0 << 1) | 0; // P,F: P_DIFF:3 X:0 N:0 |
+ |
+ RtpDepacketizer::ParsedPayload parsed; |
+ EXPECT_FALSE(depacketizer_->Parse(&parsed, packet, sizeof(packet))); |
+} |
+ |
+TEST_F(RtpDepacketizerVp9Test, ParseSsData) { |
+ const uint8_t kHeaderLength = 5; |
+ const uint8_t kYbit = 0; |
+ const size_t kNs = 2; |
+ const size_t kNg = 2; |
+ uint8_t packet[23] = {0}; |
+ packet[0] = 0x0A; // I:0 P:0 L:0 F:0 B:1 E:0 V:1 R:0 |
+ packet[1] = ((kNs - 1) << 5) | (kYbit << 4) | (kNg - 1); // N_S Y N_G |
+ packet[2] = (0 << 5) | (1 << 4) | (0 << 2) | 0; // T:0 U:1 R:0 - |
+ packet[3] = (2 << 5) | (0 << 4) | (1 << 2) | 0; // T:2 U:0 R:1 - |
+ packet[4] = 33; |
+ |
+ expected_.beginningOfFrame = true; |
+ expected_.ssDataAvailable = true; |
+ expected_.numSpatialLayers = kNs; |
+ expected_.spatialLayerResolutionPresent = kYbit ? true : false; |
+ expected_.gof.numFramesInGof = kNg; |
+ expected_.gof.temporalIdx[0] = 0; |
+ expected_.gof.temporalIdx[1] = 2; |
+ expected_.gof.temporalUpSwitch[0] = true; |
+ expected_.gof.temporalUpSwitch[1] = false; |
+ expected_.gof.numRefPics[0] = 0; |
+ expected_.gof.numRefPics[1] = 1; |
+ expected_.gof.pidDiff[1][0] = 33; |
+ ParseAndCheckPacket(packet, expected_, kHeaderLength, sizeof(packet)); |
+} |
+ |
+TEST_F(RtpDepacketizerVp9Test, ParseFirstPacketInKeyFrame) { |
+ uint8_t packet[2] = {0}; |
+ packet[0] = 0x08; // I:0 P:0 L:0 F:0 B:1 E:0 V:0 R:0 |
+ |
+ RtpDepacketizer::ParsedPayload parsed; |
+ ASSERT_TRUE(depacketizer_->Parse(&parsed, packet, sizeof(packet))); |
+ EXPECT_EQ(kVideoFrameKey, parsed.frame_type); |
+ EXPECT_TRUE(parsed.type.Video.isFirstPacket); |
+} |
+ |
+TEST_F(RtpDepacketizerVp9Test, ParseLastPacketInDeltaFrame) { |
+ uint8_t packet[2] = {0}; |
+ packet[0] = 0x44; // I:0 P:1 L:0 F:0 B:0 E:1 V:0 R:0 |
+ |
+ RtpDepacketizer::ParsedPayload parsed; |
+ ASSERT_TRUE(depacketizer_->Parse(&parsed, packet, sizeof(packet))); |
+ EXPECT_EQ(kVideoFrameDelta, parsed.frame_type); |
+ EXPECT_FALSE(parsed.type.Video.isFirstPacket); |
+} |
+ |
+TEST_F(RtpDepacketizerVp9Test, ParseResolution) { |
+ const uint16_t kWidth[2] = {640, 1280}; |
+ const uint16_t kHeight[2] = {360, 720}; |
+ uint8_t packet[20] = {0}; |
+ packet[0] = 0x0A; // I:0 P:0 L:0 F:0 B:1 E:0 V:1 R:0 |
+ packet[1] = (1 << 5) | (1 << 4) | 0; // N_S:1 Y:1 N_G:0 |
+ packet[2] = kWidth[0] >> 8; |
+ packet[3] = kWidth[0] & 0xFF; |
+ packet[4] = kHeight[0] >> 8; |
+ packet[5] = kHeight[0] & 0xFF; |
+ packet[6] = kWidth[1] >> 8; |
+ packet[7] = kWidth[1] & 0xFF; |
+ packet[8] = kHeight[1] >> 8; |
+ packet[9] = kHeight[1] & 0xFF; |
+ packet[10] = 0; // T:0 U:0 R:0 - |
+ |
+ RtpDepacketizer::ParsedPayload parsed; |
+ ASSERT_TRUE(depacketizer_->Parse(&parsed, packet, sizeof(packet))); |
+ EXPECT_EQ(kWidth[0], parsed.type.Video.width); |
+ EXPECT_EQ(kHeight[0], parsed.type.Video.height); |
+} |
+ |
+TEST_F(RtpDepacketizerVp9Test, ParseFailsForNoPayloadLength) { |
+ uint8_t packet[1] = {0}; |
+ RtpDepacketizer::ParsedPayload parsed; |
+ EXPECT_FALSE(depacketizer_->Parse(&parsed, packet, 0)); |
+} |
+ |
+TEST_F(RtpDepacketizerVp9Test, ParseFailsForTooShortBufferToFitPayload) { |
+ const uint8_t kHeaderLength = 1; |
+ uint8_t packet[kHeaderLength] = {0}; |
+ RtpDepacketizer::ParsedPayload parsed; |
+ EXPECT_FALSE(depacketizer_->Parse(&parsed, packet, sizeof(packet))); |
+} |
+ |
+} // namespace webrtc |