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