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/environment.h" | 9 #include "base/environment.h" |
10 #include "base/file_util.h" | 10 #include "base/file_util.h" |
(...skipping 10 matching lines...) Expand all Loading... | |
21 #include "media/audio/win/core_audio_util_win.h" | 21 #include "media/audio/win/core_audio_util_win.h" |
22 #include "media/base/decoder_buffer.h" | 22 #include "media/base/decoder_buffer.h" |
23 #include "media/base/seekable_buffer.h" | 23 #include "media/base/seekable_buffer.h" |
24 #include "media/base/test_data_util.h" | 24 #include "media/base/test_data_util.h" |
25 #include "testing/gmock_mutant.h" | 25 #include "testing/gmock_mutant.h" |
26 #include "testing/gmock/include/gmock/gmock.h" | 26 #include "testing/gmock/include/gmock/gmock.h" |
27 #include "testing/gtest/include/gtest/gtest.h" | 27 #include "testing/gtest/include/gtest/gtest.h" |
28 | 28 |
29 using ::testing::_; | 29 using ::testing::_; |
30 using ::testing::AnyNumber; | 30 using ::testing::AnyNumber; |
31 using ::testing::AtLeast; | |
31 using ::testing::Between; | 32 using ::testing::Between; |
32 using ::testing::CreateFunctor; | 33 using ::testing::CreateFunctor; |
33 using ::testing::DoAll; | 34 using ::testing::DoAll; |
34 using ::testing::Gt; | 35 using ::testing::Gt; |
35 using ::testing::InvokeWithoutArgs; | 36 using ::testing::InvokeWithoutArgs; |
36 using ::testing::NotNull; | 37 using ::testing::NotNull; |
37 using ::testing::Return; | 38 using ::testing::Return; |
38 using base::win::ScopedCOMInitializer; | 39 using base::win::ScopedCOMInitializer; |
39 | 40 |
40 namespace media { | 41 namespace media { |
41 | 42 |
42 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"; |
43 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"; |
44 static const size_t kFileDurationMs = 20000; | 45 static const size_t kFileDurationMs = 20000; |
45 static const size_t kNumFileSegments = 2; | 46 static const size_t kNumFileSegments = 2; |
46 static const int kBitsPerSample = 16; | 47 static const int kBitsPerSample = 16; |
47 static const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_STEREO; | |
48 static const size_t kMaxDeltaSamples = 1000; | 48 static const size_t kMaxDeltaSamples = 1000; |
49 static const char* kDeltaTimeMsFileName = "delta_times_ms.txt"; | 49 static const char* kDeltaTimeMsFileName = "delta_times_ms.txt"; |
50 | 50 |
51 MATCHER_P(HasValidDelay, value, "") { | 51 MATCHER_P(HasValidDelay, value, "") { |
52 // 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 |
53 // estimation. For now, verify that the produced output delay is always | 53 // estimation. For now, verify that the produced output delay is always |
54 // larger than the selected buffer size. | 54 // larger than the selected buffer size. |
55 return arg.hardware_delay_bytes > value.hardware_delay_bytes; | 55 return arg.hardware_delay_bytes >= value.hardware_delay_bytes; |
56 } | 56 } |
57 | 57 |
58 // Used to terminate a loop from a different thread than the loop belongs to. | 58 // Used to terminate a loop from a different thread than the loop belongs to. |
59 // |loop| should be a MessageLoopProxy. | 59 // |loop| should be a MessageLoopProxy. |
60 ACTION_P(QuitLoop, loop) { | 60 ACTION_P(QuitLoop, loop) { |
61 loop->PostTask(FROM_HERE, MessageLoop::QuitClosure()); | 61 loop->PostTask(FROM_HERE, MessageLoop::QuitClosure()); |
62 } | 62 } |
63 | 63 |
64 class MockAudioSourceCallback : public AudioOutputStream::AudioSourceCallback { | 64 class MockAudioSourceCallback : public AudioOutputStream::AudioSourceCallback { |
65 public: | 65 public: |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
174 return false; | 174 return false; |
175 } | 175 } |
176 | 176 |
177 // TODO(henrika): note that we use Wave today to query the number of | 177 // TODO(henrika): note that we use Wave today to query the number of |
178 // existing output devices. | 178 // existing output devices. |
179 if (!audio_man->HasAudioOutputDevices()) { | 179 if (!audio_man->HasAudioOutputDevices()) { |
180 LOG(WARNING) << "No output devices detected."; | 180 LOG(WARNING) << "No output devices detected."; |
181 return false; | 181 return false; |
182 } | 182 } |
183 | 183 |
184 if (WASAPIAudioOutputStream::HardwareChannelLayout() != kChannelLayout) { | |
185 LOG(WARNING) << "This test requires stereo audio output."; | |
186 return false; | |
187 } | |
188 | |
189 return true; | 184 return true; |
190 } | 185 } |
191 | 186 |
192 // Convenience method which creates a default AudioOutputStream object but | 187 // Convenience method which creates a default AudioOutputStream object but |
193 // also allows the user to modify the default settings. | 188 // also allows the user to modify the default settings. |
194 class AudioOutputStreamWrapper { | 189 class AudioOutputStreamWrapper { |
195 public: | 190 public: |
196 explicit AudioOutputStreamWrapper(AudioManager* audio_manager) | 191 explicit AudioOutputStreamWrapper(AudioManager* audio_manager) |
197 : com_init_(ScopedCOMInitializer::kMTA), | 192 : audio_man_(audio_manager), |
198 audio_man_(audio_manager), | |
199 format_(AudioParameters::AUDIO_PCM_LOW_LATENCY), | 193 format_(AudioParameters::AUDIO_PCM_LOW_LATENCY), |
200 channel_layout_(kChannelLayout), | |
201 bits_per_sample_(kBitsPerSample) { | 194 bits_per_sample_(kBitsPerSample) { |
202 // Use native/mixing sample rate and 10ms frame size as default. | 195 AudioParameters preferred_params; |
203 sample_rate_ = static_cast<int>( | 196 EXPECT_TRUE(SUCCEEDED(CoreAudioUtil::GetPreferredAudioParameters( |
204 WASAPIAudioOutputStream::HardwareSampleRate(eConsole)); | 197 eRender, eConsole, &preferred_params))); |
205 samples_per_packet_ = sample_rate_ / 100; | 198 channel_layout_ = preferred_params.channel_layout(); |
206 DCHECK(sample_rate_); | 199 sample_rate_ = preferred_params.sample_rate(); |
200 samples_per_packet_ = preferred_params.frames_per_buffer(); | |
207 } | 201 } |
208 | 202 |
209 ~AudioOutputStreamWrapper() {} | 203 ~AudioOutputStreamWrapper() {} |
210 | 204 |
211 // Creates AudioOutputStream object using default parameters. | 205 // Creates AudioOutputStream object using default parameters. |
212 AudioOutputStream* Create() { | 206 AudioOutputStream* Create() { |
213 return CreateOutputStream(); | 207 return CreateOutputStream(); |
214 } | 208 } |
215 | 209 |
216 // Creates AudioOutputStream object using non-default parameters where the | 210 // Creates AudioOutputStream object using non-default parameters where the |
(...skipping 19 matching lines...) Expand all Loading... | |
236 | 230 |
237 private: | 231 private: |
238 AudioOutputStream* CreateOutputStream() { | 232 AudioOutputStream* CreateOutputStream() { |
239 AudioOutputStream* aos = audio_man_->MakeAudioOutputStream( | 233 AudioOutputStream* aos = audio_man_->MakeAudioOutputStream( |
240 AudioParameters(format_, channel_layout_, sample_rate_, | 234 AudioParameters(format_, channel_layout_, sample_rate_, |
241 bits_per_sample_, samples_per_packet_)); | 235 bits_per_sample_, samples_per_packet_)); |
242 EXPECT_TRUE(aos); | 236 EXPECT_TRUE(aos); |
243 return aos; | 237 return aos; |
244 } | 238 } |
245 | 239 |
246 ScopedCOMInitializer com_init_; | |
tommi (sloooow) - chröme
2013/01/31 13:42:08
where is COM now initialized?
henrika (OOO until Aug 14)
2013/01/31 14:29:38
AudioManagerBase::AudioManagerBase() does that for
| |
247 AudioManager* audio_man_; | 240 AudioManager* audio_man_; |
248 AudioParameters::Format format_; | 241 AudioParameters::Format format_; |
249 ChannelLayout channel_layout_; | 242 ChannelLayout channel_layout_; |
250 int bits_per_sample_; | 243 int bits_per_sample_; |
251 int sample_rate_; | 244 int sample_rate_; |
252 int samples_per_packet_; | 245 int samples_per_packet_; |
253 }; | 246 }; |
254 | 247 |
255 // Convenience method which creates a default AudioOutputStream object. | 248 // Convenience method which creates a default AudioOutputStream object. |
256 static AudioOutputStream* CreateDefaultAudioOutputStream( | 249 static AudioOutputStream* CreateDefaultAudioOutputStream( |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
432 aos->Stop(); | 425 aos->Stop(); |
433 EXPECT_FALSE(waos->started()); | 426 EXPECT_FALSE(waos->started()); |
434 aos->Start(&source); | 427 aos->Start(&source); |
435 EXPECT_TRUE(waos->started()); | 428 EXPECT_TRUE(waos->started()); |
436 aos->Stop(); | 429 aos->Stop(); |
437 EXPECT_FALSE(waos->started()); | 430 EXPECT_FALSE(waos->started()); |
438 | 431 |
439 aos->Close(); | 432 aos->Close(); |
440 } | 433 } |
441 | 434 |
442 // Use default packet size (10ms) and verify that rendering starts. | 435 // Use preferred packet size and verify that rendering starts. |
443 TEST(WASAPIAudioOutputStreamTest, PacketSizeInMilliseconds) { | 436 TEST(WASAPIAudioOutputStreamTest, ValidPacketSize) { |
444 scoped_ptr<AudioManager> audio_manager(AudioManager::Create()); | 437 scoped_ptr<AudioManager> audio_manager(AudioManager::Create()); |
445 if (!CanRunAudioTests(audio_manager.get())) | 438 if (!CanRunAudioTests(audio_manager.get())) |
446 return; | 439 return; |
447 | 440 |
448 MessageLoopForUI loop; | 441 MessageLoopForUI loop; |
449 MockAudioSourceCallback source; | 442 MockAudioSourceCallback source; |
450 | 443 |
451 // Create default WASAPI output stream which plays out in stereo using | 444 // Create default WASAPI output stream which plays out in stereo using |
452 // the shared mixing rate. The default buffer size is 10ms. | 445 // the shared mixing rate. The default buffer size is 10ms. |
453 AudioOutputStreamWrapper aosw(audio_manager.get()); | 446 AudioOutputStreamWrapper aosw(audio_manager.get()); |
(...skipping 14 matching lines...) Expand all Loading... | |
468 Return(aosw.samples_per_packet()))); | 461 Return(aosw.samples_per_packet()))); |
469 | 462 |
470 aos->Start(&source); | 463 aos->Start(&source); |
471 loop.PostDelayedTask(FROM_HERE, MessageLoop::QuitClosure(), | 464 loop.PostDelayedTask(FROM_HERE, MessageLoop::QuitClosure(), |
472 TestTimeouts::action_timeout()); | 465 TestTimeouts::action_timeout()); |
473 loop.Run(); | 466 loop.Run(); |
474 aos->Stop(); | 467 aos->Stop(); |
475 aos->Close(); | 468 aos->Close(); |
476 } | 469 } |
477 | 470 |
478 // Use a fixed packets size (independent of sample rate) and verify | 471 // Use a non-preferred packet size and verify that Open() fails. |
479 // that rendering starts. | 472 TEST(WASAPIAudioOutputStreamTest, InvalidPacketSize) { |
480 TEST(WASAPIAudioOutputStreamTest, PacketSizeInSamples) { | |
481 scoped_ptr<AudioManager> audio_manager(AudioManager::Create()); | 473 scoped_ptr<AudioManager> audio_manager(AudioManager::Create()); |
482 if (!CanRunAudioTests(audio_manager.get())) | 474 if (!CanRunAudioTests(audio_manager.get())) |
483 return; | 475 return; |
484 | 476 |
485 MessageLoopForUI loop; | 477 if (ExclusiveModeIsEnabled()) |
486 MockAudioSourceCallback source; | 478 return; |
487 | 479 |
488 // Create default WASAPI output stream which reads data in stereo using | 480 AudioParameters preferred_params; |
489 // the native mixing rate and channel count. The buffer size is set to | 481 EXPECT_TRUE(SUCCEEDED(CoreAudioUtil::GetPreferredAudioParameters( |
490 // 1024 samples. | 482 eRender, eConsole, &preferred_params))); |
483 int too_large_packet_size = 2 * preferred_params.frames_per_buffer(); | |
484 | |
491 AudioOutputStreamWrapper aosw(audio_manager.get()); | 485 AudioOutputStreamWrapper aosw(audio_manager.get()); |
492 AudioOutputStream* aos = aosw.Create(1024); | 486 AudioOutputStream* aos = aosw.Create(too_large_packet_size); |
493 EXPECT_TRUE(aos->Open()); | 487 EXPECT_FALSE(aos->Open()); |
494 | 488 |
495 // Derive the expected size in bytes of each packet. | |
496 uint32 bytes_per_packet = aosw.channels() * aosw.samples_per_packet() * | |
497 (aosw.bits_per_sample() / 8); | |
498 | |
499 // Set up expected minimum delay estimation. | |
500 AudioBuffersState state(0, bytes_per_packet); | |
501 | |
502 // Ensure that callbacks start correctly. | |
503 EXPECT_CALL(source, OnMoreData(NotNull(), HasValidDelay(state))) | |
504 .WillOnce(DoAll( | |
505 QuitLoop(loop.message_loop_proxy()), | |
506 Return(aosw.samples_per_packet()))) | |
507 .WillRepeatedly(Return(aosw.samples_per_packet())); | |
508 | |
509 aos->Start(&source); | |
510 loop.PostDelayedTask(FROM_HERE, MessageLoop::QuitClosure(), | |
511 TestTimeouts::action_timeout()); | |
512 loop.Run(); | |
513 aos->Stop(); | |
514 aos->Close(); | 489 aos->Close(); |
515 } | 490 } |
516 | 491 |
517 // This test is intended for manual tests and should only be enabled | 492 // This test is intended for manual tests and should only be enabled |
518 // when it is required to play out data from a local PCM file. | 493 // when it is required to play out data from a local PCM file. |
519 // By default, GTest will print out YOU HAVE 1 DISABLED TEST. | 494 // By default, GTest will print out YOU HAVE 1 DISABLED TEST. |
520 // To include disabled tests in test execution, just invoke the test program | 495 // To include disabled tests in test execution, just invoke the test program |
521 // with --gtest_also_run_disabled_tests or set the GTEST_ALSO_RUN_DISABLED_TESTS | 496 // with --gtest_also_run_disabled_tests or set the GTEST_ALSO_RUN_DISABLED_TESTS |
522 // environment variable to a value greater than 0. | 497 // environment variable to a value greater than 0. |
523 // The test files are approximately 20 seconds long. | 498 // The test files are approximately 20 seconds long. |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
697 AudioOutputStream* aos = aosw.Create(48000, 160); | 672 AudioOutputStream* aos = aosw.Create(48000, 160); |
698 EXPECT_TRUE(aos->Open()); | 673 EXPECT_TRUE(aos->Open()); |
699 | 674 |
700 // Derive the expected size in bytes of each packet. | 675 // Derive the expected size in bytes of each packet. |
701 uint32 bytes_per_packet = aosw.channels() * aosw.samples_per_packet() * | 676 uint32 bytes_per_packet = aosw.channels() * aosw.samples_per_packet() * |
702 (aosw.bits_per_sample() / 8); | 677 (aosw.bits_per_sample() / 8); |
703 | 678 |
704 // Set up expected minimum delay estimation. | 679 // Set up expected minimum delay estimation. |
705 AudioBuffersState state(0, bytes_per_packet); | 680 AudioBuffersState state(0, bytes_per_packet); |
706 | 681 |
707 // Wait for the first callback and verify its parameters. | 682 // Wait for the first callback and verify its parameters. |
708 EXPECT_CALL(source, OnMoreData(NotNull(), HasValidDelay(state))) | 683 EXPECT_CALL(source, OnMoreData(NotNull(), HasValidDelay(state))) |
709 .WillOnce(DoAll( | 684 .WillOnce(DoAll( |
710 QuitLoop(loop.message_loop_proxy()), | 685 QuitLoop(loop.message_loop_proxy()), |
711 Return(aosw.samples_per_packet()))) | 686 Return(aosw.samples_per_packet()))) |
712 .WillRepeatedly(Return(aosw.samples_per_packet())); | 687 .WillRepeatedly(Return(aosw.samples_per_packet())); |
713 | 688 |
714 aos->Start(&source); | 689 aos->Start(&source); |
715 loop.PostDelayedTask(FROM_HERE, MessageLoop::QuitClosure(), | 690 loop.PostDelayedTask(FROM_HERE, MessageLoop::QuitClosure(), |
716 TestTimeouts::action_timeout()); | 691 TestTimeouts::action_timeout()); |
717 loop.Run(); | 692 loop.Run(); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
754 | 729 |
755 aos->Start(&source); | 730 aos->Start(&source); |
756 loop.PostDelayedTask(FROM_HERE, MessageLoop::QuitClosure(), | 731 loop.PostDelayedTask(FROM_HERE, MessageLoop::QuitClosure(), |
757 TestTimeouts::action_timeout()); | 732 TestTimeouts::action_timeout()); |
758 loop.Run(); | 733 loop.Run(); |
759 aos->Stop(); | 734 aos->Stop(); |
760 aos->Close(); | 735 aos->Close(); |
761 } | 736 } |
762 | 737 |
763 } // namespace media | 738 } // namespace media |
OLD | NEW |