blob: a9268533d088bcff5810e5f4ffc7addefbb845e4 [file] [log] [blame]
/*
* 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 <algorithm>
#include <vector>
#include <gtest/gtest.h>
#include "test_api.h"
#include "common_types.h"
#include "rtp_rtcp.h"
#include "rtp_rtcp_defines.h"
using namespace webrtc;
const WebRtc_UWord64 kTestPictureId = 12345678;
class RtcpCallback : public RtcpFeedback {
public:
RtcpCallback(RtpRtcp* module) {
_rtpRtcpModule = module;
};
virtual void OnRTCPPacketTimeout(const WebRtc_Word32 id) {
}
virtual void OnLipSyncUpdate(const WebRtc_Word32 id,
const WebRtc_Word32 audioVideoOffset) {
};
virtual void OnTMMBRReceived(const WebRtc_Word32 id,
const WebRtc_UWord16 bwEstimateKbit) {
};
virtual void OnXRVoIPMetricReceived(
const WebRtc_Word32 id,
const RTCPVoIPMetric* metric,
const WebRtc_Word8 VoIPmetricBuffer[28]) {
};
virtual void OnSLIReceived(const WebRtc_Word32 id,
const WebRtc_UWord8 pictureId) {
EXPECT_EQ(28, pictureId);
};
virtual void OnRPSIReceived(const WebRtc_Word32 id,
const WebRtc_UWord64 pictureId) {
EXPECT_EQ(kTestPictureId, pictureId);
};
virtual void OnApplicationDataReceived(const WebRtc_Word32 id,
const WebRtc_UWord8 subType,
const WebRtc_UWord32 name,
const WebRtc_UWord16 length,
const WebRtc_UWord8* data) {
char print_name[5];
print_name[0] = static_cast<char>(name >> 24);
print_name[1] = static_cast<char>(name >> 16);
print_name[2] = static_cast<char>(name >> 8);
print_name[3] = static_cast<char>(name);
print_name[4] = 0;
EXPECT_STRCASEEQ("test", print_name);
};
virtual void OnSendReportReceived(const WebRtc_Word32 id,
const WebRtc_UWord32 senderSSRC) {
RTCPSenderInfo senderInfo;
EXPECT_EQ(0, _rtpRtcpModule->RemoteRTCPStat(&senderInfo));
};
virtual void OnReceiveReportReceived(const WebRtc_Word32 id,
const WebRtc_UWord32 senderSSRC) {
};
private:
RtpRtcp* _rtpRtcpModule;
};
class RtpRtcpRtcpTest : public ::testing::Test {
protected:
RtpRtcpRtcpTest() {
test_CSRC[0] = 1234;
test_CSRC[2] = 2345;
test_id = 123;
test_ssrc = 3456;
test_timestamp = 4567;
test_sequence_number = 2345;
}
~RtpRtcpRtcpTest() {}
virtual void SetUp() {
module1 = RtpRtcp::CreateRtpRtcp(test_id, true, &fake_clock);
module2 = RtpRtcp::CreateRtpRtcp(test_id+1, true, &fake_clock);
EXPECT_EQ(0, module1->InitReceiver());
EXPECT_EQ(0, module1->InitSender());
EXPECT_EQ(0, module2->InitReceiver());
EXPECT_EQ(0, module2->InitSender());
receiver = new RtpReceiver();
EXPECT_EQ(0, module2->RegisterIncomingDataCallback(receiver));
transport1 = new LoopBackTransport(module2);
EXPECT_EQ(0, module1->RegisterSendTransport(transport1));
transport2 = new LoopBackTransport(module1);
EXPECT_EQ(0, module2->RegisterSendTransport(transport2));
}
virtual void TearDown() {
RtpRtcp::DestroyRtpRtcp(module1);
RtpRtcp::DestroyRtpRtcp(module2);
delete transport1;
delete transport2;
delete receiver;
}
void SetUpCallFromModule1(RtcpCallback* feedback1, RtcpCallback* feedback2 ) {
EXPECT_EQ(0, module1->RegisterIncomingRTCPCallback(feedback1));
EXPECT_EQ(0, module2->RegisterIncomingRTCPCallback(feedback2));
EXPECT_EQ(0, module1->SetRTCPStatus(kRtcpCompound));
EXPECT_EQ(0, module2->SetRTCPStatus(kRtcpCompound));
EXPECT_EQ(0, module2->SetSSRC(test_ssrc + 1));
EXPECT_EQ(0, module1->SetSSRC(test_ssrc));
EXPECT_EQ(0, module1->SetSequenceNumber(test_sequence_number));
EXPECT_EQ(0, module1->SetStartTimestamp(test_timestamp));
EXPECT_EQ(0, module1->SetCSRCs(test_CSRC, 2));
EXPECT_EQ(0, module1->SetCNAME("john.doe@test.test"));
EXPECT_EQ(0, module1->SetSendingStatus(true));
CodecInst voiceCodec;
voiceCodec.pltype = 96;
voiceCodec.plfreq = 8000;
voiceCodec.rate = 64000;
memcpy(voiceCodec.plname, "PCMU", 5);
EXPECT_EQ(0, module1->RegisterSendPayload(voiceCodec));
EXPECT_EQ(0, module1->RegisterReceivePayload(voiceCodec));
EXPECT_EQ(0, module2->RegisterSendPayload(voiceCodec));
EXPECT_EQ(0, module2->RegisterReceivePayload(voiceCodec));
// We need to send one RTP packet to get the RTCP packet to be accepted by
// the receiving module.
// send RTP packet with the data "testtest"
const WebRtc_UWord8 test[9] = "testtest";
EXPECT_EQ(0, module1->SendOutgoingData(webrtc::kAudioFrameSpeech, 96,
0, test, 8));
}
int test_id;
RtpRtcp* module1;
RtpRtcp* module2;
RtpReceiver* receiver;
LoopBackTransport* transport1;
LoopBackTransport* transport2;
WebRtc_UWord32 test_ssrc;
WebRtc_UWord32 test_timestamp;
WebRtc_UWord16 test_sequence_number;
WebRtc_UWord32 test_CSRC[webrtc::kRtpCsrcSize];
FakeRtpRtcpClock fake_clock;
};
TEST_F(RtpRtcpRtcpTest, RTCP) {
RtcpCallback* myRTCPFeedback1 = new RtcpCallback(module1);
RtcpCallback* myRTCPFeedback2 = new RtcpCallback(module2);
SetUpCallFromModule1(myRTCPFeedback1, myRTCPFeedback2);
EXPECT_EQ(0, module1->SendRTCPReferencePictureSelection(kTestPictureId));
EXPECT_EQ(0, module1->SendRTCPSliceLossIndication(156));
WebRtc_UWord32 testOfCSRC[webrtc::kRtpCsrcSize];
EXPECT_EQ(2, module2->RemoteCSRCs(testOfCSRC));
EXPECT_EQ(test_CSRC[0], testOfCSRC[0]);
EXPECT_EQ(test_CSRC[1], testOfCSRC[1]);
// Set cname of mixed.
EXPECT_EQ(0, module1->AddMixedCNAME(test_CSRC[0], "john@192.168.0.1"));
EXPECT_EQ(0, module1->AddMixedCNAME(test_CSRC[1], "jane@192.168.0.2"));
EXPECT_EQ(-1, module1->AddMixedCNAME(test_CSRC[0], NULL));
EXPECT_EQ(-1, module1->RemoveMixedCNAME(test_CSRC[0] + 1));
EXPECT_EQ(0, module1->RemoveMixedCNAME(test_CSRC[1]));
EXPECT_EQ(0, module1->AddMixedCNAME(test_CSRC[1], "jane@192.168.0.2"));
RTCPReportBlock reportBlock;
reportBlock.cumulativeLost = 1;
reportBlock.delaySinceLastSR = 2;
reportBlock.extendedHighSeqNum = 3;
reportBlock.fractionLost= 4;
reportBlock.jitter = 5;
reportBlock.lastSR = 6;
// Set report blocks.
EXPECT_EQ(-1, module1->AddRTCPReportBlock(test_CSRC[0], NULL));
EXPECT_EQ(0, module1->AddRTCPReportBlock(test_CSRC[0], &reportBlock));
reportBlock.lastSR= 7;
EXPECT_EQ(0, module1->AddRTCPReportBlock(test_CSRC[1], &reportBlock));
WebRtc_UWord32 name = 't' << 24;
name += 'e' << 16;
name += 's' << 8;
name += 't';
EXPECT_EQ(0, module1->SetRTCPApplicationSpecificData(
3,
name,
(const WebRtc_UWord8 *)"test test test test test test test test test"\
" test test test test test test test test test test test test test"\
" test test test test test test test test test test test test test"\
" test test test test test test test test test test test test test"\
" test test test test test test test test test test test test ",
300));
// send RTCP packet, triggered by timer
fake_clock.IncrementTime(7500);
module1->Process();
fake_clock.IncrementTime(100);
module2->Process();
WebRtc_UWord32 receivedNTPsecs = 0;
WebRtc_UWord32 receivedNTPfrac = 0;
WebRtc_UWord32 RTCPArrivalTimeSecs = 0;
WebRtc_UWord32 RTCPArrivalTimeFrac = 0;
WebRtc_Word8 cName[RTCP_CNAME_SIZE];
EXPECT_EQ(0, module2->RemoteNTP(&receivedNTPsecs, &receivedNTPfrac,
&RTCPArrivalTimeSecs, &RTCPArrivalTimeFrac));
EXPECT_EQ(-1, module2->RemoteCNAME(module2->RemoteSSRC() + 1, cName));
EXPECT_EQ(-1, module2->RemoteCNAME(module2->RemoteSSRC(), NULL));
// Check multiple CNAME.
EXPECT_EQ(0, module2->RemoteCNAME(module2->RemoteSSRC(), cName));
EXPECT_EQ(0, strncmp(cName, "john.doe@test.test", RTCP_CNAME_SIZE));
EXPECT_EQ(0, module2->RemoteCNAME(test_CSRC[0], cName));
EXPECT_EQ(0, strncmp(cName, "john@192.168.0.1", RTCP_CNAME_SIZE));
EXPECT_EQ(0, module2->RemoteCNAME(test_CSRC[1], cName));
EXPECT_EQ(0, strncmp(cName, "jane@192.168.0.2", RTCP_CNAME_SIZE));
// get all report blocks
std::vector<RTCPReportBlock> report_blocks;
EXPECT_EQ(-1, module1->RemoteRTCPStat(NULL));
EXPECT_EQ(0, module1->RemoteRTCPStat(&report_blocks));
EXPECT_EQ(1u, report_blocks.size());
const RTCPReportBlock& reportBlockReceived = report_blocks[0];
float secSinceLastReport =
static_cast<float>(reportBlockReceived.delaySinceLastSR) / 65536.0f;
EXPECT_GE(0.101f, secSinceLastReport);
EXPECT_LE(0.100f, secSinceLastReport);
EXPECT_EQ(test_sequence_number, reportBlockReceived.extendedHighSeqNum);
EXPECT_EQ(0, reportBlockReceived.fractionLost);
EXPECT_EQ(static_cast<WebRtc_UWord32>(0),
reportBlockReceived.cumulativeLost);
WebRtc_UWord8 fraction_lost = 0; // scale 0 to 255
WebRtc_UWord32 cum_lost = 0; // number of lost packets
WebRtc_UWord32 ext_max = 0; // highest sequence number received
WebRtc_UWord32 jitter = 0;
WebRtc_UWord32 max_jitter = 0;
EXPECT_EQ(0, module2->StatisticsRTP(&fraction_lost,
&cum_lost,
&ext_max,
&jitter,
&max_jitter));
EXPECT_EQ(0, fraction_lost);
EXPECT_EQ((WebRtc_UWord32)0, cum_lost);
EXPECT_EQ(test_sequence_number, ext_max);
EXPECT_EQ(reportBlockReceived.jitter, jitter);
WebRtc_UWord16 RTT;
WebRtc_UWord16 avgRTT;
WebRtc_UWord16 minRTT;
WebRtc_UWord16 maxRTT;
// Get RoundTripTime.
EXPECT_EQ(0, module1->RTT(test_ssrc + 1, &RTT, &avgRTT, &minRTT, &maxRTT));
EXPECT_GE(10, RTT);
EXPECT_GE(10, avgRTT);
EXPECT_GE(10, minRTT);
EXPECT_GE(10, maxRTT);
// Set report blocks.
EXPECT_EQ(0, module1->AddRTCPReportBlock(test_CSRC[0], &reportBlock));
// Test receive report.
EXPECT_EQ(0, module1->SetSendingStatus(false));
// Test that BYE clears the CNAME
EXPECT_EQ(-1, module2->RemoteCNAME(module2->RemoteSSRC(), cName));
// Send RTCP packet, triggered by timer.
fake_clock.IncrementTime(5000);
module1->Process();
module2->Process();
delete myRTCPFeedback1;
delete myRTCPFeedback2;
}
TEST_F(RtpRtcpRtcpTest, RemoteRTCPStatRemote) {
std::vector<RTCPReportBlock> report_blocks;
RtcpCallback feedback1(module1);
RtcpCallback feedback2(module2);
SetUpCallFromModule1(&feedback1, &feedback2);
EXPECT_EQ(0, module1->RemoteRTCPStat(&report_blocks));
EXPECT_EQ(0u, report_blocks.size());
// send RTCP packet, triggered by timer
fake_clock.IncrementTime(7500);
module1->Process();
fake_clock.IncrementTime(100);
module2->Process();
EXPECT_EQ(0, module1->RemoteRTCPStat(&report_blocks));
ASSERT_EQ(1u, report_blocks.size());
// |test_ssrc+1| is the SSRC of module2 that send the report.
EXPECT_EQ(test_ssrc+1, report_blocks[0].remoteSSRC);
EXPECT_EQ(test_ssrc, report_blocks[0].sourceSSRC);
EXPECT_EQ(0u, report_blocks[0].cumulativeLost);
EXPECT_LT(0u, report_blocks[0].delaySinceLastSR);
EXPECT_EQ(test_sequence_number, report_blocks[0].extendedHighSeqNum);
EXPECT_EQ(0u, report_blocks[0].fractionLost);
}