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 // MSVC++ requires this to be set before any other includes to get M_PI. 6 #define _USE_MATH_DEFINES 7 #include <cmath> 8 9 #include "base/bind.h" 10 #include "base/bind_helpers.h" 11 #include "base/memory/scoped_ptr.h" 12 #include "base/memory/scoped_vector.h" 13 #include "base/synchronization/waitable_event.h" 14 #include "base/threading/platform_thread.h" 15 #include "media/base/audio_renderer_mixer.h" 16 #include "media/base/audio_renderer_mixer_input.h" 17 #include "media/base/fake_audio_render_callback.h" 18 #include "media/base/mock_audio_renderer_sink.h" 19 #include "testing/gmock/include/gmock/gmock.h" 20 #include "testing/gtest/include/gtest/gtest.h" 21 22 namespace media { 23 24 // Parameters which control the many input case tests. 25 const int kMixerInputs = 8; 26 const int kMixerCycles = 3; 27 28 // Parameters used for testing. 29 const int kBitsPerChannel = 32; 30 const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_STEREO; 31 const int kHighLatencyBufferSize = 8192; 32 const int kLowLatencyBufferSize = 256; 33 34 // Number of full sine wave cycles for each Render() call. 35 const int kSineCycles = 4; 36 37 // Tuple of <input sampling rate, output sampling rate, epsilon>. 38 typedef std::tr1::tuple<int, int, double> AudioRendererMixerTestData; 39 class AudioRendererMixerTest 40 : public testing::TestWithParam<AudioRendererMixerTestData> { 41 public: 42 AudioRendererMixerTest() 43 : epsilon_(std::tr1::get<2>(GetParam())), 44 half_fill_(false) { 45 // Create input and output parameters based on test parameters. 46 input_parameters_ = AudioParameters( 47 AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, 48 std::tr1::get<0>(GetParam()), kBitsPerChannel, kHighLatencyBufferSize); 49 output_parameters_ = AudioParameters( 50 AudioParameters::AUDIO_PCM_LOW_LATENCY, kChannelLayout, 51 std::tr1::get<1>(GetParam()), 16, kLowLatencyBufferSize); 52 53 sink_ = new MockAudioRendererSink(); 54 EXPECT_CALL(*sink_.get(), Start()); 55 EXPECT_CALL(*sink_.get(), Stop()); 56 57 mixer_.reset(new AudioRendererMixer( 58 input_parameters_, output_parameters_, sink_)); 59 mixer_callback_ = sink_->callback(); 60 61 audio_bus_ = AudioBus::Create(output_parameters_); 62 expected_audio_bus_ = AudioBus::Create(output_parameters_); 63 64 // Allocate one callback for generating expected results. 65 double step = kSineCycles / static_cast<double>( 66 output_parameters_.frames_per_buffer()); 67 expected_callback_.reset(new FakeAudioRenderCallback(step)); 68 } 69 70 AudioRendererMixer* GetMixer(const AudioParameters& params) { 71 return mixer_.get(); 72 } 73 74 MOCK_METHOD1(RemoveMixer, void(const AudioParameters&)); 75 76 void InitializeInputs(int count) { 77 mixer_inputs_.reserve(count); 78 fake_callbacks_.reserve(count); 79 80 // Setup FakeAudioRenderCallback step to compensate for resampling. 81 double scale_factor = input_parameters_.sample_rate() / 82 static_cast<double>(output_parameters_.sample_rate()); 83 double step = kSineCycles / (scale_factor * 84 static_cast<double>(output_parameters_.frames_per_buffer())); 85 86 for (int i = 0; i < count; ++i) { 87 fake_callbacks_.push_back(new FakeAudioRenderCallback(step)); 88 mixer_inputs_.push_back(new AudioRendererMixerInput( 89 base::Bind(&AudioRendererMixerTest::GetMixer, 90 base::Unretained(this)), 91 base::Bind(&AudioRendererMixerTest::RemoveMixer, 92 base::Unretained(this)))); 93 mixer_inputs_[i]->Initialize(input_parameters_, fake_callbacks_[i]); 94 mixer_inputs_[i]->SetVolume(1.0f); 95 } 96 EXPECT_CALL(*this, RemoveMixer(testing::_)).Times(count); 97 } 98 99 bool ValidateAudioData(int index, int frames, float scale, double epsilon) { 100 for (int i = 0; i < audio_bus_->channels(); ++i) { 101 for (int j = index; j < frames; j++) { 102 double error = fabs(audio_bus_->channel(i)[j] - 103 expected_audio_bus_->channel(i)[j] * scale); 104 if (error > epsilon) { 105 EXPECT_NEAR(expected_audio_bus_->channel(i)[j] * scale, 106 audio_bus_->channel(i)[j], epsilon) 107 << " i=" << i << ", j=" << j; 108 return false; 109 } 110 } 111 } 112 return true; 113 } 114 115 bool ValidateAudioData(int index, int frames, float scale) { 116 return ValidateAudioData(index, frames, scale, epsilon_); 117 } 118 119 bool RenderAndValidateAudioData(float scale) { 120 if (half_fill_) { 121 for (size_t i = 0; i < fake_callbacks_.size(); ++i) 122 fake_callbacks_[i]->set_half_fill(true); 123 expected_callback_->set_half_fill(true); 124 // Initialize the AudioBus completely or we'll run into Valgrind problems 125 // during the verification step below. 126 expected_audio_bus_->Zero(); 127 } 128 129 // Render actual audio data. 130 int frames = mixer_callback_->Render(audio_bus_.get(), 0); 131 if (frames != audio_bus_->frames()) 132 return false; 133 134 // Render expected audio data (without scaling). 135 expected_callback_->Render(expected_audio_bus_.get(), 0); 136 137 if (half_fill_) { 138 // In this case, just verify that every frame was initialized, this will 139 // only fail under tooling such as valgrind. 140 return ValidateAudioData( 141 0, frames, 0, std::numeric_limits<double>::max()); 142 } else { 143 return ValidateAudioData(0, frames, scale); 144 } 145 } 146 147 // Fill |audio_bus_| fully with |value|. 148 void FillAudioData(float value) { 149 for (int i = 0; i < audio_bus_->channels(); ++i) { 150 std::fill(audio_bus_->channel(i), 151 audio_bus_->channel(i) + audio_bus_->frames(), value); 152 } 153 } 154 155 // Verify silence when mixer inputs are in pre-Start() and post-Start(). 156 void StartTest(int inputs) { 157 InitializeInputs(inputs); 158 159 // Verify silence before any inputs have been started. Fill the buffer 160 // before hand with non-zero data to ensure we get zeros back. 161 FillAudioData(1.0f); 162 EXPECT_TRUE(RenderAndValidateAudioData(0.0f)); 163 164 // Start() all even numbered mixer inputs and ensure we still get silence. 165 for (size_t i = 0; i < mixer_inputs_.size(); i += 2) 166 mixer_inputs_[i]->Start(); 167 FillAudioData(1.0f); 168 EXPECT_TRUE(RenderAndValidateAudioData(0.0f)); 169 170 // Start() all mixer inputs and ensure we still get silence. 171 for (size_t i = 1; i < mixer_inputs_.size(); i += 2) 172 mixer_inputs_[i]->Start(); 173 FillAudioData(1.0f); 174 EXPECT_TRUE(RenderAndValidateAudioData(0.0f)); 175 176 for (size_t i = 0; i < mixer_inputs_.size(); ++i) 177 mixer_inputs_[i]->Stop(); 178 } 179 180 // Verify output when mixer inputs are in post-Play() state. 181 void PlayTest(int inputs) { 182 InitializeInputs(inputs); 183 184 // Play() all mixer inputs and ensure we get the right values. 185 for (size_t i = 0; i < mixer_inputs_.size(); ++i) { 186 mixer_inputs_[i]->Start(); 187 mixer_inputs_[i]->Play(); 188 } 189 190 for (int i = 0; i < kMixerCycles; ++i) 191 ASSERT_TRUE(RenderAndValidateAudioData(mixer_inputs_.size())); 192 193 for (size_t i = 0; i < mixer_inputs_.size(); ++i) 194 mixer_inputs_[i]->Stop(); 195 } 196 197 // Verify volume adjusted output when mixer inputs are in post-Play() state. 198 void PlayVolumeAdjustedTest(int inputs) { 199 InitializeInputs(inputs); 200 201 for (size_t i = 0; i < mixer_inputs_.size(); ++i) { 202 mixer_inputs_[i]->Start(); 203 mixer_inputs_[i]->Play(); 204 } 205 206 // Set a different volume for each mixer input and verify the results. 207 float total_scale = 0; 208 for (size_t i = 0; i < mixer_inputs_.size(); ++i) { 209 float volume = static_cast<float>(i) / mixer_inputs_.size(); 210 total_scale += volume; 211 EXPECT_TRUE(mixer_inputs_[i]->SetVolume(volume)); 212 } 213 for (int i = 0; i < kMixerCycles; ++i) 214 ASSERT_TRUE(RenderAndValidateAudioData(total_scale)); 215 216 for (size_t i = 0; i < mixer_inputs_.size(); ++i) 217 mixer_inputs_[i]->Stop(); 218 } 219 220 // Verify output when mixer inputs can only partially fulfill a Render(). 221 void PlayPartialRenderTest(int inputs) { 222 InitializeInputs(inputs); 223 224 for (size_t i = 0; i < mixer_inputs_.size(); ++i) { 225 mixer_inputs_[i]->Start(); 226 mixer_inputs_[i]->Play(); 227 } 228 229 // Verify a properly filled buffer when half filled (remainder zeroed). 230 half_fill_ = true; 231 ASSERT_TRUE(RenderAndValidateAudioData(mixer_inputs_.size())); 232 233 for (size_t i = 0; i < mixer_inputs_.size(); ++i) 234 mixer_inputs_[i]->Stop(); 235 } 236 237 // Verify output when mixer inputs are in Pause() state. 238 void PauseTest(int inputs) { 239 InitializeInputs(inputs); 240 241 for (size_t i = 0; i < mixer_inputs_.size(); ++i) { 242 mixer_inputs_[i]->Start(); 243 mixer_inputs_[i]->Play(); 244 } 245 246 // Pause() all even numbered mixer inputs and ensure we get the right value. 247 for (size_t i = 0; i < mixer_inputs_.size(); i += 2) 248 mixer_inputs_[i]->Pause(); 249 for (int i = 0; i < kMixerCycles; ++i) 250 ASSERT_TRUE(RenderAndValidateAudioData(mixer_inputs_.size() / 2)); 251 252 for (size_t i = 0; i < mixer_inputs_.size(); ++i) 253 mixer_inputs_[i]->Stop(); 254 } 255 256 // Verify output when mixer inputs are in post-Stop() state. 257 void StopTest(int inputs) { 258 InitializeInputs(inputs); 259 260 // Start() and Stop() all inputs. 261 for (size_t i = 0; i < mixer_inputs_.size(); ++i) { 262 mixer_inputs_[i]->Start(); 263 mixer_inputs_[i]->Stop(); 264 } 265 266 // Verify we get silence back; fill |audio_bus_| before hand to be sure. 267 FillAudioData(1.0f); 268 EXPECT_TRUE(RenderAndValidateAudioData(0.0f)); 269 } 270 271 protected: 272 virtual ~AudioRendererMixerTest() {} 273 274 scoped_refptr<MockAudioRendererSink> sink_; 275 scoped_ptr<AudioRendererMixer> mixer_; 276 AudioRendererSink::RenderCallback* mixer_callback_; 277 AudioParameters input_parameters_; 278 AudioParameters output_parameters_; 279 scoped_ptr<AudioBus> audio_bus_; 280 scoped_ptr<AudioBus> expected_audio_bus_; 281 std::vector< scoped_refptr<AudioRendererMixerInput> > mixer_inputs_; 282 ScopedVector<FakeAudioRenderCallback> fake_callbacks_; 283 scoped_ptr<FakeAudioRenderCallback> expected_callback_; 284 double epsilon_; 285 bool half_fill_; 286 287 DISALLOW_COPY_AND_ASSIGN(AudioRendererMixerTest); 288 }; 289 290 class AudioRendererMixerBehavioralTest : public AudioRendererMixerTest {}; 291 292 ACTION_P(SignalEvent, event) { 293 event->Signal(); 294 } 295 296 // Verify a mixer with no inputs returns silence for all requested frames. 297 TEST_P(AudioRendererMixerTest, NoInputs) { 298 FillAudioData(1.0f); 299 EXPECT_TRUE(RenderAndValidateAudioData(0.0f)); 300 } 301 302 // Test mixer output with one input in the pre-Start() and post-Start() state. 303 TEST_P(AudioRendererMixerTest, OneInputStart) { 304 StartTest(1); 305 } 306 307 // Test mixer output with many inputs in the pre-Start() and post-Start() state. 308 TEST_P(AudioRendererMixerTest, ManyInputStart) { 309 StartTest(kMixerInputs); 310 } 311 312 // Test mixer output with one input in the post-Play() state. 313 TEST_P(AudioRendererMixerTest, OneInputPlay) { 314 PlayTest(1); 315 } 316 317 // Test mixer output with many inputs in the post-Play() state. 318 TEST_P(AudioRendererMixerTest, ManyInputPlay) { 319 PlayTest(kMixerInputs); 320 } 321 322 // Test volume adjusted mixer output with one input in the post-Play() state. 323 TEST_P(AudioRendererMixerTest, OneInputPlayVolumeAdjusted) { 324 PlayVolumeAdjustedTest(1); 325 } 326 327 // Test volume adjusted mixer output with many inputs in the post-Play() state. 328 TEST_P(AudioRendererMixerTest, ManyInputPlayVolumeAdjusted) { 329 PlayVolumeAdjustedTest(kMixerInputs); 330 } 331 332 // Test mixer output with one input and partial Render() in post-Play() state. 333 TEST_P(AudioRendererMixerTest, OneInputPlayPartialRender) { 334 PlayPartialRenderTest(1); 335 } 336 337 // Test mixer output with many inputs and partial Render() in post-Play() state. 338 TEST_P(AudioRendererMixerTest, ManyInputPlayPartialRender) { 339 PlayPartialRenderTest(kMixerInputs); 340 } 341 342 // Test mixer output with one input in the post-Pause() state. 343 TEST_P(AudioRendererMixerTest, OneInputPause) { 344 PauseTest(1); 345 } 346 347 // Test mixer output with many inputs in the post-Pause() state. 348 TEST_P(AudioRendererMixerTest, ManyInputPause) { 349 PauseTest(kMixerInputs); 350 } 351 352 // Test mixer output with one input in the post-Stop() state. 353 TEST_P(AudioRendererMixerTest, OneInputStop) { 354 StopTest(1); 355 } 356 357 // Test mixer output with many inputs in the post-Stop() state. 358 TEST_P(AudioRendererMixerTest, ManyInputStop) { 359 StopTest(kMixerInputs); 360 } 361 362 // Test mixer with many inputs in mixed post-Stop() and post-Play() states. 363 TEST_P(AudioRendererMixerTest, ManyInputMixedStopPlay) { 364 InitializeInputs(kMixerInputs); 365 366 // Start() all inputs. 367 for (size_t i = 0; i < mixer_inputs_.size(); ++i) 368 mixer_inputs_[i]->Start(); 369 370 // Stop() all even numbered mixer inputs and Play() all odd numbered inputs 371 // and ensure we get the right value. 372 for (size_t i = 1; i < mixer_inputs_.size(); i += 2) { 373 mixer_inputs_[i - 1]->Stop(); 374 mixer_inputs_[i]->Play(); 375 } 376 ASSERT_TRUE(RenderAndValidateAudioData(std::max( 377 mixer_inputs_.size() / 2, static_cast<size_t>(1)))); 378 379 for (size_t i = 1; i < mixer_inputs_.size(); i += 2) 380 mixer_inputs_[i]->Stop(); 381 } 382 383 TEST_P(AudioRendererMixerBehavioralTest, OnRenderError) { 384 InitializeInputs(kMixerInputs); 385 for (size_t i = 0; i < mixer_inputs_.size(); ++i) { 386 mixer_inputs_[i]->Start(); 387 mixer_inputs_[i]->Play(); 388 EXPECT_CALL(*fake_callbacks_[i], OnRenderError()).Times(1); 389 } 390 391 mixer_callback_->OnRenderError(); 392 for (size_t i = 0; i < mixer_inputs_.size(); ++i) 393 mixer_inputs_[i]->Stop(); 394 } 395 396 TEST_P(AudioRendererMixerBehavioralTest, OnRenderErrorPausedInput) { 397 InitializeInputs(kMixerInputs); 398 399 for (size_t i = 0; i < mixer_inputs_.size(); ++i) { 400 mixer_inputs_[i]->Start(); 401 EXPECT_CALL(*fake_callbacks_[i], OnRenderError()).Times(1); 402 } 403 404 // Fire the error before attaching any inputs. Ensure an error is recieved 405 // even if the input is not connected. 406 mixer_callback_->OnRenderError(); 407 408 for (size_t i = 0; i < mixer_inputs_.size(); ++i) 409 mixer_inputs_[i]->Stop(); 410 } 411 412 // Ensure constructing an AudioRendererMixerInput, but not initializing it does 413 // not call RemoveMixer(). 414 TEST_P(AudioRendererMixerBehavioralTest, NoInitialize) { 415 EXPECT_CALL(*this, RemoveMixer(testing::_)).Times(0); 416 scoped_refptr<AudioRendererMixerInput> audio_renderer_mixer = 417 new AudioRendererMixerInput( 418 base::Bind(&AudioRendererMixerTest::GetMixer, 419 base::Unretained(this)), 420 base::Bind(&AudioRendererMixerTest::RemoveMixer, 421 base::Unretained(this))); 422 } 423 424 // Ensure the physical stream is paused after a certain amount of time with no 425 // inputs playing. The test will hang if the behavior is incorrect. 426 TEST_P(AudioRendererMixerBehavioralTest, MixerPausesStream) { 427 const base::TimeDelta kPauseTime = base::TimeDelta::FromMilliseconds(500); 428 // This value can't be too low or valgrind, tsan will timeout on the bots. 429 const base::TimeDelta kTestTimeout = 10 * kPauseTime; 430 mixer_->set_pause_delay_for_testing(kPauseTime); 431 432 base::WaitableEvent pause_event(true, false); 433 EXPECT_CALL(*sink_.get(), Pause()).Times(2) 434 .WillRepeatedly(SignalEvent(&pause_event)); 435 InitializeInputs(1); 436 437 // Ensure never playing the input results in a sink pause. 438 const base::TimeDelta kSleepTime = base::TimeDelta::FromMilliseconds(100); 439 base::TimeTicks start_time = base::TimeTicks::Now(); 440 while (!pause_event.IsSignaled()) { 441 mixer_callback_->Render(audio_bus_.get(), 0); 442 base::PlatformThread::Sleep(kSleepTime); 443 ASSERT_TRUE(base::TimeTicks::Now() - start_time < kTestTimeout); 444 } 445 pause_event.Reset(); 446 447 // Playing the input for the first time should cause a sink play. 448 mixer_inputs_[0]->Start(); 449 EXPECT_CALL(*sink_.get(), Play()); 450 mixer_inputs_[0]->Play(); 451 mixer_inputs_[0]->Pause(); 452 453 // Ensure once the input is paused the sink eventually pauses. 454 start_time = base::TimeTicks::Now(); 455 while (!pause_event.IsSignaled()) { 456 mixer_callback_->Render(audio_bus_.get(), 0); 457 base::PlatformThread::Sleep(kSleepTime); 458 ASSERT_TRUE(base::TimeTicks::Now() - start_time < kTestTimeout); 459 } 460 461 mixer_inputs_[0]->Stop(); 462 } 463 464 INSTANTIATE_TEST_CASE_P( 465 AudioRendererMixerTest, AudioRendererMixerTest, testing::Values( 466 // No resampling. 467 std::tr1::make_tuple(44100, 44100, 0.00000048), 468 469 // Upsampling. 470 std::tr1::make_tuple(44100, 48000, 0.033), 471 472 // Downsampling. 473 std::tr1::make_tuple(48000, 41000, 0.042))); 474 475 // Test cases for behavior which is independent of parameters. Values() doesn't 476 // support single item lists and we don't want these test cases to run for every 477 // parameter set. 478 INSTANTIATE_TEST_CASE_P( 479 AudioRendererMixerBehavioralTest, AudioRendererMixerBehavioralTest, 480 testing::ValuesIn(std::vector<AudioRendererMixerTestData>( 481 1, std::tr1::make_tuple(44100, 44100, 0)))); 482 483 } // namespace media 484