Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / media / audio / win / audio_low_latency_output_win_unittest.cc
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.
4
5 #include <windows.h>
6 #include <mmsystem.h>
7
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"
28
29 using ::testing::_;
30 using ::testing::AnyNumber;
31 using ::testing::AtLeast;
32 using ::testing::Between;
33 using ::testing::CreateFunctor;
34 using ::testing::DoAll;
35 using ::testing::Gt;
36 using ::testing::InvokeWithoutArgs;
37 using ::testing::NotNull;
38 using ::testing::Return;
39 using base::win::ScopedCOMInitializer;
40
41 namespace media {
42
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";
50
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;
56 }
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, base::MessageLoop::QuitClosure());
62 }
63
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 {
67  public:
68   explicit ReadFromFileAudioSource(const std::string& name)
69     : pos_(0),
70       previous_call_time_(base::TimeTicks::Now()),
71       text_file_(NULL),
72       elements_to_write_(0) {
73     // Reads a test file from media/test/data directory.
74     file_ = ReadTestDataFile(name);
75
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]);
81   }
82
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);
89
90     EXPECT_TRUE(!text_file_);
91     text_file_ = base::OpenFile(file_name, "wt");
92     DLOG_IF(ERROR, !text_file_) << "Failed to open log file.";
93
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]);
98       ++elements_written;
99     }
100
101     base::CloseFile(text_file_);
102   }
103
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_;
115     }
116
117     int max_size =
118         audio_bus->frames() * audio_bus->channels() * kBitsPerSample / 8;
119
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);
125     if (max_size) {
126       audio_bus->FromInterleaved(
127           file_->data() + pos_, frames, kBitsPerSample / 8);
128       pos_ += max_size;
129     }
130     return frames;
131   }
132
133   virtual int OnMoreIOData(AudioBus* source,
134                            AudioBus* dest,
135                            AudioBuffersState buffers_state) OVERRIDE {
136     NOTREACHED();
137     return 0;
138   }
139
140   virtual void OnError(AudioOutputStream* stream) {}
141
142   int file_size() { return file_->data_size(); }
143
144  private:
145   scoped_refptr<DecoderBuffer> file_;
146   scoped_ptr<int[]> delta_times_;
147   int pos_;
148   base::TimeTicks previous_call_time_;
149   FILE* text_file_;
150   size_t elements_to_write_;
151 };
152
153 static bool ExclusiveModeIsEnabled() {
154   return (WASAPIAudioOutputStream::GetShareMode() ==
155           AUDCLNT_SHAREMODE_EXCLUSIVE);
156 }
157
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.";
165     return false;
166   }
167
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.";
172     return false;
173   }
174
175   return true;
176 }
177
178 // Convenience method which creates a default AudioOutputStream object but
179 // also allows the user to modify the default settings.
180 class AudioOutputStreamWrapper {
181  public:
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();
192   }
193
194   ~AudioOutputStreamWrapper() {}
195
196   // Creates AudioOutputStream object using default parameters.
197   AudioOutputStream* Create() {
198     return CreateOutputStream();
199   }
200
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();
206   }
207
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();
214   }
215
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_; }
221
222  private:
223   AudioOutputStream* CreateOutputStream() {
224     AudioOutputStream* aos = audio_man_->MakeAudioOutputStream(
225         AudioParameters(format_, channel_layout_, sample_rate_,
226                         bits_per_sample_, samples_per_packet_),
227         std::string());
228     EXPECT_TRUE(aos);
229     return aos;
230   }
231
232   AudioManager* audio_man_;
233   AudioParameters::Format format_;
234   ChannelLayout channel_layout_;
235   int bits_per_sample_;
236   int sample_rate_;
237   int samples_per_packet_;
238 };
239
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();
245   return aos;
246 }
247
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())
256     return;
257
258   // Default device intended for games, system notification sounds,
259   // and voice commands.
260   int fs = static_cast<int>(
261       WASAPIAudioOutputStream::HardwareSampleRate(std::string()));
262   EXPECT_GE(fs, 0);
263 }
264
265 // Test Create(), Close() calling sequence.
266 TEST(WASAPIAudioOutputStreamTest, CreateAndClose) {
267   scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
268   if (!CanRunAudioTests(audio_manager.get()))
269     return;
270   AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get());
271   aos->Close();
272 }
273
274 // Test Open(), Close() calling sequence.
275 TEST(WASAPIAudioOutputStreamTest, OpenAndClose) {
276   scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
277   if (!CanRunAudioTests(audio_manager.get()))
278     return;
279   AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get());
280   EXPECT_TRUE(aos->Open());
281   aos->Close();
282 }
283
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()))
288     return;
289   AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get());
290   EXPECT_TRUE(aos->Open());
291   MockAudioSourceCallback source;
292   EXPECT_CALL(source, OnError(aos))
293       .Times(0);
294   aos->Start(&source);
295   aos->Close();
296 }
297
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()))
302     return;
303   AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get());
304   EXPECT_TRUE(aos->Open());
305   MockAudioSourceCallback source;
306   EXPECT_CALL(source, OnError(aos))
307       .Times(0);
308   aos->Start(&source);
309   aos->Stop();
310   aos->Close();
311 }
312
313 // Test SetVolume(), GetVolume()
314 TEST(WASAPIAudioOutputStreamTest, Volume) {
315   scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
316   if (!CanRunAudioTests(audio_manager.get()))
317     return;
318   AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get());
319
320   // Initial volume should be full volume (1.0).
321   double volume = 0.0;
322   aos->GetVolume(&volume);
323   EXPECT_EQ(1.0, volume);
324
325   // Verify some valid volume settings.
326   aos->SetVolume(0.0);
327   aos->GetVolume(&volume);
328   EXPECT_EQ(0.0, volume);
329
330   aos->SetVolume(0.5);
331   aos->GetVolume(&volume);
332   EXPECT_EQ(0.5, volume);
333
334   aos->SetVolume(1.0);
335   aos->GetVolume(&volume);
336   EXPECT_EQ(1.0, volume);
337
338   // Ensure that invalid volume setting have no effect.
339   aos->SetVolume(1.5);
340   aos->GetVolume(&volume);
341   EXPECT_EQ(1.0, volume);
342
343   aos->SetVolume(-0.5);
344   aos->GetVolume(&volume);
345   EXPECT_EQ(1.0, volume);
346
347   aos->Close();
348 }
349
350 // Test some additional calling sequences.
351 TEST(WASAPIAudioOutputStreamTest, MiscCallingSequences) {
352   scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
353   if (!CanRunAudioTests(audio_manager.get()))
354     return;
355
356   AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get());
357   WASAPIAudioOutputStream* waos = static_cast<WASAPIAudioOutputStream*>(aos);
358
359   // Open(), Open() is a valid calling sequence (second call does nothing).
360   EXPECT_TRUE(aos->Open());
361   EXPECT_TRUE(aos->Open());
362
363   MockAudioSourceCallback source;
364
365   // Start(), Start() is a valid calling sequence (second call does nothing).
366   aos->Start(&source);
367   EXPECT_TRUE(waos->started());
368   aos->Start(&source);
369   EXPECT_TRUE(waos->started());
370
371   // Stop(), Stop() is a valid calling sequence (second call does nothing).
372   aos->Stop();
373   EXPECT_FALSE(waos->started());
374   aos->Stop();
375   EXPECT_FALSE(waos->started());
376
377   // Start(), Stop(), Start(), Stop().
378   aos->Start(&source);
379   EXPECT_TRUE(waos->started());
380   aos->Stop();
381   EXPECT_FALSE(waos->started());
382   aos->Start(&source);
383   EXPECT_TRUE(waos->started());
384   aos->Stop();
385   EXPECT_FALSE(waos->started());
386
387   aos->Close();
388 }
389
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()))
394     return;
395
396   base::MessageLoopForUI loop;
397   MockAudioSourceCallback source;
398
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());
404
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);
408
409   // Set up expected minimum delay estimation.
410   AudioBuffersState state(0, bytes_per_packet);
411
412   // Wait for the first callback and verify its parameters.
413   EXPECT_CALL(source, OnMoreData(NotNull(), HasValidDelay(state)))
414       .WillOnce(DoAll(
415           QuitLoop(loop.message_loop_proxy()),
416           Return(aosw.samples_per_packet())));
417
418   aos->Start(&source);
419   loop.PostDelayedTask(FROM_HERE, base::MessageLoop::QuitClosure(),
420                        TestTimeouts::action_timeout());
421   loop.Run();
422   aos->Stop();
423   aos->Close();
424 }
425
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()))
436     return;
437
438   AudioOutputStreamWrapper aosw(audio_manager.get());
439   AudioOutputStream* aos = aosw.Create();
440   EXPECT_TRUE(aos->Open());
441
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;
450   } else {
451     FAIL() << "This test supports 44.1, 48kHz and 96kHz only.";
452     return;
453   }
454   ReadFromFileAudioSource file_source(file_name);
455
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...";
463
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));
472     aos->Stop();
473   }
474
475   VLOG(0) << ">> Stereo file playout has stopped.";
476   aos->Close();
477 }
478
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())
485     return;
486
487   scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
488   if (!CanRunAudioTests(audio_manager.get()))
489     return;
490
491   AudioOutputStreamWrapper aosw(audio_manager.get());
492
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());
498   aos->Close();
499
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());
506   aos->Close();
507
508   // 5.3333ms @ 48kHz should work (see test above).
509   aos = aosw.Create(48000, 256);
510   EXPECT_TRUE(aos->Open());
511   aos->Close();
512
513   // 2.6667ms is smaller than the minimum supported size (=3ms).
514   aos = aosw.Create(48000, 128);
515   EXPECT_FALSE(aos->Open());
516   aos->Close();
517
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());
522   aos->Close();
523
524   // 3.3333ms @ 48kHz <=> smallest possible buffer size we can use.
525   aos = aosw.Create(48000, 160);
526   EXPECT_TRUE(aos->Open());
527   aos->Close();
528 }
529
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())
536     return;
537
538   scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
539   if (!CanRunAudioTests(audio_manager.get()))
540     return;
541
542   AudioOutputStreamWrapper aosw(audio_manager.get());
543
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());
548   aos->Close();
549
550   // 10.1587ms @ 44.1kHz shall work (see test above).
551   aos = aosw.Create(44100, 448);
552   EXPECT_TRUE(aos->Open());
553   aos->Close();
554
555   // 5.8050ms @ 44.1 should work.
556   aos = aosw.Create(44100, 256);
557   EXPECT_TRUE(aos->Open());
558   aos->Close();
559
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());
566   aos->Close();
567
568   // 5.0794ms @ 44.1kHz shall work (see test above).
569   aos = aosw.Create(44100, 224);
570   EXPECT_TRUE(aos->Open());
571   aos->Close();
572
573   // 2.9025ms is smaller than the minimum supported size (=3ms).
574   aos = aosw.Create(44100, 132);
575   EXPECT_FALSE(aos->Open());
576   aos->Close();
577
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());
582   aos->Close();
583
584   // 3.6281ms @ 44.1kHz <=> smallest possible buffer size we can use.
585   aos = aosw.Create(44100, 160);
586   EXPECT_TRUE(aos->Open());
587   aos->Close();
588 }
589
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())
594     return;
595
596   scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
597   if (!CanRunAudioTests(audio_manager.get()))
598     return;
599
600   base::MessageLoopForUI loop;
601   MockAudioSourceCallback source;
602
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());
608
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);
612
613   // Set up expected minimum delay estimation.
614   AudioBuffersState state(0, bytes_per_packet);
615
616  // Wait for the first callback and verify its parameters.
617   EXPECT_CALL(source, OnMoreData(NotNull(), HasValidDelay(state)))
618       .WillOnce(DoAll(
619           QuitLoop(loop.message_loop_proxy()),
620           Return(aosw.samples_per_packet())))
621       .WillRepeatedly(Return(aosw.samples_per_packet()));
622
623   aos->Start(&source);
624   loop.PostDelayedTask(FROM_HERE, base::MessageLoop::QuitClosure(),
625                        TestTimeouts::action_timeout());
626   loop.Run();
627   aos->Stop();
628   aos->Close();
629 }
630
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())
635     return;
636
637   scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
638   if (!CanRunAudioTests(audio_manager.get()))
639     return;
640
641   base::MessageLoopForUI loop;
642   MockAudioSourceCallback source;
643
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());
649
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);
653
654   // Set up expected minimum delay estimation.
655   AudioBuffersState state(0, bytes_per_packet);
656
657   // Wait for the first callback and verify its parameters.
658   EXPECT_CALL(source, OnMoreData(NotNull(), HasValidDelay(state)))
659     .WillOnce(DoAll(
660         QuitLoop(loop.message_loop_proxy()),
661         Return(aosw.samples_per_packet())))
662     .WillRepeatedly(Return(aosw.samples_per_packet()));
663
664   aos->Start(&source);
665   loop.PostDelayedTask(FROM_HERE, base::MessageLoop::QuitClosure(),
666                         TestTimeouts::action_timeout());
667   loop.Run();
668   aos->Stop();
669   aos->Close();
670 }
671
672 }  // namespace media