Upstream version 11.40.277.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/files/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 >= value;
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                          uint32 total_bytes_delay) {
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 void OnError(AudioOutputStream* stream) {}
134
135   int file_size() { return file_->data_size(); }
136
137  private:
138   scoped_refptr<DecoderBuffer> file_;
139   scoped_ptr<int[]> delta_times_;
140   int pos_;
141   base::TimeTicks previous_call_time_;
142   FILE* text_file_;
143   size_t elements_to_write_;
144 };
145
146 static bool ExclusiveModeIsEnabled() {
147   return (WASAPIAudioOutputStream::GetShareMode() ==
148           AUDCLNT_SHAREMODE_EXCLUSIVE);
149 }
150
151 // Convenience method which ensures that we are not running on the build
152 // bots and that at least one valid output device can be found. We also
153 // verify that we are not running on XP since the low-latency (WASAPI-
154 // based) version requires Windows Vista or higher.
155 static bool CanRunAudioTests(AudioManager* audio_man) {
156   if (!CoreAudioUtil::IsSupported()) {
157     LOG(WARNING) << "This test requires Windows Vista or higher.";
158     return false;
159   }
160
161   // TODO(henrika): note that we use Wave today to query the number of
162   // existing output devices.
163   if (!audio_man->HasAudioOutputDevices()) {
164     LOG(WARNING) << "No output devices detected.";
165     return false;
166   }
167
168   return true;
169 }
170
171 // Convenience method which creates a default AudioOutputStream object but
172 // also allows the user to modify the default settings.
173 class AudioOutputStreamWrapper {
174  public:
175   explicit AudioOutputStreamWrapper(AudioManager* audio_manager)
176       : audio_man_(audio_manager),
177         format_(AudioParameters::AUDIO_PCM_LOW_LATENCY),
178         bits_per_sample_(kBitsPerSample) {
179     AudioParameters preferred_params;
180     EXPECT_TRUE(SUCCEEDED(CoreAudioUtil::GetPreferredAudioParameters(
181         eRender, eConsole, &preferred_params)));
182     channel_layout_ = preferred_params.channel_layout();
183     sample_rate_ = preferred_params.sample_rate();
184     samples_per_packet_ = preferred_params.frames_per_buffer();
185   }
186
187   ~AudioOutputStreamWrapper() {}
188
189   // Creates AudioOutputStream object using default parameters.
190   AudioOutputStream* Create() {
191     return CreateOutputStream();
192   }
193
194   // Creates AudioOutputStream object using non-default parameters where the
195   // frame size is modified.
196   AudioOutputStream* Create(int samples_per_packet) {
197     samples_per_packet_ = samples_per_packet;
198     return CreateOutputStream();
199   }
200
201   // Creates AudioOutputStream object using non-default parameters where the
202   // sample rate and frame size are modified.
203   AudioOutputStream* Create(int sample_rate, int samples_per_packet) {
204     sample_rate_ = sample_rate;
205     samples_per_packet_ = samples_per_packet;
206     return CreateOutputStream();
207   }
208
209   AudioParameters::Format format() const { return format_; }
210   int channels() const { return ChannelLayoutToChannelCount(channel_layout_); }
211   int bits_per_sample() const { return bits_per_sample_; }
212   int sample_rate() const { return sample_rate_; }
213   int samples_per_packet() const { return samples_per_packet_; }
214
215  private:
216   AudioOutputStream* CreateOutputStream() {
217     AudioOutputStream* aos = audio_man_->MakeAudioOutputStream(
218         AudioParameters(format_, channel_layout_, sample_rate_,
219                         bits_per_sample_, samples_per_packet_),
220         std::string());
221     EXPECT_TRUE(aos);
222     return aos;
223   }
224
225   AudioManager* audio_man_;
226   AudioParameters::Format format_;
227   ChannelLayout channel_layout_;
228   int bits_per_sample_;
229   int sample_rate_;
230   int samples_per_packet_;
231 };
232
233 // Convenience method which creates a default AudioOutputStream object.
234 static AudioOutputStream* CreateDefaultAudioOutputStream(
235     AudioManager* audio_manager) {
236   AudioOutputStreamWrapper aosw(audio_manager);
237   AudioOutputStream* aos = aosw.Create();
238   return aos;
239 }
240
241 // Verify that we can retrieve the current hardware/mixing sample rate
242 // for the default audio device.
243 // TODO(henrika): modify this test when we support full device enumeration.
244 TEST(WASAPIAudioOutputStreamTest, HardwareSampleRate) {
245   // Skip this test in exclusive mode since the resulting rate is only utilized
246   // for shared mode streams.
247   scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
248   if (!CanRunAudioTests(audio_manager.get()) || ExclusiveModeIsEnabled())
249     return;
250
251   // Default device intended for games, system notification sounds,
252   // and voice commands.
253   int fs = static_cast<int>(
254       WASAPIAudioOutputStream::HardwareSampleRate(std::string()));
255   EXPECT_GE(fs, 0);
256 }
257
258 // Test Create(), Close() calling sequence.
259 TEST(WASAPIAudioOutputStreamTest, CreateAndClose) {
260   scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
261   if (!CanRunAudioTests(audio_manager.get()))
262     return;
263   AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get());
264   aos->Close();
265 }
266
267 // Test Open(), Close() calling sequence.
268 TEST(WASAPIAudioOutputStreamTest, OpenAndClose) {
269   scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
270   if (!CanRunAudioTests(audio_manager.get()))
271     return;
272   AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get());
273   EXPECT_TRUE(aos->Open());
274   aos->Close();
275 }
276
277 // Test Open(), Start(), Close() calling sequence.
278 TEST(WASAPIAudioOutputStreamTest, OpenStartAndClose) {
279   scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
280   if (!CanRunAudioTests(audio_manager.get()))
281     return;
282   AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get());
283   EXPECT_TRUE(aos->Open());
284   MockAudioSourceCallback source;
285   EXPECT_CALL(source, OnError(aos))
286       .Times(0);
287   aos->Start(&source);
288   aos->Close();
289 }
290
291 // Test Open(), Start(), Stop(), Close() calling sequence.
292 TEST(WASAPIAudioOutputStreamTest, OpenStartStopAndClose) {
293   scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
294   if (!CanRunAudioTests(audio_manager.get()))
295     return;
296   AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get());
297   EXPECT_TRUE(aos->Open());
298   MockAudioSourceCallback source;
299   EXPECT_CALL(source, OnError(aos))
300       .Times(0);
301   aos->Start(&source);
302   aos->Stop();
303   aos->Close();
304 }
305
306 // Test SetVolume(), GetVolume()
307 TEST(WASAPIAudioOutputStreamTest, Volume) {
308   scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
309   if (!CanRunAudioTests(audio_manager.get()))
310     return;
311   AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get());
312
313   // Initial volume should be full volume (1.0).
314   double volume = 0.0;
315   aos->GetVolume(&volume);
316   EXPECT_EQ(1.0, volume);
317
318   // Verify some valid volume settings.
319   aos->SetVolume(0.0);
320   aos->GetVolume(&volume);
321   EXPECT_EQ(0.0, volume);
322
323   aos->SetVolume(0.5);
324   aos->GetVolume(&volume);
325   EXPECT_EQ(0.5, volume);
326
327   aos->SetVolume(1.0);
328   aos->GetVolume(&volume);
329   EXPECT_EQ(1.0, volume);
330
331   // Ensure that invalid volume setting have no effect.
332   aos->SetVolume(1.5);
333   aos->GetVolume(&volume);
334   EXPECT_EQ(1.0, volume);
335
336   aos->SetVolume(-0.5);
337   aos->GetVolume(&volume);
338   EXPECT_EQ(1.0, volume);
339
340   aos->Close();
341 }
342
343 // Test some additional calling sequences.
344 TEST(WASAPIAudioOutputStreamTest, MiscCallingSequences) {
345   scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
346   if (!CanRunAudioTests(audio_manager.get()))
347     return;
348
349   AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get());
350   WASAPIAudioOutputStream* waos = static_cast<WASAPIAudioOutputStream*>(aos);
351
352   // Open(), Open() is a valid calling sequence (second call does nothing).
353   EXPECT_TRUE(aos->Open());
354   EXPECT_TRUE(aos->Open());
355
356   MockAudioSourceCallback source;
357
358   // Start(), Start() is a valid calling sequence (second call does nothing).
359   aos->Start(&source);
360   EXPECT_TRUE(waos->started());
361   aos->Start(&source);
362   EXPECT_TRUE(waos->started());
363
364   // Stop(), Stop() is a valid calling sequence (second call does nothing).
365   aos->Stop();
366   EXPECT_FALSE(waos->started());
367   aos->Stop();
368   EXPECT_FALSE(waos->started());
369
370   // Start(), Stop(), Start(), Stop().
371   aos->Start(&source);
372   EXPECT_TRUE(waos->started());
373   aos->Stop();
374   EXPECT_FALSE(waos->started());
375   aos->Start(&source);
376   EXPECT_TRUE(waos->started());
377   aos->Stop();
378   EXPECT_FALSE(waos->started());
379
380   aos->Close();
381 }
382
383 // Use preferred packet size and verify that rendering starts.
384 TEST(WASAPIAudioOutputStreamTest, ValidPacketSize) {
385   scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
386   if (!CanRunAudioTests(audio_manager.get()))
387     return;
388
389   base::MessageLoopForUI loop;
390   MockAudioSourceCallback source;
391
392   // Create default WASAPI output stream which plays out in stereo using
393   // the shared mixing rate. The default buffer size is 10ms.
394   AudioOutputStreamWrapper aosw(audio_manager.get());
395   AudioOutputStream* aos = aosw.Create();
396   EXPECT_TRUE(aos->Open());
397
398   // Derive the expected size in bytes of each packet.
399   uint32 bytes_per_packet = aosw.channels() * aosw.samples_per_packet() *
400       (aosw.bits_per_sample() / 8);
401
402   // Wait for the first callback and verify its parameters.
403   EXPECT_CALL(source, OnMoreData(NotNull(), HasValidDelay(bytes_per_packet)))
404       .WillOnce(DoAll(
405           QuitLoop(loop.message_loop_proxy()),
406           Return(aosw.samples_per_packet())));
407
408   aos->Start(&source);
409   loop.PostDelayedTask(FROM_HERE, base::MessageLoop::QuitClosure(),
410                        TestTimeouts::action_timeout());
411   loop.Run();
412   aos->Stop();
413   aos->Close();
414 }
415
416 // This test is intended for manual tests and should only be enabled
417 // when it is required to play out data from a local PCM file.
418 // By default, GTest will print out YOU HAVE 1 DISABLED TEST.
419 // To include disabled tests in test execution, just invoke the test program
420 // with --gtest_also_run_disabled_tests or set the GTEST_ALSO_RUN_DISABLED_TESTS
421 // environment variable to a value greater than 0.
422 // The test files are approximately 20 seconds long.
423 TEST(WASAPIAudioOutputStreamTest, DISABLED_ReadFromStereoFile) {
424   scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
425   if (!CanRunAudioTests(audio_manager.get()))
426     return;
427
428   AudioOutputStreamWrapper aosw(audio_manager.get());
429   AudioOutputStream* aos = aosw.Create();
430   EXPECT_TRUE(aos->Open());
431
432   std::string file_name;
433   if (aosw.sample_rate() == 48000) {
434     file_name = kSpeechFile_16b_s_48k;
435   } else if (aosw.sample_rate() == 44100) {
436     file_name = kSpeechFile_16b_s_44k;
437   } else if (aosw.sample_rate() == 96000) {
438     // Use 48kHz file at 96kHz as well. Will sound like Donald Duck.
439     file_name = kSpeechFile_16b_s_48k;
440   } else {
441     FAIL() << "This test supports 44.1, 48kHz and 96kHz only.";
442     return;
443   }
444   ReadFromFileAudioSource file_source(file_name);
445
446   VLOG(0) << "File name      : " << file_name.c_str();
447   VLOG(0) << "Sample rate    : " << aosw.sample_rate();
448   VLOG(0) << "Bits per sample: " << aosw.bits_per_sample();
449   VLOG(0) << "#channels      : " << aosw.channels();
450   VLOG(0) << "File size      : " << file_source.file_size();
451   VLOG(0) << "#file segments : " << kNumFileSegments;
452   VLOG(0) << ">> Listen to the stereo file while playing...";
453
454   for (int i = 0; i < kNumFileSegments; i++) {
455     // Each segment will start with a short (~20ms) block of zeros, hence
456     // some short glitches might be heard in this test if kNumFileSegments
457     // is larger than one. The exact length of the silence period depends on
458     // the selected sample rate.
459     aos->Start(&file_source);
460     base::PlatformThread::Sleep(
461         base::TimeDelta::FromMilliseconds(kFileDurationMs / kNumFileSegments));
462     aos->Stop();
463   }
464
465   VLOG(0) << ">> Stereo file playout has stopped.";
466   aos->Close();
467 }
468
469 // Verify that we can open the output stream in exclusive mode using a
470 // certain set of audio parameters and a sample rate of 48kHz.
471 // The expected outcomes of each setting in this test has been derived
472 // manually using log outputs (--v=1).
473 TEST(WASAPIAudioOutputStreamTest, ExclusiveModeBufferSizesAt48kHz) {
474   if (!ExclusiveModeIsEnabled())
475     return;
476
477   scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
478   if (!CanRunAudioTests(audio_manager.get()))
479     return;
480
481   AudioOutputStreamWrapper aosw(audio_manager.get());
482
483   // 10ms @ 48kHz shall work.
484   // Note that, this is the same size as we can use for shared-mode streaming
485   // but here the endpoint buffer delay is only 10ms instead of 20ms.
486   AudioOutputStream* aos = aosw.Create(48000, 480);
487   EXPECT_TRUE(aos->Open());
488   aos->Close();
489
490   // 5ms @ 48kHz does not work due to misalignment.
491   // This test will propose an aligned buffer size of 5.3333ms.
492   // Note that we must call Close() even is Open() fails since Close() also
493   // deletes the object and we want to create a new object in the next test.
494   aos = aosw.Create(48000, 240);
495   EXPECT_FALSE(aos->Open());
496   aos->Close();
497
498   // 5.3333ms @ 48kHz should work (see test above).
499   aos = aosw.Create(48000, 256);
500   EXPECT_TRUE(aos->Open());
501   aos->Close();
502
503   // 2.6667ms is smaller than the minimum supported size (=3ms).
504   aos = aosw.Create(48000, 128);
505   EXPECT_FALSE(aos->Open());
506   aos->Close();
507
508   // 3ms does not correspond to an aligned buffer size.
509   // This test will propose an aligned buffer size of 3.3333ms.
510   aos = aosw.Create(48000, 144);
511   EXPECT_FALSE(aos->Open());
512   aos->Close();
513
514   // 3.3333ms @ 48kHz <=> smallest possible buffer size we can use.
515   aos = aosw.Create(48000, 160);
516   EXPECT_TRUE(aos->Open());
517   aos->Close();
518 }
519
520 // Verify that we can open the output stream in exclusive mode using a
521 // certain set of audio parameters and a sample rate of 44.1kHz.
522 // The expected outcomes of each setting in this test has been derived
523 // manually using log outputs (--v=1).
524 TEST(WASAPIAudioOutputStreamTest, ExclusiveModeBufferSizesAt44kHz) {
525   if (!ExclusiveModeIsEnabled())
526     return;
527
528   scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
529   if (!CanRunAudioTests(audio_manager.get()))
530     return;
531
532   AudioOutputStreamWrapper aosw(audio_manager.get());
533
534   // 10ms @ 44.1kHz does not work due to misalignment.
535   // This test will propose an aligned buffer size of 10.1587ms.
536   AudioOutputStream* aos = aosw.Create(44100, 441);
537   EXPECT_FALSE(aos->Open());
538   aos->Close();
539
540   // 10.1587ms @ 44.1kHz shall work (see test above).
541   aos = aosw.Create(44100, 448);
542   EXPECT_TRUE(aos->Open());
543   aos->Close();
544
545   // 5.8050ms @ 44.1 should work.
546   aos = aosw.Create(44100, 256);
547   EXPECT_TRUE(aos->Open());
548   aos->Close();
549
550   // 4.9887ms @ 44.1kHz does not work to misalignment.
551   // This test will propose an aligned buffer size of 5.0794ms.
552   // Note that we must call Close() even is Open() fails since Close() also
553   // deletes the object and we want to create a new object in the next test.
554   aos = aosw.Create(44100, 220);
555   EXPECT_FALSE(aos->Open());
556   aos->Close();
557
558   // 5.0794ms @ 44.1kHz shall work (see test above).
559   aos = aosw.Create(44100, 224);
560   EXPECT_TRUE(aos->Open());
561   aos->Close();
562
563   // 2.9025ms is smaller than the minimum supported size (=3ms).
564   aos = aosw.Create(44100, 132);
565   EXPECT_FALSE(aos->Open());
566   aos->Close();
567
568   // 3.01587ms is larger than the minimum size but is not aligned.
569   // This test will propose an aligned buffer size of 3.6281ms.
570   aos = aosw.Create(44100, 133);
571   EXPECT_FALSE(aos->Open());
572   aos->Close();
573
574   // 3.6281ms @ 44.1kHz <=> smallest possible buffer size we can use.
575   aos = aosw.Create(44100, 160);
576   EXPECT_TRUE(aos->Open());
577   aos->Close();
578 }
579
580 // Verify that we can open and start the output stream in exclusive mode at
581 // the lowest possible delay at 48kHz.
582 TEST(WASAPIAudioOutputStreamTest, ExclusiveModeMinBufferSizeAt48kHz) {
583   if (!ExclusiveModeIsEnabled())
584     return;
585
586   scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
587   if (!CanRunAudioTests(audio_manager.get()))
588     return;
589
590   base::MessageLoopForUI loop;
591   MockAudioSourceCallback source;
592
593   // Create exclusive-mode WASAPI output stream which plays out in stereo
594   // using the minimum buffer size at 48kHz sample rate.
595   AudioOutputStreamWrapper aosw(audio_manager.get());
596   AudioOutputStream* aos = aosw.Create(48000, 160);
597   EXPECT_TRUE(aos->Open());
598
599   // Derive the expected size in bytes of each packet.
600   uint32 bytes_per_packet = aosw.channels() * aosw.samples_per_packet() *
601       (aosw.bits_per_sample() / 8);
602
603  // Wait for the first callback and verify its parameters.
604   EXPECT_CALL(source, OnMoreData(NotNull(), HasValidDelay(bytes_per_packet)))
605       .WillOnce(DoAll(
606           QuitLoop(loop.message_loop_proxy()),
607           Return(aosw.samples_per_packet())))
608       .WillRepeatedly(Return(aosw.samples_per_packet()));
609
610   aos->Start(&source);
611   loop.PostDelayedTask(FROM_HERE, base::MessageLoop::QuitClosure(),
612                        TestTimeouts::action_timeout());
613   loop.Run();
614   aos->Stop();
615   aos->Close();
616 }
617
618 // Verify that we can open and start the output stream in exclusive mode at
619 // the lowest possible delay at 44.1kHz.
620 TEST(WASAPIAudioOutputStreamTest, ExclusiveModeMinBufferSizeAt44kHz) {
621   if (!ExclusiveModeIsEnabled())
622     return;
623
624   scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
625   if (!CanRunAudioTests(audio_manager.get()))
626     return;
627
628   base::MessageLoopForUI loop;
629   MockAudioSourceCallback source;
630
631   // Create exclusive-mode WASAPI output stream which plays out in stereo
632   // using the minimum buffer size at 44.1kHz sample rate.
633   AudioOutputStreamWrapper aosw(audio_manager.get());
634   AudioOutputStream* aos = aosw.Create(44100, 160);
635   EXPECT_TRUE(aos->Open());
636
637   // Derive the expected size in bytes of each packet.
638   uint32 bytes_per_packet = aosw.channels() * aosw.samples_per_packet() *
639       (aosw.bits_per_sample() / 8);
640
641   // Wait for the first callback and verify its parameters.
642   EXPECT_CALL(source, OnMoreData(NotNull(), HasValidDelay(bytes_per_packet)))
643     .WillOnce(DoAll(
644         QuitLoop(loop.message_loop_proxy()),
645         Return(aosw.samples_per_packet())))
646     .WillRepeatedly(Return(aosw.samples_per_packet()));
647
648   aos->Start(&source);
649   loop.PostDelayedTask(FROM_HERE, base::MessageLoop::QuitClosure(),
650                         TestTimeouts::action_timeout());
651   loop.Run();
652   aos->Stop();
653   aos->Close();
654 }
655
656 }  // namespace media