Home | History | Annotate | Download | only in media
      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 #include "base/logging.h"
      6 #include "base/memory/ref_counted.h"
      7 #include "base/memory/scoped_ptr.h"
      8 #include "content/renderer/media/audio_renderer_mixer_manager.h"
      9 #include "media/audio/audio_parameters.h"
     10 #include "media/base/audio_hardware_config.h"
     11 #include "media/base/audio_renderer_mixer.h"
     12 #include "media/base/audio_renderer_mixer_input.h"
     13 #include "media/base/fake_audio_render_callback.h"
     14 #include "media/base/mock_audio_renderer_sink.h"
     15 #include "testing/gmock/include/gmock/gmock.h"
     16 #include "testing/gtest/include/gtest/gtest.h"
     17 
     18 namespace content {
     19 
     20 static const int kBitsPerChannel = 16;
     21 static const int kSampleRate = 48000;
     22 static const int kBufferSize = 8192;
     23 static const media::ChannelLayout kChannelLayout = media::CHANNEL_LAYOUT_STEREO;
     24 
     25 static const int kRenderViewId = 123;
     26 static const int kAnotherRenderViewId = 456;
     27 
     28 using media::AudioParameters;
     29 
     30 class AudioRendererMixerManagerTest : public testing::Test {
     31  public:
     32   AudioRendererMixerManagerTest()
     33       : fake_config_(AudioParameters(), AudioParameters()) {
     34     AudioParameters output_params(
     35         media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
     36         media::CHANNEL_LAYOUT_STEREO,
     37         kSampleRate,
     38         16,
     39         kBufferSize);
     40     fake_config_.UpdateOutputConfig(output_params);
     41 
     42     manager_.reset(new AudioRendererMixerManager(&fake_config_));
     43 
     44     // We don't want to deal with instantiating a real AudioOutputDevice since
     45     // it's not important to our testing, so we inject a mock.
     46     mock_sink_ = new media::MockAudioRendererSink();
     47     manager_->SetAudioRendererSinkForTesting(mock_sink_.get());
     48   }
     49 
     50   media::AudioRendererMixer* GetMixer(int source_render_view_id,
     51                                       const media::AudioParameters& params) {
     52     return manager_->GetMixer(source_render_view_id, params);
     53   }
     54 
     55   void RemoveMixer(int source_render_view_id,
     56                    const media::AudioParameters& params) {
     57     return manager_->RemoveMixer(source_render_view_id, params);
     58   }
     59 
     60   // Number of instantiated mixers.
     61   int mixer_count() {
     62     return manager_->mixers_.size();
     63   }
     64 
     65  protected:
     66   media::AudioHardwareConfig fake_config_;
     67   scoped_ptr<AudioRendererMixerManager> manager_;
     68   scoped_refptr<media::MockAudioRendererSink> mock_sink_;
     69 
     70   DISALLOW_COPY_AND_ASSIGN(AudioRendererMixerManagerTest);
     71 };
     72 
     73 // Verify GetMixer() and RemoveMixer() both work as expected; particularly with
     74 // respect to the explicit ref counting done.
     75 TEST_F(AudioRendererMixerManagerTest, GetRemoveMixer) {
     76   // Since we're testing two different sets of parameters, we expect
     77   // AudioRendererMixerManager to call Start and Stop on our mock twice.
     78   EXPECT_CALL(*mock_sink_.get(), Start()).Times(2);
     79   EXPECT_CALL(*mock_sink_.get(), Stop()).Times(2);
     80 
     81   // There should be no mixers outstanding to start with.
     82   EXPECT_EQ(mixer_count(), 0);
     83 
     84   media::AudioParameters params1(
     85       media::AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, kSampleRate,
     86       kBitsPerChannel, kBufferSize);
     87 
     88   media::AudioRendererMixer* mixer1 = GetMixer(kRenderViewId, params1);
     89   ASSERT_TRUE(mixer1);
     90   EXPECT_EQ(mixer_count(), 1);
     91 
     92   // The same parameters should return the same mixer1.
     93   EXPECT_EQ(mixer1, GetMixer(kRenderViewId, params1));
     94   EXPECT_EQ(mixer_count(), 1);
     95 
     96   // Remove the extra mixer we just acquired.
     97   RemoveMixer(kRenderViewId, params1);
     98   EXPECT_EQ(mixer_count(), 1);
     99 
    100   media::AudioParameters params2(
    101       media::AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, kSampleRate * 2,
    102       kBitsPerChannel, kBufferSize * 2);
    103   media::AudioRendererMixer* mixer2 = GetMixer(kRenderViewId, params2);
    104   ASSERT_TRUE(mixer2);
    105   EXPECT_EQ(mixer_count(), 2);
    106 
    107   // Different parameters should result in a different mixer1.
    108   EXPECT_NE(mixer1, mixer2);
    109 
    110   // Remove both outstanding mixers.
    111   RemoveMixer(kRenderViewId, params1);
    112   EXPECT_EQ(mixer_count(), 1);
    113   RemoveMixer(kRenderViewId, params2);
    114   EXPECT_EQ(mixer_count(), 0);
    115 }
    116 
    117 // Verify CreateInput() provides AudioRendererMixerInput with the appropriate
    118 // callbacks and they are working as expected.  Also, verify that separate
    119 // mixers are created for separate render views, even though the AudioParameters
    120 // are the same.
    121 TEST_F(AudioRendererMixerManagerTest, CreateInput) {
    122   // Expect AudioRendererMixerManager to call Start and Stop on our mock twice
    123   // each.  Note: Under normal conditions, each mixer would get its own sink!
    124   EXPECT_CALL(*mock_sink_.get(), Start()).Times(2);
    125   EXPECT_CALL(*mock_sink_.get(), Stop()).Times(2);
    126 
    127   media::AudioParameters params(
    128       media::AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, kSampleRate,
    129       kBitsPerChannel, kBufferSize);
    130 
    131   // Create two mixer inputs and ensure this doesn't instantiate any mixers yet.
    132   EXPECT_EQ(mixer_count(), 0);
    133   scoped_refptr<media::AudioRendererMixerInput> input(
    134       manager_->CreateInput(kRenderViewId));
    135   EXPECT_EQ(mixer_count(), 0);
    136   scoped_refptr<media::AudioRendererMixerInput> another_input(
    137       manager_->CreateInput(kAnotherRenderViewId));
    138   EXPECT_EQ(mixer_count(), 0);
    139 
    140   // Implicitly test that AudioRendererMixerInput was provided with the expected
    141   // callbacks needed to acquire an AudioRendererMixer and remove it.
    142   media::FakeAudioRenderCallback callback(0);
    143   input->Initialize(params, &callback);
    144   EXPECT_EQ(mixer_count(), 1);
    145   media::FakeAudioRenderCallback another_callback(1);
    146   another_input->Initialize(params, &another_callback);
    147   EXPECT_EQ(mixer_count(), 2);
    148 
    149   // Destroying the inputs should destroy the mixers.
    150   input = NULL;
    151   EXPECT_EQ(mixer_count(), 1);
    152   another_input = NULL;
    153   EXPECT_EQ(mixer_count(), 0);
    154 }
    155 
    156 }  // namespace content
    157