• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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