
BUG= R=mflodman@webrtc.org Review URL: https://webrtc-codereview.appspot.com/10419004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@5757 4adac7df-926f-26a2-2b94-8c16560cd09d
219 lines
7.1 KiB
C++
219 lines
7.1 KiB
C++
/*
|
|
* Copyright (c) 2013 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/gmock/include/gmock/gmock.h"
|
|
#include "testing/gtest/include/gtest/gtest.h"
|
|
|
|
#include "webrtc/common_types.h"
|
|
#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h"
|
|
#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
|
|
|
|
namespace webrtc {
|
|
namespace {
|
|
const uint32_t kSenderSsrc = 0x12345;
|
|
const uint32_t kReceiverSsrc = 0x23456;
|
|
const uint32_t kOneWayNetworkDelayMs = 100;
|
|
|
|
class RtcpRttStatsTestImpl : public RtcpRttStats {
|
|
public:
|
|
RtcpRttStatsTestImpl() : rtt_ms_(0) {}
|
|
virtual ~RtcpRttStatsTestImpl() {}
|
|
|
|
virtual void OnRttUpdate(uint32_t rtt_ms) {
|
|
rtt_ms_ = rtt_ms;
|
|
}
|
|
virtual uint32_t LastProcessedRtt() const {
|
|
return rtt_ms_;
|
|
}
|
|
uint32_t rtt_ms_;
|
|
};
|
|
|
|
class SendTransport : public Transport,
|
|
public NullRtpData {
|
|
public:
|
|
SendTransport() : receiver_(NULL), clock_(NULL), delay_ms_(0) {}
|
|
|
|
void SetRtpRtcpModule(ModuleRtpRtcpImpl* receiver) {
|
|
receiver_ = receiver;
|
|
}
|
|
void SimulateNetworkDelay(uint32_t delay_ms, SimulatedClock* clock) {
|
|
clock_ = clock;
|
|
delay_ms_ = delay_ms;
|
|
}
|
|
virtual int SendPacket(int /*ch*/, const void* /*data*/, int /*len*/) {
|
|
return -1;
|
|
}
|
|
virtual int SendRTCPPacket(int /*ch*/, const void *data, int len) {
|
|
if (clock_) {
|
|
clock_->AdvanceTimeMilliseconds(delay_ms_);
|
|
}
|
|
EXPECT_TRUE(receiver_ != NULL);
|
|
EXPECT_EQ(0, receiver_->IncomingRtcpPacket(
|
|
static_cast<const uint8_t*>(data), len));
|
|
return len;
|
|
}
|
|
ModuleRtpRtcpImpl* receiver_;
|
|
SimulatedClock* clock_;
|
|
uint32_t delay_ms_;
|
|
};
|
|
|
|
class RtpRtcpModule {
|
|
public:
|
|
RtpRtcpModule(SimulatedClock* clock)
|
|
: receive_statistics_(ReceiveStatistics::Create(clock)) {
|
|
RtpRtcp::Configuration config;
|
|
config.audio = false;
|
|
config.clock = clock;
|
|
config.outgoing_transport = &transport_;
|
|
config.receive_statistics = receive_statistics_.get();
|
|
config.rtt_stats = &rtt_stats_;
|
|
|
|
impl_.reset(new ModuleRtpRtcpImpl(config));
|
|
EXPECT_EQ(0, impl_->SetRTCPStatus(kRtcpCompound));
|
|
|
|
transport_.SimulateNetworkDelay(kOneWayNetworkDelayMs, clock);
|
|
}
|
|
|
|
RtcpPacketTypeCounter packets_sent_;
|
|
RtcpPacketTypeCounter packets_received_;
|
|
scoped_ptr<ReceiveStatistics> receive_statistics_;
|
|
SendTransport transport_;
|
|
RtcpRttStatsTestImpl rtt_stats_;
|
|
scoped_ptr<ModuleRtpRtcpImpl> impl_;
|
|
|
|
RtcpPacketTypeCounter RtcpSent() {
|
|
impl_->GetRtcpPacketTypeCounters(&packets_sent_, &packets_received_);
|
|
return packets_sent_;
|
|
}
|
|
RtcpPacketTypeCounter RtcpReceived() {
|
|
impl_->GetRtcpPacketTypeCounters(&packets_sent_, &packets_received_);
|
|
return packets_received_;
|
|
}
|
|
};
|
|
} // namespace
|
|
|
|
class RtpRtcpImplTest : public ::testing::Test {
|
|
protected:
|
|
RtpRtcpImplTest()
|
|
: clock_(1335900000),
|
|
sender_(&clock_),
|
|
receiver_(&clock_) {
|
|
// Send module.
|
|
EXPECT_EQ(0, sender_.impl_->SetSendingStatus(true));
|
|
EXPECT_EQ(0, sender_.impl_->SetSSRC(kSenderSsrc));
|
|
sender_.impl_->SetRemoteSSRC(kReceiverSsrc);
|
|
// Receive module.
|
|
EXPECT_EQ(0, receiver_.impl_->SetSendingStatus(false));
|
|
EXPECT_EQ(0, receiver_.impl_->SetSSRC(kReceiverSsrc));
|
|
receiver_.impl_->SetRemoteSSRC(kSenderSsrc);
|
|
// Transport settings.
|
|
sender_.transport_.SetRtpRtcpModule(receiver_.impl_.get());
|
|
receiver_.transport_.SetRtpRtcpModule(sender_.impl_.get());
|
|
}
|
|
SimulatedClock clock_;
|
|
RtpRtcpModule sender_;
|
|
RtpRtcpModule receiver_;
|
|
};
|
|
|
|
TEST_F(RtpRtcpImplTest, Rtt) {
|
|
RTPHeader header;
|
|
header.timestamp = 1;
|
|
header.sequenceNumber = 123;
|
|
header.ssrc = kSenderSsrc;
|
|
header.headerLength = 12;
|
|
receiver_.receive_statistics_->IncomingPacket(header, 100, false);
|
|
|
|
// Sender module should send a SR.
|
|
EXPECT_EQ(0, sender_.impl_->SendRTCP(kRtcpReport));
|
|
|
|
// Receiver module should send a RR with a response to the last received SR.
|
|
clock_.AdvanceTimeMilliseconds(1000);
|
|
EXPECT_EQ(0, receiver_.impl_->SendRTCP(kRtcpReport));
|
|
|
|
// Verify RTT.
|
|
uint16_t rtt;
|
|
uint16_t avg_rtt;
|
|
uint16_t min_rtt;
|
|
uint16_t max_rtt;
|
|
EXPECT_EQ(0,
|
|
sender_.impl_->RTT(kReceiverSsrc, &rtt, &avg_rtt, &min_rtt, &max_rtt));
|
|
EXPECT_EQ(2 * kOneWayNetworkDelayMs, rtt);
|
|
EXPECT_EQ(2 * kOneWayNetworkDelayMs, avg_rtt);
|
|
EXPECT_EQ(2 * kOneWayNetworkDelayMs, min_rtt);
|
|
EXPECT_EQ(2 * kOneWayNetworkDelayMs, max_rtt);
|
|
|
|
// No RTT from other ssrc.
|
|
EXPECT_EQ(-1,
|
|
sender_.impl_->RTT(kReceiverSsrc+1, &rtt, &avg_rtt, &min_rtt, &max_rtt));
|
|
|
|
// Verify RTT from rtt_stats config.
|
|
EXPECT_EQ(0U, sender_.rtt_stats_.LastProcessedRtt());
|
|
EXPECT_EQ(0U, sender_.impl_->rtt_ms());
|
|
sender_.impl_->Process();
|
|
EXPECT_EQ(2 * kOneWayNetworkDelayMs, sender_.rtt_stats_.LastProcessedRtt());
|
|
EXPECT_EQ(2 * kOneWayNetworkDelayMs, sender_.impl_->rtt_ms());
|
|
}
|
|
|
|
TEST_F(RtpRtcpImplTest, SetRtcpXrRrtrStatus) {
|
|
EXPECT_FALSE(receiver_.impl_->RtcpXrRrtrStatus());
|
|
receiver_.impl_->SetRtcpXrRrtrStatus(true);
|
|
EXPECT_TRUE(receiver_.impl_->RtcpXrRrtrStatus());
|
|
}
|
|
|
|
TEST_F(RtpRtcpImplTest, RttForReceiverOnly) {
|
|
receiver_.impl_->SetRtcpXrRrtrStatus(true);
|
|
|
|
// Receiver module should send a Receiver time reference report (RTRR).
|
|
EXPECT_EQ(0, receiver_.impl_->SendRTCP(kRtcpReport));
|
|
|
|
// Sender module should send a response to the last received RTRR (DLRR).
|
|
clock_.AdvanceTimeMilliseconds(1000);
|
|
EXPECT_EQ(0, sender_.impl_->SendRTCP(kRtcpReport));
|
|
|
|
// Verify RTT.
|
|
EXPECT_EQ(0U, receiver_.rtt_stats_.LastProcessedRtt());
|
|
EXPECT_EQ(0U, receiver_.impl_->rtt_ms());
|
|
receiver_.impl_->Process();
|
|
EXPECT_EQ(2 * kOneWayNetworkDelayMs, receiver_.rtt_stats_.LastProcessedRtt());
|
|
EXPECT_EQ(2 * kOneWayNetworkDelayMs, receiver_.impl_->rtt_ms());
|
|
}
|
|
|
|
TEST_F(RtpRtcpImplTest, RtcpPacketTypeCounter_Nack) {
|
|
EXPECT_EQ(0U, sender_.RtcpReceived().nack_packets);
|
|
EXPECT_EQ(0U, receiver_.RtcpSent().nack_packets);
|
|
// Receive module sends a NACK.
|
|
const uint16_t kNackLength = 1;
|
|
uint16_t nack_list[kNackLength] = {123};
|
|
EXPECT_EQ(0, receiver_.impl_->SendNACK(nack_list, kNackLength));
|
|
EXPECT_EQ(1U, receiver_.RtcpSent().nack_packets);
|
|
|
|
// Send module receives the NACK.
|
|
EXPECT_EQ(1U, sender_.RtcpReceived().nack_packets);
|
|
}
|
|
|
|
TEST_F(RtpRtcpImplTest, RtcpPacketTypeCounter_FirAndPli) {
|
|
EXPECT_EQ(0U, sender_.RtcpReceived().fir_packets);
|
|
EXPECT_EQ(0U, receiver_.RtcpSent().fir_packets);
|
|
// Receive module sends a FIR.
|
|
EXPECT_EQ(0, receiver_.impl_->SendRTCP(kRtcpFir));
|
|
EXPECT_EQ(1U, receiver_.RtcpSent().fir_packets);
|
|
// Send module receives the FIR.
|
|
EXPECT_EQ(1U, sender_.RtcpReceived().fir_packets);
|
|
|
|
// Receive module sends a FIR and PLI.
|
|
EXPECT_EQ(0, receiver_.impl_->SendRTCP(kRtcpFir | kRtcpPli));
|
|
EXPECT_EQ(2U, receiver_.RtcpSent().fir_packets);
|
|
EXPECT_EQ(1U, receiver_.RtcpSent().pli_packets);
|
|
// Send module receives the FIR and PLI.
|
|
EXPECT_EQ(2U, sender_.RtcpReceived().fir_packets);
|
|
EXPECT_EQ(1U, sender_.RtcpReceived().pli_packets);
|
|
}
|
|
} // namespace webrtc
|