Allow overlapping sync and async startup requests
[chromium-blink-merge.git] / media / base / audio_renderer_mixer_unittest.cc
blob8853068335ca5f221187f38bedc0874fb8430b71
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.
5 // MSVC++ requires this to be set before any other includes to get M_PI.
6 #define _USE_MATH_DEFINES
7 #include <cmath>
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"
22 namespace media {
24 // Parameters which control the many input case tests.
25 static const int kMixerInputs = 8;
26 static const int kMixerCycles = 3;
28 // Parameters used for testing.
29 static const int kBitsPerChannel = 32;
30 static const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_STEREO;
31 static const int kHighLatencyBufferSize = 8192;
32 static const int kLowLatencyBufferSize = 256;
33 static const int kSampleRate = 48000;
35 // Number of full sine wave cycles for each Render() call.
36 static const int kSineCycles = 4;
38 // Tuple of <input sampling rate, output sampling rate, epsilon>.
39 typedef std::tr1::tuple<int, int, double> AudioRendererMixerTestData;
40 class 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);
54 sink_ = new MockAudioRendererSink();
55 EXPECT_CALL(*sink_.get(), Start());
56 EXPECT_CALL(*sink_.get(), Stop());
58 mixer_.reset(new AudioRendererMixer(
59 input_parameters_, output_parameters_, sink_));
60 mixer_callback_ = sink_->callback();
62 audio_bus_ = AudioBus::Create(output_parameters_);
63 expected_audio_bus_ = AudioBus::Create(output_parameters_);
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));
71 AudioRendererMixer* GetMixer(const AudioParameters& params) {
72 return mixer_.get();
75 MOCK_METHOD1(RemoveMixer, void(const AudioParameters&));
77 void InitializeInputs(int count) {
78 mixer_inputs_.reserve(count);
79 fake_callbacks_.reserve(count);
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()));
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);
97 EXPECT_CALL(*this, RemoveMixer(testing::_)).Times(count);
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;
113 return true;
116 bool ValidateAudioData(int index, int frames, float scale) {
117 return ValidateAudioData(index, frames, scale, epsilon_);
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();
130 // Render actual audio data.
131 int frames = mixer_callback_->Render(audio_bus_.get(), 0);
132 if (frames != audio_bus_->frames())
133 return false;
135 // Render expected audio data (without scaling).
136 expected_callback_->Render(expected_audio_bus_.get(), 0);
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);
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);
156 // Verify silence when mixer inputs are in pre-Start() and post-Start().
157 void StartTest(int inputs) {
158 InitializeInputs(inputs);
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));
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));
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));
177 for (size_t i = 0; i < mixer_inputs_.size(); ++i)
178 mixer_inputs_[i]->Stop();
181 // Verify output when mixer inputs are in post-Play() state.
182 void PlayTest(int inputs) {
183 InitializeInputs(inputs);
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();
191 for (int i = 0; i < kMixerCycles; ++i)
192 ASSERT_TRUE(RenderAndValidateAudioData(mixer_inputs_.size()));
194 for (size_t i = 0; i < mixer_inputs_.size(); ++i)
195 mixer_inputs_[i]->Stop();
198 // Verify volume adjusted output when mixer inputs are in post-Play() state.
199 void PlayVolumeAdjustedTest(int inputs) {
200 InitializeInputs(inputs);
202 for (size_t i = 0; i < mixer_inputs_.size(); ++i) {
203 mixer_inputs_[i]->Start();
204 mixer_inputs_[i]->Play();
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));
214 for (int i = 0; i < kMixerCycles; ++i)
215 ASSERT_TRUE(RenderAndValidateAudioData(total_scale));
217 for (size_t i = 0; i < mixer_inputs_.size(); ++i)
218 mixer_inputs_[i]->Stop();
221 // Verify output when mixer inputs can only partially fulfill a Render().
222 void PlayPartialRenderTest(int inputs) {
223 InitializeInputs(inputs);
225 for (size_t i = 0; i < mixer_inputs_.size(); ++i) {
226 mixer_inputs_[i]->Start();
227 mixer_inputs_[i]->Play();
230 // Verify a properly filled buffer when half filled (remainder zeroed).
231 half_fill_ = true;
232 ASSERT_TRUE(RenderAndValidateAudioData(mixer_inputs_.size()));
234 for (size_t i = 0; i < mixer_inputs_.size(); ++i)
235 mixer_inputs_[i]->Stop();
238 // Verify output when mixer inputs are in Pause() state.
239 void PauseTest(int inputs) {
240 InitializeInputs(inputs);
242 for (size_t i = 0; i < mixer_inputs_.size(); ++i) {
243 mixer_inputs_[i]->Start();
244 mixer_inputs_[i]->Play();
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));
253 for (size_t i = 0; i < mixer_inputs_.size(); ++i)
254 mixer_inputs_[i]->Stop();
257 // Verify output when mixer inputs are in post-Stop() state.
258 void StopTest(int inputs) {
259 InitializeInputs(inputs);
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();
267 // Verify we get silence back; fill |audio_bus_| before hand to be sure.
268 FillAudioData(1.0f);
269 EXPECT_TRUE(RenderAndValidateAudioData(0.0f));
272 protected:
273 virtual ~AudioRendererMixerTest() {}
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_;
288 DISALLOW_COPY_AND_ASSIGN(AudioRendererMixerTest);
291 class AudioRendererMixerBehavioralTest : public AudioRendererMixerTest {};
293 ACTION_P(SignalEvent, event) {
294 event->Signal();
297 // Verify a mixer with no inputs returns silence for all requested frames.
298 TEST_P(AudioRendererMixerTest, NoInputs) {
299 FillAudioData(1.0f);
300 EXPECT_TRUE(RenderAndValidateAudioData(0.0f));
303 // Test mixer output with one input in the pre-Start() and post-Start() state.
304 TEST_P(AudioRendererMixerTest, OneInputStart) {
305 StartTest(1);
308 // Test mixer output with many inputs in the pre-Start() and post-Start() state.
309 TEST_P(AudioRendererMixerTest, ManyInputStart) {
310 StartTest(kMixerInputs);
313 // Test mixer output with one input in the post-Play() state.
314 TEST_P(AudioRendererMixerTest, OneInputPlay) {
315 PlayTest(1);
318 // Test mixer output with many inputs in the post-Play() state.
319 TEST_P(AudioRendererMixerTest, ManyInputPlay) {
320 PlayTest(kMixerInputs);
323 // Test volume adjusted mixer output with one input in the post-Play() state.
324 TEST_P(AudioRendererMixerTest, OneInputPlayVolumeAdjusted) {
325 PlayVolumeAdjustedTest(1);
328 // Test volume adjusted mixer output with many inputs in the post-Play() state.
329 TEST_P(AudioRendererMixerTest, ManyInputPlayVolumeAdjusted) {
330 PlayVolumeAdjustedTest(kMixerInputs);
333 // Test mixer output with one input and partial Render() in post-Play() state.
334 TEST_P(AudioRendererMixerTest, OneInputPlayPartialRender) {
335 PlayPartialRenderTest(1);
338 // Test mixer output with many inputs and partial Render() in post-Play() state.
339 TEST_P(AudioRendererMixerTest, ManyInputPlayPartialRender) {
340 PlayPartialRenderTest(kMixerInputs);
343 // Test mixer output with one input in the post-Pause() state.
344 TEST_P(AudioRendererMixerTest, OneInputPause) {
345 PauseTest(1);
348 // Test mixer output with many inputs in the post-Pause() state.
349 TEST_P(AudioRendererMixerTest, ManyInputPause) {
350 PauseTest(kMixerInputs);
353 // Test mixer output with one input in the post-Stop() state.
354 TEST_P(AudioRendererMixerTest, OneInputStop) {
355 StopTest(1);
358 // Test mixer output with many inputs in the post-Stop() state.
359 TEST_P(AudioRendererMixerTest, ManyInputStop) {
360 StopTest(kMixerInputs);
363 // Test mixer with many inputs in mixed post-Stop() and post-Play() states.
364 TEST_P(AudioRendererMixerTest, ManyInputMixedStopPlay) {
365 InitializeInputs(kMixerInputs);
367 // Start() all inputs.
368 for (size_t i = 0; i < mixer_inputs_.size(); ++i)
369 mixer_inputs_[i]->Start();
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();
377 ASSERT_TRUE(RenderAndValidateAudioData(std::max(
378 mixer_inputs_.size() / 2, static_cast<size_t>(1))));
380 for (size_t i = 1; i < mixer_inputs_.size(); i += 2)
381 mixer_inputs_[i]->Stop();
384 TEST_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);
392 mixer_callback_->OnRenderError();
393 for (size_t i = 0; i < mixer_inputs_.size(); ++i)
394 mixer_inputs_[i]->Stop();
397 // Ensure constructing an AudioRendererMixerInput, but not initializing it does
398 // not call RemoveMixer().
399 TEST_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)));
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.
411 TEST_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);
417 base::WaitableEvent pause_event(true, false);
418 EXPECT_CALL(*sink_.get(), Pause()).Times(2)
419 .WillRepeatedly(SignalEvent(&pause_event));
420 InitializeInputs(1);
422 // Ensure never playing the input results in a sink pause.
423 const base::TimeDelta kSleepTime = base::TimeDelta::FromMilliseconds(100);
424 base::TimeTicks start_time = base::TimeTicks::Now();
425 while (!pause_event.IsSignaled()) {
426 mixer_callback_->Render(audio_bus_.get(), 0);
427 base::PlatformThread::Sleep(kSleepTime);
428 ASSERT_TRUE(base::TimeTicks::Now() - start_time < kTestTimeout);
430 pause_event.Reset();
432 // Playing the input for the first time should cause a sink play.
433 mixer_inputs_[0]->Start();
434 EXPECT_CALL(*sink_.get(), Play());
435 mixer_inputs_[0]->Play();
436 mixer_inputs_[0]->Pause();
438 // Ensure once the input is paused the sink eventually pauses.
439 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);
446 mixer_inputs_[0]->Stop();
449 INSTANTIATE_TEST_CASE_P(
450 AudioRendererMixerTest, AudioRendererMixerTest, testing::Values(
451 // No resampling.
452 std::tr1::make_tuple(44100, 44100, 0.00000048),
454 // Upsampling.
455 std::tr1::make_tuple(44100, 48000, 0.033),
457 // Downsampling.
458 std::tr1::make_tuple(48000, 41000, 0.042)));
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.
463 INSTANTIATE_TEST_CASE_P(
464 AudioRendererMixerBehavioralTest, AudioRendererMixerBehavioralTest,
465 testing::ValuesIn(std::vector<AudioRendererMixerTestData>(
466 1, std::tr1::make_tuple(44100, 44100, 0))));
468 } // namespace media