• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
Wait(uint32_t waitLengthMs)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 
APITest(const Config & config)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 
~APITest()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 
SetUp()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 
PushAudioThreadA(void * obj)291 bool APITest::PushAudioThreadA(void* obj) {
292   return static_cast<APITest*>(obj)->PushAudioRunA();
293 }
294 
PushAudioThreadB(void * obj)295 bool APITest::PushAudioThreadB(void* obj) {
296   return static_cast<APITest*>(obj)->PushAudioRunB();
297 }
298 
PullAudioThreadA(void * obj)299 bool APITest::PullAudioThreadA(void* obj) {
300   return static_cast<APITest*>(obj)->PullAudioRunA();
301 }
302 
PullAudioThreadB(void * obj)303 bool APITest::PullAudioThreadB(void* obj) {
304   return static_cast<APITest*>(obj)->PullAudioRunB();
305 }
306 
ProcessThreadA(void * obj)307 bool APITest::ProcessThreadA(void* obj) {
308   return static_cast<APITest*>(obj)->ProcessRunA();
309 }
310 
ProcessThreadB(void * obj)311 bool APITest::ProcessThreadB(void* obj) {
312   return static_cast<APITest*>(obj)->ProcessRunB();
313 }
314 
APIThreadA(void * obj)315 bool APITest::APIThreadA(void* obj) {
316   return static_cast<APITest*>(obj)->APIRunA();
317 }
318 
APIThreadB(void * obj)319 bool APITest::APIThreadB(void* obj) {
320   return static_cast<APITest*>(obj)->APIRunB();
321 }
322 
PullAudioRunA()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 
PullAudioRunB()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 
PushAudioRunA()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 
PushAudioRunB()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 
ProcessRunA()400 bool APITest::ProcessRunA() {
401   _processEventA->Wait(100);
402   return true;
403 }
404 
ProcessRunB()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 
RunTest(char thread)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 
APIRunA()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 
APIRunB()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 
Perform()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 
CheckVADStatus(char side)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
TestDelay(char side)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.
TestRegisteration(char sendSide)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 
TestSendVAD(char side)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 
CurrentCodec(char side)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 
ChangeCodec(char side)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