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