Refactoring RtpFormatVp8Test

This is the first change in a series of changes to get new functionality
into the VP8 packetizer.

This first refactors the RtpFormatVp8Test class, without changing the
operation of the tested RtpFormatVp8 class. A test helper class
RtpFormatVp8TestHelper is introduced to reduce code duplication.

Review URL: http://webrtc-codereview.appspot.com/304009

git-svn-id: http://webrtc.googlecode.com/svn/trunk@1258 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
henrik.lundin@webrtc.org 2011-12-21 08:51:36 +00:00
parent b2c115c460
commit 00e730730e
4 changed files with 533 additions and 378 deletions

View File

@ -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

View File

@ -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_

View File

@ -16,457 +16,286 @@
#include <gtest/gtest.h>
#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 <bool>
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

View File

@ -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',