OLD | NEW |
(Empty) | |
| 1 // Copyright 2016 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 "media/audio/restartable_audio_output_device_impl.h" |
| 6 |
| 7 #include "base/single_thread_task_runner.h" |
| 8 #include "media/audio/audio_output_device.h" |
| 9 #include "media/audio/audio_output_ipc.h" |
| 10 #include "media/audio/mock_audio_output_ipc.h" |
| 11 #include "media/audio/mock_render_callback.h" |
| 12 #include "testing/gmock/include/gmock/gmock.h" |
| 13 #include "testing/gtest/include/gtest/gtest.h" |
| 14 |
| 15 using testing::_; |
| 16 using testing::Exactly; |
| 17 using testing::InSequence; |
| 18 |
| 19 namespace media { |
| 20 |
| 21 namespace { |
| 22 |
| 23 const int kHWSampleRate = 22500; |
| 24 const int kDefaultSampleRate = 32000; |
| 25 const int kNewSampleRate = 44100; |
| 26 const char kDefaultDeviceId[] = ""; |
| 27 const char kBrokenDeviceId[] = "broken-device"; |
| 28 |
| 29 AudioParameters BuildHWParams() { |
| 30 return AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, |
| 31 CHANNEL_LAYOUT_STEREO, kHWSampleRate, 16, 512); |
| 32 } |
| 33 |
| 34 class FakeAudioOutputDevice : NON_EXPORTED_BASE(public AudioOutputDevice) { |
| 35 public: |
| 36 FakeAudioOutputDevice( |
| 37 scoped_ptr<AudioOutputIPC> ipc, |
| 38 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner, |
| 39 const std::string& device_id) |
| 40 : AudioOutputDevice(std::move(ipc), |
| 41 io_task_runner, |
| 42 0, |
| 43 std::string(), |
| 44 url::Origin()), |
| 45 device_id_(device_id), |
| 46 sample_rate_(0), |
| 47 volume_(1.0), |
| 48 initialized_(false), |
| 49 started_(false), |
| 50 playing_(false) {} |
| 51 |
| 52 MOCK_METHOD0(MockStop, void()); |
| 53 |
| 54 void Initialize(const AudioParameters& params, RenderCallback*) override { |
| 55 initialized_ = true; |
| 56 sample_rate_ = params.sample_rate(); |
| 57 } |
| 58 |
| 59 void Start() override { |
| 60 EXPECT_TRUE(initialized_); |
| 61 started_ = true; |
| 62 playing_ = true; // AudioOutputDevice plays on start. |
| 63 } |
| 64 |
| 65 void Play() override { |
| 66 EXPECT_TRUE(initialized_); |
| 67 playing_ = true; |
| 68 } |
| 69 |
| 70 void Pause() override { |
| 71 EXPECT_TRUE(initialized_); |
| 72 playing_ = false; |
| 73 } |
| 74 |
| 75 void Stop() override { |
| 76 started_ = false; |
| 77 playing_ = false; |
| 78 MockStop(); |
| 79 } |
| 80 |
| 81 bool SetVolume(double volume) override { |
| 82 EXPECT_TRUE(initialized_); |
| 83 if (device_id_ == kBrokenDeviceId) { |
| 84 volume_ = 0; |
| 85 return false; |
| 86 } |
| 87 volume_ = volume; |
| 88 return true; |
| 89 } |
| 90 |
| 91 double GetVolume() { return volume_; } |
| 92 int GetSampleRate() { return sample_rate_; } |
| 93 bool IsPlaying() { return started_ && playing_; } |
| 94 |
| 95 OutputDeviceStatus GetDeviceStatus() override { |
| 96 return device_id_ == kBrokenDeviceId ? OUTPUT_DEVICE_STATUS_ERROR_INTERNAL |
| 97 : OUTPUT_DEVICE_STATUS_OK; |
| 98 } |
| 99 |
| 100 AudioParameters GetOutputParameters() override { |
| 101 AudioParameters params = BuildHWParams(); |
| 102 if (device_id_ == kBrokenDeviceId) |
| 103 params.set_format(AudioParameters::AUDIO_FAKE); |
| 104 return params; |
| 105 } |
| 106 |
| 107 protected: |
| 108 virtual ~FakeAudioOutputDevice() {} |
| 109 |
| 110 private: |
| 111 const std::string device_id_; |
| 112 int sample_rate_; |
| 113 double volume_; |
| 114 bool initialized_; |
| 115 bool started_; |
| 116 bool playing_; |
| 117 }; |
| 118 |
| 119 } // namespace |
| 120 |
| 121 class RestartableAudioOutputDeviceImplTest : public testing::Test { |
| 122 protected: |
| 123 RestartableAudioOutputDeviceImplTest() |
| 124 : message_loop_(new base::MessageLoopForIO), |
| 125 mock_ipc_(nullptr), |
| 126 default_params_(AudioParameters::AUDIO_PCM_LINEAR, |
| 127 CHANNEL_LAYOUT_STEREO, |
| 128 kDefaultSampleRate, |
| 129 16, |
| 130 512), |
| 131 new_params_(AudioParameters::AUDIO_PCM_LINEAR, |
| 132 CHANNEL_LAYOUT_STEREO, |
| 133 kNewSampleRate, |
| 134 16, |
| 135 512) {} |
| 136 |
| 137 MOCK_METHOD0(MockCreateOutputDevice, void()); |
| 138 |
| 139 scoped_refptr<media::AudioOutputDevice> CreateOutputDevice( |
| 140 int render_frame_id, |
| 141 int session_id, |
| 142 const std::string& device_id, |
| 143 const url::Origin& security_origin) { |
| 144 mock_ipc_ = new MockAudioOutputIPC(); |
| 145 mock_output_device_ = |
| 146 new FakeAudioOutputDevice(scoped_ptr<media::AudioOutputIPC>(mock_ipc_), |
| 147 message_loop_->task_runner(), device_id); |
| 148 ; |
| 149 EXPECT_CALL(*mock_output_device_.get(), MockStop()).Times(Exactly(1)); |
| 150 MockCreateOutputDevice(); |
| 151 return mock_output_device_; |
| 152 } |
| 153 |
| 154 void PrepareSink(const std::string& device_id, int times_to_restart = 0) { |
| 155 static const int kRendererFrameId = 0; |
| 156 static const int kSessionId = 0; |
| 157 static const url::Origin kSecurityOrigin; |
| 158 EXPECT_CALL(*this, MockCreateOutputDevice()).Times(times_to_restart + 1); |
| 159 sink_ = new media::RestartableAudioOutputDeviceImpl( |
| 160 base::Bind(&RestartableAudioOutputDeviceImplTest::CreateOutputDevice, |
| 161 base::Unretained(this), kRendererFrameId, kSessionId, |
| 162 device_id, kSecurityOrigin), |
| 163 base::Bind(&BuildHWParams)); |
| 164 } |
| 165 |
| 166 void TearDown() override { |
| 167 mock_output_device_ = nullptr; |
| 168 sink_ = nullptr; |
| 169 } |
| 170 |
| 171 // Used to construct |mock_output_device_|. |
| 172 scoped_ptr<base::MessageLoopForIO> message_loop_; |
| 173 MockAudioOutputIPC* mock_ipc_; // Owned by AudioOuputDevice. |
| 174 scoped_refptr<FakeAudioOutputDevice> mock_output_device_; |
| 175 |
| 176 // Sink under test. |
| 177 scoped_refptr<media::RestartableAudioOutputDeviceImpl> sink_; |
| 178 |
| 179 // Data used for initializations. |
| 180 media::AudioParameters default_params_; |
| 181 media::AudioParameters new_params_; |
| 182 MockRenderCallback callback_; |
| 183 }; |
| 184 |
| 185 TEST_F(RestartableAudioOutputDeviceImplTest, StopNotInitializedSink) { |
| 186 PrepareSink(kDefaultDeviceId); |
| 187 EXPECT_FALSE(mock_output_device_->IsPlaying()); |
| 188 sink_->Stop(); |
| 189 } |
| 190 |
| 191 TEST_F(RestartableAudioOutputDeviceImplTest, InitializeAndStopSink) { |
| 192 PrepareSink(kDefaultDeviceId); |
| 193 sink_->Initialize(default_params_, &callback_); |
| 194 EXPECT_FALSE(mock_output_device_->IsPlaying()); |
| 195 EXPECT_EQ(OUTPUT_DEVICE_STATUS_OK, sink_->GetDeviceStatus()); |
| 196 sink_->Stop(); |
| 197 } |
| 198 |
| 199 TEST_F(RestartableAudioOutputDeviceImplTest, StartAndStopSink) { |
| 200 PrepareSink(kDefaultDeviceId); |
| 201 |
| 202 sink_->Initialize(default_params_, &callback_); |
| 203 EXPECT_EQ(OUTPUT_DEVICE_STATUS_OK, sink_->GetDeviceStatus()); |
| 204 EXPECT_FALSE(mock_output_device_->IsPlaying()); |
| 205 |
| 206 sink_->Start(); |
| 207 EXPECT_EQ(OUTPUT_DEVICE_STATUS_OK, sink_->GetDeviceStatus()); |
| 208 EXPECT_FALSE(mock_output_device_->IsPlaying()); |
| 209 |
| 210 sink_->Stop(); |
| 211 } |
| 212 |
| 213 TEST_F(RestartableAudioOutputDeviceImplTest, StartPlayAndStopSink) { |
| 214 PrepareSink(kDefaultDeviceId); |
| 215 |
| 216 sink_->Initialize(default_params_, &callback_); |
| 217 EXPECT_EQ(OUTPUT_DEVICE_STATUS_OK, sink_->GetDeviceStatus()); |
| 218 EXPECT_FALSE(mock_output_device_->IsPlaying()); |
| 219 |
| 220 sink_->Start(); |
| 221 EXPECT_FALSE(mock_output_device_->IsPlaying()); |
| 222 EXPECT_EQ(OUTPUT_DEVICE_STATUS_OK, sink_->GetDeviceStatus()); |
| 223 |
| 224 EXPECT_EQ(kDefaultSampleRate, mock_output_device_->GetSampleRate()); |
| 225 |
| 226 sink_->Play(); |
| 227 EXPECT_EQ(OUTPUT_DEVICE_STATUS_OK, sink_->GetDeviceStatus()); |
| 228 EXPECT_TRUE(mock_output_device_->IsPlaying()); |
| 229 |
| 230 sink_->Stop(); |
| 231 } |
| 232 |
| 233 TEST_F(RestartableAudioOutputDeviceImplTest, StartPauseStopSink) { |
| 234 PrepareSink(kDefaultDeviceId); |
| 235 |
| 236 sink_->Initialize(default_params_, &callback_); |
| 237 EXPECT_EQ(OUTPUT_DEVICE_STATUS_OK, sink_->GetDeviceStatus()); |
| 238 EXPECT_FALSE(mock_output_device_->IsPlaying()); |
| 239 |
| 240 sink_->Start(); |
| 241 EXPECT_EQ(OUTPUT_DEVICE_STATUS_OK, sink_->GetDeviceStatus()); |
| 242 EXPECT_FALSE(mock_output_device_->IsPlaying()); |
| 243 |
| 244 sink_->Pause(); |
| 245 EXPECT_EQ(OUTPUT_DEVICE_STATUS_OK, sink_->GetDeviceStatus()); |
| 246 EXPECT_FALSE(mock_output_device_->IsPlaying()); |
| 247 |
| 248 sink_->Stop(); |
| 249 } |
| 250 |
| 251 //* |
| 252 TEST_F(RestartableAudioOutputDeviceImplTest, PausePausedSink) { |
| 253 PrepareSink(kDefaultDeviceId); |
| 254 |
| 255 sink_->Initialize(default_params_, &callback_); |
| 256 EXPECT_FALSE(mock_output_device_->IsPlaying()); |
| 257 sink_->Start(); |
| 258 EXPECT_FALSE(mock_output_device_->IsPlaying()); |
| 259 sink_->Play(); |
| 260 EXPECT_TRUE(mock_output_device_->IsPlaying()); |
| 261 sink_->Pause(); |
| 262 EXPECT_FALSE(mock_output_device_->IsPlaying()); |
| 263 sink_->Pause(); |
| 264 EXPECT_FALSE(mock_output_device_->IsPlaying()); |
| 265 EXPECT_EQ(OUTPUT_DEVICE_STATUS_OK, sink_->GetDeviceStatus()); |
| 266 sink_->Stop(); |
| 267 } |
| 268 //* |
| 269 TEST_F(RestartableAudioOutputDeviceImplTest, PlayPlayingSink) { |
| 270 PrepareSink(kDefaultDeviceId); |
| 271 |
| 272 sink_->Initialize(default_params_, &callback_); |
| 273 sink_->Start(); |
| 274 EXPECT_FALSE(mock_output_device_->IsPlaying()); |
| 275 sink_->Play(); |
| 276 EXPECT_TRUE(mock_output_device_->IsPlaying()); |
| 277 sink_->Play(); |
| 278 EXPECT_TRUE(mock_output_device_->IsPlaying()); |
| 279 EXPECT_EQ(OUTPUT_DEVICE_STATUS_OK, sink_->GetDeviceStatus()); |
| 280 sink_->Play(); |
| 281 EXPECT_TRUE(mock_output_device_->IsPlaying()); |
| 282 EXPECT_EQ(OUTPUT_DEVICE_STATUS_OK, sink_->GetDeviceStatus()); |
| 283 sink_->Stop(); |
| 284 } |
| 285 |
| 286 TEST_F(RestartableAudioOutputDeviceImplTest, StartPausePlayStopSink) { |
| 287 PrepareSink(kDefaultDeviceId); |
| 288 |
| 289 sink_->Initialize(default_params_, &callback_); |
| 290 sink_->Start(); |
| 291 EXPECT_FALSE(mock_output_device_->IsPlaying()); |
| 292 sink_->Pause(); |
| 293 EXPECT_FALSE(mock_output_device_->IsPlaying()); |
| 294 EXPECT_EQ(OUTPUT_DEVICE_STATUS_OK, sink_->GetDeviceStatus()); |
| 295 sink_->Play(); |
| 296 EXPECT_TRUE(mock_output_device_->IsPlaying()); |
| 297 EXPECT_EQ(OUTPUT_DEVICE_STATUS_OK, sink_->GetDeviceStatus()); |
| 298 sink_->Stop(); |
| 299 } |
| 300 |
| 301 TEST_F(RestartableAudioOutputDeviceImplTest, PauseAfterPlay) { |
| 302 PrepareSink(kDefaultDeviceId); |
| 303 |
| 304 sink_->Initialize(default_params_, &callback_); |
| 305 sink_->Start(); |
| 306 EXPECT_FALSE(mock_output_device_->IsPlaying()); |
| 307 sink_->Play(); |
| 308 EXPECT_TRUE(mock_output_device_->IsPlaying()); |
| 309 sink_->Pause(); |
| 310 EXPECT_FALSE(mock_output_device_->IsPlaying()); |
| 311 EXPECT_EQ(OUTPUT_DEVICE_STATUS_OK, sink_->GetDeviceStatus()); |
| 312 sink_->Stop(); |
| 313 } |
| 314 |
| 315 TEST_F(RestartableAudioOutputDeviceImplTest, MultiplePlayPause) { |
| 316 PrepareSink(kDefaultDeviceId); |
| 317 |
| 318 sink_->Initialize(default_params_, &callback_); |
| 319 sink_->Start(); |
| 320 EXPECT_FALSE(mock_output_device_->IsPlaying()); |
| 321 sink_->Play(); |
| 322 EXPECT_TRUE(mock_output_device_->IsPlaying()); |
| 323 sink_->Pause(); |
| 324 EXPECT_FALSE(mock_output_device_->IsPlaying()); |
| 325 sink_->Play(); |
| 326 EXPECT_TRUE(mock_output_device_->IsPlaying()); |
| 327 EXPECT_EQ(OUTPUT_DEVICE_STATUS_OK, sink_->GetDeviceStatus()); |
| 328 sink_->Pause(); |
| 329 EXPECT_FALSE(mock_output_device_->IsPlaying()); |
| 330 EXPECT_EQ(OUTPUT_DEVICE_STATUS_OK, sink_->GetDeviceStatus()); |
| 331 sink_->Stop(); |
| 332 } |
| 333 |
| 334 TEST_F(RestartableAudioOutputDeviceImplTest, RestartSinkNoReinit) { |
| 335 PrepareSink(kDefaultDeviceId, 1); |
| 336 |
| 337 sink_->Initialize(default_params_, &callback_); |
| 338 sink_->Start(); |
| 339 EXPECT_FALSE(mock_output_device_->IsPlaying()); |
| 340 EXPECT_EQ(kDefaultSampleRate, mock_output_device_->GetSampleRate()); |
| 341 sink_->Play(); |
| 342 EXPECT_TRUE(mock_output_device_->IsPlaying()); |
| 343 sink_->Stop(); |
| 344 EXPECT_EQ(OUTPUT_DEVICE_STATUS_OK, sink_->GetDeviceStatus()); |
| 345 sink_->Start(); |
| 346 EXPECT_FALSE(mock_output_device_->IsPlaying()); |
| 347 EXPECT_EQ(kDefaultSampleRate, mock_output_device_->GetSampleRate()); |
| 348 sink_->Play(); |
| 349 EXPECT_TRUE(mock_output_device_->IsPlaying()); |
| 350 sink_->Stop(); |
| 351 } |
| 352 |
| 353 TEST_F(RestartableAudioOutputDeviceImplTest, RestartAndReinitSink) { |
| 354 PrepareSink(kDefaultDeviceId, 1); |
| 355 |
| 356 sink_->Initialize(default_params_, &callback_); |
| 357 sink_->Start(); |
| 358 EXPECT_FALSE(mock_output_device_->IsPlaying()); |
| 359 EXPECT_EQ(kDefaultSampleRate, mock_output_device_->GetSampleRate()); |
| 360 sink_->Play(); |
| 361 EXPECT_TRUE(mock_output_device_->IsPlaying()); |
| 362 sink_->Stop(); |
| 363 |
| 364 sink_->Initialize(new_params_, &callback_); |
| 365 EXPECT_EQ(OUTPUT_DEVICE_STATUS_OK, sink_->GetDeviceStatus()); |
| 366 sink_->Start(); |
| 367 EXPECT_FALSE(mock_output_device_->IsPlaying()); |
| 368 EXPECT_EQ(kNewSampleRate, mock_output_device_->GetSampleRate()); |
| 369 sink_->Play(); |
| 370 EXPECT_TRUE(mock_output_device_->IsPlaying()); |
| 371 sink_->Stop(); |
| 372 } |
| 373 |
| 374 TEST_F(RestartableAudioOutputDeviceImplTest, GetOutputParameters) { |
| 375 PrepareSink(kDefaultDeviceId, 1); |
| 376 EXPECT_EQ(kHWSampleRate, sink_->GetOutputParameters().sample_rate()); |
| 377 sink_->Initialize(default_params_, &callback_); |
| 378 EXPECT_EQ(kHWSampleRate, sink_->GetOutputParameters().sample_rate()); |
| 379 sink_->Start(); |
| 380 EXPECT_EQ(kHWSampleRate, sink_->GetOutputParameters().sample_rate()); |
| 381 sink_->Play(); |
| 382 EXPECT_EQ(kHWSampleRate, sink_->GetOutputParameters().sample_rate()); |
| 383 sink_->Stop(); |
| 384 EXPECT_EQ(kHWSampleRate, sink_->GetOutputParameters().sample_rate()); |
| 385 sink_->Start(); |
| 386 EXPECT_EQ(kHWSampleRate, sink_->GetOutputParameters().sample_rate()); |
| 387 sink_->Stop(); |
| 388 } |
| 389 |
| 390 TEST_F(RestartableAudioOutputDeviceImplTest, SetVolume) { |
| 391 PrepareSink(kDefaultDeviceId, 1); |
| 392 |
| 393 sink_->SetVolume(0.8); // Set volume before starting sink. |
| 394 sink_->Initialize(default_params_, &callback_); |
| 395 sink_->Start(); |
| 396 sink_->Play(); |
| 397 EXPECT_DOUBLE_EQ(0.8, mock_output_device_->GetVolume()); |
| 398 sink_->Stop(); |
| 399 |
| 400 EXPECT_TRUE(sink_->SetVolume(0.1)); |
| 401 sink_->Initialize(default_params_, &callback_); |
| 402 EXPECT_TRUE(sink_->SetVolume(0.2)); |
| 403 sink_->Start(); |
| 404 EXPECT_TRUE(sink_->SetVolume(0.3)); |
| 405 sink_->Play(); |
| 406 EXPECT_DOUBLE_EQ(0.3, mock_output_device_->GetVolume()); |
| 407 EXPECT_TRUE(sink_->SetVolume(0.4)); |
| 408 EXPECT_DOUBLE_EQ(0.4, mock_output_device_->GetVolume()); |
| 409 EXPECT_TRUE(sink_->SetVolume(0.5)); |
| 410 EXPECT_DOUBLE_EQ(0.5, mock_output_device_->GetVolume()); |
| 411 sink_->Pause(); |
| 412 EXPECT_TRUE(sink_->SetVolume(0.6)); |
| 413 EXPECT_TRUE(sink_->SetVolume(0.7)); |
| 414 sink_->Play(); |
| 415 EXPECT_DOUBLE_EQ(0.7, mock_output_device_->GetVolume()); |
| 416 sink_->Stop(); |
| 417 } |
| 418 |
| 419 TEST_F(RestartableAudioOutputDeviceImplTest, CorrectStatusFromInvalidDevice) { |
| 420 PrepareSink(kBrokenDeviceId, 1); |
| 421 |
| 422 sink_->Initialize(default_params_, &callback_); |
| 423 sink_->Start(); |
| 424 EXPECT_NE(OUTPUT_DEVICE_STATUS_OK, sink_->GetDeviceStatus()); |
| 425 |
| 426 sink_->Stop(); |
| 427 // Stopped device is OK. |
| 428 EXPECT_EQ(OUTPUT_DEVICE_STATUS_OK, sink_->GetDeviceStatus()); |
| 429 |
| 430 sink_->Start(); |
| 431 EXPECT_NE(OUTPUT_DEVICE_STATUS_OK, sink_->GetDeviceStatus()); |
| 432 |
| 433 sink_->Stop(); |
| 434 } |
| 435 |
| 436 } // namespace content |
OLD | NEW |