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