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