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