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.
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"
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
;
26 static const int kRenderFrameId
= 124;
27 static const int kAnotherRenderFrameId
= 678;
29 using media::AudioParameters
;
31 class AudioRendererMixerManagerTest
: public testing::Test
{
33 AudioRendererMixerManagerTest()
34 : fake_config_(AudioParameters(), AudioParameters()) {
35 AudioParameters
output_params(
36 AudioParameters::AUDIO_PCM_LOW_LATENCY
,
37 media::CHANNEL_LAYOUT_STEREO
,
41 fake_config_
.UpdateOutputConfig(output_params
);
43 manager_
.reset(new AudioRendererMixerManager(&fake_config_
));
45 // We don't want to deal with instantiating a real AudioOutputDevice since
46 // it's not important to our testing, so we inject a mock.
47 mock_sink_
= new media::MockAudioRendererSink();
48 manager_
->SetAudioRendererSinkForTesting(mock_sink_
.get());
51 media::AudioRendererMixer
* GetMixer(int source_render_frame_id
,
52 const media::AudioParameters
& params
) {
53 return manager_
->GetMixer(source_render_frame_id
, params
);
56 void RemoveMixer(int source_render_frame_id
,
57 const media::AudioParameters
& params
) {
58 return manager_
->RemoveMixer(source_render_frame_id
, params
);
61 // Number of instantiated mixers.
63 return manager_
->mixers_
.size();
67 media::AudioHardwareConfig fake_config_
;
68 scoped_ptr
<AudioRendererMixerManager
> manager_
;
69 scoped_refptr
<media::MockAudioRendererSink
> mock_sink_
;
71 DISALLOW_COPY_AND_ASSIGN(AudioRendererMixerManagerTest
);
74 // Verify GetMixer() and RemoveMixer() both work as expected; particularly with
75 // respect to the explicit ref counting done.
76 TEST_F(AudioRendererMixerManagerTest
, GetRemoveMixer
) {
77 // Since we're testing two different sets of parameters, we expect
78 // AudioRendererMixerManager to call Start and Stop on our mock twice.
79 EXPECT_CALL(*mock_sink_
.get(), Start()).Times(2);
80 EXPECT_CALL(*mock_sink_
.get(), Stop()).Times(2);
82 // There should be no mixers outstanding to start with.
83 EXPECT_EQ(mixer_count(), 0);
85 media::AudioParameters
params1(
86 AudioParameters::AUDIO_PCM_LINEAR
, kChannelLayout
, kSampleRate
,
87 kBitsPerChannel
, kBufferSize
);
89 media::AudioRendererMixer
* mixer1
= GetMixer(kRenderFrameId
, params1
);
91 EXPECT_EQ(mixer_count(), 1);
93 // The same parameters should return the same mixer1.
94 EXPECT_EQ(mixer1
, GetMixer(kRenderFrameId
, params1
));
95 EXPECT_EQ(mixer_count(), 1);
97 // Remove the extra mixer we just acquired.
98 RemoveMixer(kRenderFrameId
, params1
);
99 EXPECT_EQ(mixer_count(), 1);
101 media::AudioParameters
params2(
102 AudioParameters::AUDIO_PCM_LINEAR
, kChannelLayout
, kSampleRate
* 2,
103 kBitsPerChannel
, kBufferSize
* 2);
104 media::AudioRendererMixer
* mixer2
= GetMixer(kRenderFrameId
, params2
);
106 EXPECT_EQ(mixer_count(), 2);
108 // Different parameters should result in a different mixer1.
109 EXPECT_NE(mixer1
, mixer2
);
111 // Remove both outstanding mixers.
112 RemoveMixer(kRenderFrameId
, params1
);
113 EXPECT_EQ(mixer_count(), 1);
114 RemoveMixer(kRenderFrameId
, params2
);
115 EXPECT_EQ(mixer_count(), 0);
118 // Verify GetMixer() correctly deduplicates mixer with irrelevant AudioParameter
120 TEST_F(AudioRendererMixerManagerTest
, MixerReuse
) {
121 EXPECT_CALL(*mock_sink_
.get(), Start()).Times(2);
122 EXPECT_CALL(*mock_sink_
.get(), Stop()).Times(2);
123 EXPECT_EQ(mixer_count(), 0);
125 media::AudioParameters
params1(AudioParameters::AUDIO_PCM_LINEAR
,
130 media::AudioRendererMixer
* mixer1
= GetMixer(kRenderFrameId
, params1
);
132 EXPECT_EQ(mixer_count(), 1);
134 // Different formats, bit depths, and buffer sizes should not result in a
136 media::AudioParameters
params2(AudioParameters::AUDIO_PCM_LOW_LATENCY
,
141 AudioParameters::NO_EFFECTS
);
142 EXPECT_EQ(mixer1
, GetMixer(kRenderFrameId
, params2
));
143 EXPECT_EQ(mixer_count(), 1);
144 RemoveMixer(kRenderFrameId
, params2
);
145 EXPECT_EQ(mixer_count(), 1);
147 // Modify some parameters that do matter.
148 media::AudioParameters
params3(AudioParameters::AUDIO_PCM_LOW_LATENCY
,
149 media::CHANNEL_LAYOUT_MONO
,
153 AudioParameters::NO_EFFECTS
);
154 ASSERT_NE(params3
.channel_layout(), params1
.channel_layout());
156 EXPECT_NE(mixer1
, GetMixer(kRenderFrameId
, params3
));
157 EXPECT_EQ(mixer_count(), 2);
158 RemoveMixer(kRenderFrameId
, params3
);
159 EXPECT_EQ(mixer_count(), 1);
161 // Remove final mixer.
162 RemoveMixer(kRenderFrameId
, params1
);
163 EXPECT_EQ(mixer_count(), 0);
166 // Verify CreateInput() provides AudioRendererMixerInput with the appropriate
167 // callbacks and they are working as expected. Also, verify that separate
168 // mixers are created for separate render views, even though the AudioParameters
170 TEST_F(AudioRendererMixerManagerTest
, CreateInput
) {
171 // Expect AudioRendererMixerManager to call Start and Stop on our mock twice
172 // each. Note: Under normal conditions, each mixer would get its own sink!
173 EXPECT_CALL(*mock_sink_
.get(), Start()).Times(2);
174 EXPECT_CALL(*mock_sink_
.get(), Stop()).Times(2);
176 media::AudioParameters
params(
177 AudioParameters::AUDIO_PCM_LINEAR
, kChannelLayout
, kSampleRate
,
178 kBitsPerChannel
, kBufferSize
);
180 // Create two mixer inputs and ensure this doesn't instantiate any mixers yet.
181 EXPECT_EQ(mixer_count(), 0);
182 media::FakeAudioRenderCallback
callback(0);
183 scoped_refptr
<media::AudioRendererMixerInput
> input(
184 manager_
->CreateInput(kRenderFrameId
));
185 input
->Initialize(params
, &callback
);
186 EXPECT_EQ(mixer_count(), 0);
187 media::FakeAudioRenderCallback
another_callback(1);
188 scoped_refptr
<media::AudioRendererMixerInput
> another_input(
189 manager_
->CreateInput(kAnotherRenderFrameId
));
190 another_input
->Initialize(params
, &another_callback
);
191 EXPECT_EQ(mixer_count(), 0);
193 // Implicitly test that AudioRendererMixerInput was provided with the expected
194 // callbacks needed to acquire an AudioRendererMixer and remove it.
196 EXPECT_EQ(mixer_count(), 1);
197 another_input
->Start();
198 EXPECT_EQ(mixer_count(), 2);
200 // Destroying the inputs should destroy the mixers.
203 EXPECT_EQ(mixer_count(), 1);
204 another_input
->Stop();
205 another_input
= NULL
;
206 EXPECT_EQ(mixer_count(), 0);
209 } // namespace content