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 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:
     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 
     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 
    290 class AudioRendererMixerBehavioralTest : public AudioRendererMixerTest {};
    291 
    292 ACTION_P(SignalEvent, event) {
    293   event->Signal();
    294 }
    295 
    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));
    300 }
    301 
    302 // Test mixer output with one input in the pre-Start() and post-Start() state.
    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.
    308 TEST_P(AudioRendererMixerTest, ManyInputStart) {
    309   StartTest(kMixerInputs);
    310 }
    311 
    312 // Test mixer output with one input in the post-Play() state.
    313 TEST_P(AudioRendererMixerTest, OneInputPlay) {
    314   PlayTest(1);
    315 }
    316 
    317 // Test mixer output with many inputs in the post-Play() state.
    318 TEST_P(AudioRendererMixerTest, ManyInputPlay) {
    319   PlayTest(kMixerInputs);
    320 }
    321 
    322 // Test volume adjusted mixer output with one input in the post-Play() state.
    323 TEST_P(AudioRendererMixerTest, OneInputPlayVolumeAdjusted) {
    324   PlayVolumeAdjustedTest(1);
    325 }
    326 
    327 // Test volume adjusted mixer output with many inputs in the post-Play() state.
    328 TEST_P(AudioRendererMixerTest, ManyInputPlayVolumeAdjusted) {
    329   PlayVolumeAdjustedTest(kMixerInputs);
    330 }
    331 
    332 // Test mixer output with one input and partial Render() in post-Play() state.
    333 TEST_P(AudioRendererMixerTest, OneInputPlayPartialRender) {
    334   PlayPartialRenderTest(1);
    335 }
    336 
    337 // Test mixer output with many inputs and partial Render() in post-Play() state.
    338 TEST_P(AudioRendererMixerTest, ManyInputPlayPartialRender) {
    339   PlayPartialRenderTest(kMixerInputs);
    340 }
    341 
    342 // Test mixer output with one input in the post-Pause() state.
    343 TEST_P(AudioRendererMixerTest, OneInputPause) {
    344   PauseTest(1);
    345 }
    346 
    347 // Test mixer output with many inputs in the post-Pause() state.
    348 TEST_P(AudioRendererMixerTest, ManyInputPause) {
    349   PauseTest(kMixerInputs);
    350 }
    351 
    352 // Test mixer output with one input in the post-Stop() state.
    353 TEST_P(AudioRendererMixerTest, OneInputStop) {
    354   StopTest(1);
    355 }
    356 
    357 // Test mixer output with many inputs in the post-Stop() state.
    358 TEST_P(AudioRendererMixerTest, ManyInputStop) {
    359   StopTest(kMixerInputs);
    360 }
    361 
    362 // Test mixer with many inputs in mixed post-Stop() and post-Play() states.
    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 
    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().
    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.
    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