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