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