blob: df9578cc4f8993b31b18d719883fff2f24d78a01 [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 <stdio.h>
#include <string.h>
#include <vector>
#include "critical_section_wrapper.h"
#include "event_wrapper.h"
#include "thread_wrapper.h"
#include "voe_extended_test.h"
#include "../../source/voice_engine_defines.h" // defines build macros
#include "system_wrappers/interface/ref_count.h"
#if defined(_WIN32)
#include <conio.h>
#include <winsock2.h>
#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
#include <netdb.h>
#endif
using namespace webrtc;
namespace voetest {
// Set this flag to ensure that test packets are transmitted to
// RemoteIP::RemotePort during tests of SetSendToS and SetSendGQos. Requires
// receiver at the remote side and Wireshark with a proper ip.src filter.
#define _SEND_TO_REMOTE_IP_
#ifdef _SEND_TO_REMOTE_IP_
const int RemotePort = 12345; // transmit to this UDP port
const char* RemoteIP = "192.168.200.1"; // transmit to this IP address
#endif
#ifdef MAC_IPHONE
#define SLEEP_IF_IPHONE(x) SLEEP(x)
#else
#define SLEEP_IF_IPHONE(x)
#endif
#ifdef WEBRTC_ANDROID
// Global pointers
extern void* globalJavaVM;
extern void* globalContext;
#endif
extern char* GetFilename(char* filename);
extern const char* GetFilename(const char* filename);
extern int GetResource(char* resource, char* dest, int destLen);
extern char* GetResource(char* resource);
extern const char* GetResource(const char* resource);
// ----------------------------------------------------------------------------
// External AudioDeviceModule implementation
// ----------------------------------------------------------------------------
// static
AudioDeviceModuleImpl* AudioDeviceModuleImpl::Create() {
AudioDeviceModuleImpl* xADM = new AudioDeviceModuleImpl();
if (xADM)
xADM->AddRef();
return xADM;
}
// static
bool AudioDeviceModuleImpl::Destroy(AudioDeviceModuleImpl* adm) {
if (!adm)
return false;
int32_t count = adm->Release();
if (count != 0) {
return false;
} else {
delete adm;
return true;
}
}
AudioDeviceModuleImpl::AudioDeviceModuleImpl() :
_ref_count(0) {
}
AudioDeviceModuleImpl::~AudioDeviceModuleImpl() {
}
int32_t AudioDeviceModuleImpl::AddRef() {
return ++_ref_count;
}
int32_t AudioDeviceModuleImpl::Release() {
// Avoid self destruction in this mock implementation.
// Ensures that we can always check the reference counter while alive.
return --_ref_count;
}
// ----------------------------------------------------------------------------
// External transport (Transport) implementations:
// ----------------------------------------------------------------------------
ExtendedTestTransport::ExtendedTestTransport(VoENetwork* ptr) :
myNetw(ptr), _thread(NULL), _lock(NULL), _event(NULL), _length(0), _channel(0) {
const char* threadName = "voe_extended_test_external_thread";
_lock = CriticalSectionWrapper::CreateCriticalSection();
_event = EventWrapper::Create();
_thread = ThreadWrapper::CreateThread(Run, this, kHighPriority, threadName);
if (_thread) {
unsigned int id;
_thread->Start(id);
}
}
ExtendedTestTransport::~ExtendedTestTransport() {
if (_thread) {
_thread->SetNotAlive();
_event->Set();
if (_thread->Stop()) {
delete _thread;
_thread = NULL;
delete _event;
_event = NULL;
delete _lock;
_lock = NULL;
}
}
}
bool ExtendedTestTransport::Run(void* ptr) {
return static_cast<ExtendedTestTransport*> (ptr)->Process();
}
bool ExtendedTestTransport::Process() {
switch (_event->Wait(500)) {
case kEventSignaled:
_lock->Enter();
myNetw->ReceivedRTPPacket(_channel, _packetBuffer, _length);
_lock->Leave();
return true;
case kEventTimeout:
return true;
case kEventError:
break;
}
return true;
}
int ExtendedTestTransport::SendPacket(int channel, const void *data, int len) {
_lock->Enter();
if (len < 1612) {
memcpy(_packetBuffer, (const unsigned char*) data, len);
_length = len;
_channel = channel;
}
_lock->Leave();
_event->Set(); // triggers ReceivedRTPPacket() from worker thread
return len;
}
int ExtendedTestTransport::SendRTCPPacket(int channel, const void *data, int len) {
myNetw->ReceivedRTCPPacket(channel, data, len);
return len;
}
XTransport::XTransport(VoENetwork* netw, VoEFile* file) :
_netw(netw), _file(file) {
}
int XTransport::SendPacket(int channel, const void *data, int len) {
// loopback
// _netw->ReceivedRTPPacket(channel, data, len);
return 0;
}
int XTransport::SendRTCPPacket(int, const void *, int) {
return 0;
}
// ----------------------------------------------------------------------------
// VoERTPObserver
// ----------------------------------------------------------------------------
XRTPObserver::XRTPObserver() :
_SSRC(0) {
}
XRTPObserver::~XRTPObserver() {
}
void XRTPObserver::OnIncomingCSRCChanged(const int /*channel*/, const unsigned int /*CSRC*/,
const bool /*added*/) {
}
void XRTPObserver::OnIncomingSSRCChanged(const int /*channel*/, const unsigned int SSRC) {
// char msg[128];
// sprintf(msg, "OnIncomingSSRCChanged(channel=%d, SSRC=%lu)\n",
// channel, SSRC);
// TEST_LOG(msg);
_SSRC = SSRC; // skip channel dependency for simplicty
}
// ----------------------------------------------------------------------------
// VoEExtendedTest
// ----------------------------------------------------------------------------
int VoEExtendedTest::PrepareTest(const char* str) const {
TEST_LOG("\n\n================================================\n");
TEST_LOG("\tExtended *%s* Test\n", str);
TEST_LOG("================================================\n\n");
return 0;
}
int VoEExtendedTest::TestPassed(const char* str) const {
TEST_LOG("\n\n------------------------------------------------\n");
TEST_LOG("\tExtended *%s* test passed!\n", str);
TEST_LOG("------------------------------------------------\n\n");
return 0;
}
void VoEExtendedTest::OnPeriodicDeadOrAlive(const int /*channel*/, const bool alive) {
_alive = alive;
if (alive) {
TEST_LOG("=> ALIVE ");
} else {
TEST_LOG("=> DEAD ");
}
fflush(NULL);
}
void VoEExtendedTest::CallbackOnError(const int errCode, int) {
_errCode = errCode;
TEST_LOG("\n************************\n");
TEST_LOG(" RUNTIME ERROR: %d \n", errCode);
TEST_LOG("************************\n");
}
VoEExtendedTest::VoEExtendedTest(VoETestManager& mgr) :
_mgr(mgr) {
for (int i = 0; i < 32; i++) {
_listening[i] = false;
_playing[i] = false;
_sending[i] = false;
}
}
VoEExtendedTest::~VoEExtendedTest() {
}
void VoEExtendedTest::StartMedia(int channel, int rtpPort, bool listen,
bool playout, bool send) {
VoEBase* voe_base_ = _mgr.BasePtr();
_listening[channel] = false;
_playing[channel] = false;
_sending[channel] = false;
voe_base_->SetLocalReceiver(channel, rtpPort);
voe_base_->SetSendDestination(channel, rtpPort, "127.0.0.1");
if (listen) {
_listening[channel] = true;
voe_base_->StartReceive(channel);
}
if (playout) {
_playing[channel] = true;
voe_base_->StartPlayout(channel);
}
if (send) {
_sending[channel] = true;
voe_base_->StartSend(channel);
}
}
void VoEExtendedTest::StopMedia(int channel) {
VoEBase* voe_base_ = _mgr.BasePtr();
if (_listening[channel]) {
_listening[channel] = false;
voe_base_->StopReceive(channel);
}
if (_playing[channel]) {
_playing[channel] = false;
voe_base_->StopPlayout(channel);
}
if (_sending[channel]) {
_sending[channel] = false;
voe_base_->StopSend(channel);
}
}
void VoEExtendedTest::Play(int channel, unsigned int timeMillisec, bool addFileAsMicrophone,
bool addTimeMarker) {
VoEBase* voe_base_ = _mgr.BasePtr();
VoEFile* file = _mgr.FilePtr();
voe_base_->StartPlayout(channel);
TEST_LOG("[playing]");
fflush(NULL);
if (addFileAsMicrophone) {
file->StartPlayingFileAsMicrophone(channel, _mgr.AudioFilename(), true, true);
TEST_LOG("[file as mic]");
fflush(NULL);
}
if (addTimeMarker) {
float dtSec = (float) ((float) timeMillisec / 1000.0);
TEST_LOG("[dT=%.1f]", dtSec);
fflush(NULL); // print sleep time in seconds
}
SLEEP(timeMillisec);
voe_base_->StopPlayout(channel);
file->StopPlayingFileAsMicrophone(channel);
}
void VoEExtendedTest::Sleep(unsigned int timeMillisec, bool addMarker) {
if (addMarker) {
float dtSec = (float) ((float) timeMillisec / 1000.0);
TEST_LOG("[dT=%.1f]", dtSec); // print sleep time in seconds
}
::Sleep(timeMillisec);
}
int VoEExtendedTest::TestBase() {
#ifndef _WIN32
// Sleep a bit instead when pause not supported
#undef PAUSE
#define PAUSE SLEEP(2000);
#endif
PrepareTest("Base");
// TODO(qhogpat): make this an actual instance variable. I think the
// macro black magic will make more sense then. This is named like an
// instance variable since it is required in order to appease the
// gods of darkness.
VoEBase* voe_base_ = _mgr.BasePtr();
VoENetwork* netw = _mgr.NetworkPtr();
#ifdef _TEST_RTP_RTCP_
VoERTP_RTCP* rtp = _mgr.RTP_RTCPPtr();
#endif
//////////////////////////
// SetTraceFileName
#ifdef _USE_EXTENDED_TRACE_
TEST(SetTraceFileName - SetDebugTraceFileName); ANL();
TEST_MUSTPASS(VoiceEngine::SetTraceFile(NULL)); MARK();
// don't use these files
TEST_MUSTPASS(VoiceEngine::SetTraceFile(GetFilename(""
"VoEBase_trace_dont_use.txt"))); MARK();
// use these instead
TEST_MUSTPASS(VoiceEngine::SetTraceFile(GetFilename(""
"VoEBase_trace.txt"))); MARK();
TEST_MUSTPASS(VoiceEngine::SetTraceFilter(kTraceStream |
kTraceStateInfo |
kTraceWarning |
kTraceError |
kTraceCritical |
kTraceApiCall |
kTraceMemory |
kTraceInfo)); MARK();
ANL(); AOK(); ANL(); ANL();
#endif
///////////////////////////////////////
// RegisterVoiceEngineObserver
// DeRegisterVoiceEngineObserver
TEST(SetObserver);
ANL();
TEST_MUSTPASS(voe_base_->RegisterVoiceEngineObserver(*this));
MARK();
SLEEP(100);
TEST_MUSTPASS(voe_base_->DeRegisterVoiceEngineObserver());
MARK();
ANL();
AOK();
ANL();
ANL();
/////////////////////
// GetVersion
TEST(GetVersion);
ANL();
char version[1024];
// audio device module and AudioProcessing fail to getversion when they
// are not initiliazed
TEST_MUSTPASS(voe_base_->GetVersion(version));
MARK();
TEST_LOG("\n-----\n%s\n-----\n", version);
ANL();
AOK();
ANL();
ANL();
///////////////
// Init
TEST(Init);
ANL();
TEST_MUSTPASS(voe_base_->Init());
MARK();
TEST_MUSTPASS(voe_base_->Terminate());
TEST_MUSTPASS(voe_base_->Init());
MARK();
// ensure that no new memory is allocated at the second call (check
// trace file)
TEST_MUSTPASS(voe_base_->Init());
MARK();
TEST_MUSTPASS(voe_base_->Terminate());
#if (!defined(MAC_IPHONE) && !defined(WEBRTC_ANDROID))
// verify AEC recording
TEST_MUSTPASS(voe_base_->Init());
MARK(); // verify output dat-files
TEST_MUSTPASS(voe_base_->Terminate());
#endif
ANL();
AOK();
ANL();
ANL();
////////////////////
// Terminate
TEST(Terminate);
ANL();
TEST_MUSTPASS(voe_base_->Terminate());
MARK(); // should be ignored
TEST_MUSTPASS(voe_base_->Init());
TEST_MUSTPASS(voe_base_->Terminate());
MARK(); // should terminate
ANL();
AOK();
ANL();
ANL();
// ------------------------------------------------------------------------
// >> Init(AudioDeviceModule)
//
// Note that our mock implementation of the ADM also mocks the
// reference counting part. This approach enables us to keep track
// of the internal reference counter without checking return values
// from the ADM and we also avoid the built-in self destruction.
//
// TODO(henrika): this test does not verify that external ADM methods
// are called by the VoiceEngine once registered. We could extend
// the mock implementation and add counters for each ADM API to ensure
// that they are called in the correct sequence and the correct number
// of times.
TEST_LOG("\nTesting: Init in combination with an external ADM\n");
// Create the ADM and call AddRef within the factory method.
AudioDeviceModuleImpl* xADM = AudioDeviceModuleImpl::Create();
ASSERT_FALSE(xADM == NULL);
ASSERT_TRUE(xADM->ReferenceCounter() == 1);
// Verify default usage case for external ADM.
TEST_MUSTPASS(voe_base_->Init(xADM));MARK();
ASSERT_TRUE(xADM->ReferenceCounter() == 2);
TEST_MUSTPASS(voe_base_->Terminate());
ASSERT_TRUE(xADM->ReferenceCounter() == 1);
// Our reference-count implementation does not self destruct.
// We do it manually here instead by calling Release followed by delete.
ASSERT_TRUE(AudioDeviceModuleImpl::Destroy(xADM));
ANL();
AOK();ANL();
// >> end of Init(AudioDeviceModule)
// ------------------------------------------------------------------------
///////////////////////////
// MaxNumOfChannels
TEST(MaxNumOfChannels);
ANL();
TEST_MUSTPASS(voe_base_->MaxNumOfChannels() < 0);
MARK();
ANL();
AOK();
ANL();
ANL();
////////////////////////
// CreateChannel
// DeleteChannel
int i;
int channel;
int nChannels(voe_base_->MaxNumOfChannels());
TEST(CreateChannel);
ANL();
TEST(DeleteChannel);
ANL();
TEST_MUSTPASS(voe_base_->Init());
channel = voe_base_->CreateChannel();
MARK();
TEST_MUSTPASS(channel != 0);
channel = voe_base_->CreateChannel();
MARK();
TEST_MUSTPASS(channel != 1);
TEST_MUSTPASS(voe_base_->DeleteChannel(0));
MARK();
TEST_MUSTPASS(voe_base_->DeleteChannel(1));
MARK();
// create and delete one channel many times
for (i = 0; i < 10; i++) {
channel = voe_base_->CreateChannel();
MARK();
TEST_MUSTPASS(channel != 0); // should be 0 each time
TEST_MUSTPASS(voe_base_->DeleteChannel(channel));
MARK();
}
// create max number of channels
for (i = 0; i < nChannels; i++) {
channel = voe_base_->CreateChannel();
MARK();
TEST_MUSTPASS(channel != i);
}
channel = voe_base_->CreateChannel();
MARK(); // should fail since no more channels can now be created
TEST_MUSTPASS(channel != -1);
int aChannel = (((nChannels - 17) > 0) ? (nChannels - 17) : 0);
TEST_MUSTPASS(voe_base_->DeleteChannel(aChannel));
MARK();
channel = voe_base_->CreateChannel();
MARK(); // should reuse channel
TEST_MUSTPASS(channel != aChannel);
// delete all created channels
for (i = 0; i < nChannels; i++) {
TEST_MUSTPASS(voe_base_->DeleteChannel(i));
MARK();
}
// try to delete a non-existing channel
TEST_MUSTPASS(-1 != voe_base_->DeleteChannel(aChannel));
MARK();
TEST_ERROR(VE_CHANNEL_NOT_VALID);
ANL();
AOK();
ANL();
ANL();
// ------------------------------------------------------------------------
// >> SetLocalReceiver
//
// State: VE not initialized, no existing channels
TEST_MUSTPASS(voe_base_->Init());
int ch;
TEST(SetLocalReceiver);
ANL();
// no channel created yet => should fail
TEST_MUSTPASS(!voe_base_->SetLocalReceiver(0, 100));
MARK();
TEST_ERROR(VE_CHANNEL_NOT_VALID);
ch = voe_base_->CreateChannel();
#ifdef MAC_IPHONE
printf("\nNOTE: Local IP must be set in source code (line %d) \n",
__LINE__ + 1);
char* localIp = "127.0.0.1";
#else
char localIp[64] = { 0 };
TEST_MUSTPASS(netw->GetLocalIP(localIp));
MARK();
// NOTE: This API is supported on Win, Mac and Linux and may fail or not
// return local IP for other platforms.
#endif
// trivial invalid function calls
TEST_MUSTPASS(!voe_base_->SetLocalReceiver(ch+1, 12345));
MARK();
TEST_ERROR(VE_CHANNEL_NOT_VALID);
TEST_MUSTPASS(!voe_base_->SetLocalReceiver(ch, -1));
MARK();
TEST_ERROR(VE_INVALID_PORT_NMBR);
// check conflict with ongoing receiving
TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 12345));
MARK();
TEST_MUSTPASS(voe_base_->StartReceive(ch));
TEST_MUSTPASS(!voe_base_->SetLocalReceiver(ch, 12345));
MARK();
TEST_ERROR(VE_ALREADY_LISTENING);
TEST_MUSTPASS(voe_base_->StopReceive(ch));
// check conflict with ongoing transmission
TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 12345, "127.0.0.1"));
TEST_MUSTPASS(voe_base_->StartSend(ch));
TEST_MUSTPASS(!voe_base_->SetLocalReceiver(ch, 12345));
MARK();
TEST_ERROR(VE_ALREADY_SENDING);
TEST_MUSTPASS(voe_base_->StopSend(ch));
// valid function calls
// Need to sleep between, otherwise it may fail for unknown reason
TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 12345));
MARK();
SLEEP(100);
TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 12345));
MARK();
SLEEP(100);
TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 12345, kVoEDefault, localIp));
MARK();
SLEEP(100);
TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 12345, kVoEDefault, NULL,
"230.1.2.3"));
MARK();
SLEEP(100);
TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 12345, kVoEDefault, localIp,
"230.1.2.3"));
MARK();
SLEEP(100);
TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 12345, 5555, NULL));
MARK();
SLEEP(100);
TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 12345));
MARK();
SLEEP(100);
// STATE: no media but sockets exists and are binded to 12345 and 12346
// respectively
// Add some dynamic tests as well:
// ensure that last setting is used (cancels old settings)
TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 12345));
MARK();
SLEEP(100);
TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 44444));
MARK();
SLEEP(100);
TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 54321));
MARK();
TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 54321, "127.0.0.1"));
TEST_MUSTPASS(voe_base_->StartReceive(ch));
TEST_MUSTPASS(voe_base_->StartSend(ch));
Play(ch, 1000, true, true);
TEST_MUSTPASS(voe_base_->StopSend(ch));
TEST_MUSTPASS(voe_base_->StopReceive(ch));
TEST_MUSTPASS(voe_base_->DeleteChannel(ch));
ANL();
AOK();
ANL();
ANL();
// >> end of SetLocalReceiver
// ------------------------------------------------------------------------
// ------------------------------------------------------------------------
// >> GetLocalReceiver
//
// State: VE initialized, no existing channels
TEST(GetLocalReceiver);
ANL();
int port;
char ipaddr[64];
int RTCPport;
ch = voe_base_->CreateChannel();
// verify non-configured (blank) local receiver
TEST_MUSTPASS(voe_base_->GetLocalReceiver(ch, port, RTCPport, ipaddr));
MARK();
TEST_MUSTPASS(port != 0);
TEST_MUSTPASS(RTCPport != 0);
TEST_MUSTPASS(strcmp(ipaddr, "") != 0);
// check some trivial set/get combinations
TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 12345))
TEST_MUSTPASS(voe_base_->GetLocalReceiver(ch, port, RTCPport, ipaddr));
MARK();
TEST_MUSTPASS(port != 12345);
TEST_MUSTPASS(RTCPport != 12346);
TEST_MUSTPASS(strcmp(ipaddr, "0.0.0.0") != 0); // now binded to "any" IP
TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 12345, 55555))
TEST_MUSTPASS(voe_base_->GetLocalReceiver(ch, port, RTCPport, ipaddr));
MARK();
TEST_MUSTPASS(port != 12345);
TEST_MUSTPASS(RTCPport != 55555);
TEST_MUSTPASS(strcmp(ipaddr, "0.0.0.0") != 0);
TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 12345, kVoEDefault, localIp))
TEST_MUSTPASS(voe_base_->GetLocalReceiver(ch, port, RTCPport, ipaddr));
MARK();
TEST_MUSTPASS(port != 12345);
TEST_MUSTPASS(RTCPport != 12346);
TEST_MUSTPASS(strcmp(ipaddr, localIp) != 0);
TEST_MUSTPASS(voe_base_->DeleteChannel(ch));
ANL();
AOK();
ANL();
ANL();
// >> end of GetLocalReceiver
// ------------------------------------------------------------------------
// ------------------------------------------------------------------------
// >> SetSendDestination
//
// State: VE initialized, no existing channels
TEST(SetSendDestination);
ANL();
// call without existing channel
TEST_MUSTPASS(!voe_base_->SetSendDestination(0, 12345, "127.0.0.1"));
MARK();
TEST_ERROR(VE_CHANNEL_NOT_VALID);
ch = voe_base_->CreateChannel();
// trivial fail tests
TEST_MUSTPASS(!voe_base_->SetSendDestination(ch, 65536, "127.0.0.1"));
MARK();
TEST_ERROR(VE_INVALID_PORT_NMBR); // invalid RTP port
TEST_MUSTPASS(!voe_base_->SetSendDestination(ch, 12345, "127.0.0.1", 65536));
MARK();
TEST_ERROR(VE_INVALID_PORT_NMBR); // invalid source port
TEST_MUSTPASS(!voe_base_->SetSendDestination(ch, 12345, "127.0.0.1", kVoEDefault,
65536));
MARK();
TEST_ERROR(VE_INVALID_PORT_NMBR); // invalid RTCP port
TEST_MUSTPASS(!voe_base_->SetSendDestination(ch, 12345, "127.0.0.300"));
MARK();
TEST_ERROR(VE_INVALID_IP_ADDRESS); // invalid IP address
// sockets must be created first to support multi-cast (not required
// otherwise)
TEST_MUSTPASS(!voe_base_->SetSendDestination(ch, 55555, "230.0.0.1"));
MARK();
TEST_ERROR(VE_SOCKET_ERROR);
TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 55555)); // create sockets
TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 55555, "230.0.0.1"));
MARK(); // should work now
voe_base_->DeleteChannel(0);
ch = voe_base_->CreateChannel();
// STATE: one channel created, no sockets exist
// valid function calls
TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 33333, "127.0.0.1"));
MARK();
TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 33333, "127.0.0.1", 44444));
MARK();
TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 33333, "127.0.0.1", kVoEDefault,
55555));
MARK();
TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 33333, "127.0.0.1", 44444,
55555));
MARK();
voe_base_->DeleteChannel(0);
ch = voe_base_->CreateChannel();
// create receive sockets first and then an extra pair of send sockets
TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 44444));
TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 44444, "127.0.0.1", 11111));
MARK(); // binds to 11111
TEST_MUSTPASS(voe_base_->DeleteChannel(ch));
ANL();
AOK();
ANL();
ANL();
// >> end of SetSendDestination
// ------------------------------------------------------------------------
// ------------------------------------------------------------------------
// >> GetSendDestination
//
// State: VE initialized, no existing channels
TEST(GetSendDestination);
ANL();
int sourcePort;
ch = voe_base_->CreateChannel();
// verify non-configured (blank) local receiver
TEST_MUSTPASS(voe_base_->GetSendDestination(ch, port, ipaddr, sourcePort,
RTCPport));
MARK();
TEST_MUSTPASS(port != 0);
TEST_MUSTPASS(sourcePort != 0);
TEST_MUSTPASS(RTCPport != 0);
TEST_MUSTPASS(strcmp(ipaddr, "") != 0);
// check some trivial set/get combinations
TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 44444, "127.0.0.1"));
TEST_MUSTPASS(voe_base_->GetSendDestination(ch, port, ipaddr, sourcePort,
RTCPport));
MARK();
TEST_MUSTPASS(port != 44444);
TEST_MUSTPASS(sourcePort != 0); // should be 0 since no local receiver has
// NOT been defined yet
TEST_MUSTPASS(RTCPport != 44445);
TEST_MUSTPASS(strcmp(ipaddr, "127.0.0.1") != 0);
TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 55555));
TEST_MUSTPASS(voe_base_->GetSendDestination(ch, port, ipaddr, sourcePort,
RTCPport));
MARK();
TEST_MUSTPASS(port != 44444);
TEST_MUSTPASS(sourcePort != 55555); // should be equal to local port
TEST_MUSTPASS(RTCPport != 44445);
TEST_MUSTPASS(strcmp(ipaddr, "127.0.0.1") != 0);
voe_base_->DeleteChannel(0);
ch = voe_base_->CreateChannel();
TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 44444, "127.0.0.1"));
// NULL as IP-address input should work as well
TEST_MUSTPASS(voe_base_->GetSendDestination(ch, port, NULL, sourcePort,
RTCPport));
MARK();
TEST_MUSTPASS(port != 44444);
TEST_MUSTPASS(sourcePort != 0);
TEST_MUSTPASS(RTCPport != 44445);
TEST_MUSTPASS(voe_base_->DeleteChannel(ch));
ANL();
AOK();
ANL();
ANL();
// >> end of GetLocalReceiver
// ------------------------------------------------------------------------
// ------------------------------------------------------------------------
// >> StartReceive
// >> StopReceive
//
// State: VE initialized, no existing channels
TEST(StartReceive);
ANL();
TEST(StopReceive);
ANL();
// call without existing channel
TEST_MUSTPASS(!voe_base_->StartReceive(0));
MARK();
TEST_ERROR(VE_CHANNEL_NOT_VALID);
TEST_MUSTPASS(!voe_base_->StopReceive(0));
MARK();
TEST_ERROR(VE_CHANNEL_NOT_VALID);
ch = voe_base_->CreateChannel();
// sockets must be created first
TEST_MUSTPASS(!voe_base_->StartReceive(0));
MARK();
TEST_ERROR(VE_SOCKETS_NOT_INITED);
TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 55555));
TEST_MUSTPASS(voe_base_->StartReceive(0));
MARK(); // should work this time
// enable again (should work)
TEST_MUSTPASS(voe_base_->StartReceive(0));
MARK();
// Stop/Start (should work)
TEST_MUSTPASS(voe_base_->StopReceive(0));
MARK();
TEST_MUSTPASS(voe_base_->StartReceive(0));
MARK();
// Verify in loopback
TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 55555, "127.0.0.1"));
TEST_MUSTPASS(voe_base_->StartSend(ch));
Play(ch, 1000, true, true);
TEST_MUSTPASS(voe_base_->StopSend(ch));
TEST_MUSTPASS(voe_base_->StopReceive(0));
MARK();
voe_base_->DeleteChannel(0);
ch = voe_base_->CreateChannel();
// Ensure that it is OK to add delay between SetLocalReceiver and StarListen
TEST_LOG("\nspeak after 2 seconds and ensure that no delay is added:\n");
TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 55555));
Sleep(2000, true); // adding emulated delay here
TEST_MUSTPASS(voe_base_->StartReceive(0));
TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 55555, "127.0.0.1"));
TEST_MUSTPASS(voe_base_->StartSend(ch));
Play(ch, 2000, true, true);
TEST_MUSTPASS(voe_base_->StopSend(ch));
TEST_MUSTPASS(voe_base_->StopReceive(0));
TEST_MUSTPASS(voe_base_->DeleteChannel(ch));
ANL();
// Multi-channel tests
for (i = 0; i < voe_base_->MaxNumOfChannels(); i++) {
ch = voe_base_->CreateChannel();
TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 11111+2*i));
TEST_MUSTPASS(voe_base_->StartReceive(ch));
MARK();
}
for (i = 0; i < voe_base_->MaxNumOfChannels(); i++) {
TEST_MUSTPASS(voe_base_->StopReceive(i));
MARK();
voe_base_->DeleteChannel(i);
}
for (i = 0; i < voe_base_->MaxNumOfChannels(); i++) {
ch = voe_base_->CreateChannel();
TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 11111+2*i));
TEST_MUSTPASS(voe_base_->StartReceive(ch));
MARK();
TEST_MUSTPASS(voe_base_->StopReceive(ch));
MARK();
voe_base_->DeleteChannel(ch);
}
ANL();
AOK();
ANL();
ANL();
// >> end of StartReceive/StopReceive
// ------------------------------------------------------------------------
// ------------------------------------------------------------------------
// >> StartPlayout
// >> StopPlayout
//
// State: VE initialized, no existing channels
TEST(StartPlayout);
ANL();
TEST(StopPlayout);
ANL();
// call without existing channel
TEST_MUSTPASS(!voe_base_->StartPlayout(0));
MARK();
TEST_ERROR(VE_CHANNEL_NOT_VALID);
TEST_MUSTPASS(!voe_base_->StopPlayout(0));
MARK();
TEST_ERROR(VE_CHANNEL_NOT_VALID);
ch = voe_base_->CreateChannel();
TEST_MUSTPASS(voe_base_->StartPlayout(ch));
MARK();
TEST_MUSTPASS(voe_base_->StartPlayout(ch));
MARK();
TEST_MUSTPASS(voe_base_->StopPlayout(ch));
MARK();
TEST_MUSTPASS(voe_base_->StopPlayout(ch));
MARK();
voe_base_->DeleteChannel(ch);
// Multi-channel tests
const int MaxNumberOfPlayingChannels(kVoiceEngineMaxNumOfActiveChannels);
for (i = 0; i < MaxNumberOfPlayingChannels; i++) {
ch = voe_base_->CreateChannel();
TEST_MUSTPASS(voe_base_->StartPlayout(ch));
MARK();
}
for (i = 0; i < MaxNumberOfPlayingChannels; i++) {
TEST_MUSTPASS(voe_base_->StopPlayout(i));
MARK();
voe_base_->DeleteChannel(i);
}
for (i = 0; i < MaxNumberOfPlayingChannels; i++) {
ch = voe_base_->CreateChannel();
TEST_MUSTPASS(voe_base_->StartPlayout(ch));
MARK();
TEST_MUSTPASS(voe_base_->StopPlayout(ch));
MARK();
voe_base_->DeleteChannel(ch);
}
ANL();
AOK();
ANL();
ANL();
// >> end of StartPlayout/StopPlayout
// ------------------------------------------------------------------------
// ------------------------------------------------------------------------
// >> StartSend
// >> StopSend
//
// State: VE initialized, no existing channels
TEST(StartSend);
ANL();
TEST(StopSend);
ANL();
// call without existing channel
TEST_MUSTPASS(!voe_base_->StartSend(0));
MARK();
TEST_ERROR(VE_CHANNEL_NOT_VALID);
TEST_MUSTPASS(!voe_base_->StopSend(0));
MARK();
TEST_ERROR(VE_CHANNEL_NOT_VALID);
ch = voe_base_->CreateChannel();
// call without initialized destination
TEST_MUSTPASS(!voe_base_->StartSend(ch));
MARK();
TEST_ERROR(VE_DESTINATION_NOT_INITED);
// initialize destination and try again (should work even without existing
// sockets)
TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 33333, "127.0.0.1"));
TEST_MUSTPASS(voe_base_->StartSend(ch));
MARK();
SLEEP(100);
// STATE: sockets should now have been created automatically at the first
// transmitted packet should be binded to 33333 and "0.0.0.0"
TEST_MUSTPASS(voe_base_->StopSend(ch));
MARK();
voe_base_->DeleteChannel(ch);
ch = voe_base_->CreateChannel();
// try loopback with unique send sockets (closed when channel is deleted or
// new source is set)
TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 33333));
TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 33333, "127.0.0.1", 44444));
TEST_MUSTPASS(voe_base_->StartSend(ch));
MARK();
TEST_MUSTPASS(voe_base_->StartReceive(ch));
Play(ch, 2000, true, true);
TEST_MUSTPASS(voe_base_->StopSend(ch));
MARK();
TEST_MUSTPASS(voe_base_->StopReceive(ch));
voe_base_->DeleteChannel(ch);
ANL();
// Multi-channel tests
for (i = 0; i < voe_base_->MaxNumOfChannels(); i++) {
ch = voe_base_->CreateChannel();
TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 33333 + 2*i));
TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 33333 + 2*i, "127.0.0.1"));
TEST_MUSTPASS(voe_base_->StartSend(ch));
MARK();
}
for (i = 0; i < voe_base_->MaxNumOfChannels(); i++) {
TEST_MUSTPASS(voe_base_->StopSend(i));
MARK();
voe_base_->DeleteChannel(i);
}
for (i = 0; i < voe_base_->MaxNumOfChannels(); i++) {
ch = voe_base_->CreateChannel();
TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 45633 + 2*i));
TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 45633 + 2*i, "127.0.0.1"));
TEST_MUSTPASS(voe_base_->StartSend(ch));
MARK();
TEST_MUSTPASS(voe_base_->StopSend(ch));
MARK();
voe_base_->DeleteChannel(ch);
}
ANL();
AOK();
ANL();
ANL();
// >> end of StartSend/StopSend
// ------------------------------------------------------------------------
//////////////////////////////
// SetNetEQPlayoutMode
// GetNetEQPlayoutMode
TEST(SetNetEQPlayoutMode);
ANL();
TEST(GetNetEQPlayoutMode);
ANL();
NetEqModes mode;
ch = voe_base_->CreateChannel();
// invalid function calls (should fail)
TEST_MUSTPASS(!voe_base_->GetNetEQPlayoutMode(ch+1, mode));
MARK();
TEST_MUSTPASS(!voe_base_->SetNetEQPlayoutMode(ch+1, kNetEqDefault));
MARK();
// verify default mode (should be kNetEqDefault)
TEST_MUSTPASS(voe_base_->GetNetEQPlayoutMode(ch, mode));
MARK();
TEST_MUSTPASS(mode != kNetEqDefault);
TEST_MUSTPASS(voe_base_->SetNetEQPlayoutMode(ch, kNetEqStreaming));
MARK();
voe_base_->DeleteChannel(ch);
// ensure that default mode is set as soon as new channel is created
ch = voe_base_->CreateChannel();
TEST_MUSTPASS(voe_base_->GetNetEQPlayoutMode(ch, mode));
MARK();
TEST_MUSTPASS(mode != kNetEqDefault);
voe_base_->DeleteChannel(ch);
// verify Set/Get for all supported modes and max number of channels
for (i = 0; i < voe_base_->MaxNumOfChannels(); i++) {
ch = voe_base_->CreateChannel();
// verify Set/Get for all supported modes
TEST_MUSTPASS(voe_base_->SetNetEQPlayoutMode(i, kNetEqDefault));
MARK();
TEST_MUSTPASS(voe_base_->GetNetEQPlayoutMode(i, mode));
MARK();
TEST_MUSTPASS(mode != kNetEqDefault);
TEST_MUSTPASS(voe_base_->SetNetEQPlayoutMode(i, kNetEqStreaming));
MARK();
TEST_MUSTPASS(voe_base_->GetNetEQPlayoutMode(i, mode));
MARK();
TEST_MUSTPASS(mode != kNetEqStreaming);
TEST_MUSTPASS(voe_base_->SetNetEQPlayoutMode(i, kNetEqFax));
MARK();
TEST_MUSTPASS(voe_base_->GetNetEQPlayoutMode(i, mode));
MARK();
TEST_MUSTPASS(mode != kNetEqFax);
SLEEP(50);
}
for (i = 0; i < voe_base_->MaxNumOfChannels(); i++) {
voe_base_->DeleteChannel(i);
}
ANL();
AOK();
ANL();
ANL();
//////////////////////////////
// SetNetEQBGNMode
// GetNetEQBGNMode
TEST(SetNetEQBGNMode);
ANL();
TEST(GetNetEQBGNMode);
ANL();
NetEqBgnModes bgnMode;
ch = voe_base_->CreateChannel();
// invalid function calls (should fail)
TEST_MUSTPASS(!voe_base_->GetNetEQBGNMode(ch+1, bgnMode));
MARK();
TEST_MUSTPASS(!voe_base_->SetNetEQBGNMode(ch+1, kBgnOn));
MARK();
// verify default mode (should be kBgnOn)
TEST_MUSTPASS(voe_base_->GetNetEQBGNMode(ch, bgnMode));
MARK();
TEST_MUSTPASS(bgnMode != kBgnOn);
voe_base_->DeleteChannel(ch);
// ensure that default mode is set as soon as new channel is created
ch = voe_base_->CreateChannel();
TEST_MUSTPASS(voe_base_->GetNetEQBGNMode(ch, bgnMode));
MARK();
TEST_MUSTPASS(bgnMode != kBgnOn);
voe_base_->DeleteChannel(ch);
// verify Set/Get for all supported modes and max number of channels
for (i = 0; i < voe_base_->MaxNumOfChannels(); i++) {
ch = voe_base_->CreateChannel();
// verify Set/Get for all supported modes
TEST_MUSTPASS(voe_base_->SetNetEQBGNMode(i, kBgnOn));
MARK();
TEST_MUSTPASS(voe_base_->GetNetEQBGNMode(i, bgnMode));
MARK();
TEST_MUSTPASS(bgnMode != kBgnOn);
TEST_MUSTPASS(voe_base_->SetNetEQBGNMode(i, kBgnFade));
MARK();
TEST_MUSTPASS(voe_base_->GetNetEQBGNMode(i, bgnMode));
MARK();
TEST_MUSTPASS(bgnMode != kBgnFade);
TEST_MUSTPASS(voe_base_->SetNetEQBGNMode(i, kBgnOff));
MARK();
TEST_MUSTPASS(voe_base_->GetNetEQBGNMode(i, bgnMode));
MARK();
TEST_MUSTPASS(bgnMode != kBgnOff);
SLEEP(50);
}
for (i = 0; i < voe_base_->MaxNumOfChannels(); i++) {
voe_base_->DeleteChannel(i);
}
// Verify real-time performance for all playout modes in full duplex
ch = voe_base_->CreateChannel();
TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch , 12345));
TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 12345, "127.0.0.1"));
TEST_MUSTPASS(voe_base_->StartReceive(ch));
TEST_MUSTPASS(voe_base_->StartSend(ch));
TEST_MUSTPASS(voe_base_->StartPlayout(ch));
TEST_MUSTPASS(voe_base_->SetNetEQPlayoutMode(ch, kNetEqDefault));
MARK();
TEST_LOG("\nenjoy full duplex using kNetEqDefault playout mode...\n");
PAUSE
TEST_MUSTPASS(voe_base_->SetNetEQPlayoutMode(ch, kNetEqStreaming));
MARK();
TEST_LOG("\nenjoy full duplex using kNetEqStreaming playout mode...\n");
PAUSE
TEST_MUSTPASS(voe_base_->SetNetEQPlayoutMode(ch, kNetEqFax));
MARK();
TEST_LOG("\nenjoy full duplex using kNetEqFax playout mode...\n");
PAUSE
TEST_MUSTPASS(voe_base_->StopSend(ch));
TEST_MUSTPASS(voe_base_->StopPlayout(ch));
TEST_MUSTPASS(voe_base_->StopReceive(ch));
voe_base_->DeleteChannel(ch);
ANL();
AOK();
ANL();
ANL();
/////////////////////
// Full duplex tests
ch = voe_base_->CreateChannel(); // We must delete this channel first to be able
// to reuse port 12345
// start with default case, also test non-default RTCP port
#ifdef _TEST_RTP_RTCP_
TEST_MUSTPASS(rtp->SetRTCP_CNAME(ch, "Johnny"));
#endif
TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 12345, 12349));
TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 12345, "127.0.0.1", kVoEDefault,
12349));
TEST_MUSTPASS(voe_base_->StartReceive(ch));
TEST_MUSTPASS(voe_base_->StartSend(ch));
TEST_MUSTPASS(voe_base_->StartPlayout(ch));
TEST_LOG("full duplex is now activated (1)\n");
TEST_LOG("waiting for RTCP packet...\n");
SLEEP(7000); // Make sure we get RTCP packet
PAUSE;
// Verify that we got RTCP packet from correct source port
#ifdef _TEST_RTP_RTCP_
char tmpStr[64] = { 0 };
TEST_MUSTPASS(rtp->GetRemoteRTCP_CNAME(ch, tmpStr));
TEST_MUSTPASS(_stricmp("Johnny", tmpStr));
#endif
int rtpPort(0), rtcpPort(0);
char ipAddr[64] = { 0 };
TEST_MUSTPASS(netw->GetSourceInfo(ch, rtpPort, rtcpPort, ipAddr));
TEST_MUSTPASS(12349 != rtcpPort);
TEST_MUSTPASS(voe_base_->StopSend(ch));
TEST_MUSTPASS(voe_base_->StopPlayout(ch));
TEST_MUSTPASS(voe_base_->StopReceive(ch));
// Call StartSend before StartReceive
TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 12345));
TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 12345, "127.0.0.1"));
TEST_MUSTPASS(voe_base_->StartSend(ch));
TEST_MUSTPASS(voe_base_->StartReceive(ch));
TEST_MUSTPASS(voe_base_->StartPlayout(ch));
TEST_LOG("\nfull duplex is now activated (2)\n");
PAUSE
TEST_MUSTPASS(voe_base_->StopSend(ch));
TEST_MUSTPASS(voe_base_->StopPlayout(ch));
TEST_MUSTPASS(voe_base_->StopReceive(ch));
// Try again using same ports
TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 12345));
TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 12345, "127.0.0.1"));
TEST_MUSTPASS(voe_base_->StartSend(ch));
TEST_MUSTPASS(voe_base_->StartReceive(ch));
TEST_MUSTPASS(voe_base_->StartPlayout(ch));
TEST_LOG("\nfull duplex is now activated (3)\n");
TEST_LOG("waiting for RTCP packet...\n");
SLEEP(7000); // Make sure we get RTCP packet
PAUSE
// Verify correct RTCP source port
TEST_MUSTPASS(netw->GetSourceInfo(ch, rtpPort, rtcpPort, ipAddr));
TEST_MUSTPASS(12345+1 != rtcpPort);
TEST_MUSTPASS(voe_base_->StopSend(ch));
TEST_MUSTPASS(voe_base_->StopPlayout(ch));
TEST_MUSTPASS(voe_base_->StopReceive(ch));
voe_base_->DeleteChannel(ch);
ch = voe_base_->CreateChannel();
// Try with extra send socket
TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch , 22222));
TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 22222, "127.0.0.1", 11111));
TEST_MUSTPASS(voe_base_->StartReceive(ch));
TEST_MUSTPASS(voe_base_->StartSend(ch));
TEST_MUSTPASS(voe_base_->StartPlayout(ch));
TEST_LOG("\nfull duplex is now activated (4)\n");
PAUSE
TEST_MUSTPASS(voe_base_->StopSend(ch));
TEST_MUSTPASS(voe_base_->StopPlayout(ch));
TEST_MUSTPASS(voe_base_->StopReceive(ch));
// repeat default case starting with a fresh channel
voe_base_->DeleteChannel(ch);
ch = voe_base_->CreateChannel();
TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch , 12345));
TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 12345, "127.0.0.1"));
TEST_MUSTPASS(voe_base_->StartReceive(ch));
TEST_MUSTPASS(voe_base_->StartSend(ch));
TEST_MUSTPASS(voe_base_->StartPlayout(ch));
TEST_LOG("\nfull duplex is now activated (5)\n");
PAUSE
TEST_MUSTPASS(voe_base_->StopSend(ch));
TEST_MUSTPASS(voe_base_->StopPlayout(ch));
TEST_MUSTPASS(voe_base_->StopReceive(ch));
// restart call again
TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 12345));
TEST_MUSTPASS(voe_base_->StartReceive(ch));
TEST_MUSTPASS(voe_base_->StartPlayout(ch));
TEST_MUSTPASS(voe_base_->StartSend(ch));
TEST_LOG("\nfull duplex is now activated (6)\n");
PAUSE
TEST_MUSTPASS(voe_base_->StopSend(ch));
TEST_MUSTPASS(voe_base_->StopPlayout(ch));
TEST_MUSTPASS(voe_base_->StopReceive(ch));
// force sending from new socket
TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch , 12345));
TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 12345, "127.0.0.1", 12350,
12359));
TEST_MUSTPASS(voe_base_->StartReceive(ch));
TEST_MUSTPASS(voe_base_->StartPlayout(ch));
TEST_MUSTPASS(voe_base_->StartSend(ch));
TEST_LOG("\nfull duplex is now activated (7)\n");
PAUSE
// Test getting send settings
TEST_MUSTPASS(voe_base_->GetSendDestination(ch, rtpPort, ipAddr, sourcePort,
rtcpPort));
TEST_MUSTPASS(12345 != rtpPort);
TEST_MUSTPASS(_stricmp("127.0.0.1", ipAddr));
TEST_MUSTPASS(12350 != sourcePort);
TEST_MUSTPASS(12359 != rtcpPort);
TEST_MUSTPASS(voe_base_->StopSend(ch));
TEST_MUSTPASS(voe_base_->StopPlayout(ch));
TEST_MUSTPASS(voe_base_->StopReceive(ch));
// new channel and new port
ch = voe_base_->CreateChannel();
TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch , 33221));
TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 33221, "127.0.0.1"));
TEST_MUSTPASS(voe_base_->StartReceive(ch));
TEST_MUSTPASS(voe_base_->StartPlayout(ch));
TEST_MUSTPASS(voe_base_->StartSend(ch));
TEST_LOG("\nfull duplex is now activated (8)\n");
PAUSE
TEST_MUSTPASS(voe_base_->StopSend(ch));
TEST_MUSTPASS(voe_base_->StopPlayout(ch));
TEST_MUSTPASS(voe_base_->StopReceive(ch));
voe_base_->DeleteChannel(ch);
ch = voe_base_->CreateChannel();
#ifndef MAC_IPHONE
// bind to local IP and try again
strcpy(localIp, "127.0.0.1");
#else
localIp = "127.0.0.1";
#endif
TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 33221, 12349, localIp));
TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 33221, localIp));
TEST_MUSTPASS(voe_base_->StartReceive(ch));
TEST_MUSTPASS(voe_base_->StartPlayout(ch));
TEST_MUSTPASS(voe_base_->StartSend(ch));
TEST_LOG("\nfull duplex is now activated (9)\n");
PAUSE
TEST_MUSTPASS(voe_base_->GetLocalReceiver(ch, rtpPort, rtcpPort, ipAddr));
TEST_MUSTPASS(33221 != rtpPort);
TEST_MUSTPASS(_stricmp(localIp, ipAddr));
TEST_MUSTPASS(12349 != rtcpPort);
ANL();
AOK();
ANL();
ANL();
//////////////////////
// Trace filter tests
#ifdef _USE_EXTENDED_TRACE_
TEST(SetTraceFilter); ANL();
TEST_MUSTPASS(VoiceEngine::SetTraceFile(GetFilename(""
"VoEBase_trace_filter.txt"))); MARK();
SLEEP(100);
// Test a few different filters, verify in trace file
// Each SetTraceFilter calls should be seen once, no more, no less
TEST_MUSTPASS(VoiceEngine::SetTraceFilter(kTraceNone)); MARK();
SLEEP(300);
// API call and info should NOT be seen in log
TEST_MUSTPASS(voe_base_->SetOnHoldStatus(0, true)); MARK();
// API call and error should NOT be seen in log
TEST_MUSTPASS(!voe_base_->SetOnHoldStatus(999, true)); MARK();
TEST_MUSTPASS(VoiceEngine::SetTraceFilter(kTraceApiCall |
kTraceCritical |
kTraceError |
kTraceWarning)); MARK();
SLEEP(300);
// API call should and info should NOT be seen in log
TEST_MUSTPASS(voe_base_->SetOnHoldStatus(0, false)); MARK();
// API call and error should be seen in log
TEST_MUSTPASS(!voe_base_->SetOnHoldStatus(999, true)); MARK();
TEST_MUSTPASS(VoiceEngine::SetTraceFilter(kTraceApiCall | kTraceInfo));
MARK();
SLEEP(300);
// API call and info should be seen in log
TEST_MUSTPASS(voe_base_->SetOnHoldStatus(0, true)); MARK();
// API call should and error should NOT be seen in log
TEST_MUSTPASS(!voe_base_->SetOnHoldStatus(999, true)); MARK();
// Back to default
TEST_MUSTPASS(VoiceEngine::SetTraceFilter(kTraceAll)); MARK();
SLEEP(300);
AOK(); ANL();
#endif
// ------------------------------------------------------------------------
// >> Multiple instance testing
//
// We should support 8 instances simultaneously
// and at least one should be able to have a call running
// One instance is already created
VoiceEngine* instVE[7];
VoEBase* baseVE[7];
for (int instNum = 0; instNum < 7; instNum++) {
instVE[instNum] = VoiceEngine::Create();
baseVE[instNum] = VoEBase::GetInterface(instVE[instNum]);
TEST_MUSTPASS(baseVE[instNum]->Init());
TEST_MUSTPASS(baseVE[instNum]->CreateChannel());
}
TEST_LOG("Created 7 more instances of VE, make sure audio is ok...\n\n");
PAUSE
for (int instNum = 0; instNum < 7; instNum++) {
TEST_MUSTPASS(baseVE[instNum]->DeleteChannel(0));
TEST_MUSTPASS(baseVE[instNum]->Terminate());
TEST_MUSTPASS(baseVE[instNum]->Release());
VoiceEngine::Delete(instVE[instNum]);
}
AOK();
ANL();
//////////////
// Close down
TEST_MUSTPASS(voe_base_->StopSend(ch));
TEST_MUSTPASS(voe_base_->StopPlayout(ch));
TEST_MUSTPASS(voe_base_->StopReceive(ch));
TEST_MUSTPASS(voe_base_->DeleteChannel(ch));
voe_base_->DeleteChannel(0);
TEST_MUSTPASS(voe_base_->Terminate());
return 0;
}
// ----------------------------------------------------------------------------
// VoEExtendedTest::TestCallReport
// ----------------------------------------------------------------------------
int VoEExtendedTest::TestCallReport() {
// Get required sub-API pointers
VoEBase* voe_base_ = _mgr.BasePtr();
VoECallReport* report = _mgr.CallReportPtr();
VoEFile* file = _mgr.FilePtr();
VoEAudioProcessing* apm = _mgr.APMPtr();
VoENetwork* netw = _mgr.NetworkPtr();
PrepareTest("CallReport");
// check if this interface is supported
if (!report) {
TEST_LOG("VoECallReport is not supported!");
return -1;
}
#ifdef _USE_EXTENDED_TRACE_
TEST_MUSTPASS(VoiceEngine::SetTraceFile(GetFilename("VoECallReport_trace.txt")));
TEST_MUSTPASS(VoiceEngine::SetTraceFilter(kTraceStateInfo |
kTraceStateInfo |
kTraceWarning |
kTraceError |
kTraceCritical |
kTraceApiCall |
kTraceMemory |
kTraceInfo));
#endif
TEST_MUSTPASS(voe_base_->Init());
TEST_MUSTPASS(voe_base_->CreateChannel());
TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 12345));
TEST_MUSTPASS(voe_base_->SetSendDestination(0, 12345, "127.0.0.1"));
TEST_MUSTPASS(voe_base_->StartReceive(0));
TEST_MUSTPASS(voe_base_->StartSend(0));
TEST_MUSTPASS(voe_base_->StartPlayout(0));
TEST_MUSTPASS(file->StartPlayingFileAsMicrophone(0, _mgr.AudioFilename(),
true, true));
///////////////////////////
// Actual test starts here
TEST(ResetCallReportStatistics);
ANL();
TEST_MUSTPASS(!report->ResetCallReportStatistics(-2));
MARK(); // not OK
TEST_MUSTPASS(!report->ResetCallReportStatistics(1));
MARK(); // not OK
TEST_MUSTPASS(report->ResetCallReportStatistics(0));
MARK(); // OK
TEST_MUSTPASS(report->ResetCallReportStatistics(-1));
MARK(); // OK
AOK();
ANL();
bool enabled = false;
EchoStatistics echo;
TEST(GetEchoMetricSummary);
ANL();
TEST_MUSTPASS(apm->GetEcMetricsStatus(enabled));
TEST_MUSTPASS(enabled != false);
TEST_MUSTPASS(apm->SetEcMetricsStatus(true));
TEST_MUSTPASS(report->GetEchoMetricSummary(echo)); // all outputs will be
// -100 in loopback (skip further tests)
AOK();
ANL();
// TODO(xians): investigate the cause of test failure before enabling.
/*
StatVal delays;
TEST(GetRoundTripTimeSummary);
ANL();
// All values should be >=0 since RTCP is now on
TEST_MUSTPASS(report->GetRoundTripTimeSummary(0, delays));
MARK();
TEST_MUSTPASS(delays.min == -1);
TEST_MUSTPASS(delays.max == -1);
TEST_MUSTPASS(delays.average == -1);
rtp_rtcp->SetRTCPStatus(0, false);
// All values should be -1 since RTCP is off
TEST_MUSTPASS(report->GetRoundTripTimeSummary(0, delays));
MARK();
TEST_MUSTPASS(delays.min != -1);
TEST_MUSTPASS(delays.max != -1);
TEST_MUSTPASS(delays.average != -1);
rtp_rtcp->SetRTCPStatus(0, true);
AOK();
ANL();
*/
int nDead = 0;
int nAlive = 0;
TEST(GetDeadOrAliveSummary);
ANL();
// All results should be -1 since dead-or-alive is not active
TEST_MUSTPASS(report->GetDeadOrAliveSummary(0, nDead, nAlive) != -1);
MARK();
TEST_MUSTPASS(netw->SetPeriodicDeadOrAliveStatus(0, true, 1));
SLEEP(2000);
// All results should be >= 0 since dead-or-alive is active
TEST_MUSTPASS(report->GetDeadOrAliveSummary(0, nDead, nAlive));
MARK();
TEST_MUSTPASS(nDead == -1);
TEST_MUSTPASS(nAlive == -1)
TEST_MUSTPASS(netw->SetPeriodicDeadOrAliveStatus(0, false));
AOK();
ANL();
TEST(WriteReportToFile);
ANL();
// Greek and Coptic (see http://www.utf8-chartable.de/unicode-utf8-table.pl)
char fileNameUTF8[64];
fileNameUTF8[0] = (char) 0xce;
fileNameUTF8[1] = (char) 0xba;
fileNameUTF8[2] = (char) 0xce;
fileNameUTF8[3] = (char) 0xbb;
fileNameUTF8[4] = (char) 0xce;
fileNameUTF8[5] = (char) 0xbd;
fileNameUTF8[6] = (char) 0xce;
fileNameUTF8[7] = (char) 0xbe;
fileNameUTF8[8] = '.';
fileNameUTF8[9] = 't';
fileNameUTF8[10] = 'x';
fileNameUTF8[11] = 't';
fileNameUTF8[12] = 0;
TEST_MUSTPASS(!report->WriteReportToFile(NULL));
MARK();
TEST_MUSTPASS(report->WriteReportToFile("call_report.txt"));
MARK();
TEST_MUSTPASS(report->WriteReportToFile(fileNameUTF8));
MARK(); // should work with UTF-8 as well (κλνξ.txt)
AOK();
ANL();
TEST_MUSTPASS(file->StopPlayingFileAsMicrophone(0));
TEST_MUSTPASS(voe_base_->StopSend(0));
TEST_MUSTPASS(voe_base_->StopPlayout(0));
TEST_MUSTPASS(voe_base_->StopReceive(0));
TEST_MUSTPASS(voe_base_->DeleteChannel(0));
TEST_MUSTPASS(voe_base_->Terminate());
return 0;
}
// ----------------------------------------------------------------------------
// VoEExtendedTest::TestCodec
// ----------------------------------------------------------------------------
int VoEExtendedTest::TestCodec() {
PrepareTest("Codec");
VoEBase* voe_base_ = _mgr.BasePtr();
VoECodec* codec = _mgr.CodecPtr();
VoEFile* file = _mgr.FilePtr();
#ifdef _USE_EXTENDED_TRACE_
TEST_MUSTPASS(VoiceEngine::SetTraceFile(GetFilename("VoECodec_trace.txt")));
TEST_MUSTPASS(VoiceEngine::SetTraceFilter(kTraceStateInfo |
kTraceStateInfo |
kTraceWarning |
kTraceError |
kTraceCritical |
kTraceApiCall |
kTraceMemory |
kTraceInfo));
#endif
TEST_MUSTPASS(voe_base_->Init());
TEST_MUSTPASS(voe_base_->CreateChannel());
#ifdef WEBRTC_EXTERNAL_TRANSPORT
ExtendedTestTransport* ptrTransport(NULL);
ptrTransport = new ExtendedTestTransport(netw);
TEST_MUSTPASS(netw->RegisterExternalTransport(0, *ptrTransport));
#else
TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 12345));
TEST_MUSTPASS(voe_base_->SetSendDestination(0, 12345, "127.0.0.1"));
#endif
TEST_MUSTPASS(voe_base_->StartReceive(0));
TEST_MUSTPASS(voe_base_->StartSend(0));
TEST_MUSTPASS(voe_base_->StartPlayout(0));
///////////////////////////
// Actual test starts here
int i;
int err;
CodecInst cinst;
/////////////////////////
// GetNumOfCodecs
int nCodecs;
TEST(GetNumOfCodecs);
ANL();
// validate #codecs
nCodecs = codec->NumOfCodecs();
MARK();
TEST_MUSTPASS(nCodecs < 0);
AOK();
ANL();
///////////////////
// GetCodec
TEST(GetCodec);
ANL();
// scan all supported codecs
nCodecs = codec->NumOfCodecs();
for (int index = 0; index < nCodecs; index++) {
TEST_MUSTPASS(codec->GetCodec(index, cinst));
TEST_LOG("[%2d] %16s: fs=%6d, pt=%4d, rate=%7d, ch=%2d, size=%5d", index, cinst.plname,
cinst.plfreq, cinst.pltype, cinst.rate, cinst.channels, cinst.pacsize);
if (cinst.pltype == -1) {
TEST_LOG(" <= NOTE pt=-1\n");
} else {
ANL();
}
}
// ensure that an invalid index parameter is detected
TEST_MUSTPASS(-1 != codec->GetCodec(-1, cinst));
nCodecs = codec->NumOfCodecs();
TEST_MUSTPASS(-1 != codec->GetCodec(nCodecs, cinst));
MARK();
// ensure that error code is VE_INVALID_LISTNR
err = voe_base_->LastError();
TEST_MUSTPASS(err != VE_INVALID_LISTNR);
AOK();
ANL();
///////////////////////
// GetSendCodec
TEST(GetSendCodec);
ANL();
CodecInst defaultCodec;
// check the channel parameter
int nMaxChannels(voe_base_->MaxNumOfChannels());
TEST_MUSTPASS(-1 != codec->GetSendCodec(nMaxChannels-1, cinst));
MARK(); // not created
TEST_MUSTPASS(-1 != codec->GetSendCodec(nMaxChannels, cinst));
MARK(); // out of range
TEST_MUSTPASS(-1 != codec->GetSendCodec(-1, cinst));
MARK(); // out of range
TEST_MUSTPASS(codec->GetSendCodec(0, cinst));
MARK(); // OK
nCodecs = codec->NumOfCodecs();
for (int index = 0; index < nCodecs; index++) {
TEST_MUSTPASS(codec->GetCodec(index, defaultCodec));
if (codec->SetSendCodec(0, defaultCodec) == 0) {
TEST_MUSTPASS(codec->GetSendCodec(0, cinst));
MARK();
//TEST_LOG("[%2d] %s: fs=%d, pt=%d, rate=%d, ch=%d, size=%d\n",
// index, cinst.plname, cinst.plfreq, cinst.pltype, cinst.rate,
// cinst.channels, cinst.pacsize);
TEST_MUSTPASS(cinst.pacsize != defaultCodec.pacsize);
TEST_MUSTPASS(cinst.plfreq != defaultCodec.plfreq);
TEST_MUSTPASS(cinst.pltype != defaultCodec.pltype);
TEST_MUSTPASS(cinst.rate != defaultCodec.rate);
TEST_MUSTPASS(cinst.channels != defaultCodec.channels);
}
}
ANL();
AOK();
ANL();
///////////////////////
// SetSendCodec
TEST(SetSendCodec);
ANL();
// --- Scan all supported codecs and set default parameters
nCodecs = codec->NumOfCodecs();
for (int index = 0; index < nCodecs; index++) {
// Get default (ACM) settings
TEST_MUSTPASS(codec->GetCodec(index, cinst));
defaultCodec = cinst;
TEST_LOG("[%2d] %s (default): fs=%d, pt=%d, rate=%d, ch=%d, size=%d\n",
index, cinst.plname, cinst.plfreq, cinst.pltype, cinst.rate,
cinst.channels, cinst.pacsize);
// Verify invalid codec names
if (!_stricmp("CN", cinst.plname) || !_stricmp("telephone-event",
cinst.plname)
|| !_stricmp("red", cinst.plname)) {
// default settings for invalid payload names (should give
// VE_INVALID_PLNAME)
TEST_MUSTPASS(!codec->SetSendCodec(0, cinst));
err = voe_base_->LastError();
TEST_MUSTPASS(err != VE_INVALID_ARGUMENT);
continue;
}
// If we build the ACM with more codecs than we have payload types,
// some codecs will be given -1 as default payload type. This is a fix
// to ensure that we can complete these tests also for this case.
if (cinst.pltype == -1) {
cinst.pltype = 97;
}
// --- Default settings
TEST_MUSTPASS(codec->SetSendCodec(0, cinst));
// --- Packet size
TEST_LOG("\npacsize : ");
for (int pacsize = 80; pacsize < 1440; pacsize += 80) {
cinst.pacsize = pacsize;
if (-1 != codec->SetSendCodec(0, cinst)) {
// log valid packet size
TEST_LOG("%d ", pacsize);
} else {
err = voe_base_->LastError();
TEST_MUSTPASS(err != VE_INVALID_ARGUMENT);
}
}
cinst.pacsize = defaultCodec.pacsize;
// --- Audio channels (1/mono or 2/stereo)
TEST_LOG("\nchannels: ");
for (int channels = 1; channels < 4; channels++) {
cinst.channels = channels;
if (-1 != codec->SetSendCodec(0, cinst)) {
// valid channels (only 1 should be OK)
TEST_LOG("%d ", channels);
} else {
err = voe_base_->LastError();
TEST_MUSTPASS(err != VE_INVALID_ARGUMENT);
}
}
cinst.channels = defaultCodec.channels;
// --- Payload frequency
TEST_LOG("\nplfreq : ");
cinst.plfreq = defaultCodec.plfreq;
TEST_MUSTPASS(codec->SetSendCodec(0, cinst));
TEST_LOG("%d ", cinst.plfreq);
// --- Payload name
strcpy(cinst.plname, "INVALID");
TEST_MUSTPASS(-1 != codec->SetSendCodec(0, cinst))
{
// ensure that error code is VE_INVALID_PLNAME
err = voe_base_->LastError();
TEST_MUSTPASS(err != VE_INVALID_ARGUMENT);
}
// restore default plname
strcpy(cinst.plname, defaultCodec.plname);
// --- Payload type (dynamic range is 96-127)
TEST_LOG("\npltype : ");
// All PT should be OK, test a few different
cinst.pltype = defaultCodec.pltype;
TEST_MUSTPASS(codec->SetSendCodec(0, cinst));
TEST_LOG("%d ", cinst.pltype);
cinst.pltype = defaultCodec.pltype + 1;
TEST_MUSTPASS(codec->SetSendCodec(0, cinst));
TEST_LOG("%d ", cinst.pltype);
const int valid_pltypes[4] = { 0, 96, 117, 127 };
for (i = 0; i < static_cast<int> (sizeof(valid_pltypes) / sizeof(int)); i++) {
cinst.pltype = valid_pltypes[i];
TEST_MUSTPASS(codec->SetSendCodec(0, cinst));
TEST_LOG("%d ", cinst.pltype);
}
// Restore default
cinst.pltype = defaultCodec.pltype;
// --- Codec rate
TEST_LOG("\nrate : ");
if (_stricmp("isac", cinst.plname) == 0) {
// ISAC
if (cinst.plfreq == 16000) {
int valid_rates[3] = { -1, 10000, 32000 };
// failed in RegisterPayload when rate is 32000
for (i = 0; i < static_cast<int> (sizeof(valid_rates) / sizeof(int)); i++) {
cinst.rate = valid_rates[i];
TEST_MUSTPASS(codec->SetSendCodec(0, cinst));
TEST_LOG("%d ", cinst.rate);
}
cinst.rate = 0; // invalid
TEST_MUSTPASS(-1 != codec->SetSendCodec(0, cinst))
{
// ensure that error code is VE_CANNOT_SET_SEND_CODEC
err = voe_base_->LastError();
TEST_MUSTPASS(err != VE_INVALID_ARGUMENT);
}
ANL();
} else //ISACSWB
{
// rate changing fails in RegisterPayload
int valid_rates[8] = { -1, 10000, 25000, 32000, 35000, 45000, 50000, 52000 };
for (i = 0; i < static_cast<int> (sizeof(valid_rates) / sizeof(int)); i++) {
cinst.rate = valid_rates[i];
TEST_MUSTPASS(codec->SetSendCodec(0, cinst));
TEST_LOG("%d ", cinst.rate);
}
int invalid_rates[3] = { 0, 5000, 57000 }; // invalid
for (i = 0; i < static_cast<int> (sizeof(invalid_rates) / sizeof(int)); i++) {
cinst.rate = invalid_rates[i];
TEST_MUSTPASS(-1 != codec->SetSendCodec(0, cinst))
{
// ensure that error code is VE_CANNOT_SET_SEND_CODEC
err = voe_base_->LastError();
TEST_MUSTPASS(err != VE_INVALID_ARGUMENT);
}
}
ANL();
}
} else if (_stricmp("amr", cinst.plname) == 0) {
int valid_rates[8] = { 4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200 };
for (i = 0;
i < static_cast<int> (sizeof(valid_rates) / sizeof(int));
i++) {
cinst.rate = valid_rates[i];
TEST_MUSTPASS(codec->SetSendCodec(0, cinst));
TEST_LOG("%d ", cinst.rate);
}
ANL();
} else if (_stricmp("g7291", cinst.plname) == 0) {
int valid_rates[12] = { 8000, 12000, 14000, 16000, 18000, 20000, 22000,
24000, 26000, 28000, 30000, 32000 };
for (i = 0;
i < static_cast<int> (sizeof(valid_rates) / sizeof(int));
i++) {
cinst.rate = valid_rates[i];
TEST_MUSTPASS(codec->SetSendCodec(0, cinst));
TEST_LOG("%d ", cinst.rate);
}
ANL();
} else if (_stricmp("amr-wb", cinst.plname) == 0) {
int valid_rates[9] = { 7000, 9000, 12000, 14000, 16000, 18000, 20000,
23000, 24000 };
for (i = 0;
i < static_cast<int> (sizeof(valid_rates) / sizeof(int));
i++) {
cinst.rate = valid_rates[i];
TEST_MUSTPASS(codec->SetSendCodec(0, cinst));
TEST_LOG("%d ", cinst.rate);
}
TEST_LOG(" <=> ");
ANL();
} else if (_stricmp("speex", cinst.plname) == 0) {
// Valid speex rates are > 2000, testing some of them here
int valid_rates[9] = { 2001, 4000, 7000, 11000, 15000, 20000, 25000,
33000, 46000 };
for (i = 0;
i < static_cast<int> (sizeof(valid_rates) / sizeof(int));
i++) {
cinst.rate = valid_rates[i];
TEST_MUSTPASS(codec->SetSendCodec(0, cinst));
TEST_LOG("%d ", cinst.rate);
}
cinst.rate = 2000; // invalid
TEST_MUSTPASS(-1 != codec->SetSendCodec(0, cinst))
{
err = voe_base_->LastError();
TEST_MUSTPASS(err != VE_INVALID_ARGUMENT);
}
ANL();
} else if (_stricmp("silk", cinst.plname) == 0) {
// Valid Silk rates are 6000 - 40000, listing some of them here
int valid_rates[7] = { 6000, 10000, 15000, 20000, 25000, 32000, 40000 };
for (i = 0;
i < static_cast<int> (sizeof(valid_rates) / sizeof(int));
i++) {
cinst.rate = valid_rates[i];
TEST_MUSTPASS(codec->SetSendCodec(0, cinst));
TEST_LOG("%d ", cinst.rate);
}
cinst.rate = 5999; // invalid
TEST_MUSTPASS(-1 != codec->SetSendCodec(0, cinst))
{
err = voe_base_->LastError();
TEST_MUSTPASS(err != VE_INVALID_ARGUMENT);
}
cinst.rate = 40001; // invalid
TEST_MUSTPASS(-1 != codec->SetSendCodec(0, cinst))
{
err = voe_base_->LastError();
TEST_MUSTPASS(err != VE_INVALID_ARGUMENT);
}
ANL();
} else {
// Use default rate for all other codecs.
cinst.rate = defaultCodec.rate;
TEST_MUSTPASS(codec->SetSendCodec(0, cinst));
TEST_LOG("%d ", cinst.rate);
cinst.rate = defaultCodec.rate + 17;
TEST_MUSTPASS(!codec->SetSendCodec(0, cinst));
err = voe_base_->LastError();
TEST_MUSTPASS(err != VE_INVALID_ARGUMENT);
ANL();
}
cinst.rate = defaultCodec.rate;
// run some extra tests for L16
if (_stricmp("l16", cinst.plname) == 0) {
if (8000 == cinst.plfreq) {
// valid pacsizes: 80, 160, 240, 320
cinst.pacsize = 480; // only supported in combination with 16kHz
TEST_MUSTPASS(-1 != codec->SetSendCodec(0, cinst));
err = voe_base_->LastError();
TEST_MUSTPASS(err != VE_INVALID_ARGUMENT);
cinst.pacsize = 640; // only supported in combination with 16kHz
TEST_MUSTPASS(-1 != codec->SetSendCodec(0, cinst));
err = voe_base_->LastError();
TEST_MUSTPASS(err != VE_INVALID_ARGUMENT);
} else {
// valid pacsizes: 160, 320, 480, 640
cinst.pacsize = 80; // only supported in combination with 8kHz
TEST_MUSTPASS(-1 != codec->SetSendCodec(0, cinst));
err = voe_base_->LastError();
TEST_MUSTPASS(err != VE_INVALID_ARGUMENT);
cinst.pacsize = 240; // only supported in combination with 8kHz
TEST_MUSTPASS(-1 != codec->SetSendCodec(0, cinst));
err = voe_base_->LastError();
TEST_MUSTPASS(err != VE_INVALID_ARGUMENT);
}
}
ANL();
} // for (int index = 0; index < nCodecs; index++)
// restore PCMU
const CodecInst tmp = { 0, "PCMU", 8000, 160, 1, 64000 };
TEST_MUSTPASS(codec->SetSendCodec(0, tmp));
ANL();
AOK();
ANL();
///////
// VAD
const int VADSleep = 0;
bool disabledDTX;
VadModes mode;
bool enabled;
// verify default settings (should be OFF, kVadConventional and DTX enabled)
TEST_MUSTPASS(codec->GetVADStatus(0, enabled, mode, disabledDTX));
TEST_LOG("VAD: enabled=%d, mode=%d, disabledDTX=%d\n", enabled, mode,
disabledDTX);
TEST_MUSTPASS(enabled != false);
TEST_MUSTPASS(mode != kVadConventional);
TEST_MUSTPASS(disabledDTX != true);
// enable default VAD settings
TEST_MUSTPASS(codec->SetVADStatus(0, true));
TEST_MUSTPASS(codec->GetVADStatus(0, enabled, mode, disabledDTX));
TEST_LOG("VAD: enabled=%d, mode=%d, disabledDTX=%d\n", enabled, mode,
disabledDTX);
TEST_MUSTPASS(enabled != true);
TEST_MUSTPASS(mode != kVadConventional);
TEST_MUSTPASS(disabledDTX != false);
SLEEP(VADSleep);
// set kVadConventional mode
TEST_MUSTPASS(codec->SetVADStatus(0, true, kVadConventional));
TEST_MUSTPASS(codec->GetVADStatus(0, enabled, mode, disabledDTX));
TEST_LOG("VAD: enabled=%d, mode=%d, disabledDTX=%d\n", enabled, mode,
disabledDTX);
TEST_MUSTPASS(mode != kVadConventional);
SLEEP(VADSleep);
// set kVadAggressiveLow mode
TEST_MUSTPASS(codec->SetVADStatus(0, true, kVadAggressiveLow));
TEST_MUSTPASS(codec->GetVADStatus(0, enabled, mode, disabledDTX));
TEST_LOG("VAD: enabled=%d, mode=%d, disabledDTX=%d\n", enabled, mode,
disabledDTX);
TEST_MUSTPASS(mode != kVadAggressiveLow);
SLEEP(VADSleep);
// set kVadAggressiveMid mode
TEST_MUSTPASS(codec->SetVADStatus(0, true, kVadAggressiveMid));
TEST_MUSTPASS(codec->GetVADStatus(0, enabled, mode, disabledDTX));
TEST_LOG("VAD: enabled=%d, mode=%d, disabledDTX=%d\n", enabled, mode,
disabledDTX);
TEST_MUSTPASS(mode != kVadAggressiveMid);
SLEEP(VADSleep);
// set kVadAggressiveMid mode
TEST_MUSTPASS(codec->SetVADStatus(0, true, kVadAggressiveHigh));
TEST_MUSTPASS(codec->GetVADStatus(0, enabled, mode, disabledDTX));
TEST_LOG("VAD: enabled=%d, mode=%d, disabledDTX=%d\n", enabled, mode,
disabledDTX);
TEST_MUSTPASS(mode != kVadAggressiveHigh);
SLEEP(VADSleep);
// turn DTX OFF (audio should not be affected by VAD decisions)
TEST_MUSTPASS(codec->SetVADStatus(0, true, kVadConventional, true));
TEST_MUSTPASS(codec->GetVADStatus(0, enabled, mode, disabledDTX));
TEST_LOG("VAD: enabled=%d, mode=%d, disabledDTX=%d\n", enabled, mode,
disabledDTX);
TEST_MUSTPASS(disabledDTX != true);
SLEEP(VADSleep);
// try to enable DTX again (should fail since VAD is disabled)
TEST_MUSTPASS(codec->SetVADStatus(0, false, kVadConventional, false));
TEST_MUSTPASS(codec->GetVADStatus(0, enabled, mode, disabledDTX));
TEST_LOG("VAD: enabled=%d, mode=%d, disabledDTX=%d\n", enabled, mode,
disabledDTX);
TEST_MUSTPASS(disabledDTX == false);
SLEEP(VADSleep);
// disable VAD
TEST_MUSTPASS(codec->SetVADStatus(0, false));
TEST_MUSTPASS(codec->GetVADStatus(0, enabled, mode, disabledDTX));
TEST_LOG("VAD: enabled=%d, mode=%d, disabledDTX=%d\n", enabled, mode,
disabledDTX);
TEST_MUSTPASS(enabled != false);
SLEEP(VADSleep);
// restore default VAD
TEST_MUSTPASS(codec->SetVADStatus(0, true));
TEST_MUSTPASS(codec->SetVADStatus(0, false));
TEST_MUSTPASS(codec->GetVADStatus(0, enabled, mode, disabledDTX));
TEST_LOG("VAD: enabled=%d, mode=%d, disabledDTX=%d\n", enabled, mode,
disabledDTX);
TEST_MUSTPASS(enabled != false);
TEST_MUSTPASS(mode != kVadConventional);
TEST_MUSTPASS(disabledDTX != true);
SLEEP(VADSleep);
AOK();
ANL();
ANL();
//////////////////////
// GetRecCodec
TEST(GetRecCodec);
ANL();
// stop all streaming first
TEST_MUSTPASS(voe_base_->StopPlayout(0));
TEST_MUSTPASS(voe_base_->StopSend(0));
TEST_MUSTPASS(voe_base_->StopReceive(0));
// start loopback streaming (PCMU is default)
#ifndef WEBRTC_EXTERNAL_TRANSPORT
TEST_MUSTPASS(voe_base_->SetSendDestination(0,8000,"127.0.0.1"));
TEST_MUSTPASS(voe_base_->SetLocalReceiver(0,8000));
#endif
TEST_MUSTPASS(voe_base_->StartReceive(0));
TEST_MUSTPASS(voe_base_->StartPlayout(0));
TEST_MUSTPASS(voe_base_->StartSend(0));
SLEEP(100); // ensure that at least one packets is received
// scan all supported and valid codecs
CodecInst newCodec;
for (i = 0; i < codec->NumOfCodecs(); i++) {
TEST_MUSTPASS(codec->GetCodec(i, newCodec));
// test all valid send codecs
if (!_stricmp("red", newCodec.plname) || !_stricmp("cn", newCodec.plname)
|| !_stricmp("telephone-event", newCodec.plname)) {
continue; // Ignore these
}
if (-1 != codec->SetSendCodec(0, newCodec)) {
SLEEP(150);
// verify correct detection
TEST_MUSTPASS(codec->GetRecCodec(0, cinst));
TEST_LOG("%s %s ", newCodec.plname, cinst.plname);
TEST_MUSTPASS(_stricmp(newCodec.plname, cinst.plname) != 0);
TEST_MUSTPASS(cinst.pltype != newCodec.pltype);
TEST_MUSTPASS(cinst.plfreq != newCodec.plfreq);
}
}
// stop streaming
TEST_MUSTPASS(voe_base_->StopPlayout(0));
TEST_MUSTPASS(voe_base_->StopSend(0));
TEST_MUSTPASS(voe_base_->StopReceive(0));
ANL();
AOK();
ANL();
ANL();
#ifdef WEBRTC_CODEC_GSMAMR
//////////////////////////
// SetAMREncFormat
// Fresh channel
TEST_MUSTPASS(voe_base_->DeleteChannel(0));
TEST_MUSTPASS(voe_base_->CreateChannel());
TEST(SetAMREncFormat); ANL();
//set another codec which is not AMR
TEST_MUSTPASS(codec->GetCodec(0, cinst));
TEST_MUSTPASS(codec->SetSendCodec(0, cinst));
//try to change the encode format, tests should fail
TEST_MUSTPASS(-1 != codec->SetAMREncFormat(0)); MARK();
TEST_MUSTPASS(-1 != codec->SetAMREncFormat(0, kRfc3267BwEfficient));
MARK();
TEST_MUSTPASS(-1 != codec->SetAMREncFormat(0, kRfc3267OctetAligned));
MARK();
TEST_MUSTPASS(-1 != codec->SetAMREncFormat(0, kRfc3267FileStorage));
MARK();
//set AMR as encoder
strcpy(cinst.plname,"AMR");
cinst.channels=1; cinst.plfreq=8000; cinst.rate=12200; cinst.pltype=112;
cinst.pacsize=160;
TEST_MUSTPASS(codec->SetSendCodec(0, cinst));
//try to change the encode format, tests should pass
TEST_MUSTPASS(codec->SetAMREncFormat(0)); MARK();
TEST_MUSTPASS(codec->SetAMREncFormat(0, kRfc3267BwEfficient)); MARK();
TEST_MUSTPASS(codec->SetAMREncFormat(0, kRfc3267OctetAligned)); MARK();
TEST_MUSTPASS(codec->SetAMREncFormat(0, kRfc3267FileStorage)); MARK();
TEST_MUSTPASS(-1 != codec->SetAMREncFormat(-1)); MARK();
TEST_MUSTPASS(codec->SetAMREncFormat(0)); MARK(); // restore default
ANL();
AOK();
ANL();
//////////////////////////
// SetAMRDecFormat
TEST(SetAMRDecFormat); ANL();
// It should not be possible to set AMR dec format before valid AMR decoder
// is registered
TEST_MUSTPASS(!codec->SetAMRDecFormat(0)); MARK();
err = voe_base_->LastError();
TEST_MUSTPASS(err != VE_AUDIO_CODING_MODULE_ERROR);
// Ensure that ACM::RegisterReceiveCodec(AMR) is called
TEST_MUSTPASS(codec->SetRecPayloadType(0, cinst));
// All these tests should now pass
TEST_MUSTPASS(codec->SetAMRDecFormat(0)); MARK();
TEST_MUSTPASS(codec->SetAMRDecFormat(0, kRfc3267BwEfficient)); MARK();
TEST_MUSTPASS(codec->SetAMRDecFormat(0, kRfc3267OctetAligned)); MARK();
TEST_MUSTPASS(codec->SetAMRDecFormat(0, kRfc3267FileStorage)); MARK();
TEST_MUSTPASS(-1 != codec->SetAMRDecFormat(-1)); MARK();
TEST_MUSTPASS(codec->SetAMRDecFormat(0)); MARK(); // restore default
ANL();
AOK();
ANL();
#endif // #ifdef WEBRTC_CODEC_GSMAMR
#ifdef WEBRTC_CODEC_GSMAMRWB
//////////////////////////
// SetAMRWbEncFormat
// Fresh channel
TEST_MUSTPASS(voe_base_->DeleteChannel(0));
TEST_MUSTPASS(voe_base_->CreateChannel());
TEST(SetAMRWbEncFormat); ANL();
//set another codec which is not AMR-wb
TEST_MUSTPASS(codec->GetCodec(0, cinst));
TEST_MUSTPASS(codec->SetSendCodec(0, cinst));
//try to change the encode format, tests should fail
TEST_MUSTPASS(-1 != codec->SetAMRWbEncFormat(0)); MARK();
TEST_MUSTPASS(-1 != codec->SetAMRWbEncFormat(0, kRfc3267BwEfficient));
MARK();
TEST_MUSTPASS(-1 != codec->SetAMRWbEncFormat(0, kRfc3267OctetAligned));
MARK();
TEST_MUSTPASS(-1 != codec->SetAMRWbEncFormat(0, kRfc3267FileStorage));
MARK();
//set AMR-wb as encoder
strcpy(cinst.plname,"AMR-WB");
cinst.channels=1; cinst.plfreq=16000; cinst.rate=20000;
cinst.pltype=112; cinst.pacsize=320;
TEST_MUSTPASS(codec->SetSendCodec(0, cinst));
//try to change the encode format, tests should pass
TEST_MUSTPASS(codec->SetAMRWbEncFormat(0)); MARK();
TEST_MUSTPASS(codec->SetAMRWbEncFormat(0, kRfc3267BwEfficient)); MARK();
TEST_MUSTPASS(codec->SetAMRWbEncFormat(0, kRfc3267OctetAligned)); MARK();
TEST_MUSTPASS(codec->SetAMRWbEncFormat(0, kRfc3267FileStorage)); MARK();
TEST_MUSTPASS(-1 != codec->SetAMRWbEncFormat(-1)); MARK();
TEST_MUSTPASS(codec->SetAMRWbEncFormat(0)); MARK(); // restore default
ANL();
AOK();
ANL();
//////////////////////////
// SetAMRDecFormat
TEST(SetAMRWbDecFormat); ANL();
// It should not be possible to set AMR dec format before valid AMR decoder
// is registered
TEST_MUSTPASS(!codec->SetAMRWbDecFormat(0)); MARK();
err = voe_base_->LastError();
TEST_MUSTPASS(err != VE_AUDIO_CODING_MODULE_ERROR);
// Ensure that ACM::RegisterReceiveCodec(AMR) is called
TEST_MUSTPASS(codec->SetRecPayloadType(0, cinst));
// All these tests should now pass
TEST_MUSTPASS(codec->SetAMRWbDecFormat(0)); MARK();
TEST_MUSTPASS(codec->SetAMRWbDecFormat(0, kRfc3267BwEfficient)); MARK();
TEST_MUSTPASS(codec->SetAMRWbDecFormat(0, kRfc3267OctetAligned)); MARK();
TEST_MUSTPASS(codec->SetAMRWbDecFormat(0, kRfc3267FileStorage)); MARK();
TEST_MUSTPASS(-1 != codec->SetAMRWbDecFormat(-1)); MARK();
TEST_MUSTPASS(codec->SetAMRWbDecFormat(0)); MARK(); // restore default
ANL();
AOK();
ANL();
#endif // #ifdef WEBRTC_CODEC_GSMAMRWB
///////////////////////////////
// SetSendCNPayloadType
TEST(SetSendCNPayloadType);
ANL();
TEST_MUSTPASS(-1 != codec->SetSendCNPayloadType(-1, 0));
MARK(); // invalid channel
// Invalid payload range (only dynamic range [96,127]
TEST_MUSTPASS(-1 != codec->SetSendCNPayloadType(0, 0));
MARK(); // invalid PT
TEST_MUSTPASS(-1 != codec->SetSendCNPayloadType(0, 95));
MARK(); // invalid PT
TEST_MUSTPASS(-1 != codec->SetSendCNPayloadType(0, 128));
MARK(); // invalid PT
TEST_MUSTPASS(-1 != codec->SetSendCNPayloadType(0, -1));
MARK(); // invalid PT
// Not possible to change PT for 8000
TEST_MUSTPASS(!codec->SetSendCNPayloadType(0, 96, kFreq8000Hz));
MARK();
err = voe_base_->LastError();
TEST_MUSTPASS(err != VE_INVALID_PLFREQ);
// Try some dynamic for 16000 and 32000 as well
TEST_MUSTPASS(codec->SetSendCNPayloadType(0, 96, kFreq16000Hz));
MARK();
TEST_MUSTPASS(codec->SetSendCNPayloadType(0, 96, kFreq32000Hz));
MARK(); // same should work
TEST_MUSTPASS(codec->SetSendCNPayloadType(0, 127, kFreq16000Hz));
MARK();
TEST_MUSTPASS(codec->SetSendCNPayloadType(0, 127, kFreq32000Hz));
MARK();
TEST_MUSTPASS(codec->SetSendCNPayloadType(0, 100, kFreq32000Hz));
MARK();
ANL();
AOK();
ANL();
/////////////////////////////
// SetRecPayloadType
TEST(SetRecPayloadType);
ANL();
// scan all supported and valid codecs without changing payloads
nCodecs = codec->NumOfCodecs();
for (i = 0; i < nCodecs; i++) {
TEST_MUSTPASS(codec->GetCodec(i, newCodec));
// If no default payload type is defined, we use 127
if (-1 == newCodec.pltype) {
newCodec.pltype = 127;
}
TEST_MUSTPASS(codec->SetRecPayloadType(0, newCodec));
MARK(); // use default
newCodec.pltype = 99;
TEST_MUSTPASS(codec->SetRecPayloadType(0, newCodec));
MARK(); // use same PT on all
newCodec.pltype = -1;
TEST_MUSTPASS(codec->SetRecPayloadType(0, newCodec));
MARK(); // deregister all PTs
}
ANL();
AOK();
ANL();
/////////////////////////////
// GetRecPayloadType
TEST(GetRecPayloadType);
ANL();
CodecInst extraCodec;
for (i = 0; i < nCodecs; i++) {
// Set defaults
TEST_MUSTPASS(codec->GetCodec(i, newCodec));
// If no default payload type is defined, we use 127
if (-1 == newCodec.pltype) {
newCodec.pltype = 127;
}
TEST_MUSTPASS(codec->SetRecPayloadType(0, newCodec));
//TEST_LOG("[%2d] %s (SetRec): fs=%d, pt=%d, rate=%d, ch=%d, size=%d\n",
// i, newCodec.plname, newCodec.plfreq, newCodec.pltype, newCodec.rate,
// newCodec.channels, newCodec.pacsize);
extraCodec.pltype = -1; // don't know this yet
extraCodec.plfreq = newCodec.plfreq;
extraCodec.rate = newCodec.rate;
extraCodec.channels = newCodec.channels;
strcpy(extraCodec.plname, newCodec.plname);
// Verfify that setting is OK
TEST_MUSTPASS(codec->GetRecPayloadType(0, extraCodec));
//TEST_LOG("[%2d] %s (GetRec): fs=%d, pt=%d, rate=%d, ch=%d, size=%d\n",
// i, extraCodec.plname, extraCodec.plfreq, extraCodec.pltype,
// extraCodec.rate, extraCodec.channels, extraCodec.pacsize);
TEST_MUSTPASS(newCodec.pltype != extraCodec.pltype);
TEST_MUSTPASS(newCodec.plfreq != extraCodec.plfreq);
TEST_MUSTPASS(newCodec.channels != extraCodec.channels);
}
AOK();
ANL();
////////////////////////////////////////////////////
// SetRecPayloadType - remove receive codecs
TEST(SetRecPayloadType - removing receive codecs);
ANL();
#ifndef WEBRTC_EXTERNAL_TRANSPORT
TEST_MUSTPASS(voe_base_->SetSendDestination(0, 8000, "127.0.0.1"));
TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 8000));
#endif
TEST_MUSTPASS(voe_base_->StartSend(0));
if (file) {
TEST_MUSTPASS(file->StartPlayingFileAsMicrophone(0,
_mgr.AudioFilename(),
true,
true));
}
// Scan all supported and valid codecs and remove from receiving db, then
// restore
nCodecs = codec->NumOfCodecs();
for (i = 0; i < nCodecs; i++) {
TEST_MUSTPASS(codec->GetCodec(i, cinst));
if (!_stricmp("red", cinst.plname) || !_stricmp("cn", cinst.plname)
|| !_stricmp("telephone-event", cinst.plname)) {
continue; // Ignore these
}
TEST_LOG("Testing codec: %s", cinst.plname);
fflush(NULL);
if (-1 == cinst.pltype) {
// If no default payload type is defined, we use 127,
// codec is not registered for receiving
cinst.pltype = 127;
} else {
// Remove codec
memcpy(&extraCodec, &cinst, sizeof(CodecInst));
extraCodec.pltype = -1;
TEST_MUSTPASS(codec->SetRecPayloadType(0, extraCodec));
}
// Set send codec
TEST_MUSTPASS(codec->SetSendCodec(0, cinst));
// Verify no audio
TEST_MUSTPASS(voe_base_->StartReceive(0));
TEST_MUSTPASS(voe_base_->StartPlayout(0));
TEST_LOG(" silence");
fflush(NULL);
SLEEP(800);
TEST_MUSTPASS(voe_base_->StopPlayout(0));
TEST_MUSTPASS(voe_base_->StopReceive(0));
// Restore codec
TEST_MUSTPASS(codec->SetRecPayloadType(0, cinst));
// Verify audio
TEST_MUSTPASS(voe_base_->StartReceive(0));
TEST_MUSTPASS(voe_base_->StartPlayout(0));
TEST_LOG(" audio");
fflush(NULL);
SLEEP(800);
TEST_MUSTPASS(voe_base_->StopPlayout(0));
TEST_MUSTPASS(voe_base_->StopReceive(0));
if (127 == cinst.pltype) {
// If no default payload type is defined, i.e. we have set pt to
//127 above,
// make sure we remove codec from receiving
cinst.pltype = -1;
TEST_MUSTPASS(codec->SetRecPayloadType(0, cinst));
}
ANL();
}
// Remove certain codecs
TEST_LOG("Removing receive codecs:");
for (i = 0; i < nCodecs; i++) {
TEST_MUSTPASS(codec->GetCodec(i, cinst));
if (!_stricmp("ipcmwb", cinst.plname) || !_stricmp("pcmu", cinst.plname)
|| !_stricmp("eg711a", cinst.plname)) {
TEST_LOG(" %s", cinst.plname);
memcpy(&extraCodec, &cinst, sizeof(CodecInst));
extraCodec.pltype = -1;
TEST_MUSTPASS(codec->SetRecPayloadType(0, extraCodec));
}
}
ANL();
TEST_MUSTPASS(voe_base_->StartReceive(0));
TEST_MUSTPASS(voe_base_->StartPlayout(0));
// Test sending all codecs - verify audio/no audio depending on codec
TEST_LOG("Looping through send codecs \n");
TEST_LOG("Verify that removed codecs are not audible and the other are \n");
for (i = 0; i < nCodecs; i++) {
TEST_MUSTPASS(codec->GetCodec(i, cinst));
if (!_stricmp("red", cinst.plname) || !_stricmp("cn", cinst.plname)
|| !_stricmp("telephone-event", cinst.plname)) {
continue; // Ignore these
}
TEST_LOG("Testing codec: %s \n", cinst.plname);
// If no default payload type is defined, we use 127 and set receive
// payload type
if (-1 == cinst.pltype) {
cinst.pltype = 127;
TEST_MUSTPASS(voe_base_->StopPlayout(0));
TEST_MUSTPASS(voe_base_->StopReceive(0));
TEST_MUSTPASS(codec->SetRecPayloadType(0, cinst));
TEST_MUSTPASS(voe_base_->StartReceive(0));
TEST_MUSTPASS(voe_base_->StartPlayout(0));
}
// Set send codec
TEST_MUSTPASS(codec->SetSendCodec(0, cinst));
// Verify audio/no audio
SLEEP(800);
}
TEST_MUSTPASS(voe_base_->StopPlayout(0));
TEST_MUSTPASS(voe_base_->StopReceive(0));
// Restore codecs
TEST_LOG("Restoring receive codecs:");
for (i = 0; i < nCodecs; i++) {
TEST_MUSTPASS(codec->GetCodec(i, cinst));
if (!_stricmp("ipcmwb", cinst.plname) || !_stricmp("pcmu", cinst.plname)
|| !_stricmp("eg711a", cinst.plname)) {
TEST_LOG(" %s", cinst.plname);
memcpy(&extraCodec, &cinst, sizeof(CodecInst));
TEST_MUSTPASS(codec->SetRecPayloadType(0, cinst));
}
}
ANL();
TEST_MUSTPASS(voe_base_->StartReceive(0));
TEST_MUSTPASS(voe_base_->StartPlayout(0));
// Test sending all codecs - verify audio
TEST_LOG("Looping through send codecs \n");
TEST_LOG("Verify that all codecs are audible \n");
for (i = 0; i < nCodecs; i++) {
TEST_MUSTPASS(codec->GetCodec(i, cinst));
if (!_stricmp("red", cinst.plname) || !_stricmp("cn", cinst.plname)
|| !_stricmp("telephone-event", cinst.plname)) {
continue; // Ignore these
}
TEST_LOG("Testing codec: %s \n", cinst.plname);
// If no default payload type is defined, we use 127 and set receive
// payload type
if (-1 == cinst.pltype) {
cinst.pltype = 127;
TEST_MUSTPASS(voe_base_->StopPlayout(0));
TEST_MUSTPASS(voe_base_->StopReceive(0));
TEST_MUSTPASS(codec->SetRecPayloadType(0, cinst));
TEST_MUSTPASS(voe_base_->StartReceive(0));
TEST_MUSTPASS(voe_base_->StartPlayout(0));
}
// Set send codec
TEST_MUSTPASS(codec->SetSendCodec(0, cinst));
// Verify audio/no audio
SLEEP(800);
}
TEST_MUSTPASS(voe_base_->StopPlayout(0));
TEST_MUSTPASS(voe_base_->StopSend(0));
TEST_MUSTPASS(voe_base_->StopReceive(0));
// Fresh channel
TEST_MUSTPASS(voe_base_->DeleteChannel(0));
TEST_MUSTPASS(voe_base_->CreateChannel());
#if defined(WEBRTC_CODEC_ISAC)
/////////////////////////////////////
// SetISACInitTargetRate - wb
TEST(SetISACInitTargetRate);
ANL();
// set PCMU as sending codec
cinst.channels = 1;
cinst.pacsize = 160;
cinst.plfreq = 8000;
strcpy(cinst.plname, "PCMU");
cinst.pltype = 0;
cinst.rate = 64000;
TEST_MUSTPASS(codec->SetSendCodec(0, cinst));
TEST_MUSTPASS(!codec->SetISACInitTargetRate(0, 10000));
MARK(); // should fail since iSAC is not active
err = voe_base_->LastError();
TEST_MUSTPASS(err != VE_CODEC_ERROR);
// set iSAC as sending codec (16kHz)
cinst.channels = 1;
cinst.plfreq = 16000;
strcpy(cinst.plname, "ISAC");
cinst.pltype = 103;
cinst.rate = -1; // adaptive rate
cinst.pacsize = 480; // 30ms
TEST_MUSTPASS(codec->SetSendCodec(0, cinst));
TEST_MUSTPASS(!codec->SetISACInitTargetRate(1, 10000));
MARK(); // invalid channel
err = voe_base_->LastError();
TEST_MUSTPASS(err != VE_CHANNEL_NOT_VALID);
TEST_MUSTPASS(!codec->SetISACInitTargetRate(0, 500));
MARK(); // invalid target rates (too small)
err = voe_base_->LastError();
TEST_MUSTPASS(err != VE_INVALID_ARGUMENT);
TEST_MUSTPASS(!codec->SetISACInitTargetRate(0, 33000));
MARK(); // invalid target rates (too large)
err = voe_base_->LastError();
TEST_MUSTPASS(err != VE_INVALID_ARGUMENT);
TEST_MUSTPASS(codec->SetISACInitTargetRate(0, 10000));
MARK(); // life is good now
TEST_MUSTPASS(codec->SetISACInitTargetRate(0, 0));
MARK(); // 0 is a valid rate
TEST_MUSTPASS(codec->SetISACInitTargetRate(0, 32000));
MARK(); // try max as well
TEST_MUSTPASS(codec->SetISACInitTargetRate(0, 32000, true));
MARK();
TEST_MUSTPASS(codec->SetISACInitTargetRate(0, 32000, false));
MARK();
cinst.pacsize = 960; // 60ms
TEST_MUSTPASS(codec->SetSendCodec(0, cinst));
TEST_MUSTPASS(codec->SetISACInitTargetRate(0, 32000, false));
MARK();
cinst.rate = 20000;
TEST_MUSTPASS(codec->SetSendCodec(0, cinst));
TEST_MUSTPASS(!codec->SetISACInitTargetRate(0, 32000));
MARK(); // only works in adaptive mode
err = voe_base_->LastError();
TEST_MUSTPASS(err != VE_AUDIO_CODING_MODULE_ERROR);
cinst.rate = -1;
TEST_MUSTPASS(codec->SetSendCodec(0, cinst));
TEST_MUSTPASS(codec->SetISACInitTargetRate(0, 32000));
MARK(); // back to adaptive mode
ANL();
AOK();
ANL();
/////////////////////////////////////
// SetISACInitTargetRate - swb
TEST(ISACSWB SetISACInitTargetRate);
ANL();
// set iSAC as sending codec
cinst.channels = 1;
cinst.plfreq = 32000;
strcpy(cinst.plname, "ISAC");
cinst.pltype = 104;
cinst.rate = -1; // default rate
cinst.pacsize = 960; // 30ms
TEST_MUSTPASS(codec->SetSendCodec(0, cinst));
TEST_MUSTPASS(!codec->SetISACInitTargetRate(1, 10000));
MARK(); // invalid channel
err = voe_base_->LastError();
TEST_MUSTPASS(err != VE_CHANNEL_NOT_VALID);
TEST_MUSTPASS(!codec->SetISACInitTargetRate(0, -1));
MARK(); // invalid target rates (too small)
err = voe_base_->LastError();
TEST_MUSTPASS(err != VE_INVALID_ARGUMENT);
TEST_MUSTPASS(!codec->SetISACInitTargetRate(0, -1));
MARK(); // invalid target rates (too small)
err = voe_base_->LastError();
TEST_MUSTPASS(err != VE_INVALID_ARGUMENT);
TEST_MUSTPASS(!codec->SetISACInitTargetRate(0, 500));
MARK(); // invalid target rates (too small)
err = voe_base_->LastError();
TEST_MUSTPASS(err != VE_INVALID_ARGUMENT);
TEST_MUSTPASS(!codec->SetISACInitTargetRate(0, 57000));
MARK(); // invalid target rates (valid range is [10000, 56000])
err = voe_base_->LastError();
TEST_MUSTPASS(err != VE_INVALID_ARGUMENT);
TEST_MUSTPASS(codec->SetISACInitTargetRate(0, 10000));
MARK();
TEST_MUSTPASS(codec->SetISACInitTargetRate(0, 0));
MARK();
TEST_MUSTPASS(codec->SetISACInitTargetRate(0, 56000));
MARK(); // try max as well
TEST_MUSTPASS(codec->SetISACInitTargetRate(0, 56000, true));
MARK();
TEST_MUSTPASS(codec->SetISACInitTargetRate(0, 56000, false));
MARK();
ANL();
AOK();
ANL();
////////////////////////////////
// SetISACMaxRate
TEST(SetISACMaxRate);
ANL();
// set PCMU as sending codec
cinst.channels = 1;
cinst.pacsize = 160;
cinst.plfreq = 8000;
strcpy(cinst.plname, "PCMU");
cinst.pltype = 0;
cinst.rate = 64000;
TEST_MUSTPASS(codec->SetSendCodec(0, cinst));
TEST_MUSTPASS(!codec->SetISACMaxRate(0, 48000));
MARK(); // should fail since iSAC is not active
TEST_MUSTPASS(voe_base_->LastError() != VE_CODEC_ERROR);
// set iSAC as sending codec
cinst.channels = 1;
cinst.plfreq = 16000;
strcpy(cinst.plname, "ISAC");
cinst.pltype = 103;
cinst.rate = -1; // adaptive rate
cinst.pacsize = 480; // 30ms
TEST_MUSTPASS(codec->SetSendCodec(0, cinst));
TEST_MUSTPASS(!codec->SetISACMaxRate(1, 48000));
MARK(); // invalid channel
TEST_MUSTPASS(voe_base_->LastError() != VE_CHANNEL_NOT_VALID);
TEST_MUSTPASS(!codec->SetISACMaxRate(0, 31900));
MARK(); // invalid target rates (too small)
TEST_MUSTPASS(voe_base_->LastError() != VE_INVALID_ARGUMENT);
TEST_MUSTPASS(!codec->SetISACMaxRate(0, 53500));
MARK(); // invalid target rates (too large)
TEST_MUSTPASS(voe_base_->LastError() != VE_INVALID_ARGUMENT);
TEST_MUSTPASS(codec->SetISACMaxRate(0, 32000));
MARK(); // life is good now
TEST_MUSTPASS(codec->SetISACMaxRate(0, 40000));
MARK();
TEST_MUSTPASS(codec->SetISACMaxRate(0, 48000));
MARK();
TEST_MUSTPASS(codec->SetISACMaxRate(0, 53400));
MARK(); // try max as well (default)
cinst.pacsize = 960; // 60ms
TEST_MUSTPASS(codec->SetSendCodec(0, cinst));
TEST_MUSTPASS(codec->SetISACMaxRate(0, 48000));
MARK();
cinst.rate = 20000;
TEST_MUSTPASS(codec->SetSendCodec(0, cinst));
TEST_MUSTPASS(codec->SetISACMaxRate(0, 40000));
MARK(); // also works in non-adaptive mode
ANL();
AOK();
ANL();
TEST(ISACSWB SetISACMaxRate);
ANL();
// set iSAC as sending codec
cinst.channels = 1;
cinst.plfreq = 32000;
strcpy(cinst.plname, "ISAC");
cinst.pltype = 104;
cinst.rate = 45000; // instantaneous mode
cinst.pacsize = 960; // 30ms
TEST_MUSTPASS(codec->SetSendCodec(0, cinst));
TEST_MUSTPASS(!codec->SetISACMaxRate(1, 48000));
MARK(); // invalid channel
TEST_MUSTPASS(voe_base_->LastError() != VE_CHANNEL_NOT_VALID);
TEST_MUSTPASS(!codec->SetISACMaxRate(0, 31900));
MARK(); // invalid target rates (too small)
TEST_MUSTPASS(voe_base_->LastError() != VE_INVALID_ARGUMENT);
TEST_MUSTPASS(!codec->SetISACMaxRate(0, 107500));
MARK(); // invalid target rates (too large)
TEST_MUSTPASS(voe_base_->LastError() != VE_INVALID_ARGUMENT);
TEST_MUSTPASS(codec->SetISACMaxRate(0, 32000));
MARK(); // life is good now
TEST_MUSTPASS(codec->SetISACMaxRate(0, 40000));
MARK();
TEST_MUSTPASS(codec->SetISACMaxRate(0, 55000));
MARK();
TEST_MUSTPASS(codec->SetISACMaxRate(0, 80000));
MARK();
TEST_MUSTPASS(codec->SetISACMaxRate(0, 107000));
MARK(); // try max as well (default)
cinst.rate = -1; // adaptive mode
cinst.pacsize = 960; // 30ms
TEST_MUSTPASS(codec->SetSendCodec(0, cinst));
TEST_MUSTPASS(!codec->SetISACMaxRate(1, 48000));
MARK(); // invalid channel
TEST_MUSTPASS(voe_base_->LastError() != VE_CHANNEL_NOT_VALID);
TEST_MUSTPASS(!codec->SetISACMaxRate(0, 31900));
MARK(); // invalid target rates (too small)
TEST_MUSTPASS(voe_base_->LastError() != VE_INVALID_ARGUMENT);
TEST_MUSTPASS(!codec->SetISACMaxRate(0, 107500));
MARK(); // invalid target rates (too large)
TEST_MUSTPASS(voe_base_->LastError() != VE_INVALID_ARGUMENT);
TEST_MUSTPASS(codec->SetISACMaxRate(0, 32000));
MARK(); // life is good now
TEST_MUSTPASS(codec->SetISACMaxRate(0, 40000));
MARK();
TEST_MUSTPASS(codec->SetISACMaxRate(0, 55000));
MARK();
TEST_MUSTPASS(codec->SetISACMaxRate(0, 80000));
MARK();
TEST_MUSTPASS(codec->SetISACMaxRate(0, 107000));
MARK(); // try max as well (default)
ANL();
AOK();
ANL();
////////////////////////////////
// SetISACMaxPayloadSize
TEST(SetISACMaxPayloadSize);
ANL();
// set PCMU as sending codec
cinst.channels = 1;
cinst.pacsize = 160;
cinst.plfreq = 8000;
strcpy(cinst.plname, "PCMU");
cinst.pltype = 0;
cinst.rate = 64000;
TEST_MUSTPASS(codec->SetSendCodec(0, cinst));
TEST_MUSTPASS(!codec->SetISACMaxPayloadSize(0, 120));
MARK(); // should fail since iSAC is not active
err = voe_base_->LastError();
TEST_MUSTPASS(err != VE_CODEC_ERROR);
// set iSAC as sending codec
cinst.channels = 1;
cinst.plfreq = 16000;
strcpy(cinst.plname, "ISAC");
cinst.pltype = 103;
cinst.rate = -1; // adaptive rate
cinst.pacsize = 480; // 30ms
TEST_MUSTPASS(codec->SetSendCodec(0, cinst));
TEST_MUSTPASS(!codec->SetISACMaxPayloadSize(1, 120));
MARK(); // invalid channel
err = voe_base_->LastError();
TEST_MUSTPASS(err != VE_CHANNEL_NOT_VALID);
TEST_MUSTPASS(!codec->SetISACMaxPayloadSize(0, 100));
MARK(); // invalid size (too small)
err = voe_base_->LastError();
TEST_MUSTPASS(err != VE_INVALID_ARGUMENT);
TEST_MUSTPASS(!codec->SetISACMaxPayloadSize(0, 410));
MARK(); // invalid size (too large)
err = voe_base_->LastError();
TEST_MUSTPASS(err != VE_INVALID_ARGUMENT);
TEST_MUSTPASS(codec->SetISACMaxPayloadSize(0, 200));
MARK(); // life is good now
TEST_MUSTPASS(codec->SetISACMaxPayloadSize(0, 120));
MARK();
TEST_MUSTPASS(codec->SetISACMaxPayloadSize(0, 400));
MARK();
ANL();
AOK();
ANL();
TEST(ISACSWB SetISACMaxPayloadSize);
ANL();
// set iSAC as sending codec
cinst.channels = 1;
cinst.plfreq = 32000;
strcpy(cinst.plname, "ISAC");
cinst.pltype = 104;
cinst.rate = 45000; // default rate
cinst.pacsize = 960; // 30ms
TEST_MUSTPASS(codec->SetSendCodec(0, cinst));
TEST_MUSTPASS(!codec->SetISACMaxPayloadSize(1, 100));
MARK(); // invalid channel
err = voe_base_->LastError();
TEST_MUSTPASS(err != VE_CHANNEL_NOT_VALID);
TEST_MUSTPASS(!codec->SetISACMaxPayloadSize(0, 100));
MARK(); // invalid size (too small)
err = voe_base_->LastError();
TEST_MUSTPASS(err != VE_INVALID_ARGUMENT);
TEST_MUSTPASS(!codec->SetISACMaxPayloadSize(0, 610));
MARK(); // invalid size (too large)