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/TestStereo.h"
12
13 #include <assert.h>
14
15 #include <string>
16
17 #include "testing/gtest/include/gtest/gtest.h"
18 #include "webrtc/common_types.h"
19 #include "webrtc/engine_configurations.h"
20 #include "webrtc/modules/audio_coding/include/audio_coding_module_typedefs.h"
21 #include "webrtc/modules/audio_coding/test/utility.h"
22 #include "webrtc/system_wrappers/include/trace.h"
23 #include "webrtc/test/testsupport/fileutils.h"
24
25 namespace webrtc {
26
27 // Class for simulating packet handling
TestPackStereo()28 TestPackStereo::TestPackStereo()
29 : receiver_acm_(NULL),
30 seq_no_(0),
31 timestamp_diff_(0),
32 last_in_timestamp_(0),
33 total_bytes_(0),
34 payload_size_(0),
35 codec_mode_(kNotSet),
36 lost_packet_(false) {
37 }
38
~TestPackStereo()39 TestPackStereo::~TestPackStereo() {
40 }
41
RegisterReceiverACM(AudioCodingModule * acm)42 void TestPackStereo::RegisterReceiverACM(AudioCodingModule* acm) {
43 receiver_acm_ = acm;
44 return;
45 }
46
SendData(const FrameType frame_type,const uint8_t payload_type,const uint32_t timestamp,const uint8_t * payload_data,const size_t payload_size,const RTPFragmentationHeader * fragmentation)47 int32_t TestPackStereo::SendData(const FrameType frame_type,
48 const uint8_t payload_type,
49 const uint32_t timestamp,
50 const uint8_t* payload_data,
51 const size_t payload_size,
52 const RTPFragmentationHeader* fragmentation) {
53 WebRtcRTPHeader rtp_info;
54 int32_t status = 0;
55
56 rtp_info.header.markerBit = false;
57 rtp_info.header.ssrc = 0;
58 rtp_info.header.sequenceNumber = seq_no_++;
59 rtp_info.header.payloadType = payload_type;
60 rtp_info.header.timestamp = timestamp;
61 if (frame_type == kEmptyFrame) {
62 // Skip this frame
63 return 0;
64 }
65
66 if (lost_packet_ == false) {
67 if (frame_type != kAudioFrameCN) {
68 rtp_info.type.Audio.isCNG = false;
69 rtp_info.type.Audio.channel = static_cast<int>(codec_mode_);
70 } else {
71 rtp_info.type.Audio.isCNG = true;
72 rtp_info.type.Audio.channel = static_cast<int>(kMono);
73 }
74 status = receiver_acm_->IncomingPacket(payload_data, payload_size,
75 rtp_info);
76
77 if (frame_type != kAudioFrameCN) {
78 payload_size_ = static_cast<int>(payload_size);
79 } else {
80 payload_size_ = -1;
81 }
82
83 timestamp_diff_ = timestamp - last_in_timestamp_;
84 last_in_timestamp_ = timestamp;
85 total_bytes_ += payload_size;
86 }
87 return status;
88 }
89
payload_size()90 uint16_t TestPackStereo::payload_size() {
91 return static_cast<uint16_t>(payload_size_);
92 }
93
timestamp_diff()94 uint32_t TestPackStereo::timestamp_diff() {
95 return timestamp_diff_;
96 }
97
reset_payload_size()98 void TestPackStereo::reset_payload_size() {
99 payload_size_ = 0;
100 }
101
set_codec_mode(enum StereoMonoMode mode)102 void TestPackStereo::set_codec_mode(enum StereoMonoMode mode) {
103 codec_mode_ = mode;
104 }
105
set_lost_packet(bool lost)106 void TestPackStereo::set_lost_packet(bool lost) {
107 lost_packet_ = lost;
108 }
109
TestStereo(int test_mode)110 TestStereo::TestStereo(int test_mode)
111 : acm_a_(AudioCodingModule::Create(0)),
112 acm_b_(AudioCodingModule::Create(1)),
113 channel_a2b_(NULL),
114 test_cntr_(0),
115 pack_size_samp_(0),
116 pack_size_bytes_(0),
117 counter_(0)
118 #ifdef WEBRTC_CODEC_G722
119 , g722_pltype_(0)
120 #endif
121 , l16_8khz_pltype_(-1)
122 , l16_16khz_pltype_(-1)
123 , l16_32khz_pltype_(-1)
124 #ifdef PCMA_AND_PCMU
125 , pcma_pltype_(-1)
126 , pcmu_pltype_(-1)
127 #endif
128 #ifdef WEBRTC_CODEC_OPUS
129 , opus_pltype_(-1)
130 #endif
131 {
132 // test_mode = 0 for silent test (auto test)
133 test_mode_ = test_mode;
134 }
135
~TestStereo()136 TestStereo::~TestStereo() {
137 if (channel_a2b_ != NULL) {
138 delete channel_a2b_;
139 channel_a2b_ = NULL;
140 }
141 }
142
Perform()143 void TestStereo::Perform() {
144 uint16_t frequency_hz;
145 int audio_channels;
146 int codec_channels;
147 bool dtx;
148 bool vad;
149 ACMVADMode vad_mode;
150
151 // Open both mono and stereo test files in 32 kHz.
152 const std::string file_name_stereo = webrtc::test::ResourcePath(
153 "audio_coding/teststereo32kHz", "pcm");
154 const std::string file_name_mono = webrtc::test::ResourcePath(
155 "audio_coding/testfile32kHz", "pcm");
156 frequency_hz = 32000;
157 in_file_stereo_ = new PCMFile();
158 in_file_mono_ = new PCMFile();
159 in_file_stereo_->Open(file_name_stereo, frequency_hz, "rb");
160 in_file_stereo_->ReadStereo(true);
161 in_file_mono_->Open(file_name_mono, frequency_hz, "rb");
162 in_file_mono_->ReadStereo(false);
163
164 // Create and initialize two ACMs, one for each side of a one-to-one call.
165 ASSERT_TRUE((acm_a_.get() != NULL) && (acm_b_.get() != NULL));
166 EXPECT_EQ(0, acm_a_->InitializeReceiver());
167 EXPECT_EQ(0, acm_b_->InitializeReceiver());
168
169 // Register all available codes as receiving codecs.
170 uint8_t num_encoders = acm_a_->NumberOfCodecs();
171 CodecInst my_codec_param;
172 for (uint8_t n = 0; n < num_encoders; n++) {
173 EXPECT_EQ(0, acm_b_->Codec(n, &my_codec_param));
174 EXPECT_EQ(0, acm_b_->RegisterReceiveCodec(my_codec_param));
175 }
176
177 // Test that unregister all receive codecs works.
178 for (uint8_t n = 0; n < num_encoders; n++) {
179 EXPECT_EQ(0, acm_b_->Codec(n, &my_codec_param));
180 EXPECT_EQ(0, acm_b_->UnregisterReceiveCodec(my_codec_param.pltype));
181 }
182
183 // Register all available codes as receiving codecs once more.
184 for (uint8_t n = 0; n < num_encoders; n++) {
185 EXPECT_EQ(0, acm_b_->Codec(n, &my_codec_param));
186 EXPECT_EQ(0, acm_b_->RegisterReceiveCodec(my_codec_param));
187 }
188
189 // Create and connect the channel.
190 channel_a2b_ = new TestPackStereo;
191 EXPECT_EQ(0, acm_a_->RegisterTransportCallback(channel_a2b_));
192 channel_a2b_->RegisterReceiverACM(acm_b_.get());
193
194 // Start with setting VAD/DTX, before we know we will send stereo.
195 // Continue with setting a stereo codec as send codec and verify that
196 // VAD/DTX gets turned off.
197 EXPECT_EQ(0, acm_a_->SetVAD(true, true, VADNormal));
198 EXPECT_EQ(0, acm_a_->VAD(&dtx, &vad, &vad_mode));
199 EXPECT_TRUE(dtx);
200 EXPECT_TRUE(vad);
201 char codec_pcma_temp[] = "PCMA";
202 RegisterSendCodec('A', codec_pcma_temp, 8000, 64000, 80, 2, pcma_pltype_);
203 EXPECT_EQ(0, acm_a_->VAD(&dtx, &vad, &vad_mode));
204 EXPECT_FALSE(dtx);
205 EXPECT_FALSE(vad);
206 if (test_mode_ != 0) {
207 printf("\n");
208 }
209
210 //
211 // Test Stereo-To-Stereo for all codecs.
212 //
213 audio_channels = 2;
214 codec_channels = 2;
215
216 // All codecs are tested for all allowed sampling frequencies, rates and
217 // packet sizes.
218 #ifdef WEBRTC_CODEC_G722
219 if (test_mode_ != 0) {
220 printf("===========================================================\n");
221 printf("Test number: %d\n", test_cntr_ + 1);
222 printf("Test type: Stereo-to-stereo\n");
223 }
224 channel_a2b_->set_codec_mode(kStereo);
225 test_cntr_++;
226 OpenOutFile(test_cntr_);
227 char codec_g722[] = "G722";
228 RegisterSendCodec('A', codec_g722, 16000, 64000, 160, codec_channels,
229 g722_pltype_);
230 Run(channel_a2b_, audio_channels, codec_channels);
231 RegisterSendCodec('A', codec_g722, 16000, 64000, 320, codec_channels,
232 g722_pltype_);
233 Run(channel_a2b_, audio_channels, codec_channels);
234 RegisterSendCodec('A', codec_g722, 16000, 64000, 480, codec_channels,
235 g722_pltype_);
236 Run(channel_a2b_, audio_channels, codec_channels);
237 RegisterSendCodec('A', codec_g722, 16000, 64000, 640, codec_channels,
238 g722_pltype_);
239 Run(channel_a2b_, audio_channels, codec_channels);
240 RegisterSendCodec('A', codec_g722, 16000, 64000, 800, codec_channels,
241 g722_pltype_);
242 Run(channel_a2b_, audio_channels, codec_channels);
243 RegisterSendCodec('A', codec_g722, 16000, 64000, 960, codec_channels,
244 g722_pltype_);
245 Run(channel_a2b_, audio_channels, codec_channels);
246 out_file_.Close();
247 #endif
248 if (test_mode_ != 0) {
249 printf("===========================================================\n");
250 printf("Test number: %d\n", test_cntr_ + 1);
251 printf("Test type: Stereo-to-stereo\n");
252 }
253 channel_a2b_->set_codec_mode(kStereo);
254 test_cntr_++;
255 OpenOutFile(test_cntr_);
256 char codec_l16[] = "L16";
257 RegisterSendCodec('A', codec_l16, 8000, 128000, 80, codec_channels,
258 l16_8khz_pltype_);
259 Run(channel_a2b_, audio_channels, codec_channels);
260 RegisterSendCodec('A', codec_l16, 8000, 128000, 160, codec_channels,
261 l16_8khz_pltype_);
262 Run(channel_a2b_, audio_channels, codec_channels);
263 RegisterSendCodec('A', codec_l16, 8000, 128000, 240, codec_channels,
264 l16_8khz_pltype_);
265 Run(channel_a2b_, audio_channels, codec_channels);
266 RegisterSendCodec('A', codec_l16, 8000, 128000, 320, codec_channels,
267 l16_8khz_pltype_);
268 Run(channel_a2b_, audio_channels, codec_channels);
269 out_file_.Close();
270
271 if (test_mode_ != 0) {
272 printf("===========================================================\n");
273 printf("Test number: %d\n", test_cntr_ + 1);
274 printf("Test type: Stereo-to-stereo\n");
275 }
276 test_cntr_++;
277 OpenOutFile(test_cntr_);
278 RegisterSendCodec('A', codec_l16, 16000, 256000, 160, codec_channels,
279 l16_16khz_pltype_);
280 Run(channel_a2b_, audio_channels, codec_channels);
281 RegisterSendCodec('A', codec_l16, 16000, 256000, 320, codec_channels,
282 l16_16khz_pltype_);
283 Run(channel_a2b_, audio_channels, codec_channels);
284 RegisterSendCodec('A', codec_l16, 16000, 256000, 480, codec_channels,
285 l16_16khz_pltype_);
286 Run(channel_a2b_, audio_channels, codec_channels);
287 RegisterSendCodec('A', codec_l16, 16000, 256000, 640, codec_channels,
288 l16_16khz_pltype_);
289 Run(channel_a2b_, audio_channels, codec_channels);
290 out_file_.Close();
291
292 if (test_mode_ != 0) {
293 printf("===========================================================\n");
294 printf("Test number: %d\n", test_cntr_ + 1);
295 printf("Test type: Stereo-to-stereo\n");
296 }
297 test_cntr_++;
298 OpenOutFile(test_cntr_);
299 RegisterSendCodec('A', codec_l16, 32000, 512000, 320, codec_channels,
300 l16_32khz_pltype_);
301 Run(channel_a2b_, audio_channels, codec_channels);
302 RegisterSendCodec('A', codec_l16, 32000, 512000, 640, codec_channels,
303 l16_32khz_pltype_);
304 Run(channel_a2b_, audio_channels, codec_channels);
305 out_file_.Close();
306 #ifdef PCMA_AND_PCMU
307 if (test_mode_ != 0) {
308 printf("===========================================================\n");
309 printf("Test number: %d\n", test_cntr_ + 1);
310 printf("Test type: Stereo-to-stereo\n");
311 }
312 channel_a2b_->set_codec_mode(kStereo);
313 audio_channels = 2;
314 codec_channels = 2;
315 test_cntr_++;
316 OpenOutFile(test_cntr_);
317 char codec_pcma[] = "PCMA";
318 RegisterSendCodec('A', codec_pcma, 8000, 64000, 80, codec_channels,
319 pcma_pltype_);
320 Run(channel_a2b_, audio_channels, codec_channels);
321 RegisterSendCodec('A', codec_pcma, 8000, 64000, 160, codec_channels,
322 pcma_pltype_);
323 Run(channel_a2b_, audio_channels, codec_channels);
324 RegisterSendCodec('A', codec_pcma, 8000, 64000, 240, codec_channels,
325 pcma_pltype_);
326 Run(channel_a2b_, audio_channels, codec_channels);
327 RegisterSendCodec('A', codec_pcma, 8000, 64000, 320, codec_channels,
328 pcma_pltype_);
329 Run(channel_a2b_, audio_channels, codec_channels);
330 RegisterSendCodec('A', codec_pcma, 8000, 64000, 400, codec_channels,
331 pcma_pltype_);
332 Run(channel_a2b_, audio_channels, codec_channels);
333 RegisterSendCodec('A', codec_pcma, 8000, 64000, 480, codec_channels,
334 pcma_pltype_);
335 Run(channel_a2b_, audio_channels, codec_channels);
336
337 // Test that VAD/DTX cannot be turned on while sending stereo.
338 EXPECT_EQ(-1, acm_a_->SetVAD(true, true, VADNormal));
339 EXPECT_EQ(0, acm_a_->VAD(&dtx, &vad, &vad_mode));
340 EXPECT_FALSE(dtx);
341 EXPECT_FALSE(vad);
342 EXPECT_EQ(0, acm_a_->SetVAD(false, false, VADNormal));
343 EXPECT_EQ(0, acm_a_->VAD(&dtx, &vad, &vad_mode));
344 EXPECT_FALSE(dtx);
345 EXPECT_FALSE(vad);
346
347 out_file_.Close();
348 if (test_mode_ != 0) {
349 printf("===========================================================\n");
350 printf("Test number: %d\n", test_cntr_ + 1);
351 printf("Test type: Stereo-to-stereo\n");
352 }
353 test_cntr_++;
354 OpenOutFile(test_cntr_);
355 char codec_pcmu[] = "PCMU";
356 RegisterSendCodec('A', codec_pcmu, 8000, 64000, 80, codec_channels,
357 pcmu_pltype_);
358 Run(channel_a2b_, audio_channels, codec_channels);
359 RegisterSendCodec('A', codec_pcmu, 8000, 64000, 160, codec_channels,
360 pcmu_pltype_);
361 Run(channel_a2b_, audio_channels, codec_channels);
362 RegisterSendCodec('A', codec_pcmu, 8000, 64000, 240, codec_channels,
363 pcmu_pltype_);
364 Run(channel_a2b_, audio_channels, codec_channels);
365 RegisterSendCodec('A', codec_pcmu, 8000, 64000, 320, codec_channels,
366 pcmu_pltype_);
367 Run(channel_a2b_, audio_channels, codec_channels);
368 RegisterSendCodec('A', codec_pcmu, 8000, 64000, 400, codec_channels,
369 pcmu_pltype_);
370 Run(channel_a2b_, audio_channels, codec_channels);
371 RegisterSendCodec('A', codec_pcmu, 8000, 64000, 480, codec_channels,
372 pcmu_pltype_);
373 Run(channel_a2b_, audio_channels, codec_channels);
374 out_file_.Close();
375 #endif
376 #ifdef WEBRTC_CODEC_OPUS
377 if (test_mode_ != 0) {
378 printf("===========================================================\n");
379 printf("Test number: %d\n", test_cntr_ + 1);
380 printf("Test type: Stereo-to-stereo\n");
381 }
382 channel_a2b_->set_codec_mode(kStereo);
383 audio_channels = 2;
384 codec_channels = 2;
385 test_cntr_++;
386 OpenOutFile(test_cntr_);
387
388 char codec_opus[] = "opus";
389 // Run Opus with 10 ms frame size.
390 RegisterSendCodec('A', codec_opus, 48000, 64000, 480, codec_channels,
391 opus_pltype_);
392 Run(channel_a2b_, audio_channels, codec_channels);
393 // Run Opus with 20 ms frame size.
394 RegisterSendCodec('A', codec_opus, 48000, 64000, 480*2, codec_channels,
395 opus_pltype_);
396 Run(channel_a2b_, audio_channels, codec_channels);
397 // Run Opus with 40 ms frame size.
398 RegisterSendCodec('A', codec_opus, 48000, 64000, 480*4, codec_channels,
399 opus_pltype_);
400 Run(channel_a2b_, audio_channels, codec_channels);
401 // Run Opus with 60 ms frame size.
402 RegisterSendCodec('A', codec_opus, 48000, 64000, 480*6, codec_channels,
403 opus_pltype_);
404 Run(channel_a2b_, audio_channels, codec_channels);
405 // Run Opus with 20 ms frame size and different bitrates.
406 RegisterSendCodec('A', codec_opus, 48000, 40000, 960, codec_channels,
407 opus_pltype_);
408 Run(channel_a2b_, audio_channels, codec_channels);
409 RegisterSendCodec('A', codec_opus, 48000, 510000, 960, codec_channels,
410 opus_pltype_);
411 Run(channel_a2b_, audio_channels, codec_channels);
412 out_file_.Close();
413 #endif
414 //
415 // Test Mono-To-Stereo for all codecs.
416 //
417 audio_channels = 1;
418 codec_channels = 2;
419
420 #ifdef WEBRTC_CODEC_G722
421 if (test_mode_ != 0) {
422 printf("===============================================================\n");
423 printf("Test number: %d\n", test_cntr_ + 1);
424 printf("Test type: Mono-to-stereo\n");
425 }
426 test_cntr_++;
427 channel_a2b_->set_codec_mode(kStereo);
428 OpenOutFile(test_cntr_);
429 RegisterSendCodec('A', codec_g722, 16000, 64000, 160, codec_channels,
430 g722_pltype_);
431 Run(channel_a2b_, audio_channels, codec_channels);
432 out_file_.Close();
433 #endif
434 if (test_mode_ != 0) {
435 printf("===============================================================\n");
436 printf("Test number: %d\n", test_cntr_ + 1);
437 printf("Test type: Mono-to-stereo\n");
438 }
439 test_cntr_++;
440 channel_a2b_->set_codec_mode(kStereo);
441 OpenOutFile(test_cntr_);
442 RegisterSendCodec('A', codec_l16, 8000, 128000, 80, codec_channels,
443 l16_8khz_pltype_);
444 Run(channel_a2b_, audio_channels, codec_channels);
445 out_file_.Close();
446 if (test_mode_ != 0) {
447 printf("===============================================================\n");
448 printf("Test number: %d\n", test_cntr_ + 1);
449 printf("Test type: Mono-to-stereo\n");
450 }
451 test_cntr_++;
452 OpenOutFile(test_cntr_);
453 RegisterSendCodec('A', codec_l16, 16000, 256000, 160, codec_channels,
454 l16_16khz_pltype_);
455 Run(channel_a2b_, audio_channels, codec_channels);
456 out_file_.Close();
457 if (test_mode_ != 0) {
458 printf("===============================================================\n");
459 printf("Test number: %d\n", test_cntr_ + 1);
460 printf("Test type: Mono-to-stereo\n");
461 }
462 test_cntr_++;
463 OpenOutFile(test_cntr_);
464 RegisterSendCodec('A', codec_l16, 32000, 512000, 320, codec_channels,
465 l16_32khz_pltype_);
466 Run(channel_a2b_, audio_channels, codec_channels);
467 out_file_.Close();
468 #ifdef PCMA_AND_PCMU
469 if (test_mode_ != 0) {
470 printf("===============================================================\n");
471 printf("Test number: %d\n", test_cntr_ + 1);
472 printf("Test type: Mono-to-stereo\n");
473 }
474 test_cntr_++;
475 channel_a2b_->set_codec_mode(kStereo);
476 OpenOutFile(test_cntr_);
477 RegisterSendCodec('A', codec_pcmu, 8000, 64000, 80, codec_channels,
478 pcmu_pltype_);
479 Run(channel_a2b_, audio_channels, codec_channels);
480 RegisterSendCodec('A', codec_pcma, 8000, 64000, 80, codec_channels,
481 pcma_pltype_);
482 Run(channel_a2b_, audio_channels, codec_channels);
483 out_file_.Close();
484 #endif
485 #ifdef WEBRTC_CODEC_OPUS
486 if (test_mode_ != 0) {
487 printf("===============================================================\n");
488 printf("Test number: %d\n", test_cntr_ + 1);
489 printf("Test type: Mono-to-stereo\n");
490 }
491
492 // Keep encode and decode in stereo.
493 test_cntr_++;
494 channel_a2b_->set_codec_mode(kStereo);
495 OpenOutFile(test_cntr_);
496 RegisterSendCodec('A', codec_opus, 48000, 64000, 960, codec_channels,
497 opus_pltype_);
498 Run(channel_a2b_, audio_channels, codec_channels);
499
500 // Encode in mono, decode in stereo mode.
501 RegisterSendCodec('A', codec_opus, 48000, 64000, 960, 1, opus_pltype_);
502 Run(channel_a2b_, audio_channels, codec_channels);
503 out_file_.Close();
504 #endif
505
506 //
507 // Test Stereo-To-Mono for all codecs.
508 //
509 audio_channels = 2;
510 codec_channels = 1;
511 channel_a2b_->set_codec_mode(kMono);
512
513 #ifdef WEBRTC_CODEC_G722
514 // Run stereo audio and mono codec.
515 if (test_mode_ != 0) {
516 printf("===============================================================\n");
517 printf("Test number: %d\n", test_cntr_ + 1);
518 printf("Test type: Stereo-to-mono\n");
519 }
520 test_cntr_++;
521 OpenOutFile(test_cntr_);
522 RegisterSendCodec('A', codec_g722, 16000, 64000, 160, codec_channels,
523 g722_pltype_);
524
525 // Make sure it is possible to set VAD/CNG, now that we are sending mono
526 // again.
527 EXPECT_EQ(0, acm_a_->SetVAD(true, true, VADNormal));
528 EXPECT_EQ(0, acm_a_->VAD(&dtx, &vad, &vad_mode));
529 EXPECT_TRUE(dtx);
530 EXPECT_TRUE(vad);
531 EXPECT_EQ(0, acm_a_->SetVAD(false, false, VADNormal));
532 Run(channel_a2b_, audio_channels, codec_channels);
533 out_file_.Close();
534 #endif
535 if (test_mode_ != 0) {
536 printf("===============================================================\n");
537 printf("Test number: %d\n", test_cntr_ + 1);
538 printf("Test type: Stereo-to-mono\n");
539 }
540 test_cntr_++;
541 OpenOutFile(test_cntr_);
542 RegisterSendCodec('A', codec_l16, 8000, 128000, 80, codec_channels,
543 l16_8khz_pltype_);
544 Run(channel_a2b_, audio_channels, codec_channels);
545 out_file_.Close();
546 if (test_mode_ != 0) {
547 printf("===============================================================\n");
548 printf("Test number: %d\n", test_cntr_ + 1);
549 printf("Test type: Stereo-to-mono\n");
550 }
551 test_cntr_++;
552 OpenOutFile(test_cntr_);
553 RegisterSendCodec('A', codec_l16, 16000, 256000, 160, codec_channels,
554 l16_16khz_pltype_);
555 Run(channel_a2b_, audio_channels, codec_channels);
556 out_file_.Close();
557 if (test_mode_ != 0) {
558 printf("==============================================================\n");
559 printf("Test number: %d\n", test_cntr_ + 1);
560 printf("Test type: Stereo-to-mono\n");
561 }
562 test_cntr_++;
563 OpenOutFile(test_cntr_);
564 RegisterSendCodec('A', codec_l16, 32000, 512000, 320, codec_channels,
565 l16_32khz_pltype_);
566 Run(channel_a2b_, audio_channels, codec_channels);
567 out_file_.Close();
568 #ifdef PCMA_AND_PCMU
569 if (test_mode_ != 0) {
570 printf("===============================================================\n");
571 printf("Test number: %d\n", test_cntr_ + 1);
572 printf("Test type: Stereo-to-mono\n");
573 }
574 test_cntr_++;
575 OpenOutFile(test_cntr_);
576 RegisterSendCodec('A', codec_pcmu, 8000, 64000, 80, codec_channels,
577 pcmu_pltype_);
578 Run(channel_a2b_, audio_channels, codec_channels);
579 RegisterSendCodec('A', codec_pcma, 8000, 64000, 80, codec_channels,
580 pcma_pltype_);
581 Run(channel_a2b_, audio_channels, codec_channels);
582 out_file_.Close();
583 #endif
584 #ifdef WEBRTC_CODEC_OPUS
585 if (test_mode_ != 0) {
586 printf("===============================================================\n");
587 printf("Test number: %d\n", test_cntr_ + 1);
588 printf("Test type: Stereo-to-mono\n");
589 }
590 test_cntr_++;
591 OpenOutFile(test_cntr_);
592 // Encode and decode in mono.
593 RegisterSendCodec('A', codec_opus, 48000, 32000, 960, codec_channels,
594 opus_pltype_);
595 CodecInst opus_codec_param;
596 for (uint8_t n = 0; n < num_encoders; n++) {
597 EXPECT_EQ(0, acm_b_->Codec(n, &opus_codec_param));
598 if (!strcmp(opus_codec_param.plname, "opus")) {
599 opus_codec_param.channels = 1;
600 EXPECT_EQ(0, acm_b_->RegisterReceiveCodec(opus_codec_param));
601 break;
602 }
603 }
604 Run(channel_a2b_, audio_channels, codec_channels);
605
606 // Encode in stereo, decode in mono.
607 RegisterSendCodec('A', codec_opus, 48000, 32000, 960, 2, opus_pltype_);
608 Run(channel_a2b_, audio_channels, codec_channels);
609
610 out_file_.Close();
611
612 // Test switching between decoding mono and stereo for Opus.
613
614 // Decode in mono.
615 test_cntr_++;
616 OpenOutFile(test_cntr_);
617 if (test_mode_ != 0) {
618 // Print out codec and settings
619 printf("Test number: %d\nCodec: Opus Freq: 48000 Rate :32000 PackSize: 960"
620 " Decode: mono\n", test_cntr_);
621 }
622 Run(channel_a2b_, audio_channels, codec_channels);
623 out_file_.Close();
624 // Decode in stereo.
625 test_cntr_++;
626 OpenOutFile(test_cntr_);
627 if (test_mode_ != 0) {
628 // Print out codec and settings
629 printf("Test number: %d\nCodec: Opus Freq: 48000 Rate :32000 PackSize: 960"
630 " Decode: stereo\n", test_cntr_);
631 }
632 opus_codec_param.channels = 2;
633 EXPECT_EQ(0, acm_b_->RegisterReceiveCodec(opus_codec_param));
634 Run(channel_a2b_, audio_channels, 2);
635 out_file_.Close();
636 // Decode in mono.
637 test_cntr_++;
638 OpenOutFile(test_cntr_);
639 if (test_mode_ != 0) {
640 // Print out codec and settings
641 printf("Test number: %d\nCodec: Opus Freq: 48000 Rate :32000 PackSize: 960"
642 " Decode: mono\n", test_cntr_);
643 }
644 opus_codec_param.channels = 1;
645 EXPECT_EQ(0, acm_b_->RegisterReceiveCodec(opus_codec_param));
646 Run(channel_a2b_, audio_channels, codec_channels);
647 out_file_.Close();
648
649 #endif
650
651 // Print out which codecs were tested, and which were not, in the run.
652 if (test_mode_ != 0) {
653 printf("\nThe following codecs was INCLUDED in the test:\n");
654 #ifdef WEBRTC_CODEC_G722
655 printf(" G.722\n");
656 #endif
657 printf(" PCM16\n");
658 printf(" G.711\n");
659 #ifdef WEBRTC_CODEC_OPUS
660 printf(" Opus\n");
661 #endif
662 printf("\nTo complete the test, listen to the %d number of output "
663 "files.\n",
664 test_cntr_);
665 }
666
667 // Delete the file pointers.
668 delete in_file_stereo_;
669 delete in_file_mono_;
670 }
671
672 // Register Codec to use in the test
673 //
674 // Input: side - which ACM to use, 'A' or 'B'
675 // codec_name - name to use when register the codec
676 // sampling_freq_hz - sampling frequency in Herz
677 // rate - bitrate in bytes
678 // pack_size - packet size in samples
679 // channels - number of channels; 1 for mono, 2 for stereo
680 // payload_type - payload type for the codec
RegisterSendCodec(char side,char * codec_name,int32_t sampling_freq_hz,int rate,int pack_size,int channels,int payload_type)681 void TestStereo::RegisterSendCodec(char side, char* codec_name,
682 int32_t sampling_freq_hz, int rate,
683 int pack_size, int channels,
684 int payload_type) {
685 if (test_mode_ != 0) {
686 // Print out codec and settings
687 printf("Codec: %s Freq: %d Rate: %d PackSize: %d\n", codec_name,
688 sampling_freq_hz, rate, pack_size);
689 }
690
691 // Store packet size in samples, used to validate the received packet
692 pack_size_samp_ = pack_size;
693
694 // Store the expected packet size in bytes, used to validate the received
695 // packet. Add 0.875 to always round up to a whole byte.
696 pack_size_bytes_ = (uint16_t)(static_cast<float>(pack_size * rate) /
697 static_cast<float>(sampling_freq_hz * 8) +
698 0.875);
699
700 // Set pointer to the ACM where to register the codec
701 AudioCodingModule* my_acm = NULL;
702 switch (side) {
703 case 'A': {
704 my_acm = acm_a_.get();
705 break;
706 }
707 case 'B': {
708 my_acm = acm_b_.get();
709 break;
710 }
711 default:
712 break;
713 }
714 ASSERT_TRUE(my_acm != NULL);
715
716 CodecInst my_codec_param;
717 // Get all codec parameters before registering
718 EXPECT_GT(AudioCodingModule::Codec(codec_name, &my_codec_param,
719 sampling_freq_hz, channels), -1);
720 my_codec_param.rate = rate;
721 my_codec_param.pacsize = pack_size;
722 EXPECT_EQ(0, my_acm->RegisterSendCodec(my_codec_param));
723
724 send_codec_name_ = codec_name;
725 }
726
Run(TestPackStereo * channel,int in_channels,int out_channels,int percent_loss)727 void TestStereo::Run(TestPackStereo* channel, int in_channels, int out_channels,
728 int percent_loss) {
729 AudioFrame audio_frame;
730
731 int32_t out_freq_hz_b = out_file_.SamplingFrequency();
732 uint16_t rec_size;
733 uint32_t time_stamp_diff;
734 channel->reset_payload_size();
735 int error_count = 0;
736 int variable_bytes = 0;
737 int variable_packets = 0;
738 // Set test length to 500 ms (50 blocks of 10 ms each).
739 in_file_mono_->SetNum10MsBlocksToRead(50);
740 in_file_stereo_->SetNum10MsBlocksToRead(50);
741 // Fast-forward 1 second (100 blocks) since the files start with silence.
742 in_file_stereo_->FastForward(100);
743 in_file_mono_->FastForward(100);
744
745 while (1) {
746 // Simulate packet loss by setting |packet_loss_| to "true" in
747 // |percent_loss| percent of the loops.
748 if (percent_loss > 0) {
749 if (counter_ == floor((100 / percent_loss) + 0.5)) {
750 counter_ = 0;
751 channel->set_lost_packet(true);
752 } else {
753 channel->set_lost_packet(false);
754 }
755 counter_++;
756 }
757
758 // Add 10 msec to ACM
759 if (in_channels == 1) {
760 if (in_file_mono_->EndOfFile()) {
761 break;
762 }
763 in_file_mono_->Read10MsData(audio_frame);
764 } else {
765 if (in_file_stereo_->EndOfFile()) {
766 break;
767 }
768 in_file_stereo_->Read10MsData(audio_frame);
769 }
770 EXPECT_GE(acm_a_->Add10MsData(audio_frame), 0);
771
772 // Verify that the received packet size matches the settings.
773 rec_size = channel->payload_size();
774 if ((0 < rec_size) & (rec_size < 65535)) {
775 if (strcmp(send_codec_name_, "opus") == 0) {
776 // Opus is a variable rate codec, hence calculate the average packet
777 // size, and later make sure the average is in the right range.
778 variable_bytes += rec_size;
779 variable_packets++;
780 } else {
781 // For fixed rate codecs, check that packet size is correct.
782 if ((rec_size != pack_size_bytes_ * out_channels)
783 && (pack_size_bytes_ < 65535)) {
784 error_count++;
785 }
786 }
787 // Verify that the timestamp is updated with expected length
788 time_stamp_diff = channel->timestamp_diff();
789 if ((counter_ > 10) && (time_stamp_diff != pack_size_samp_)) {
790 error_count++;
791 }
792 }
793
794 // Run received side of ACM
795 EXPECT_EQ(0, acm_b_->PlayoutData10Ms(out_freq_hz_b, &audio_frame));
796
797 // Write output speech to file
798 out_file_.Write10MsData(
799 audio_frame.data_,
800 audio_frame.samples_per_channel_ * audio_frame.num_channels_);
801 }
802
803 EXPECT_EQ(0, error_count);
804
805 // Check that packet size is in the right range for variable rate codecs,
806 // such as Opus.
807 if (variable_packets > 0) {
808 variable_bytes /= variable_packets;
809 EXPECT_NEAR(variable_bytes, pack_size_bytes_, 18);
810 }
811
812 if (in_file_mono_->EndOfFile()) {
813 in_file_mono_->Rewind();
814 }
815 if (in_file_stereo_->EndOfFile()) {
816 in_file_stereo_->Rewind();
817 }
818 // Reset in case we ended with a lost packet
819 channel->set_lost_packet(false);
820 }
821
OpenOutFile(int16_t test_number)822 void TestStereo::OpenOutFile(int16_t test_number) {
823 std::string file_name;
824 std::stringstream file_stream;
825 file_stream << webrtc::test::OutputPath() << "teststereo_out_" << test_number
826 << ".pcm";
827 file_name = file_stream.str();
828 out_file_.Open(file_name, 32000, "wb");
829 }
830
DisplaySendReceiveCodec()831 void TestStereo::DisplaySendReceiveCodec() {
832 auto send_codec = acm_a_->SendCodec();
833 if (test_mode_ != 0) {
834 ASSERT_TRUE(send_codec);
835 printf("%s -> ", send_codec->plname);
836 }
837 CodecInst receive_codec;
838 acm_b_->ReceiveCodec(&receive_codec);
839 if (test_mode_ != 0) {
840 printf("%s\n", receive_codec.plname);
841 }
842 }
843
844 } // namespace webrtc
845