1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include <windows.h> 6 #include <mmsystem.h> 7 8 #include "base/basictypes.h" 9 #include "base/environment.h" 10 #include "base/file_util.h" 11 #include "base/memory/scoped_ptr.h" 12 #include "base/message_loop/message_loop.h" 13 #include "base/path_service.h" 14 #include "base/test/test_timeouts.h" 15 #include "base/time/time.h" 16 #include "base/win/scoped_com_initializer.h" 17 #include "media/audio/audio_io.h" 18 #include "media/audio/audio_manager.h" 19 #include "media/audio/mock_audio_source_callback.h" 20 #include "media/audio/win/audio_low_latency_output_win.h" 21 #include "media/audio/win/core_audio_util_win.h" 22 #include "media/base/decoder_buffer.h" 23 #include "media/base/seekable_buffer.h" 24 #include "media/base/test_data_util.h" 25 #include "testing/gmock/include/gmock/gmock.h" 26 #include "testing/gmock_mutant.h" 27 #include "testing/gtest/include/gtest/gtest.h" 28 29 using ::testing::_; 30 using ::testing::AnyNumber; 31 using ::testing::AtLeast; 32 using ::testing::Between; 33 using ::testing::CreateFunctor; 34 using ::testing::DoAll; 35 using ::testing::Gt; 36 using ::testing::InvokeWithoutArgs; 37 using ::testing::NotNull; 38 using ::testing::Return; 39 using base::win::ScopedCOMInitializer; 40 41 namespace media { 42 43 static const char kSpeechFile_16b_s_48k[] = "speech_16b_stereo_48kHz.raw"; 44 static const char kSpeechFile_16b_s_44k[] = "speech_16b_stereo_44kHz.raw"; 45 static const size_t kFileDurationMs = 20000; 46 static const size_t kNumFileSegments = 2; 47 static const int kBitsPerSample = 16; 48 static const size_t kMaxDeltaSamples = 1000; 49 static const char kDeltaTimeMsFileName[] = "delta_times_ms.txt"; 50 51 MATCHER_P(HasValidDelay, value, "") { 52 // It is difficult to come up with a perfect test condition for the delay 53 // estimation. For now, verify that the produced output delay is always 54 // larger than the selected buffer size. 55 return arg.hardware_delay_bytes >= value.hardware_delay_bytes; 56 } 57 58 // Used to terminate a loop from a different thread than the loop belongs to. 59 // |loop| should be a MessageLoopProxy. 60 ACTION_P(QuitLoop, loop) { 61 loop->PostTask(FROM_HERE, base::MessageLoop::QuitClosure()); 62 } 63 64 // This audio source implementation should be used for manual tests only since 65 // it takes about 20 seconds to play out a file. 66 class ReadFromFileAudioSource : public AudioOutputStream::AudioSourceCallback { 67 public: 68 explicit ReadFromFileAudioSource(const std::string& name) 69 : pos_(0), 70 previous_call_time_(base::TimeTicks::Now()), 71 text_file_(NULL), 72 elements_to_write_(0) { 73 // Reads a test file from media/test/data directory. 74 file_ = ReadTestDataFile(name); 75 76 // Creates an array that will store delta times between callbacks. 77 // The content of this array will be written to a text file at 78 // destruction and can then be used for off-line analysis of the exact 79 // timing of callbacks. The text file will be stored in media/test/data. 80 delta_times_.reset(new int[kMaxDeltaSamples]); 81 } 82 83 virtual ~ReadFromFileAudioSource() { 84 // Get complete file path to output file in directory containing 85 // media_unittests.exe. 86 base::FilePath file_name; 87 EXPECT_TRUE(PathService::Get(base::DIR_EXE, &file_name)); 88 file_name = file_name.AppendASCII(kDeltaTimeMsFileName); 89 90 EXPECT_TRUE(!text_file_); 91 text_file_ = base::OpenFile(file_name, "wt"); 92 DLOG_IF(ERROR, !text_file_) << "Failed to open log file."; 93 94 // Write the array which contains delta times to a text file. 95 size_t elements_written = 0; 96 while (elements_written < elements_to_write_) { 97 fprintf(text_file_, "%d\n", delta_times_[elements_written]); 98 ++elements_written; 99 } 100 101 base::CloseFile(text_file_); 102 } 103 104 // AudioOutputStream::AudioSourceCallback implementation. 105 virtual int OnMoreData(AudioBus* audio_bus, 106 AudioBuffersState buffers_state) { 107 // Store time difference between two successive callbacks in an array. 108 // These values will be written to a file in the destructor. 109 const base::TimeTicks now_time = base::TimeTicks::Now(); 110 const int diff = (now_time - previous_call_time_).InMilliseconds(); 111 previous_call_time_ = now_time; 112 if (elements_to_write_ < kMaxDeltaSamples) { 113 delta_times_[elements_to_write_] = diff; 114 ++elements_to_write_; 115 } 116 117 int max_size = 118 audio_bus->frames() * audio_bus->channels() * kBitsPerSample / 8; 119 120 // Use samples read from a data file and fill up the audio buffer 121 // provided to us in the callback. 122 if (pos_ + static_cast<int>(max_size) > file_size()) 123 max_size = file_size() - pos_; 124 int frames = max_size / (audio_bus->channels() * kBitsPerSample / 8); 125 if (max_size) { 126 audio_bus->FromInterleaved( 127 file_->data() + pos_, frames, kBitsPerSample / 8); 128 pos_ += max_size; 129 } 130 return frames; 131 } 132 133 virtual void OnError(AudioOutputStream* stream) {} 134 135 int file_size() { return file_->data_size(); } 136 137 private: 138 scoped_refptr<DecoderBuffer> file_; 139 scoped_ptr<int[]> delta_times_; 140 int pos_; 141 base::TimeTicks previous_call_time_; 142 FILE* text_file_; 143 size_t elements_to_write_; 144 }; 145 146 static bool ExclusiveModeIsEnabled() { 147 return (WASAPIAudioOutputStream::GetShareMode() == 148 AUDCLNT_SHAREMODE_EXCLUSIVE); 149 } 150 151 // Convenience method which ensures that we are not running on the build 152 // bots and that at least one valid output device can be found. We also 153 // verify that we are not running on XP since the low-latency (WASAPI- 154 // based) version requires Windows Vista or higher. 155 static bool CanRunAudioTests(AudioManager* audio_man) { 156 if (!CoreAudioUtil::IsSupported()) { 157 LOG(WARNING) << "This test requires Windows Vista or higher."; 158 return false; 159 } 160 161 // TODO(henrika): note that we use Wave today to query the number of 162 // existing output devices. 163 if (!audio_man->HasAudioOutputDevices()) { 164 LOG(WARNING) << "No output devices detected."; 165 return false; 166 } 167 168 return true; 169 } 170 171 // Convenience method which creates a default AudioOutputStream object but 172 // also allows the user to modify the default settings. 173 class AudioOutputStreamWrapper { 174 public: 175 explicit AudioOutputStreamWrapper(AudioManager* audio_manager) 176 : audio_man_(audio_manager), 177 format_(AudioParameters::AUDIO_PCM_LOW_LATENCY), 178 bits_per_sample_(kBitsPerSample) { 179 AudioParameters preferred_params; 180 EXPECT_TRUE(SUCCEEDED(CoreAudioUtil::GetPreferredAudioParameters( 181 eRender, eConsole, &preferred_params))); 182 channel_layout_ = preferred_params.channel_layout(); 183 sample_rate_ = preferred_params.sample_rate(); 184 samples_per_packet_ = preferred_params.frames_per_buffer(); 185 } 186 187 ~AudioOutputStreamWrapper() {} 188 189 // Creates AudioOutputStream object using default parameters. 190 AudioOutputStream* Create() { 191 return CreateOutputStream(); 192 } 193 194 // Creates AudioOutputStream object using non-default parameters where the 195 // frame size is modified. 196 AudioOutputStream* Create(int samples_per_packet) { 197 samples_per_packet_ = samples_per_packet; 198 return CreateOutputStream(); 199 } 200 201 // Creates AudioOutputStream object using non-default parameters where the 202 // sample rate and frame size are modified. 203 AudioOutputStream* Create(int sample_rate, int samples_per_packet) { 204 sample_rate_ = sample_rate; 205 samples_per_packet_ = samples_per_packet; 206 return CreateOutputStream(); 207 } 208 209 AudioParameters::Format format() const { return format_; } 210 int channels() const { return ChannelLayoutToChannelCount(channel_layout_); } 211 int bits_per_sample() const { return bits_per_sample_; } 212 int sample_rate() const { return sample_rate_; } 213 int samples_per_packet() const { return samples_per_packet_; } 214 215 private: 216 AudioOutputStream* CreateOutputStream() { 217 AudioOutputStream* aos = audio_man_->MakeAudioOutputStream( 218 AudioParameters(format_, channel_layout_, sample_rate_, 219 bits_per_sample_, samples_per_packet_), 220 std::string()); 221 EXPECT_TRUE(aos); 222 return aos; 223 } 224 225 AudioManager* audio_man_; 226 AudioParameters::Format format_; 227 ChannelLayout channel_layout_; 228 int bits_per_sample_; 229 int sample_rate_; 230 int samples_per_packet_; 231 }; 232 233 // Convenience method which creates a default AudioOutputStream object. 234 static AudioOutputStream* CreateDefaultAudioOutputStream( 235 AudioManager* audio_manager) { 236 AudioOutputStreamWrapper aosw(audio_manager); 237 AudioOutputStream* aos = aosw.Create(); 238 return aos; 239 } 240 241 // Verify that we can retrieve the current hardware/mixing sample rate 242 // for the default audio device. 243 // TODO(henrika): modify this test when we support full device enumeration. 244 TEST(WASAPIAudioOutputStreamTest, HardwareSampleRate) { 245 // Skip this test in exclusive mode since the resulting rate is only utilized 246 // for shared mode streams. 247 scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); 248 if (!CanRunAudioTests(audio_manager.get()) || ExclusiveModeIsEnabled()) 249 return; 250 251 // Default device intended for games, system notification sounds, 252 // and voice commands. 253 int fs = static_cast<int>( 254 WASAPIAudioOutputStream::HardwareSampleRate(std::string())); 255 EXPECT_GE(fs, 0); 256 } 257 258 // Test Create(), Close() calling sequence. 259 TEST(WASAPIAudioOutputStreamTest, CreateAndClose) { 260 scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); 261 if (!CanRunAudioTests(audio_manager.get())) 262 return; 263 AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get()); 264 aos->Close(); 265 } 266 267 // Test Open(), Close() calling sequence. 268 TEST(WASAPIAudioOutputStreamTest, OpenAndClose) { 269 scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); 270 if (!CanRunAudioTests(audio_manager.get())) 271 return; 272 AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get()); 273 EXPECT_TRUE(aos->Open()); 274 aos->Close(); 275 } 276 277 // Test Open(), Start(), Close() calling sequence. 278 TEST(WASAPIAudioOutputStreamTest, OpenStartAndClose) { 279 scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); 280 if (!CanRunAudioTests(audio_manager.get())) 281 return; 282 AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get()); 283 EXPECT_TRUE(aos->Open()); 284 MockAudioSourceCallback source; 285 EXPECT_CALL(source, OnError(aos)) 286 .Times(0); 287 aos->Start(&source); 288 aos->Close(); 289 } 290 291 // Test Open(), Start(), Stop(), Close() calling sequence. 292 TEST(WASAPIAudioOutputStreamTest, OpenStartStopAndClose) { 293 scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); 294 if (!CanRunAudioTests(audio_manager.get())) 295 return; 296 AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get()); 297 EXPECT_TRUE(aos->Open()); 298 MockAudioSourceCallback source; 299 EXPECT_CALL(source, OnError(aos)) 300 .Times(0); 301 aos->Start(&source); 302 aos->Stop(); 303 aos->Close(); 304 } 305 306 // Test SetVolume(), GetVolume() 307 TEST(WASAPIAudioOutputStreamTest, Volume) { 308 scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); 309 if (!CanRunAudioTests(audio_manager.get())) 310 return; 311 AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get()); 312 313 // Initial volume should be full volume (1.0). 314 double volume = 0.0; 315 aos->GetVolume(&volume); 316 EXPECT_EQ(1.0, volume); 317 318 // Verify some valid volume settings. 319 aos->SetVolume(0.0); 320 aos->GetVolume(&volume); 321 EXPECT_EQ(0.0, volume); 322 323 aos->SetVolume(0.5); 324 aos->GetVolume(&volume); 325 EXPECT_EQ(0.5, volume); 326 327 aos->SetVolume(1.0); 328 aos->GetVolume(&volume); 329 EXPECT_EQ(1.0, volume); 330 331 // Ensure that invalid volume setting have no effect. 332 aos->SetVolume(1.5); 333 aos->GetVolume(&volume); 334 EXPECT_EQ(1.0, volume); 335 336 aos->SetVolume(-0.5); 337 aos->GetVolume(&volume); 338 EXPECT_EQ(1.0, volume); 339 340 aos->Close(); 341 } 342 343 // Test some additional calling sequences. 344 TEST(WASAPIAudioOutputStreamTest, MiscCallingSequences) { 345 scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); 346 if (!CanRunAudioTests(audio_manager.get())) 347 return; 348 349 AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get()); 350 WASAPIAudioOutputStream* waos = static_cast<WASAPIAudioOutputStream*>(aos); 351 352 // Open(), Open() is a valid calling sequence (second call does nothing). 353 EXPECT_TRUE(aos->Open()); 354 EXPECT_TRUE(aos->Open()); 355 356 MockAudioSourceCallback source; 357 358 // Start(), Start() is a valid calling sequence (second call does nothing). 359 aos->Start(&source); 360 EXPECT_TRUE(waos->started()); 361 aos->Start(&source); 362 EXPECT_TRUE(waos->started()); 363 364 // Stop(), Stop() is a valid calling sequence (second call does nothing). 365 aos->Stop(); 366 EXPECT_FALSE(waos->started()); 367 aos->Stop(); 368 EXPECT_FALSE(waos->started()); 369 370 // Start(), Stop(), Start(), Stop(). 371 aos->Start(&source); 372 EXPECT_TRUE(waos->started()); 373 aos->Stop(); 374 EXPECT_FALSE(waos->started()); 375 aos->Start(&source); 376 EXPECT_TRUE(waos->started()); 377 aos->Stop(); 378 EXPECT_FALSE(waos->started()); 379 380 aos->Close(); 381 } 382 383 // Use preferred packet size and verify that rendering starts. 384 TEST(WASAPIAudioOutputStreamTest, ValidPacketSize) { 385 scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); 386 if (!CanRunAudioTests(audio_manager.get())) 387 return; 388 389 base::MessageLoopForUI loop; 390 MockAudioSourceCallback source; 391 392 // Create default WASAPI output stream which plays out in stereo using 393 // the shared mixing rate. The default buffer size is 10ms. 394 AudioOutputStreamWrapper aosw(audio_manager.get()); 395 AudioOutputStream* aos = aosw.Create(); 396 EXPECT_TRUE(aos->Open()); 397 398 // Derive the expected size in bytes of each packet. 399 uint32 bytes_per_packet = aosw.channels() * aosw.samples_per_packet() * 400 (aosw.bits_per_sample() / 8); 401 402 // Set up expected minimum delay estimation. 403 AudioBuffersState state(0, bytes_per_packet); 404 405 // Wait for the first callback and verify its parameters. 406 EXPECT_CALL(source, OnMoreData(NotNull(), HasValidDelay(state))) 407 .WillOnce(DoAll( 408 QuitLoop(loop.message_loop_proxy()), 409 Return(aosw.samples_per_packet()))); 410 411 aos->Start(&source); 412 loop.PostDelayedTask(FROM_HERE, base::MessageLoop::QuitClosure(), 413 TestTimeouts::action_timeout()); 414 loop.Run(); 415 aos->Stop(); 416 aos->Close(); 417 } 418 419 // This test is intended for manual tests and should only be enabled 420 // when it is required to play out data from a local PCM file. 421 // By default, GTest will print out YOU HAVE 1 DISABLED TEST. 422 // To include disabled tests in test execution, just invoke the test program 423 // with --gtest_also_run_disabled_tests or set the GTEST_ALSO_RUN_DISABLED_TESTS 424 // environment variable to a value greater than 0. 425 // The test files are approximately 20 seconds long. 426 TEST(WASAPIAudioOutputStreamTest, DISABLED_ReadFromStereoFile) { 427 scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); 428 if (!CanRunAudioTests(audio_manager.get())) 429 return; 430 431 AudioOutputStreamWrapper aosw(audio_manager.get()); 432 AudioOutputStream* aos = aosw.Create(); 433 EXPECT_TRUE(aos->Open()); 434 435 std::string file_name; 436 if (aosw.sample_rate() == 48000) { 437 file_name = kSpeechFile_16b_s_48k; 438 } else if (aosw.sample_rate() == 44100) { 439 file_name = kSpeechFile_16b_s_44k; 440 } else if (aosw.sample_rate() == 96000) { 441 // Use 48kHz file at 96kHz as well. Will sound like Donald Duck. 442 file_name = kSpeechFile_16b_s_48k; 443 } else { 444 FAIL() << "This test supports 44.1, 48kHz and 96kHz only."; 445 return; 446 } 447 ReadFromFileAudioSource file_source(file_name); 448 449 VLOG(0) << "File name : " << file_name.c_str(); 450 VLOG(0) << "Sample rate : " << aosw.sample_rate(); 451 VLOG(0) << "Bits per sample: " << aosw.bits_per_sample(); 452 VLOG(0) << "#channels : " << aosw.channels(); 453 VLOG(0) << "File size : " << file_source.file_size(); 454 VLOG(0) << "#file segments : " << kNumFileSegments; 455 VLOG(0) << ">> Listen to the stereo file while playing..."; 456 457 for (int i = 0; i < kNumFileSegments; i++) { 458 // Each segment will start with a short (~20ms) block of zeros, hence 459 // some short glitches might be heard in this test if kNumFileSegments 460 // is larger than one. The exact length of the silence period depends on 461 // the selected sample rate. 462 aos->Start(&file_source); 463 base::PlatformThread::Sleep( 464 base::TimeDelta::FromMilliseconds(kFileDurationMs / kNumFileSegments)); 465 aos->Stop(); 466 } 467 468 VLOG(0) << ">> Stereo file playout has stopped."; 469 aos->Close(); 470 } 471 472 // Verify that we can open the output stream in exclusive mode using a 473 // certain set of audio parameters and a sample rate of 48kHz. 474 // The expected outcomes of each setting in this test has been derived 475 // manually using log outputs (--v=1). 476 TEST(WASAPIAudioOutputStreamTest, ExclusiveModeBufferSizesAt48kHz) { 477 if (!ExclusiveModeIsEnabled()) 478 return; 479 480 scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); 481 if (!CanRunAudioTests(audio_manager.get())) 482 return; 483 484 AudioOutputStreamWrapper aosw(audio_manager.get()); 485 486 // 10ms @ 48kHz shall work. 487 // Note that, this is the same size as we can use for shared-mode streaming 488 // but here the endpoint buffer delay is only 10ms instead of 20ms. 489 AudioOutputStream* aos = aosw.Create(48000, 480); 490 EXPECT_TRUE(aos->Open()); 491 aos->Close(); 492 493 // 5ms @ 48kHz does not work due to misalignment. 494 // This test will propose an aligned buffer size of 5.3333ms. 495 // Note that we must call Close() even is Open() fails since Close() also 496 // deletes the object and we want to create a new object in the next test. 497 aos = aosw.Create(48000, 240); 498 EXPECT_FALSE(aos->Open()); 499 aos->Close(); 500 501 // 5.3333ms @ 48kHz should work (see test above). 502 aos = aosw.Create(48000, 256); 503 EXPECT_TRUE(aos->Open()); 504 aos->Close(); 505 506 // 2.6667ms is smaller than the minimum supported size (=3ms). 507 aos = aosw.Create(48000, 128); 508 EXPECT_FALSE(aos->Open()); 509 aos->Close(); 510 511 // 3ms does not correspond to an aligned buffer size. 512 // This test will propose an aligned buffer size of 3.3333ms. 513 aos = aosw.Create(48000, 144); 514 EXPECT_FALSE(aos->Open()); 515 aos->Close(); 516 517 // 3.3333ms @ 48kHz <=> smallest possible buffer size we can use. 518 aos = aosw.Create(48000, 160); 519 EXPECT_TRUE(aos->Open()); 520 aos->Close(); 521 } 522 523 // Verify that we can open the output stream in exclusive mode using a 524 // certain set of audio parameters and a sample rate of 44.1kHz. 525 // The expected outcomes of each setting in this test has been derived 526 // manually using log outputs (--v=1). 527 TEST(WASAPIAudioOutputStreamTest, ExclusiveModeBufferSizesAt44kHz) { 528 if (!ExclusiveModeIsEnabled()) 529 return; 530 531 scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); 532 if (!CanRunAudioTests(audio_manager.get())) 533 return; 534 535 AudioOutputStreamWrapper aosw(audio_manager.get()); 536 537 // 10ms @ 44.1kHz does not work due to misalignment. 538 // This test will propose an aligned buffer size of 10.1587ms. 539 AudioOutputStream* aos = aosw.Create(44100, 441); 540 EXPECT_FALSE(aos->Open()); 541 aos->Close(); 542 543 // 10.1587ms @ 44.1kHz shall work (see test above). 544 aos = aosw.Create(44100, 448); 545 EXPECT_TRUE(aos->Open()); 546 aos->Close(); 547 548 // 5.8050ms @ 44.1 should work. 549 aos = aosw.Create(44100, 256); 550 EXPECT_TRUE(aos->Open()); 551 aos->Close(); 552 553 // 4.9887ms @ 44.1kHz does not work to misalignment. 554 // This test will propose an aligned buffer size of 5.0794ms. 555 // Note that we must call Close() even is Open() fails since Close() also 556 // deletes the object and we want to create a new object in the next test. 557 aos = aosw.Create(44100, 220); 558 EXPECT_FALSE(aos->Open()); 559 aos->Close(); 560 561 // 5.0794ms @ 44.1kHz shall work (see test above). 562 aos = aosw.Create(44100, 224); 563 EXPECT_TRUE(aos->Open()); 564 aos->Close(); 565 566 // 2.9025ms is smaller than the minimum supported size (=3ms). 567 aos = aosw.Create(44100, 132); 568 EXPECT_FALSE(aos->Open()); 569 aos->Close(); 570 571 // 3.01587ms is larger than the minimum size but is not aligned. 572 // This test will propose an aligned buffer size of 3.6281ms. 573 aos = aosw.Create(44100, 133); 574 EXPECT_FALSE(aos->Open()); 575 aos->Close(); 576 577 // 3.6281ms @ 44.1kHz <=> smallest possible buffer size we can use. 578 aos = aosw.Create(44100, 160); 579 EXPECT_TRUE(aos->Open()); 580 aos->Close(); 581 } 582 583 // Verify that we can open and start the output stream in exclusive mode at 584 // the lowest possible delay at 48kHz. 585 TEST(WASAPIAudioOutputStreamTest, ExclusiveModeMinBufferSizeAt48kHz) { 586 if (!ExclusiveModeIsEnabled()) 587 return; 588 589 scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); 590 if (!CanRunAudioTests(audio_manager.get())) 591 return; 592 593 base::MessageLoopForUI loop; 594 MockAudioSourceCallback source; 595 596 // Create exclusive-mode WASAPI output stream which plays out in stereo 597 // using the minimum buffer size at 48kHz sample rate. 598 AudioOutputStreamWrapper aosw(audio_manager.get()); 599 AudioOutputStream* aos = aosw.Create(48000, 160); 600 EXPECT_TRUE(aos->Open()); 601 602 // Derive the expected size in bytes of each packet. 603 uint32 bytes_per_packet = aosw.channels() * aosw.samples_per_packet() * 604 (aosw.bits_per_sample() / 8); 605 606 // Set up expected minimum delay estimation. 607 AudioBuffersState state(0, bytes_per_packet); 608 609 // Wait for the first callback and verify its parameters. 610 EXPECT_CALL(source, OnMoreData(NotNull(), HasValidDelay(state))) 611 .WillOnce(DoAll( 612 QuitLoop(loop.message_loop_proxy()), 613 Return(aosw.samples_per_packet()))) 614 .WillRepeatedly(Return(aosw.samples_per_packet())); 615 616 aos->Start(&source); 617 loop.PostDelayedTask(FROM_HERE, base::MessageLoop::QuitClosure(), 618 TestTimeouts::action_timeout()); 619 loop.Run(); 620 aos->Stop(); 621 aos->Close(); 622 } 623 624 // Verify that we can open and start the output stream in exclusive mode at 625 // the lowest possible delay at 44.1kHz. 626 TEST(WASAPIAudioOutputStreamTest, ExclusiveModeMinBufferSizeAt44kHz) { 627 if (!ExclusiveModeIsEnabled()) 628 return; 629 630 scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); 631 if (!CanRunAudioTests(audio_manager.get())) 632 return; 633 634 base::MessageLoopForUI loop; 635 MockAudioSourceCallback source; 636 637 // Create exclusive-mode WASAPI output stream which plays out in stereo 638 // using the minimum buffer size at 44.1kHz sample rate. 639 AudioOutputStreamWrapper aosw(audio_manager.get()); 640 AudioOutputStream* aos = aosw.Create(44100, 160); 641 EXPECT_TRUE(aos->Open()); 642 643 // Derive the expected size in bytes of each packet. 644 uint32 bytes_per_packet = aosw.channels() * aosw.samples_per_packet() * 645 (aosw.bits_per_sample() / 8); 646 647 // Set up expected minimum delay estimation. 648 AudioBuffersState state(0, bytes_per_packet); 649 650 // Wait for the first callback and verify its parameters. 651 EXPECT_CALL(source, OnMoreData(NotNull(), HasValidDelay(state))) 652 .WillOnce(DoAll( 653 QuitLoop(loop.message_loop_proxy()), 654 Return(aosw.samples_per_packet()))) 655 .WillRepeatedly(Return(aosw.samples_per_packet())); 656 657 aos->Start(&source); 658 loop.PostDelayedTask(FROM_HERE, base::MessageLoop::QuitClosure(), 659 TestTimeouts::action_timeout()); 660 loop.Run(); 661 aos->Stop(); 662 aos->Close(); 663 } 664 665 } // namespace media 666