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