• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
AudioRendererMixerTest()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 
GetMixer(const AudioParameters & params)70   AudioRendererMixer* GetMixer(const AudioParameters& params) {
71     return mixer_.get();
72   }
73 
74   MOCK_METHOD1(RemoveMixer, void(const AudioParameters&));
75 
InitializeInputs(int count)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 
ValidateAudioData(int index,int frames,float scale,double epsilon)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 
ValidateAudioData(int index,int frames,float scale)115   bool ValidateAudioData(int index, int frames, float scale) {
116     return ValidateAudioData(index, frames, scale, epsilon_);
117   }
118 
RenderAndValidateAudioData(float scale)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|.
FillAudioData(float 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().
StartTest(int inputs)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.
PlayTest(int inputs)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.
PlayVolumeAdjustedTest(int inputs)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().
PlayPartialRenderTest(int inputs)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.
PauseTest(int inputs)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.
StopTest(int inputs)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:
~AudioRendererMixerTest()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 
ACTION_P(SignalEvent,event)292 ACTION_P(SignalEvent, event) {
293   event->Signal();
294 }
295 
296 // Verify a mixer with no inputs returns silence for all requested frames.
TEST_P(AudioRendererMixerTest,NoInputs)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.
TEST_P(AudioRendererMixerTest,OneInputStart)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.
TEST_P(AudioRendererMixerTest,ManyInputStart)308 TEST_P(AudioRendererMixerTest, ManyInputStart) {
309   StartTest(kMixerInputs);
310 }
311 
312 // Test mixer output with one input in the post-Play() state.
TEST_P(AudioRendererMixerTest,OneInputPlay)313 TEST_P(AudioRendererMixerTest, OneInputPlay) {
314   PlayTest(1);
315 }
316 
317 // Test mixer output with many inputs in the post-Play() state.
TEST_P(AudioRendererMixerTest,ManyInputPlay)318 TEST_P(AudioRendererMixerTest, ManyInputPlay) {
319   PlayTest(kMixerInputs);
320 }
321 
322 // Test volume adjusted mixer output with one input in the post-Play() state.
TEST_P(AudioRendererMixerTest,OneInputPlayVolumeAdjusted)323 TEST_P(AudioRendererMixerTest, OneInputPlayVolumeAdjusted) {
324   PlayVolumeAdjustedTest(1);
325 }
326 
327 // Test volume adjusted mixer output with many inputs in the post-Play() state.
TEST_P(AudioRendererMixerTest,ManyInputPlayVolumeAdjusted)328 TEST_P(AudioRendererMixerTest, ManyInputPlayVolumeAdjusted) {
329   PlayVolumeAdjustedTest(kMixerInputs);
330 }
331 
332 // Test mixer output with one input and partial Render() in post-Play() state.
TEST_P(AudioRendererMixerTest,OneInputPlayPartialRender)333 TEST_P(AudioRendererMixerTest, OneInputPlayPartialRender) {
334   PlayPartialRenderTest(1);
335 }
336 
337 // Test mixer output with many inputs and partial Render() in post-Play() state.
TEST_P(AudioRendererMixerTest,ManyInputPlayPartialRender)338 TEST_P(AudioRendererMixerTest, ManyInputPlayPartialRender) {
339   PlayPartialRenderTest(kMixerInputs);
340 }
341 
342 // Test mixer output with one input in the post-Pause() state.
TEST_P(AudioRendererMixerTest,OneInputPause)343 TEST_P(AudioRendererMixerTest, OneInputPause) {
344   PauseTest(1);
345 }
346 
347 // Test mixer output with many inputs in the post-Pause() state.
TEST_P(AudioRendererMixerTest,ManyInputPause)348 TEST_P(AudioRendererMixerTest, ManyInputPause) {
349   PauseTest(kMixerInputs);
350 }
351 
352 // Test mixer output with one input in the post-Stop() state.
TEST_P(AudioRendererMixerTest,OneInputStop)353 TEST_P(AudioRendererMixerTest, OneInputStop) {
354   StopTest(1);
355 }
356 
357 // Test mixer output with many inputs in the post-Stop() state.
TEST_P(AudioRendererMixerTest,ManyInputStop)358 TEST_P(AudioRendererMixerTest, ManyInputStop) {
359   StopTest(kMixerInputs);
360 }
361 
362 // Test mixer with many inputs in mixed post-Stop() and post-Play() states.
TEST_P(AudioRendererMixerTest,ManyInputMixedStopPlay)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 
TEST_P(AudioRendererMixerBehavioralTest,OnRenderError)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 // Ensure constructing an AudioRendererMixerInput, but not initializing it does
397 // not call RemoveMixer().
TEST_P(AudioRendererMixerBehavioralTest,NoInitialize)398 TEST_P(AudioRendererMixerBehavioralTest, NoInitialize) {
399   EXPECT_CALL(*this, RemoveMixer(testing::_)).Times(0);
400   scoped_refptr<AudioRendererMixerInput> audio_renderer_mixer =
401       new AudioRendererMixerInput(
402           base::Bind(&AudioRendererMixerTest::GetMixer,
403                      base::Unretained(this)),
404           base::Bind(&AudioRendererMixerTest::RemoveMixer,
405                      base::Unretained(this)));
406 }
407 
408 // Ensure the physical stream is paused after a certain amount of time with no
409 // inputs playing.  The test will hang if the behavior is incorrect.
TEST_P(AudioRendererMixerBehavioralTest,MixerPausesStream)410 TEST_P(AudioRendererMixerBehavioralTest, MixerPausesStream) {
411   const base::TimeDelta kPauseTime = base::TimeDelta::FromMilliseconds(500);
412   // This value can't be too low or valgrind, tsan will timeout on the bots.
413   const base::TimeDelta kTestTimeout = 10 * kPauseTime;
414   mixer_->set_pause_delay_for_testing(kPauseTime);
415 
416   base::WaitableEvent pause_event(true, false);
417   EXPECT_CALL(*sink_.get(), Pause()).Times(2)
418       .WillRepeatedly(SignalEvent(&pause_event));
419   InitializeInputs(1);
420 
421   // Ensure never playing the input results in a sink pause.
422   const base::TimeDelta kSleepTime = base::TimeDelta::FromMilliseconds(100);
423   base::TimeTicks start_time = base::TimeTicks::Now();
424   while (!pause_event.IsSignaled()) {
425     mixer_callback_->Render(audio_bus_.get(), 0);
426     base::PlatformThread::Sleep(kSleepTime);
427     ASSERT_TRUE(base::TimeTicks::Now() - start_time < kTestTimeout);
428   }
429   pause_event.Reset();
430 
431   // Playing the input for the first time should cause a sink play.
432   mixer_inputs_[0]->Start();
433   EXPECT_CALL(*sink_.get(), Play());
434   mixer_inputs_[0]->Play();
435   mixer_inputs_[0]->Pause();
436 
437   // Ensure once the input is paused the sink eventually pauses.
438   start_time = base::TimeTicks::Now();
439   while (!pause_event.IsSignaled()) {
440     mixer_callback_->Render(audio_bus_.get(), 0);
441     base::PlatformThread::Sleep(kSleepTime);
442     ASSERT_TRUE(base::TimeTicks::Now() - start_time < kTestTimeout);
443   }
444 
445   mixer_inputs_[0]->Stop();
446 }
447 
448 INSTANTIATE_TEST_CASE_P(
449     AudioRendererMixerTest, AudioRendererMixerTest, testing::Values(
450         // No resampling.
451         std::tr1::make_tuple(44100, 44100, 0.00000048),
452 
453         // Upsampling.
454         std::tr1::make_tuple(44100, 48000, 0.033),
455 
456         // Downsampling.
457         std::tr1::make_tuple(48000, 41000, 0.042)));
458 
459 // Test cases for behavior which is independent of parameters.  Values() doesn't
460 // support single item lists and we don't want these test cases to run for every
461 // parameter set.
462 INSTANTIATE_TEST_CASE_P(
463     AudioRendererMixerBehavioralTest, AudioRendererMixerBehavioralTest,
464     testing::ValuesIn(std::vector<AudioRendererMixerTestData>(
465         1, std::tr1::make_tuple(44100, 44100, 0))));
466 
467 }  // namespace media
468