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