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