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