Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <windows.h> | 5 #include <windows.h> |
| 6 #include <mmsystem.h> | 6 #include <mmsystem.h> |
| 7 | 7 |
| 8 #include "base/basictypes.h" | 8 #include "base/basictypes.h" |
| 9 #include "base/command_line.h" | |
| 9 #include "base/environment.h" | 10 #include "base/environment.h" |
| 10 #include "base/file_util.h" | 11 #include "base/file_util.h" |
| 12 #include "media/base/media_switches.h" | |
| 11 #include "base/memory/scoped_ptr.h" | 13 #include "base/memory/scoped_ptr.h" |
| 12 #include "base/message_loop.h" | 14 #include "base/message_loop.h" |
| 13 #include "base/test/test_timeouts.h" | 15 #include "base/test/test_timeouts.h" |
| 14 #include "base/time.h" | 16 #include "base/time.h" |
| 15 #include "base/path_service.h" | 17 #include "base/path_service.h" |
| 16 #include "base/win/scoped_com_initializer.h" | 18 #include "base/win/scoped_com_initializer.h" |
| 17 #include "media/audio/audio_io.h" | 19 #include "media/audio/audio_io.h" |
| 18 #include "media/audio/audio_manager.h" | 20 #include "media/audio/audio_manager.h" |
| 19 #include "media/audio/audio_util.h" | 21 #include "media/audio/audio_util.h" |
| 20 #include "media/audio/win/audio_low_latency_output_win.h" | 22 #include "media/audio/win/audio_low_latency_output_win.h" |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 34 using ::testing::InvokeWithoutArgs; | 36 using ::testing::InvokeWithoutArgs; |
| 35 using ::testing::NotNull; | 37 using ::testing::NotNull; |
| 36 using ::testing::Return; | 38 using ::testing::Return; |
| 37 using base::win::ScopedCOMInitializer; | 39 using base::win::ScopedCOMInitializer; |
| 38 | 40 |
| 39 namespace media { | 41 namespace media { |
| 40 | 42 |
| 41 static const char kSpeechFile_16b_s_48k[] = "speech_16b_stereo_48kHz.raw"; | 43 static const char kSpeechFile_16b_s_48k[] = "speech_16b_stereo_48kHz.raw"; |
| 42 static const char kSpeechFile_16b_s_44k[] = "speech_16b_stereo_44kHz.raw"; | 44 static const char kSpeechFile_16b_s_44k[] = "speech_16b_stereo_44kHz.raw"; |
| 43 static const size_t kFileDurationMs = 20000; | 45 static const size_t kFileDurationMs = 20000; |
| 44 static const size_t kNumFileSegments = 1; | 46 static const size_t kNumFileSegments = 2; |
| 45 | 47 |
| 46 static const size_t kMaxDeltaSamples = 1000; | 48 static const size_t kMaxDeltaSamples = 1000; |
| 47 static const char* kDeltaTimeMsFileName = "delta_times_ms.txt"; | 49 static const char* kDeltaTimeMsFileName = "delta_times_ms.txt"; |
| 48 | 50 |
| 49 MATCHER_P(HasValidDelay, value, "") { | 51 MATCHER_P(HasValidDelay, value, "") { |
| 50 // It is difficult to come up with a perfect test condition for the delay | 52 // It is difficult to come up with a perfect test condition for the delay |
| 51 // estimation. For now, verify that the produced output delay is always | 53 // estimation. For now, verify that the produced output delay is always |
| 52 // larger than the selected buffer size. | 54 // larger than the selected buffer size. |
| 53 return arg.hardware_delay_bytes > value.hardware_delay_bytes; | 55 return arg.hardware_delay_bytes > value.hardware_delay_bytes; |
| 54 } | 56 } |
| 55 | 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, MessageLoop::QuitClosure()); | |
| 62 } | |
| 63 | |
| 56 class MockAudioSourceCallback : public AudioOutputStream::AudioSourceCallback { | 64 class MockAudioSourceCallback : public AudioOutputStream::AudioSourceCallback { |
| 57 public: | 65 public: |
| 58 MOCK_METHOD3(OnMoreData, uint32(uint8* dest, | 66 MOCK_METHOD3(OnMoreData, uint32(uint8* dest, |
| 59 uint32 max_size, | 67 uint32 max_size, |
| 60 AudioBuffersState buffers_state)); | 68 AudioBuffersState buffers_state)); |
| 61 MOCK_METHOD2(OnError, void(AudioOutputStream* stream, int code)); | 69 MOCK_METHOD2(OnError, void(AudioOutputStream* stream, int code)); |
| 62 }; | 70 }; |
| 63 | 71 |
| 64 // This audio source implementation should be used for manual tests only since | 72 // This audio source implementation should be used for manual tests only since |
| 65 // it takes about 20 seconds to play out a file. | 73 // it takes about 20 seconds to play out a file. |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 131 | 139 |
| 132 private: | 140 private: |
| 133 scoped_refptr<DecoderBuffer> file_; | 141 scoped_refptr<DecoderBuffer> file_; |
| 134 scoped_array<int> delta_times_; | 142 scoped_array<int> delta_times_; |
| 135 int pos_; | 143 int pos_; |
| 136 base::Time previous_call_time_; | 144 base::Time previous_call_time_; |
| 137 FILE* text_file_; | 145 FILE* text_file_; |
| 138 size_t elements_to_write_; | 146 size_t elements_to_write_; |
| 139 }; | 147 }; |
| 140 | 148 |
| 149 static bool ExclusiveModeIsEnabled() { | |
| 150 const CommandLine* cmd_line = CommandLine::ForCurrentProcess(); | |
| 151 return (cmd_line->HasSwitch(switches::kEnableExclusiveMode)); | |
| 152 } | |
| 153 | |
| 141 // Convenience method which ensures that we are not running on the build | 154 // Convenience method which ensures that we are not running on the build |
| 142 // bots and that at least one valid output device can be found. We also | 155 // bots and that at least one valid output device can be found. We also |
| 143 // verify that we are not running on XP since the low-latency (WASAPI- | 156 // verify that we are not running on XP since the low-latency (WASAPI- |
| 144 // based) version requires Windows Vista or higher. | 157 // based) version requires Windows Vista or higher. |
| 145 static bool CanRunAudioTests(AudioManager* audio_man) { | 158 static bool CanRunAudioTests(AudioManager* audio_man) { |
| 146 if (!media::IsWASAPISupported()) { | 159 if (!media::IsWASAPISupported()) { |
| 147 LOG(WARNING) << "This tests requires Windows Vista or higher."; | 160 LOG(WARNING) << "This tests requires Windows Vista or higher."; |
| 148 return false; | 161 return false; |
| 149 } | 162 } |
| 150 // TODO(henrika): note that we use Wave today to query the number of | 163 // TODO(henrika): note that we use Wave today to query the number of |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 179 } | 192 } |
| 180 | 193 |
| 181 // Creates AudioOutputStream object using non-default parameters where the | 194 // Creates AudioOutputStream object using non-default parameters where the |
| 182 // frame size is modified. | 195 // frame size is modified. |
| 183 AudioOutputStream* Create(int samples_per_packet) { | 196 AudioOutputStream* Create(int samples_per_packet) { |
| 184 samples_per_packet_ = samples_per_packet; | 197 samples_per_packet_ = samples_per_packet; |
| 185 return CreateOutputStream(); | 198 return CreateOutputStream(); |
| 186 } | 199 } |
| 187 | 200 |
| 188 // Creates AudioOutputStream object using non-default parameters where the | 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 // Creates AudioOutputStream object using non-default parameters where the | |
| 189 // channel layout is modified. | 210 // channel layout is modified. |
| 190 AudioOutputStream* Create(ChannelLayout channel_layout) { | 211 AudioOutputStream* Create(ChannelLayout channel_layout) { |
| 191 channel_layout_ = channel_layout; | 212 channel_layout_ = channel_layout; |
| 192 return CreateOutputStream(); | 213 return CreateOutputStream(); |
| 193 } | 214 } |
| 194 | 215 |
| 195 AudioParameters::Format format() const { return format_; } | 216 AudioParameters::Format format() const { return format_; } |
| 196 int channels() const { return ChannelLayoutToChannelCount(channel_layout_); } | 217 int channels() const { return ChannelLayoutToChannelCount(channel_layout_); } |
| 197 int bits_per_sample() const { return bits_per_sample_; } | 218 int bits_per_sample() const { return bits_per_sample_; } |
| 198 int sample_rate() const { return sample_rate_; } | 219 int sample_rate() const { return sample_rate_; } |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 217 }; | 238 }; |
| 218 | 239 |
| 219 // Convenience method which creates a default AudioOutputStream object. | 240 // Convenience method which creates a default AudioOutputStream object. |
| 220 static AudioOutputStream* CreateDefaultAudioOutputStream( | 241 static AudioOutputStream* CreateDefaultAudioOutputStream( |
| 221 AudioManager* audio_manager) { | 242 AudioManager* audio_manager) { |
| 222 AudioOutputStreamWrapper aosw(audio_manager); | 243 AudioOutputStreamWrapper aosw(audio_manager); |
| 223 AudioOutputStream* aos = aosw.Create(); | 244 AudioOutputStream* aos = aosw.Create(); |
| 224 return aos; | 245 return aos; |
| 225 } | 246 } |
| 226 | 247 |
| 227 static void QuitMessageLoop(base::MessageLoopProxy* proxy) { | |
| 228 proxy->PostTask(FROM_HERE, MessageLoop::QuitClosure()); | |
| 229 } | |
| 230 | |
| 231 // Verify that we can retrieve the current hardware/mixing sample rate | 248 // Verify that we can retrieve the current hardware/mixing sample rate |
| 232 // for all supported device roles. The ERole enumeration defines constants | 249 // for all supported device roles. The ERole enumeration defines constants |
| 233 // that indicate the role that the system/user has assigned to an audio | 250 // that indicate the role that the system/user has assigned to an audio |
| 234 // endpoint device. | 251 // endpoint device. |
| 235 // TODO(henrika): modify this test when we support full device enumeration. | 252 // TODO(henrika): modify this test when we support full device enumeration. |
| 236 TEST(WinAudioOutputTest, WASAPIAudioOutputStreamTestHardwareSampleRate) { | 253 TEST(WinAudioOutputTest, WASAPIAudioOutputStreamTestHardwareSampleRate) { |
| 237 scoped_ptr<AudioManager> audio_manager(AudioManager::Create()); | 254 scoped_ptr<AudioManager> audio_manager(AudioManager::Create()); |
| 238 if (!CanRunAudioTests(audio_manager.get())) | 255 if (!CanRunAudioTests(audio_manager.get())) |
| 239 return; | 256 return; |
| 240 | 257 |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 402 // Derive the expected size in bytes of each packet. | 419 // Derive the expected size in bytes of each packet. |
| 403 uint32 bytes_per_packet = aosw.channels() * aosw.samples_per_packet() * | 420 uint32 bytes_per_packet = aosw.channels() * aosw.samples_per_packet() * |
| 404 (aosw.bits_per_sample() / 8); | 421 (aosw.bits_per_sample() / 8); |
| 405 | 422 |
| 406 // Set up expected minimum delay estimation. | 423 // Set up expected minimum delay estimation. |
| 407 AudioBuffersState state(0, bytes_per_packet); | 424 AudioBuffersState state(0, bytes_per_packet); |
| 408 | 425 |
| 409 // Wait for the first callback and verify its parameters. | 426 // Wait for the first callback and verify its parameters. |
| 410 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_per_packet, | 427 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_per_packet, |
| 411 HasValidDelay(state))) | 428 HasValidDelay(state))) |
| 412 .WillOnce( | 429 .WillOnce(DoAll( |
| 413 DoAll( | 430 QuitLoop(proxy.get()), |
| 414 InvokeWithoutArgs( | 431 Return(bytes_per_packet))); |
| 415 CreateFunctor(&QuitMessageLoop, proxy.get())), | |
| 416 Return(bytes_per_packet))); | |
| 417 | 432 |
| 418 aos->Start(&source); | 433 aos->Start(&source); |
| 419 loop.PostDelayedTask(FROM_HERE, MessageLoop::QuitClosure(), | 434 loop.PostDelayedTask(FROM_HERE, MessageLoop::QuitClosure(), |
| 420 TestTimeouts::action_timeout()); | 435 TestTimeouts::action_timeout()); |
| 421 loop.Run(); | 436 loop.Run(); |
| 422 aos->Stop(); | 437 aos->Stop(); |
| 423 aos->Close(); | 438 aos->Close(); |
| 424 } | 439 } |
| 425 | 440 |
| 426 // Use a fixed packets size (independent of sample rate) and verify | 441 // Use a fixed packets size (independent of sample rate) and verify |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 444 // Derive the expected size in bytes of each packet. | 459 // Derive the expected size in bytes of each packet. |
| 445 uint32 bytes_per_packet = aosw.channels() * aosw.samples_per_packet() * | 460 uint32 bytes_per_packet = aosw.channels() * aosw.samples_per_packet() * |
| 446 (aosw.bits_per_sample() / 8); | 461 (aosw.bits_per_sample() / 8); |
| 447 | 462 |
| 448 // Set up expected minimum delay estimation. | 463 // Set up expected minimum delay estimation. |
| 449 AudioBuffersState state(0, bytes_per_packet); | 464 AudioBuffersState state(0, bytes_per_packet); |
| 450 | 465 |
| 451 // Wait for the first callback and verify its parameters. | 466 // Wait for the first callback and verify its parameters. |
| 452 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_per_packet, | 467 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_per_packet, |
| 453 HasValidDelay(state))) | 468 HasValidDelay(state))) |
| 454 .WillOnce( | 469 .WillOnce(DoAll( |
| 455 DoAll( | 470 QuitLoop(proxy.get()), |
| 456 InvokeWithoutArgs( | 471 Return(bytes_per_packet))); |
| 457 CreateFunctor(&QuitMessageLoop, proxy.get())), | |
| 458 Return(bytes_per_packet))); | |
| 459 | 472 |
| 460 aos->Start(&source); | 473 aos->Start(&source); |
| 461 loop.PostDelayedTask(FROM_HERE, MessageLoop::QuitClosure(), | 474 loop.PostDelayedTask(FROM_HERE, MessageLoop::QuitClosure(), |
| 462 TestTimeouts::action_timeout()); | 475 TestTimeouts::action_timeout()); |
| 463 loop.Run(); | 476 loop.Run(); |
| 464 aos->Stop(); | 477 aos->Stop(); |
| 465 aos->Close(); | 478 aos->Close(); |
| 466 } | 479 } |
| 467 | 480 |
| 468 TEST(WinAudioOutputTest, WASAPIAudioOutputStreamTestMono) { | 481 TEST(WinAudioOutputTest, WASAPIAudioOutputStreamTestMono) { |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 490 } | 503 } |
| 491 // Derive the expected size in bytes of each packet. | 504 // Derive the expected size in bytes of each packet. |
| 492 uint32 bytes_per_packet = aosw.channels() * aosw.samples_per_packet() * | 505 uint32 bytes_per_packet = aosw.channels() * aosw.samples_per_packet() * |
| 493 (aosw.bits_per_sample() / 8); | 506 (aosw.bits_per_sample() / 8); |
| 494 | 507 |
| 495 // Set up expected minimum delay estimation. | 508 // Set up expected minimum delay estimation. |
| 496 AudioBuffersState state(0, bytes_per_packet); | 509 AudioBuffersState state(0, bytes_per_packet); |
| 497 | 510 |
| 498 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_per_packet, | 511 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_per_packet, |
| 499 HasValidDelay(state))) | 512 HasValidDelay(state))) |
| 500 .WillOnce( | 513 .WillOnce(DoAll( |
| 501 DoAll( | 514 QuitLoop(proxy.get()), |
| 502 InvokeWithoutArgs( | 515 Return(bytes_per_packet))); |
| 503 CreateFunctor(&QuitMessageLoop, proxy.get())), | |
| 504 Return(bytes_per_packet))); | |
| 505 | 516 |
| 506 aos->Start(&source); | 517 aos->Start(&source); |
| 507 loop.PostDelayedTask(FROM_HERE, MessageLoop::QuitClosure(), | 518 loop.PostDelayedTask(FROM_HERE, MessageLoop::QuitClosure(), |
| 508 TestTimeouts::action_timeout()); | 519 TestTimeouts::action_timeout()); |
| 509 loop.Run(); | 520 loop.Run(); |
| 510 aos->Stop(); | 521 aos->Stop(); |
| 511 aos->Close(); | 522 aos->Close(); |
| 512 } | 523 } |
| 513 | 524 |
| 514 // This test is intended for manual tests and should only be enabled | 525 // This test is intended for manual tests and should only be enabled |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 555 aos->Start(&file_source); | 566 aos->Start(&file_source); |
| 556 base::PlatformThread::Sleep( | 567 base::PlatformThread::Sleep( |
| 557 base::TimeDelta::FromMilliseconds(kFileDurationMs / kNumFileSegments)); | 568 base::TimeDelta::FromMilliseconds(kFileDurationMs / kNumFileSegments)); |
| 558 aos->Stop(); | 569 aos->Stop(); |
| 559 } | 570 } |
| 560 | 571 |
| 561 LOG(INFO) << ">> File playout has stopped."; | 572 LOG(INFO) << ">> File playout has stopped."; |
| 562 aos->Close(); | 573 aos->Close(); |
| 563 } | 574 } |
| 564 | 575 |
| 576 // Verify that we can open the output stream in exclusive mode using a | |
| 577 // certain set of audio parameters and a sample rate of 48kHz. | |
| 578 // The expected outcomes of each setting in this test has been derived | |
| 579 // manually using log outputs (--v=1). | |
| 580 TEST(WinAudioOutputTest, | |
| 581 WASAPIAudioOutputStreamTestExclusiveModeBufferSizesAt48kHzSampleRate) { | |
|
scherkus (not reviewing)
2012/07/25 23:44:44
considering the tests already contain "WinAudioOut
henrika (OOO until Aug 14)
2012/07/26 08:31:11
Done.
| |
| 582 if (!ExclusiveModeIsEnabled()) | |
| 583 return; | |
| 584 | |
| 585 scoped_ptr<AudioManager> audio_manager(AudioManager::Create()); | |
| 586 if (!CanRunAudioTests(audio_manager.get())) | |
| 587 return; | |
| 588 | |
| 589 AudioOutputStreamWrapper aosw(audio_manager.get()); | |
| 590 | |
| 591 // 10ms @ 48kHz shall work. | |
| 592 // Note that, this is the same size as we can use for shared-mode streaming | |
| 593 // but here the endpoint buffer delay is only 10ms instead of 20ms. | |
| 594 AudioOutputStream* aos = aosw.Create(48000, 480); | |
| 595 EXPECT_TRUE(aos->Open()); | |
| 596 aos->Close(); | |
| 597 | |
| 598 // 5ms @ 48kHz does not work due to misalignment. | |
| 599 // This test will propose an aligned buffer size of 5.3333ms. | |
| 600 // Note that we must call Close() even is Open() fails since Close() also | |
| 601 // deletes the object and we want to create a new object in the next test. | |
| 602 aos = aosw.Create(48000, 240); | |
| 603 EXPECT_FALSE(aos->Open()); | |
| 604 aos->Close(); | |
| 605 | |
| 606 // 5.3333ms @ 48kHz should work (see test above). | |
| 607 aos = aosw.Create(48000, 256); | |
| 608 EXPECT_TRUE(aos->Open()); | |
| 609 aos->Close(); | |
| 610 | |
| 611 // 2.6667ms is smaller than the minimum supported size (=3ms). | |
| 612 aos = aosw.Create(48000, 128); | |
| 613 EXPECT_FALSE(aos->Open()); | |
| 614 aos->Close(); | |
| 615 | |
| 616 // 3ms does not correspond to an aligned buffer size. | |
| 617 // This test will propose an aligned buffer size of 3.3333ms. | |
| 618 aos = aosw.Create(48000, 144); | |
| 619 EXPECT_FALSE(aos->Open()); | |
| 620 aos->Close(); | |
| 621 | |
| 622 // 3.3333ms @ 48kHz <=> smallest possible buffer size we can use. | |
| 623 aos = aosw.Create(48000, 160); | |
| 624 EXPECT_TRUE(aos->Open()); | |
| 625 aos->Close(); | |
| 626 } | |
| 627 | |
| 628 // Verify that we can open the output stream in exclusive mode using a | |
| 629 // certain set of audio parameters and a sample rate of 44.1kHz. | |
| 630 // The expected outcomes of each setting in this test has been derived | |
| 631 // manually using log outputs (--v=1). | |
| 632 TEST(WinAudioOutputTest, | |
| 633 WASAPIAudioOutputStreamTestExclusiveModeBufferSizesAt44kHzSampleRate) { | |
| 634 if (!ExclusiveModeIsEnabled()) | |
| 635 return; | |
| 636 | |
| 637 scoped_ptr<AudioManager> audio_manager(AudioManager::Create()); | |
| 638 if (!CanRunAudioTests(audio_manager.get())) | |
| 639 return; | |
| 640 | |
| 641 AudioOutputStreamWrapper aosw(audio_manager.get()); | |
| 642 | |
| 643 // 10ms @ 44.1kHz does not work due to misalignment. | |
| 644 // This test will propose an aligned buffer size of 10.1587ms. | |
| 645 AudioOutputStream* aos = aosw.Create(44100, 441); | |
| 646 EXPECT_FALSE(aos->Open()); | |
| 647 aos->Close(); | |
| 648 | |
| 649 // 10.1587ms @ 44.1kHz shall work (see test above). | |
| 650 aos = aosw.Create(44100, 448); | |
| 651 EXPECT_TRUE(aos->Open()); | |
| 652 aos->Close(); | |
| 653 | |
| 654 // 5.8050ms @ 44.1 should work. | |
| 655 aos = aosw.Create(44100, 256); | |
| 656 EXPECT_TRUE(aos->Open()); | |
| 657 aos->Close(); | |
| 658 | |
| 659 // 4.9887ms @ 44.1kHz does not work to misalignment. | |
| 660 // This test will propose an aligned buffer size of 5.0794ms. | |
| 661 // Note that we must call Close() even is Open() fails since Close() also | |
| 662 // deletes the object and we want to create a new object in the next test. | |
| 663 aos = aosw.Create(44100, 220); | |
| 664 EXPECT_FALSE(aos->Open()); | |
| 665 aos->Close(); | |
| 666 | |
| 667 // 5.0794ms @ 44.1kHz shall work (see test above). | |
| 668 aos = aosw.Create(44100, 224); | |
| 669 EXPECT_TRUE(aos->Open()); | |
| 670 aos->Close(); | |
| 671 | |
| 672 // 2.9025ms is smaller than the minimum supported size (=3ms). | |
| 673 aos = aosw.Create(44100, 132); | |
| 674 EXPECT_FALSE(aos->Open()); | |
| 675 aos->Close(); | |
| 676 | |
| 677 // 3.01587ms is larger than the minimum size but is not aligned. | |
| 678 // This test will propose an aligned buffer size of 3.6281ms. | |
| 679 aos = aosw.Create(44100, 133); | |
| 680 EXPECT_FALSE(aos->Open()); | |
| 681 aos->Close(); | |
| 682 | |
| 683 // 3.6281ms @ 44.1kHz <=> smallest possible buffer size we can use. | |
| 684 aos = aosw.Create(44100, 160); | |
| 685 EXPECT_TRUE(aos->Open()); | |
| 686 aos->Close(); | |
| 687 } | |
| 688 | |
| 689 // Verify that we can open and start the output stream in exclusive mode at | |
| 690 // the lowest possible delay at 48kHz. | |
| 691 TEST(WinAudioOutputTest, | |
| 692 WASAPIAudioOutputStreamTestExclusiveModeMinBufferSizeAt48kHzSampleRate) { | |
| 693 if (!ExclusiveModeIsEnabled()) | |
| 694 return; | |
| 695 | |
| 696 scoped_ptr<AudioManager> audio_manager(AudioManager::Create()); | |
| 697 if (!CanRunAudioTests(audio_manager.get())) | |
| 698 return; | |
| 699 | |
| 700 MessageLoopForUI loop; | |
| 701 scoped_refptr<base::MessageLoopProxy> proxy(loop.message_loop_proxy()); | |
| 702 | |
| 703 MockAudioSourceCallback source; | |
| 704 | |
| 705 // Create exclusive-mode WASAPI output stream which plays out in stereo | |
| 706 // using the minimum buffer size at 48kHz sample rate. | |
| 707 AudioOutputStreamWrapper aosw(audio_manager.get()); | |
| 708 AudioOutputStream* aos = aosw.Create(48000, 160); | |
| 709 EXPECT_TRUE(aos->Open()); | |
| 710 | |
| 711 // Derive the expected size in bytes of each packet. | |
| 712 uint32 bytes_per_packet = aosw.channels() * aosw.samples_per_packet() * | |
| 713 (aosw.bits_per_sample() / 8); | |
| 714 | |
| 715 // Set up expected minimum delay estimation. | |
| 716 AudioBuffersState state(0, bytes_per_packet); | |
| 717 | |
| 718 // Wait for the first callback and verify its parameters. | |
| 719 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_per_packet, | |
| 720 HasValidDelay(state))) | |
| 721 .WillOnce(DoAll( | |
| 722 QuitLoop(proxy.get()), | |
| 723 Return(bytes_per_packet))); | |
| 724 | |
| 725 aos->Start(&source); | |
| 726 loop.PostDelayedTask(FROM_HERE, MessageLoop::QuitClosure(), | |
| 727 TestTimeouts::action_timeout()); | |
| 728 loop.Run(); | |
| 729 aos->Stop(); | |
| 730 aos->Close(); | |
| 731 } | |
| 732 | |
| 733 // Verify that we can open and start the output stream in exclusive mode at | |
| 734 // the lowest possible delay at 44.1kHz. | |
| 735 TEST(WinAudioOutputTest, | |
| 736 WASAPIAudioOutputStreamTestExclusiveModeMinBufferSizeAt44kHzSampleRate) { | |
| 737 if (!ExclusiveModeIsEnabled()) | |
| 738 return; | |
| 739 | |
| 740 scoped_ptr<AudioManager> audio_manager(AudioManager::Create()); | |
| 741 if (!CanRunAudioTests(audio_manager.get())) | |
| 742 return; | |
| 743 | |
| 744 MessageLoopForUI loop; | |
| 745 scoped_refptr<base::MessageLoopProxy> proxy(loop.message_loop_proxy()); | |
| 746 | |
| 747 MockAudioSourceCallback source; | |
| 748 | |
| 749 // Create exclusive-mode WASAPI output stream which plays out in stereo | |
| 750 // using the minimum buffer size at 48kHz sample rate. | |
| 751 AudioOutputStreamWrapper aosw(audio_manager.get()); | |
| 752 AudioOutputStream* aos = aosw.Create(44100, 160); | |
| 753 EXPECT_TRUE(aos->Open()); | |
| 754 | |
| 755 // Derive the expected size in bytes of each packet. | |
| 756 uint32 bytes_per_packet = aosw.channels() * aosw.samples_per_packet() * | |
| 757 (aosw.bits_per_sample() / 8); | |
| 758 | |
| 759 // Set up expected minimum delay estimation. | |
| 760 AudioBuffersState state(0, bytes_per_packet); | |
| 761 | |
| 762 // Wait for the first callback and verify its parameters. | |
| 763 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_per_packet, | |
| 764 HasValidDelay(state))) | |
| 765 .WillOnce(DoAll( | |
| 766 QuitLoop(proxy.get()), | |
| 767 Return(bytes_per_packet))); | |
| 768 | |
| 769 aos->Start(&source); | |
| 770 loop.PostDelayedTask(FROM_HERE, MessageLoop::QuitClosure(), | |
| 771 TestTimeouts::action_timeout()); | |
| 772 loop.Run(); | |
| 773 aos->Stop(); | |
| 774 aos->Close(); | |
| 775 } | |
| 776 | |
| 565 } // namespace media | 777 } // namespace media |
| OLD | NEW |