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 |