audio_renderer_mixer_unittest.cc revision 46d4c2bc3267f3f028f39e7e311b0f89aba2e4fd
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.
25const int kMixerInputs = 8;
26const int kMixerCycles = 3;
27
28// Parameters used for testing.
29const int kBitsPerChannel = 32;
30const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_STEREO;
31const int kHighLatencyBufferSize = 8192;
32const int kLowLatencyBufferSize = 256;
33
34// Number of full sine wave cycles for each Render() call.
35const int kSineCycles = 4;
36
37// Tuple of <input sampling rate, output sampling rate, epsilon>.
38typedef std::tr1::tuple<int, int, double> AudioRendererMixerTestData;
39class 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_, Start());
55    EXPECT_CALL(*sink_, 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
290class AudioRendererMixerBehavioralTest : public AudioRendererMixerTest {};
291
292ACTION_P(SignalEvent, event) {
293  event->Signal();
294}
295
296// Verify a mixer with no inputs returns silence for all requested frames.
297TEST_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.
303TEST_P(AudioRendererMixerTest, OneInputStart) {
304  StartTest(1);
305}
306
307// Test mixer output with many inputs in the pre-Start() and post-Start() state.
308TEST_P(AudioRendererMixerTest, ManyInputStart) {
309  StartTest(kMixerInputs);
310}
311
312// Test mixer output with one input in the post-Play() state.
313TEST_P(AudioRendererMixerTest, OneInputPlay) {
314  PlayTest(1);
315}
316
317// Test mixer output with many inputs in the post-Play() state.
318TEST_P(AudioRendererMixerTest, ManyInputPlay) {
319  PlayTest(kMixerInputs);
320}
321
322// Test volume adjusted mixer output with one input in the post-Play() state.
323TEST_P(AudioRendererMixerTest, OneInputPlayVolumeAdjusted) {
324  PlayVolumeAdjustedTest(1);
325}
326
327// Test volume adjusted mixer output with many inputs in the post-Play() state.
328TEST_P(AudioRendererMixerTest, ManyInputPlayVolumeAdjusted) {
329  PlayVolumeAdjustedTest(kMixerInputs);
330}
331
332// Test mixer output with one input and partial Render() in post-Play() state.
333TEST_P(AudioRendererMixerTest, OneInputPlayPartialRender) {
334  PlayPartialRenderTest(1);
335}
336
337// Test mixer output with many inputs and partial Render() in post-Play() state.
338TEST_P(AudioRendererMixerTest, ManyInputPlayPartialRender) {
339  PlayPartialRenderTest(kMixerInputs);
340}
341
342// Test mixer output with one input in the post-Pause() state.
343TEST_P(AudioRendererMixerTest, OneInputPause) {
344  PauseTest(1);
345}
346
347// Test mixer output with many inputs in the post-Pause() state.
348TEST_P(AudioRendererMixerTest, ManyInputPause) {
349  PauseTest(kMixerInputs);
350}
351
352// Test mixer output with one input in the post-Stop() state.
353TEST_P(AudioRendererMixerTest, OneInputStop) {
354  StopTest(1);
355}
356
357// Test mixer output with many inputs in the post-Stop() state.
358TEST_P(AudioRendererMixerTest, ManyInputStop) {
359  StopTest(kMixerInputs);
360}
361
362// Test mixer with many inputs in mixed post-Stop() and post-Play() states.
363TEST_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
383TEST_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
396TEST_P(AudioRendererMixerBehavioralTest, OnRenderErrorPausedInput) {
397  InitializeInputs(kMixerInputs);
398
399  for (size_t i = 0; i < mixer_inputs_.size(); ++i)
400    EXPECT_CALL(*fake_callbacks_[i], OnRenderError()).Times(1);
401
402  // Fire the error before attaching any inputs.  Ensure an error is recieved
403  // even if the input is not connected.
404  mixer_callback_->OnRenderError();
405
406  for (size_t i = 0; i < mixer_inputs_.size(); ++i)
407    mixer_inputs_[i]->Stop();
408}
409
410// Ensure constructing an AudioRendererMixerInput, but not initializing it does
411// not call RemoveMixer().
412TEST_P(AudioRendererMixerBehavioralTest, NoInitialize) {
413  EXPECT_CALL(*this, RemoveMixer(testing::_)).Times(0);
414  scoped_refptr<AudioRendererMixerInput> audio_renderer_mixer =
415      new AudioRendererMixerInput(
416          base::Bind(&AudioRendererMixerTest::GetMixer,
417                     base::Unretained(this)),
418          base::Bind(&AudioRendererMixerTest::RemoveMixer,
419                     base::Unretained(this)));
420}
421
422// Ensure the physical stream is paused after a certain amount of time with no
423// inputs playing.  The test will hang if the behavior is incorrect.
424TEST_P(AudioRendererMixerBehavioralTest, MixerPausesStream) {
425  const base::TimeDelta kPauseTime = base::TimeDelta::FromMilliseconds(500);
426  // This value can't be too low or valgrind, tsan will timeout on the bots.
427  const base::TimeDelta kTestTimeout = 10 * kPauseTime;
428  mixer_->set_pause_delay_for_testing(kPauseTime);
429
430  base::WaitableEvent pause_event(true, false);
431  EXPECT_CALL(*sink_.get(), Pause()).Times(2)
432      .WillRepeatedly(SignalEvent(&pause_event));
433  InitializeInputs(1);
434
435  // Ensure never playing the input results in a sink pause.
436  const base::TimeDelta kSleepTime = base::TimeDelta::FromMilliseconds(100);
437  base::TimeTicks start_time = base::TimeTicks::Now();
438  while (!pause_event.IsSignaled()) {
439    mixer_callback_->Render(audio_bus_.get(), 0);
440    base::PlatformThread::Sleep(kSleepTime);
441    ASSERT_TRUE(base::TimeTicks::Now() - start_time < kTestTimeout);
442  }
443  pause_event.Reset();
444
445  // Playing the input for the first time should cause a sink play.
446  mixer_inputs_[0]->Start();
447  EXPECT_CALL(*sink_.get(), Play());
448  mixer_inputs_[0]->Play();
449  mixer_inputs_[0]->Pause();
450
451  // Ensure once the input is paused the sink eventually pauses.
452  start_time = base::TimeTicks::Now();
453  while (!pause_event.IsSignaled()) {
454    mixer_callback_->Render(audio_bus_.get(), 0);
455    base::PlatformThread::Sleep(kSleepTime);
456    ASSERT_TRUE(base::TimeTicks::Now() - start_time < kTestTimeout);
457  }
458
459  mixer_inputs_[0]->Stop();
460}
461
462INSTANTIATE_TEST_CASE_P(
463    AudioRendererMixerTest, AudioRendererMixerTest, testing::Values(
464        // No resampling.
465        std::tr1::make_tuple(44100, 44100, 0.00000048),
466
467        // Upsampling.
468        std::tr1::make_tuple(44100, 48000, 0.033),
469
470        // Downsampling.
471        std::tr1::make_tuple(48000, 41000, 0.042)));
472
473// Test cases for behavior which is independent of parameters.  Values() doesn't
474// support single item lists and we don't want these test cases to run for every
475// parameter set.
476INSTANTIATE_TEST_CASE_P(
477    AudioRendererMixerBehavioralTest, AudioRendererMixerBehavioralTest,
478    testing::ValuesIn(std::vector<AudioRendererMixerTestData>(
479        1, std::tr1::make_tuple(44100, 44100, 0))));
480
481}  // namespace media
482