audio_output_controller_unittest.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
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 "base/basictypes.h" 6#include "base/bind.h" 7#include "base/environment.h" 8#include "base/logging.h" 9#include "base/memory/ref_counted.h" 10#include "base/memory/scoped_ptr.h" 11#include "base/message_loop.h" 12#include "base/synchronization/waitable_event.h" 13#include "media/audio/audio_output_controller.h" 14#include "media/audio/audio_parameters.h" 15#include "media/base/audio_bus.h" 16#include "testing/gmock/include/gmock/gmock.h" 17#include "testing/gtest/include/gtest/gtest.h" 18 19using ::testing::_; 20using ::testing::AtLeast; 21using ::testing::DoAll; 22using ::testing::Invoke; 23using ::testing::NotNull; 24using ::testing::Return; 25 26namespace media { 27 28static const int kSampleRate = AudioParameters::kAudioCDSampleRate; 29static const int kBitsPerSample = 16; 30static const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_STEREO; 31static const int kSamplesPerPacket = kSampleRate / 100; 32static const int kHardwareBufferSize = kSamplesPerPacket * 33 ChannelLayoutToChannelCount(kChannelLayout) * kBitsPerSample / 8; 34static const double kTestVolume = 0.25; 35 36class MockAudioOutputControllerEventHandler 37 : public AudioOutputController::EventHandler { 38 public: 39 MockAudioOutputControllerEventHandler() {} 40 41 MOCK_METHOD0(OnCreated, void()); 42 MOCK_METHOD0(OnPlaying, void()); 43 MOCK_METHOD1(OnAudible, void(bool is_audible)); 44 MOCK_METHOD0(OnPaused, void()); 45 MOCK_METHOD0(OnError, void()); 46 MOCK_METHOD2(OnDeviceChange, void(int new_buffer_size, int new_sample_rate)); 47 48 private: 49 DISALLOW_COPY_AND_ASSIGN(MockAudioOutputControllerEventHandler); 50}; 51 52class MockAudioOutputControllerSyncReader 53 : public AudioOutputController::SyncReader { 54 public: 55 MockAudioOutputControllerSyncReader() {} 56 57 MOCK_METHOD1(UpdatePendingBytes, void(uint32 bytes)); 58 MOCK_METHOD2(Read, int(AudioBus* source, AudioBus* dest)); 59 MOCK_METHOD0(Close, void()); 60 MOCK_METHOD0(DataReady, bool()); 61 62 private: 63 DISALLOW_COPY_AND_ASSIGN(MockAudioOutputControllerSyncReader); 64}; 65 66class MockAudioOutputStream : public AudioOutputStream { 67 public: 68 MOCK_METHOD0(Open, bool()); 69 MOCK_METHOD1(Start, void(AudioSourceCallback* callback)); 70 MOCK_METHOD0(Stop, void()); 71 MOCK_METHOD1(SetVolume, void(double volume)); 72 MOCK_METHOD1(GetVolume, void(double* volume)); 73 MOCK_METHOD0(Close, void()); 74 75 // Set/get the callback passed to Start(). 76 AudioSourceCallback* callback() const { return callback_; } 77 void SetCallback(AudioSourceCallback* asc) { callback_ = asc; } 78 79 private: 80 AudioSourceCallback* callback_; 81}; 82 83ACTION_P(SignalEvent, event) { 84 event->Signal(); 85} 86 87static const float kBufferNonZeroData = 1.0f; 88ACTION(PopulateBuffer) { 89 arg1->Zero(); 90 // Note: To confirm the buffer will be populated in these tests, it's 91 // sufficient that only the first float in channel 0 is set to the value. 92 arg1->channel(0)[0] = kBufferNonZeroData; 93} 94 95class AudioOutputControllerTest : public testing::Test { 96 public: 97 AudioOutputControllerTest() 98 : audio_manager_(AudioManager::Create()), 99 create_event_(false, false), 100 play_event_(false, false), 101 read_event_(false, false), 102 pause_event_(false, false) { 103 } 104 105 virtual ~AudioOutputControllerTest() { 106 } 107 108 protected: 109 void Create(int samples_per_packet) { 110 EXPECT_FALSE(create_event_.IsSignaled()); 111 EXPECT_FALSE(play_event_.IsSignaled()); 112 EXPECT_FALSE(read_event_.IsSignaled()); 113 EXPECT_FALSE(pause_event_.IsSignaled()); 114 115 params_ = AudioParameters( 116 AudioParameters::AUDIO_FAKE, kChannelLayout, 117 kSampleRate, kBitsPerSample, samples_per_packet); 118 119 if (params_.IsValid()) { 120 EXPECT_CALL(mock_event_handler_, OnCreated()) 121 .WillOnce(SignalEvent(&create_event_)); 122 } 123 124 controller_ = AudioOutputController::Create( 125 audio_manager_.get(), &mock_event_handler_, params_, 126 &mock_sync_reader_); 127 if (controller_) 128 controller_->SetVolume(kTestVolume); 129 130 EXPECT_EQ(params_.IsValid(), controller_ != NULL); 131 } 132 133 void Play() { 134 // Expect the event handler to receive one OnPlaying() call and one or more 135 // OnAudible() calls. 136 EXPECT_CALL(mock_event_handler_, OnPlaying()) 137 .WillOnce(SignalEvent(&play_event_)); 138 EXPECT_CALL(mock_event_handler_, OnAudible(_)) 139 .Times(AtLeast(1)); 140 141 // During playback, the mock pretends to provide audio data rendered and 142 // sent from the render process. 143 EXPECT_CALL(mock_sync_reader_, UpdatePendingBytes(_)) 144 .Times(AtLeast(1)); 145 EXPECT_CALL(mock_sync_reader_, Read(_, _)) 146 .WillRepeatedly(DoAll(PopulateBuffer(), 147 SignalEvent(&read_event_), 148 Return(params_.frames_per_buffer()))); 149 EXPECT_CALL(mock_sync_reader_, DataReady()) 150 .WillRepeatedly(Return(true)); 151 152 controller_->Play(); 153 } 154 155 void Pause() { 156 // Expect the event handler to receive one OnPaused() call. 157 EXPECT_CALL(mock_event_handler_, OnPaused()) 158 .WillOnce(SignalEvent(&pause_event_)); 159 160 controller_->Pause(); 161 } 162 163 void ChangeDevice() { 164 // Expect the event handler to receive one OnPaying() call and no OnPaused() 165 // call. 166 EXPECT_CALL(mock_event_handler_, OnPlaying()) 167 .WillOnce(SignalEvent(&play_event_)); 168 EXPECT_CALL(mock_event_handler_, OnPaused()) 169 .Times(0); 170 171 // Simulate a device change event to AudioOutputController from the 172 // AudioManager. 173 audio_manager_->GetMessageLoop()->PostTask( 174 FROM_HERE, 175 base::Bind(&AudioOutputController::OnDeviceChange, controller_)); 176 } 177 178 void Divert(bool was_playing, int num_times_to_be_started) { 179 if (was_playing) { 180 // Expect the handler to receive one OnPlaying() call as a result of the 181 // stream switching. 182 EXPECT_CALL(mock_event_handler_, OnPlaying()) 183 .WillOnce(SignalEvent(&play_event_)); 184 } 185 186 EXPECT_CALL(mock_stream_, Open()) 187 .WillOnce(Return(true)); 188 EXPECT_CALL(mock_stream_, SetVolume(kTestVolume)); 189 if (num_times_to_be_started > 0) { 190 EXPECT_CALL(mock_stream_, Start(NotNull())) 191 .Times(num_times_to_be_started) 192 .WillRepeatedly( 193 Invoke(&mock_stream_, &MockAudioOutputStream::SetCallback)); 194 EXPECT_CALL(mock_stream_, Stop()) 195 .Times(num_times_to_be_started); 196 } 197 198 controller_->StartDiverting(&mock_stream_); 199 } 200 201 void ReadDivertedAudioData() { 202 scoped_ptr<AudioBus> dest = AudioBus::Create(params_); 203 ASSERT_TRUE(!!mock_stream_.callback()); 204 const int frames_read = 205 mock_stream_.callback()->OnMoreData(dest.get(), AudioBuffersState()); 206 EXPECT_LT(0, frames_read); 207 EXPECT_EQ(kBufferNonZeroData, dest->channel(0)[0]); 208 } 209 210 void Revert(bool was_playing) { 211 if (was_playing) { 212 // Expect the handler to receive one OnPlaying() call as a result of the 213 // stream switching back. 214 EXPECT_CALL(mock_event_handler_, OnPlaying()) 215 .WillOnce(SignalEvent(&play_event_)); 216 } 217 218 EXPECT_CALL(mock_stream_, Close()); 219 220 controller_->StopDiverting(); 221 } 222 223 void Close() { 224 EXPECT_CALL(mock_sync_reader_, Close()); 225 226 controller_->Close(base::MessageLoop::QuitClosure()); 227 base::MessageLoop::current()->Run(); 228 } 229 230 // These help make test sequences more readable. 231 void DivertNeverPlaying() { Divert(false, 0); } 232 void DivertWillEventuallyBeTwicePlayed() { Divert(false, 2); } 233 void DivertWhilePlaying() { Divert(true, 1); } 234 void RevertWasNotPlaying() { Revert(false); } 235 void RevertWhilePlaying() { Revert(true); } 236 237 // These synchronize the main thread with key events taking place on other 238 // threads. 239 void WaitForCreate() { create_event_.Wait(); } 240 void WaitForPlay() { play_event_.Wait(); } 241 void WaitForReads() { 242 // Note: Arbitrarily chosen, but more iterations causes tests to take 243 // significantly more time. 244 static const int kNumIterations = 3; 245 for (int i = 0; i < kNumIterations; ++i) { 246 read_event_.Wait(); 247 } 248 } 249 void WaitForPause() { pause_event_.Wait(); } 250 251 private: 252 base::MessageLoopForIO message_loop_; 253 scoped_ptr<AudioManager> audio_manager_; 254 MockAudioOutputControllerEventHandler mock_event_handler_; 255 MockAudioOutputControllerSyncReader mock_sync_reader_; 256 MockAudioOutputStream mock_stream_; 257 base::WaitableEvent create_event_; 258 base::WaitableEvent play_event_; 259 base::WaitableEvent read_event_; 260 base::WaitableEvent pause_event_; 261 AudioParameters params_; 262 scoped_refptr<AudioOutputController> controller_; 263 264 DISALLOW_COPY_AND_ASSIGN(AudioOutputControllerTest); 265}; 266 267TEST_F(AudioOutputControllerTest, CreateAndClose) { 268 Create(kSamplesPerPacket); 269 Close(); 270} 271 272TEST_F(AudioOutputControllerTest, HardwareBufferTooLarge) { 273 Create(kSamplesPerPacket * 1000); 274} 275 276TEST_F(AudioOutputControllerTest, PlayAndClose) { 277 Create(kSamplesPerPacket); 278 WaitForCreate(); 279 Play(); 280 WaitForPlay(); 281 WaitForReads(); 282 Close(); 283} 284 285TEST_F(AudioOutputControllerTest, PlayPauseClose) { 286 Create(kSamplesPerPacket); 287 WaitForCreate(); 288 Play(); 289 WaitForPlay(); 290 WaitForReads(); 291 Pause(); 292 WaitForPause(); 293 Close(); 294} 295 296TEST_F(AudioOutputControllerTest, PlayPausePlayClose) { 297 Create(kSamplesPerPacket); 298 WaitForCreate(); 299 Play(); 300 WaitForPlay(); 301 WaitForReads(); 302 Pause(); 303 WaitForPause(); 304 Play(); 305 WaitForPlay(); 306 Close(); 307} 308 309TEST_F(AudioOutputControllerTest, PlayDeviceChangeClose) { 310 Create(kSamplesPerPacket); 311 WaitForCreate(); 312 Play(); 313 WaitForPlay(); 314 WaitForReads(); 315 ChangeDevice(); 316 WaitForPlay(); 317 WaitForReads(); 318 Close(); 319} 320 321TEST_F(AudioOutputControllerTest, PlayDivertRevertClose) { 322 Create(kSamplesPerPacket); 323 WaitForCreate(); 324 Play(); 325 WaitForPlay(); 326 WaitForReads(); 327 DivertWhilePlaying(); 328 WaitForPlay(); 329 ReadDivertedAudioData(); 330 RevertWhilePlaying(); 331 WaitForPlay(); 332 WaitForReads(); 333 Close(); 334} 335 336TEST_F(AudioOutputControllerTest, PlayDivertRevertDivertRevertClose) { 337 Create(kSamplesPerPacket); 338 WaitForCreate(); 339 Play(); 340 WaitForPlay(); 341 WaitForReads(); 342 DivertWhilePlaying(); 343 WaitForPlay(); 344 ReadDivertedAudioData(); 345 RevertWhilePlaying(); 346 WaitForPlay(); 347 WaitForReads(); 348 DivertWhilePlaying(); 349 WaitForPlay(); 350 ReadDivertedAudioData(); 351 RevertWhilePlaying(); 352 WaitForPlay(); 353 WaitForReads(); 354 Close(); 355} 356 357TEST_F(AudioOutputControllerTest, DivertPlayPausePlayRevertClose) { 358 Create(kSamplesPerPacket); 359 WaitForCreate(); 360 DivertWillEventuallyBeTwicePlayed(); 361 Play(); 362 WaitForPlay(); 363 ReadDivertedAudioData(); 364 Pause(); 365 WaitForPause(); 366 Play(); 367 WaitForPlay(); 368 ReadDivertedAudioData(); 369 RevertWhilePlaying(); 370 WaitForPlay(); 371 WaitForReads(); 372 Close(); 373} 374 375TEST_F(AudioOutputControllerTest, DivertRevertClose) { 376 Create(kSamplesPerPacket); 377 WaitForCreate(); 378 DivertNeverPlaying(); 379 RevertWasNotPlaying(); 380 Close(); 381} 382 383} // namespace media 384