
Also refactor TransportFeedback to use this. BUG= Review URL: https://codereview.webrtc.org/1307663004 Cr-Commit-Position: refs/heads/master@{#9935}
162 lines
5.1 KiB
C++
162 lines
5.1 KiB
C++
/*
|
|
* Copyright (c) 2014 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 "testing/gtest/include/gtest/gtest.h"
|
|
|
|
#include "webrtc/base/checks.h"
|
|
#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
|
|
#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
|
|
|
|
namespace webrtc {
|
|
|
|
using RTCPUtility::RtcpCommonHeader;
|
|
|
|
namespace rtcp {
|
|
|
|
TEST(RtcpUtilityTest, MidNtp) {
|
|
const uint32_t kNtpSec = 0x12345678;
|
|
const uint32_t kNtpFrac = 0x23456789;
|
|
const uint32_t kNtpMid = 0x56782345;
|
|
EXPECT_EQ(kNtpMid, RTCPUtility::MidNtp(kNtpSec, kNtpFrac));
|
|
}
|
|
|
|
TEST(RtcpUtilityTest, NackRequests) {
|
|
RTCPUtility::NackStats stats;
|
|
EXPECT_EQ(0U, stats.unique_requests());
|
|
EXPECT_EQ(0U, stats.requests());
|
|
stats.ReportRequest(10);
|
|
EXPECT_EQ(1U, stats.unique_requests());
|
|
EXPECT_EQ(1U, stats.requests());
|
|
|
|
stats.ReportRequest(10);
|
|
EXPECT_EQ(1U, stats.unique_requests());
|
|
stats.ReportRequest(11);
|
|
EXPECT_EQ(2U, stats.unique_requests());
|
|
|
|
stats.ReportRequest(11);
|
|
EXPECT_EQ(2U, stats.unique_requests());
|
|
stats.ReportRequest(13);
|
|
EXPECT_EQ(3U, stats.unique_requests());
|
|
|
|
stats.ReportRequest(11);
|
|
EXPECT_EQ(3U, stats.unique_requests());
|
|
EXPECT_EQ(6U, stats.requests());
|
|
}
|
|
|
|
TEST(RtcpUtilityTest, NackRequestsWithWrap) {
|
|
RTCPUtility::NackStats stats;
|
|
stats.ReportRequest(65534);
|
|
EXPECT_EQ(1U, stats.unique_requests());
|
|
|
|
stats.ReportRequest(65534);
|
|
EXPECT_EQ(1U, stats.unique_requests());
|
|
stats.ReportRequest(65535);
|
|
EXPECT_EQ(2U, stats.unique_requests());
|
|
|
|
stats.ReportRequest(65535);
|
|
EXPECT_EQ(2U, stats.unique_requests());
|
|
stats.ReportRequest(0);
|
|
EXPECT_EQ(3U, stats.unique_requests());
|
|
|
|
stats.ReportRequest(65535);
|
|
EXPECT_EQ(3U, stats.unique_requests());
|
|
stats.ReportRequest(0);
|
|
EXPECT_EQ(3U, stats.unique_requests());
|
|
stats.ReportRequest(1);
|
|
EXPECT_EQ(4U, stats.unique_requests());
|
|
EXPECT_EQ(8U, stats.requests());
|
|
}
|
|
|
|
class RtcpParseCommonHeaderTest : public ::testing::Test {
|
|
public:
|
|
RtcpParseCommonHeaderTest() { memset(buffer, 0, kBufferCapacityBytes); }
|
|
virtual ~RtcpParseCommonHeaderTest() {}
|
|
|
|
protected:
|
|
static const size_t kBufferCapacityBytes = 40;
|
|
uint8_t buffer[kBufferCapacityBytes];
|
|
RtcpCommonHeader header;
|
|
};
|
|
|
|
TEST_F(RtcpParseCommonHeaderTest, TooSmallBuffer) {
|
|
// Buffer needs to be able to hold the header.
|
|
for (size_t i = 0; i < RtcpCommonHeader::kHeaderSizeBytes; ++i)
|
|
EXPECT_FALSE(RtcpParseCommonHeader(buffer, i, &header));
|
|
}
|
|
|
|
TEST_F(RtcpParseCommonHeaderTest, Version) {
|
|
// Version 2 is the only allowed for now.
|
|
for (int v = 0; v < 4; ++v) {
|
|
buffer[0] = v << 6;
|
|
EXPECT_EQ(v == 2, RtcpParseCommonHeader(
|
|
buffer, RtcpCommonHeader::kHeaderSizeBytes, &header));
|
|
}
|
|
}
|
|
|
|
TEST_F(RtcpParseCommonHeaderTest, PacketSize) {
|
|
// Set v = 2, leave p, fmt, pt as 0.
|
|
buffer[0] = 2 << 6;
|
|
|
|
const size_t kBlockSize = 3;
|
|
ByteWriter<uint16_t>::WriteBigEndian(&buffer[2], kBlockSize);
|
|
const size_t kSizeInBytes = (kBlockSize + 1) * 4;
|
|
|
|
EXPECT_FALSE(RtcpParseCommonHeader(buffer, kSizeInBytes - 1, &header));
|
|
EXPECT_TRUE(RtcpParseCommonHeader(buffer, kSizeInBytes, &header));
|
|
}
|
|
|
|
TEST_F(RtcpParseCommonHeaderTest, PayloadSize) {
|
|
// Set v = 2, p = 1, but leave fmt, pt as 0.
|
|
buffer[0] = (2 << 6) | (1 << 5);
|
|
|
|
// Padding bit set, but no byte for padding (can't specify padding length).
|
|
EXPECT_FALSE(RtcpParseCommonHeader(buffer, 4, &header));
|
|
|
|
const size_t kBlockSize = 3;
|
|
ByteWriter<uint16_t>::WriteBigEndian(&buffer[2], kBlockSize);
|
|
const size_t kSizeInBytes = (kBlockSize + 1) * 4;
|
|
const size_t kPayloadSizeBytes =
|
|
kSizeInBytes - RtcpCommonHeader::kHeaderSizeBytes;
|
|
|
|
// Padding one byte larger than possible.
|
|
buffer[kSizeInBytes - 1] = kPayloadSizeBytes + 1;
|
|
EXPECT_FALSE(RtcpParseCommonHeader(buffer, kSizeInBytes, &header));
|
|
|
|
// Pure padding packet?
|
|
buffer[kSizeInBytes - 1] = kPayloadSizeBytes;
|
|
EXPECT_TRUE(RtcpParseCommonHeader(buffer, kSizeInBytes, &header));
|
|
EXPECT_EQ(kPayloadSizeBytes, header.padding_bytes);
|
|
EXPECT_EQ(0u, header.payload_size_bytes);
|
|
|
|
// Single byte of actual data.
|
|
buffer[kSizeInBytes - 1] = kPayloadSizeBytes - 1;
|
|
EXPECT_TRUE(RtcpParseCommonHeader(buffer, kSizeInBytes, &header));
|
|
EXPECT_EQ(kPayloadSizeBytes - 1, header.padding_bytes);
|
|
EXPECT_EQ(1u, header.payload_size_bytes);
|
|
}
|
|
|
|
TEST_F(RtcpParseCommonHeaderTest, FormatAndPayloadType) {
|
|
// Format/count and packet type both set to max values.
|
|
const uint8_t kCountOrFormat = 0x1F;
|
|
const uint8_t kPacketType = 0xFF;
|
|
buffer[0] = 2 << 6; // V = 2.
|
|
buffer[0] |= kCountOrFormat;
|
|
buffer[1] = kPacketType;
|
|
|
|
EXPECT_TRUE(RtcpParseCommonHeader(buffer, RtcpCommonHeader::kHeaderSizeBytes,
|
|
&header));
|
|
EXPECT_EQ(kCountOrFormat, header.count_or_format);
|
|
EXPECT_EQ(kPacketType, header.packet_type);
|
|
}
|
|
|
|
} // namespace rtcp
|
|
} // namespace webrtc
|
|
|