Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / media / base / audio_renderer_mixer_unittest.cc
blob6cca1ddb9678694420ca0a80a8adb6897c7c9bdc
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 const int kMixerInputs = 8;
26 const int kMixerCycles = 3;
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;
34 // Number of full sine wave cycles for each Render() call.
35 const int kSineCycles = 4;
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);
53 sink_ = new MockAudioRendererSink();
54 EXPECT_CALL(*sink_.get(), Start());
55 EXPECT_CALL(*sink_.get(), Stop());
57 mixer_.reset(new AudioRendererMixer(
58 input_parameters_, output_parameters_, sink_));
59 mixer_callback_ = sink_->callback();
61 audio_bus_ = AudioBus::Create(output_parameters_);
62 expected_audio_bus_ = AudioBus::Create(output_parameters_);
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));
70 AudioRendererMixer* GetMixer(const AudioParameters& params) {
71 return mixer_.get();
74 MOCK_METHOD1(RemoveMixer, void(const AudioParameters&));
76 void InitializeInputs(int count) {
77 mixer_inputs_.reserve(count);
78 fake_callbacks_.reserve(count);
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()));
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);
96 EXPECT_CALL(*this, RemoveMixer(testing::_)).Times(count);
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;
112 return true;
115 bool ValidateAudioData(int index, int frames, float scale) {
116 return ValidateAudioData(index, frames, scale, epsilon_);
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();
129 // Render actual audio data.
130 int frames = mixer_callback_->Render(audio_bus_.get(), 0);
131 if (frames != audio_bus_->frames())
132 return false;
134 // Render expected audio data (without scaling).
135 expected_callback_->Render(expected_audio_bus_.get(), 0);
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);
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);
155 // Verify silence when mixer inputs are in pre-Start() and post-Start().
156 void StartTest(int inputs) {
157 InitializeInputs(inputs);
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));
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));
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));
176 for (size_t i = 0; i < mixer_inputs_.size(); ++i)
177 mixer_inputs_[i]->Stop();
180 // Verify output when mixer inputs are in post-Play() state.
181 void PlayTest(int inputs) {
182 InitializeInputs(inputs);
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();
190 for (int i = 0; i < kMixerCycles; ++i)
191 ASSERT_TRUE(RenderAndValidateAudioData(mixer_inputs_.size()));
193 for (size_t i = 0; i < mixer_inputs_.size(); ++i)
194 mixer_inputs_[i]->Stop();
197 // Verify volume adjusted output when mixer inputs are in post-Play() state.
198 void PlayVolumeAdjustedTest(int inputs) {
199 InitializeInputs(inputs);
201 for (size_t i = 0; i < mixer_inputs_.size(); ++i) {
202 mixer_inputs_[i]->Start();
203 mixer_inputs_[i]->Play();
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));
213 for (int i = 0; i < kMixerCycles; ++i)
214 ASSERT_TRUE(RenderAndValidateAudioData(total_scale));
216 for (size_t i = 0; i < mixer_inputs_.size(); ++i)
217 mixer_inputs_[i]->Stop();
220 // Verify output when mixer inputs can only partially fulfill a Render().
221 void PlayPartialRenderTest(int inputs) {
222 InitializeInputs(inputs);
224 for (size_t i = 0; i < mixer_inputs_.size(); ++i) {
225 mixer_inputs_[i]->Start();
226 mixer_inputs_[i]->Play();
229 // Verify a properly filled buffer when half filled (remainder zeroed).
230 half_fill_ = true;
231 ASSERT_TRUE(RenderAndValidateAudioData(mixer_inputs_.size()));
233 for (size_t i = 0; i < mixer_inputs_.size(); ++i)
234 mixer_inputs_[i]->Stop();
237 // Verify output when mixer inputs are in Pause() state.
238 void PauseTest(int inputs) {
239 InitializeInputs(inputs);
241 for (size_t i = 0; i < mixer_inputs_.size(); ++i) {
242 mixer_inputs_[i]->Start();
243 mixer_inputs_[i]->Play();
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));
252 for (size_t i = 0; i < mixer_inputs_.size(); ++i)
253 mixer_inputs_[i]->Stop();
256 // Verify output when mixer inputs are in post-Stop() state.
257 void StopTest(int inputs) {
258 InitializeInputs(inputs);
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();
266 // Verify we get silence back; fill |audio_bus_| before hand to be sure.
267 FillAudioData(1.0f);
268 EXPECT_TRUE(RenderAndValidateAudioData(0.0f));
271 protected:
272 virtual ~AudioRendererMixerTest() {}
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_;
287 DISALLOW_COPY_AND_ASSIGN(AudioRendererMixerTest);
290 class AudioRendererMixerBehavioralTest : public AudioRendererMixerTest {};
292 ACTION_P(SignalEvent, event) {
293 event->Signal();
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));
302 // Test mixer output with one input in the pre-Start() and post-Start() state.
303 TEST_P(AudioRendererMixerTest, OneInputStart) {
304 StartTest(1);
307 // Test mixer output with many inputs in the pre-Start() and post-Start() state.
308 TEST_P(AudioRendererMixerTest, ManyInputStart) {
309 StartTest(kMixerInputs);
312 // Test mixer output with one input in the post-Play() state.
313 TEST_P(AudioRendererMixerTest, OneInputPlay) {
314 PlayTest(1);
317 // Test mixer output with many inputs in the post-Play() state.
318 TEST_P(AudioRendererMixerTest, ManyInputPlay) {
319 PlayTest(kMixerInputs);
322 // Test volume adjusted mixer output with one input in the post-Play() state.
323 TEST_P(AudioRendererMixerTest, OneInputPlayVolumeAdjusted) {
324 PlayVolumeAdjustedTest(1);
327 // Test volume adjusted mixer output with many inputs in the post-Play() state.
328 TEST_P(AudioRendererMixerTest, ManyInputPlayVolumeAdjusted) {
329 PlayVolumeAdjustedTest(kMixerInputs);
332 // Test mixer output with one input and partial Render() in post-Play() state.
333 TEST_P(AudioRendererMixerTest, OneInputPlayPartialRender) {
334 PlayPartialRenderTest(1);
337 // Test mixer output with many inputs and partial Render() in post-Play() state.
338 TEST_P(AudioRendererMixerTest, ManyInputPlayPartialRender) {
339 PlayPartialRenderTest(kMixerInputs);
342 // Test mixer output with one input in the post-Pause() state.
343 TEST_P(AudioRendererMixerTest, OneInputPause) {
344 PauseTest(1);
347 // Test mixer output with many inputs in the post-Pause() state.
348 TEST_P(AudioRendererMixerTest, ManyInputPause) {
349 PauseTest(kMixerInputs);
352 // Test mixer output with one input in the post-Stop() state.
353 TEST_P(AudioRendererMixerTest, OneInputStop) {
354 StopTest(1);
357 // Test mixer output with many inputs in the post-Stop() state.
358 TEST_P(AudioRendererMixerTest, ManyInputStop) {
359 StopTest(kMixerInputs);
362 // Test mixer with many inputs in mixed post-Stop() and post-Play() states.
363 TEST_P(AudioRendererMixerTest, ManyInputMixedStopPlay) {
364 InitializeInputs(kMixerInputs);
366 // Start() all inputs.
367 for (size_t i = 0; i < mixer_inputs_.size(); ++i)
368 mixer_inputs_[i]->Start();
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();
376 ASSERT_TRUE(RenderAndValidateAudioData(std::max(
377 mixer_inputs_.size() / 2, static_cast<size_t>(1))));
379 for (size_t i = 1; i < mixer_inputs_.size(); i += 2)
380 mixer_inputs_[i]->Stop();
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);
391 mixer_callback_->OnRenderError();
392 for (size_t i = 0; i < mixer_inputs_.size(); ++i)
393 mixer_inputs_[i]->Stop();
396 TEST_P(AudioRendererMixerBehavioralTest, OnRenderErrorPausedInput) {
397 InitializeInputs(kMixerInputs);
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);
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();
408 for (size_t i = 0; i < mixer_inputs_.size(); ++i)
409 mixer_inputs_[i]->Stop();
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)));
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);
432 base::WaitableEvent pause_event(true, false);
433 EXPECT_CALL(*sink_.get(), Pause()).Times(2)
434 .WillRepeatedly(SignalEvent(&pause_event));
435 InitializeInputs(1);
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);
445 pause_event.Reset();
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();
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);
461 mixer_inputs_[0]->Stop();
464 INSTANTIATE_TEST_CASE_P(
465 AudioRendererMixerTest, AudioRendererMixerTest, testing::Values(
466 // No resampling.
467 std::tr1::make_tuple(44100, 44100, 0.00000048),
469 // Upsampling.
470 std::tr1::make_tuple(44100, 48000, 0.033),
472 // Downsampling.
473 std::tr1::make_tuple(48000, 41000, 0.042)));
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))));
483 } // namespace media