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 "testing/gtest/include/gtest/gtest.h"
     12 #include "webrtc/modules/audio_coding/main/acm2/acm_common_defs.h"
     13 #include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h"
     14 #include "webrtc/modules/audio_coding/main/test/PCMFile.h"
     15 #include "webrtc/modules/audio_coding/main/test/utility.h"
     16 #include "webrtc/modules/interface/module_common_types.h"
     17 #include "webrtc/system_wrappers/interface/scoped_ptr.h"
     18 #include "webrtc/typedefs.h"
     19 #include "webrtc/test/testsupport/fileutils.h"
     20 #include "webrtc/test/testsupport/gtest_disable.h"
     21 
     22 namespace webrtc {
     23 
     24 class DualStreamTest : public AudioPacketizationCallback,
     25                        public ::testing::Test {
     26  protected:
     27   DualStreamTest();
     28   ~DualStreamTest();
     29 
     30   void RunTest(int frame_size_primary_samples,
     31                int num_channels_primary,
     32                int sampling_rate,
     33                bool start_in_sync,
     34                int num_channels_input);
     35 
     36   void ApiTest();
     37 
     38   virtual int32_t SendData(
     39       FrameType frameType, uint8_t payload_type,
     40       uint32_t timestamp, const uint8_t* payload_data,
     41       uint16_t payload_size,
     42       const RTPFragmentationHeader* fragmentation) OVERRIDE;
     43 
     44   void Perform(bool start_in_sync, int num_channels_input);
     45 
     46   void InitializeSender(int frame_size_primary_samples,
     47                         int num_channels_primary, int sampling_rate);
     48 
     49   void PopulateCodecInstances(int frame_size_primary_ms,
     50                               int num_channels_primary, int sampling_rate);
     51 
     52   void Validate(bool start_in_sync, int tolerance);
     53   bool EqualTimestamp(int stream, int position);
     54   int EqualPayloadLength(int stream, int position);
     55   bool EqualPayloadData(int stream, int position);
     56 
     57   static const int kMaxNumStoredPayloads = 2;
     58 
     59   enum {
     60     kPrimary = 0,
     61     kSecondary,
     62     kMaxNumStreams
     63   };
     64 
     65   scoped_ptr<AudioCodingModule> acm_dual_stream_;
     66   scoped_ptr<AudioCodingModule> acm_ref_primary_;
     67   scoped_ptr<AudioCodingModule> acm_ref_secondary_;
     68 
     69   CodecInst primary_encoder_;
     70   CodecInst secondary_encoder_;
     71 
     72   CodecInst red_encoder_;
     73 
     74   int payload_ref_is_stored_[kMaxNumStreams][kMaxNumStoredPayloads];
     75   int payload_dual_is_stored_[kMaxNumStreams][kMaxNumStoredPayloads];
     76 
     77   uint32_t timestamp_ref_[kMaxNumStreams][kMaxNumStoredPayloads];
     78   uint32_t timestamp_dual_[kMaxNumStreams][kMaxNumStoredPayloads];
     79 
     80   int payload_len_ref_[kMaxNumStreams][kMaxNumStoredPayloads];
     81   int payload_len_dual_[kMaxNumStreams][kMaxNumStoredPayloads];
     82 
     83   uint8_t payload_data_ref_[kMaxNumStreams][MAX_PAYLOAD_SIZE_BYTE
     84       * kMaxNumStoredPayloads];
     85   uint8_t payload_data_dual_[kMaxNumStreams][MAX_PAYLOAD_SIZE_BYTE
     86       * kMaxNumStoredPayloads];
     87   int num_received_payloads_dual_[kMaxNumStreams];
     88   int num_received_payloads_ref_[kMaxNumStreams];
     89 
     90   int num_compared_payloads_[kMaxNumStreams];
     91   uint32_t last_timestamp_[kMaxNumStreams];
     92   bool received_payload_[kMaxNumStreams];
     93 };
     94 
     95 DualStreamTest::DualStreamTest()
     96     : acm_dual_stream_(AudioCodingModule::Create(0)),
     97       acm_ref_primary_(AudioCodingModule::Create(1)),
     98       acm_ref_secondary_(AudioCodingModule::Create(2)),
     99       payload_ref_is_stored_(),
    100       payload_dual_is_stored_(),
    101       timestamp_ref_(),
    102       num_received_payloads_dual_(),
    103       num_received_payloads_ref_(),
    104       num_compared_payloads_(),
    105       last_timestamp_(),
    106       received_payload_() {}
    107 
    108 DualStreamTest::~DualStreamTest() {}
    109 
    110 void DualStreamTest::PopulateCodecInstances(int frame_size_primary_ms,
    111                                             int num_channels_primary,
    112                                             int sampling_rate) {
    113   CodecInst my_codec;
    114 
    115   // Invalid values. To check later on if the codec are found in the database.
    116   primary_encoder_.pltype = -1;
    117   secondary_encoder_.pltype = -1;
    118   red_encoder_.pltype = -1;
    119 
    120   for (int n = 0; n < AudioCodingModule::NumberOfCodecs(); n++) {
    121     AudioCodingModule::Codec(n, &my_codec);
    122     if (strcmp(my_codec.plname, "ISAC") == 0
    123         && my_codec.plfreq == sampling_rate) {
    124       my_codec.rate = 32000;
    125       my_codec.pacsize = 30 * sampling_rate / 1000;
    126       memcpy(&secondary_encoder_, &my_codec, sizeof(my_codec));
    127     } else if (strcmp(my_codec.plname, "L16") == 0
    128         && my_codec.channels == num_channels_primary
    129         && my_codec.plfreq == sampling_rate) {
    130       my_codec.pacsize = frame_size_primary_ms * sampling_rate / 1000;
    131       memcpy(&primary_encoder_, &my_codec, sizeof(my_codec));
    132     } else if (strcmp(my_codec.plname, "red") == 0) {
    133       memcpy(&red_encoder_, &my_codec, sizeof(my_codec));
    134     }
    135   }
    136 
    137   ASSERT_GE(primary_encoder_.pltype, 0);
    138   ASSERT_GE(secondary_encoder_.pltype, 0);
    139   ASSERT_GE(red_encoder_.pltype, 0);
    140 }
    141 
    142 void DualStreamTest::InitializeSender(int frame_size_primary_samples,
    143                                       int num_channels_primary,
    144                                       int sampling_rate) {
    145   ASSERT_TRUE(acm_dual_stream_.get() != NULL);
    146   ASSERT_TRUE(acm_ref_primary_.get() != NULL);
    147   ASSERT_TRUE(acm_ref_secondary_.get() != NULL);
    148 
    149   ASSERT_EQ(0, acm_dual_stream_->InitializeSender());
    150   ASSERT_EQ(0, acm_ref_primary_->InitializeSender());
    151   ASSERT_EQ(0, acm_ref_secondary_->InitializeSender());
    152 
    153   PopulateCodecInstances(frame_size_primary_samples, num_channels_primary,
    154                          sampling_rate);
    155 
    156   ASSERT_EQ(0, acm_ref_primary_->RegisterSendCodec(primary_encoder_));
    157   ASSERT_EQ(0, acm_ref_secondary_->RegisterSendCodec(secondary_encoder_));
    158   ASSERT_EQ(0, acm_dual_stream_->RegisterSendCodec(primary_encoder_));
    159   ASSERT_EQ(0,
    160             acm_dual_stream_->RegisterSecondarySendCodec(secondary_encoder_));
    161 
    162   ASSERT_EQ(0, acm_ref_primary_->RegisterTransportCallback(this));
    163   ASSERT_EQ(0, acm_ref_secondary_->RegisterTransportCallback(this));
    164   ASSERT_EQ(0, acm_dual_stream_->RegisterTransportCallback(this));
    165 }
    166 
    167 void DualStreamTest::Perform(bool start_in_sync, int num_channels_input) {
    168   PCMFile pcm_file;
    169   std::string file_name = test::ResourcePath(
    170       (num_channels_input == 1) ?
    171           "audio_coding/testfile32kHz" : "audio_coding/teststereo32kHz",
    172       "pcm");
    173   pcm_file.Open(file_name, 32000, "rb");
    174   pcm_file.ReadStereo(num_channels_input == 2);
    175   AudioFrame audio_frame;
    176 
    177   int tolerance = 0;
    178   if (num_channels_input == 2 && primary_encoder_.channels == 2
    179       && secondary_encoder_.channels == 1) {
    180     tolerance = 12;
    181   }
    182 
    183   if (!start_in_sync) {
    184     pcm_file.Read10MsData(audio_frame);
    185     // Unregister secondary codec and feed only the primary
    186     acm_dual_stream_->UnregisterSecondarySendCodec();
    187     EXPECT_EQ(0, acm_dual_stream_->Add10MsData(audio_frame));
    188     EXPECT_EQ(0, acm_ref_primary_->Add10MsData(audio_frame));
    189     ASSERT_EQ(0,
    190               acm_dual_stream_->RegisterSecondarySendCodec(secondary_encoder_));
    191   }
    192 
    193   const int kNumFramesToProcess = 100;
    194   int frame_cntr = 0;
    195   while (!pcm_file.EndOfFile() && frame_cntr < kNumFramesToProcess) {
    196     pcm_file.Read10MsData(audio_frame);
    197     frame_cntr++;
    198     EXPECT_EQ(0, acm_dual_stream_->Add10MsData(audio_frame));
    199     EXPECT_EQ(0, acm_ref_primary_->Add10MsData(audio_frame));
    200     EXPECT_EQ(0, acm_ref_secondary_->Add10MsData(audio_frame));
    201 
    202     EXPECT_GE(acm_dual_stream_->Process(), 0);
    203     EXPECT_GE(acm_ref_primary_->Process(), 0);
    204     EXPECT_GE(acm_ref_secondary_->Process(), 0);
    205 
    206     if (start_in_sync || frame_cntr > 7) {
    207       // If we haven't started in sync the first few audio frames might
    208       // slightly differ due to the difference in the state of the resamplers
    209       // of dual-ACM and reference-ACM.
    210       Validate(start_in_sync, tolerance);
    211     } else {
    212       // SendData stores the payloads, if we are not comparing we have to free
    213       // the space by resetting these flags.
    214       memset(payload_ref_is_stored_, 0, sizeof(payload_ref_is_stored_));
    215       memset(payload_dual_is_stored_, 0, sizeof(payload_dual_is_stored_));
    216     }
    217   }
    218   pcm_file.Close();
    219 
    220   // Make sure that number of received payloads match. In case of secondary
    221   // encoder, the dual-stream might deliver one lesser payload. The reason is
    222   // that some secondary payloads are stored to be sent with a payload generated
    223   // later and the input file may end before the "next" payload .
    224   EXPECT_EQ(num_received_payloads_ref_[kPrimary],
    225             num_received_payloads_dual_[kPrimary]);
    226   EXPECT_TRUE(
    227       num_received_payloads_ref_[kSecondary]
    228           == num_received_payloads_dual_[kSecondary]
    229           || num_received_payloads_ref_[kSecondary]
    230               == (num_received_payloads_dual_[kSecondary] + 1));
    231 
    232   // Make sure all received payloads are compared.
    233   if (start_in_sync) {
    234     EXPECT_EQ(num_received_payloads_dual_[kPrimary],
    235               num_compared_payloads_[kPrimary]);
    236     EXPECT_EQ(num_received_payloads_dual_[kSecondary],
    237               num_compared_payloads_[kSecondary]);
    238   } else {
    239     // In asynchronous test we don't compare couple of first frames, so we
    240     // should account for them in our counting.
    241     EXPECT_GE(num_compared_payloads_[kPrimary],
    242               num_received_payloads_dual_[kPrimary] - 4);
    243     EXPECT_GE(num_compared_payloads_[kSecondary],
    244               num_received_payloads_dual_[kSecondary] - 4);
    245   }
    246 }
    247 
    248 bool DualStreamTest::EqualTimestamp(int stream_index, int position) {
    249   if (timestamp_dual_[stream_index][position]
    250       != timestamp_ref_[stream_index][position]) {
    251     return false;
    252   }
    253   return true;
    254 }
    255 
    256 int DualStreamTest::EqualPayloadLength(int stream_index, int position) {
    257   return abs(
    258       payload_len_dual_[stream_index][position]
    259           - payload_len_ref_[stream_index][position]);
    260 }
    261 
    262 bool DualStreamTest::EqualPayloadData(int stream_index, int position) {
    263   assert(
    264       payload_len_dual_[stream_index][position]
    265           == payload_len_ref_[stream_index][position]);
    266   int offset = position * MAX_PAYLOAD_SIZE_BYTE;
    267   for (int n = 0; n < payload_len_dual_[stream_index][position]; n++) {
    268     if (payload_data_dual_[stream_index][offset + n]
    269         != payload_data_ref_[stream_index][offset + n]) {
    270       return false;
    271     }
    272   }
    273   return true;
    274 }
    275 
    276 void DualStreamTest::Validate(bool start_in_sync, int tolerance) {
    277   for (int stream_index = 0; stream_index < kMaxNumStreams; stream_index++) {
    278     int my_tolerance = stream_index == kPrimary ? 0 : tolerance;
    279     for (int position = 0; position < kMaxNumStoredPayloads; position++) {
    280       if (payload_ref_is_stored_[stream_index][position] == 1
    281           && payload_dual_is_stored_[stream_index][position] == 1) {
    282         // Check timestamps only if codecs started in sync or it is primary.
    283         if (start_in_sync || stream_index == 0)
    284           EXPECT_TRUE(EqualTimestamp(stream_index, position));
    285         EXPECT_LE(EqualPayloadLength(stream_index, position), my_tolerance);
    286         if (my_tolerance == 0)
    287           EXPECT_TRUE(EqualPayloadData(stream_index, position));
    288         num_compared_payloads_[stream_index]++;
    289         payload_ref_is_stored_[stream_index][position] = 0;
    290         payload_dual_is_stored_[stream_index][position] = 0;
    291       }
    292     }
    293   }
    294 }
    295 
    296 int32_t DualStreamTest::SendData(FrameType frameType, uint8_t payload_type,
    297                                  uint32_t timestamp,
    298                                  const uint8_t* payload_data,
    299                                  uint16_t payload_size,
    300                                  const RTPFragmentationHeader* fragmentation) {
    301   int position;
    302   int stream_index;
    303 
    304   if (payload_type == red_encoder_.pltype) {
    305     if (fragmentation == NULL) {
    306       assert(false);
    307       return -1;
    308     }
    309     // As the oldest payloads are in the higher indices of fragmentation,
    310     // to be able to check the increment of timestamps are correct we loop
    311     // backward.
    312     for (int n = fragmentation->fragmentationVectorSize - 1; n >= 0; --n) {
    313       if (fragmentation->fragmentationPlType[n] == primary_encoder_.pltype) {
    314         // Received primary payload from dual stream.
    315         stream_index = kPrimary;
    316       } else if (fragmentation->fragmentationPlType[n]
    317           == secondary_encoder_.pltype) {
    318         // Received secondary payload from dual stream.
    319         stream_index = kSecondary;
    320       } else {
    321         assert(false);
    322         return -1;
    323       }
    324       num_received_payloads_dual_[stream_index]++;
    325       if (payload_dual_is_stored_[stream_index][0] == 0) {
    326         position = 0;
    327       } else if (payload_dual_is_stored_[stream_index][1] == 0) {
    328         position = 1;
    329       } else {
    330         assert(false);
    331         return -1;
    332       }
    333       timestamp_dual_[stream_index][position] = timestamp
    334           - fragmentation->fragmentationTimeDiff[n];
    335       payload_len_dual_[stream_index][position] = fragmentation
    336           ->fragmentationLength[n];
    337       memcpy(
    338           &payload_data_dual_[stream_index][position * MAX_PAYLOAD_SIZE_BYTE],
    339           &payload_data[fragmentation->fragmentationOffset[n]],
    340           fragmentation->fragmentationLength[n]);
    341       payload_dual_is_stored_[stream_index][position] = 1;
    342       // Check if timestamps are incremented correctly.
    343       if (received_payload_[stream_index]) {
    344         int t = timestamp_dual_[stream_index][position]
    345             - last_timestamp_[stream_index];
    346         if ((stream_index == kPrimary) && (t != primary_encoder_.pacsize)) {
    347           assert(false);
    348           return -1;
    349         }
    350         if ((stream_index == kSecondary) && (t != secondary_encoder_.pacsize)) {
    351           assert(false);
    352           return -1;
    353         }
    354       } else {
    355         received_payload_[stream_index] = true;
    356       }
    357       last_timestamp_[stream_index] = timestamp_dual_[stream_index][position];
    358     }
    359   } else {
    360     if (fragmentation != NULL) {
    361       assert(false);
    362       return -1;
    363     }
    364     if (payload_type == primary_encoder_.pltype) {
    365       stream_index = kPrimary;
    366     } else if (payload_type == secondary_encoder_.pltype) {
    367       stream_index = kSecondary;
    368     } else {
    369       assert(false);
    370       return -1;
    371     }
    372     num_received_payloads_ref_[stream_index]++;
    373     if (payload_ref_is_stored_[stream_index][0] == 0) {
    374       position = 0;
    375     } else if (payload_ref_is_stored_[stream_index][1] == 0) {
    376       position = 1;
    377     } else {
    378       assert(false);
    379       return -1;
    380     }
    381     timestamp_ref_[stream_index][position] = timestamp;
    382     payload_len_ref_[stream_index][position] = payload_size;
    383     memcpy(&payload_data_ref_[stream_index][position * MAX_PAYLOAD_SIZE_BYTE],
    384            payload_data, payload_size);
    385     payload_ref_is_stored_[stream_index][position] = 1;
    386   }
    387   return 0;
    388 }
    389 
    390 // Mono input, mono primary WB 20 ms frame.
    391 TEST_F(DualStreamTest,
    392        DISABLED_ON_ANDROID(BitExactSyncMonoInputMonoPrimaryWb20Ms)) {
    393   InitializeSender(20, 1, 16000);
    394   Perform(true, 1);
    395 }
    396 
    397 // Mono input, stereo primary WB 20 ms frame.
    398 TEST_F(DualStreamTest,
    399        DISABLED_ON_ANDROID(BitExactSyncMonoInput_StereoPrimaryWb20Ms)) {
    400   InitializeSender(20, 2, 16000);
    401   Perform(true, 1);
    402 }
    403 
    404 // Mono input, mono primary SWB 20 ms frame.
    405 TEST_F(DualStreamTest,
    406        DISABLED_ON_ANDROID(BitExactSyncMonoInputMonoPrimarySwb20Ms)) {
    407   InitializeSender(20, 1, 32000);
    408   Perform(true, 1);
    409 }
    410 
    411 // Mono input, stereo primary SWB 20 ms frame.
    412 TEST_F(DualStreamTest,
    413        DISABLED_ON_ANDROID(BitExactSyncMonoInputStereoPrimarySwb20Ms)) {
    414   InitializeSender(20, 2, 32000);
    415   Perform(true, 1);
    416 }
    417 
    418 // Mono input, mono primary WB 40 ms frame.
    419 TEST_F(DualStreamTest,
    420        DISABLED_ON_ANDROID(BitExactSyncMonoInputMonoPrimaryWb40Ms)) {
    421   InitializeSender(40, 1, 16000);
    422   Perform(true, 1);
    423 }
    424 
    425 // Mono input, stereo primary WB 40 ms frame
    426 TEST_F(DualStreamTest,
    427        DISABLED_ON_ANDROID(BitExactSyncMonoInputStereoPrimaryWb40Ms)) {
    428   InitializeSender(40, 2, 16000);
    429   Perform(true, 1);
    430 }
    431 
    432 // Stereo input, mono primary WB 20 ms frame.
    433 TEST_F(DualStreamTest,
    434        DISABLED_ON_ANDROID(BitExactSyncStereoInputMonoPrimaryWb20Ms)) {
    435   InitializeSender(20, 1, 16000);
    436   Perform(true, 2);
    437 }
    438 
    439 // Stereo input, stereo primary WB 20 ms frame.
    440 TEST_F(DualStreamTest,
    441        DISABLED_ON_ANDROID(BitExactSyncStereoInputStereoPrimaryWb20Ms)) {
    442   InitializeSender(20, 2, 16000);
    443   Perform(true, 2);
    444 }
    445 
    446 // Stereo input, mono primary SWB 20 ms frame.
    447 TEST_F(DualStreamTest,
    448        DISABLED_ON_ANDROID(BitExactSyncStereoInputMonoPrimarySwb20Ms)) {
    449   InitializeSender(20, 1, 32000);
    450   Perform(true, 2);
    451 }
    452 
    453 // Stereo input, stereo primary SWB 20 ms frame.
    454 TEST_F(DualStreamTest,
    455        DISABLED_ON_ANDROID(BitExactSyncStereoInputStereoPrimarySwb20Ms)) {
    456   InitializeSender(20, 2, 32000);
    457   Perform(true, 2);
    458 }
    459 
    460 // Stereo input, mono primary WB 40 ms frame.
    461 TEST_F(DualStreamTest,
    462        DISABLED_ON_ANDROID(BitExactSyncStereoInputMonoPrimaryWb40Ms)) {
    463   InitializeSender(40, 1, 16000);
    464   Perform(true, 2);
    465 }
    466 
    467 // Stereo input, stereo primary WB 40 ms frame.
    468 TEST_F(DualStreamTest,
    469        DISABLED_ON_ANDROID(BitExactSyncStereoInputStereoPrimaryWb40Ms)) {
    470   InitializeSender(40, 2, 16000);
    471   Perform(true, 2);
    472 }
    473 
    474 // Asynchronous test, ACM is fed with data then secondary coder is registered.
    475 // Mono input, mono primary WB 20 ms frame.
    476 TEST_F(DualStreamTest,
    477        DISABLED_ON_ANDROID(BitExactAsyncMonoInputMonoPrimaryWb20Ms)) {
    478   InitializeSender(20, 1, 16000);
    479   Perform(false, 1);
    480 }
    481 
    482 // Mono input, mono primary WB 20 ms frame.
    483 TEST_F(DualStreamTest,
    484        DISABLED_ON_ANDROID(BitExactAsyncMonoInputMonoPrimaryWb40Ms)) {
    485   InitializeSender(40, 1, 16000);
    486   Perform(false, 1);
    487 }
    488 
    489 TEST_F(DualStreamTest, DISABLED_ON_ANDROID(Api)) {
    490   PopulateCodecInstances(20, 1, 16000);
    491   CodecInst my_codec;
    492   ASSERT_EQ(0, acm_dual_stream_->InitializeSender());
    493   ASSERT_EQ(-1, acm_dual_stream_->SecondarySendCodec(&my_codec));
    494 
    495   // Not allowed to register secondary codec if primary is not registered yet.
    496   ASSERT_EQ(-1,
    497       acm_dual_stream_->RegisterSecondarySendCodec(secondary_encoder_));
    498   ASSERT_EQ(-1, acm_dual_stream_->SecondarySendCodec(&my_codec));
    499 
    500   ASSERT_EQ(0, acm_dual_stream_->RegisterSendCodec(primary_encoder_));
    501 
    502   ASSERT_EQ(0, acm_dual_stream_->SetVAD(true, true, VADNormal));
    503 
    504   // Make sure vad is activated.
    505   bool vad_status;
    506   bool dtx_status;
    507   ACMVADMode vad_mode;
    508   EXPECT_EQ(0, acm_dual_stream_->VAD(&vad_status, &dtx_status, &vad_mode));
    509   EXPECT_TRUE(vad_status);
    510   EXPECT_TRUE(dtx_status);
    511   EXPECT_EQ(VADNormal, vad_mode);
    512 
    513   ASSERT_EQ(0,
    514       acm_dual_stream_->RegisterSecondarySendCodec(secondary_encoder_));
    515 
    516   ASSERT_EQ(0, acm_dual_stream_->SecondarySendCodec(&my_codec));
    517   ASSERT_EQ(0, memcmp(&my_codec, &secondary_encoder_, sizeof(my_codec)));
    518 
    519   // Test if VAD get disabled after registering secondary codec.
    520   EXPECT_EQ(0, acm_dual_stream_->VAD(&vad_status, &dtx_status, &vad_mode));
    521   EXPECT_FALSE(vad_status);
    522   EXPECT_FALSE(dtx_status);
    523 
    524   // Activating VAD should fail.
    525   ASSERT_EQ(-1, acm_dual_stream_->SetVAD(true, true, VADNormal));
    526 
    527   // Unregister secondary encoder and it should be possible to activate VAD.
    528   acm_dual_stream_->UnregisterSecondarySendCodec();
    529   // Should fail.
    530   ASSERT_EQ(-1, acm_dual_stream_->SecondarySendCodec(&my_codec));
    531 
    532   ASSERT_EQ(0, acm_dual_stream_->SetVAD(true, true, VADVeryAggr));
    533   // Make sure VAD is activated.
    534   EXPECT_EQ(0, acm_dual_stream_->VAD(&vad_status, &dtx_status, &vad_mode));
    535   EXPECT_TRUE(vad_status);
    536   EXPECT_TRUE(dtx_status);
    537   EXPECT_EQ(VADVeryAggr, vad_mode);
    538 }
    539 
    540 }  // namespace webrtc
    541