audio_low_latency_output_win_unittest.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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.h"
13#include "base/test/test_timeouts.h"
14#include "base/time.h"
15#include "base/path_service.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/audio_util.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_mutant.h"
26#include "testing/gmock/include/gmock/gmock.h"
27#include "testing/gtest/include/gtest/gtest.h"
28
29using ::testing::_;
30using ::testing::AnyNumber;
31using ::testing::AtLeast;
32using ::testing::Between;
33using ::testing::CreateFunctor;
34using ::testing::DoAll;
35using ::testing::Gt;
36using ::testing::InvokeWithoutArgs;
37using ::testing::NotNull;
38using ::testing::Return;
39using base::win::ScopedCOMInitializer;
40
41namespace media {
42
43static const char kSpeechFile_16b_s_48k[] = "speech_16b_stereo_48kHz.raw";
44static const char kSpeechFile_16b_s_44k[] = "speech_16b_stereo_44kHz.raw";
45static const size_t kFileDurationMs = 20000;
46static const size_t kNumFileSegments = 2;
47static const int kBitsPerSample = 16;
48static const size_t kMaxDeltaSamples = 1000;
49static const char kDeltaTimeMsFileName[] = "delta_times_ms.txt";
50
51MATCHER_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.
60ACTION_P(QuitLoop, loop) {
61  loop->PostTask(FROM_HERE, MessageLoop::QuitClosure());
62}
63
64class MockAudioSourceCallback : public AudioOutputStream::AudioSourceCallback {
65 public:
66  MOCK_METHOD2(OnMoreData, int(AudioBus* audio_bus,
67                               AudioBuffersState buffers_state));
68  MOCK_METHOD3(OnMoreIOData, int(AudioBus* source,
69                                 AudioBus* dest,
70                                 AudioBuffersState buffers_state));
71  MOCK_METHOD1(OnError, void(AudioOutputStream* stream));
72};
73
74// This audio source implementation should be used for manual tests only since
75// it takes about 20 seconds to play out a file.
76class ReadFromFileAudioSource : public AudioOutputStream::AudioSourceCallback {
77 public:
78  explicit ReadFromFileAudioSource(const std::string& name)
79    : pos_(0),
80      previous_call_time_(base::Time::Now()),
81      text_file_(NULL),
82      elements_to_write_(0) {
83    // Reads a test file from media/test/data directory.
84    file_ = ReadTestDataFile(name);
85
86    // Creates an array that will store delta times between callbacks.
87    // The content of this array will be written to a text file at
88    // destruction and can then be used for off-line analysis of the exact
89    // timing of callbacks. The text file will be stored in media/test/data.
90    delta_times_.reset(new int[kMaxDeltaSamples]);
91  }
92
93  virtual ~ReadFromFileAudioSource() {
94    // Get complete file path to output file in directory containing
95    // media_unittests.exe.
96    base::FilePath file_name;
97    EXPECT_TRUE(PathService::Get(base::DIR_EXE, &file_name));
98    file_name = file_name.AppendASCII(kDeltaTimeMsFileName);
99
100    EXPECT_TRUE(!text_file_);
101    text_file_ = file_util::OpenFile(file_name, "wt");
102    DLOG_IF(ERROR, !text_file_) << "Failed to open log file.";
103
104    // Write the array which contains delta times to a text file.
105    size_t elements_written = 0;
106    while (elements_written < elements_to_write_) {
107      fprintf(text_file_, "%d\n", delta_times_[elements_written]);
108      ++elements_written;
109    }
110
111    file_util::CloseFile(text_file_);
112  }
113
114  // AudioOutputStream::AudioSourceCallback implementation.
115  virtual int OnMoreData(AudioBus* audio_bus,
116                         AudioBuffersState buffers_state) {
117    // Store time difference between two successive callbacks in an array.
118    // These values will be written to a file in the destructor.
119    int diff = (base::Time::Now() - previous_call_time_).InMilliseconds();
120    previous_call_time_ = base::Time::Now();
121    if (elements_to_write_ < kMaxDeltaSamples) {
122      delta_times_[elements_to_write_] = diff;
123      ++elements_to_write_;
124    }
125
126    int max_size =
127        audio_bus->frames() * audio_bus->channels() * kBitsPerSample / 8;
128
129    // Use samples read from a data file and fill up the audio buffer
130    // provided to us in the callback.
131    if (pos_ + static_cast<int>(max_size) > file_size())
132      max_size = file_size() - pos_;
133    int frames = max_size / (audio_bus->channels() * kBitsPerSample / 8);
134    if (max_size) {
135      audio_bus->FromInterleaved(
136          file_->GetData() + pos_, frames, kBitsPerSample / 8);
137      pos_ += max_size;
138    }
139    return frames;
140  }
141
142  virtual int OnMoreIOData(AudioBus* source,
143                           AudioBus* dest,
144                           AudioBuffersState buffers_state) OVERRIDE {
145    NOTREACHED();
146    return 0;
147  }
148
149  virtual void OnError(AudioOutputStream* stream) {}
150
151  int file_size() { return file_->GetDataSize(); }
152
153 private:
154  scoped_refptr<DecoderBuffer> file_;
155  scoped_array<int> delta_times_;
156  int pos_;
157  base::Time previous_call_time_;
158  FILE* text_file_;
159  size_t elements_to_write_;
160};
161
162static bool ExclusiveModeIsEnabled() {
163  return (WASAPIAudioOutputStream::GetShareMode() ==
164          AUDCLNT_SHAREMODE_EXCLUSIVE);
165}
166
167// Convenience method which ensures that we are not running on the build
168// bots and that at least one valid output device can be found. We also
169// verify that we are not running on XP since the low-latency (WASAPI-
170// based) version requires Windows Vista or higher.
171static bool CanRunAudioTests(AudioManager* audio_man) {
172  if (!CoreAudioUtil::IsSupported()) {
173    LOG(WARNING) << "This test requires Windows Vista or higher.";
174    return false;
175  }
176
177  // TODO(henrika): note that we use Wave today to query the number of
178  // existing output devices.
179  if (!audio_man->HasAudioOutputDevices()) {
180    LOG(WARNING) << "No output devices detected.";
181    return false;
182  }
183
184  return true;
185}
186
187// Convenience method which creates a default AudioOutputStream object but
188// also allows the user to modify the default settings.
189class AudioOutputStreamWrapper {
190 public:
191  explicit AudioOutputStreamWrapper(AudioManager* audio_manager)
192      : audio_man_(audio_manager),
193        format_(AudioParameters::AUDIO_PCM_LOW_LATENCY),
194        bits_per_sample_(kBitsPerSample) {
195    AudioParameters preferred_params;
196    EXPECT_TRUE(SUCCEEDED(CoreAudioUtil::GetPreferredAudioParameters(
197        eRender, eConsole, &preferred_params)));
198    channel_layout_ = preferred_params.channel_layout();
199    sample_rate_ = preferred_params.sample_rate();
200    samples_per_packet_ = preferred_params.frames_per_buffer();
201  }
202
203  ~AudioOutputStreamWrapper() {}
204
205  // Creates AudioOutputStream object using default parameters.
206  AudioOutputStream* Create() {
207    return CreateOutputStream();
208  }
209
210  // Creates AudioOutputStream object using non-default parameters where the
211  // frame size is modified.
212  AudioOutputStream* Create(int samples_per_packet) {
213    samples_per_packet_ = samples_per_packet;
214    return CreateOutputStream();
215  }
216
217  // Creates AudioOutputStream object using non-default parameters where the
218  // sample rate and frame size are modified.
219  AudioOutputStream* Create(int sample_rate, int samples_per_packet) {
220    sample_rate_ = sample_rate;
221    samples_per_packet_ = samples_per_packet;
222    return CreateOutputStream();
223  }
224
225  AudioParameters::Format format() const { return format_; }
226  int channels() const { return ChannelLayoutToChannelCount(channel_layout_); }
227  int bits_per_sample() const { return bits_per_sample_; }
228  int sample_rate() const { return sample_rate_; }
229  int samples_per_packet() const { return samples_per_packet_; }
230
231 private:
232  AudioOutputStream* CreateOutputStream() {
233    AudioOutputStream* aos = audio_man_->MakeAudioOutputStream(
234        AudioParameters(format_, channel_layout_, sample_rate_,
235                        bits_per_sample_, samples_per_packet_));
236    EXPECT_TRUE(aos);
237    return aos;
238  }
239
240  AudioManager* audio_man_;
241  AudioParameters::Format format_;
242  ChannelLayout channel_layout_;
243  int bits_per_sample_;
244  int sample_rate_;
245  int samples_per_packet_;
246};
247
248// Convenience method which creates a default AudioOutputStream object.
249static AudioOutputStream* CreateDefaultAudioOutputStream(
250    AudioManager* audio_manager) {
251  AudioOutputStreamWrapper aosw(audio_manager);
252  AudioOutputStream* aos = aosw.Create();
253  return aos;
254}
255
256// Verify that we can retrieve the current hardware/mixing sample rate
257// for the default audio device.
258// TODO(henrika): modify this test when we support full device enumeration.
259TEST(WASAPIAudioOutputStreamTest, HardwareSampleRate) {
260  // Skip this test in exclusive mode since the resulting rate is only utilized
261  // for shared mode streams.
262  scoped_ptr<AudioManager> audio_manager(AudioManager::Create());
263  if (!CanRunAudioTests(audio_manager.get()) || ExclusiveModeIsEnabled())
264    return;
265
266  // Default device intended for games, system notification sounds,
267  // and voice commands.
268  int fs = static_cast<int>(
269      WASAPIAudioOutputStream::HardwareSampleRate());
270  EXPECT_GE(fs, 0);
271}
272
273// Test Create(), Close() calling sequence.
274TEST(WASAPIAudioOutputStreamTest, CreateAndClose) {
275  scoped_ptr<AudioManager> audio_manager(AudioManager::Create());
276  if (!CanRunAudioTests(audio_manager.get()))
277    return;
278  AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get());
279  aos->Close();
280}
281
282// Test Open(), Close() calling sequence.
283TEST(WASAPIAudioOutputStreamTest, OpenAndClose) {
284  scoped_ptr<AudioManager> audio_manager(AudioManager::Create());
285  if (!CanRunAudioTests(audio_manager.get()))
286    return;
287  AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get());
288  EXPECT_TRUE(aos->Open());
289  aos->Close();
290}
291
292// Test Open(), Start(), Close() calling sequence.
293TEST(WASAPIAudioOutputStreamTest, OpenStartAndClose) {
294  scoped_ptr<AudioManager> audio_manager(AudioManager::Create());
295  if (!CanRunAudioTests(audio_manager.get()))
296    return;
297  AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get());
298  EXPECT_TRUE(aos->Open());
299  MockAudioSourceCallback source;
300  EXPECT_CALL(source, OnError(aos))
301      .Times(0);
302  aos->Start(&source);
303  aos->Close();
304}
305
306// Test Open(), Start(), Stop(), Close() calling sequence.
307TEST(WASAPIAudioOutputStreamTest, OpenStartStopAndClose) {
308  scoped_ptr<AudioManager> audio_manager(AudioManager::Create());
309  if (!CanRunAudioTests(audio_manager.get()))
310    return;
311  AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get());
312  EXPECT_TRUE(aos->Open());
313  MockAudioSourceCallback source;
314  EXPECT_CALL(source, OnError(aos))
315      .Times(0);
316  aos->Start(&source);
317  aos->Stop();
318  aos->Close();
319}
320
321// Test SetVolume(), GetVolume()
322TEST(WASAPIAudioOutputStreamTest, Volume) {
323  scoped_ptr<AudioManager> audio_manager(AudioManager::Create());
324  if (!CanRunAudioTests(audio_manager.get()))
325    return;
326  AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get());
327
328  // Initial volume should be full volume (1.0).
329  double volume = 0.0;
330  aos->GetVolume(&volume);
331  EXPECT_EQ(1.0, volume);
332
333  // Verify some valid volume settings.
334  aos->SetVolume(0.0);
335  aos->GetVolume(&volume);
336  EXPECT_EQ(0.0, volume);
337
338  aos->SetVolume(0.5);
339  aos->GetVolume(&volume);
340  EXPECT_EQ(0.5, volume);
341
342  aos->SetVolume(1.0);
343  aos->GetVolume(&volume);
344  EXPECT_EQ(1.0, volume);
345
346  // Ensure that invalid volume setting have no effect.
347  aos->SetVolume(1.5);
348  aos->GetVolume(&volume);
349  EXPECT_EQ(1.0, volume);
350
351  aos->SetVolume(-0.5);
352  aos->GetVolume(&volume);
353  EXPECT_EQ(1.0, volume);
354
355  aos->Close();
356}
357
358// Test some additional calling sequences.
359TEST(WASAPIAudioOutputStreamTest, MiscCallingSequences) {
360  scoped_ptr<AudioManager> audio_manager(AudioManager::Create());
361  if (!CanRunAudioTests(audio_manager.get()))
362    return;
363
364  AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get());
365  WASAPIAudioOutputStream* waos = static_cast<WASAPIAudioOutputStream*>(aos);
366
367  // Open(), Open() is a valid calling sequence (second call does nothing).
368  EXPECT_TRUE(aos->Open());
369  EXPECT_TRUE(aos->Open());
370
371  MockAudioSourceCallback source;
372
373  // Start(), Start() is a valid calling sequence (second call does nothing).
374  aos->Start(&source);
375  EXPECT_TRUE(waos->started());
376  aos->Start(&source);
377  EXPECT_TRUE(waos->started());
378
379  // Stop(), Stop() is a valid calling sequence (second call does nothing).
380  aos->Stop();
381  EXPECT_FALSE(waos->started());
382  aos->Stop();
383  EXPECT_FALSE(waos->started());
384
385  // Start(), Stop(), Start(), Stop().
386  aos->Start(&source);
387  EXPECT_TRUE(waos->started());
388  aos->Stop();
389  EXPECT_FALSE(waos->started());
390  aos->Start(&source);
391  EXPECT_TRUE(waos->started());
392  aos->Stop();
393  EXPECT_FALSE(waos->started());
394
395  aos->Close();
396}
397
398// Use preferred packet size and verify that rendering starts.
399TEST(WASAPIAudioOutputStreamTest, ValidPacketSize) {
400  scoped_ptr<AudioManager> audio_manager(AudioManager::Create());
401  if (!CanRunAudioTests(audio_manager.get()))
402    return;
403
404  MessageLoopForUI loop;
405  MockAudioSourceCallback source;
406
407  // Create default WASAPI output stream which plays out in stereo using
408  // the shared mixing rate. The default buffer size is 10ms.
409  AudioOutputStreamWrapper aosw(audio_manager.get());
410  AudioOutputStream* aos = aosw.Create();
411  EXPECT_TRUE(aos->Open());
412
413  // Derive the expected size in bytes of each packet.
414  uint32 bytes_per_packet = aosw.channels() * aosw.samples_per_packet() *
415                           (aosw.bits_per_sample() / 8);
416
417  // Set up expected minimum delay estimation.
418  AudioBuffersState state(0, bytes_per_packet);
419
420  // Wait for the first callback and verify its parameters.
421  EXPECT_CALL(source, OnMoreData(NotNull(), HasValidDelay(state)))
422      .WillOnce(DoAll(
423          QuitLoop(loop.message_loop_proxy()),
424          Return(aosw.samples_per_packet())));
425
426  aos->Start(&source);
427  loop.PostDelayedTask(FROM_HERE, MessageLoop::QuitClosure(),
428                       TestTimeouts::action_timeout());
429  loop.Run();
430  aos->Stop();
431  aos->Close();
432}
433
434// Use a non-preferred packet size and verify that Open() fails.
435TEST(WASAPIAudioOutputStreamTest, InvalidPacketSize) {
436  scoped_ptr<AudioManager> audio_manager(AudioManager::Create());
437  if (!CanRunAudioTests(audio_manager.get()))
438    return;
439
440  if (ExclusiveModeIsEnabled())
441    return;
442
443  AudioParameters preferred_params;
444  EXPECT_TRUE(SUCCEEDED(CoreAudioUtil::GetPreferredAudioParameters(
445      eRender, eConsole, &preferred_params)));
446  int too_large_packet_size = 2 * preferred_params.frames_per_buffer();
447
448  AudioOutputStreamWrapper aosw(audio_manager.get());
449  AudioOutputStream* aos = aosw.Create(too_large_packet_size);
450  EXPECT_FALSE(aos->Open());
451
452  aos->Close();
453}
454
455// This test is intended for manual tests and should only be enabled
456// when it is required to play out data from a local PCM file.
457// By default, GTest will print out YOU HAVE 1 DISABLED TEST.
458// To include disabled tests in test execution, just invoke the test program
459// with --gtest_also_run_disabled_tests or set the GTEST_ALSO_RUN_DISABLED_TESTS
460// environment variable to a value greater than 0.
461// The test files are approximately 20 seconds long.
462TEST(WASAPIAudioOutputStreamTest, DISABLED_ReadFromStereoFile) {
463  scoped_ptr<AudioManager> audio_manager(AudioManager::Create());
464  if (!CanRunAudioTests(audio_manager.get()))
465    return;
466
467  AudioOutputStreamWrapper aosw(audio_manager.get());
468  AudioOutputStream* aos = aosw.Create();
469  EXPECT_TRUE(aos->Open());
470
471  std::string file_name;
472  if (aosw.sample_rate() == 48000) {
473    file_name = kSpeechFile_16b_s_48k;
474  } else if (aosw.sample_rate() == 44100) {
475    file_name = kSpeechFile_16b_s_44k;
476  } else if (aosw.sample_rate() == 96000) {
477    // Use 48kHz file at 96kHz as well. Will sound like Donald Duck.
478    file_name = kSpeechFile_16b_s_48k;
479  } else {
480    FAIL() << "This test supports 44.1, 48kHz and 96kHz only.";
481    return;
482  }
483  ReadFromFileAudioSource file_source(file_name);
484
485  LOG(INFO) << "File name      : " << file_name.c_str();
486  LOG(INFO) << "Sample rate    : " << aosw.sample_rate();
487  LOG(INFO) << "Bits per sample: " << aosw.bits_per_sample();
488  LOG(INFO) << "#channels      : " << aosw.channels();
489  LOG(INFO) << "File size      : " << file_source.file_size();
490  LOG(INFO) << "#file segments : " << kNumFileSegments;
491  LOG(INFO) << ">> Listen to the stereo file while playing...";
492
493  for (int i = 0; i < kNumFileSegments; i++) {
494    // Each segment will start with a short (~20ms) block of zeros, hence
495    // some short glitches might be heard in this test if kNumFileSegments
496    // is larger than one. The exact length of the silence period depends on
497    // the selected sample rate.
498    aos->Start(&file_source);
499    base::PlatformThread::Sleep(
500        base::TimeDelta::FromMilliseconds(kFileDurationMs / kNumFileSegments));
501    aos->Stop();
502  }
503
504  LOG(INFO) << ">> Stereo file playout has stopped.";
505  aos->Close();
506}
507
508// Verify that we can open the output stream in exclusive mode using a
509// certain set of audio parameters and a sample rate of 48kHz.
510// The expected outcomes of each setting in this test has been derived
511// manually using log outputs (--v=1).
512TEST(WASAPIAudioOutputStreamTest, ExclusiveModeBufferSizesAt48kHz) {
513  if (!ExclusiveModeIsEnabled())
514    return;
515
516  scoped_ptr<AudioManager> audio_manager(AudioManager::Create());
517  if (!CanRunAudioTests(audio_manager.get()))
518    return;
519
520  AudioOutputStreamWrapper aosw(audio_manager.get());
521
522  // 10ms @ 48kHz shall work.
523  // Note that, this is the same size as we can use for shared-mode streaming
524  // but here the endpoint buffer delay is only 10ms instead of 20ms.
525  AudioOutputStream* aos = aosw.Create(48000, 480);
526  EXPECT_TRUE(aos->Open());
527  aos->Close();
528
529  // 5ms @ 48kHz does not work due to misalignment.
530  // This test will propose an aligned buffer size of 5.3333ms.
531  // Note that we must call Close() even is Open() fails since Close() also
532  // deletes the object and we want to create a new object in the next test.
533  aos = aosw.Create(48000, 240);
534  EXPECT_FALSE(aos->Open());
535  aos->Close();
536
537  // 5.3333ms @ 48kHz should work (see test above).
538  aos = aosw.Create(48000, 256);
539  EXPECT_TRUE(aos->Open());
540  aos->Close();
541
542  // 2.6667ms is smaller than the minimum supported size (=3ms).
543  aos = aosw.Create(48000, 128);
544  EXPECT_FALSE(aos->Open());
545  aos->Close();
546
547  // 3ms does not correspond to an aligned buffer size.
548  // This test will propose an aligned buffer size of 3.3333ms.
549  aos = aosw.Create(48000, 144);
550  EXPECT_FALSE(aos->Open());
551  aos->Close();
552
553  // 3.3333ms @ 48kHz <=> smallest possible buffer size we can use.
554  aos = aosw.Create(48000, 160);
555  EXPECT_TRUE(aos->Open());
556  aos->Close();
557}
558
559// Verify that we can open the output stream in exclusive mode using a
560// certain set of audio parameters and a sample rate of 44.1kHz.
561// The expected outcomes of each setting in this test has been derived
562// manually using log outputs (--v=1).
563TEST(WASAPIAudioOutputStreamTest, ExclusiveModeBufferSizesAt44kHz) {
564  if (!ExclusiveModeIsEnabled())
565    return;
566
567  scoped_ptr<AudioManager> audio_manager(AudioManager::Create());
568  if (!CanRunAudioTests(audio_manager.get()))
569    return;
570
571  AudioOutputStreamWrapper aosw(audio_manager.get());
572
573  // 10ms @ 44.1kHz does not work due to misalignment.
574  // This test will propose an aligned buffer size of 10.1587ms.
575  AudioOutputStream* aos = aosw.Create(44100, 441);
576  EXPECT_FALSE(aos->Open());
577  aos->Close();
578
579  // 10.1587ms @ 44.1kHz shall work (see test above).
580  aos = aosw.Create(44100, 448);
581  EXPECT_TRUE(aos->Open());
582  aos->Close();
583
584  // 5.8050ms @ 44.1 should work.
585  aos = aosw.Create(44100, 256);
586  EXPECT_TRUE(aos->Open());
587  aos->Close();
588
589  // 4.9887ms @ 44.1kHz does not work to misalignment.
590  // This test will propose an aligned buffer size of 5.0794ms.
591  // Note that we must call Close() even is Open() fails since Close() also
592  // deletes the object and we want to create a new object in the next test.
593  aos = aosw.Create(44100, 220);
594  EXPECT_FALSE(aos->Open());
595  aos->Close();
596
597  // 5.0794ms @ 44.1kHz shall work (see test above).
598  aos = aosw.Create(44100, 224);
599  EXPECT_TRUE(aos->Open());
600  aos->Close();
601
602  // 2.9025ms is smaller than the minimum supported size (=3ms).
603  aos = aosw.Create(44100, 132);
604  EXPECT_FALSE(aos->Open());
605  aos->Close();
606
607  // 3.01587ms is larger than the minimum size but is not aligned.
608  // This test will propose an aligned buffer size of 3.6281ms.
609  aos = aosw.Create(44100, 133);
610  EXPECT_FALSE(aos->Open());
611  aos->Close();
612
613  // 3.6281ms @ 44.1kHz <=> smallest possible buffer size we can use.
614  aos = aosw.Create(44100, 160);
615  EXPECT_TRUE(aos->Open());
616  aos->Close();
617}
618
619// Verify that we can open and start the output stream in exclusive mode at
620// the lowest possible delay at 48kHz.
621TEST(WASAPIAudioOutputStreamTest, ExclusiveModeMinBufferSizeAt48kHz) {
622  if (!ExclusiveModeIsEnabled())
623    return;
624
625  scoped_ptr<AudioManager> audio_manager(AudioManager::Create());
626  if (!CanRunAudioTests(audio_manager.get()))
627    return;
628
629  MessageLoopForUI loop;
630  MockAudioSourceCallback source;
631
632  // Create exclusive-mode WASAPI output stream which plays out in stereo
633  // using the minimum buffer size at 48kHz sample rate.
634  AudioOutputStreamWrapper aosw(audio_manager.get());
635  AudioOutputStream* aos = aosw.Create(48000, 160);
636  EXPECT_TRUE(aos->Open());
637
638  // Derive the expected size in bytes of each packet.
639  uint32 bytes_per_packet = aosw.channels() * aosw.samples_per_packet() *
640      (aosw.bits_per_sample() / 8);
641
642  // Set up expected minimum delay estimation.
643  AudioBuffersState state(0, bytes_per_packet);
644
645 // Wait for the first callback and verify its parameters.
646  EXPECT_CALL(source, OnMoreData(NotNull(), HasValidDelay(state)))
647      .WillOnce(DoAll(
648          QuitLoop(loop.message_loop_proxy()),
649          Return(aosw.samples_per_packet())))
650      .WillRepeatedly(Return(aosw.samples_per_packet()));
651
652  aos->Start(&source);
653  loop.PostDelayedTask(FROM_HERE, MessageLoop::QuitClosure(),
654                       TestTimeouts::action_timeout());
655  loop.Run();
656  aos->Stop();
657  aos->Close();
658}
659
660// Verify that we can open and start the output stream in exclusive mode at
661// the lowest possible delay at 44.1kHz.
662TEST(WASAPIAudioOutputStreamTest, ExclusiveModeMinBufferSizeAt44kHz) {
663  if (!ExclusiveModeIsEnabled())
664    return;
665
666  scoped_ptr<AudioManager> audio_manager(AudioManager::Create());
667  if (!CanRunAudioTests(audio_manager.get()))
668    return;
669
670  MessageLoopForUI loop;
671  MockAudioSourceCallback source;
672
673  // Create exclusive-mode WASAPI output stream which plays out in stereo
674  // using the minimum buffer size at 44.1kHz sample rate.
675  AudioOutputStreamWrapper aosw(audio_manager.get());
676  AudioOutputStream* aos = aosw.Create(44100, 160);
677  EXPECT_TRUE(aos->Open());
678
679  // Derive the expected size in bytes of each packet.
680  uint32 bytes_per_packet = aosw.channels() * aosw.samples_per_packet() *
681      (aosw.bits_per_sample() / 8);
682
683  // Set up expected minimum delay estimation.
684  AudioBuffersState state(0, bytes_per_packet);
685
686  // Wait for the first callback and verify its parameters.
687  EXPECT_CALL(source, OnMoreData(NotNull(), HasValidDelay(state)))
688    .WillOnce(DoAll(
689        QuitLoop(loop.message_loop_proxy()),
690        Return(aosw.samples_per_packet())))
691    .WillRepeatedly(Return(aosw.samples_per_packet()));
692
693  aos->Start(&source);
694  loop.PostDelayedTask(FROM_HERE, MessageLoop::QuitClosure(),
695                        TestTimeouts::action_timeout());
696  loop.Run();
697  aos->Stop();
698  aos->Close();
699}
700
701}  // namespace media
702