Home | History | Annotate | Download | only in test
      1 /*
      2  *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 #include "webrtc/modules/audio_coding/test/APITest.h"
     12 
     13 #include <ctype.h>
     14 #include <stdio.h>
     15 #include <stdlib.h>
     16 #include <string.h>
     17 
     18 #include <iostream>
     19 #include <ostream>
     20 #include <string>
     21 
     22 #include "testing/gtest/include/gtest/gtest.h"
     23 #include "webrtc/base/platform_thread.h"
     24 #include "webrtc/common.h"
     25 #include "webrtc/common_types.h"
     26 #include "webrtc/engine_configurations.h"
     27 #include "webrtc/modules/audio_coding/acm2/acm_common_defs.h"
     28 #include "webrtc/modules/audio_coding/test/utility.h"
     29 #include "webrtc/system_wrappers/include/event_wrapper.h"
     30 #include "webrtc/system_wrappers/include/tick_util.h"
     31 #include "webrtc/system_wrappers/include/trace.h"
     32 #include "webrtc/test/testsupport/fileutils.h"
     33 
     34 namespace webrtc {
     35 
     36 #define TEST_DURATION_SEC 600
     37 #define NUMBER_OF_SENDER_TESTS 6
     38 #define MAX_FILE_NAME_LENGTH_BYTE 500
     39 
     40 void APITest::Wait(uint32_t waitLengthMs) {
     41   if (_randomTest) {
     42     return;
     43   } else {
     44     EventWrapper* myEvent = EventWrapper::Create();
     45     myEvent->Wait(waitLengthMs);
     46     delete myEvent;
     47     return;
     48   }
     49 }
     50 
     51 APITest::APITest(const Config& config)
     52     : _acmA(AudioCodingModule::Create(1)),
     53       _acmB(AudioCodingModule::Create(2)),
     54       _channel_A2B(NULL),
     55       _channel_B2A(NULL),
     56       _writeToFile(true),
     57       _pullEventA(NULL),
     58       _pushEventA(NULL),
     59       _processEventA(NULL),
     60       _apiEventA(NULL),
     61       _pullEventB(NULL),
     62       _pushEventB(NULL),
     63       _processEventB(NULL),
     64       _apiEventB(NULL),
     65       _codecCntrA(0),
     66       _codecCntrB(0),
     67       _thereIsEncoderA(false),
     68       _thereIsEncoderB(false),
     69       _thereIsDecoderA(false),
     70       _thereIsDecoderB(false),
     71       _sendVADA(false),
     72       _sendDTXA(false),
     73       _sendVADModeA(VADNormal),
     74       _sendVADB(false),
     75       _sendDTXB(false),
     76       _sendVADModeB(VADNormal),
     77       _minDelayA(0),
     78       _minDelayB(0),
     79       _dotPositionA(0),
     80       _dotMoveDirectionA(1),
     81       _dotPositionB(39),
     82       _dotMoveDirectionB(-1),
     83       _vadCallbackA(NULL),
     84       _vadCallbackB(NULL),
     85       _apiTestRWLock(*RWLockWrapper::CreateRWLock()),
     86       _randomTest(false),
     87       _testNumA(0),
     88       _testNumB(1) {
     89   int n;
     90   for (n = 0; n < 32; n++) {
     91     _payloadUsed[n] = false;
     92   }
     93 
     94   _movingDot[40] = '\0';
     95 
     96   for (int n = 0; n < 40; n++) {
     97     _movingDot[n] = ' ';
     98   }
     99 }
    100 
    101 APITest::~APITest() {
    102   DELETE_POINTER(_channel_A2B);
    103   DELETE_POINTER(_channel_B2A);
    104 
    105   DELETE_POINTER(_pushEventA);
    106   DELETE_POINTER(_pullEventA);
    107   DELETE_POINTER(_processEventA);
    108   DELETE_POINTER(_apiEventA);
    109 
    110   DELETE_POINTER(_pushEventB);
    111   DELETE_POINTER(_pullEventB);
    112   DELETE_POINTER(_processEventB);
    113   DELETE_POINTER(_apiEventB);
    114 
    115   _inFileA.Close();
    116   _outFileA.Close();
    117 
    118   _inFileB.Close();
    119   _outFileB.Close();
    120 
    121   DELETE_POINTER(_vadCallbackA);
    122   DELETE_POINTER(_vadCallbackB);
    123 
    124   delete &_apiTestRWLock;
    125 }
    126 
    127 int16_t APITest::SetUp() {
    128   CodecInst dummyCodec;
    129   int lastPayloadType = 0;
    130 
    131   int16_t numCodecs = _acmA->NumberOfCodecs();
    132   for (uint8_t n = 0; n < numCodecs; n++) {
    133     AudioCodingModule::Codec(n, &dummyCodec);
    134     if ((STR_CASE_CMP(dummyCodec.plname, "CN") == 0)
    135         && (dummyCodec.plfreq == 32000)) {
    136       continue;
    137     }
    138 
    139     printf("Register Receive Codec %s  ", dummyCodec.plname);
    140 
    141     if ((n != 0) && !FixedPayloadTypeCodec(dummyCodec.plname)) {
    142       // Check registration with an already occupied payload type
    143       int currentPayloadType = dummyCodec.pltype;
    144       dummyCodec.pltype = 97;  //lastPayloadType;
    145       CHECK_ERROR(_acmB->RegisterReceiveCodec(dummyCodec));
    146       dummyCodec.pltype = currentPayloadType;
    147     }
    148 
    149     if ((n < numCodecs - 1) && !FixedPayloadTypeCodec(dummyCodec.plname)) {
    150       // test if re-registration works;
    151       CodecInst nextCodec;
    152       int currentPayloadType = dummyCodec.pltype;
    153       AudioCodingModule::Codec(n + 1, &nextCodec);
    154       dummyCodec.pltype = nextCodec.pltype;
    155       if (!FixedPayloadTypeCodec(nextCodec.plname)) {
    156         _acmB->RegisterReceiveCodec(dummyCodec);
    157       }
    158       dummyCodec.pltype = currentPayloadType;
    159     }
    160 
    161     if ((n < numCodecs - 1) && !FixedPayloadTypeCodec(dummyCodec.plname)) {
    162       // test if un-registration works;
    163       CodecInst nextCodec;
    164       AudioCodingModule::Codec(n + 1, &nextCodec);
    165       nextCodec.pltype = dummyCodec.pltype;
    166       if (!FixedPayloadTypeCodec(nextCodec.plname)) {
    167         CHECK_ERROR_MT(_acmA->RegisterReceiveCodec(nextCodec));
    168         CHECK_ERROR_MT(_acmA->UnregisterReceiveCodec(nextCodec.pltype));
    169       }
    170     }
    171 
    172     CHECK_ERROR_MT(_acmA->RegisterReceiveCodec(dummyCodec));
    173     printf("   side A done!");
    174     CHECK_ERROR_MT(_acmB->RegisterReceiveCodec(dummyCodec));
    175     printf("   side B done!\n");
    176 
    177     if (!strcmp(dummyCodec.plname, "CN")) {
    178       CHECK_ERROR_MT(_acmA->RegisterSendCodec(dummyCodec));
    179       CHECK_ERROR_MT(_acmB->RegisterSendCodec(dummyCodec));
    180     }
    181     lastPayloadType = dummyCodec.pltype;
    182     if ((lastPayloadType >= 96) && (lastPayloadType <= 127)) {
    183       _payloadUsed[lastPayloadType - 96] = true;
    184     }
    185   }
    186   _thereIsDecoderA = true;
    187   _thereIsDecoderB = true;
    188 
    189   // Register Send Codec
    190   AudioCodingModule::Codec((uint8_t) _codecCntrA, &dummyCodec);
    191   CHECK_ERROR_MT(_acmA->RegisterSendCodec(dummyCodec));
    192   _thereIsEncoderA = true;
    193   //
    194   AudioCodingModule::Codec((uint8_t) _codecCntrB, &dummyCodec);
    195   CHECK_ERROR_MT(_acmB->RegisterSendCodec(dummyCodec));
    196   _thereIsEncoderB = true;
    197 
    198   uint16_t frequencyHz;
    199 
    200   printf("\n\nAPI Test\n");
    201   printf("========\n");
    202   printf("Hit enter to accept the default values indicated in []\n\n");
    203 
    204   //--- Input A
    205   std::string file_name = webrtc::test::ResourcePath(
    206       "audio_coding/testfile32kHz", "pcm");
    207   frequencyHz = 32000;
    208   printf("Enter input file at side A [%s]: ", file_name.c_str());
    209   PCMFile::ChooseFile(&file_name, 499, &frequencyHz);
    210   _inFileA.Open(file_name, frequencyHz, "rb", true);
    211 
    212   //--- Output A
    213   std::string out_file_a = webrtc::test::OutputPath() + "outA.pcm";
    214   printf("Enter output file at side A [%s]: ", out_file_a.c_str());
    215   PCMFile::ChooseFile(&out_file_a, 499, &frequencyHz);
    216   _outFileA.Open(out_file_a, frequencyHz, "wb");
    217 
    218   //--- Input B
    219   file_name = webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm");
    220   printf("\n\nEnter input file at side B [%s]: ", file_name.c_str());
    221   PCMFile::ChooseFile(&file_name, 499, &frequencyHz);
    222   _inFileB.Open(file_name, frequencyHz, "rb", true);
    223 
    224   //--- Output B
    225   std::string out_file_b = webrtc::test::OutputPath() + "outB.pcm";
    226   printf("Enter output file at side B [%s]: ", out_file_b.c_str());
    227   PCMFile::ChooseFile(&out_file_b, 499, &frequencyHz);
    228   _outFileB.Open(out_file_b, frequencyHz, "wb");
    229 
    230   //--- Set A-to-B channel
    231   _channel_A2B = new Channel(2);
    232   CHECK_ERROR_MT(_acmA->RegisterTransportCallback(_channel_A2B));
    233   _channel_A2B->RegisterReceiverACM(_acmB.get());
    234 
    235   //--- Set B-to-A channel
    236   _channel_B2A = new Channel(1);
    237   CHECK_ERROR_MT(_acmB->RegisterTransportCallback(_channel_B2A));
    238   _channel_B2A->RegisterReceiverACM(_acmA.get());
    239 
    240   //--- EVENT TIMERS
    241   // A
    242   _pullEventA = EventTimerWrapper::Create();
    243   _pushEventA = EventTimerWrapper::Create();
    244   _processEventA = EventTimerWrapper::Create();
    245   _apiEventA = EventWrapper::Create();
    246   // B
    247   _pullEventB = EventTimerWrapper::Create();
    248   _pushEventB = EventTimerWrapper::Create();
    249   _processEventB = EventTimerWrapper::Create();
    250   _apiEventB = EventWrapper::Create();
    251 
    252   //--- I/O params
    253   // A
    254   _outFreqHzA = _outFileA.SamplingFrequency();
    255   // B
    256   _outFreqHzB = _outFileB.SamplingFrequency();
    257 
    258   //Trace::SetEncryptedTraceFile("ACMAPITestEncrypted.txt");
    259 
    260   char print[11];
    261 
    262   // Create a trace file.
    263   Trace::CreateTrace();
    264   Trace::SetTraceFile(
    265       (webrtc::test::OutputPath() + "acm_api_trace.txt").c_str());
    266 
    267   printf("\nRandom Test (y/n)?");
    268   EXPECT_TRUE(fgets(print, 10, stdin) != NULL);
    269   print[10] = '\0';
    270   if (strstr(print, "y") != NULL) {
    271     _randomTest = true;
    272     _verbose = false;
    273     _writeToFile = false;
    274   } else {
    275     _randomTest = false;
    276     printf("\nPrint Tests (y/n)? ");
    277     EXPECT_TRUE(fgets(print, 10, stdin) != NULL);
    278     print[10] = '\0';
    279     if (strstr(print, "y") == NULL) {
    280       EXPECT_TRUE(freopen("APITest_log.txt", "w", stdout) != 0);
    281       _verbose = false;
    282     }
    283   }
    284 
    285   _vadCallbackA = new VADCallback;
    286   _vadCallbackB = new VADCallback;
    287 
    288   return 0;
    289 }
    290 
    291 bool APITest::PushAudioThreadA(void* obj) {
    292   return static_cast<APITest*>(obj)->PushAudioRunA();
    293 }
    294 
    295 bool APITest::PushAudioThreadB(void* obj) {
    296   return static_cast<APITest*>(obj)->PushAudioRunB();
    297 }
    298 
    299 bool APITest::PullAudioThreadA(void* obj) {
    300   return static_cast<APITest*>(obj)->PullAudioRunA();
    301 }
    302 
    303 bool APITest::PullAudioThreadB(void* obj) {
    304   return static_cast<APITest*>(obj)->PullAudioRunB();
    305 }
    306 
    307 bool APITest::ProcessThreadA(void* obj) {
    308   return static_cast<APITest*>(obj)->ProcessRunA();
    309 }
    310 
    311 bool APITest::ProcessThreadB(void* obj) {
    312   return static_cast<APITest*>(obj)->ProcessRunB();
    313 }
    314 
    315 bool APITest::APIThreadA(void* obj) {
    316   return static_cast<APITest*>(obj)->APIRunA();
    317 }
    318 
    319 bool APITest::APIThreadB(void* obj) {
    320   return static_cast<APITest*>(obj)->APIRunB();
    321 }
    322 
    323 bool APITest::PullAudioRunA() {
    324   _pullEventA->Wait(100);
    325   AudioFrame audioFrame;
    326   if (_acmA->PlayoutData10Ms(_outFreqHzA, &audioFrame) < 0) {
    327     bool thereIsDecoder;
    328     {
    329       ReadLockScoped rl(_apiTestRWLock);
    330       thereIsDecoder = _thereIsDecoderA;
    331     }
    332     if (thereIsDecoder) {
    333       fprintf(stderr, "\n>>>>>>    cannot pull audio A       <<<<<<<< \n");
    334     }
    335   } else {
    336     if (_writeToFile) {
    337       _outFileA.Write10MsData(audioFrame);
    338     }
    339   }
    340   return true;
    341 }
    342 
    343 bool APITest::PullAudioRunB() {
    344   _pullEventB->Wait(100);
    345   AudioFrame audioFrame;
    346   if (_acmB->PlayoutData10Ms(_outFreqHzB, &audioFrame) < 0) {
    347     bool thereIsDecoder;
    348     {
    349       ReadLockScoped rl(_apiTestRWLock);
    350       thereIsDecoder = _thereIsDecoderB;
    351     }
    352     if (thereIsDecoder) {
    353       fprintf(stderr, "\n>>>>>>    cannot pull audio B       <<<<<<<< \n");
    354       fprintf(stderr, "%d %d\n", _testNumA, _testNumB);
    355     }
    356   } else {
    357     if (_writeToFile) {
    358       _outFileB.Write10MsData(audioFrame);
    359     }
    360   }
    361   return true;
    362 }
    363 
    364 bool APITest::PushAudioRunA() {
    365   _pushEventA->Wait(100);
    366   AudioFrame audioFrame;
    367   _inFileA.Read10MsData(audioFrame);
    368   if (_acmA->Add10MsData(audioFrame) < 0) {
    369     bool thereIsEncoder;
    370     {
    371       ReadLockScoped rl(_apiTestRWLock);
    372       thereIsEncoder = _thereIsEncoderA;
    373     }
    374     if (thereIsEncoder) {
    375       fprintf(stderr, "\n>>>>        add10MsData at A failed       <<<<\n");
    376     }
    377   }
    378   return true;
    379 }
    380 
    381 bool APITest::PushAudioRunB() {
    382   _pushEventB->Wait(100);
    383   AudioFrame audioFrame;
    384   _inFileB.Read10MsData(audioFrame);
    385   if (_acmB->Add10MsData(audioFrame) < 0) {
    386     bool thereIsEncoder;
    387     {
    388       ReadLockScoped rl(_apiTestRWLock);
    389       thereIsEncoder = _thereIsEncoderB;
    390     }
    391 
    392     if (thereIsEncoder) {
    393       fprintf(stderr, "\n>>>>   cannot add audio to B    <<<<");
    394     }
    395   }
    396 
    397   return true;
    398 }
    399 
    400 bool APITest::ProcessRunA() {
    401   _processEventA->Wait(100);
    402   return true;
    403 }
    404 
    405 bool APITest::ProcessRunB() {
    406   _processEventB->Wait(100);
    407   return true;
    408 }
    409 
    410 /*/
    411  *
    412  * In side A we test the APIs which are related to sender Side.
    413  *
    414 /*/
    415 
    416 void APITest::RunTest(char thread) {
    417   int testNum;
    418   {
    419     WriteLockScoped cs(_apiTestRWLock);
    420     if (thread == 'A') {
    421       _testNumA = (_testNumB + 1 + (rand() % 3)) % 4;
    422       testNum = _testNumA;
    423 
    424       _movingDot[_dotPositionA] = ' ';
    425       if (_dotPositionA == 0) {
    426         _dotMoveDirectionA = 1;
    427       }
    428       if (_dotPositionA == 19) {
    429         _dotMoveDirectionA = -1;
    430       }
    431       _dotPositionA += _dotMoveDirectionA;
    432       _movingDot[_dotPositionA] = (_dotMoveDirectionA > 0) ? '>' : '<';
    433     } else {
    434       _testNumB = (_testNumA + 1 + (rand() % 3)) % 4;
    435       testNum = _testNumB;
    436 
    437       _movingDot[_dotPositionB] = ' ';
    438       if (_dotPositionB == 20) {
    439         _dotMoveDirectionB = 1;
    440       }
    441       if (_dotPositionB == 39) {
    442         _dotMoveDirectionB = -1;
    443       }
    444       _dotPositionB += _dotMoveDirectionB;
    445       _movingDot[_dotPositionB] = (_dotMoveDirectionB > 0) ? '>' : '<';
    446     }
    447     //fprintf(stderr, "%c: %d \n", thread, testNum);
    448     //fflush(stderr);
    449   }
    450   switch (testNum) {
    451     case 0:
    452       CurrentCodec('A');
    453       ChangeCodec('A');
    454       break;
    455     case 1:
    456       if (!_randomTest) {
    457         fprintf(stdout, "\nTesting Delay ...\n");
    458       }
    459       TestDelay('A');
    460       break;
    461     case 2:
    462       TestSendVAD('A');
    463       break;
    464     case 3:
    465       TestRegisteration('A');
    466       break;
    467     default:
    468       fprintf(stderr, "Wrong Test Number\n");
    469       getc(stdin);
    470       exit(1);
    471   }
    472 }
    473 
    474 bool APITest::APIRunA() {
    475   _apiEventA->Wait(50);
    476 
    477   bool randomTest;
    478   {
    479     ReadLockScoped rl(_apiTestRWLock);
    480     randomTest = _randomTest;
    481   }
    482   if (randomTest) {
    483     RunTest('A');
    484   } else {
    485     CurrentCodec('A');
    486     ChangeCodec('A');
    487     if (_codecCntrA == 0) {
    488       fprintf(stdout, "\nTesting Delay ...\n");
    489       TestDelay('A');
    490     }
    491     // VAD TEST
    492     TestSendVAD('A');
    493     TestRegisteration('A');
    494   }
    495   return true;
    496 }
    497 
    498 bool APITest::APIRunB() {
    499   _apiEventB->Wait(50);
    500   bool randomTest;
    501   {
    502     ReadLockScoped rl(_apiTestRWLock);
    503     randomTest = _randomTest;
    504   }
    505   //_apiEventB->Wait(2000);
    506   if (randomTest) {
    507     RunTest('B');
    508   }
    509 
    510   return true;
    511 }
    512 
    513 void APITest::Perform() {
    514   SetUp();
    515 
    516   //--- THREADS
    517   // A
    518   // PUSH
    519   rtc::PlatformThread myPushAudioThreadA(PushAudioThreadA, this,
    520                                          "PushAudioThreadA");
    521   myPushAudioThreadA.Start();
    522   // PULL
    523   rtc::PlatformThread myPullAudioThreadA(PullAudioThreadA, this,
    524                                          "PullAudioThreadA");
    525   myPullAudioThreadA.Start();
    526   // Process
    527   rtc::PlatformThread myProcessThreadA(ProcessThreadA, this, "ProcessThreadA");
    528   myProcessThreadA.Start();
    529   // API
    530   rtc::PlatformThread myAPIThreadA(APIThreadA, this, "APIThreadA");
    531   myAPIThreadA.Start();
    532   // B
    533   // PUSH
    534   rtc::PlatformThread myPushAudioThreadB(PushAudioThreadB, this,
    535                                          "PushAudioThreadB");
    536   myPushAudioThreadB.Start();
    537   // PULL
    538   rtc::PlatformThread myPullAudioThreadB(PullAudioThreadB, this,
    539                                          "PullAudioThreadB");
    540   myPullAudioThreadB.Start();
    541   // Process
    542   rtc::PlatformThread myProcessThreadB(ProcessThreadB, this, "ProcessThreadB");
    543   myProcessThreadB.Start();
    544   // API
    545   rtc::PlatformThread myAPIThreadB(APIThreadB, this, "APIThreadB");
    546   myAPIThreadB.Start();
    547 
    548   //_apiEventA->StartTimer(true, 5000);
    549   //_apiEventB->StartTimer(true, 5000);
    550 
    551   _processEventA->StartTimer(true, 10);
    552   _processEventB->StartTimer(true, 10);
    553 
    554   _pullEventA->StartTimer(true, 10);
    555   _pullEventB->StartTimer(true, 10);
    556 
    557   _pushEventA->StartTimer(true, 10);
    558   _pushEventB->StartTimer(true, 10);
    559 
    560   // Keep main thread waiting for sender/receiver
    561   // threads to complete
    562   EventWrapper* completeEvent = EventWrapper::Create();
    563   uint64_t startTime = TickTime::MillisecondTimestamp();
    564   uint64_t currentTime;
    565   // Run test in 2 minutes (120000 ms).
    566   do {
    567     {
    568       //ReadLockScoped rl(_apiTestRWLock);
    569       //fprintf(stderr, "\r%s", _movingDot);
    570     }
    571     //fflush(stderr);
    572     completeEvent->Wait(50);
    573     currentTime = TickTime::MillisecondTimestamp();
    574   } while ((currentTime - startTime) < 120000);
    575 
    576   //completeEvent->Wait(0xFFFFFFFF);
    577   //(unsigned long)((unsigned long)TEST_DURATION_SEC * (unsigned long)1000));
    578   delete completeEvent;
    579 
    580   myPushAudioThreadA.Stop();
    581   myPullAudioThreadA.Stop();
    582   myProcessThreadA.Stop();
    583   myAPIThreadA.Stop();
    584 
    585   myPushAudioThreadB.Stop();
    586   myPullAudioThreadB.Stop();
    587   myProcessThreadB.Stop();
    588   myAPIThreadB.Stop();
    589 }
    590 
    591 void APITest::CheckVADStatus(char side) {
    592 
    593   bool dtxEnabled;
    594   bool vadEnabled;
    595   ACMVADMode vadMode;
    596 
    597   if (side == 'A') {
    598     _acmA->VAD(&dtxEnabled, &vadEnabled, &vadMode);
    599     _acmA->RegisterVADCallback(NULL);
    600     _vadCallbackA->Reset();
    601     _acmA->RegisterVADCallback(_vadCallbackA);
    602 
    603     if (!_randomTest) {
    604       if (_verbose) {
    605         fprintf(stdout, "DTX %3s, VAD %3s, Mode %d", dtxEnabled ? "ON" : "OFF",
    606                 vadEnabled ? "ON" : "OFF", (int) vadMode);
    607         Wait(5000);
    608         fprintf(stdout, " => bit-rate %3.0f kbps\n", _channel_A2B->BitRate());
    609       } else {
    610         Wait(5000);
    611         fprintf(stdout, "DTX %3s, VAD %3s, Mode %d => bit-rate %3.0f kbps\n",
    612                 dtxEnabled ? "ON" : "OFF", vadEnabled ? "ON" : "OFF",
    613                 (int) vadMode, _channel_A2B->BitRate());
    614       }
    615       _vadCallbackA->PrintFrameTypes();
    616     }
    617 
    618     if (dtxEnabled != _sendDTXA) {
    619       fprintf(stderr, ">>>   Error Enabling DTX    <<<\n");
    620     }
    621     if ((vadEnabled != _sendVADA) && (!dtxEnabled)) {
    622       fprintf(stderr, ">>>   Error Enabling VAD    <<<\n");
    623     }
    624     if ((vadMode != _sendVADModeA) && vadEnabled) {
    625       fprintf(stderr, ">>>   Error setting VAD-mode    <<<\n");
    626     }
    627   } else {
    628     _acmB->VAD(&dtxEnabled, &vadEnabled, &vadMode);
    629 
    630     _acmB->RegisterVADCallback(NULL);
    631     _vadCallbackB->Reset();
    632     _acmB->RegisterVADCallback(_vadCallbackB);
    633 
    634     if (!_randomTest) {
    635       if (_verbose) {
    636         fprintf(stdout, "DTX %3s, VAD %3s, Mode %d", dtxEnabled ? "ON" : "OFF",
    637                 vadEnabled ? "ON" : "OFF", (int) vadMode);
    638         Wait(5000);
    639         fprintf(stdout, " => bit-rate %3.0f kbps\n", _channel_B2A->BitRate());
    640       } else {
    641         Wait(5000);
    642         fprintf(stdout, "DTX %3s, VAD %3s, Mode %d => bit-rate %3.0f kbps\n",
    643                 dtxEnabled ? "ON" : "OFF", vadEnabled ? "ON" : "OFF",
    644                 (int) vadMode, _channel_B2A->BitRate());
    645       }
    646       _vadCallbackB->PrintFrameTypes();
    647     }
    648 
    649     if (dtxEnabled != _sendDTXB) {
    650       fprintf(stderr, ">>>   Error Enabling DTX    <<<\n");
    651     }
    652     if ((vadEnabled != _sendVADB) && (!dtxEnabled)) {
    653       fprintf(stderr, ">>>   Error Enabling VAD    <<<\n");
    654     }
    655     if ((vadMode != _sendVADModeB) && vadEnabled) {
    656       fprintf(stderr, ">>>   Error setting VAD-mode    <<<\n");
    657     }
    658   }
    659 }
    660 
    661 // Set Min delay, get delay, playout timestamp
    662 void APITest::TestDelay(char side) {
    663   AudioCodingModule* myACM;
    664   Channel* myChannel;
    665   int32_t* myMinDelay;
    666   EventTimerWrapper* myEvent = EventTimerWrapper::Create();
    667 
    668   uint32_t inTimestamp = 0;
    669   uint32_t outTimestamp = 0;
    670   double estimDelay = 0;
    671 
    672   double averageEstimDelay = 0;
    673   double averageDelay = 0;
    674 
    675   CircularBuffer estimDelayCB(100);
    676   estimDelayCB.SetArithMean(true);
    677 
    678   if (side == 'A') {
    679     myACM = _acmA.get();
    680     myChannel = _channel_B2A;
    681     myMinDelay = &_minDelayA;
    682   } else {
    683     myACM = _acmB.get();
    684     myChannel = _channel_A2B;
    685     myMinDelay = &_minDelayB;
    686   }
    687 
    688   CHECK_ERROR_MT(myACM->SetMinimumPlayoutDelay(*myMinDelay));
    689 
    690   inTimestamp = myChannel->LastInTimestamp();
    691   CHECK_ERROR_MT(myACM->PlayoutTimestamp(&outTimestamp));
    692 
    693   if (!_randomTest) {
    694     myEvent->StartTimer(true, 30);
    695     int n = 0;
    696     int settlePoint = 5000;
    697     while (n < settlePoint + 400) {
    698       myEvent->Wait(1000);
    699 
    700       inTimestamp = myChannel->LastInTimestamp();
    701       CHECK_ERROR_MT(myACM->PlayoutTimestamp(&outTimestamp));
    702 
    703       //std::cout << outTimestamp << std::endl << std::flush;
    704       estimDelay = (double) ((uint32_t)(inTimestamp - outTimestamp))
    705           / ((double) myACM->ReceiveFrequency() / 1000.0);
    706 
    707       estimDelayCB.Update(estimDelay);
    708 
    709       estimDelayCB.ArithMean(averageEstimDelay);
    710       //printf("\n %6.1f \n", estimDelay);
    711       //std::cout << " " << std::flush;
    712 
    713       if (_verbose) {
    714         fprintf(stdout,
    715                 "\rExpected: %4d,    retreived: %6.1f,   measured: %6.1f",
    716                 *myMinDelay, averageDelay, averageEstimDelay);
    717         std::cout << " " << std::flush;
    718       }
    719       if ((averageDelay > *myMinDelay) && (n < settlePoint)) {
    720         settlePoint = n;
    721       }
    722       n++;
    723     }
    724     myEvent->StopTimer();
    725   }
    726 
    727   if ((!_verbose) && (!_randomTest)) {
    728     fprintf(stdout, "\nExpected: %4d,    retreived: %6.1f,   measured: %6.1f",
    729             *myMinDelay, averageDelay, averageEstimDelay);
    730   }
    731 
    732   *myMinDelay = (rand() % 1000) + 1;
    733 
    734   NetworkStatistics networkStat;
    735   CHECK_ERROR_MT(myACM->GetNetworkStatistics(&networkStat));
    736 
    737   if (!_randomTest) {
    738     fprintf(stdout, "\n\nJitter Statistics at Side %c\n", side);
    739     fprintf(stdout, "--------------------------------------\n");
    740     fprintf(stdout, "buffer-size............. %d\n",
    741             networkStat.currentBufferSize);
    742     fprintf(stdout, "Preferred buffer-size... %d\n",
    743             networkStat.preferredBufferSize);
    744     fprintf(stdout, "Peaky jitter mode........%d\n",
    745             networkStat.jitterPeaksFound);
    746     fprintf(stdout, "packet-size rate........ %d\n",
    747             networkStat.currentPacketLossRate);
    748     fprintf(stdout, "discard rate............ %d\n",
    749             networkStat.currentDiscardRate);
    750     fprintf(stdout, "expand rate............. %d\n",
    751             networkStat.currentExpandRate);
    752     fprintf(stdout, "speech expand rate...... %d\n",
    753             networkStat.currentSpeechExpandRate);
    754     fprintf(stdout, "Preemptive rate......... %d\n",
    755             networkStat.currentPreemptiveRate);
    756     fprintf(stdout, "Accelerate rate......... %d\n",
    757             networkStat.currentAccelerateRate);
    758     fprintf(stdout, "Secondary decoded rate.. %d\n",
    759             networkStat.currentSecondaryDecodedRate);
    760     fprintf(stdout, "Clock-drift............. %d\n", networkStat.clockDriftPPM);
    761     fprintf(stdout, "Mean waiting time....... %d\n",
    762             networkStat.meanWaitingTimeMs);
    763     fprintf(stdout, "Median waiting time..... %d\n",
    764             networkStat.medianWaitingTimeMs);
    765     fprintf(stdout, "Min waiting time........ %d\n",
    766             networkStat.minWaitingTimeMs);
    767     fprintf(stdout, "Max waiting time........ %d\n",
    768             networkStat.maxWaitingTimeMs);
    769   }
    770 
    771   CHECK_ERROR_MT(myACM->SetMinimumPlayoutDelay(*myMinDelay));
    772 
    773   if (!_randomTest) {
    774     myEvent->Wait(500);
    775     fprintf(stdout, "\n");
    776     fprintf(stdout, "\n");
    777   }
    778   delete myEvent;
    779 }
    780 
    781 // Unregister a codec & register again.
    782 void APITest::TestRegisteration(char sendSide) {
    783   AudioCodingModule* sendACM;
    784   AudioCodingModule* receiveACM;
    785   bool* thereIsDecoder;
    786   EventWrapper* myEvent = EventWrapper::Create();
    787 
    788   if (!_randomTest) {
    789     fprintf(stdout, "\n\n");
    790     fprintf(stdout,
    791             "---------------------------------------------------------\n");
    792     fprintf(stdout, "           Unregister/register Receive Codec\n");
    793     fprintf(stdout,
    794             "---------------------------------------------------------\n");
    795   }
    796 
    797   switch (sendSide) {
    798     case 'A': {
    799       sendACM = _acmA.get();
    800       receiveACM = _acmB.get();
    801       thereIsDecoder = &_thereIsDecoderB;
    802       break;
    803     }
    804     case 'B': {
    805       sendACM = _acmB.get();
    806       receiveACM = _acmA.get();
    807       thereIsDecoder = &_thereIsDecoderA;
    808       break;
    809     }
    810     default:
    811       fprintf(stderr, "Invalid sender-side in TestRegistration(%c)\n",
    812               sendSide);
    813       exit(-1);
    814   }
    815 
    816   auto myCodec = sendACM->SendCodec();
    817   if (!myCodec) {
    818     CodecInst ci;
    819     AudioCodingModule::Codec(_codecCntrA, &ci);
    820     myCodec = rtc::Optional<CodecInst>(ci);
    821   }
    822 
    823   if (!_randomTest) {
    824     fprintf(stdout, "Unregistering reveive codec, NO AUDIO.\n");
    825     fflush (stdout);
    826   }
    827   {
    828     WriteLockScoped wl(_apiTestRWLock);
    829     *thereIsDecoder = false;
    830   }
    831   //myEvent->Wait(20);
    832   CHECK_ERROR_MT(receiveACM->UnregisterReceiveCodec(myCodec->pltype));
    833   Wait(1000);
    834 
    835   int currentPayload = myCodec->pltype;
    836 
    837   if (!FixedPayloadTypeCodec(myCodec->plname)) {
    838     int32_t i;
    839     for (i = 0; i < 32; i++) {
    840       if (!_payloadUsed[i]) {
    841         if (!_randomTest) {
    842           fprintf(stdout,
    843                   "Register receive codec with new Payload, AUDIO BACK.\n");
    844         }
    845         //myCodec->pltype = i + 96;
    846         //CHECK_ERROR_MT(receiveACM->RegisterReceiveCodec(*myCodec));
    847         //CHECK_ERROR_MT(sendACM->RegisterSendCodec(*myCodec));
    848         //myEvent->Wait(20);
    849         //{
    850         //    WriteLockScoped wl(_apiTestRWLock);
    851         //    *thereIsDecoder = true;
    852         //}
    853         Wait(1000);
    854 
    855         if (!_randomTest) {
    856           fprintf(stdout, "Unregistering reveive codec, NO AUDIO.\n");
    857         }
    858         //{
    859         //    WriteLockScoped wl(_apiTestRWLock);
    860         //    *thereIsDecoder = false;
    861         //}
    862         //myEvent->Wait(20);
    863         //CHECK_ERROR_MT(receiveACM->UnregisterReceiveCodec(myCodec->pltype));
    864         Wait(1000);
    865 
    866         myCodec->pltype = currentPayload;
    867         if (!_randomTest) {
    868           fprintf(stdout,
    869                   "Register receive codec with default Payload, AUDIO BACK.\n");
    870           fflush (stdout);
    871         }
    872         CHECK_ERROR_MT(receiveACM->RegisterReceiveCodec(*myCodec));
    873         //CHECK_ERROR_MT(sendACM->RegisterSendCodec(*myCodec));
    874         myEvent->Wait(20);
    875         {
    876           WriteLockScoped wl(_apiTestRWLock);
    877           *thereIsDecoder = true;
    878         }
    879         Wait(1000);
    880 
    881         break;
    882       }
    883     }
    884     if (i == 32) {
    885       CHECK_ERROR_MT(receiveACM->RegisterReceiveCodec(*myCodec));
    886       {
    887         WriteLockScoped wl(_apiTestRWLock);
    888         *thereIsDecoder = true;
    889       }
    890     }
    891   } else {
    892     if (!_randomTest) {
    893       fprintf(stdout,
    894               "Register receive codec with fixed Payload, AUDIO BACK.\n");
    895       fflush (stdout);
    896     }
    897     CHECK_ERROR_MT(receiveACM->RegisterReceiveCodec(*myCodec));
    898     //CHECK_ERROR_MT(receiveACM->UnregisterReceiveCodec(myCodec->pltype));
    899     //CHECK_ERROR_MT(receiveACM->RegisterReceiveCodec(*myCodec));
    900     myEvent->Wait(20);
    901     {
    902       WriteLockScoped wl(_apiTestRWLock);
    903       *thereIsDecoder = true;
    904     }
    905   }
    906   delete myEvent;
    907   if (!_randomTest) {
    908     fprintf(stdout,
    909             "---------------------------------------------------------\n");
    910   }
    911 }
    912 
    913 void APITest::TestSendVAD(char side) {
    914   if (_randomTest) {
    915     return;
    916   }
    917 
    918   bool* vad;
    919   bool* dtx;
    920   ACMVADMode* mode;
    921   Channel* myChannel;
    922   AudioCodingModule* myACM;
    923 
    924   CodecInst myCodec;
    925   if (!_randomTest) {
    926     fprintf(stdout, "\n\n");
    927     fprintf(stdout, "-----------------------------------------------\n");
    928     fprintf(stdout, "                Test VAD API\n");
    929     fprintf(stdout, "-----------------------------------------------\n");
    930   }
    931 
    932   if (side == 'A') {
    933     AudioCodingModule::Codec(_codecCntrA, &myCodec);
    934     vad = &_sendVADA;
    935     dtx = &_sendDTXA;
    936     mode = &_sendVADModeA;
    937     myChannel = _channel_A2B;
    938     myACM = _acmA.get();
    939   } else {
    940     AudioCodingModule::Codec(_codecCntrB, &myCodec);
    941     vad = &_sendVADB;
    942     dtx = &_sendDTXB;
    943     mode = &_sendVADModeB;
    944     myChannel = _channel_B2A;
    945     myACM = _acmB.get();
    946   }
    947 
    948   CheckVADStatus(side);
    949   if (!_randomTest) {
    950     fprintf(stdout, "\n\n");
    951   }
    952 
    953   switch (*mode) {
    954     case VADNormal:
    955       *vad = true;
    956       *dtx = true;
    957       *mode = VADAggr;
    958       break;
    959     case VADLowBitrate:
    960       *vad = true;
    961       *dtx = true;
    962       *mode = VADVeryAggr;
    963       break;
    964     case VADAggr:
    965       *vad = true;
    966       *dtx = true;
    967       *mode = VADLowBitrate;
    968       break;
    969     case VADVeryAggr:
    970       *vad = false;
    971       *dtx = false;
    972       *mode = VADNormal;
    973       break;
    974     default:
    975       *mode = VADNormal;
    976   }
    977 
    978   *dtx = (myCodec.plfreq == 32000) ? false : *dtx;
    979 
    980   CHECK_ERROR_MT(myACM->SetVAD(*dtx, *vad, *mode));
    981   myChannel->ResetStats();
    982 
    983   CheckVADStatus(side);
    984   if (!_randomTest) {
    985     fprintf(stdout, "\n");
    986     fprintf(stdout, "-----------------------------------------------\n");
    987   }
    988 
    989   // Fault Test
    990   CHECK_PROTECTED_MT(myACM->SetVAD(false, true, (ACMVADMode) - 1));
    991   CHECK_PROTECTED_MT(myACM->SetVAD(false, true, (ACMVADMode) 4));
    992 
    993 }
    994 
    995 void APITest::CurrentCodec(char side) {
    996   auto myCodec = (side == 'A' ? _acmA : _acmB)->SendCodec();
    997 
    998   if (!_randomTest) {
    999     fprintf(stdout, "\n\n");
   1000     fprintf(stdout, "Send codec in Side A\n");
   1001     fprintf(stdout, "----------------------------\n");
   1002     fprintf(stdout, "Name................. %s\n", myCodec->plname);
   1003     fprintf(stdout, "Sampling Frequency... %d\n", myCodec->plfreq);
   1004     fprintf(stdout, "Rate................. %d\n", myCodec->rate);
   1005     fprintf(stdout, "Payload-type......... %d\n", myCodec->pltype);
   1006     fprintf(stdout, "Packet-size.......... %d\n", myCodec->pacsize);
   1007   }
   1008 
   1009   Wait(100);
   1010 }
   1011 
   1012 void APITest::ChangeCodec(char side) {
   1013   CodecInst myCodec;
   1014   AudioCodingModule* myACM;
   1015   uint8_t* codecCntr;
   1016   bool* thereIsEncoder;
   1017   bool* vad;
   1018   bool* dtx;
   1019   ACMVADMode* mode;
   1020   Channel* myChannel;
   1021   // Reset and Wait
   1022   if (!_randomTest) {
   1023     fprintf(stdout, "Reset Encoder Side A \n");
   1024   }
   1025   if (side == 'A') {
   1026     myACM = _acmA.get();
   1027     codecCntr = &_codecCntrA;
   1028     {
   1029       WriteLockScoped wl(_apiTestRWLock);
   1030       thereIsEncoder = &_thereIsEncoderA;
   1031     }
   1032     vad = &_sendVADA;
   1033     dtx = &_sendDTXA;
   1034     mode = &_sendVADModeA;
   1035     myChannel = _channel_A2B;
   1036   } else {
   1037     myACM = _acmB.get();
   1038     codecCntr = &_codecCntrB;
   1039     {
   1040       WriteLockScoped wl(_apiTestRWLock);
   1041       thereIsEncoder = &_thereIsEncoderB;
   1042     }
   1043     vad = &_sendVADB;
   1044     dtx = &_sendDTXB;
   1045     mode = &_sendVADModeB;
   1046     myChannel = _channel_B2A;
   1047   }
   1048 
   1049   Wait(100);
   1050 
   1051   // Register the next codec
   1052   do {
   1053     *codecCntr =
   1054         (*codecCntr < AudioCodingModule::NumberOfCodecs() - 1) ?
   1055             (*codecCntr + 1) : 0;
   1056 
   1057     if (*codecCntr == 0) {
   1058       //printf("Initialize Sender Side A \n");
   1059       {
   1060         WriteLockScoped wl(_apiTestRWLock);
   1061         *thereIsEncoder = false;
   1062       }
   1063       // After Initialization CN is lost, re-register them
   1064       if (AudioCodingModule::Codec("CN", &myCodec, 8000, 1) >= 0) {
   1065         CHECK_ERROR_MT(myACM->RegisterSendCodec(myCodec));
   1066       }
   1067       if (AudioCodingModule::Codec("CN", &myCodec, 16000, 1) >= 0) {
   1068         CHECK_ERROR_MT(myACM->RegisterSendCodec(myCodec));
   1069       }
   1070       // VAD & DTX are disabled after initialization
   1071       *vad = false;
   1072       *dtx = false;
   1073       _writeToFile = false;
   1074     }
   1075 
   1076     AudioCodingModule::Codec(*codecCntr, &myCodec);
   1077   } while (!STR_CASE_CMP(myCodec.plname, "CN")
   1078       || !STR_CASE_CMP(myCodec.plname, "telephone-event")
   1079       || !STR_CASE_CMP(myCodec.plname, "RED"));
   1080 
   1081   if (!_randomTest) {
   1082     fprintf(stdout,"\n=====================================================\n");
   1083     fprintf(stdout, "      Registering New Codec %s, %d kHz, %d kbps\n",
   1084             myCodec.plname, myCodec.plfreq / 1000, myCodec.rate / 1000);
   1085   }
   1086   //std::cout<< std::flush;
   1087 
   1088   // NO DTX for supe-wideband codec at this point
   1089   if (myCodec.plfreq == 32000) {
   1090     *dtx = false;
   1091     CHECK_ERROR_MT(myACM->SetVAD(*dtx, *vad, *mode));
   1092 
   1093   }
   1094 
   1095   CHECK_ERROR_MT(myACM->RegisterSendCodec(myCodec));
   1096   myChannel->ResetStats();
   1097   {
   1098     WriteLockScoped wl(_apiTestRWLock);
   1099     *thereIsEncoder = true;
   1100   }
   1101   Wait(500);
   1102 }
   1103 
   1104 }  // namespace webrtc
   1105