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
20 using ::testing::_;
21 using ::testing::AllOf;
22 using ::testing::DoAll;
23 using ::testing::Field;
24 using ::testing::Mock;
25 using ::testing::NotNull;
26 using ::testing::Return;
27 using ::testing::SetArrayArgument;
28 using media::AudioBus;
29 using media::AudioBuffersState;
30 using media::AudioInputStream;
31 using media::AudioManager;
32 using media::AudioManagerBase;
33 using media::AudioOutputDispatcher;
34 using media::AudioOutputProxy;
35 using media::AudioOutputStream;
36 using media::AudioParameters;
37 using media::FakeAudioOutputStream;
38
39 namespace {
40
41 static const int kTestCloseDelayMs = 10;
42
43 // Delay between callbacks to AudioSourceCallback::OnMoreData.
44 static const int kOnMoreDataCallbackDelayMs = 10;
45
46 // Let start run long enough for many OnMoreData callbacks to occur.
47 static const int kStartRunTimeMs = kOnMoreDataCallbackDelayMs * 10;
48
49 class MockAudioOutputStream : public AudioOutputStream {
50 public:
MockAudioOutputStream(AudioManagerBase * manager,const AudioParameters & params)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
Start(AudioSourceCallback * callback)60 void Start(AudioSourceCallback* callback) {
61 start_called_ = true;
62 fake_output_stream_->Start(callback);
63 }
64
Stop()65 void Stop() {
66 stop_called_ = true;
67 fake_output_stream_->Stop();
68 }
69
~MockAudioOutputStream()70 ~MockAudioOutputStream() {}
71
start_called()72 bool start_called() { return start_called_; }
stop_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
87 class MockAudioManager : public AudioManagerBase {
88 public:
MockAudioManager()89 MockAudioManager() : AudioManagerBase(&fake_audio_log_factory_) {}
~MockAudioManager()90 virtual ~MockAudioManager() {
91 Shutdown();
92 }
93
94 MOCK_METHOD0(HasAudioOutputDevices, bool());
95 MOCK_METHOD0(HasAudioInputDevices, bool());
96 MOCK_METHOD0(GetAudioInputDeviceModel, base::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
129 class MockAudioSourceCallback : public AudioOutputStream::AudioSourceCallback {
130 public:
OnMoreData(AudioBus * audio_bus,AudioBuffersState buffers_state)131 int OnMoreData(AudioBus* audio_bus, AudioBuffersState buffers_state) {
132 audio_bus->Zero();
133 return audio_bus->frames();
134 }
OnMoreIOData(AudioBus * source,AudioBus * dest,AudioBuffersState buffers_state)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
144 namespace media {
145
146 class AudioOutputProxyTest : public testing::Test {
147 protected:
SetUp()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
TearDown()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
InitDispatcher(base::TimeDelta close_delay)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
OnStart()175 virtual void OnStart() {}
176
manager()177 MockAudioManager& manager() {
178 return manager_;
179 }
180
WaitForCloseTimer(MockAudioOutputStream * stream)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
CloseAndWaitForCloseTimer(AudioOutputProxy * proxy,MockAudioOutputStream * stream)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.
OpenAndClose(AudioOutputDispatcher * dispatcher)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().
StartAndStop(AudioOutputDispatcher * dispatcher)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.
CloseAfterStop(AudioOutputDispatcher * dispatcher)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.
TwoStreams(AudioOutputDispatcher * dispatcher)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.
OpenFailed(AudioOutputDispatcher * dispatcher)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
CreateAndWait(AudioOutputDispatcher * dispatcher)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
OneStream_TwoPlays(AudioOutputDispatcher * dispatcher)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
TwoStreams_BothPlaying(AudioOutputDispatcher * dispatcher)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
StartFailed(AudioOutputDispatcher * dispatcher)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
423 class AudioOutputResamplerTest : public AudioOutputProxyTest {
424 public:
TearDown()425 virtual void TearDown() {
426 AudioOutputProxyTest::TearDown();
427 }
428
InitDispatcher(base::TimeDelta close_delay)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
OnStart()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
TEST_F(AudioOutputProxyTest,CreateAndClose)456 TEST_F(AudioOutputProxyTest, CreateAndClose) {
457 AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher_impl_);
458 proxy->Close();
459 }
460
TEST_F(AudioOutputResamplerTest,CreateAndClose)461 TEST_F(AudioOutputResamplerTest, CreateAndClose) {
462 AudioOutputProxy* proxy = new AudioOutputProxy(resampler_);
463 proxy->Close();
464 }
465
TEST_F(AudioOutputProxyTest,OpenAndClose)466 TEST_F(AudioOutputProxyTest, OpenAndClose) {
467 OpenAndClose(dispatcher_impl_);
468 }
469
TEST_F(AudioOutputResamplerTest,OpenAndClose)470 TEST_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.
TEST_F(AudioOutputProxyTest,CreateAndWait)476 TEST_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.
TEST_F(AudioOutputResamplerTest,CreateAndWait)482 TEST_F(AudioOutputResamplerTest, CreateAndWait) {
483 CreateAndWait(resampler_);
484 }
485
TEST_F(AudioOutputProxyTest,StartAndStop)486 TEST_F(AudioOutputProxyTest, StartAndStop) {
487 StartAndStop(dispatcher_impl_);
488 }
489
TEST_F(AudioOutputResamplerTest,StartAndStop)490 TEST_F(AudioOutputResamplerTest, StartAndStop) {
491 StartAndStop(resampler_);
492 }
493
TEST_F(AudioOutputProxyTest,CloseAfterStop)494 TEST_F(AudioOutputProxyTest, CloseAfterStop) {
495 CloseAfterStop(dispatcher_impl_);
496 }
497
TEST_F(AudioOutputResamplerTest,CloseAfterStop)498 TEST_F(AudioOutputResamplerTest, CloseAfterStop) {
499 CloseAfterStop(resampler_);
500 }
501
TEST_F(AudioOutputProxyTest,TwoStreams)502 TEST_F(AudioOutputProxyTest, TwoStreams) { TwoStreams(dispatcher_impl_); }
503
TEST_F(AudioOutputResamplerTest,TwoStreams)504 TEST_F(AudioOutputResamplerTest, TwoStreams) { TwoStreams(resampler_); }
505
506 // Two streams: verify that second stream is allocated when the first
507 // starts playing.
TEST_F(AudioOutputProxyTest,OneStream_TwoPlays)508 TEST_F(AudioOutputProxyTest, OneStream_TwoPlays) {
509 OneStream_TwoPlays(dispatcher_impl_);
510 }
511
TEST_F(AudioOutputResamplerTest,OneStream_TwoPlays)512 TEST_F(AudioOutputResamplerTest, OneStream_TwoPlays) {
513 OneStream_TwoPlays(resampler_);
514 }
515
516 // Two streams, both are playing. Dispatcher should not open a third stream.
TEST_F(AudioOutputProxyTest,TwoStreams_BothPlaying)517 TEST_F(AudioOutputProxyTest, TwoStreams_BothPlaying) {
518 TwoStreams_BothPlaying(dispatcher_impl_);
519 }
520
TEST_F(AudioOutputResamplerTest,TwoStreams_BothPlaying)521 TEST_F(AudioOutputResamplerTest, TwoStreams_BothPlaying) {
522 TwoStreams_BothPlaying(resampler_);
523 }
524
TEST_F(AudioOutputProxyTest,OpenFailed)525 TEST_F(AudioOutputProxyTest, OpenFailed) { OpenFailed(dispatcher_impl_); }
526
527 // Start() method failed.
TEST_F(AudioOutputProxyTest,StartFailed)528 TEST_F(AudioOutputProxyTest, StartFailed) {
529 StartFailed(dispatcher_impl_);
530 }
531
TEST_F(AudioOutputResamplerTest,StartFailed)532 TEST_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.
TEST_F(AudioOutputResamplerTest,LowLatencyCreateFailedFallback)536 TEST_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.
TEST_F(AudioOutputResamplerTest,LowLatencyOpenFailedFallback)552 TEST_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.
TEST_F(AudioOutputResamplerTest,HighLatencyFallbackFailed)573 TEST_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.
TEST_F(AudioOutputResamplerTest,AllFallbackFailed)608 TEST_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
TEST_F(AudioOutputResamplerTest,LowLatencyOpenEventuallyFails)627 TEST_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.
TEST_F(AudioOutputResamplerTest,WedgeFix)682 TEST_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