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
34namespace 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
47void 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
58APITest::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
109APITest::~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
136int16_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
303bool APITest::PushAudioThreadA(void* obj) {
304  return static_cast<APITest*>(obj)->PushAudioRunA();
305}
306
307bool APITest::PushAudioThreadB(void* obj) {
308  return static_cast<APITest*>(obj)->PushAudioRunB();
309}
310
311bool APITest::PullAudioThreadA(void* obj) {
312  return static_cast<APITest*>(obj)->PullAudioRunA();
313}
314
315bool APITest::PullAudioThreadB(void* obj) {
316  return static_cast<APITest*>(obj)->PullAudioRunB();
317}
318
319bool APITest::ProcessThreadA(void* obj) {
320  return static_cast<APITest*>(obj)->ProcessRunA();
321}
322
323bool APITest::ProcessThreadB(void* obj) {
324  return static_cast<APITest*>(obj)->ProcessRunB();
325}
326
327bool APITest::APIThreadA(void* obj) {
328  return static_cast<APITest*>(obj)->APIRunA();
329}
330
331bool APITest::APIThreadB(void* obj) {
332  return static_cast<APITest*>(obj)->APIRunB();
333}
334
335bool 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
355bool 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
376bool 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
393bool 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
412bool 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
429bool 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
450void 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
511bool 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
536bool 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
551void 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
645void 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
716void 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.
832void 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.
963void 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
1022void 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
1104void 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
1126void 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