blob: 69ed843e50af157f0bc90bc3d0af8d68c0d462e4 [file] [log] [blame]
/*
* 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 <algorithm>
#include <vector>
#include "testing/gtest/include/gtest/gtest.h"
#include "webrtc/modules/rtp_rtcp/test/testAPI/test_api.h"
#include "webrtc/common_types.h"
#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h"
#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
#include "webrtc/modules/rtp_rtcp/source/rtp_receiver_audio.h"
namespace webrtc {
namespace {
#define test_rate 64000u
class VerifyingAudioReceiver : public NullRtpData {
public:
int32_t OnReceivedPayloadData(
const uint8_t* payloadData,
const size_t payloadSize,
const webrtc::WebRtcRTPHeader* rtpHeader) override {
if (rtpHeader->header.payloadType == 98 ||
rtpHeader->header.payloadType == 99) {
EXPECT_EQ(4u, payloadSize);
char str[5];
memcpy(str, payloadData, payloadSize);
str[4] = 0;
// All our test vectors for payload type 96 and 97 even the stereo is on
// a per channel base equal to the 4 chars "test".
// Note there is no null termination so we add that to use the
// test EXPECT_STRCASEEQ.
EXPECT_STRCASEEQ("test", str);
return 0;
}
if (rtpHeader->header.payloadType == 100 ||
rtpHeader->header.payloadType == 101 ||
rtpHeader->header.payloadType == 102) {
if (rtpHeader->type.Audio.channel == 1) {
if (payloadData[0] == 0xff) {
// All our test vectors for payload type 100, 101 and 102 have the
// first channel data being equal to 0xff.
return 0;
}
}
ADD_FAILURE() << "This code path should never happen.";
return -1;
}
return 0;
}
};
class RTPCallback : public NullRtpFeedback {
public:
int32_t OnInitializeDecoder(const int8_t payloadType,
const char payloadName[RTP_PAYLOAD_NAME_SIZE],
const int frequency,
const uint8_t channels,
const uint32_t rate) override {
if (payloadType == 96) {
EXPECT_EQ(test_rate, rate) <<
"The rate should be 64K for this payloadType";
}
return 0;
}
};
class RtpRtcpAudioTest : public ::testing::Test {
protected:
RtpRtcpAudioTest() : fake_clock(123456) {
test_CSRC[0] = 1234;
test_CSRC[2] = 2345;
test_ssrc = 3456;
test_timestamp = 4567;
test_sequence_number = 2345;
}
~RtpRtcpAudioTest() {}
void SetUp() override {
audioFeedback = new NullRtpAudioFeedback();
data_receiver1 = new VerifyingAudioReceiver();
data_receiver2 = new VerifyingAudioReceiver();
rtp_callback = new RTPCallback();
transport1 = new LoopBackTransport();
transport2 = new LoopBackTransport();
receive_statistics1_.reset(ReceiveStatistics::Create(&fake_clock));
receive_statistics2_.reset(ReceiveStatistics::Create(&fake_clock));
rtp_payload_registry1_.reset(new RTPPayloadRegistry(
RTPPayloadStrategy::CreateStrategy(true)));
rtp_payload_registry2_.reset(new RTPPayloadRegistry(
RTPPayloadStrategy::CreateStrategy(true)));
RtpRtcp::Configuration configuration;
configuration.audio = true;
configuration.clock = &fake_clock;
configuration.receive_statistics = receive_statistics1_.get();
configuration.outgoing_transport = transport1;
configuration.audio_messages = audioFeedback;
module1 = RtpRtcp::CreateRtpRtcp(configuration);
rtp_receiver1_.reset(RtpReceiver::CreateAudioReceiver(
&fake_clock, audioFeedback, data_receiver1, NULL,
rtp_payload_registry1_.get()));
configuration.receive_statistics = receive_statistics2_.get();
configuration.outgoing_transport = transport2;
configuration.audio_messages = audioFeedback;
module2 = RtpRtcp::CreateRtpRtcp(configuration);
rtp_receiver2_.reset(RtpReceiver::CreateAudioReceiver(
&fake_clock, audioFeedback, data_receiver2, NULL,
rtp_payload_registry2_.get()));
transport1->SetSendModule(module2, rtp_payload_registry2_.get(),
rtp_receiver2_.get(), receive_statistics2_.get());
transport2->SetSendModule(module1, rtp_payload_registry1_.get(),
rtp_receiver1_.get(), receive_statistics1_.get());
}
void TearDown() override {
delete module1;
delete module2;
delete transport1;
delete transport2;
delete audioFeedback;
delete data_receiver1;
delete data_receiver2;
delete rtp_callback;
}
RtpRtcp* module1;
RtpRtcp* module2;
rtc::scoped_ptr<ReceiveStatistics> receive_statistics1_;
rtc::scoped_ptr<ReceiveStatistics> receive_statistics2_;
rtc::scoped_ptr<RtpReceiver> rtp_receiver1_;
rtc::scoped_ptr<RtpReceiver> rtp_receiver2_;
rtc::scoped_ptr<RTPPayloadRegistry> rtp_payload_registry1_;
rtc::scoped_ptr<RTPPayloadRegistry> rtp_payload_registry2_;
VerifyingAudioReceiver* data_receiver1;
VerifyingAudioReceiver* data_receiver2;
LoopBackTransport* transport1;
LoopBackTransport* transport2;
NullRtpAudioFeedback* audioFeedback;
RTPCallback* rtp_callback;
uint32_t test_ssrc;
uint32_t test_timestamp;
uint16_t test_sequence_number;
uint32_t test_CSRC[webrtc::kRtpCsrcSize];
SimulatedClock fake_clock;
};
TEST_F(RtpRtcpAudioTest, Basic) {
module1->SetSSRC(test_ssrc);
module1->SetStartTimestamp(test_timestamp);
// Test detection at the end of a DTMF tone.
// EXPECT_EQ(0, module2->SetTelephoneEventForwardToDecoder(true));
EXPECT_EQ(0, module1->SetSendingStatus(true));
// Start basic RTP test.
// Send an empty RTP packet.
// Should fail since we have not registered the payload type.
EXPECT_EQ(-1, module1->SendOutgoingData(webrtc::kAudioFrameSpeech,
96, 0, -1, NULL, 0));
CodecInst voice_codec;
memset(&voice_codec, 0, sizeof(voice_codec));
voice_codec.pltype = 96;
voice_codec.plfreq = 8000;
memcpy(voice_codec.plname, "PCMU", 5);
EXPECT_EQ(0, module1->RegisterSendPayload(voice_codec));
EXPECT_EQ(0, rtp_receiver1_->RegisterReceivePayload(
voice_codec.plname,
voice_codec.pltype,
voice_codec.plfreq,
voice_codec.channels,
(voice_codec.rate < 0) ? 0 : voice_codec.rate));
EXPECT_EQ(0, module2->RegisterSendPayload(voice_codec));
voice_codec.rate = test_rate;
EXPECT_EQ(0, rtp_receiver2_->RegisterReceivePayload(
voice_codec.plname,
voice_codec.pltype,
voice_codec.plfreq,
voice_codec.channels,
(voice_codec.rate < 0) ? 0 : voice_codec.rate));
const uint8_t test[5] = "test";
EXPECT_EQ(0, module1->SendOutgoingData(webrtc::kAudioFrameSpeech, 96,
0, -1, test, 4));
EXPECT_EQ(test_ssrc, rtp_receiver2_->SSRC());
uint32_t timestamp;
EXPECT_TRUE(rtp_receiver2_->Timestamp(&timestamp));
EXPECT_EQ(test_timestamp, timestamp);
}
TEST_F(RtpRtcpAudioTest, RED) {
CodecInst voice_codec;
memset(&voice_codec, 0, sizeof(voice_codec));
voice_codec.pltype = 96;
voice_codec.plfreq = 8000;
memcpy(voice_codec.plname, "PCMU", 5);
EXPECT_EQ(0, module1->RegisterSendPayload(voice_codec));
EXPECT_EQ(0, rtp_receiver1_->RegisterReceivePayload(
voice_codec.plname,
voice_codec.pltype,
voice_codec.plfreq,
voice_codec.channels,
(voice_codec.rate < 0) ? 0 : voice_codec.rate));
EXPECT_EQ(0, module2->RegisterSendPayload(voice_codec));
voice_codec.rate = test_rate;
EXPECT_EQ(0, rtp_receiver2_->RegisterReceivePayload(
voice_codec.plname,
voice_codec.pltype,
voice_codec.plfreq,
voice_codec.channels,
(voice_codec.rate < 0) ? 0 : voice_codec.rate));
module1->SetSSRC(test_ssrc);
module1->SetStartTimestamp(test_timestamp);
EXPECT_EQ(0, module1->SetSendingStatus(true));
voice_codec.pltype = 127;
voice_codec.plfreq = 8000;
memcpy(voice_codec.plname, "RED", 4);
EXPECT_EQ(0, module1->SetSendREDPayloadType(voice_codec.pltype));
int8_t red = 0;
EXPECT_EQ(0, module1->SendREDPayloadType(&red));
EXPECT_EQ(voice_codec.pltype, red);
EXPECT_EQ(0, rtp_receiver1_->RegisterReceivePayload(
voice_codec.plname,
voice_codec.pltype,
voice_codec.plfreq,
voice_codec.channels,
(voice_codec.rate < 0) ? 0 : voice_codec.rate));
EXPECT_EQ(0, rtp_receiver2_->RegisterReceivePayload(
voice_codec.plname,
voice_codec.pltype,
voice_codec.plfreq,
voice_codec.channels,
(voice_codec.rate < 0) ? 0 : voice_codec.rate));
RTPFragmentationHeader fragmentation;
fragmentation.fragmentationVectorSize = 2;
fragmentation.fragmentationLength = new size_t[2];
fragmentation.fragmentationLength[0] = 4;
fragmentation.fragmentationLength[1] = 4;
fragmentation.fragmentationOffset = new size_t[2];
fragmentation.fragmentationOffset[0] = 0;
fragmentation.fragmentationOffset[1] = 4;
fragmentation.fragmentationTimeDiff = new uint16_t[2];
fragmentation.fragmentationTimeDiff[0] = 0;
fragmentation.fragmentationTimeDiff[1] = 0;
fragmentation.fragmentationPlType = new uint8_t[2];
fragmentation.fragmentationPlType[0] = 96;
fragmentation.fragmentationPlType[1] = 96;
const uint8_t test[5] = "test";
// Send a RTP packet.
EXPECT_EQ(0, module1->SendOutgoingData(webrtc::kAudioFrameSpeech,
96, 160, -1, test, 4,
&fragmentation));
EXPECT_EQ(0, module1->SetSendREDPayloadType(-1));
EXPECT_EQ(-1, module1->SendREDPayloadType(&red));
}
TEST_F(RtpRtcpAudioTest, DTMF) {
CodecInst voice_codec;
memset(&voice_codec, 0, sizeof(voice_codec));
voice_codec.pltype = 96;
voice_codec.plfreq = 8000;
memcpy(voice_codec.plname, "PCMU", 5);
EXPECT_EQ(0, module1->RegisterSendPayload(voice_codec));
EXPECT_EQ(0, rtp_receiver1_->RegisterReceivePayload(
voice_codec.plname,
voice_codec.pltype,
voice_codec.plfreq,
voice_codec.channels,
(voice_codec.rate < 0) ? 0 : voice_codec.rate));
EXPECT_EQ(0, module2->RegisterSendPayload(voice_codec));
voice_codec.rate = test_rate;
EXPECT_EQ(0, rtp_receiver2_->RegisterReceivePayload(
voice_codec.plname,
voice_codec.pltype,
voice_codec.plfreq,
voice_codec.channels,
(voice_codec.rate < 0) ? 0 : voice_codec.rate));
module1->SetSSRC(test_ssrc);
module1->SetStartTimestamp(test_timestamp);
EXPECT_EQ(0, module1->SetSendingStatus(true));
// Prepare for DTMF.
voice_codec.pltype = 97;
voice_codec.plfreq = 8000;
memcpy(voice_codec.plname, "telephone-event", 16);
EXPECT_EQ(0, module1->RegisterSendPayload(voice_codec));
EXPECT_EQ(0, rtp_receiver2_->RegisterReceivePayload(
voice_codec.plname,
voice_codec.pltype,
voice_codec.plfreq,
voice_codec.channels,
(voice_codec.rate < 0) ? 0 : voice_codec.rate));
// Start DTMF test.
uint32_t timeStamp = 160;
// Send a DTMF tone using RFC 2833 (4733).
for (int i = 0; i < 16; i++) {
EXPECT_EQ(0, module1->SendTelephoneEventOutband(i, timeStamp, 10));
}
timeStamp += 160; // Prepare for next packet.
const uint8_t test[9] = "test";
// Send RTP packets for 16 tones a 160 ms 100ms
// pause between = 2560ms + 1600ms = 4160ms
for (; timeStamp <= 250 * 160; timeStamp += 160) {
EXPECT_EQ(0, module1->SendOutgoingData(webrtc::kAudioFrameSpeech, 96,
timeStamp, -1, test, 4));
fake_clock.AdvanceTimeMilliseconds(20);
module1->Process();
}
EXPECT_EQ(0, module1->SendTelephoneEventOutband(32, 9000, 10));
for (; timeStamp <= 740 * 160; timeStamp += 160) {
EXPECT_EQ(0, module1->SendOutgoingData(webrtc::kAudioFrameSpeech, 96,
timeStamp, -1, test, 4));
fake_clock.AdvanceTimeMilliseconds(20);
module1->Process();
}
}
} // namespace
} // namespace webrtc