Home | History | Annotate | Download | only in base
      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 static const int kMixerInputs = 8;
     26 static const int kMixerCycles = 3;
     27 
     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;
     34 
     35 // Number of full sine wave cycles for each Render() call.
     36 static const int kSineCycles = 4;
     37 
     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);
     53 
     54     sink_ = new MockAudioRendererSink();
     55     EXPECT_CALL(*sink_.get(), Start());
     56     EXPECT_CALL(*sink_.get(), 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 
    291 class AudioRendererMixerBehavioralTest : public AudioRendererMixerTest {};
    292 
    293 ACTION_P(SignalEvent, event) {
    294   event->Signal();
    295 }
    296 
    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));
    301 }
    302 
    303 // Test mixer output with one input in the pre-Start() and post-Start() state.
    304 TEST_P(AudioRendererMixerTest, OneInputStart) {
    305   StartTest(1);
    306 }
    307 
    308 // Test mixer output with many inputs in the pre-Start() and post-Start() state.
    309 TEST_P(AudioRendererMixerTest, ManyInputStart) {
    310   StartTest(kMixerInputs);
    311 }
    312 
    313 // Test mixer output with one input in the post-Play() state.
    314 TEST_P(AudioRendererMixerTest, OneInputPlay) {
    315   PlayTest(1);
    316 }
    317 
    318 // Test mixer output with many inputs in the post-Play() state.
    319 TEST_P(AudioRendererMixerTest, ManyInputPlay) {
    320   PlayTest(kMixerInputs);
    321 }
    322 
    323 // Test volume adjusted mixer output with one input in the post-Play() state.
    324 TEST_P(AudioRendererMixerTest, OneInputPlayVolumeAdjusted) {
    325   PlayVolumeAdjustedTest(1);
    326 }
    327 
    328 // Test volume adjusted mixer output with many inputs in the post-Play() state.
    329 TEST_P(AudioRendererMixerTest, ManyInputPlayVolumeAdjusted) {
    330   PlayVolumeAdjustedTest(kMixerInputs);
    331 }
    332 
    333 // Test mixer output with one input and partial Render() in post-Play() state.
    334 TEST_P(AudioRendererMixerTest, OneInputPlayPartialRender) {
    335   PlayPartialRenderTest(1);
    336 }
    337 
    338 // Test mixer output with many inputs and partial Render() in post-Play() state.
    339 TEST_P(AudioRendererMixerTest, ManyInputPlayPartialRender) {
    340   PlayPartialRenderTest(kMixerInputs);
    341 }
    342 
    343 // Test mixer output with one input in the post-Pause() state.
    344 TEST_P(AudioRendererMixerTest, OneInputPause) {
    345   PauseTest(1);
    346 }
    347 
    348 // Test mixer output with many inputs in the post-Pause() state.
    349 TEST_P(AudioRendererMixerTest, ManyInputPause) {
    350   PauseTest(kMixerInputs);
    351 }
    352 
    353 // Test mixer output with one input in the post-Stop() state.
    354 TEST_P(AudioRendererMixerTest, OneInputStop) {
    355   StopTest(1);
    356 }
    357 
    358 // Test mixer output with many inputs in the post-Stop() state.
    359 TEST_P(AudioRendererMixerTest, ManyInputStop) {
    360   StopTest(kMixerInputs);
    361 }
    362 
    363 // Test mixer with many inputs in mixed post-Stop() and post-Play() states.
    364 TEST_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 
    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);
    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().
    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)));
    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.
    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);
    416 
    417   base::WaitableEvent pause_event(true, false);
    418   EXPECT_CALL(*sink_.get(), Pause()).Times(2)
    419       .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::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);
    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_.get(), 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::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);
    444   }
    445 
    446   mixer_inputs_[0]->Stop();
    447 }
    448 
    449 INSTANTIATE_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.
    463 INSTANTIATE_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