diff --git a/src/modules/rtp_rtcp/source/rtp_format_vp8_test_helper.cc b/src/modules/rtp_rtcp/source/rtp_format_vp8_test_helper.cc new file mode 100644 index 0000000000..4c9e386383 --- /dev/null +++ b/src/modules/rtp_rtcp/source/rtp_format_vp8_test_helper.cc @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2011 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 "modules/rtp_rtcp/source/rtp_format_vp8_test_helper.h" + +#include "gtest/gtest.h" + +namespace webrtc { + +namespace test { + +RtpFormatVp8TestHelper::RtpFormatVp8TestHelper(const RTPVideoHeaderVP8* hdr) + : payload_data_(NULL), + buffer_(NULL), + fragmentation_(NULL), + hdr_info_(hdr), + sloppy_partitioning_(false), + inited_(false) {} + +RtpFormatVp8TestHelper::~RtpFormatVp8TestHelper() { + delete fragmentation_; + delete [] payload_data_; + delete [] buffer_; +} + +bool RtpFormatVp8TestHelper::Init(const int* partition_sizes, + int num_partitions) { + if (inited_) return false; + fragmentation_ = new RTPFragmentationHeader; + fragmentation_->VerifyAndAllocateFragmentationHeader(num_partitions); + payload_size_ = 0; + // Calculate sum payload size. + for (int p = 0; p < num_partitions; ++p) { + payload_size_ += partition_sizes[p]; + } + buffer_size_ = payload_size_ + 6; // Add space for payload descriptor. + payload_data_ = new WebRtc_UWord8[payload_size_]; + buffer_ = new WebRtc_UWord8[buffer_size_]; + int j = 0; + // Loop through the partitions again. + for (int p = 0; p < num_partitions; ++p) { + fragmentation_->fragmentationLength[p] = partition_sizes[p]; + fragmentation_->fragmentationOffset[p] = j; + for (int i = 0; i < partition_sizes[p]; ++i) { + assert(j < payload_size_); + payload_data_[j++] = p; // Set the payload value to the partition index. + } + } + data_ptr_ = payload_data_; + inited_ = true; + return true; +} + +void RtpFormatVp8TestHelper::GetAllPacketsAndCheck( + RtpFormatVp8* packetizer, + const int* expected_sizes, + const int* expected_part, + const bool* expected_frag_start, + const int* max_size, + int expected_num_packets) { + ASSERT_TRUE(inited_); + int send_bytes = 0; + bool last; + for (int i = 0; i < expected_num_packets; ++i) { + std::ostringstream ss; + ss << "Checking packet " << i; + SCOPED_TRACE(ss.str()); + EXPECT_EQ(expected_part[i], + packetizer->NextPacket(max_size[i], buffer_, &send_bytes, &last)); + CheckPacket(send_bytes, expected_sizes[i], last, + expected_frag_start[i]); + } +} + +// Payload descriptor +// 0 1 2 3 4 5 6 7 +// +-+-+-+-+-+-+-+-+ +// |X|R|N|S|PartID | (REQUIRED) +// +-+-+-+-+-+-+-+-+ +// X: |I|L|T|K| RSV | (OPTIONAL) +// +-+-+-+-+-+-+-+-+ +// I: | PictureID | (OPTIONAL) +// +-+-+-+-+-+-+-+-+ +// L: | TL0PICIDX | (OPTIONAL) +// +-+-+-+-+-+-+-+-+ +// T/K: | TID | KEYIDX | (OPTIONAL) +// +-+-+-+-+-+-+-+-+ + +// First octet tests. +#define EXPECT_BIT_EQ(x, n, a) EXPECT_EQ((((x) >> (n)) & 0x1), a) + +#define EXPECT_RSV_ZERO(x) EXPECT_EQ(((x) & 0xE0), 0) + +#define EXPECT_BIT_X_EQ(x, a) EXPECT_BIT_EQ(x, 7, a) + +#define EXPECT_BIT_N_EQ(x, a) EXPECT_BIT_EQ(x, 5, a) + +#define EXPECT_BIT_S_EQ(x, a) EXPECT_BIT_EQ(x, 4, a) + +#define EXPECT_PART_ID_EQ(x, a) EXPECT_EQ(((x) & 0x0F), a) + +// Extension fields tests +#define EXPECT_BIT_I_EQ(x, a) EXPECT_BIT_EQ(x, 7, a) + +#define EXPECT_BIT_L_EQ(x, a) EXPECT_BIT_EQ(x, 6, a) + +#define EXPECT_BIT_T_EQ(x, a) EXPECT_BIT_EQ(x, 5, a) + +#define EXPECT_BIT_K_EQ(x, a) EXPECT_BIT_EQ(x, 4, a) + +#define EXPECT_TID_EQ(x, a) EXPECT_EQ((((x) & 0xC0) >> 6), a) + +#define EXPECT_BIT_Y_EQ(x, a) EXPECT_BIT_EQ(x, 5, a) + +#define EXPECT_KEYIDX_EQ(x, a) EXPECT_EQ(((x) & 0x1F), a) + +void RtpFormatVp8TestHelper::CheckHeader(bool frag_start) { + payload_start_ = 1; + EXPECT_BIT_EQ(buffer_[0], 6, 0); // Check reserved bit. + + if (hdr_info_->pictureId != kNoPictureId || + hdr_info_->temporalIdx != kNoTemporalIdx || + hdr_info_->tl0PicIdx != kNoTl0PicIdx || + hdr_info_->keyIdx != kNoKeyIdx) { + EXPECT_BIT_X_EQ(buffer_[0], 1); + ++payload_start_; + CheckPictureID(); + CheckTl0PicIdx(); + CheckTIDAndKeyIdx(); + } else { + EXPECT_BIT_X_EQ(buffer_[0], 0); + } + + EXPECT_BIT_N_EQ(buffer_[0], hdr_info_->nonReference); + EXPECT_BIT_S_EQ(buffer_[0], frag_start); + + // Check partition index. + if (!sloppy_partitioning_) { + // The test payload data is constructed such that the payload value is the + // same as the partition index. + EXPECT_EQ(buffer_[0] & 0x0F, buffer_[payload_start_]); + } else { + // Partition should be set to 0. + EXPECT_EQ(buffer_[0] & 0x0F, 0); + } +} + +// Verify that the I bit and the PictureID field are both set in accordance +// with the information in hdr_info_->pictureId. +void RtpFormatVp8TestHelper::CheckPictureID() { + if (hdr_info_->pictureId != kNoPictureId) { + EXPECT_BIT_I_EQ(buffer_[1], 1); + if (hdr_info_->pictureId > 0x7F) { + EXPECT_BIT_EQ(buffer_[payload_start_], 7, 1); + EXPECT_EQ(buffer_[payload_start_] & 0x7F, + (hdr_info_->pictureId >> 8) & 0x7F); + EXPECT_EQ(buffer_[payload_start_ + 1], + hdr_info_->pictureId & 0xFF); + payload_start_ += 2; + } else { + EXPECT_BIT_EQ(buffer_[payload_start_], 7, 0); + EXPECT_EQ(buffer_[payload_start_] & 0x7F, + (hdr_info_->pictureId) & 0x7F); + payload_start_ += 1; + } + } else { + EXPECT_BIT_I_EQ(buffer_[1], 0); + } +} + +// Verify that the L bit and the TL0PICIDX field are both set in accordance +// with the information in hdr_info_->tl0PicIdx. +void RtpFormatVp8TestHelper::CheckTl0PicIdx() { + if (hdr_info_->tl0PicIdx != kNoTl0PicIdx) { + EXPECT_BIT_L_EQ(buffer_[1], 1); + EXPECT_EQ(buffer_[payload_start_], hdr_info_->tl0PicIdx); + ++payload_start_; + } else { + EXPECT_BIT_L_EQ(buffer_[1], 0); + } +} + +// Verify that the T bit and the TL0PICIDX field, and the K bit and KEYIDX +// field are all set in accordance with the information in +// hdr_info_->temporalIdx and hdr_info_->keyIdx, respectively. +void RtpFormatVp8TestHelper::CheckTIDAndKeyIdx() { + if (hdr_info_->temporalIdx == kNoTemporalIdx && + hdr_info_->keyIdx == kNoKeyIdx) { + EXPECT_BIT_T_EQ(buffer_[1], 0); + EXPECT_BIT_K_EQ(buffer_[1], 0); + return; + } + if (hdr_info_->temporalIdx != kNoTemporalIdx) { + EXPECT_BIT_T_EQ(buffer_[1], 1); + EXPECT_TID_EQ(buffer_[payload_start_], hdr_info_->temporalIdx); + EXPECT_BIT_Y_EQ(buffer_[payload_start_], hdr_info_->layerSync); + } else { + EXPECT_BIT_T_EQ(buffer_[1], 0); + EXPECT_TID_EQ(buffer_[payload_start_], 0); + EXPECT_BIT_Y_EQ(buffer_[payload_start_], false); + } + if (hdr_info_->keyIdx != kNoKeyIdx) { + EXPECT_BIT_K_EQ(buffer_[1], 1); + EXPECT_KEYIDX_EQ(buffer_[payload_start_], hdr_info_->keyIdx); + } else { + EXPECT_BIT_K_EQ(buffer_[1], 0); + EXPECT_KEYIDX_EQ(buffer_[payload_start_], 0); + } + ++payload_start_; +} + +// Verify that the payload (i.e., after the headers) of the packet stored in +// buffer_ is identical to the expected (as found in data_ptr_). +void RtpFormatVp8TestHelper::CheckPayload(int payload_end) { + for (int i = payload_start_; i < payload_end; ++i, ++data_ptr_) + EXPECT_EQ(buffer_[i], *data_ptr_); +} + +// Verify that the input variable "last" agrees with the position of data_ptr_. +// If data_ptr_ has advanced payload_size_ bytes from the start (payload_data_) +// we are at the end and last should be true. Otherwise, it should be false. +void RtpFormatVp8TestHelper::CheckLast(bool last) const { + EXPECT_EQ(last, data_ptr_ == payload_data_ + payload_size_); +} + +// Verify the contents of a packet. Check the length versus expected_bytes, +// the header, payload, and "last" flag. +void RtpFormatVp8TestHelper::CheckPacket(int send_bytes, + int expect_bytes, + bool last, + bool frag_start) { + EXPECT_EQ(send_bytes, expect_bytes); + CheckHeader(frag_start); + CheckPayload(send_bytes); + CheckLast(last); +} + +} // namespace test + +} // namespace webrtc diff --git a/src/modules/rtp_rtcp/source/rtp_format_vp8_test_helper.h b/src/modules/rtp_rtcp/source/rtp_format_vp8_test_helper.h new file mode 100644 index 0000000000..8e8fad1d23 --- /dev/null +++ b/src/modules/rtp_rtcp/source/rtp_format_vp8_test_helper.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2011 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. + */ + +// This file contains the class RtpFormatVp8TestHelper. The class is +// responsible for setting up a fake VP8 bitstream according to the +// RTPVideoHeaderVP8 header, and partition information. After initialization, +// an RTPFragmentationHeader is provided so that the tester can create a +// packetizer. The packetizer can then be provided to this helper class, which +// will then extract all packets and compare to the expected outcome. + +#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_FORMAT_VP8_TEST_HELPER_H_ +#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_FORMAT_VP8_TEST_HELPER_H_ + +#include "modules/interface/module_common_types.h" +#include "modules/rtp_rtcp/source/rtp_format_vp8.h" +#include "system_wrappers/interface/constructor_magic.h" +#include "typedefs.h" + +namespace webrtc { + +namespace test { + +class RtpFormatVp8TestHelper { + public: + explicit RtpFormatVp8TestHelper(const RTPVideoHeaderVP8* hdr); + ~RtpFormatVp8TestHelper(); + bool Init(const int* partition_sizes, int num_partitions); + void GetAllPacketsAndCheck(RtpFormatVp8* packetizer, + const int* expected_sizes, + const int* expected_part, + const bool* expected_frag_start, + const int* max_size, + int expected_num_packets); + + uint8_t* payload_data() const { return payload_data_; } + int payload_size() const { return payload_size_; } + RTPFragmentationHeader* fragmentation() const { return fragmentation_; } + int buffer_size() const { return buffer_size_; } + void set_sloppy_partitioning(bool value) { sloppy_partitioning_ = value; } + + private: + void CheckHeader(bool frag_start); + void CheckPictureID(); + void CheckTl0PicIdx(); + void CheckTIDAndKeyIdx(); + void CheckPayload(int payload_end); + void CheckLast(bool last) const; + void CheckPacket(int send_bytes, int expect_bytes, bool last, + bool frag_start); + + uint8_t* payload_data_; + uint8_t* buffer_; + uint8_t* data_ptr_; + RTPFragmentationHeader* fragmentation_; + const RTPVideoHeaderVP8* hdr_info_; + int payload_start_; + int payload_size_; + int buffer_size_; + bool sloppy_partitioning_; + bool inited_; + + DISALLOW_COPY_AND_ASSIGN(RtpFormatVp8TestHelper); +}; + +} // namespace test + +} // namespace webrtc + +#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_FORMAT_VP8_TEST_HELPER_H_ diff --git a/src/modules/rtp_rtcp/source/rtp_format_vp8_unittest.cc b/src/modules/rtp_rtcp/source/rtp_format_vp8_unittest.cc index b2e0cf17f5..f2c028c5de 100644 --- a/src/modules/rtp_rtcp/source/rtp_format_vp8_unittest.cc +++ b/src/modules/rtp_rtcp/source/rtp_format_vp8_unittest.cc @@ -16,457 +16,286 @@ #include #include "modules/rtp_rtcp/source/rtp_format_vp8.h" -#include "typedefs.h" // NOLINT(build/include) +#include "modules/rtp_rtcp/source/rtp_format_vp8_test_helper.h" +#include "typedefs.h" namespace webrtc { -const int kPayloadSize = 30; -const int kBufferSize = kPayloadSize + 6; // Add space for payload descriptor. +template +struct CompileAssert { +}; + +#undef COMPILE_ASSERT +#define COMPILE_ASSERT(expr, msg) \ + typedef CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1] class RtpFormatVp8Test : public ::testing::Test { protected: - RtpFormatVp8Test() {} - virtual void SetUp(); - virtual void TearDown(); - void CheckHeader(bool first_in_frame, bool frag_start, int part_id); - void CheckPictureID(); - void CheckTl0PicIdx(); - void CheckTIDAndKeyIdx(); - void CheckPayload(int payload_end); - void CheckLast(bool last) const; - void CheckPacket(int send_bytes, int expect_bytes, bool last, - bool first_in_frame, bool frag_start); - void CheckPacketZeroPartId(int send_bytes, int expect_bytes, bool last, - bool first_in_frame, bool frag_start); - WebRtc_UWord8 payload_data_[kPayloadSize]; - WebRtc_UWord8 buffer_[kBufferSize]; - WebRtc_UWord8 *data_ptr_; - RTPFragmentationHeader* fragmentation_; + RtpFormatVp8Test() : helper_(NULL) {} + virtual void TearDown() { delete helper_; } + bool Init() { + const int kSizeVector[] = {10, 10, 10}; + const int kNumPartitions = sizeof(kSizeVector) / sizeof(kSizeVector[0]); + return Init(kSizeVector, kNumPartitions); + } + bool Init(const int* partition_sizes, int num_partitions) { + hdr_info_.pictureId = kNoPictureId; + hdr_info_.nonReference = false; + hdr_info_.temporalIdx = kNoTemporalIdx; + hdr_info_.layerSync = false; + hdr_info_.tl0PicIdx = kNoTl0PicIdx; + hdr_info_.keyIdx = kNoKeyIdx; + if (helper_ != NULL) return false; + helper_ = new test::RtpFormatVp8TestHelper(&hdr_info_); + return helper_->Init(partition_sizes, num_partitions); + } + RTPVideoHeaderVP8 hdr_info_; - int payload_start_; + test::RtpFormatVp8TestHelper* helper_; }; -void RtpFormatVp8Test::SetUp() { - for (int i = 0; i < kPayloadSize; i++) { - payload_data_[i] = i / 10; // Integer division. - } - data_ptr_ = payload_data_; - - fragmentation_ = new RTPFragmentationHeader; - fragmentation_->VerifyAndAllocateFragmentationHeader(3); - fragmentation_->fragmentationLength[0] = 10; - fragmentation_->fragmentationLength[1] = 10; - fragmentation_->fragmentationLength[2] = 10; - fragmentation_->fragmentationOffset[0] = 0; - fragmentation_->fragmentationOffset[1] = 10; - fragmentation_->fragmentationOffset[2] = 20; - - hdr_info_.pictureId = kNoPictureId; - hdr_info_.nonReference = false; - hdr_info_.temporalIdx = kNoTemporalIdx; - hdr_info_.layerSync = false; - hdr_info_.tl0PicIdx = kNoTl0PicIdx; - hdr_info_.keyIdx = kNoKeyIdx; -} - -void RtpFormatVp8Test::TearDown() { - delete fragmentation_; -} - -// First octet tests. -#define EXPECT_BIT_EQ(x, n, a) EXPECT_EQ((((x) >> (n)) & 0x1), a) - -#define EXPECT_RSV_ZERO(x) EXPECT_EQ(((x) & 0xE0), 0) - -#define EXPECT_BIT_X_EQ(x, a) EXPECT_BIT_EQ(x, 7, a) - -#define EXPECT_BIT_N_EQ(x, a) EXPECT_BIT_EQ(x, 5, a) - -#define EXPECT_BIT_S_EQ(x, a) EXPECT_BIT_EQ(x, 4, a) - -#define EXPECT_PART_ID_EQ(x, a) EXPECT_EQ(((x) & 0x0F), a) - -// Extension fields tests -#define EXPECT_BIT_I_EQ(x, a) EXPECT_BIT_EQ(x, 7, a) - -#define EXPECT_BIT_L_EQ(x, a) EXPECT_BIT_EQ(x, 6, a) - -#define EXPECT_BIT_T_EQ(x, a) EXPECT_BIT_EQ(x, 5, a) - -#define EXPECT_BIT_K_EQ(x, a) EXPECT_BIT_EQ(x, 4, a) - -#define EXPECT_TID_EQ(x, a) EXPECT_EQ((((x) & 0xC0) >> 6), a) - -#define EXPECT_BIT_Y_EQ(x, a) EXPECT_BIT_EQ(x, 5, a) - -#define EXPECT_KEYIDX_EQ(x, a) EXPECT_EQ(((x) & 0x1F), a) - -void RtpFormatVp8Test::CheckHeader(bool first_in_frame, bool frag_start, - int part_id) { - payload_start_ = 1; - EXPECT_BIT_EQ(buffer_[0], 6, 0); // Check reserved bit. - - - if (hdr_info_.pictureId != kNoPictureId || - hdr_info_.temporalIdx != kNoTemporalIdx || - hdr_info_.tl0PicIdx != kNoTl0PicIdx || - hdr_info_.keyIdx != kNoKeyIdx) { - EXPECT_BIT_X_EQ(buffer_[0], 1); - ++payload_start_; - CheckPictureID(); - CheckTl0PicIdx(); - CheckTIDAndKeyIdx(); - } else { - EXPECT_BIT_X_EQ(buffer_[0], 0); - } - - EXPECT_BIT_N_EQ(buffer_[0], 0); - EXPECT_BIT_S_EQ(buffer_[0], frag_start); - - // Check partition index. - if (part_id < 0) { - // (Payload data is the same as the partition index.) - EXPECT_EQ(buffer_[0] & 0x0F, buffer_[payload_start_]); - } else { - EXPECT_EQ(buffer_[0] & 0x0F, part_id); - } -} - -void RtpFormatVp8Test::CheckPictureID() { - if (hdr_info_.pictureId != kNoPictureId) { - EXPECT_BIT_I_EQ(buffer_[1], 1); - if (hdr_info_.pictureId > 0x7F) { - EXPECT_BIT_EQ(buffer_[payload_start_], 7, 1); - EXPECT_EQ(buffer_[payload_start_] & 0x7F, - (hdr_info_.pictureId >> 8) & 0x7F); - EXPECT_EQ(buffer_[payload_start_ + 1], - hdr_info_.pictureId & 0xFF); - payload_start_ += 2; - } else { - EXPECT_BIT_EQ(buffer_[payload_start_], 7, 0); - EXPECT_EQ(buffer_[payload_start_] & 0x7F, - (hdr_info_.pictureId) & 0x7F); - payload_start_ += 1; - } - } else { - EXPECT_BIT_I_EQ(buffer_[1], 0); - } -} - -void RtpFormatVp8Test::CheckTl0PicIdx() { - if (hdr_info_.tl0PicIdx != kNoTl0PicIdx) { - EXPECT_BIT_L_EQ(buffer_[1], 1); - EXPECT_EQ(buffer_[payload_start_], hdr_info_.tl0PicIdx); - ++payload_start_; - } else { - EXPECT_BIT_L_EQ(buffer_[1], 0); - } -} - -void RtpFormatVp8Test::CheckTIDAndKeyIdx() { - if (hdr_info_.temporalIdx == kNoTemporalIdx && - hdr_info_.keyIdx == kNoKeyIdx) { - EXPECT_BIT_T_EQ(buffer_[1], 0); - EXPECT_BIT_K_EQ(buffer_[1], 0); - return; - } - if (hdr_info_.temporalIdx != kNoTemporalIdx) { - EXPECT_BIT_T_EQ(buffer_[1], 1); - EXPECT_TID_EQ(buffer_[payload_start_], hdr_info_.temporalIdx); - EXPECT_BIT_Y_EQ(buffer_[payload_start_], hdr_info_.layerSync); - } else { - EXPECT_BIT_T_EQ(buffer_[1], 0); - EXPECT_TID_EQ(buffer_[payload_start_], 0); - EXPECT_BIT_Y_EQ(buffer_[payload_start_], false); - } - if (hdr_info_.keyIdx != kNoKeyIdx) { - EXPECT_BIT_K_EQ(buffer_[1], 1); - EXPECT_KEYIDX_EQ(buffer_[payload_start_], hdr_info_.keyIdx); - } else { - EXPECT_BIT_K_EQ(buffer_[1], 0); - EXPECT_KEYIDX_EQ(buffer_[payload_start_], 0); - } - ++payload_start_; -} - -void RtpFormatVp8Test::CheckPayload(int payload_end) { - for (int i = payload_start_; i < payload_end; i++, data_ptr_++) - EXPECT_EQ(buffer_[i], *data_ptr_); -} - -void RtpFormatVp8Test::CheckLast(bool last) const { - EXPECT_EQ(last, data_ptr_ == payload_data_ + kPayloadSize); -} - -void RtpFormatVp8Test::CheckPacket(int send_bytes, int expect_bytes, bool last, - bool first_in_frame, bool frag_start) { - EXPECT_EQ(send_bytes, expect_bytes); - CheckHeader(first_in_frame, frag_start, -1); - CheckPayload(send_bytes); - CheckLast(last); -} - -void RtpFormatVp8Test::CheckPacketZeroPartId(int send_bytes, - int expect_bytes, - bool last, - bool first_in_frame, - bool frag_start) { - EXPECT_EQ(send_bytes, expect_bytes); - CheckHeader(first_in_frame, frag_start, 0); - CheckPayload(send_bytes); - CheckLast(last); -} - TEST_F(RtpFormatVp8Test, TestStrictMode) { - int send_bytes = 0; - bool last; - bool first_in_frame = true; + ASSERT_TRUE(Init()); hdr_info_.pictureId = 200; // > 0x7F should produce 2-byte PictureID. - RtpFormatVp8 packetizer = RtpFormatVp8(payload_data_, kPayloadSize, - hdr_info_, *fragmentation_, kStrict); + RtpFormatVp8 packetizer = RtpFormatVp8(helper_->payload_data(), + helper_->payload_size(), + hdr_info_, + *(helper_->fragmentation()), + kStrict); - // Get first packet, expect balanced size ~= same as second packet. - EXPECT_EQ(0, packetizer.NextPacket(13, buffer_, &send_bytes, &last)); - CheckPacket(send_bytes, 8, last, - first_in_frame, - /* frag_start */ true); - first_in_frame = false; + // The expected sizes are obtained by running a verified good implementation. + const int kExpectedSizes[] = {8, 10, 14, 5, 5, 7, 5}; + const int kExpectedPart[] = {0, 0, 1, 2, 2, 2, 2}; + const bool kExpectedFragStart[] = + {true, false, true, true, false, false, false}; + const int kMaxSize[] = {13, 13, 20, 7, 7, 7, 7}; + const int kExpectedNum = sizeof(kExpectedSizes) / sizeof(kExpectedSizes[0]); + COMPILE_ASSERT(kExpectedNum == + sizeof(kExpectedPart) / sizeof(kExpectedPart[0]), + kExpectedPart_wrong_size); + COMPILE_ASSERT(kExpectedNum == + sizeof(kExpectedFragStart) / sizeof(kExpectedFragStart[0]), + kExpectedFragStart_wrong_size); + COMPILE_ASSERT(kExpectedNum == sizeof(kMaxSize) / sizeof(kMaxSize[0]), + kMaxSize_wrong_size); - // Get second packet. - EXPECT_EQ(0, packetizer.NextPacket(13, buffer_, &send_bytes, &last)); - CheckPacket(send_bytes, 10, last, - first_in_frame, - /* frag_start */ false); - - // Second partition. - // Get first (and only) packet. - EXPECT_EQ(1, packetizer.NextPacket(20, buffer_, &send_bytes, &last)); - CheckPacket(send_bytes, 14, last, - first_in_frame, - /* frag_start */ true); - - // Third partition. - // Get first packet (of four). - EXPECT_EQ(2, packetizer.NextPacket(7, buffer_, &send_bytes, &last)); - CheckPacket(send_bytes, 5, last, - first_in_frame, - /* frag_start */ true); - - // Get second packet (of four). - EXPECT_EQ(2, packetizer.NextPacket(7, buffer_, &send_bytes, &last)); - CheckPacket(send_bytes, 5, last, - first_in_frame, - /* frag_start */ false); - - // Get third packet (of four). - EXPECT_EQ(2, packetizer.NextPacket(7, buffer_, &send_bytes, &last)); - CheckPacket(send_bytes, 7, last, - first_in_frame, - /* frag_start */ false); - - // Get fourth and last packet. - EXPECT_EQ(2, packetizer.NextPacket(7, buffer_, &send_bytes, &last)); - CheckPacket(send_bytes, 5, last, - first_in_frame, - /* frag_start */ false); + helper_->GetAllPacketsAndCheck(&packetizer, kExpectedSizes, kExpectedPart, + kExpectedFragStart, kMaxSize, kExpectedNum); } TEST_F(RtpFormatVp8Test, TestAggregateMode) { - int send_bytes = 0; - bool last; - bool first_in_frame = true; + ASSERT_TRUE(Init()); hdr_info_.pictureId = 20; // <= 0x7F should produce 1-byte PictureID. - RtpFormatVp8 packetizer = RtpFormatVp8(payload_data_, kPayloadSize, - hdr_info_, *fragmentation_, + RtpFormatVp8 packetizer = RtpFormatVp8(helper_->payload_data(), + helper_->payload_size(), + hdr_info_, + *(helper_->fragmentation()), kAggregate); - // Get first packet. - // First part of first partition (balanced fragments are expected). - EXPECT_EQ(0, packetizer.NextPacket(8, buffer_, &send_bytes, &last)); - CheckPacket(send_bytes, 7, last, - first_in_frame, - /* frag_start */ true); - first_in_frame = false; + // The expected sizes are obtained by running a verified good implementation. + const int kExpectedSizes[] = {7, 5, 7, 23}; + const int kExpectedPart[] = {0, 0, 0, 1}; + const bool kExpectedFragStart[] = {true, false, false, true}; + const int kMaxSize[] = {8, 8, 8, 25}; + const int kExpectedNum = sizeof(kExpectedSizes) / sizeof(kExpectedSizes[0]); + COMPILE_ASSERT(kExpectedNum == + sizeof(kExpectedPart) / sizeof(kExpectedPart[0]), + kExpectedPart_wrong_size); + COMPILE_ASSERT(kExpectedNum == + sizeof(kExpectedFragStart) / sizeof(kExpectedFragStart[0]), + kExpectedFragStart_wrong_size); + COMPILE_ASSERT(kExpectedNum == sizeof(kMaxSize) / sizeof(kMaxSize[0]), + kMaxSize_wrong_size); - // Get second packet. - // Second fragment of first partition. - EXPECT_EQ(0, packetizer.NextPacket(8, buffer_, &send_bytes, &last)); - CheckPacket(send_bytes, 5, last, - first_in_frame, - /* frag_start */ false); - - // Get third packet. - // Third fragment of first partition. - EXPECT_EQ(0, packetizer.NextPacket(8, buffer_, &send_bytes, &last)); - CheckPacket(send_bytes, 7, last, - first_in_frame, - /* frag_start */ false); - - // Get fourth packet. - // Last two partitions aggregated. - EXPECT_EQ(1, packetizer.NextPacket(25, buffer_, &send_bytes, &last)); - CheckPacket(send_bytes, 23, last, - first_in_frame, - /* frag_start */ true); + helper_->GetAllPacketsAndCheck(&packetizer, kExpectedSizes, kExpectedPart, + kExpectedFragStart, kMaxSize, kExpectedNum); } TEST_F(RtpFormatVp8Test, TestSloppyMode) { - int send_bytes = 0; - bool last; - bool first_in_frame = true; + ASSERT_TRUE(Init()); hdr_info_.pictureId = kNoPictureId; // No PictureID. - RtpFormatVp8 packetizer = RtpFormatVp8(payload_data_, kPayloadSize, - hdr_info_, *fragmentation_, kSloppy); + RtpFormatVp8 packetizer = RtpFormatVp8(helper_->payload_data(), + helper_->payload_size(), + hdr_info_, + *(helper_->fragmentation()), + kSloppy); - // Get first packet. - EXPECT_EQ(0, packetizer.NextPacket(9, buffer_, &send_bytes, &last)); - CheckPacket(send_bytes, 9, last, - first_in_frame, - /* frag_start */ true); - first_in_frame = false; + // The expected sizes are obtained by running a verified good implementation. + const int kExpectedSizes[] = {9, 9, 9, 7}; + const int kExpectedPart[] = {0, 0, 1, 2}; + const bool kExpectedFragStart[] = {true, false, false, false}; + const int kMaxSize[] = {9, 9, 9, 9}; + const int kExpectedNum = sizeof(kExpectedSizes) / sizeof(kExpectedSizes[0]); + COMPILE_ASSERT(kExpectedNum == + sizeof(kExpectedPart) / sizeof(kExpectedPart[0]), + kExpectedPart_wrong_size); + COMPILE_ASSERT(kExpectedNum == + sizeof(kExpectedFragStart) / sizeof(kExpectedFragStart[0]), + kExpectedFragStart_wrong_size); + COMPILE_ASSERT(kExpectedNum == sizeof(kMaxSize) / sizeof(kMaxSize[0]), + kMaxSize_wrong_size); - // Get second packet. - // Fragments of first and second partitions. - EXPECT_EQ(0, packetizer.NextPacket(9, buffer_, &send_bytes, &last)); - CheckPacket(send_bytes, 9, last, - first_in_frame, - /* frag_start */ false); - - // Get third packet. - // Fragments of second and third partitions. - EXPECT_EQ(1, packetizer.NextPacket(9, buffer_, &send_bytes, &last)); - CheckPacket(send_bytes, 9, last, - first_in_frame, - /* frag_start */ false); - - // Get fourth packet. - // Second half of last partition. - EXPECT_EQ(2, packetizer.NextPacket(9, buffer_, &send_bytes, &last)); - CheckPacket(send_bytes, 7, last, - first_in_frame, - /* frag_start */ false); + helper_->GetAllPacketsAndCheck(&packetizer, kExpectedSizes, kExpectedPart, + kExpectedFragStart, kMaxSize, kExpectedNum); } // Verify that sloppy mode is forced if fragmentation info is missing. TEST_F(RtpFormatVp8Test, TestSloppyModeFallback) { - int send_bytes = 0; - bool last; - bool first_in_frame = true; + ASSERT_TRUE(Init()); hdr_info_.pictureId = 200; // > 0x7F should produce 2-byte PictureID - RtpFormatVp8 packetizer = RtpFormatVp8(payload_data_, kPayloadSize, + RtpFormatVp8 packetizer = RtpFormatVp8(helper_->payload_data(), + helper_->payload_size(), hdr_info_); - // Get first packet. - EXPECT_EQ(0, packetizer.NextPacket(10, buffer_, &send_bytes, &last)); - CheckPacketZeroPartId(send_bytes, 10, last, - first_in_frame, - /* frag_start */ true); - first_in_frame = false; + // Expecting three full packets, and one with the remainder. + const int kExpectedSizes[] = {10, 10, 10, 7}; + const int kExpectedPart[] = {0, 0, 0, 0}; // Always 0 for sloppy mode. + // Frag start only true for first packet in sloppy mode. + const bool kExpectedFragStart[] = {true, false, false, false}; + const int kMaxSize[] = {10, 10, 10, 7}; // Small enough to produce 4 packets. + const int kExpectedNum = sizeof(kExpectedSizes) / sizeof(kExpectedSizes[0]); + COMPILE_ASSERT(kExpectedNum == + sizeof(kExpectedPart) / sizeof(kExpectedPart[0]), + kExpectedPart_wrong_size); + COMPILE_ASSERT(kExpectedNum == + sizeof(kExpectedFragStart) / sizeof(kExpectedFragStart[0]), + kExpectedFragStart_wrong_size); + COMPILE_ASSERT(kExpectedNum == sizeof(kMaxSize) / sizeof(kMaxSize[0]), + kMaxSize_wrong_size); - // Get second packet. - // Fragments of first and second partitions. - EXPECT_EQ(0, packetizer.NextPacket(10, buffer_, &send_bytes, &last)); - CheckPacketZeroPartId(send_bytes, 10, last, - first_in_frame, - /* frag_start */ false); - - // Get third packet. - // Fragments of second and third partitions. - EXPECT_EQ(0, packetizer.NextPacket(10, buffer_, &send_bytes, &last)); - CheckPacketZeroPartId(send_bytes, 10, last, - first_in_frame, - /* frag_start */ false); - - // Get fourth packet. - // Second half of last partition. - EXPECT_EQ(0, packetizer.NextPacket(7, buffer_, &send_bytes, &last)); - CheckPacketZeroPartId(send_bytes, 7, last, - first_in_frame, - /* frag_start */ false); + helper_->set_sloppy_partitioning(true); + helper_->GetAllPacketsAndCheck(&packetizer, kExpectedSizes, kExpectedPart, + kExpectedFragStart, kMaxSize, kExpectedNum); } -// Verify that non-reference bit is set. +// Verify that non-reference bit is set. Sloppy mode fallback is expected. TEST_F(RtpFormatVp8Test, TestNonReferenceBit) { - int send_bytes = 0; - bool last; + ASSERT_TRUE(Init()); hdr_info_.nonReference = true; - RtpFormatVp8 packetizer = RtpFormatVp8(payload_data_, kPayloadSize, + RtpFormatVp8 packetizer = RtpFormatVp8(helper_->payload_data(), + helper_->payload_size(), hdr_info_); - // Get first packet. - ASSERT_EQ(0, packetizer.NextPacket(25, buffer_, &send_bytes, &last)); - ASSERT_FALSE(last); - EXPECT_BIT_N_EQ(buffer_[0], 1); + // Sloppy mode => First packet full; other not. + const int kExpectedSizes[] = {25, 7}; + const int kExpectedPart[] = {0, 0}; // Always 0 for sloppy mode. + // Frag start only true for first packet in sloppy mode. + const bool kExpectedFragStart[] = {true, false}; + const int kMaxSize[] = {25, 25}; // Small enough to produce two packets. + const int kExpectedNum = sizeof(kExpectedSizes) / sizeof(kExpectedSizes[0]); + COMPILE_ASSERT(kExpectedNum == + sizeof(kExpectedPart) / sizeof(kExpectedPart[0]), + kExpectedPart_wrong_size); + COMPILE_ASSERT(kExpectedNum == + sizeof(kExpectedFragStart) / sizeof(kExpectedFragStart[0]), + kExpectedFragStart_wrong_size); + COMPILE_ASSERT(kExpectedNum == sizeof(kMaxSize) / sizeof(kMaxSize[0]), + kMaxSize_wrong_size); - // Get second packet. - ASSERT_EQ(0, packetizer.NextPacket(25, buffer_, &send_bytes, &last)); - ASSERT_TRUE(last); - EXPECT_BIT_N_EQ(buffer_[0], 1); + helper_->set_sloppy_partitioning(true); + helper_->GetAllPacketsAndCheck(&packetizer, kExpectedSizes, kExpectedPart, + kExpectedFragStart, kMaxSize, kExpectedNum); } // Verify Tl0PicIdx and TID fields, and layerSync bit. TEST_F(RtpFormatVp8Test, TestTl0PicIdxAndTID) { - int send_bytes = 0; - bool last; + ASSERT_TRUE(Init()); hdr_info_.tl0PicIdx = 117; hdr_info_.temporalIdx = 2; hdr_info_.layerSync = true; - RtpFormatVp8 packetizer = RtpFormatVp8(payload_data_, kPayloadSize, - hdr_info_, *fragmentation_, + RtpFormatVp8 packetizer = RtpFormatVp8(helper_->payload_data(), + helper_->payload_size(), + hdr_info_, + *(helper_->fragmentation()), kAggregate); - // Get first and only packet. - EXPECT_EQ(0, packetizer.NextPacket(kBufferSize, buffer_, &send_bytes, - &last)); - bool first_in_frame = true; - CheckPacket(send_bytes, kPayloadSize + 4, last, - first_in_frame, - /* frag_start */ true); + // Expect one single packet of payload_size() + 4 bytes header. + const int kExpectedSizes[1] = {helper_->payload_size() + 4}; + const int kExpectedPart[1] = {0}; // Packet starts with partition 0. + const bool kExpectedFragStart[1] = {true}; + // kMaxSize is only limited by allocated buffer size. + const int kMaxSize[1] = {helper_->buffer_size()}; + const int kExpectedNum = sizeof(kExpectedSizes) / sizeof(kExpectedSizes[0]); + COMPILE_ASSERT(kExpectedNum == + sizeof(kExpectedPart) / sizeof(kExpectedPart[0]), + kExpectedPart_wrong_size); + COMPILE_ASSERT(kExpectedNum == + sizeof(kExpectedFragStart) / sizeof(kExpectedFragStart[0]), + kExpectedFragStart_wrong_size); + COMPILE_ASSERT(kExpectedNum == sizeof(kMaxSize) / sizeof(kMaxSize[0]), + kMaxSize_wrong_size); + + helper_->GetAllPacketsAndCheck(&packetizer, kExpectedSizes, kExpectedPart, + kExpectedFragStart, kMaxSize, kExpectedNum); } // Verify KeyIdx field. TEST_F(RtpFormatVp8Test, TestKeyIdx) { - int send_bytes = 0; - bool last; + ASSERT_TRUE(Init()); hdr_info_.keyIdx = 17; - RtpFormatVp8 packetizer = RtpFormatVp8(payload_data_, kPayloadSize, - hdr_info_, *fragmentation_, + RtpFormatVp8 packetizer = RtpFormatVp8(helper_->payload_data(), + helper_->payload_size(), + hdr_info_, + *(helper_->fragmentation()), kAggregate); - // Get first and only packet. - EXPECT_EQ(0, packetizer.NextPacket(kBufferSize, buffer_, &send_bytes, - &last)); - bool first_in_frame = true; - CheckPacket(send_bytes, kPayloadSize + 3, last, - first_in_frame, - /* frag_start */ true); + // Expect one single packet of payload_size() + 3 bytes header. + const int kExpectedSizes[1] = {helper_->payload_size() + 3}; + const int kExpectedPart[1] = {0}; // Packet starts with partition 0. + const bool kExpectedFragStart[1] = {true}; + // kMaxSize is only limited by allocated buffer size. + const int kMaxSize[1] = {helper_->buffer_size()}; + const int kExpectedNum = sizeof(kExpectedSizes) / sizeof(kExpectedSizes[0]); + COMPILE_ASSERT(kExpectedNum == + sizeof(kExpectedPart) / sizeof(kExpectedPart[0]), + kExpectedPart_wrong_size); + COMPILE_ASSERT(kExpectedNum == + sizeof(kExpectedFragStart) / sizeof(kExpectedFragStart[0]), + kExpectedFragStart_wrong_size); + COMPILE_ASSERT(kExpectedNum == sizeof(kMaxSize) / sizeof(kMaxSize[0]), + kMaxSize_wrong_size); + + helper_->GetAllPacketsAndCheck(&packetizer, kExpectedSizes, kExpectedPart, + kExpectedFragStart, kMaxSize, kExpectedNum); } // Verify TID field and KeyIdx field in combination. TEST_F(RtpFormatVp8Test, TestTIDAndKeyIdx) { - int send_bytes = 0; - bool last; + ASSERT_TRUE(Init()); hdr_info_.temporalIdx = 1; hdr_info_.keyIdx = 5; - RtpFormatVp8 packetizer = RtpFormatVp8(payload_data_, kPayloadSize, - hdr_info_, *fragmentation_, + RtpFormatVp8 packetizer = RtpFormatVp8(helper_->payload_data(), + helper_->payload_size(), + hdr_info_, + *(helper_->fragmentation()), kAggregate); - // Get first and only packet. - EXPECT_EQ(0, packetizer.NextPacket(kBufferSize, buffer_, &send_bytes, - &last)); - bool first_in_frame = true; - CheckPacket(send_bytes, kPayloadSize + 3, last, - first_in_frame, - /* frag_start */ true); + // Expect one single packet of payload_size() + 3 bytes header. + const int kExpectedSizes[1] = {helper_->payload_size() + 3}; + const int kExpectedPart[1] = {0}; // Packet starts with partition 0. + const bool kExpectedFragStart[1] = {true}; + // kMaxSize is only limited by allocated buffer size. + const int kMaxSize[1] = {helper_->buffer_size()}; + const int kExpectedNum = sizeof(kExpectedSizes) / sizeof(kExpectedSizes[0]); + COMPILE_ASSERT(kExpectedNum == + sizeof(kExpectedPart) / sizeof(kExpectedPart[0]), + kExpectedPart_wrong_size); + COMPILE_ASSERT(kExpectedNum == + sizeof(kExpectedFragStart) / sizeof(kExpectedFragStart[0]), + kExpectedFragStart_wrong_size); + COMPILE_ASSERT(kExpectedNum == sizeof(kMaxSize) / sizeof(kMaxSize[0]), + kMaxSize_wrong_size); + + helper_->GetAllPacketsAndCheck(&packetizer, kExpectedSizes, kExpectedPart, + kExpectedFragStart, kMaxSize, kExpectedNum); } } // namespace diff --git a/src/modules/rtp_rtcp/source/rtp_rtcp_tests.gypi b/src/modules/rtp_rtcp/source/rtp_rtcp_tests.gypi index ec11396476..8619f6cf4c 100644 --- a/src/modules/rtp_rtcp/source/rtp_rtcp_tests.gypi +++ b/src/modules/rtp_rtcp/source/rtp_rtcp_tests.gypi @@ -22,6 +22,8 @@ ], 'sources': [ 'rtp_format_vp8_unittest.cc', + 'rtp_format_vp8_test_helper.cc', + 'rtp_format_vp8_test_helper.h', 'rtcp_format_remb_unittest.cc', 'rtp_utility_test.cc', 'rtp_header_extension_test.cc',