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 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 39 TestPackStereo::~TestPackStereo() { 40 } 41 42 void TestPackStereo::RegisterReceiverACM(AudioCodingModule* acm) { 43 receiver_acm_ = acm; 44 return; 45 } 46 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 90 uint16_t TestPackStereo::payload_size() { 91 return static_cast<uint16_t>(payload_size_); 92 } 93 94 uint32_t TestPackStereo::timestamp_diff() { 95 return timestamp_diff_; 96 } 97 98 void TestPackStereo::reset_payload_size() { 99 payload_size_ = 0; 100 } 101 102 void TestPackStereo::set_codec_mode(enum StereoMonoMode mode) { 103 codec_mode_ = mode; 104 } 105 106 void TestPackStereo::set_lost_packet(bool lost) { 107 lost_packet_ = lost; 108 } 109 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 136 TestStereo::~TestStereo() { 137 if (channel_a2b_ != NULL) { 138 delete channel_a2b_; 139 channel_a2b_ = NULL; 140 } 141 } 142 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 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 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 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 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