Home | History | Annotate | Download | only in test
      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 "TwoWayCommunication.h"
     12 
     13 #include <ctype.h>
     14 #include <stdio.h>
     15 #include <string.h>
     16 
     17 #ifdef WIN32
     18 #include <Windows.h>
     19 #endif
     20 
     21 #include "testing/gtest/include/gtest/gtest.h"
     22 #include "webrtc/engine_configurations.h"
     23 #include "webrtc/common_types.h"
     24 #include "webrtc/modules/audio_coding/test/PCMFile.h"
     25 #include "webrtc/modules/audio_coding/test/utility.h"
     26 #include "webrtc/system_wrappers/include/trace.h"
     27 #include "webrtc/test/testsupport/fileutils.h"
     28 
     29 namespace webrtc {
     30 
     31 #define MAX_FILE_NAME_LENGTH_BYTE 500
     32 
     33 TwoWayCommunication::TwoWayCommunication(int testMode)
     34     : _acmA(AudioCodingModule::Create(1)),
     35       _acmRefA(AudioCodingModule::Create(3)),
     36       _testMode(testMode) {
     37   AudioCodingModule::Config config;
     38   // The clicks will be more obvious in FAX mode. TODO(henrik.lundin) Really?
     39   config.neteq_config.playout_mode = kPlayoutFax;
     40   config.id = 2;
     41   _acmB.reset(AudioCodingModule::Create(config));
     42   config.id = 4;
     43   _acmRefB.reset(AudioCodingModule::Create(config));
     44 }
     45 
     46 TwoWayCommunication::~TwoWayCommunication() {
     47   delete _channel_A2B;
     48   delete _channel_B2A;
     49   delete _channelRef_A2B;
     50   delete _channelRef_B2A;
     51 #ifdef WEBRTC_DTMF_DETECTION
     52   if (_dtmfDetectorA != NULL) {
     53     delete _dtmfDetectorA;
     54   }
     55   if (_dtmfDetectorB != NULL) {
     56     delete _dtmfDetectorB;
     57   }
     58 #endif
     59   _inFileA.Close();
     60   _inFileB.Close();
     61   _outFileA.Close();
     62   _outFileB.Close();
     63   _outFileRefA.Close();
     64   _outFileRefB.Close();
     65 }
     66 
     67 void TwoWayCommunication::ChooseCodec(uint8_t* codecID_A,
     68                                       uint8_t* codecID_B) {
     69   rtc::scoped_ptr<AudioCodingModule> tmpACM(AudioCodingModule::Create(0));
     70   uint8_t noCodec = tmpACM->NumberOfCodecs();
     71   CodecInst codecInst;
     72   printf("List of Supported Codecs\n");
     73   printf("========================\n");
     74   for (uint8_t codecCntr = 0; codecCntr < noCodec; codecCntr++) {
     75     EXPECT_EQ(tmpACM->Codec(codecCntr, &codecInst), 0);
     76     printf("%d- %s\n", codecCntr, codecInst.plname);
     77   }
     78   printf("\nChoose a send codec for side A [0]: ");
     79   char myStr[15] = "";
     80   EXPECT_TRUE(fgets(myStr, 10, stdin) != NULL);
     81   *codecID_A = (uint8_t) atoi(myStr);
     82 
     83   printf("\nChoose a send codec for side B [0]: ");
     84   EXPECT_TRUE(fgets(myStr, 10, stdin) != NULL);
     85   *codecID_B = (uint8_t) atoi(myStr);
     86 
     87   printf("\n");
     88 }
     89 
     90 void TwoWayCommunication::SetUp() {
     91   uint8_t codecID_A;
     92   uint8_t codecID_B;
     93 
     94   ChooseCodec(&codecID_A, &codecID_B);
     95   CodecInst codecInst_A;
     96   CodecInst codecInst_B;
     97   CodecInst dummyCodec;
     98   EXPECT_EQ(0, _acmA->Codec(codecID_A, &codecInst_A));
     99   EXPECT_EQ(0, _acmB->Codec(codecID_B, &codecInst_B));
    100   EXPECT_EQ(0, _acmA->Codec(6, &dummyCodec));
    101 
    102   //--- Set A codecs
    103   EXPECT_EQ(0, _acmA->RegisterSendCodec(codecInst_A));
    104   EXPECT_EQ(0, _acmA->RegisterReceiveCodec(codecInst_B));
    105   //--- Set ref-A codecs
    106   EXPECT_EQ(0, _acmRefA->RegisterSendCodec(codecInst_A));
    107   EXPECT_EQ(0, _acmRefA->RegisterReceiveCodec(codecInst_B));
    108 
    109   //--- Set B codecs
    110   EXPECT_EQ(0, _acmB->RegisterSendCodec(codecInst_B));
    111   EXPECT_EQ(0, _acmB->RegisterReceiveCodec(codecInst_A));
    112 
    113   //--- Set ref-B codecs
    114   EXPECT_EQ(0, _acmRefB->RegisterSendCodec(codecInst_B));
    115   EXPECT_EQ(0, _acmRefB->RegisterReceiveCodec(codecInst_A));
    116 
    117   uint16_t frequencyHz;
    118 
    119   //--- Input A
    120   std::string in_file_name = webrtc::test::ResourcePath(
    121       "audio_coding/testfile32kHz", "pcm");
    122   frequencyHz = 32000;
    123   printf("Enter input file at side A [%s]: ", in_file_name.c_str());
    124   PCMFile::ChooseFile(&in_file_name, 499, &frequencyHz);
    125   _inFileA.Open(in_file_name, frequencyHz, "rb");
    126 
    127   //--- Output A
    128   std::string out_file_a = webrtc::test::OutputPath() + "outA.pcm";
    129   printf("Output file at side A: %s\n", out_file_a.c_str());
    130   printf("Sampling frequency (in Hz) of the above file: %u\n", frequencyHz);
    131   _outFileA.Open(out_file_a, frequencyHz, "wb");
    132   std::string ref_file_name = webrtc::test::OutputPath() + "ref_outA.pcm";
    133   _outFileRefA.Open(ref_file_name, frequencyHz, "wb");
    134 
    135   //--- Input B
    136   in_file_name = webrtc::test::ResourcePath("audio_coding/testfile32kHz",
    137                                             "pcm");
    138   frequencyHz = 32000;
    139   printf("\n\nEnter input file at side B [%s]: ", in_file_name.c_str());
    140   PCMFile::ChooseFile(&in_file_name, 499, &frequencyHz);
    141   _inFileB.Open(in_file_name, frequencyHz, "rb");
    142 
    143   //--- Output B
    144   std::string out_file_b = webrtc::test::OutputPath() + "outB.pcm";
    145   printf("Output file at side B: %s\n", out_file_b.c_str());
    146   printf("Sampling frequency (in Hz) of the above file: %u\n", frequencyHz);
    147   _outFileB.Open(out_file_b, frequencyHz, "wb");
    148   ref_file_name = webrtc::test::OutputPath() + "ref_outB.pcm";
    149   _outFileRefB.Open(ref_file_name, frequencyHz, "wb");
    150 
    151   //--- Set A-to-B channel
    152   _channel_A2B = new Channel;
    153   _acmA->RegisterTransportCallback(_channel_A2B);
    154   _channel_A2B->RegisterReceiverACM(_acmB.get());
    155   //--- Do the same for the reference
    156   _channelRef_A2B = new Channel;
    157   _acmRefA->RegisterTransportCallback(_channelRef_A2B);
    158   _channelRef_A2B->RegisterReceiverACM(_acmRefB.get());
    159 
    160   //--- Set B-to-A channel
    161   _channel_B2A = new Channel;
    162   _acmB->RegisterTransportCallback(_channel_B2A);
    163   _channel_B2A->RegisterReceiverACM(_acmA.get());
    164   //--- Do the same for reference
    165   _channelRef_B2A = new Channel;
    166   _acmRefB->RegisterTransportCallback(_channelRef_B2A);
    167   _channelRef_B2A->RegisterReceiverACM(_acmRefA.get());
    168 }
    169 
    170 void TwoWayCommunication::SetUpAutotest() {
    171   CodecInst codecInst_A;
    172   CodecInst codecInst_B;
    173   CodecInst dummyCodec;
    174 
    175   EXPECT_EQ(0, _acmA->Codec("ISAC", &codecInst_A, 16000, 1));
    176   EXPECT_EQ(0, _acmB->Codec("L16", &codecInst_B, 8000, 1));
    177   EXPECT_EQ(0, _acmA->Codec(6, &dummyCodec));
    178 
    179   //--- Set A codecs
    180   EXPECT_EQ(0, _acmA->RegisterSendCodec(codecInst_A));
    181   EXPECT_EQ(0, _acmA->RegisterReceiveCodec(codecInst_B));
    182 
    183   //--- Set ref-A codecs
    184   EXPECT_GT(_acmRefA->RegisterSendCodec(codecInst_A), -1);
    185   EXPECT_GT(_acmRefA->RegisterReceiveCodec(codecInst_B), -1);
    186 
    187   //--- Set B codecs
    188   EXPECT_GT(_acmB->RegisterSendCodec(codecInst_B), -1);
    189   EXPECT_GT(_acmB->RegisterReceiveCodec(codecInst_A), -1);
    190 
    191   //--- Set ref-B codecs
    192   EXPECT_EQ(0, _acmRefB->RegisterSendCodec(codecInst_B));
    193   EXPECT_EQ(0, _acmRefB->RegisterReceiveCodec(codecInst_A));
    194 
    195   uint16_t frequencyHz;
    196 
    197   //--- Input A and B
    198   std::string in_file_name = webrtc::test::ResourcePath(
    199       "audio_coding/testfile32kHz", "pcm");
    200   frequencyHz = 16000;
    201   _inFileA.Open(in_file_name, frequencyHz, "rb");
    202   _inFileB.Open(in_file_name, frequencyHz, "rb");
    203 
    204   //--- Output A
    205   std::string output_file_a = webrtc::test::OutputPath() + "outAutotestA.pcm";
    206   frequencyHz = 16000;
    207   _outFileA.Open(output_file_a, frequencyHz, "wb");
    208   std::string output_ref_file_a = webrtc::test::OutputPath()
    209       + "ref_outAutotestA.pcm";
    210   _outFileRefA.Open(output_ref_file_a, frequencyHz, "wb");
    211 
    212   //--- Output B
    213   std::string output_file_b = webrtc::test::OutputPath() + "outAutotestB.pcm";
    214   frequencyHz = 16000;
    215   _outFileB.Open(output_file_b, frequencyHz, "wb");
    216   std::string output_ref_file_b = webrtc::test::OutputPath()
    217       + "ref_outAutotestB.pcm";
    218   _outFileRefB.Open(output_ref_file_b, frequencyHz, "wb");
    219 
    220   //--- Set A-to-B channel
    221   _channel_A2B = new Channel;
    222   _acmA->RegisterTransportCallback(_channel_A2B);
    223   _channel_A2B->RegisterReceiverACM(_acmB.get());
    224   //--- Do the same for the reference
    225   _channelRef_A2B = new Channel;
    226   _acmRefA->RegisterTransportCallback(_channelRef_A2B);
    227   _channelRef_A2B->RegisterReceiverACM(_acmRefB.get());
    228 
    229   //--- Set B-to-A channel
    230   _channel_B2A = new Channel;
    231   _acmB->RegisterTransportCallback(_channel_B2A);
    232   _channel_B2A->RegisterReceiverACM(_acmA.get());
    233   //--- Do the same for reference
    234   _channelRef_B2A = new Channel;
    235   _acmRefB->RegisterTransportCallback(_channelRef_B2A);
    236   _channelRef_B2A->RegisterReceiverACM(_acmRefA.get());
    237 }
    238 
    239 void TwoWayCommunication::Perform() {
    240   if (_testMode == 0) {
    241     SetUpAutotest();
    242   } else {
    243     SetUp();
    244   }
    245   unsigned int msecPassed = 0;
    246   unsigned int secPassed = 0;
    247 
    248   int32_t outFreqHzA = _outFileA.SamplingFrequency();
    249   int32_t outFreqHzB = _outFileB.SamplingFrequency();
    250 
    251   AudioFrame audioFrame;
    252 
    253   auto codecInst_B = _acmB->SendCodec();
    254   ASSERT_TRUE(codecInst_B);
    255 
    256   // In the following loop we tests that the code can handle misuse of the APIs.
    257   // In the middle of a session with data flowing between two sides, called A
    258   // and B, APIs will be called, and the code should continue to run, and be
    259   // able to recover.
    260   while (!_inFileA.EndOfFile() && !_inFileB.EndOfFile()) {
    261     msecPassed += 10;
    262     EXPECT_GT(_inFileA.Read10MsData(audioFrame), 0);
    263     EXPECT_GE(_acmA->Add10MsData(audioFrame), 0);
    264     EXPECT_GE(_acmRefA->Add10MsData(audioFrame), 0);
    265 
    266     EXPECT_GT(_inFileB.Read10MsData(audioFrame), 0);
    267 
    268     EXPECT_GE(_acmB->Add10MsData(audioFrame), 0);
    269     EXPECT_GE(_acmRefB->Add10MsData(audioFrame), 0);
    270     EXPECT_EQ(0, _acmA->PlayoutData10Ms(outFreqHzA, &audioFrame));
    271     _outFileA.Write10MsData(audioFrame);
    272     EXPECT_EQ(0, _acmRefA->PlayoutData10Ms(outFreqHzA, &audioFrame));
    273     _outFileRefA.Write10MsData(audioFrame);
    274     EXPECT_EQ(0, _acmB->PlayoutData10Ms(outFreqHzB, &audioFrame));
    275     _outFileB.Write10MsData(audioFrame);
    276     EXPECT_EQ(0, _acmRefB->PlayoutData10Ms(outFreqHzB, &audioFrame));
    277     _outFileRefB.Write10MsData(audioFrame);
    278 
    279     // Update time counters each time a second of data has passed.
    280     if (msecPassed >= 1000) {
    281       msecPassed = 0;
    282       secPassed++;
    283     }
    284     // Re-register send codec on side B.
    285     if (((secPassed % 5) == 4) && (msecPassed >= 990)) {
    286       EXPECT_EQ(0, _acmB->RegisterSendCodec(*codecInst_B));
    287       EXPECT_TRUE(_acmB->SendCodec());
    288     }
    289     // Initialize receiver on side A.
    290     if (((secPassed % 7) == 6) && (msecPassed == 0))
    291       EXPECT_EQ(0, _acmA->InitializeReceiver());
    292     // Re-register codec on side A.
    293     if (((secPassed % 7) == 6) && (msecPassed >= 990)) {
    294       EXPECT_EQ(0, _acmA->RegisterReceiveCodec(*codecInst_B));
    295     }
    296   }
    297 }
    298 
    299 }  // namespace webrtc
    300