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