2011-12-16 14:31:37 +00:00
|
|
|
/*
|
2012-02-16 02:18:09 +00:00
|
|
|
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
2011-12-16 14:31:37 +00:00
|
|
|
*
|
|
|
|
|
* 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 includes unit tests for the RTCPSender.
|
|
|
|
|
*/
|
|
|
|
|
|
2013-05-29 14:27:38 +00:00
|
|
|
#include "testing/gmock/include/gmock/gmock.h"
|
|
|
|
|
#include "testing/gtest/include/gtest/gtest.h"
|
2011-12-16 14:31:37 +00:00
|
|
|
|
2013-05-29 12:12:51 +00:00
|
|
|
#include "webrtc/common_types.h"
|
|
|
|
|
#include "webrtc/modules/rtp_rtcp/source/rtcp_sender.h"
|
2016-02-18 08:33:26 -08:00
|
|
|
#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
|
2013-07-10 15:40:42 +00:00
|
|
|
#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
|
2016-02-18 08:33:26 -08:00
|
|
|
#include "webrtc/test/mock_transport.h"
|
2015-08-21 00:02:47 -07:00
|
|
|
#include "webrtc/test/rtcp_packet_parser.h"
|
|
|
|
|
|
2016-02-18 08:33:26 -08:00
|
|
|
using ::testing::_;
|
2015-08-21 00:02:47 -07:00
|
|
|
using ::testing::ElementsAre;
|
2016-02-18 08:33:26 -08:00
|
|
|
using ::testing::Invoke;
|
|
|
|
|
using webrtc::RTCPUtility::RtcpCommonHeader;
|
2011-12-16 14:31:37 +00:00
|
|
|
|
|
|
|
|
namespace webrtc {
|
|
|
|
|
|
2013-04-04 19:43:34 +00:00
|
|
|
TEST(NACKStringBuilderTest, TestCase1) {
|
|
|
|
|
NACKStringBuilder builder;
|
|
|
|
|
builder.PushNACK(5);
|
|
|
|
|
builder.PushNACK(7);
|
|
|
|
|
builder.PushNACK(9);
|
|
|
|
|
builder.PushNACK(10);
|
|
|
|
|
builder.PushNACK(11);
|
|
|
|
|
builder.PushNACK(12);
|
|
|
|
|
builder.PushNACK(15);
|
|
|
|
|
builder.PushNACK(18);
|
|
|
|
|
builder.PushNACK(19);
|
|
|
|
|
EXPECT_EQ(std::string("5,7,9-12,15,18-19"), builder.GetResult());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST(NACKStringBuilderTest, TestCase2) {
|
|
|
|
|
NACKStringBuilder builder;
|
|
|
|
|
builder.PushNACK(5);
|
|
|
|
|
builder.PushNACK(6);
|
|
|
|
|
builder.PushNACK(7);
|
|
|
|
|
builder.PushNACK(9);
|
|
|
|
|
builder.PushNACK(10);
|
|
|
|
|
builder.PushNACK(11);
|
|
|
|
|
builder.PushNACK(12);
|
|
|
|
|
builder.PushNACK(15);
|
|
|
|
|
builder.PushNACK(18);
|
|
|
|
|
builder.PushNACK(19);
|
|
|
|
|
EXPECT_EQ(std::string("5-7,9-12,15,18-19"), builder.GetResult());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST(NACKStringBuilderTest, TestCase3) {
|
|
|
|
|
NACKStringBuilder builder;
|
|
|
|
|
builder.PushNACK(5);
|
|
|
|
|
builder.PushNACK(7);
|
|
|
|
|
builder.PushNACK(9);
|
|
|
|
|
builder.PushNACK(10);
|
|
|
|
|
builder.PushNACK(11);
|
|
|
|
|
builder.PushNACK(12);
|
|
|
|
|
builder.PushNACK(15);
|
|
|
|
|
builder.PushNACK(18);
|
|
|
|
|
builder.PushNACK(19);
|
|
|
|
|
builder.PushNACK(21);
|
|
|
|
|
EXPECT_EQ(std::string("5,7,9-12,15,18-19,21"), builder.GetResult());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST(NACKStringBuilderTest, TestCase4) {
|
|
|
|
|
NACKStringBuilder builder;
|
|
|
|
|
builder.PushNACK(5);
|
|
|
|
|
builder.PushNACK(7);
|
|
|
|
|
builder.PushNACK(8);
|
|
|
|
|
builder.PushNACK(9);
|
|
|
|
|
builder.PushNACK(10);
|
|
|
|
|
builder.PushNACK(11);
|
|
|
|
|
builder.PushNACK(12);
|
|
|
|
|
builder.PushNACK(15);
|
|
|
|
|
builder.PushNACK(18);
|
|
|
|
|
builder.PushNACK(19);
|
|
|
|
|
EXPECT_EQ(std::string("5,7-12,15,18-19"), builder.GetResult());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST(NACKStringBuilderTest, TestCase5) {
|
|
|
|
|
NACKStringBuilder builder;
|
|
|
|
|
builder.PushNACK(5);
|
|
|
|
|
builder.PushNACK(7);
|
|
|
|
|
builder.PushNACK(9);
|
|
|
|
|
builder.PushNACK(10);
|
|
|
|
|
builder.PushNACK(11);
|
|
|
|
|
builder.PushNACK(12);
|
|
|
|
|
builder.PushNACK(15);
|
|
|
|
|
builder.PushNACK(16);
|
|
|
|
|
builder.PushNACK(18);
|
|
|
|
|
builder.PushNACK(19);
|
|
|
|
|
EXPECT_EQ(std::string("5,7,9-12,15-16,18-19"), builder.GetResult());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST(NACKStringBuilderTest, TestCase6) {
|
|
|
|
|
NACKStringBuilder builder;
|
|
|
|
|
builder.PushNACK(5);
|
|
|
|
|
builder.PushNACK(7);
|
|
|
|
|
builder.PushNACK(9);
|
|
|
|
|
builder.PushNACK(10);
|
|
|
|
|
builder.PushNACK(11);
|
|
|
|
|
builder.PushNACK(12);
|
|
|
|
|
builder.PushNACK(15);
|
|
|
|
|
builder.PushNACK(16);
|
|
|
|
|
builder.PushNACK(17);
|
|
|
|
|
builder.PushNACK(18);
|
|
|
|
|
builder.PushNACK(19);
|
|
|
|
|
EXPECT_EQ(std::string("5,7,9-12,15-19"), builder.GetResult());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST(NACKStringBuilderTest, TestCase7) {
|
|
|
|
|
NACKStringBuilder builder;
|
|
|
|
|
builder.PushNACK(5);
|
|
|
|
|
builder.PushNACK(6);
|
|
|
|
|
builder.PushNACK(7);
|
|
|
|
|
builder.PushNACK(8);
|
|
|
|
|
builder.PushNACK(11);
|
|
|
|
|
builder.PushNACK(12);
|
|
|
|
|
builder.PushNACK(13);
|
|
|
|
|
builder.PushNACK(14);
|
|
|
|
|
builder.PushNACK(15);
|
|
|
|
|
EXPECT_EQ(std::string("5-8,11-15"), builder.GetResult());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST(NACKStringBuilderTest, TestCase8) {
|
|
|
|
|
NACKStringBuilder builder;
|
|
|
|
|
builder.PushNACK(5);
|
|
|
|
|
builder.PushNACK(7);
|
|
|
|
|
builder.PushNACK(9);
|
|
|
|
|
builder.PushNACK(11);
|
|
|
|
|
builder.PushNACK(15);
|
|
|
|
|
builder.PushNACK(17);
|
|
|
|
|
builder.PushNACK(19);
|
|
|
|
|
EXPECT_EQ(std::string("5,7,9,11,15,17,19"), builder.GetResult());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST(NACKStringBuilderTest, TestCase9) {
|
|
|
|
|
NACKStringBuilder builder;
|
|
|
|
|
builder.PushNACK(5);
|
|
|
|
|
builder.PushNACK(6);
|
|
|
|
|
builder.PushNACK(7);
|
|
|
|
|
builder.PushNACK(8);
|
|
|
|
|
builder.PushNACK(9);
|
|
|
|
|
builder.PushNACK(10);
|
|
|
|
|
builder.PushNACK(11);
|
|
|
|
|
builder.PushNACK(12);
|
|
|
|
|
EXPECT_EQ(std::string("5-12"), builder.GetResult());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST(NACKStringBuilderTest, TestCase10) {
|
|
|
|
|
NACKStringBuilder builder;
|
|
|
|
|
builder.PushNACK(5);
|
|
|
|
|
EXPECT_EQ(std::string("5"), builder.GetResult());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST(NACKStringBuilderTest, TestCase11) {
|
|
|
|
|
NACKStringBuilder builder;
|
|
|
|
|
EXPECT_EQ(std::string(""), builder.GetResult());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST(NACKStringBuilderTest, TestCase12) {
|
|
|
|
|
NACKStringBuilder builder;
|
|
|
|
|
builder.PushNACK(5);
|
|
|
|
|
builder.PushNACK(6);
|
|
|
|
|
EXPECT_EQ(std::string("5-6"), builder.GetResult());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST(NACKStringBuilderTest, TestCase13) {
|
|
|
|
|
NACKStringBuilder builder;
|
|
|
|
|
builder.PushNACK(5);
|
|
|
|
|
builder.PushNACK(6);
|
|
|
|
|
builder.PushNACK(9);
|
|
|
|
|
EXPECT_EQ(std::string("5-6,9"), builder.GetResult());
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-21 00:02:47 -07:00
|
|
|
class RtcpPacketTypeCounterObserverImpl : public RtcpPacketTypeCounterObserver {
|
|
|
|
|
public:
|
|
|
|
|
RtcpPacketTypeCounterObserverImpl() : ssrc_(0) {}
|
|
|
|
|
virtual ~RtcpPacketTypeCounterObserverImpl() {}
|
|
|
|
|
void RtcpPacketTypesCounterUpdated(
|
|
|
|
|
uint32_t ssrc,
|
|
|
|
|
const RtcpPacketTypeCounter& packet_counter) override {
|
|
|
|
|
ssrc_ = ssrc;
|
|
|
|
|
counter_ = packet_counter;
|
|
|
|
|
}
|
|
|
|
|
uint32_t ssrc_;
|
|
|
|
|
RtcpPacketTypeCounter counter_;
|
|
|
|
|
};
|
2011-12-16 14:31:37 +00:00
|
|
|
|
|
|
|
|
class TestTransport : public Transport,
|
2013-08-15 23:38:54 +00:00
|
|
|
public NullRtpData {
|
2011-12-16 14:31:37 +00:00
|
|
|
public:
|
2015-08-21 00:02:47 -07:00
|
|
|
TestTransport() {}
|
|
|
|
|
|
2015-10-02 03:39:33 -07:00
|
|
|
bool SendRtp(const uint8_t* /*data*/,
|
|
|
|
|
size_t /*len*/,
|
|
|
|
|
const PacketOptions& options) override {
|
2015-09-28 09:59:31 -07:00
|
|
|
return false;
|
2011-12-16 14:31:37 +00:00
|
|
|
}
|
2015-09-28 09:59:31 -07:00
|
|
|
bool SendRtcp(const uint8_t* data, size_t len) override {
|
2015-08-21 00:02:47 -07:00
|
|
|
parser_.Parse(static_cast<const uint8_t*>(data), len);
|
2015-09-28 09:59:31 -07:00
|
|
|
return true;
|
2011-12-16 14:31:37 +00:00
|
|
|
}
|
2015-08-21 00:02:47 -07:00
|
|
|
int OnReceivedPayloadData(const uint8_t* payload_data,
|
|
|
|
|
const size_t payload_size,
|
|
|
|
|
const WebRtcRTPHeader* rtp_header) override {
|
2012-05-11 11:08:54 +00:00
|
|
|
return 0;
|
|
|
|
|
}
|
2015-08-21 00:02:47 -07:00
|
|
|
test::RtcpPacketParser parser_;
|
2011-12-16 14:31:37 +00:00
|
|
|
};
|
|
|
|
|
|
2015-07-24 09:58:18 +02:00
|
|
|
namespace {
|
2015-08-21 00:02:47 -07:00
|
|
|
static const uint32_t kSenderSsrc = 0x11111111;
|
|
|
|
|
static const uint32_t kRemoteSsrc = 0x22222222;
|
2015-07-24 09:58:18 +02:00
|
|
|
}
|
2013-12-13 08:42:42 +00:00
|
|
|
|
2015-07-24 09:58:18 +02:00
|
|
|
class RtcpSenderTest : public ::testing::Test {
|
|
|
|
|
protected:
|
2012-06-07 08:10:14 +00:00
|
|
|
RtcpSenderTest()
|
2015-08-21 00:02:47 -07:00
|
|
|
: clock_(1335900000),
|
2013-10-02 13:15:34 +00:00
|
|
|
receive_statistics_(ReceiveStatistics::Create(&clock_)) {
|
2012-05-11 11:08:54 +00:00
|
|
|
RtpRtcp::Configuration configuration;
|
|
|
|
|
configuration.audio = false;
|
2013-10-02 13:15:34 +00:00
|
|
|
configuration.clock = &clock_;
|
2015-08-21 00:02:47 -07:00
|
|
|
configuration.outgoing_transport = &test_transport_;
|
|
|
|
|
|
|
|
|
|
rtp_rtcp_impl_.reset(new ModuleRtpRtcpImpl(configuration));
|
2015-09-29 04:45:43 -07:00
|
|
|
rtcp_sender_.reset(new RTCPSender(false, &clock_, receive_statistics_.get(),
|
2016-01-21 05:42:04 -08:00
|
|
|
nullptr, nullptr, &test_transport_));
|
2015-08-21 00:02:47 -07:00
|
|
|
rtcp_sender_->SetSSRC(kSenderSsrc);
|
|
|
|
|
rtcp_sender_->SetRemoteSSRC(kRemoteSsrc);
|
2011-12-16 14:31:37 +00:00
|
|
|
}
|
2015-07-24 09:58:18 +02:00
|
|
|
|
2015-08-21 00:02:47 -07:00
|
|
|
void InsertIncomingPacket(uint32_t remote_ssrc, uint16_t seq_num) {
|
|
|
|
|
RTPHeader header;
|
|
|
|
|
header.ssrc = remote_ssrc;
|
|
|
|
|
header.sequenceNumber = seq_num;
|
|
|
|
|
header.timestamp = 12345;
|
|
|
|
|
header.headerLength = 12;
|
|
|
|
|
size_t kPacketLength = 100;
|
|
|
|
|
receive_statistics_->IncomingPacket(header, kPacketLength, false);
|
2011-12-16 14:31:37 +00:00
|
|
|
}
|
|
|
|
|
|
2015-08-21 00:02:47 -07:00
|
|
|
test::RtcpPacketParser* parser() { return &test_transport_.parser_; }
|
|
|
|
|
|
|
|
|
|
RTCPSender::FeedbackState feedback_state() {
|
|
|
|
|
return rtp_rtcp_impl_->GetFeedbackState();
|
2012-04-30 08:24:55 +00:00
|
|
|
}
|
|
|
|
|
|
2013-10-02 13:15:34 +00:00
|
|
|
SimulatedClock clock_;
|
2015-08-21 00:02:47 -07:00
|
|
|
TestTransport test_transport_;
|
2015-02-26 14:34:55 +00:00
|
|
|
rtc::scoped_ptr<ReceiveStatistics> receive_statistics_;
|
2015-08-21 00:02:47 -07:00
|
|
|
rtc::scoped_ptr<ModuleRtpRtcpImpl> rtp_rtcp_impl_;
|
|
|
|
|
rtc::scoped_ptr<RTCPSender> rtcp_sender_;
|
2011-12-16 14:31:37 +00:00
|
|
|
};
|
|
|
|
|
|
2015-08-21 00:02:47 -07:00
|
|
|
TEST_F(RtcpSenderTest, SetRtcpStatus) {
|
2015-10-02 02:36:56 -07:00
|
|
|
EXPECT_EQ(RtcpMode::kOff, rtcp_sender_->Status());
|
|
|
|
|
rtcp_sender_->SetRTCPStatus(RtcpMode::kReducedSize);
|
|
|
|
|
EXPECT_EQ(RtcpMode::kReducedSize, rtcp_sender_->Status());
|
2015-08-21 00:02:47 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(RtcpSenderTest, SetSendingStatus) {
|
|
|
|
|
EXPECT_FALSE(rtcp_sender_->Sending());
|
|
|
|
|
EXPECT_EQ(0, rtcp_sender_->SetSendingStatus(feedback_state(), true));
|
|
|
|
|
EXPECT_TRUE(rtcp_sender_->Sending());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(RtcpSenderTest, NoPacketSentIfOff) {
|
2015-10-02 02:36:56 -07:00
|
|
|
rtcp_sender_->SetRTCPStatus(RtcpMode::kOff);
|
2015-08-21 00:02:47 -07:00
|
|
|
EXPECT_EQ(-1, rtcp_sender_->SendRTCP(feedback_state(), kRtcpSr));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(RtcpSenderTest, SendSr) {
|
|
|
|
|
const uint32_t kPacketCount = 0x12345;
|
|
|
|
|
const uint32_t kOctetCount = 0x23456;
|
2015-10-02 02:36:56 -07:00
|
|
|
rtcp_sender_->SetRTCPStatus(RtcpMode::kReducedSize);
|
2014-07-15 15:25:39 +00:00
|
|
|
RTCPSender::FeedbackState feedback_state = rtp_rtcp_impl_->GetFeedbackState();
|
2015-08-21 00:02:47 -07:00
|
|
|
feedback_state.packets_sent = kPacketCount;
|
|
|
|
|
feedback_state.media_bytes_sent = kOctetCount;
|
|
|
|
|
uint32_t ntp_secs;
|
|
|
|
|
uint32_t ntp_frac;
|
|
|
|
|
clock_.CurrentNtp(ntp_secs, ntp_frac);
|
|
|
|
|
EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state, kRtcpSr));
|
|
|
|
|
EXPECT_EQ(1, parser()->sender_report()->num_packets());
|
|
|
|
|
EXPECT_EQ(kSenderSsrc, parser()->sender_report()->Ssrc());
|
|
|
|
|
EXPECT_EQ(ntp_secs, parser()->sender_report()->NtpSec());
|
|
|
|
|
EXPECT_EQ(ntp_frac, parser()->sender_report()->NtpFrac());
|
|
|
|
|
EXPECT_EQ(kPacketCount, parser()->sender_report()->PacketCount());
|
|
|
|
|
EXPECT_EQ(kOctetCount, parser()->sender_report()->OctetCount());
|
|
|
|
|
EXPECT_EQ(0, parser()->report_block()->num_packets());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(RtcpSenderTest, SendRr) {
|
2015-10-02 02:36:56 -07:00
|
|
|
rtcp_sender_->SetRTCPStatus(RtcpMode::kReducedSize);
|
2015-08-21 00:02:47 -07:00
|
|
|
EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpRr));
|
|
|
|
|
EXPECT_EQ(1, parser()->receiver_report()->num_packets());
|
|
|
|
|
EXPECT_EQ(kSenderSsrc, parser()->receiver_report()->Ssrc());
|
|
|
|
|
EXPECT_EQ(0, parser()->report_block()->num_packets());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(RtcpSenderTest, SendRrWithOneReportBlock) {
|
|
|
|
|
const uint16_t kSeqNum = 11111;
|
|
|
|
|
InsertIncomingPacket(kRemoteSsrc, kSeqNum);
|
2015-10-02 02:36:56 -07:00
|
|
|
rtcp_sender_->SetRTCPStatus(RtcpMode::kCompound);
|
2015-08-21 00:02:47 -07:00
|
|
|
EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpRr));
|
|
|
|
|
EXPECT_EQ(1, parser()->receiver_report()->num_packets());
|
|
|
|
|
EXPECT_EQ(kSenderSsrc, parser()->receiver_report()->Ssrc());
|
|
|
|
|
EXPECT_EQ(1, parser()->report_block()->num_packets());
|
|
|
|
|
EXPECT_EQ(kRemoteSsrc, parser()->report_block()->Ssrc());
|
|
|
|
|
EXPECT_EQ(0U, parser()->report_block()->FractionLost());
|
|
|
|
|
EXPECT_EQ(0U, parser()->report_block()->CumPacketLost());
|
|
|
|
|
EXPECT_EQ(kSeqNum, parser()->report_block()->ExtHighestSeqNum());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(RtcpSenderTest, SendRrWithTwoReportBlocks) {
|
|
|
|
|
const uint16_t kSeqNum = 11111;
|
|
|
|
|
InsertIncomingPacket(kRemoteSsrc, kSeqNum);
|
|
|
|
|
InsertIncomingPacket(kRemoteSsrc + 1, kSeqNum + 1);
|
2015-10-02 02:36:56 -07:00
|
|
|
rtcp_sender_->SetRTCPStatus(RtcpMode::kCompound);
|
2015-08-21 00:02:47 -07:00
|
|
|
EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpRr));
|
|
|
|
|
EXPECT_EQ(1, parser()->receiver_report()->num_packets());
|
|
|
|
|
EXPECT_EQ(kSenderSsrc, parser()->receiver_report()->Ssrc());
|
|
|
|
|
EXPECT_EQ(2, parser()->report_block()->num_packets());
|
|
|
|
|
EXPECT_EQ(1, parser()->report_blocks_per_ssrc(kRemoteSsrc));
|
|
|
|
|
EXPECT_EQ(1, parser()->report_blocks_per_ssrc(kRemoteSsrc + 1));
|
|
|
|
|
}
|
2011-12-16 14:31:37 +00:00
|
|
|
|
2015-08-21 00:02:47 -07:00
|
|
|
TEST_F(RtcpSenderTest, SendSdes) {
|
2015-10-02 02:36:56 -07:00
|
|
|
rtcp_sender_->SetRTCPStatus(RtcpMode::kReducedSize);
|
2015-08-21 00:02:47 -07:00
|
|
|
EXPECT_EQ(0, rtcp_sender_->SetCNAME("alice@host"));
|
|
|
|
|
EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpSdes));
|
|
|
|
|
EXPECT_EQ(1, parser()->sdes()->num_packets());
|
|
|
|
|
EXPECT_EQ(1, parser()->sdes_chunk()->num_packets());
|
|
|
|
|
EXPECT_EQ(kSenderSsrc, parser()->sdes_chunk()->Ssrc());
|
|
|
|
|
EXPECT_EQ("alice@host", parser()->sdes_chunk()->Cname());
|
2011-12-16 14:31:37 +00:00
|
|
|
}
|
|
|
|
|
|
2015-08-21 00:02:47 -07:00
|
|
|
TEST_F(RtcpSenderTest, SdesIncludedInCompoundPacket) {
|
2015-10-02 02:36:56 -07:00
|
|
|
rtcp_sender_->SetRTCPStatus(RtcpMode::kCompound);
|
2015-08-21 00:02:47 -07:00
|
|
|
EXPECT_EQ(0, rtcp_sender_->SetCNAME("alice@host"));
|
|
|
|
|
EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpReport));
|
|
|
|
|
EXPECT_EQ(1, parser()->receiver_report()->num_packets());
|
|
|
|
|
EXPECT_EQ(1, parser()->sdes()->num_packets());
|
|
|
|
|
EXPECT_EQ(1, parser()->sdes_chunk()->num_packets());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(RtcpSenderTest, SendBye) {
|
2015-10-02 02:36:56 -07:00
|
|
|
rtcp_sender_->SetRTCPStatus(RtcpMode::kReducedSize);
|
2015-08-21 00:02:47 -07:00
|
|
|
EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpBye));
|
|
|
|
|
EXPECT_EQ(1, parser()->bye()->num_packets());
|
|
|
|
|
EXPECT_EQ(kSenderSsrc, parser()->bye()->Ssrc());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(RtcpSenderTest, StopSendingTriggersBye) {
|
2015-10-02 02:36:56 -07:00
|
|
|
rtcp_sender_->SetRTCPStatus(RtcpMode::kReducedSize);
|
2015-08-21 00:02:47 -07:00
|
|
|
EXPECT_EQ(0, rtcp_sender_->SetSendingStatus(feedback_state(), true));
|
|
|
|
|
EXPECT_EQ(0, rtcp_sender_->SetSendingStatus(feedback_state(), false));
|
|
|
|
|
EXPECT_EQ(1, parser()->bye()->num_packets());
|
|
|
|
|
EXPECT_EQ(kSenderSsrc, parser()->bye()->Ssrc());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(RtcpSenderTest, SendApp) {
|
|
|
|
|
const uint8_t kSubType = 30;
|
|
|
|
|
uint32_t name = 'n' << 24;
|
|
|
|
|
name += 'a' << 16;
|
|
|
|
|
name += 'm' << 8;
|
|
|
|
|
name += 'e';
|
|
|
|
|
const uint8_t kData[] = {'t', 'e', 's', 't', 'd', 'a', 't', 'a'};
|
|
|
|
|
const uint16_t kDataLength = sizeof(kData) / sizeof(kData[0]);
|
|
|
|
|
EXPECT_EQ(0, rtcp_sender_->SetApplicationSpecificData(kSubType, name, kData,
|
|
|
|
|
kDataLength));
|
2015-10-02 02:36:56 -07:00
|
|
|
rtcp_sender_->SetRTCPStatus(RtcpMode::kReducedSize);
|
2015-08-21 00:02:47 -07:00
|
|
|
EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpApp));
|
|
|
|
|
EXPECT_EQ(1, parser()->app()->num_packets());
|
|
|
|
|
EXPECT_EQ(kSubType, parser()->app()->SubType());
|
|
|
|
|
EXPECT_EQ(name, parser()->app()->Name());
|
|
|
|
|
EXPECT_EQ(1, parser()->app_item()->num_packets());
|
|
|
|
|
EXPECT_EQ(kDataLength, parser()->app_item()->DataLength());
|
|
|
|
|
EXPECT_EQ(0, strncmp(reinterpret_cast<const char*>(kData),
|
|
|
|
|
reinterpret_cast<const char*>(parser()->app_item()->Data()),
|
|
|
|
|
parser()->app_item()->DataLength()));
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-01 10:11:16 +02:00
|
|
|
TEST_F(RtcpSenderTest, SendEmptyApp) {
|
|
|
|
|
const uint8_t kSubType = 30;
|
|
|
|
|
const uint32_t kName = 0x6E616D65;
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(
|
|
|
|
|
0, rtcp_sender_->SetApplicationSpecificData(kSubType, kName, nullptr, 0));
|
|
|
|
|
|
2015-10-02 02:36:56 -07:00
|
|
|
rtcp_sender_->SetRTCPStatus(RtcpMode::kReducedSize);
|
2015-09-01 10:11:16 +02:00
|
|
|
EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpApp));
|
|
|
|
|
EXPECT_EQ(1, parser()->app()->num_packets());
|
|
|
|
|
EXPECT_EQ(kSubType, parser()->app()->SubType());
|
|
|
|
|
EXPECT_EQ(kName, parser()->app()->Name());
|
|
|
|
|
EXPECT_EQ(0, parser()->app_item()->num_packets());
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-21 00:02:47 -07:00
|
|
|
TEST_F(RtcpSenderTest, SetInvalidApplicationSpecificData) {
|
|
|
|
|
const uint8_t kData[] = {'t', 'e', 's', 't', 'd', 'a', 't'};
|
|
|
|
|
const uint16_t kInvalidDataLength = sizeof(kData) / sizeof(kData[0]);
|
|
|
|
|
EXPECT_EQ(-1, rtcp_sender_->SetApplicationSpecificData(
|
|
|
|
|
0, 0, kData, kInvalidDataLength)); // Should by multiple of 4.
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(RtcpSenderTest, SendFirNonRepeat) {
|
2015-10-02 02:36:56 -07:00
|
|
|
rtcp_sender_->SetRTCPStatus(RtcpMode::kReducedSize);
|
2015-08-21 00:02:47 -07:00
|
|
|
EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpFir));
|
|
|
|
|
EXPECT_EQ(1, parser()->fir()->num_packets());
|
|
|
|
|
EXPECT_EQ(kSenderSsrc, parser()->fir()->Ssrc());
|
|
|
|
|
EXPECT_EQ(1, parser()->fir_item()->num_packets());
|
|
|
|
|
EXPECT_EQ(kRemoteSsrc, parser()->fir_item()->Ssrc());
|
|
|
|
|
uint8_t seq = parser()->fir_item()->SeqNum();
|
|
|
|
|
// Sends non-repeat FIR as default.
|
|
|
|
|
EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpFir));
|
|
|
|
|
EXPECT_EQ(2, parser()->fir()->num_packets());
|
|
|
|
|
EXPECT_EQ(2, parser()->fir_item()->num_packets());
|
|
|
|
|
EXPECT_EQ(seq + 1, parser()->fir_item()->SeqNum());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(RtcpSenderTest, SendFirRepeat) {
|
2015-10-02 02:36:56 -07:00
|
|
|
rtcp_sender_->SetRTCPStatus(RtcpMode::kReducedSize);
|
2015-08-21 00:02:47 -07:00
|
|
|
EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpFir));
|
|
|
|
|
EXPECT_EQ(1, parser()->fir()->num_packets());
|
|
|
|
|
EXPECT_EQ(1, parser()->fir_item()->num_packets());
|
|
|
|
|
uint8_t seq = parser()->fir_item()->SeqNum();
|
|
|
|
|
const bool kRepeat = true;
|
|
|
|
|
EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpFir, 0, nullptr,
|
|
|
|
|
kRepeat));
|
|
|
|
|
EXPECT_EQ(2, parser()->fir()->num_packets());
|
|
|
|
|
EXPECT_EQ(2, parser()->fir_item()->num_packets());
|
|
|
|
|
EXPECT_EQ(seq, parser()->fir_item()->SeqNum());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(RtcpSenderTest, SendPli) {
|
2015-10-02 02:36:56 -07:00
|
|
|
rtcp_sender_->SetRTCPStatus(RtcpMode::kReducedSize);
|
2015-08-21 00:02:47 -07:00
|
|
|
EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpPli));
|
|
|
|
|
EXPECT_EQ(1, parser()->pli()->num_packets());
|
|
|
|
|
EXPECT_EQ(kSenderSsrc, parser()->pli()->Ssrc());
|
|
|
|
|
EXPECT_EQ(kRemoteSsrc, parser()->pli()->MediaSsrc());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(RtcpSenderTest, SendRpsi) {
|
|
|
|
|
const uint64_t kPictureId = 0x41;
|
|
|
|
|
const int8_t kPayloadType = 100;
|
2015-10-02 02:36:56 -07:00
|
|
|
rtcp_sender_->SetRTCPStatus(RtcpMode::kReducedSize);
|
2014-07-15 15:25:39 +00:00
|
|
|
RTCPSender::FeedbackState feedback_state = rtp_rtcp_impl_->GetFeedbackState();
|
2015-08-21 00:02:47 -07:00
|
|
|
feedback_state.send_payload_type = kPayloadType;
|
|
|
|
|
EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state, kRtcpRpsi, 0, nullptr,
|
|
|
|
|
false, kPictureId));
|
|
|
|
|
EXPECT_EQ(kPayloadType, parser()->rpsi()->PayloadType());
|
|
|
|
|
EXPECT_EQ(kPictureId, parser()->rpsi()->PictureId());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(RtcpSenderTest, SendSli) {
|
|
|
|
|
const uint16_t kFirstMb = 0;
|
|
|
|
|
const uint16_t kNumberOfMb = 0x1FFF;
|
|
|
|
|
const uint8_t kPictureId = 60;
|
2015-10-02 02:36:56 -07:00
|
|
|
rtcp_sender_->SetRTCPStatus(RtcpMode::kReducedSize);
|
2015-08-21 00:02:47 -07:00
|
|
|
EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpSli, 0, nullptr,
|
|
|
|
|
false, kPictureId));
|
|
|
|
|
EXPECT_EQ(1, parser()->sli()->num_packets());
|
|
|
|
|
EXPECT_EQ(kSenderSsrc, parser()->sli()->Ssrc());
|
|
|
|
|
EXPECT_EQ(kRemoteSsrc, parser()->sli()->MediaSsrc());
|
|
|
|
|
EXPECT_EQ(1, parser()->sli_item()->num_packets());
|
|
|
|
|
EXPECT_EQ(kFirstMb, parser()->sli_item()->FirstMb());
|
|
|
|
|
EXPECT_EQ(kNumberOfMb, parser()->sli_item()->NumberOfMb());
|
|
|
|
|
EXPECT_EQ(kPictureId, parser()->sli_item()->PictureId());
|
|
|
|
|
}
|
2011-12-16 14:31:37 +00:00
|
|
|
|
2015-08-21 00:02:47 -07:00
|
|
|
TEST_F(RtcpSenderTest, SendNack) {
|
2015-10-02 02:36:56 -07:00
|
|
|
rtcp_sender_->SetRTCPStatus(RtcpMode::kReducedSize);
|
2015-08-21 00:02:47 -07:00
|
|
|
const uint16_t kList[] = {0, 1, 16};
|
|
|
|
|
const int32_t kListLength = sizeof(kList) / sizeof(kList[0]);
|
|
|
|
|
EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpNack, kListLength,
|
|
|
|
|
kList));
|
|
|
|
|
EXPECT_EQ(1, parser()->nack()->num_packets());
|
|
|
|
|
EXPECT_EQ(kSenderSsrc, parser()->nack()->Ssrc());
|
|
|
|
|
EXPECT_EQ(kRemoteSsrc, parser()->nack()->MediaSsrc());
|
|
|
|
|
EXPECT_EQ(1, parser()->nack_item()->num_packets());
|
|
|
|
|
EXPECT_THAT(parser()->nack_item()->last_nack_list(), ElementsAre(0, 1, 16));
|
2011-12-16 14:31:37 +00:00
|
|
|
}
|
|
|
|
|
|
2015-08-21 00:02:47 -07:00
|
|
|
TEST_F(RtcpSenderTest, SendRemb) {
|
|
|
|
|
const int kBitrate = 261011;
|
|
|
|
|
std::vector<uint32_t> ssrcs;
|
|
|
|
|
ssrcs.push_back(kRemoteSsrc);
|
|
|
|
|
ssrcs.push_back(kRemoteSsrc + 1);
|
2015-10-02 02:36:56 -07:00
|
|
|
rtcp_sender_->SetRTCPStatus(RtcpMode::kReducedSize);
|
2015-08-21 00:02:47 -07:00
|
|
|
rtcp_sender_->SetREMBData(kBitrate, ssrcs);
|
|
|
|
|
EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpRemb));
|
|
|
|
|
EXPECT_EQ(1, parser()->psfb_app()->num_packets());
|
|
|
|
|
EXPECT_EQ(kSenderSsrc, parser()->psfb_app()->Ssrc());
|
|
|
|
|
EXPECT_EQ(1, parser()->remb_item()->num_packets());
|
|
|
|
|
EXPECT_EQ(kBitrate, parser()->remb_item()->last_bitrate_bps());
|
|
|
|
|
EXPECT_THAT(parser()->remb_item()->last_ssrc_list(),
|
|
|
|
|
ElementsAre(kRemoteSsrc, kRemoteSsrc + 1));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(RtcpSenderTest, RembIncludedInCompoundPacketIfEnabled) {
|
|
|
|
|
const int kBitrate = 261011;
|
|
|
|
|
std::vector<uint32_t> ssrcs;
|
|
|
|
|
ssrcs.push_back(kRemoteSsrc);
|
2015-10-02 02:36:56 -07:00
|
|
|
rtcp_sender_->SetRTCPStatus(RtcpMode::kCompound);
|
2015-08-21 00:02:47 -07:00
|
|
|
rtcp_sender_->SetREMBStatus(true);
|
|
|
|
|
EXPECT_TRUE(rtcp_sender_->REMB());
|
|
|
|
|
rtcp_sender_->SetREMBData(kBitrate, ssrcs);
|
|
|
|
|
EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpReport));
|
|
|
|
|
EXPECT_EQ(1, parser()->psfb_app()->num_packets());
|
|
|
|
|
EXPECT_EQ(1, parser()->remb_item()->num_packets());
|
|
|
|
|
// REMB should be included in each compound packet.
|
|
|
|
|
EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpReport));
|
|
|
|
|
EXPECT_EQ(2, parser()->psfb_app()->num_packets());
|
|
|
|
|
EXPECT_EQ(2, parser()->remb_item()->num_packets());
|
|
|
|
|
}
|
2013-10-02 13:15:34 +00:00
|
|
|
|
2015-08-21 00:02:47 -07:00
|
|
|
TEST_F(RtcpSenderTest, RembNotIncludedInCompoundPacketIfNotEnabled) {
|
|
|
|
|
const int kBitrate = 261011;
|
|
|
|
|
std::vector<uint32_t> ssrcs;
|
|
|
|
|
ssrcs.push_back(kRemoteSsrc);
|
2015-10-02 02:36:56 -07:00
|
|
|
rtcp_sender_->SetRTCPStatus(RtcpMode::kCompound);
|
2015-08-21 00:02:47 -07:00
|
|
|
rtcp_sender_->SetREMBData(kBitrate, ssrcs);
|
|
|
|
|
EXPECT_FALSE(rtcp_sender_->REMB());
|
|
|
|
|
EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpReport));
|
|
|
|
|
EXPECT_EQ(0, parser()->psfb_app()->num_packets());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(RtcpSenderTest, SendXrWithVoipMetric) {
|
2015-10-02 02:36:56 -07:00
|
|
|
rtcp_sender_->SetRTCPStatus(RtcpMode::kReducedSize);
|
2015-08-21 00:02:47 -07:00
|
|
|
RTCPVoIPMetric metric;
|
|
|
|
|
metric.lossRate = 1;
|
|
|
|
|
metric.discardRate = 2;
|
|
|
|
|
metric.burstDensity = 3;
|
|
|
|
|
metric.gapDensity = 4;
|
|
|
|
|
metric.burstDuration = 0x1111;
|
|
|
|
|
metric.gapDuration = 0x2222;
|
|
|
|
|
metric.roundTripDelay = 0x3333;
|
|
|
|
|
metric.endSystemDelay = 0x4444;
|
|
|
|
|
metric.signalLevel = 5;
|
|
|
|
|
metric.noiseLevel = 6;
|
|
|
|
|
metric.RERL = 7;
|
|
|
|
|
metric.Gmin = 8;
|
|
|
|
|
metric.Rfactor = 9;
|
|
|
|
|
metric.extRfactor = 10;
|
|
|
|
|
metric.MOSLQ = 11;
|
|
|
|
|
metric.MOSCQ = 12;
|
|
|
|
|
metric.RXconfig = 13;
|
|
|
|
|
metric.JBnominal = 0x5555;
|
|
|
|
|
metric.JBmax = 0x6666;
|
|
|
|
|
metric.JBabsMax = 0x7777;
|
|
|
|
|
EXPECT_EQ(0, rtcp_sender_->SetRTCPVoIPMetrics(&metric));
|
|
|
|
|
EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpXrVoipMetric));
|
|
|
|
|
EXPECT_EQ(1, parser()->xr_header()->num_packets());
|
|
|
|
|
EXPECT_EQ(kSenderSsrc, parser()->xr_header()->Ssrc());
|
|
|
|
|
EXPECT_EQ(1, parser()->voip_metric()->num_packets());
|
|
|
|
|
EXPECT_EQ(kRemoteSsrc, parser()->voip_metric()->Ssrc());
|
|
|
|
|
EXPECT_EQ(metric.lossRate, parser()->voip_metric()->LossRate());
|
|
|
|
|
EXPECT_EQ(metric.discardRate, parser()->voip_metric()->DiscardRate());
|
|
|
|
|
EXPECT_EQ(metric.burstDensity, parser()->voip_metric()->BurstDensity());
|
|
|
|
|
EXPECT_EQ(metric.gapDensity, parser()->voip_metric()->GapDensity());
|
|
|
|
|
EXPECT_EQ(metric.burstDuration, parser()->voip_metric()->BurstDuration());
|
|
|
|
|
EXPECT_EQ(metric.gapDuration, parser()->voip_metric()->GapDuration());
|
|
|
|
|
EXPECT_EQ(metric.roundTripDelay, parser()->voip_metric()->RoundTripDelay());
|
|
|
|
|
EXPECT_EQ(metric.endSystemDelay, parser()->voip_metric()->EndSystemDelay());
|
|
|
|
|
EXPECT_EQ(metric.signalLevel, parser()->voip_metric()->SignalLevel());
|
|
|
|
|
EXPECT_EQ(metric.noiseLevel, parser()->voip_metric()->NoiseLevel());
|
|
|
|
|
EXPECT_EQ(metric.RERL, parser()->voip_metric()->Rerl());
|
|
|
|
|
EXPECT_EQ(metric.Gmin, parser()->voip_metric()->Gmin());
|
|
|
|
|
EXPECT_EQ(metric.Rfactor, parser()->voip_metric()->Rfactor());
|
|
|
|
|
EXPECT_EQ(metric.extRfactor, parser()->voip_metric()->ExtRfactor());
|
|
|
|
|
EXPECT_EQ(metric.MOSLQ, parser()->voip_metric()->MosLq());
|
|
|
|
|
EXPECT_EQ(metric.MOSCQ, parser()->voip_metric()->MosCq());
|
|
|
|
|
EXPECT_EQ(metric.RXconfig, parser()->voip_metric()->RxConfig());
|
|
|
|
|
EXPECT_EQ(metric.JBnominal, parser()->voip_metric()->JbNominal());
|
|
|
|
|
EXPECT_EQ(metric.JBmax, parser()->voip_metric()->JbMax());
|
|
|
|
|
EXPECT_EQ(metric.JBabsMax, parser()->voip_metric()->JbAbsMax());
|
2013-10-02 13:15:34 +00:00
|
|
|
}
|
|
|
|
|
|
2015-08-21 00:02:47 -07:00
|
|
|
TEST_F(RtcpSenderTest, SendXrWithDlrr) {
|
2015-10-02 02:36:56 -07:00
|
|
|
rtcp_sender_->SetRTCPStatus(RtcpMode::kCompound);
|
2014-07-15 15:25:39 +00:00
|
|
|
RTCPSender::FeedbackState feedback_state = rtp_rtcp_impl_->GetFeedbackState();
|
2015-08-21 00:02:47 -07:00
|
|
|
feedback_state.has_last_xr_rr = true;
|
|
|
|
|
RtcpReceiveTimeInfo last_xr_rr;
|
|
|
|
|
last_xr_rr.sourceSSRC = 0x11111111;
|
|
|
|
|
last_xr_rr.lastRR = 0x22222222;
|
|
|
|
|
last_xr_rr.delaySinceLastRR = 0x33333333;
|
|
|
|
|
feedback_state.last_xr_rr = last_xr_rr;
|
2013-10-02 13:15:34 +00:00
|
|
|
EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state, kRtcpReport));
|
2015-08-21 00:02:47 -07:00
|
|
|
EXPECT_EQ(1, parser()->xr_header()->num_packets());
|
|
|
|
|
EXPECT_EQ(kSenderSsrc, parser()->xr_header()->Ssrc());
|
|
|
|
|
EXPECT_EQ(1, parser()->dlrr()->num_packets());
|
|
|
|
|
EXPECT_EQ(1, parser()->dlrr_items()->num_packets());
|
|
|
|
|
EXPECT_EQ(last_xr_rr.sourceSSRC, parser()->dlrr_items()->Ssrc(0));
|
|
|
|
|
EXPECT_EQ(last_xr_rr.lastRR, parser()->dlrr_items()->LastRr(0));
|
|
|
|
|
EXPECT_EQ(last_xr_rr.delaySinceLastRR,
|
|
|
|
|
parser()->dlrr_items()->DelayLastRr(0));
|
|
|
|
|
}
|
2013-10-02 13:15:34 +00:00
|
|
|
|
2015-08-21 00:02:47 -07:00
|
|
|
TEST_F(RtcpSenderTest, SendXrWithRrtr) {
|
2015-10-02 02:36:56 -07:00
|
|
|
rtcp_sender_->SetRTCPStatus(RtcpMode::kCompound);
|
2015-08-21 00:02:47 -07:00
|
|
|
EXPECT_EQ(0, rtcp_sender_->SetSendingStatus(feedback_state(), false));
|
|
|
|
|
rtcp_sender_->SendRtcpXrReceiverReferenceTime(true);
|
|
|
|
|
uint32_t ntp_secs;
|
|
|
|
|
uint32_t ntp_frac;
|
|
|
|
|
clock_.CurrentNtp(ntp_secs, ntp_frac);
|
|
|
|
|
EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpReport));
|
|
|
|
|
EXPECT_EQ(1, parser()->xr_header()->num_packets());
|
|
|
|
|
EXPECT_EQ(kSenderSsrc, parser()->xr_header()->Ssrc());
|
|
|
|
|
EXPECT_EQ(0, parser()->dlrr()->num_packets());
|
|
|
|
|
EXPECT_EQ(1, parser()->rrtr()->num_packets());
|
|
|
|
|
EXPECT_EQ(ntp_secs, parser()->rrtr()->NtpSec());
|
|
|
|
|
EXPECT_EQ(ntp_frac, parser()->rrtr()->NtpFrac());
|
2013-10-02 13:15:34 +00:00
|
|
|
}
|
|
|
|
|
|
2015-08-21 00:02:47 -07:00
|
|
|
TEST_F(RtcpSenderTest, TestNoXrRrtrSentIfSending) {
|
2015-10-02 02:36:56 -07:00
|
|
|
rtcp_sender_->SetRTCPStatus(RtcpMode::kCompound);
|
2015-08-21 00:02:47 -07:00
|
|
|
EXPECT_EQ(0, rtcp_sender_->SetSendingStatus(feedback_state(), true));
|
|
|
|
|
rtcp_sender_->SendRtcpXrReceiverReferenceTime(true);
|
|
|
|
|
EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpReport));
|
|
|
|
|
EXPECT_EQ(0, parser()->xr_header()->num_packets());
|
|
|
|
|
EXPECT_EQ(0, parser()->rrtr()->num_packets());
|
|
|
|
|
}
|
2013-10-02 13:15:34 +00:00
|
|
|
|
2015-08-21 00:02:47 -07:00
|
|
|
TEST_F(RtcpSenderTest, TestNoXrRrtrSentIfNotEnabled) {
|
2015-10-02 02:36:56 -07:00
|
|
|
rtcp_sender_->SetRTCPStatus(RtcpMode::kCompound);
|
2015-08-21 00:02:47 -07:00
|
|
|
EXPECT_EQ(0, rtcp_sender_->SetSendingStatus(feedback_state(), false));
|
|
|
|
|
rtcp_sender_->SendRtcpXrReceiverReferenceTime(false);
|
|
|
|
|
EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpReport));
|
|
|
|
|
EXPECT_EQ(0, parser()->xr_header()->num_packets());
|
|
|
|
|
EXPECT_EQ(0, parser()->rrtr()->num_packets());
|
2013-10-02 13:15:34 +00:00
|
|
|
}
|
|
|
|
|
|
2015-08-21 00:02:47 -07:00
|
|
|
TEST_F(RtcpSenderTest, TestRegisterRtcpPacketTypeObserver) {
|
|
|
|
|
RtcpPacketTypeCounterObserverImpl observer;
|
2015-09-29 04:45:43 -07:00
|
|
|
rtcp_sender_.reset(new RTCPSender(false, &clock_, receive_statistics_.get(),
|
2016-01-21 05:42:04 -08:00
|
|
|
&observer, nullptr, &test_transport_));
|
2015-08-21 00:02:47 -07:00
|
|
|
rtcp_sender_->SetRemoteSSRC(kRemoteSsrc);
|
2015-10-02 02:36:56 -07:00
|
|
|
rtcp_sender_->SetRTCPStatus(RtcpMode::kReducedSize);
|
2015-08-21 00:02:47 -07:00
|
|
|
EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpPli));
|
|
|
|
|
EXPECT_EQ(1, parser()->pli()->num_packets());
|
|
|
|
|
EXPECT_EQ(kRemoteSsrc, observer.ssrc_);
|
|
|
|
|
EXPECT_EQ(1U, observer.counter_.pli_packets);
|
|
|
|
|
EXPECT_EQ(clock_.TimeInMilliseconds(),
|
|
|
|
|
observer.counter_.first_packet_time_ms);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(RtcpSenderTest, SendTmmbr) {
|
|
|
|
|
const unsigned int kBitrateBps = 312000;
|
2015-10-02 02:36:56 -07:00
|
|
|
rtcp_sender_->SetRTCPStatus(RtcpMode::kReducedSize);
|
2015-08-21 00:02:47 -07:00
|
|
|
rtcp_sender_->SetTargetBitrate(kBitrateBps);
|
|
|
|
|
EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpTmmbr));
|
|
|
|
|
EXPECT_EQ(1, parser()->tmmbr()->num_packets());
|
|
|
|
|
EXPECT_EQ(kSenderSsrc, parser()->tmmbr()->Ssrc());
|
|
|
|
|
EXPECT_EQ(1, parser()->tmmbr_item()->num_packets());
|
|
|
|
|
EXPECT_EQ(kBitrateBps / 1000, parser()->tmmbr_item()->BitrateKbps());
|
|
|
|
|
// TODO(asapersson): tmmbr_item()->Overhead() looks broken, always zero.
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(RtcpSenderTest, TmmbrIncludedInCompoundPacketIfEnabled) {
|
|
|
|
|
const unsigned int kBitrateBps = 312000;
|
2015-10-02 02:36:56 -07:00
|
|
|
rtcp_sender_->SetRTCPStatus(RtcpMode::kCompound);
|
2015-08-21 00:02:47 -07:00
|
|
|
EXPECT_FALSE(rtcp_sender_->TMMBR());
|
|
|
|
|
rtcp_sender_->SetTMMBRStatus(true);
|
|
|
|
|
EXPECT_TRUE(rtcp_sender_->TMMBR());
|
|
|
|
|
rtcp_sender_->SetTargetBitrate(kBitrateBps);
|
|
|
|
|
EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpReport));
|
|
|
|
|
EXPECT_EQ(1, parser()->tmmbr()->num_packets());
|
|
|
|
|
EXPECT_EQ(1, parser()->tmmbr_item()->num_packets());
|
|
|
|
|
// TMMBR should be included in each compound packet.
|
|
|
|
|
EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpReport));
|
|
|
|
|
EXPECT_EQ(2, parser()->tmmbr()->num_packets());
|
|
|
|
|
EXPECT_EQ(2, parser()->tmmbr_item()->num_packets());
|
|
|
|
|
|
|
|
|
|
rtcp_sender_->SetTMMBRStatus(false);
|
|
|
|
|
EXPECT_FALSE(rtcp_sender_->TMMBR());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(RtcpSenderTest, SendTmmbn) {
|
2015-10-02 02:36:56 -07:00
|
|
|
rtcp_sender_->SetRTCPStatus(RtcpMode::kCompound);
|
2015-08-21 00:02:47 -07:00
|
|
|
TMMBRSet bounding_set;
|
|
|
|
|
bounding_set.VerifyAndAllocateSet(1);
|
|
|
|
|
const uint32_t kBitrateKbps = 32768;
|
|
|
|
|
const uint32_t kPacketOh = 40;
|
|
|
|
|
const uint32_t kSourceSsrc = 12345;
|
|
|
|
|
bounding_set.AddEntry(kBitrateKbps, kPacketOh, kSourceSsrc);
|
2016-02-16 17:59:27 +01:00
|
|
|
EXPECT_EQ(0, rtcp_sender_->SetTMMBN(&bounding_set));
|
2015-08-21 00:02:47 -07:00
|
|
|
EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpSr));
|
|
|
|
|
EXPECT_EQ(1, parser()->sender_report()->num_packets());
|
|
|
|
|
EXPECT_EQ(1, parser()->tmmbn()->num_packets());
|
|
|
|
|
EXPECT_EQ(kSenderSsrc, parser()->tmmbn()->Ssrc());
|
|
|
|
|
EXPECT_EQ(1, parser()->tmmbn_items()->num_packets());
|
|
|
|
|
EXPECT_EQ(kBitrateKbps, parser()->tmmbn_items()->BitrateKbps(0));
|
|
|
|
|
EXPECT_EQ(kPacketOh, parser()->tmmbn_items()->Overhead(0));
|
|
|
|
|
EXPECT_EQ(kSourceSsrc, parser()->tmmbn_items()->Ssrc(0));
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-30 08:24:55 +00:00
|
|
|
// This test is written to verify actual behaviour. It does not seem
|
|
|
|
|
// to make much sense to send an empty TMMBN, since there is no place
|
|
|
|
|
// to put an actual limit here. It's just information that no limit
|
|
|
|
|
// is set, which is kind of the starting assumption.
|
|
|
|
|
// See http://code.google.com/p/webrtc/issues/detail?id=468 for one
|
|
|
|
|
// situation where this caused confusion.
|
|
|
|
|
TEST_F(RtcpSenderTest, SendsTmmbnIfSetAndEmpty) {
|
2015-10-02 02:36:56 -07:00
|
|
|
rtcp_sender_->SetRTCPStatus(RtcpMode::kCompound);
|
2012-04-30 08:24:55 +00:00
|
|
|
TMMBRSet bounding_set;
|
2016-02-16 17:59:27 +01:00
|
|
|
EXPECT_EQ(0, rtcp_sender_->SetTMMBN(&bounding_set));
|
2015-08-21 00:02:47 -07:00
|
|
|
EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpSr));
|
|
|
|
|
EXPECT_EQ(1, parser()->sender_report()->num_packets());
|
|
|
|
|
EXPECT_EQ(1, parser()->tmmbn()->num_packets());
|
|
|
|
|
EXPECT_EQ(kSenderSsrc, parser()->tmmbn()->Ssrc());
|
|
|
|
|
EXPECT_EQ(0, parser()->tmmbn_items()->num_packets());
|
|
|
|
|
}
|
2012-04-30 11:23:41 +00:00
|
|
|
|
2015-08-21 00:02:47 -07:00
|
|
|
TEST_F(RtcpSenderTest, SendCompoundPliRemb) {
|
|
|
|
|
const int kBitrate = 261011;
|
|
|
|
|
std::vector<uint32_t> ssrcs;
|
|
|
|
|
ssrcs.push_back(kRemoteSsrc);
|
2015-10-02 02:36:56 -07:00
|
|
|
rtcp_sender_->SetRTCPStatus(RtcpMode::kCompound);
|
2015-08-21 00:02:47 -07:00
|
|
|
rtcp_sender_->SetREMBData(kBitrate, ssrcs);
|
|
|
|
|
std::set<RTCPPacketType> packet_types;
|
|
|
|
|
packet_types.insert(kRtcpRemb);
|
|
|
|
|
packet_types.insert(kRtcpPli);
|
|
|
|
|
EXPECT_EQ(0, rtcp_sender_->SendCompoundRTCP(feedback_state(), packet_types));
|
|
|
|
|
EXPECT_EQ(1, parser()->remb_item()->num_packets());
|
|
|
|
|
EXPECT_EQ(1, parser()->pli()->num_packets());
|
2011-12-16 14:31:37 +00:00
|
|
|
}
|
2015-07-24 09:58:18 +02:00
|
|
|
|
2016-02-18 08:33:26 -08:00
|
|
|
|
|
|
|
|
// This test is written to verify that BYE is always the last packet
|
|
|
|
|
// type in a RTCP compoud packet. The rtcp_sender_ is recreated with
|
|
|
|
|
// mock_transport, which is used to check for whether BYE at the end
|
|
|
|
|
// of a RTCP compound packet.
|
|
|
|
|
TEST_F(RtcpSenderTest, ByeMustBeLast) {
|
|
|
|
|
MockTransport mock_transport;
|
|
|
|
|
EXPECT_CALL(mock_transport, SendRtcp(_, _))
|
|
|
|
|
.WillOnce(Invoke([](const uint8_t* data, size_t len) {
|
|
|
|
|
const uint8_t* next_packet = data;
|
|
|
|
|
while (next_packet < data + len) {
|
|
|
|
|
RtcpCommonHeader header;
|
|
|
|
|
RtcpParseCommonHeader(next_packet, len - (next_packet - data), &header);
|
|
|
|
|
next_packet = next_packet +
|
|
|
|
|
header.payload_size_bytes +
|
|
|
|
|
RtcpCommonHeader::kHeaderSizeBytes;
|
|
|
|
|
if (header.packet_type == RTCPUtility::PT_BYE) {
|
|
|
|
|
bool is_last_packet = (data + len == next_packet);
|
|
|
|
|
EXPECT_TRUE(is_last_packet) <<
|
|
|
|
|
"Bye packet should be last in a compound RTCP packet.";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
// Re-configure rtcp_sender_ with mock_transport_
|
|
|
|
|
rtcp_sender_.reset(new RTCPSender(false, &clock_, receive_statistics_.get(),
|
|
|
|
|
nullptr, nullptr, &mock_transport));
|
|
|
|
|
rtcp_sender_->SetSSRC(kSenderSsrc);
|
|
|
|
|
rtcp_sender_->SetRemoteSSRC(kRemoteSsrc);
|
|
|
|
|
|
|
|
|
|
// Set up XR VoIP metric to be included with BYE
|
|
|
|
|
rtcp_sender_->SetRTCPStatus(RtcpMode::kCompound);
|
|
|
|
|
RTCPVoIPMetric metric;
|
|
|
|
|
EXPECT_EQ(0, rtcp_sender_->SetRTCPVoIPMetrics(&metric));
|
|
|
|
|
EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpBye));
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-16 14:31:37 +00:00
|
|
|
} // namespace webrtc
|