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