blob: ae60fd9af1b39dd1d17e8d5bb78deb069207c80b [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;
#define test_rate 64000u
class VerifyingAudioReceiver : public RtpData {
public:
VerifyingAudioReceiver(RtpRtcp* rtpRtcpModule) {}
virtual WebRtc_Word32 OnReceivedPayloadData(
const WebRtc_UWord8* payloadData,
const WebRtc_UWord16 payloadSize,
const webrtc::WebRtcRTPHeader* rtpHeader) {
if (rtpHeader->header.payloadType == 98 ||
rtpHeader->header.payloadType == 99) {
EXPECT_EQ(4, 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;
}
} else if (rtpHeader->type.Audio.channel == 2) {
if (payloadData[0] == 0x0) {
// All our test vectors for payload type 100, 101 and 102 have the
// second channel data being equal to 0x00.
return 0;
}
} else if (rtpHeader->type.Audio.channel == 3) {
// All our test vectors for payload type 100, 101 and 102 have the
// third channel data being equal to 0xaa.
if (payloadData[0] == 0xaa) {
return 0;
}
}
EXPECT_EQ(false, true) << "This code path should never happen.";
return -1;
}
return 0;
}
};
class RTPCallback : public RtpFeedback {
public:
virtual WebRtc_Word32 OnInitializeDecoder(
const WebRtc_Word32 id,
const WebRtc_Word8 payloadType,
const WebRtc_Word8 payloadName[RTP_PAYLOAD_NAME_SIZE],
const int frequency,
const WebRtc_UWord8 channels,
const WebRtc_UWord32 rate) {
if (payloadType == 96) {
EXPECT_EQ(test_rate, rate) <<
"The rate should be 64K for this payloadType";
}
return 0;
}
virtual void OnPacketTimeout(const WebRtc_Word32 id) {
}
virtual void OnReceivedPacket(const WebRtc_Word32 id,
const RtpRtcpPacketType packetType) {
}
virtual void OnPeriodicDeadOrAlive(const WebRtc_Word32 id,
const RTPAliveType alive) {
}
virtual void OnIncomingSSRCChanged(const WebRtc_Word32 id,
const WebRtc_UWord32 SSRC) {
}
virtual void OnIncomingCSRCChanged(const WebRtc_Word32 id,
const WebRtc_UWord32 CSRC,
const bool added) {
}
};
class AudioFeedback : public RtpAudioFeedback {
virtual void OnReceivedTelephoneEvent(const WebRtc_Word32 id,
const WebRtc_UWord8 event,
const bool end) {
static WebRtc_UWord8 expectedEvent = 0;
if (end) {
WebRtc_UWord8 oldEvent = expectedEvent-1;
if (expectedEvent == 32) {
oldEvent = 15;
}
EXPECT_EQ(oldEvent, event);
} else {
EXPECT_EQ(expectedEvent, event);
expectedEvent++;
}
if (expectedEvent == 16) {
expectedEvent = 32;
}
}
virtual void OnPlayTelephoneEvent(const WebRtc_Word32 id,
const WebRtc_UWord8 event,
const WebRtc_UWord16 lengthMs,
const WebRtc_UWord8 volume) {
};
};
class RtpRtcpAudioTest : public ::testing::Test {
protected:
RtpRtcpAudioTest() {
test_CSRC[0] = 1234;
test_CSRC[2] = 2345;
test_id = 123;
test_ssrc = 3456;
test_timestamp = 4567;
test_sequence_number = 2345;
}
~RtpRtcpAudioTest() {}
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());
data_receiver1 = new VerifyingAudioReceiver(module1);
EXPECT_EQ(0, module1->RegisterIncomingDataCallback(data_receiver1));
data_receiver2 = new VerifyingAudioReceiver(module2);
EXPECT_EQ(0, module2->RegisterIncomingDataCallback(data_receiver2));
transport1 = new LoopBackTransport(module2);
EXPECT_EQ(0, module1->RegisterSendTransport(transport1));
transport2 = new LoopBackTransport(module1);
EXPECT_EQ(0, module2->RegisterSendTransport(transport2));
rtp_callback = new RTPCallback();
EXPECT_EQ(0, module2->RegisterIncomingRTPCallback(rtp_callback));
}
virtual void TearDown() {
RtpRtcp::DestroyRtpRtcp(module1);
RtpRtcp::DestroyRtpRtcp(module2);
delete transport1;
delete transport2;
delete data_receiver1;
delete data_receiver2;
delete rtp_callback;
}
int test_id;
RtpRtcp* module1;
RtpRtcp* module2;
VerifyingAudioReceiver* data_receiver1;
VerifyingAudioReceiver* data_receiver2;
LoopBackTransport* transport1;
LoopBackTransport* transport2;
RTPCallback* rtp_callback;
WebRtc_UWord32 test_ssrc;
WebRtc_UWord32 test_timestamp;
WebRtc_UWord16 test_sequence_number;
WebRtc_UWord32 test_CSRC[webrtc::kRtpCsrcSize];
FakeRtpRtcpClock fake_clock;
};
TEST_F(RtpRtcpAudioTest, Basic) {
EXPECT_EQ(0, module1->SetSSRC(test_ssrc));
EXPECT_EQ(0, module1->SetStartTimestamp(test_timestamp));
EXPECT_EQ(false, module1->TelephoneEvent());
// Test detection at the end of a DTMF tone.
EXPECT_EQ(0, module2->SetTelephoneEventStatus(true, true, true));
EXPECT_EQ(true, module2->TelephoneEvent());
EXPECT_EQ(0, module1->SetSendingStatus(true));
// Start basic RTP test.
// Send an empty RTP packet.
// Should fail since we have not registerd the payload type.
EXPECT_EQ(-1, module1->SendOutgoingData(webrtc::kAudioFrameSpeech,
96, 0, NULL, 0));
CodecInst voiceCodec;
voiceCodec.pltype = 96;
voiceCodec.plfreq = 8000;
memcpy(voiceCodec.plname, "PCMU", 5);
EXPECT_EQ(0, module1->RegisterSendPayload(voiceCodec));
EXPECT_EQ(0, module1->RegisterReceivePayload(voiceCodec));
EXPECT_EQ(0, module2->RegisterSendPayload(voiceCodec));
voiceCodec.rate = test_rate;
EXPECT_EQ(0, module2->RegisterReceivePayload(voiceCodec));
printf("4\n");
const WebRtc_UWord8 test[5] = "test";
EXPECT_EQ(0, module1->SendOutgoingData(webrtc::kAudioFrameSpeech, 96,
0, test, 4));
EXPECT_EQ(test_ssrc, module2->RemoteSSRC());
EXPECT_EQ(test_timestamp, module2->RemoteTimestamp());
}
TEST_F(RtpRtcpAudioTest, RED) {
CodecInst voiceCodec;
voiceCodec.pltype = 96;
voiceCodec.plfreq = 8000;
memcpy(voiceCodec.plname, "PCMU", 5);
EXPECT_EQ(0, module1->RegisterSendPayload(voiceCodec));
EXPECT_EQ(0, module1->RegisterReceivePayload(voiceCodec));
EXPECT_EQ(0, module2->RegisterSendPayload(voiceCodec));
voiceCodec.rate = test_rate;
EXPECT_EQ(0, module2->RegisterReceivePayload(voiceCodec));
EXPECT_EQ(0, module1->SetSSRC(test_ssrc));
EXPECT_EQ(0, module1->SetStartTimestamp(test_timestamp));
EXPECT_EQ(0, module1->SetSendingStatus(true));
voiceCodec.pltype = 127;
voiceCodec.plfreq = 8000;
memcpy(voiceCodec.plname, "RED", 4);
EXPECT_EQ(0, module1->SetSendREDPayloadType(voiceCodec.pltype));
WebRtc_Word8 red = 0;
EXPECT_EQ(0, module1->SendREDPayloadType(red));
EXPECT_EQ(voiceCodec.pltype, red);
EXPECT_EQ(0, module1->RegisterReceivePayload(voiceCodec));
EXPECT_EQ(0, module2->RegisterReceivePayload(voiceCodec));
RTPFragmentationHeader fragmentation;
fragmentation.fragmentationVectorSize = 2;
fragmentation.fragmentationLength = new WebRtc_UWord32[2];
fragmentation.fragmentationLength[0] = 4;
fragmentation.fragmentationLength[1] = 4;
fragmentation.fragmentationOffset = new WebRtc_UWord32[2];
fragmentation.fragmentationOffset[0] = 0;
fragmentation.fragmentationOffset[1] = 4;
fragmentation.fragmentationTimeDiff = new WebRtc_UWord16[2];
fragmentation.fragmentationTimeDiff[0] = 0;
fragmentation.fragmentationTimeDiff[1] = 0;
fragmentation.fragmentationPlType = new WebRtc_UWord8[2];
fragmentation.fragmentationPlType[0] = 96;
fragmentation.fragmentationPlType[1] = 96;
const WebRtc_UWord8 test[5] = "test";
// Send a RTP packet.
EXPECT_EQ(0, module1->SendOutgoingData(webrtc::kAudioFrameSpeech,
96, 160, test, 4,
&fragmentation));
EXPECT_EQ(0, module1->SetSendREDPayloadType(-1));
EXPECT_EQ(-1, module1->SendREDPayloadType(red));
}
TEST_F(RtpRtcpAudioTest, DTMF) {
CodecInst voiceCodec;
voiceCodec.pltype = 96;
voiceCodec.plfreq = 8000;
memcpy(voiceCodec.plname, "PCMU", 5);
EXPECT_EQ(0, module1->RegisterSendPayload(voiceCodec));
EXPECT_EQ(0, module1->RegisterReceivePayload(voiceCodec));
EXPECT_EQ(0, module2->RegisterSendPayload(voiceCodec));
voiceCodec.rate = test_rate;
EXPECT_EQ(0, module2->RegisterReceivePayload(voiceCodec));
EXPECT_EQ(0, module1->SetSSRC(test_ssrc));
EXPECT_EQ(0, module1->SetStartTimestamp(test_timestamp));
EXPECT_EQ(0, module1->SetSendingStatus(true));
AudioFeedback* audioFeedback = new AudioFeedback();
EXPECT_EQ(0, module2->RegisterAudioCallback(audioFeedback));
// Prepare for DTMF.
voiceCodec.pltype = 97;
voiceCodec.plfreq = 8000;
memcpy(voiceCodec.plname, "telephone-event", 16);
EXPECT_EQ(0, module1->RegisterSendPayload(voiceCodec));
EXPECT_EQ(0, module2->RegisterReceivePayload(voiceCodec));
// Start DTMF test.
WebRtc_UWord32 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 WebRtc_UWord8 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, test, 4));
fake_clock.IncrementTime(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, test, 4));
fake_clock.IncrementTime(20);
module1->Process();
}
delete audioFeedback;
}
TEST_F(RtpRtcpAudioTest, Stereo) {
CodecInst voiceCodec;
voiceCodec.pltype = 96;
voiceCodec.plfreq = 8000;
memcpy(voiceCodec.plname, "PCMU", 5);
EXPECT_EQ(0, module1->RegisterSendPayload(voiceCodec));
EXPECT_EQ(0, module1->RegisterReceivePayload(voiceCodec));
EXPECT_EQ(0, module2->RegisterSendPayload(voiceCodec));
voiceCodec.rate = test_rate;
EXPECT_EQ(0, module2->RegisterReceivePayload(voiceCodec));
EXPECT_EQ(0, module1->SetSSRC(test_ssrc));
EXPECT_EQ(0, module1->SetStartTimestamp(test_timestamp));
EXPECT_EQ(0, module1->SetSendingStatus(true));
// Prepare for 3 channel audio 8 bits per sample.
voiceCodec.pltype = 98;
voiceCodec.channels = 3;
memcpy(voiceCodec.plname, "PCMA", 5);
EXPECT_EQ(0, module1->RegisterSendPayload(voiceCodec));
EXPECT_EQ(0, module2->RegisterReceivePayload(voiceCodec));
// Prepare for 3 channel audio 16 bits per sample.
voiceCodec.pltype = 99;
memcpy(voiceCodec.plname, "L16", 4);
EXPECT_EQ(0, module1->RegisterSendPayload(voiceCodec));
EXPECT_EQ(0, module2->RegisterReceivePayload(voiceCodec));
// Prepare for 3 channel audio 5 bits per sample.
voiceCodec.pltype = 100;
memcpy(voiceCodec.plname, "G726-40",8);
EXPECT_EQ(0, module1->RegisterSendPayload(voiceCodec));
EXPECT_EQ(0, module2->RegisterReceivePayload(voiceCodec));
// Prepare for 3 channel audio 3 bits per sample.
voiceCodec.pltype = 101;
memcpy(voiceCodec.plname, "G726-24",8);
EXPECT_EQ(0, module1->RegisterSendPayload(voiceCodec));
EXPECT_EQ(0, module2->RegisterReceivePayload(voiceCodec));
// Prepare for 3 channel audio 2 bits per sample.
voiceCodec.pltype = 102;
memcpy(voiceCodec.plname, "G726-16",8);
EXPECT_EQ(0, module1->RegisterSendPayload(voiceCodec));
EXPECT_EQ(0, module2->RegisterReceivePayload(voiceCodec));
// Test sample based multi channel codec, 3 channels 8 bits.
WebRtc_UWord8 test3channels[15] = "ttteeesssttt";
WebRtc_UWord32 timeStamp = 160;
EXPECT_EQ(0, module1->SendOutgoingData(webrtc::kAudioFrameSpeech, 98,
timeStamp, test3channels, 12));
fake_clock.IncrementTime(20);
module1->Process();
timeStamp += 160; // Prepare for next packet.
// Test sample based multi channel codec, 3 channels 16 bits.
const WebRtc_UWord8 test3channels16[13] = "teteteststst";
EXPECT_EQ(0, module1->SendOutgoingData(webrtc::kAudioFrameSpeech, 99,
timeStamp, test3channels16, 12));
fake_clock.IncrementTime(20);
module1->Process();
timeStamp += 160; // Prepare for next packet.
// Test sample based multi channel codec, 3 channels 5 bits.
test3channels[0] = 0xf8; // 5 ones 3 zeros.
test3channels[1] = 0x2b; // 2 zeros 5 10 1 one.
test3channels[2] = 0xf0; // 4 ones 4 zeros.
test3channels[3] = 0x2b; // 1 zero 5 01 2 ones.
test3channels[4] = 0xe0; // 3 ones 5 zeros.
test3channels[5] = 0x0;
test3channels[6] = 0x0;
test3channels[7] = 0x0;
test3channels[8] = 0x0;
test3channels[9] = 0x0;
test3channels[10] = 0x0;
test3channels[11] = 0x0;
test3channels[12] = 0x0;
test3channels[13] = 0x0;
test3channels[14] = 0x0;
EXPECT_EQ(0, module1->SendOutgoingData(webrtc::kAudioFrameSpeech, 100,
timeStamp, test3channels, 15));
fake_clock.IncrementTime(20);
module1->Process();
timeStamp += 160; // Prepare for next packet.
// Test sample based multi channel codec, 3 channels 3 bits.
test3channels[0] = 0xe2; // 3 ones 3 zeros 2 10
test3channels[1] = 0xf0; // 1 1 3 ones 3 zeros 1 0
test3channels[2] = 0xb8; // 2 10 3 ones 3 zeros
test3channels[3] = 0xa0; // 3 101 5 zeros
test3channels[4] = 0x0;
EXPECT_EQ(0, module1->SendOutgoingData(webrtc::kAudioFrameSpeech, 101,
timeStamp, test3channels, 15));
fake_clock.IncrementTime(20);
module1->Process();
timeStamp += 160; // Prepare for next packet.
// Test sample based multi channel codec, 3 channels 2 bits.
test3channels[0] = 0xcb; // 2 ones 2 zeros 2 10 2 ones
test3channels[1] = 0x2c; // 2 zeros 2 10 2 ones 2 zeros
test3channels[2] = 0xb2; // 2 10 2 ones 2 zeros 2 10
test3channels[3] = 0xcb; // 2 ones 2 zeros 2 10 2 ones
test3channels[4] = 0x2c; // 2 zeros 2 10 2 ones 2 zeros
EXPECT_EQ(0, module1->SendOutgoingData(webrtc::kAudioFrameSpeech, 102,
timeStamp, test3channels, 15));
}