I'm splitting the timer functions in EventWrapper into a separate interface. - Users of the timer functions have different needs than users of a generic event - Providing a default implementation for EventWrapper that simply uses rtc::Event. This means that clients of WebRTC that don't use the relatively few classes, typically rendering classes, that depend on the event timer functionality, also don't pull in dependencies on multimedia timers. R=mflodman@webrtc.org, mflodman BUG= Review URL: https://webrtc-codereview.appspot.com/48599004 Cr-Commit-Position: refs/heads/master@{#8833} git-svn-id: http://webrtc.googlecode.com/svn/trunk@8833 4adac7df-926f-26a2-2b94-8c16560cd09d
1192 lines
33 KiB
C++
1192 lines
33 KiB
C++
/*
|
|
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license
|
|
* that can be found in the LICENSE file in the root of the source
|
|
* tree. An additional intellectual property rights grant can be found
|
|
* in the file PATENTS. All contributing project authors may
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
*/
|
|
|
|
#include "webrtc/modules/audio_coding/main/test/APITest.h"
|
|
|
|
#include <ctype.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include <iostream>
|
|
#include <ostream>
|
|
#include <string>
|
|
|
|
#include "testing/gtest/include/gtest/gtest.h"
|
|
#include "webrtc/common.h"
|
|
#include "webrtc/common_types.h"
|
|
#include "webrtc/engine_configurations.h"
|
|
#include "webrtc/modules/audio_coding/main/acm2/acm_common_defs.h"
|
|
#include "webrtc/modules/audio_coding/main/test/utility.h"
|
|
#include "webrtc/system_wrappers/interface/event_wrapper.h"
|
|
#include "webrtc/system_wrappers/interface/thread_wrapper.h"
|
|
#include "webrtc/system_wrappers/interface/tick_util.h"
|
|
#include "webrtc/system_wrappers/interface/trace.h"
|
|
#include "webrtc/test/testsupport/fileutils.h"
|
|
|
|
namespace webrtc {
|
|
|
|
#define TEST_DURATION_SEC 600
|
|
#define NUMBER_OF_SENDER_TESTS 6
|
|
#define MAX_FILE_NAME_LENGTH_BYTE 500
|
|
#define CHECK_THREAD_NULLITY(myThread, S) \
|
|
if(myThread != NULL) { \
|
|
(myThread)->Start(); \
|
|
} else { \
|
|
ADD_FAILURE() << S; \
|
|
}
|
|
|
|
void APITest::Wait(uint32_t waitLengthMs) {
|
|
if (_randomTest) {
|
|
return;
|
|
} else {
|
|
EventWrapper* myEvent = EventWrapper::Create();
|
|
myEvent->Wait(waitLengthMs);
|
|
delete myEvent;
|
|
return;
|
|
}
|
|
}
|
|
|
|
APITest::APITest(const Config& config)
|
|
: _acmA(AudioCodingModule::Create(1)),
|
|
_acmB(AudioCodingModule::Create(2)),
|
|
_channel_A2B(NULL),
|
|
_channel_B2A(NULL),
|
|
_writeToFile(true),
|
|
_pullEventA(NULL),
|
|
_pushEventA(NULL),
|
|
_processEventA(NULL),
|
|
_apiEventA(NULL),
|
|
_pullEventB(NULL),
|
|
_pushEventB(NULL),
|
|
_processEventB(NULL),
|
|
_apiEventB(NULL),
|
|
_codecCntrA(0),
|
|
_codecCntrB(0),
|
|
_thereIsEncoderA(false),
|
|
_thereIsEncoderB(false),
|
|
_thereIsDecoderA(false),
|
|
_thereIsDecoderB(false),
|
|
_sendVADA(false),
|
|
_sendDTXA(false),
|
|
_sendVADModeA(VADNormal),
|
|
_sendVADB(false),
|
|
_sendDTXB(false),
|
|
_sendVADModeB(VADNormal),
|
|
_minDelayA(0),
|
|
_minDelayB(0),
|
|
_dotPositionA(0),
|
|
_dotMoveDirectionA(1),
|
|
_dotPositionB(39),
|
|
_dotMoveDirectionB(-1),
|
|
_dtmfCallback(NULL),
|
|
_vadCallbackA(NULL),
|
|
_vadCallbackB(NULL),
|
|
_apiTestRWLock(*RWLockWrapper::CreateRWLock()),
|
|
_randomTest(false),
|
|
_testNumA(0),
|
|
_testNumB(1) {
|
|
int n;
|
|
for (n = 0; n < 32; n++) {
|
|
_payloadUsed[n] = false;
|
|
}
|
|
|
|
_movingDot[40] = '\0';
|
|
|
|
for (int n = 0; n < 40; n++) {
|
|
_movingDot[n] = ' ';
|
|
}
|
|
}
|
|
|
|
APITest::~APITest() {
|
|
DELETE_POINTER(_channel_A2B);
|
|
DELETE_POINTER(_channel_B2A);
|
|
|
|
DELETE_POINTER(_pushEventA);
|
|
DELETE_POINTER(_pullEventA);
|
|
DELETE_POINTER(_processEventA);
|
|
DELETE_POINTER(_apiEventA);
|
|
|
|
DELETE_POINTER(_pushEventB);
|
|
DELETE_POINTER(_pullEventB);
|
|
DELETE_POINTER(_processEventB);
|
|
DELETE_POINTER(_apiEventB);
|
|
|
|
_inFileA.Close();
|
|
_outFileA.Close();
|
|
|
|
_inFileB.Close();
|
|
_outFileB.Close();
|
|
|
|
DELETE_POINTER(_dtmfCallback);
|
|
DELETE_POINTER(_vadCallbackA);
|
|
DELETE_POINTER(_vadCallbackB);
|
|
|
|
delete &_apiTestRWLock;
|
|
}
|
|
|
|
int16_t APITest::SetUp() {
|
|
CodecInst dummyCodec;
|
|
int lastPayloadType = 0;
|
|
|
|
int16_t numCodecs = _acmA->NumberOfCodecs();
|
|
for (uint8_t n = 0; n < numCodecs; n++) {
|
|
AudioCodingModule::Codec(n, &dummyCodec);
|
|
if ((STR_CASE_CMP(dummyCodec.plname, "CN") == 0)
|
|
&& (dummyCodec.plfreq == 32000)) {
|
|
continue;
|
|
}
|
|
|
|
printf("Register Receive Codec %s ", dummyCodec.plname);
|
|
|
|
if ((n != 0) && !FixedPayloadTypeCodec(dummyCodec.plname)) {
|
|
// Check registration with an already occupied payload type
|
|
int currentPayloadType = dummyCodec.pltype;
|
|
dummyCodec.pltype = 97; //lastPayloadType;
|
|
CHECK_ERROR(_acmB->RegisterReceiveCodec(dummyCodec));
|
|
dummyCodec.pltype = currentPayloadType;
|
|
}
|
|
|
|
if ((n < numCodecs - 1) && !FixedPayloadTypeCodec(dummyCodec.plname)) {
|
|
// test if re-registration works;
|
|
CodecInst nextCodec;
|
|
int currentPayloadType = dummyCodec.pltype;
|
|
AudioCodingModule::Codec(n + 1, &nextCodec);
|
|
dummyCodec.pltype = nextCodec.pltype;
|
|
if (!FixedPayloadTypeCodec(nextCodec.plname)) {
|
|
_acmB->RegisterReceiveCodec(dummyCodec);
|
|
}
|
|
dummyCodec.pltype = currentPayloadType;
|
|
}
|
|
|
|
if ((n < numCodecs - 1) && !FixedPayloadTypeCodec(dummyCodec.plname)) {
|
|
// test if un-registration works;
|
|
CodecInst nextCodec;
|
|
AudioCodingModule::Codec(n + 1, &nextCodec);
|
|
nextCodec.pltype = dummyCodec.pltype;
|
|
if (!FixedPayloadTypeCodec(nextCodec.plname)) {
|
|
CHECK_ERROR_MT(_acmA->RegisterReceiveCodec(nextCodec));
|
|
CHECK_ERROR_MT(_acmA->UnregisterReceiveCodec(nextCodec.pltype));
|
|
}
|
|
}
|
|
|
|
CHECK_ERROR_MT(_acmA->RegisterReceiveCodec(dummyCodec));
|
|
printf(" side A done!");
|
|
CHECK_ERROR_MT(_acmB->RegisterReceiveCodec(dummyCodec));
|
|
printf(" side B done!\n");
|
|
|
|
if (!strcmp(dummyCodec.plname, "CN")) {
|
|
CHECK_ERROR_MT(_acmA->RegisterSendCodec(dummyCodec));
|
|
CHECK_ERROR_MT(_acmB->RegisterSendCodec(dummyCodec));
|
|
}
|
|
lastPayloadType = dummyCodec.pltype;
|
|
if ((lastPayloadType >= 96) && (lastPayloadType <= 127)) {
|
|
_payloadUsed[lastPayloadType - 96] = true;
|
|
}
|
|
}
|
|
_thereIsDecoderA = true;
|
|
_thereIsDecoderB = true;
|
|
|
|
// Register Send Codec
|
|
AudioCodingModule::Codec((uint8_t) _codecCntrA, &dummyCodec);
|
|
CHECK_ERROR_MT(_acmA->RegisterSendCodec(dummyCodec));
|
|
_thereIsEncoderA = true;
|
|
//
|
|
AudioCodingModule::Codec((uint8_t) _codecCntrB, &dummyCodec);
|
|
CHECK_ERROR_MT(_acmB->RegisterSendCodec(dummyCodec));
|
|
_thereIsEncoderB = true;
|
|
|
|
uint16_t frequencyHz;
|
|
|
|
printf("\n\nAPI Test\n");
|
|
printf("========\n");
|
|
printf("Hit enter to accept the default values indicated in []\n\n");
|
|
|
|
//--- Input A
|
|
std::string file_name = webrtc::test::ResourcePath(
|
|
"audio_coding/testfile32kHz", "pcm");
|
|
frequencyHz = 32000;
|
|
printf("Enter input file at side A [%s]: ", file_name.c_str());
|
|
PCMFile::ChooseFile(&file_name, 499, &frequencyHz);
|
|
_inFileA.Open(file_name, frequencyHz, "rb", true);
|
|
|
|
//--- Output A
|
|
std::string out_file_a = webrtc::test::OutputPath() + "outA.pcm";
|
|
printf("Enter output file at side A [%s]: ", out_file_a.c_str());
|
|
PCMFile::ChooseFile(&out_file_a, 499, &frequencyHz);
|
|
_outFileA.Open(out_file_a, frequencyHz, "wb");
|
|
|
|
//--- Input B
|
|
file_name = webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm");
|
|
printf("\n\nEnter input file at side B [%s]: ", file_name.c_str());
|
|
PCMFile::ChooseFile(&file_name, 499, &frequencyHz);
|
|
_inFileB.Open(file_name, frequencyHz, "rb", true);
|
|
|
|
//--- Output B
|
|
std::string out_file_b = webrtc::test::OutputPath() + "outB.pcm";
|
|
printf("Enter output file at side B [%s]: ", out_file_b.c_str());
|
|
PCMFile::ChooseFile(&out_file_b, 499, &frequencyHz);
|
|
_outFileB.Open(out_file_b, frequencyHz, "wb");
|
|
|
|
//--- Set A-to-B channel
|
|
_channel_A2B = new Channel(2);
|
|
CHECK_ERROR_MT(_acmA->RegisterTransportCallback(_channel_A2B));
|
|
_channel_A2B->RegisterReceiverACM(_acmB.get());
|
|
|
|
//--- Set B-to-A channel
|
|
_channel_B2A = new Channel(1);
|
|
CHECK_ERROR_MT(_acmB->RegisterTransportCallback(_channel_B2A));
|
|
_channel_B2A->RegisterReceiverACM(_acmA.get());
|
|
|
|
//--- EVENT TIMERS
|
|
// A
|
|
_pullEventA = EventTimerWrapper::Create();
|
|
_pushEventA = EventTimerWrapper::Create();
|
|
_processEventA = EventTimerWrapper::Create();
|
|
_apiEventA = EventWrapper::Create();
|
|
// B
|
|
_pullEventB = EventTimerWrapper::Create();
|
|
_pushEventB = EventTimerWrapper::Create();
|
|
_processEventB = EventTimerWrapper::Create();
|
|
_apiEventB = EventWrapper::Create();
|
|
|
|
//--- I/O params
|
|
// A
|
|
_outFreqHzA = _outFileA.SamplingFrequency();
|
|
// B
|
|
_outFreqHzB = _outFileB.SamplingFrequency();
|
|
|
|
//Trace::SetEncryptedTraceFile("ACMAPITestEncrypted.txt");
|
|
|
|
char print[11];
|
|
|
|
// Create a trace file.
|
|
Trace::CreateTrace();
|
|
Trace::SetTraceFile(
|
|
(webrtc::test::OutputPath() + "acm_api_trace.txt").c_str());
|
|
|
|
printf("\nRandom Test (y/n)?");
|
|
EXPECT_TRUE(fgets(print, 10, stdin) != NULL);
|
|
print[10] = '\0';
|
|
if (strstr(print, "y") != NULL) {
|
|
_randomTest = true;
|
|
_verbose = false;
|
|
_writeToFile = false;
|
|
} else {
|
|
_randomTest = false;
|
|
printf("\nPrint Tests (y/n)? ");
|
|
EXPECT_TRUE(fgets(print, 10, stdin) != NULL);
|
|
print[10] = '\0';
|
|
if (strstr(print, "y") == NULL) {
|
|
EXPECT_TRUE(freopen("APITest_log.txt", "w", stdout) != 0);
|
|
_verbose = false;
|
|
}
|
|
}
|
|
|
|
#ifdef WEBRTC_DTMF_DETECTION
|
|
_dtmfCallback = new DTMFDetector;
|
|
#endif
|
|
_vadCallbackA = new VADCallback;
|
|
_vadCallbackB = new VADCallback;
|
|
|
|
return 0;
|
|
}
|
|
|
|
bool APITest::PushAudioThreadA(void* obj) {
|
|
return static_cast<APITest*>(obj)->PushAudioRunA();
|
|
}
|
|
|
|
bool APITest::PushAudioThreadB(void* obj) {
|
|
return static_cast<APITest*>(obj)->PushAudioRunB();
|
|
}
|
|
|
|
bool APITest::PullAudioThreadA(void* obj) {
|
|
return static_cast<APITest*>(obj)->PullAudioRunA();
|
|
}
|
|
|
|
bool APITest::PullAudioThreadB(void* obj) {
|
|
return static_cast<APITest*>(obj)->PullAudioRunB();
|
|
}
|
|
|
|
bool APITest::ProcessThreadA(void* obj) {
|
|
return static_cast<APITest*>(obj)->ProcessRunA();
|
|
}
|
|
|
|
bool APITest::ProcessThreadB(void* obj) {
|
|
return static_cast<APITest*>(obj)->ProcessRunB();
|
|
}
|
|
|
|
bool APITest::APIThreadA(void* obj) {
|
|
return static_cast<APITest*>(obj)->APIRunA();
|
|
}
|
|
|
|
bool APITest::APIThreadB(void* obj) {
|
|
return static_cast<APITest*>(obj)->APIRunB();
|
|
}
|
|
|
|
bool APITest::PullAudioRunA() {
|
|
_pullEventA->Wait(100);
|
|
AudioFrame audioFrame;
|
|
if (_acmA->PlayoutData10Ms(_outFreqHzA, &audioFrame) < 0) {
|
|
bool thereIsDecoder;
|
|
{
|
|
ReadLockScoped rl(_apiTestRWLock);
|
|
thereIsDecoder = _thereIsDecoderA;
|
|
}
|
|
if (thereIsDecoder) {
|
|
fprintf(stderr, "\n>>>>>> cannot pull audio A <<<<<<<< \n");
|
|
}
|
|
} else {
|
|
if (_writeToFile) {
|
|
_outFileA.Write10MsData(audioFrame);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool APITest::PullAudioRunB() {
|
|
_pullEventB->Wait(100);
|
|
AudioFrame audioFrame;
|
|
if (_acmB->PlayoutData10Ms(_outFreqHzB, &audioFrame) < 0) {
|
|
bool thereIsDecoder;
|
|
{
|
|
ReadLockScoped rl(_apiTestRWLock);
|
|
thereIsDecoder = _thereIsDecoderB;
|
|
}
|
|
if (thereIsDecoder) {
|
|
fprintf(stderr, "\n>>>>>> cannot pull audio B <<<<<<<< \n");
|
|
fprintf(stderr, "%d %d\n", _testNumA, _testNumB);
|
|
}
|
|
} else {
|
|
if (_writeToFile) {
|
|
_outFileB.Write10MsData(audioFrame);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool APITest::PushAudioRunA() {
|
|
_pushEventA->Wait(100);
|
|
AudioFrame audioFrame;
|
|
_inFileA.Read10MsData(audioFrame);
|
|
if (_acmA->Add10MsData(audioFrame) < 0) {
|
|
bool thereIsEncoder;
|
|
{
|
|
ReadLockScoped rl(_apiTestRWLock);
|
|
thereIsEncoder = _thereIsEncoderA;
|
|
}
|
|
if (thereIsEncoder) {
|
|
fprintf(stderr, "\n>>>> add10MsData at A failed <<<<\n");
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool APITest::PushAudioRunB() {
|
|
_pushEventB->Wait(100);
|
|
AudioFrame audioFrame;
|
|
_inFileB.Read10MsData(audioFrame);
|
|
if (_acmB->Add10MsData(audioFrame) < 0) {
|
|
bool thereIsEncoder;
|
|
{
|
|
ReadLockScoped rl(_apiTestRWLock);
|
|
thereIsEncoder = _thereIsEncoderB;
|
|
}
|
|
|
|
if (thereIsEncoder) {
|
|
fprintf(stderr, "\n>>>> cannot add audio to B <<<<");
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool APITest::ProcessRunA() {
|
|
_processEventA->Wait(100);
|
|
return true;
|
|
}
|
|
|
|
bool APITest::ProcessRunB() {
|
|
_processEventB->Wait(100);
|
|
return true;
|
|
}
|
|
|
|
/*/
|
|
*
|
|
* In side A we test the APIs which are related to sender Side.
|
|
*
|
|
/*/
|
|
|
|
void APITest::RunTest(char thread) {
|
|
int testNum;
|
|
{
|
|
WriteLockScoped cs(_apiTestRWLock);
|
|
if (thread == 'A') {
|
|
_testNumA = (_testNumB + 1 + (rand() % 4)) % 5;
|
|
testNum = _testNumA;
|
|
|
|
_movingDot[_dotPositionA] = ' ';
|
|
if (_dotPositionA == 0) {
|
|
_dotMoveDirectionA = 1;
|
|
}
|
|
if (_dotPositionA == 19) {
|
|
_dotMoveDirectionA = -1;
|
|
}
|
|
_dotPositionA += _dotMoveDirectionA;
|
|
_movingDot[_dotPositionA] = (_dotMoveDirectionA > 0) ? '>' : '<';
|
|
} else {
|
|
_testNumB = (_testNumA + 1 + (rand() % 4)) % 5;
|
|
testNum = _testNumB;
|
|
|
|
_movingDot[_dotPositionB] = ' ';
|
|
if (_dotPositionB == 20) {
|
|
_dotMoveDirectionB = 1;
|
|
}
|
|
if (_dotPositionB == 39) {
|
|
_dotMoveDirectionB = -1;
|
|
}
|
|
_dotPositionB += _dotMoveDirectionB;
|
|
_movingDot[_dotPositionB] = (_dotMoveDirectionB > 0) ? '>' : '<';
|
|
}
|
|
//fprintf(stderr, "%c: %d \n", thread, testNum);
|
|
//fflush(stderr);
|
|
}
|
|
switch (testNum) {
|
|
case 0:
|
|
CurrentCodec('A');
|
|
ChangeCodec('A');
|
|
break;
|
|
case 1:
|
|
TestPlayout('B');
|
|
break;
|
|
case 2:
|
|
if (!_randomTest) {
|
|
fprintf(stdout, "\nTesting Delay ...\n");
|
|
}
|
|
TestDelay('A');
|
|
break;
|
|
case 3:
|
|
TestSendVAD('A');
|
|
break;
|
|
case 4:
|
|
TestRegisteration('A');
|
|
break;
|
|
default:
|
|
fprintf(stderr, "Wrong Test Number\n");
|
|
getc(stdin);
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
bool APITest::APIRunA() {
|
|
_apiEventA->Wait(50);
|
|
|
|
bool randomTest;
|
|
{
|
|
ReadLockScoped rl(_apiTestRWLock);
|
|
randomTest = _randomTest;
|
|
}
|
|
if (randomTest) {
|
|
RunTest('A');
|
|
} else {
|
|
CurrentCodec('A');
|
|
ChangeCodec('A');
|
|
TestPlayout('B');
|
|
if (_codecCntrA == 0) {
|
|
fprintf(stdout, "\nTesting Delay ...\n");
|
|
TestDelay('A');
|
|
}
|
|
// VAD TEST
|
|
TestSendVAD('A');
|
|
TestRegisteration('A');
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool APITest::APIRunB() {
|
|
_apiEventB->Wait(50);
|
|
bool randomTest;
|
|
{
|
|
ReadLockScoped rl(_apiTestRWLock);
|
|
randomTest = _randomTest;
|
|
}
|
|
//_apiEventB->Wait(2000);
|
|
if (randomTest) {
|
|
RunTest('B');
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void APITest::Perform() {
|
|
SetUp();
|
|
|
|
//--- THREADS
|
|
// A
|
|
// PUSH
|
|
rtc::scoped_ptr<ThreadWrapper> myPushAudioThreadA =
|
|
ThreadWrapper::CreateThread(PushAudioThreadA, this, "PushAudioThreadA");
|
|
CHECK_THREAD_NULLITY(myPushAudioThreadA, "Unable to start A::PUSH thread");
|
|
// PULL
|
|
rtc::scoped_ptr<ThreadWrapper> myPullAudioThreadA =
|
|
ThreadWrapper::CreateThread(PullAudioThreadA, this, "PullAudioThreadA");
|
|
CHECK_THREAD_NULLITY(myPullAudioThreadA, "Unable to start A::PULL thread");
|
|
// Process
|
|
rtc::scoped_ptr<ThreadWrapper> myProcessThreadA = ThreadWrapper::CreateThread(
|
|
ProcessThreadA, this, "ProcessThreadA");
|
|
CHECK_THREAD_NULLITY(myProcessThreadA, "Unable to start A::Process thread");
|
|
// API
|
|
rtc::scoped_ptr<ThreadWrapper> myAPIThreadA = ThreadWrapper::CreateThread(
|
|
APIThreadA, this, "APIThreadA");
|
|
CHECK_THREAD_NULLITY(myAPIThreadA, "Unable to start A::API thread");
|
|
// B
|
|
// PUSH
|
|
rtc::scoped_ptr<ThreadWrapper> myPushAudioThreadB =
|
|
ThreadWrapper::CreateThread(PushAudioThreadB, this, "PushAudioThreadB");
|
|
CHECK_THREAD_NULLITY(myPushAudioThreadB, "Unable to start B::PUSH thread");
|
|
// PULL
|
|
rtc::scoped_ptr<ThreadWrapper> myPullAudioThreadB =
|
|
ThreadWrapper::CreateThread(PullAudioThreadB, this, "PullAudioThreadB");
|
|
CHECK_THREAD_NULLITY(myPullAudioThreadB, "Unable to start B::PULL thread");
|
|
// Process
|
|
rtc::scoped_ptr<ThreadWrapper> myProcessThreadB = ThreadWrapper::CreateThread(
|
|
ProcessThreadB, this, "ProcessThreadB");
|
|
CHECK_THREAD_NULLITY(myProcessThreadB, "Unable to start B::Process thread");
|
|
// API
|
|
rtc::scoped_ptr<ThreadWrapper> myAPIThreadB = ThreadWrapper::CreateThread(
|
|
APIThreadB, this, "APIThreadB");
|
|
CHECK_THREAD_NULLITY(myAPIThreadB, "Unable to start B::API thread");
|
|
|
|
//_apiEventA->StartTimer(true, 5000);
|
|
//_apiEventB->StartTimer(true, 5000);
|
|
|
|
_processEventA->StartTimer(true, 10);
|
|
_processEventB->StartTimer(true, 10);
|
|
|
|
_pullEventA->StartTimer(true, 10);
|
|
_pullEventB->StartTimer(true, 10);
|
|
|
|
_pushEventA->StartTimer(true, 10);
|
|
_pushEventB->StartTimer(true, 10);
|
|
|
|
// Keep main thread waiting for sender/receiver
|
|
// threads to complete
|
|
EventWrapper* completeEvent = EventWrapper::Create();
|
|
uint64_t startTime = TickTime::MillisecondTimestamp();
|
|
uint64_t currentTime;
|
|
// Run test in 2 minutes (120000 ms).
|
|
do {
|
|
{
|
|
//ReadLockScoped rl(_apiTestRWLock);
|
|
//fprintf(stderr, "\r%s", _movingDot);
|
|
}
|
|
//fflush(stderr);
|
|
completeEvent->Wait(50);
|
|
currentTime = TickTime::MillisecondTimestamp();
|
|
} while ((currentTime - startTime) < 120000);
|
|
|
|
//completeEvent->Wait(0xFFFFFFFF);
|
|
//(unsigned long)((unsigned long)TEST_DURATION_SEC * (unsigned long)1000));
|
|
delete completeEvent;
|
|
|
|
myPushAudioThreadA->Stop();
|
|
myPullAudioThreadA->Stop();
|
|
myProcessThreadA->Stop();
|
|
myAPIThreadA->Stop();
|
|
|
|
myPushAudioThreadB->Stop();
|
|
myPullAudioThreadB->Stop();
|
|
myProcessThreadB->Stop();
|
|
myAPIThreadB->Stop();
|
|
}
|
|
|
|
void APITest::CheckVADStatus(char side) {
|
|
|
|
bool dtxEnabled;
|
|
bool vadEnabled;
|
|
ACMVADMode vadMode;
|
|
|
|
if (side == 'A') {
|
|
_acmA->VAD(&dtxEnabled, &vadEnabled, &vadMode);
|
|
_acmA->RegisterVADCallback(NULL);
|
|
_vadCallbackA->Reset();
|
|
_acmA->RegisterVADCallback(_vadCallbackA);
|
|
|
|
if (!_randomTest) {
|
|
if (_verbose) {
|
|
fprintf(stdout, "DTX %3s, VAD %3s, Mode %d", dtxEnabled ? "ON" : "OFF",
|
|
vadEnabled ? "ON" : "OFF", (int) vadMode);
|
|
Wait(5000);
|
|
fprintf(stdout, " => bit-rate %3.0f kbps\n", _channel_A2B->BitRate());
|
|
} else {
|
|
Wait(5000);
|
|
fprintf(stdout, "DTX %3s, VAD %3s, Mode %d => bit-rate %3.0f kbps\n",
|
|
dtxEnabled ? "ON" : "OFF", vadEnabled ? "ON" : "OFF",
|
|
(int) vadMode, _channel_A2B->BitRate());
|
|
}
|
|
_vadCallbackA->PrintFrameTypes();
|
|
}
|
|
|
|
if (dtxEnabled != _sendDTXA) {
|
|
fprintf(stderr, ">>> Error Enabling DTX <<<\n");
|
|
}
|
|
if ((vadEnabled != _sendVADA) && (!dtxEnabled)) {
|
|
fprintf(stderr, ">>> Error Enabling VAD <<<\n");
|
|
}
|
|
if ((vadMode != _sendVADModeA) && vadEnabled) {
|
|
fprintf(stderr, ">>> Error setting VAD-mode <<<\n");
|
|
}
|
|
} else {
|
|
_acmB->VAD(&dtxEnabled, &vadEnabled, &vadMode);
|
|
|
|
_acmB->RegisterVADCallback(NULL);
|
|
_vadCallbackB->Reset();
|
|
_acmB->RegisterVADCallback(_vadCallbackB);
|
|
|
|
if (!_randomTest) {
|
|
if (_verbose) {
|
|
fprintf(stdout, "DTX %3s, VAD %3s, Mode %d", dtxEnabled ? "ON" : "OFF",
|
|
vadEnabled ? "ON" : "OFF", (int) vadMode);
|
|
Wait(5000);
|
|
fprintf(stdout, " => bit-rate %3.0f kbps\n", _channel_B2A->BitRate());
|
|
} else {
|
|
Wait(5000);
|
|
fprintf(stdout, "DTX %3s, VAD %3s, Mode %d => bit-rate %3.0f kbps\n",
|
|
dtxEnabled ? "ON" : "OFF", vadEnabled ? "ON" : "OFF",
|
|
(int) vadMode, _channel_B2A->BitRate());
|
|
}
|
|
_vadCallbackB->PrintFrameTypes();
|
|
}
|
|
|
|
if (dtxEnabled != _sendDTXB) {
|
|
fprintf(stderr, ">>> Error Enabling DTX <<<\n");
|
|
}
|
|
if ((vadEnabled != _sendVADB) && (!dtxEnabled)) {
|
|
fprintf(stderr, ">>> Error Enabling VAD <<<\n");
|
|
}
|
|
if ((vadMode != _sendVADModeB) && vadEnabled) {
|
|
fprintf(stderr, ">>> Error setting VAD-mode <<<\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
// Set Min delay, get delay, playout timestamp
|
|
void APITest::TestDelay(char side) {
|
|
AudioCodingModule* myACM;
|
|
Channel* myChannel;
|
|
int32_t* myMinDelay;
|
|
EventTimerWrapper* myEvent = EventTimerWrapper::Create();
|
|
|
|
uint32_t inTimestamp = 0;
|
|
uint32_t outTimestamp = 0;
|
|
double estimDelay = 0;
|
|
|
|
double averageEstimDelay = 0;
|
|
double averageDelay = 0;
|
|
|
|
CircularBuffer estimDelayCB(100);
|
|
estimDelayCB.SetArithMean(true);
|
|
|
|
if (side == 'A') {
|
|
myACM = _acmA.get();
|
|
myChannel = _channel_B2A;
|
|
myMinDelay = &_minDelayA;
|
|
} else {
|
|
myACM = _acmB.get();
|
|
myChannel = _channel_A2B;
|
|
myMinDelay = &_minDelayB;
|
|
}
|
|
|
|
CHECK_ERROR_MT(myACM->SetMinimumPlayoutDelay(*myMinDelay));
|
|
|
|
inTimestamp = myChannel->LastInTimestamp();
|
|
CHECK_ERROR_MT(myACM->PlayoutTimestamp(&outTimestamp));
|
|
|
|
if (!_randomTest) {
|
|
myEvent->StartTimer(true, 30);
|
|
int n = 0;
|
|
int settlePoint = 5000;
|
|
while (n < settlePoint + 400) {
|
|
myEvent->Wait(1000);
|
|
|
|
inTimestamp = myChannel->LastInTimestamp();
|
|
CHECK_ERROR_MT(myACM->PlayoutTimestamp(&outTimestamp));
|
|
|
|
//std::cout << outTimestamp << std::endl << std::flush;
|
|
estimDelay = (double) ((uint32_t)(inTimestamp - outTimestamp))
|
|
/ ((double) myACM->ReceiveFrequency() / 1000.0);
|
|
|
|
estimDelayCB.Update(estimDelay);
|
|
|
|
estimDelayCB.ArithMean(averageEstimDelay);
|
|
//printf("\n %6.1f \n", estimDelay);
|
|
//std::cout << " " << std::flush;
|
|
|
|
if (_verbose) {
|
|
fprintf(stdout,
|
|
"\rExpected: %4d, retreived: %6.1f, measured: %6.1f",
|
|
*myMinDelay, averageDelay, averageEstimDelay);
|
|
std::cout << " " << std::flush;
|
|
}
|
|
if ((averageDelay > *myMinDelay) && (n < settlePoint)) {
|
|
settlePoint = n;
|
|
}
|
|
n++;
|
|
}
|
|
myEvent->StopTimer();
|
|
}
|
|
|
|
if ((!_verbose) && (!_randomTest)) {
|
|
fprintf(stdout, "\nExpected: %4d, retreived: %6.1f, measured: %6.1f",
|
|
*myMinDelay, averageDelay, averageEstimDelay);
|
|
}
|
|
|
|
*myMinDelay = (rand() % 1000) + 1;
|
|
|
|
NetworkStatistics networkStat;
|
|
CHECK_ERROR_MT(myACM->GetNetworkStatistics(&networkStat));
|
|
|
|
if (!_randomTest) {
|
|
fprintf(stdout, "\n\nJitter Statistics at Side %c\n", side);
|
|
fprintf(stdout, "--------------------------------------\n");
|
|
fprintf(stdout, "buffer-size............. %d\n",
|
|
networkStat.currentBufferSize);
|
|
fprintf(stdout, "Preferred buffer-size... %d\n",
|
|
networkStat.preferredBufferSize);
|
|
fprintf(stdout, "Peaky jitter mode........%d\n",
|
|
networkStat.jitterPeaksFound);
|
|
fprintf(stdout, "packet-size rate........ %d\n",
|
|
networkStat.currentPacketLossRate);
|
|
fprintf(stdout, "discard rate............ %d\n",
|
|
networkStat.currentDiscardRate);
|
|
fprintf(stdout, "expand rate............. %d\n",
|
|
networkStat.currentExpandRate);
|
|
fprintf(stdout, "speech expand rate...... %d\n",
|
|
networkStat.currentSpeechExpandRate);
|
|
fprintf(stdout, "Preemptive rate......... %d\n",
|
|
networkStat.currentPreemptiveRate);
|
|
fprintf(stdout, "Accelerate rate......... %d\n",
|
|
networkStat.currentAccelerateRate);
|
|
fprintf(stdout, "Secondary decoded rate.. %d\n",
|
|
networkStat.currentSecondaryDecodedRate);
|
|
fprintf(stdout, "Clock-drift............. %d\n", networkStat.clockDriftPPM);
|
|
fprintf(stdout, "Mean waiting time....... %d\n",
|
|
networkStat.meanWaitingTimeMs);
|
|
fprintf(stdout, "Median waiting time..... %d\n",
|
|
networkStat.medianWaitingTimeMs);
|
|
fprintf(stdout, "Min waiting time........ %d\n",
|
|
networkStat.minWaitingTimeMs);
|
|
fprintf(stdout, "Max waiting time........ %d\n",
|
|
networkStat.maxWaitingTimeMs);
|
|
}
|
|
|
|
CHECK_ERROR_MT(myACM->SetMinimumPlayoutDelay(*myMinDelay));
|
|
|
|
if (!_randomTest) {
|
|
myEvent->Wait(500);
|
|
fprintf(stdout, "\n");
|
|
fprintf(stdout, "\n");
|
|
}
|
|
delete myEvent;
|
|
}
|
|
|
|
// Unregister a codec & register again.
|
|
void APITest::TestRegisteration(char sendSide) {
|
|
AudioCodingModule* sendACM;
|
|
AudioCodingModule* receiveACM;
|
|
bool* thereIsDecoder;
|
|
EventWrapper* myEvent = EventWrapper::Create();
|
|
|
|
if (!_randomTest) {
|
|
fprintf(stdout, "\n\n");
|
|
fprintf(stdout,
|
|
"---------------------------------------------------------\n");
|
|
fprintf(stdout, " Unregister/register Receive Codec\n");
|
|
fprintf(stdout,
|
|
"---------------------------------------------------------\n");
|
|
}
|
|
|
|
switch (sendSide) {
|
|
case 'A': {
|
|
sendACM = _acmA.get();
|
|
receiveACM = _acmB.get();
|
|
thereIsDecoder = &_thereIsDecoderB;
|
|
break;
|
|
}
|
|
case 'B': {
|
|
sendACM = _acmB.get();
|
|
receiveACM = _acmA.get();
|
|
thereIsDecoder = &_thereIsDecoderA;
|
|
break;
|
|
}
|
|
default:
|
|
fprintf(stderr, "Invalid sender-side in TestRegistration(%c)\n",
|
|
sendSide);
|
|
exit(-1);
|
|
}
|
|
|
|
CodecInst myCodec;
|
|
if (sendACM->SendCodec(&myCodec) < 0) {
|
|
AudioCodingModule::Codec(_codecCntrA, &myCodec);
|
|
}
|
|
|
|
if (!_randomTest) {
|
|
fprintf(stdout, "Unregistering reveive codec, NO AUDIO.\n");
|
|
fflush (stdout);
|
|
}
|
|
{
|
|
WriteLockScoped wl(_apiTestRWLock);
|
|
*thereIsDecoder = false;
|
|
}
|
|
//myEvent->Wait(20);
|
|
CHECK_ERROR_MT(receiveACM->UnregisterReceiveCodec(myCodec.pltype));
|
|
Wait(1000);
|
|
|
|
int currentPayload = myCodec.pltype;
|
|
|
|
if (!FixedPayloadTypeCodec(myCodec.plname)) {
|
|
int32_t i;
|
|
for (i = 0; i < 32; i++) {
|
|
if (!_payloadUsed[i]) {
|
|
if (!_randomTest) {
|
|
fprintf(stdout,
|
|
"Register receive codec with new Payload, AUDIO BACK.\n");
|
|
}
|
|
//myCodec.pltype = i + 96;
|
|
//CHECK_ERROR_MT(receiveACM->RegisterReceiveCodec(myCodec));
|
|
//CHECK_ERROR_MT(sendACM->RegisterSendCodec(myCodec));
|
|
//myEvent->Wait(20);
|
|
//{
|
|
// WriteLockScoped wl(_apiTestRWLock);
|
|
// *thereIsDecoder = true;
|
|
//}
|
|
Wait(1000);
|
|
|
|
if (!_randomTest) {
|
|
fprintf(stdout, "Unregistering reveive codec, NO AUDIO.\n");
|
|
}
|
|
//{
|
|
// WriteLockScoped wl(_apiTestRWLock);
|
|
// *thereIsDecoder = false;
|
|
//}
|
|
//myEvent->Wait(20);
|
|
//CHECK_ERROR_MT(receiveACM->UnregisterReceiveCodec(myCodec.pltype));
|
|
Wait(1000);
|
|
|
|
myCodec.pltype = currentPayload;
|
|
if (!_randomTest) {
|
|
fprintf(stdout,
|
|
"Register receive codec with default Payload, AUDIO BACK.\n");
|
|
fflush (stdout);
|
|
}
|
|
CHECK_ERROR_MT(receiveACM->RegisterReceiveCodec(myCodec));
|
|
//CHECK_ERROR_MT(sendACM->RegisterSendCodec(myCodec));
|
|
myEvent->Wait(20);
|
|
{
|
|
WriteLockScoped wl(_apiTestRWLock);
|
|
*thereIsDecoder = true;
|
|
}
|
|
Wait(1000);
|
|
|
|
break;
|
|
}
|
|
}
|
|
if (i == 32) {
|
|
CHECK_ERROR_MT(receiveACM->RegisterReceiveCodec(myCodec));
|
|
{
|
|
WriteLockScoped wl(_apiTestRWLock);
|
|
*thereIsDecoder = true;
|
|
}
|
|
}
|
|
} else {
|
|
if (!_randomTest) {
|
|
fprintf(stdout,
|
|
"Register receive codec with fixed Payload, AUDIO BACK.\n");
|
|
fflush (stdout);
|
|
}
|
|
CHECK_ERROR_MT(receiveACM->RegisterReceiveCodec(myCodec));
|
|
//CHECK_ERROR_MT(receiveACM->UnregisterReceiveCodec(myCodec.pltype));
|
|
//CHECK_ERROR_MT(receiveACM->RegisterReceiveCodec(myCodec));
|
|
myEvent->Wait(20);
|
|
{
|
|
WriteLockScoped wl(_apiTestRWLock);
|
|
*thereIsDecoder = true;
|
|
}
|
|
}
|
|
delete myEvent;
|
|
if (!_randomTest) {
|
|
fprintf(stdout,
|
|
"---------------------------------------------------------\n");
|
|
}
|
|
}
|
|
|
|
// Playout Mode, background noise mode.
|
|
// Receiver Frequency, playout frequency.
|
|
void APITest::TestPlayout(char receiveSide) {
|
|
AudioCodingModule* receiveACM;
|
|
AudioPlayoutMode* playoutMode = NULL;
|
|
switch (receiveSide) {
|
|
case 'A': {
|
|
receiveACM = _acmA.get();
|
|
playoutMode = &_playoutModeA;
|
|
break;
|
|
}
|
|
case 'B': {
|
|
receiveACM = _acmB.get();
|
|
playoutMode = &_playoutModeB;
|
|
break;
|
|
}
|
|
default:
|
|
receiveACM = _acmA.get();
|
|
}
|
|
|
|
int32_t receiveFreqHz = receiveACM->ReceiveFrequency();
|
|
int32_t playoutFreqHz = receiveACM->PlayoutFrequency();
|
|
|
|
CHECK_ERROR_MT(receiveFreqHz);
|
|
CHECK_ERROR_MT(playoutFreqHz);
|
|
|
|
|
|
char playoutString[25];
|
|
switch (*playoutMode) {
|
|
case voice: {
|
|
*playoutMode = fax;
|
|
strncpy(playoutString, "FAX", 25);
|
|
break;
|
|
}
|
|
case fax: {
|
|
*playoutMode = streaming;
|
|
strncpy(playoutString, "Streaming", 25);
|
|
break;
|
|
}
|
|
case streaming: {
|
|
*playoutMode = voice;
|
|
strncpy(playoutString, "Voice", 25);
|
|
break;
|
|
}
|
|
default:
|
|
*playoutMode = voice;
|
|
strncpy(playoutString, "Voice", 25);
|
|
}
|
|
CHECK_ERROR_MT(receiveACM->SetPlayoutMode(*playoutMode));
|
|
playoutString[24] = '\0';
|
|
|
|
if (!_randomTest) {
|
|
fprintf(stdout, "\n");
|
|
fprintf(stdout, "In Side %c\n", receiveSide);
|
|
fprintf(stdout, "---------------------------------\n");
|
|
fprintf(stdout, "Receive Frequency....... %d Hz\n", receiveFreqHz);
|
|
fprintf(stdout, "Playout Frequency....... %d Hz\n", playoutFreqHz);
|
|
fprintf(stdout, "Audio Playout Mode...... %s\n", playoutString);
|
|
}
|
|
}
|
|
|
|
void APITest::TestSendVAD(char side) {
|
|
if (_randomTest) {
|
|
return;
|
|
}
|
|
|
|
bool* vad;
|
|
bool* dtx;
|
|
ACMVADMode* mode;
|
|
Channel* myChannel;
|
|
AudioCodingModule* myACM;
|
|
|
|
CodecInst myCodec;
|
|
if (!_randomTest) {
|
|
fprintf(stdout, "\n\n");
|
|
fprintf(stdout, "-----------------------------------------------\n");
|
|
fprintf(stdout, " Test VAD API\n");
|
|
fprintf(stdout, "-----------------------------------------------\n");
|
|
}
|
|
|
|
if (side == 'A') {
|
|
AudioCodingModule::Codec(_codecCntrA, &myCodec);
|
|
vad = &_sendVADA;
|
|
dtx = &_sendDTXA;
|
|
mode = &_sendVADModeA;
|
|
myChannel = _channel_A2B;
|
|
myACM = _acmA.get();
|
|
} else {
|
|
AudioCodingModule::Codec(_codecCntrB, &myCodec);
|
|
vad = &_sendVADB;
|
|
dtx = &_sendDTXB;
|
|
mode = &_sendVADModeB;
|
|
myChannel = _channel_B2A;
|
|
myACM = _acmB.get();
|
|
}
|
|
|
|
CheckVADStatus(side);
|
|
if (!_randomTest) {
|
|
fprintf(stdout, "\n\n");
|
|
}
|
|
|
|
switch (*mode) {
|
|
case VADNormal:
|
|
*vad = true;
|
|
*dtx = true;
|
|
*mode = VADAggr;
|
|
break;
|
|
case VADLowBitrate:
|
|
*vad = true;
|
|
*dtx = true;
|
|
*mode = VADVeryAggr;
|
|
break;
|
|
case VADAggr:
|
|
*vad = true;
|
|
*dtx = true;
|
|
*mode = VADLowBitrate;
|
|
break;
|
|
case VADVeryAggr:
|
|
*vad = false;
|
|
*dtx = false;
|
|
*mode = VADNormal;
|
|
break;
|
|
default:
|
|
*mode = VADNormal;
|
|
}
|
|
|
|
*dtx = (myCodec.plfreq == 32000) ? false : *dtx;
|
|
|
|
CHECK_ERROR_MT(myACM->SetVAD(*dtx, *vad, *mode));
|
|
myChannel->ResetStats();
|
|
|
|
CheckVADStatus(side);
|
|
if (!_randomTest) {
|
|
fprintf(stdout, "\n");
|
|
fprintf(stdout, "-----------------------------------------------\n");
|
|
}
|
|
|
|
// Fault Test
|
|
CHECK_PROTECTED_MT(myACM->SetVAD(false, true, (ACMVADMode) - 1));
|
|
CHECK_PROTECTED_MT(myACM->SetVAD(false, true, (ACMVADMode) 4));
|
|
|
|
}
|
|
|
|
void APITest::CurrentCodec(char side) {
|
|
CodecInst myCodec;
|
|
if (side == 'A') {
|
|
_acmA->SendCodec(&myCodec);
|
|
} else {
|
|
_acmB->SendCodec(&myCodec);
|
|
}
|
|
|
|
if (!_randomTest) {
|
|
fprintf(stdout, "\n\n");
|
|
fprintf(stdout, "Send codec in Side A\n");
|
|
fprintf(stdout, "----------------------------\n");
|
|
fprintf(stdout, "Name................. %s\n", myCodec.plname);
|
|
fprintf(stdout, "Sampling Frequency... %d\n", myCodec.plfreq);
|
|
fprintf(stdout, "Rate................. %d\n", myCodec.rate);
|
|
fprintf(stdout, "Payload-type......... %d\n", myCodec.pltype);
|
|
fprintf(stdout, "Packet-size.......... %d\n", myCodec.pacsize);
|
|
}
|
|
|
|
Wait(100);
|
|
}
|
|
|
|
void APITest::ChangeCodec(char side) {
|
|
CodecInst myCodec;
|
|
AudioCodingModule* myACM;
|
|
uint8_t* codecCntr;
|
|
bool* thereIsEncoder;
|
|
bool* vad;
|
|
bool* dtx;
|
|
ACMVADMode* mode;
|
|
Channel* myChannel;
|
|
// Reset and Wait
|
|
if (!_randomTest) {
|
|
fprintf(stdout, "Reset Encoder Side A \n");
|
|
}
|
|
if (side == 'A') {
|
|
myACM = _acmA.get();
|
|
codecCntr = &_codecCntrA;
|
|
{
|
|
WriteLockScoped wl(_apiTestRWLock);
|
|
thereIsEncoder = &_thereIsEncoderA;
|
|
}
|
|
vad = &_sendVADA;
|
|
dtx = &_sendDTXA;
|
|
mode = &_sendVADModeA;
|
|
myChannel = _channel_A2B;
|
|
} else {
|
|
myACM = _acmB.get();
|
|
codecCntr = &_codecCntrB;
|
|
{
|
|
WriteLockScoped wl(_apiTestRWLock);
|
|
thereIsEncoder = &_thereIsEncoderB;
|
|
}
|
|
vad = &_sendVADB;
|
|
dtx = &_sendDTXB;
|
|
mode = &_sendVADModeB;
|
|
myChannel = _channel_B2A;
|
|
}
|
|
|
|
myACM->ResetEncoder();
|
|
Wait(100);
|
|
|
|
// Register the next codec
|
|
do {
|
|
*codecCntr =
|
|
(*codecCntr < AudioCodingModule::NumberOfCodecs() - 1) ?
|
|
(*codecCntr + 1) : 0;
|
|
|
|
if (*codecCntr == 0) {
|
|
//printf("Initialize Sender Side A \n");
|
|
{
|
|
WriteLockScoped wl(_apiTestRWLock);
|
|
*thereIsEncoder = false;
|
|
}
|
|
CHECK_ERROR_MT(myACM->InitializeSender());
|
|
Wait(1000);
|
|
|
|
// After Initialization CN is lost, re-register them
|
|
if (AudioCodingModule::Codec("CN", &myCodec, 8000, 1) >= 0) {
|
|
CHECK_ERROR_MT(myACM->RegisterSendCodec(myCodec));
|
|
}
|
|
if (AudioCodingModule::Codec("CN", &myCodec, 16000, 1) >= 0) {
|
|
CHECK_ERROR_MT(myACM->RegisterSendCodec(myCodec));
|
|
}
|
|
// VAD & DTX are disabled after initialization
|
|
*vad = false;
|
|
*dtx = false;
|
|
_writeToFile = false;
|
|
}
|
|
|
|
AudioCodingModule::Codec(*codecCntr, &myCodec);
|
|
} while (!STR_CASE_CMP(myCodec.plname, "CN")
|
|
|| !STR_CASE_CMP(myCodec.plname, "telephone-event")
|
|
|| !STR_CASE_CMP(myCodec.plname, "RED"));
|
|
|
|
if (!_randomTest) {
|
|
fprintf(stdout,"\n=====================================================\n");
|
|
fprintf(stdout, " Registering New Codec %s, %d kHz, %d kbps\n",
|
|
myCodec.plname, myCodec.plfreq / 1000, myCodec.rate / 1000);
|
|
}
|
|
//std::cout<< std::flush;
|
|
|
|
// NO DTX for supe-wideband codec at this point
|
|
if (myCodec.plfreq == 32000) {
|
|
*dtx = false;
|
|
CHECK_ERROR_MT(myACM->SetVAD(*dtx, *vad, *mode));
|
|
|
|
}
|
|
|
|
CHECK_ERROR_MT(myACM->RegisterSendCodec(myCodec));
|
|
myChannel->ResetStats();
|
|
{
|
|
WriteLockScoped wl(_apiTestRWLock);
|
|
*thereIsEncoder = true;
|
|
}
|
|
Wait(500);
|
|
}
|
|
|
|
} // namespace webrtc
|