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