audio_output_proxy_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 <string>
6
7#include "base/message_loop/message_loop.h"
8#include "base/message_loop/message_loop_proxy.h"
9#include "base/run_loop.h"
10#include "media/audio/audio_manager.h"
11#include "media/audio/audio_manager_base.h"
12#include "media/audio/audio_output_dispatcher_impl.h"
13#include "media/audio/audio_output_proxy.h"
14#include "media/audio/audio_output_resampler.h"
15#include "media/audio/fake_audio_log_factory.h"
16#include "media/audio/fake_audio_output_stream.h"
17#include "testing/gmock/include/gmock/gmock.h"
18#include "testing/gtest/include/gtest/gtest.h"
19
20using ::testing::_;
21using ::testing::AllOf;
22using ::testing::DoAll;
23using ::testing::Field;
24using ::testing::Mock;
25using ::testing::NotNull;
26using ::testing::Return;
27using ::testing::SetArrayArgument;
28using media::AudioBus;
29using media::AudioBuffersState;
30using media::AudioInputStream;
31using media::AudioManager;
32using media::AudioManagerBase;
33using media::AudioOutputDispatcher;
34using media::AudioOutputProxy;
35using media::AudioOutputStream;
36using media::AudioParameters;
37using media::FakeAudioOutputStream;
38
39namespace {
40
41static const int kTestCloseDelayMs = 10;
42
43// Delay between callbacks to AudioSourceCallback::OnMoreData.
44static const int kOnMoreDataCallbackDelayMs = 10;
45
46// Let start run long enough for many OnMoreData callbacks to occur.
47static const int kStartRunTimeMs = kOnMoreDataCallbackDelayMs * 10;
48
49class MockAudioOutputStream : public AudioOutputStream {
50 public:
51  MockAudioOutputStream(AudioManagerBase* manager,
52                        const AudioParameters& params)
53      : start_called_(false),
54        stop_called_(false),
55        params_(params),
56        fake_output_stream_(
57            FakeAudioOutputStream::MakeFakeStream(manager, params_)) {
58  }
59
60  void Start(AudioSourceCallback* callback) {
61    start_called_ = true;
62    fake_output_stream_->Start(callback);
63  }
64
65  void Stop() {
66    stop_called_ = true;
67    fake_output_stream_->Stop();
68  }
69
70  ~MockAudioOutputStream() {}
71
72  bool start_called() { return start_called_; }
73  bool stop_called() { return stop_called_; }
74
75  MOCK_METHOD0(Open, bool());
76  MOCK_METHOD1(SetVolume, void(double volume));
77  MOCK_METHOD1(GetVolume, void(double* volume));
78  MOCK_METHOD0(Close, void());
79
80 private:
81  bool start_called_;
82  bool stop_called_;
83  AudioParameters params_;
84  scoped_ptr<AudioOutputStream> fake_output_stream_;
85};
86
87class MockAudioManager : public AudioManagerBase {
88 public:
89  MockAudioManager() : AudioManagerBase(&fake_audio_log_factory_) {}
90  virtual ~MockAudioManager() {
91    Shutdown();
92  }
93
94  MOCK_METHOD0(HasAudioOutputDevices, bool());
95  MOCK_METHOD0(HasAudioInputDevices, bool());
96  MOCK_METHOD0(GetAudioInputDeviceModel, string16());
97  MOCK_METHOD3(MakeAudioOutputStream, AudioOutputStream*(
98      const AudioParameters& params,
99      const std::string& device_id,
100      const std::string& input_device_id));
101  MOCK_METHOD3(MakeAudioOutputStreamProxy, AudioOutputStream*(
102      const AudioParameters& params,
103      const std::string& device_id,
104      const std::string& input_device_id));
105  MOCK_METHOD2(MakeAudioInputStream, AudioInputStream*(
106      const AudioParameters& params, const std::string& device_id));
107  MOCK_METHOD0(ShowAudioInputSettings, void());
108  MOCK_METHOD0(GetMessageLoop, scoped_refptr<base::MessageLoopProxy>());
109  MOCK_METHOD0(GetWorkerLoop, scoped_refptr<base::MessageLoopProxy>());
110  MOCK_METHOD1(GetAudioInputDeviceNames, void(
111      media::AudioDeviceNames* device_name));
112
113  MOCK_METHOD1(MakeLinearOutputStream, AudioOutputStream*(
114      const AudioParameters& params));
115  MOCK_METHOD3(MakeLowLatencyOutputStream, AudioOutputStream*(
116      const AudioParameters& params, const std::string& device_id,
117      const std::string& input_device_id));
118  MOCK_METHOD2(MakeLinearInputStream, AudioInputStream*(
119      const AudioParameters& params, const std::string& device_id));
120  MOCK_METHOD2(MakeLowLatencyInputStream, AudioInputStream*(
121      const AudioParameters& params, const std::string& device_id));
122  MOCK_METHOD2(GetPreferredOutputStreamParameters, AudioParameters(
123      const std::string& device_id, const AudioParameters& params));
124
125 private:
126  media::FakeAudioLogFactory fake_audio_log_factory_;
127};
128
129class MockAudioSourceCallback : public AudioOutputStream::AudioSourceCallback {
130 public:
131  int OnMoreData(AudioBus* audio_bus, AudioBuffersState buffers_state) {
132    audio_bus->Zero();
133    return audio_bus->frames();
134  }
135  int OnMoreIOData(AudioBus* source, AudioBus* dest,
136                   AudioBuffersState buffers_state) {
137    return OnMoreData(dest, buffers_state);
138  }
139  MOCK_METHOD1(OnError, void(AudioOutputStream* stream));
140};
141
142}  // namespace
143
144namespace media {
145
146class AudioOutputProxyTest : public testing::Test {
147 protected:
148  virtual void SetUp() {
149    EXPECT_CALL(manager_, GetMessageLoop())
150        .WillRepeatedly(Return(message_loop_.message_loop_proxy()));
151    EXPECT_CALL(manager_, GetWorkerLoop())
152        .WillRepeatedly(Return(message_loop_.message_loop_proxy()));
153    // Use a low sample rate and large buffer size when testing otherwise the
154    // FakeAudioOutputStream will keep the message loop busy indefinitely; i.e.,
155    // RunUntilIdle() will never terminate.
156    params_ = AudioParameters(AudioParameters::AUDIO_PCM_LINEAR,
157                              CHANNEL_LAYOUT_STEREO, 8000, 16, 2048);
158    InitDispatcher(base::TimeDelta::FromMilliseconds(kTestCloseDelayMs));
159  }
160
161  virtual void TearDown() {
162    // This is necessary to free all proxy objects that have been
163    // closed by the test.
164    message_loop_.RunUntilIdle();
165  }
166
167  virtual void InitDispatcher(base::TimeDelta close_delay) {
168    dispatcher_impl_ = new AudioOutputDispatcherImpl(&manager(),
169                                                     params_,
170                                                     std::string(),
171                                                     std::string(),
172                                                     close_delay);
173  }
174
175  virtual void OnStart() {}
176
177  MockAudioManager& manager() {
178    return manager_;
179  }
180
181  void WaitForCloseTimer(MockAudioOutputStream* stream) {
182    base::RunLoop run_loop;
183    EXPECT_CALL(*stream, Close())
184        .WillOnce(testing::InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
185    run_loop.Run();
186  }
187
188  void CloseAndWaitForCloseTimer(AudioOutputProxy* proxy,
189                                 MockAudioOutputStream* stream) {
190    // Close the stream and verify it doesn't happen immediately.
191    proxy->Close();
192    Mock::VerifyAndClear(stream);
193
194    // Wait for the actual close event to come from the close timer.
195    WaitForCloseTimer(stream);
196  }
197
198  // Basic Open() and Close() test.
199  void OpenAndClose(AudioOutputDispatcher* dispatcher) {
200    MockAudioOutputStream stream(&manager_, params_);
201
202    EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _))
203        .WillOnce(Return(&stream));
204    EXPECT_CALL(stream, Open())
205        .WillOnce(Return(true));
206
207    AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher);
208    EXPECT_TRUE(proxy->Open());
209    CloseAndWaitForCloseTimer(proxy, &stream);
210  }
211
212  // Creates a stream, and then calls Start() and Stop().
213  void StartAndStop(AudioOutputDispatcher* dispatcher) {
214    MockAudioOutputStream stream(&manager_, params_);
215
216    EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _))
217        .WillOnce(Return(&stream));
218    EXPECT_CALL(stream, Open())
219        .WillOnce(Return(true));
220    EXPECT_CALL(stream, SetVolume(_))
221        .Times(1);
222
223    AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher);
224    EXPECT_TRUE(proxy->Open());
225
226    proxy->Start(&callback_);
227    OnStart();
228    proxy->Stop();
229
230    CloseAndWaitForCloseTimer(proxy, &stream);
231    EXPECT_TRUE(stream.stop_called());
232    EXPECT_TRUE(stream.start_called());
233  }
234
235  // Verify that the stream is closed after Stop() is called.
236  void CloseAfterStop(AudioOutputDispatcher* dispatcher) {
237    MockAudioOutputStream stream(&manager_, params_);
238
239    EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _))
240        .WillOnce(Return(&stream));
241    EXPECT_CALL(stream, Open())
242        .WillOnce(Return(true));
243    EXPECT_CALL(stream, SetVolume(_))
244        .Times(1);
245
246    AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher);
247    EXPECT_TRUE(proxy->Open());
248
249    proxy->Start(&callback_);
250    OnStart();
251    proxy->Stop();
252
253    // Wait for the close timer to fire after StopStream().
254    WaitForCloseTimer(&stream);
255    proxy->Close();
256    EXPECT_TRUE(stream.stop_called());
257    EXPECT_TRUE(stream.start_called());
258  }
259
260  // Create two streams, but don't start them.  Only one device must be opened.
261  void TwoStreams(AudioOutputDispatcher* dispatcher) {
262    MockAudioOutputStream stream(&manager_, params_);
263
264    EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _))
265        .WillOnce(Return(&stream));
266    EXPECT_CALL(stream, Open())
267        .WillOnce(Return(true));
268
269    AudioOutputProxy* proxy1 = new AudioOutputProxy(dispatcher);
270    AudioOutputProxy* proxy2 = new AudioOutputProxy(dispatcher);
271    EXPECT_TRUE(proxy1->Open());
272    EXPECT_TRUE(proxy2->Open());
273    proxy1->Close();
274    CloseAndWaitForCloseTimer(proxy2, &stream);
275    EXPECT_FALSE(stream.stop_called());
276    EXPECT_FALSE(stream.start_called());
277  }
278
279  // Open() method failed.
280  void OpenFailed(AudioOutputDispatcher* dispatcher) {
281    MockAudioOutputStream stream(&manager_, params_);
282
283    EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _))
284        .WillOnce(Return(&stream));
285    EXPECT_CALL(stream, Open())
286        .WillOnce(Return(false));
287    EXPECT_CALL(stream, Close())
288        .Times(1);
289
290    AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher);
291    EXPECT_FALSE(proxy->Open());
292    proxy->Close();
293    EXPECT_FALSE(stream.stop_called());
294    EXPECT_FALSE(stream.start_called());
295  }
296
297  void CreateAndWait(AudioOutputDispatcher* dispatcher) {
298    MockAudioOutputStream stream(&manager_, params_);
299
300    EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _))
301        .WillOnce(Return(&stream));
302    EXPECT_CALL(stream, Open())
303        .WillOnce(Return(true));
304
305    AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher);
306    EXPECT_TRUE(proxy->Open());
307
308    WaitForCloseTimer(&stream);
309    proxy->Close();
310    EXPECT_FALSE(stream.stop_called());
311    EXPECT_FALSE(stream.start_called());
312  }
313
314  void OneStream_TwoPlays(AudioOutputDispatcher* dispatcher) {
315    MockAudioOutputStream stream(&manager_, params_);
316
317    EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _))
318        .WillOnce(Return(&stream));
319
320    EXPECT_CALL(stream, Open())
321        .WillOnce(Return(true));
322    EXPECT_CALL(stream, SetVolume(_))
323        .Times(2);
324
325    AudioOutputProxy* proxy1 = new AudioOutputProxy(dispatcher);
326    EXPECT_TRUE(proxy1->Open());
327
328    proxy1->Start(&callback_);
329    OnStart();
330    proxy1->Stop();
331
332    // The stream should now be idle and get reused by |proxy2|.
333    AudioOutputProxy* proxy2 = new AudioOutputProxy(dispatcher);
334    EXPECT_TRUE(proxy2->Open());
335    proxy2->Start(&callback_);
336    OnStart();
337    proxy2->Stop();
338
339    proxy1->Close();
340    CloseAndWaitForCloseTimer(proxy2, &stream);
341    EXPECT_TRUE(stream.stop_called());
342    EXPECT_TRUE(stream.start_called());
343  }
344
345  void TwoStreams_BothPlaying(AudioOutputDispatcher* dispatcher) {
346    MockAudioOutputStream stream1(&manager_, params_);
347    MockAudioOutputStream stream2(&manager_, params_);
348
349    EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _))
350        .WillOnce(Return(&stream1))
351        .WillOnce(Return(&stream2));
352
353    EXPECT_CALL(stream1, Open())
354        .WillOnce(Return(true));
355    EXPECT_CALL(stream1, SetVolume(_))
356        .Times(1);
357
358    EXPECT_CALL(stream2, Open())
359        .WillOnce(Return(true));
360    EXPECT_CALL(stream2, SetVolume(_))
361        .Times(1);
362
363    AudioOutputProxy* proxy1 = new AudioOutputProxy(dispatcher);
364    AudioOutputProxy* proxy2 = new AudioOutputProxy(dispatcher);
365    EXPECT_TRUE(proxy1->Open());
366    EXPECT_TRUE(proxy2->Open());
367
368    proxy1->Start(&callback_);
369    proxy2->Start(&callback_);
370    OnStart();
371    proxy1->Stop();
372    CloseAndWaitForCloseTimer(proxy1, &stream1);
373
374    proxy2->Stop();
375    CloseAndWaitForCloseTimer(proxy2, &stream2);
376
377    EXPECT_TRUE(stream1.stop_called());
378    EXPECT_TRUE(stream1.start_called());
379    EXPECT_TRUE(stream2.stop_called());
380    EXPECT_TRUE(stream2.start_called());
381  }
382
383  void StartFailed(AudioOutputDispatcher* dispatcher) {
384    MockAudioOutputStream stream(&manager_, params_);
385
386    EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _))
387        .WillOnce(Return(&stream));
388    EXPECT_CALL(stream, Open())
389        .WillOnce(Return(true));
390
391    AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher);
392    EXPECT_TRUE(proxy->Open());
393
394    WaitForCloseTimer(&stream);
395
396    // |stream| is closed at this point. Start() should reopen it again.
397    EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _))
398        .Times(2)
399        .WillRepeatedly(Return(reinterpret_cast<AudioOutputStream*>(NULL)));
400
401    EXPECT_CALL(callback_, OnError(_))
402        .Times(2);
403
404    proxy->Start(&callback_);
405
406    // Double Start() in the error case should be allowed since it's possible a
407    // callback may not have had time to process the OnError() in between.
408    proxy->Stop();
409    proxy->Start(&callback_);
410
411    Mock::VerifyAndClear(&callback_);
412
413    proxy->Close();
414  }
415
416  base::MessageLoop message_loop_;
417  scoped_refptr<AudioOutputDispatcherImpl> dispatcher_impl_;
418  MockAudioManager manager_;
419  MockAudioSourceCallback callback_;
420  AudioParameters params_;
421};
422
423class AudioOutputResamplerTest : public AudioOutputProxyTest {
424 public:
425  virtual void TearDown() {
426    AudioOutputProxyTest::TearDown();
427  }
428
429  virtual void InitDispatcher(base::TimeDelta close_delay) OVERRIDE {
430    // Use a low sample rate and large buffer size when testing otherwise the
431    // FakeAudioOutputStream will keep the message loop busy indefinitely; i.e.,
432    // RunUntilIdle() will never terminate.
433    resampler_params_ = AudioParameters(
434        AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO,
435        16000, 16, 1024);
436    resampler_ = new AudioOutputResampler(
437        &manager(), params_, resampler_params_, std::string(), std::string(),
438        close_delay);
439  }
440
441  virtual void OnStart() OVERRIDE {
442    // Let Start() run for a bit.
443    base::RunLoop run_loop;
444    message_loop_.PostDelayedTask(
445        FROM_HERE,
446        run_loop.QuitClosure(),
447        base::TimeDelta::FromMilliseconds(kStartRunTimeMs));
448    run_loop.Run();
449  }
450
451 protected:
452  AudioParameters resampler_params_;
453  scoped_refptr<AudioOutputResampler> resampler_;
454};
455
456TEST_F(AudioOutputProxyTest, CreateAndClose) {
457  AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher_impl_);
458  proxy->Close();
459}
460
461TEST_F(AudioOutputResamplerTest, CreateAndClose) {
462  AudioOutputProxy* proxy = new AudioOutputProxy(resampler_);
463  proxy->Close();
464}
465
466TEST_F(AudioOutputProxyTest, OpenAndClose) {
467  OpenAndClose(dispatcher_impl_);
468}
469
470TEST_F(AudioOutputResamplerTest, OpenAndClose) {
471  OpenAndClose(resampler_);
472}
473
474// Create a stream, and verify that it is closed after kTestCloseDelayMs.
475// if it doesn't start playing.
476TEST_F(AudioOutputProxyTest, CreateAndWait) {
477  CreateAndWait(dispatcher_impl_);
478}
479
480// Create a stream, and verify that it is closed after kTestCloseDelayMs.
481// if it doesn't start playing.
482TEST_F(AudioOutputResamplerTest, CreateAndWait) {
483  CreateAndWait(resampler_);
484}
485
486TEST_F(AudioOutputProxyTest, StartAndStop) {
487  StartAndStop(dispatcher_impl_);
488}
489
490TEST_F(AudioOutputResamplerTest, StartAndStop) {
491  StartAndStop(resampler_);
492}
493
494TEST_F(AudioOutputProxyTest, CloseAfterStop) {
495  CloseAfterStop(dispatcher_impl_);
496}
497
498TEST_F(AudioOutputResamplerTest, CloseAfterStop) {
499  CloseAfterStop(resampler_);
500}
501
502TEST_F(AudioOutputProxyTest, TwoStreams) { TwoStreams(dispatcher_impl_); }
503
504TEST_F(AudioOutputResamplerTest, TwoStreams) { TwoStreams(resampler_); }
505
506// Two streams: verify that second stream is allocated when the first
507// starts playing.
508TEST_F(AudioOutputProxyTest, OneStream_TwoPlays) {
509  OneStream_TwoPlays(dispatcher_impl_);
510}
511
512TEST_F(AudioOutputResamplerTest, OneStream_TwoPlays) {
513  OneStream_TwoPlays(resampler_);
514}
515
516// Two streams, both are playing. Dispatcher should not open a third stream.
517TEST_F(AudioOutputProxyTest, TwoStreams_BothPlaying) {
518  TwoStreams_BothPlaying(dispatcher_impl_);
519}
520
521TEST_F(AudioOutputResamplerTest, TwoStreams_BothPlaying) {
522  TwoStreams_BothPlaying(resampler_);
523}
524
525TEST_F(AudioOutputProxyTest, OpenFailed) { OpenFailed(dispatcher_impl_); }
526
527// Start() method failed.
528TEST_F(AudioOutputProxyTest, StartFailed) {
529  StartFailed(dispatcher_impl_);
530}
531
532TEST_F(AudioOutputResamplerTest, StartFailed) { StartFailed(resampler_); }
533
534// Simulate AudioOutputStream::Create() failure with a low latency stream and
535// ensure AudioOutputResampler falls back to the high latency path.
536TEST_F(AudioOutputResamplerTest, LowLatencyCreateFailedFallback) {
537  MockAudioOutputStream stream(&manager_, params_);
538  EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _))
539      .Times(2)
540      .WillOnce(Return(static_cast<AudioOutputStream*>(NULL)))
541      .WillRepeatedly(Return(&stream));
542  EXPECT_CALL(stream, Open())
543      .WillOnce(Return(true));
544
545  AudioOutputProxy* proxy = new AudioOutputProxy(resampler_);
546  EXPECT_TRUE(proxy->Open());
547  CloseAndWaitForCloseTimer(proxy, &stream);
548}
549
550// Simulate AudioOutputStream::Open() failure with a low latency stream and
551// ensure AudioOutputResampler falls back to the high latency path.
552TEST_F(AudioOutputResamplerTest, LowLatencyOpenFailedFallback) {
553  MockAudioOutputStream failed_stream(&manager_, params_);
554  MockAudioOutputStream okay_stream(&manager_, params_);
555  EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _))
556      .Times(2)
557      .WillOnce(Return(&failed_stream))
558      .WillRepeatedly(Return(&okay_stream));
559  EXPECT_CALL(failed_stream, Open())
560      .WillOnce(Return(false));
561  EXPECT_CALL(failed_stream, Close())
562      .Times(1);
563  EXPECT_CALL(okay_stream, Open())
564      .WillOnce(Return(true));
565
566  AudioOutputProxy* proxy = new AudioOutputProxy(resampler_);
567  EXPECT_TRUE(proxy->Open());
568  CloseAndWaitForCloseTimer(proxy, &okay_stream);
569}
570
571// Simulate failures to open both the low latency and the fallback high latency
572// stream and ensure AudioOutputResampler falls back to a fake stream.
573TEST_F(AudioOutputResamplerTest, HighLatencyFallbackFailed) {
574  MockAudioOutputStream okay_stream(&manager_, params_);
575
576// Only Windows has a high latency output driver that is not the same as the low
577// latency path.
578#if defined(OS_WIN)
579  static const int kFallbackCount = 2;
580#else
581  static const int kFallbackCount = 1;
582#endif
583  EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _))
584      .Times(kFallbackCount)
585      .WillRepeatedly(Return(static_cast<AudioOutputStream*>(NULL)));
586
587  // To prevent shared memory issues the sample rate and buffer size should
588  // match the input stream parameters.
589  EXPECT_CALL(manager(), MakeAudioOutputStream(AllOf(
590      testing::Property(&AudioParameters::format, AudioParameters::AUDIO_FAKE),
591      testing::Property(&AudioParameters::sample_rate, params_.sample_rate()),
592      testing::Property(
593          &AudioParameters::frames_per_buffer, params_.frames_per_buffer())),
594                         _, _))
595      .Times(1)
596      .WillOnce(Return(&okay_stream));
597  EXPECT_CALL(okay_stream, Open())
598      .WillOnce(Return(true));
599
600  AudioOutputProxy* proxy = new AudioOutputProxy(resampler_);
601  EXPECT_TRUE(proxy->Open());
602  CloseAndWaitForCloseTimer(proxy, &okay_stream);
603}
604
605// Simulate failures to open both the low latency, the fallback high latency
606// stream, and the fake audio output stream and ensure AudioOutputResampler
607// terminates normally.
608TEST_F(AudioOutputResamplerTest, AllFallbackFailed) {
609// Only Windows has a high latency output driver that is not the same as the low
610// latency path.
611#if defined(OS_WIN)
612  static const int kFallbackCount = 3;
613#else
614  static const int kFallbackCount = 2;
615#endif
616  EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _))
617      .Times(kFallbackCount)
618      .WillRepeatedly(Return(static_cast<AudioOutputStream*>(NULL)));
619
620  AudioOutputProxy* proxy = new AudioOutputProxy(resampler_);
621  EXPECT_FALSE(proxy->Open());
622  proxy->Close();
623}
624
625// Simulate an eventual OpenStream() failure; i.e. successful OpenStream() calls
626// eventually followed by one which fails; root cause of http://crbug.com/150619
627TEST_F(AudioOutputResamplerTest, LowLatencyOpenEventuallyFails) {
628  MockAudioOutputStream stream1(&manager_, params_);
629  MockAudioOutputStream stream2(&manager_, params_);
630
631  // Setup the mock such that all three streams are successfully created.
632  EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _))
633      .WillOnce(Return(&stream1))
634      .WillOnce(Return(&stream2))
635      .WillRepeatedly(Return(static_cast<AudioOutputStream*>(NULL)));
636
637  // Stream1 should be able to successfully open and start.
638  EXPECT_CALL(stream1, Open())
639      .WillOnce(Return(true));
640  EXPECT_CALL(stream1, SetVolume(_))
641      .Times(1);
642
643  // Stream2 should also be able to successfully open and start.
644  EXPECT_CALL(stream2, Open())
645      .WillOnce(Return(true));
646  EXPECT_CALL(stream2, SetVolume(_))
647      .Times(1);
648
649  // Open and start the first proxy and stream.
650  AudioOutputProxy* proxy1 = new AudioOutputProxy(resampler_);
651  EXPECT_TRUE(proxy1->Open());
652  proxy1->Start(&callback_);
653  OnStart();
654
655  // Open and start the second proxy and stream.
656  AudioOutputProxy* proxy2 = new AudioOutputProxy(resampler_);
657  EXPECT_TRUE(proxy2->Open());
658  proxy2->Start(&callback_);
659  OnStart();
660
661  // Attempt to open the third stream which should fail.
662  AudioOutputProxy* proxy3 = new AudioOutputProxy(resampler_);
663  EXPECT_FALSE(proxy3->Open());
664  proxy3->Close();
665
666  // Perform the required Stop()/Close() shutdown dance for each proxy.  Under
667  // the hood each proxy should correctly call CloseStream() if OpenStream()
668  // succeeded or not.
669  proxy2->Stop();
670  CloseAndWaitForCloseTimer(proxy2, &stream2);
671
672  proxy1->Stop();
673  CloseAndWaitForCloseTimer(proxy1, &stream1);
674
675  EXPECT_TRUE(stream1.stop_called());
676  EXPECT_TRUE(stream1.start_called());
677  EXPECT_TRUE(stream2.stop_called());
678  EXPECT_TRUE(stream2.start_called());
679}
680
681// Ensures the methods used to fix audio output wedges are working correctly.
682TEST_F(AudioOutputResamplerTest, WedgeFix) {
683  MockAudioOutputStream stream1(&manager_, params_);
684  MockAudioOutputStream stream2(&manager_, params_);
685  MockAudioOutputStream stream3(&manager_, params_);
686
687  // Setup the mock such that all three streams are successfully created.
688  EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _))
689      .WillOnce(Return(&stream1))
690      .WillOnce(Return(&stream2))
691      .WillOnce(Return(&stream3));
692
693  // Stream1 should be able to successfully open and start.
694  EXPECT_CALL(stream1, Open())
695      .WillOnce(Return(true));
696  EXPECT_CALL(stream1, SetVolume(_));
697  EXPECT_CALL(stream2, Open())
698      .WillOnce(Return(true));
699  EXPECT_CALL(stream2, SetVolume(_));
700
701  // Open and start the first proxy and stream.
702  AudioOutputProxy* proxy1 = new AudioOutputProxy(resampler_.get());
703  EXPECT_TRUE(proxy1->Open());
704  proxy1->Start(&callback_);
705  OnStart();
706
707  // Open, but do not start the second proxy.
708  AudioOutputProxy* proxy2 = new AudioOutputProxy(resampler_.get());
709  EXPECT_TRUE(proxy2->Open());
710
711  // Open, start and then stop the third proxy.
712  AudioOutputProxy* proxy3 = new AudioOutputProxy(resampler_.get());
713  EXPECT_TRUE(proxy3->Open());
714  proxy3->Start(&callback_);
715  OnStart();
716  proxy3->Stop();
717
718  // Wait for stream to timeout and shutdown.
719  WaitForCloseTimer(&stream2);
720
721  EXPECT_CALL(stream1, Close());
722  resampler_->CloseStreamsForWedgeFix();
723
724  // Don't pump the MessageLoop between CloseStreamsForWedgeFix() and
725  // RestartStreamsForWedgeFix() to simulate intended usage.  The OnStart() call
726  // will take care of necessary work.
727
728  // Stream3 should take Stream1's place after RestartStreamsForWedgeFix().  No
729  // additional streams should be opened for proxy2 and proxy3.
730  EXPECT_CALL(stream3, Open())
731      .WillOnce(Return(true));
732  EXPECT_CALL(stream3, SetVolume(_));
733
734  resampler_->RestartStreamsForWedgeFix();
735  OnStart();
736
737  // Perform the required Stop()/Close() shutdown dance for each proxy.
738  proxy3->Close();
739  proxy2->Close();
740  proxy1->Stop();
741  CloseAndWaitForCloseTimer(proxy1, &stream3);
742
743  // Wait for all of the messages to fly and then verify stream behavior.
744  EXPECT_TRUE(stream1.stop_called());
745  EXPECT_TRUE(stream1.start_called());
746  EXPECT_TRUE(stream2.stop_called());
747  EXPECT_TRUE(stream2.start_called());
748  EXPECT_TRUE(stream3.stop_called());
749  EXPECT_TRUE(stream3.start_called());
750}
751
752}  // namespace media
753