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: 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 87 class 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, 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: 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 144 namespace media { 145 146 class 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 423 class 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 456 TEST_F(AudioOutputProxyTest, CreateAndClose) { 457 AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher_impl_); 458 proxy->Close(); 459 } 460 461 TEST_F(AudioOutputResamplerTest, CreateAndClose) { 462 AudioOutputProxy* proxy = new AudioOutputProxy(resampler_); 463 proxy->Close(); 464 } 465 466 TEST_F(AudioOutputProxyTest, OpenAndClose) { 467 OpenAndClose(dispatcher_impl_); 468 } 469 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. 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. 482 TEST_F(AudioOutputResamplerTest, CreateAndWait) { 483 CreateAndWait(resampler_); 484 } 485 486 TEST_F(AudioOutputProxyTest, StartAndStop) { 487 StartAndStop(dispatcher_impl_); 488 } 489 490 TEST_F(AudioOutputResamplerTest, StartAndStop) { 491 StartAndStop(resampler_); 492 } 493 494 TEST_F(AudioOutputProxyTest, CloseAfterStop) { 495 CloseAfterStop(dispatcher_impl_); 496 } 497 498 TEST_F(AudioOutputResamplerTest, CloseAfterStop) { 499 CloseAfterStop(resampler_); 500 } 501 502 TEST_F(AudioOutputProxyTest, TwoStreams) { TwoStreams(dispatcher_impl_); } 503 504 TEST_F(AudioOutputResamplerTest, TwoStreams) { TwoStreams(resampler_); } 505 506 // Two streams: verify that second stream is allocated when the first 507 // starts playing. 508 TEST_F(AudioOutputProxyTest, OneStream_TwoPlays) { 509 OneStream_TwoPlays(dispatcher_impl_); 510 } 511 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. 517 TEST_F(AudioOutputProxyTest, TwoStreams_BothPlaying) { 518 TwoStreams_BothPlaying(dispatcher_impl_); 519 } 520 521 TEST_F(AudioOutputResamplerTest, TwoStreams_BothPlaying) { 522 TwoStreams_BothPlaying(resampler_); 523 } 524 525 TEST_F(AudioOutputProxyTest, OpenFailed) { OpenFailed(dispatcher_impl_); } 526 527 // Start() method failed. 528 TEST_F(AudioOutputProxyTest, StartFailed) { 529 StartFailed(dispatcher_impl_); 530 } 531 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. 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. 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. 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. 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 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. 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