| /* |
| * Copyright (c) 2012 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 "webrtc/modules/rtp_rtcp/source/rtp_format_vp8_test_helper.h" |
| |
| #include "webrtc/test/gtest.h" |
| |
| namespace webrtc { |
| |
| namespace test { |
| |
| constexpr RtpPacketToSend::ExtensionManager* kNoExtensions = nullptr; |
| |
| RtpFormatVp8TestHelper::RtpFormatVp8TestHelper(const RTPVideoHeaderVP8* hdr) |
| : packet_(kNoExtensions), |
| payload_data_(NULL), |
| data_ptr_(NULL), |
| fragmentation_(NULL), |
| hdr_info_(hdr), |
| payload_start_(0), |
| payload_size_(0), |
| sloppy_partitioning_(false), |
| inited_(false) {} |
| |
| RtpFormatVp8TestHelper::~RtpFormatVp8TestHelper() { |
| delete fragmentation_; |
| delete [] payload_data_; |
| } |
| |
| bool RtpFormatVp8TestHelper::Init(const size_t* partition_sizes, |
| size_t num_partitions) { |
| if (inited_) return false; |
| fragmentation_ = new RTPFragmentationHeader; |
| fragmentation_->VerifyAndAllocateFragmentationHeader(num_partitions); |
| payload_size_ = 0; |
| // Calculate sum payload size. |
| for (size_t p = 0; p < num_partitions; ++p) { |
| payload_size_ += partition_sizes[p]; |
| } |
| payload_data_ = new uint8_t[payload_size_]; |
| size_t j = 0; |
| // Loop through the partitions again. |
| for (size_t p = 0; p < num_partitions; ++p) { |
| fragmentation_->fragmentationLength[p] = partition_sizes[p]; |
| fragmentation_->fragmentationOffset[p] = j; |
| for (size_t 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( |
| RtpPacketizerVp8* packetizer, |
| const size_t* expected_sizes, |
| const int* expected_part, |
| const bool* expected_frag_start, |
| size_t expected_num_packets) { |
| ASSERT_TRUE(inited_); |
| for (size_t i = 0; i < expected_num_packets; ++i) { |
| std::ostringstream ss; |
| ss << "Checking packet " << i; |
| SCOPED_TRACE(ss.str()); |
| EXPECT_TRUE(packetizer->NextPacket(&packet_)); |
| CheckPacket(expected_sizes[i], i + 1 == expected_num_packets, |
| 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; |
| rtc::ArrayView<const uint8_t> buffer = packet_.payload(); |
| 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 ? 1 : 0); |
| EXPECT_BIT_S_EQ(buffer[0], frag_start ? 1 : 0); |
| |
| // 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() { |
| auto buffer = packet_.payload(); |
| if (hdr_info_->pictureId != kNoPictureId) { |
| EXPECT_BIT_I_EQ(buffer[1], 1); |
| 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_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() { |
| auto buffer = packet_.payload(); |
| 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() { |
| auto buffer = packet_.payload(); |
| 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 ? 1 : 0); |
| } else { |
| EXPECT_BIT_T_EQ(buffer[1], 0); |
| EXPECT_TID_EQ(buffer[payload_start_], 0); |
| EXPECT_BIT_Y_EQ(buffer[payload_start_], 0); |
| } |
| 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() { |
| auto buffer = packet_.payload(); |
| size_t payload_end = buffer.size(); |
| for (size_t 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(size_t expect_bytes, |
| bool last, |
| bool frag_start) { |
| EXPECT_EQ(expect_bytes, packet_.payload_size()); |
| CheckHeader(frag_start); |
| CheckPayload(); |
| CheckLast(last); |
| } |
| |
| } // namespace test |
| |
| } // namespace webrtc |