1 // Copyright (c) 2013 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 "media/audio/audio_parameters.h"
6 #include "media/base/fake_audio_render_callback.h"
7 #include "media/base/mock_audio_renderer_sink.h"
8 #include "testing/gmock/include/gmock/gmock.h"
9 #include "testing/gtest/include/gtest/gtest.h"
10 #include "third_party/WebKit/Source/WebKit/chromium/public/WebAudioSourceProviderClient.h"
11 #include "webkit/media/webaudiosourceprovider_impl.h"
13 namespace webkit_media
{
16 const float kTestVolume
= 0.25;
19 class WebAudioSourceProviderImplTest
20 : public testing::Test
,
21 public WebKit::WebAudioSourceProviderClient
{
23 WebAudioSourceProviderImplTest()
24 : params_(media::AudioParameters::AUDIO_PCM_LINEAR
,
25 media::CHANNEL_LAYOUT_STEREO
, 48000, 16, 64),
27 mock_sink_(new media::MockAudioRendererSink()),
28 wasp_impl_(new WebAudioSourceProviderImpl(mock_sink_
)) {
31 virtual ~WebAudioSourceProviderImplTest() {}
33 void CallAllSinkMethodsAndVerify(bool verify
) {
34 testing::InSequence s
;
36 EXPECT_CALL(*mock_sink_
, Start()).Times(verify
);
39 EXPECT_CALL(*mock_sink_
, Play()).Times(verify
);
42 EXPECT_CALL(*mock_sink_
, Pause()).Times(verify
);
45 EXPECT_CALL(*mock_sink_
, SetVolume(kTestVolume
)).Times(verify
);
46 wasp_impl_
->SetVolume(kTestVolume
);
48 EXPECT_CALL(*mock_sink_
, Stop()).Times(verify
);
51 testing::Mock::VerifyAndClear(mock_sink_
);
54 void SetClient(WebKit::WebAudioSourceProviderClient
* client
) {
55 testing::InSequence s
;
58 EXPECT_CALL(*mock_sink_
, Stop());
59 EXPECT_CALL(*this, setFormat(params_
.channels(), params_
.sample_rate()));
61 wasp_impl_
->setClient(client
);
63 testing::Mock::VerifyAndClear(mock_sink_
);
64 testing::Mock::VerifyAndClear(this);
67 bool CompareBusses(const media::AudioBus
* bus1
, const media::AudioBus
* bus2
) {
68 EXPECT_EQ(bus1
->channels(), bus2
->channels());
69 EXPECT_EQ(bus1
->frames(), bus2
->frames());
70 for (int ch
= 0; ch
< bus1
->channels(); ++ch
) {
71 if (memcmp(bus1
->channel(ch
), bus2
->channel(ch
),
72 sizeof(*bus1
->channel(ch
)) * bus1
->frames()) != 0) {
79 // WebKit::WebAudioSourceProviderClient implementation.
80 MOCK_METHOD2(setFormat
, void(size_t numberOfChannels
, float sampleRate
));
83 media::AudioParameters params_
;
84 media::FakeAudioRenderCallback fake_callback_
;
85 scoped_refptr
<media::MockAudioRendererSink
> mock_sink_
;
86 scoped_refptr
<WebAudioSourceProviderImpl
> wasp_impl_
;
88 DISALLOW_COPY_AND_ASSIGN(WebAudioSourceProviderImplTest
);
91 TEST_F(WebAudioSourceProviderImplTest
, SetClientBeforeInitialize
) {
92 // setClient() with a NULL client should do nothing if no client is set.
93 wasp_impl_
->setClient(NULL
);
95 EXPECT_CALL(*mock_sink_
, Stop());
96 wasp_impl_
->setClient(this);
98 // When Initialize() is called after setClient(), the params should propagate
99 // to the client via setFormat() during the call.
100 EXPECT_CALL(*this, setFormat(params_
.channels(), params_
.sample_rate()));
101 wasp_impl_
->Initialize(params_
, &fake_callback_
);
103 // setClient() with the same client should do nothing.
104 wasp_impl_
->setClient(this);
107 // Verify AudioRendererSink functionality w/ and w/o a client.
108 TEST_F(WebAudioSourceProviderImplTest
, SinkMethods
) {
109 wasp_impl_
->Initialize(params_
, &fake_callback_
);
110 ASSERT_EQ(mock_sink_
->callback(), &fake_callback_
);
112 // Without a client all WASP calls should fall through to the underlying sink.
113 CallAllSinkMethodsAndVerify(true);
115 // With a client no calls should reach the Stop()'d sink. Also, setClient()
116 // should propagate the params provided during Initialize() at call time.
118 CallAllSinkMethodsAndVerify(false);
120 // Removing the client should cause WASP to revert to the underlying sink.
121 EXPECT_CALL(*mock_sink_
, SetVolume(kTestVolume
));
123 CallAllSinkMethodsAndVerify(true);
126 // Verify underlying sink state is restored after client removal.
127 TEST_F(WebAudioSourceProviderImplTest
, SinkStateRestored
) {
128 wasp_impl_
->Initialize(params_
, &fake_callback_
);
130 // Verify state set before the client is set propagates back afterward.
131 EXPECT_CALL(*mock_sink_
, Start());
135 EXPECT_CALL(*mock_sink_
, SetVolume(1.0));
136 EXPECT_CALL(*mock_sink_
, Start());
139 // Verify state set while the client was attached propagates back afterward.
142 wasp_impl_
->SetVolume(kTestVolume
);
144 EXPECT_CALL(*mock_sink_
, SetVolume(kTestVolume
));
145 EXPECT_CALL(*mock_sink_
, Start());
146 EXPECT_CALL(*mock_sink_
, Play());
150 // Test the AudioRendererSink state machine and its effects on provideInput().
151 TEST_F(WebAudioSourceProviderImplTest
, ProvideInput
) {
152 scoped_ptr
<media::AudioBus
> bus1
= media::AudioBus::Create(params_
);
153 scoped_ptr
<media::AudioBus
> bus2
= media::AudioBus::Create(params_
);
155 // Point the WebVector into memory owned by |bus1|.
156 WebKit::WebVector
<float*> audio_data(static_cast<size_t>(bus1
->channels()));
157 for (size_t i
= 0; i
< audio_data
.size(); ++i
)
158 audio_data
[i
] = bus1
->channel(i
);
160 // Verify provideInput() works before Initialize() and returns silence.
161 bus1
->channel(0)[0] = 1;
163 wasp_impl_
->provideInput(audio_data
, params_
.frames_per_buffer());
164 ASSERT_TRUE(CompareBusses(bus1
.get(), bus2
.get()));
166 wasp_impl_
->Initialize(params_
, &fake_callback_
);
169 // Verify provideInput() is muted prior to Start() and no calls to the render
170 // callback have occurred.
171 bus1
->channel(0)[0] = 1;
173 wasp_impl_
->provideInput(audio_data
, params_
.frames_per_buffer());
174 ASSERT_TRUE(CompareBusses(bus1
.get(), bus2
.get()));
175 ASSERT_EQ(fake_callback_
.last_audio_delay_milliseconds(), -1);
180 bus1
->channel(0)[0] = 1;
181 wasp_impl_
->provideInput(audio_data
, params_
.frames_per_buffer());
182 ASSERT_TRUE(CompareBusses(bus1
.get(), bus2
.get()));
183 ASSERT_EQ(fake_callback_
.last_audio_delay_milliseconds(), -1);
187 // Now we should get real audio data.
188 wasp_impl_
->provideInput(audio_data
, params_
.frames_per_buffer());
189 ASSERT_FALSE(CompareBusses(bus1
.get(), bus2
.get()));
191 // Ensure volume adjustment is working.
192 fake_callback_
.reset();
193 fake_callback_
.Render(bus2
.get(), 0);
194 bus2
->Scale(kTestVolume
);
196 fake_callback_
.reset();
197 wasp_impl_
->SetVolume(kTestVolume
);
198 wasp_impl_
->provideInput(audio_data
, params_
.frames_per_buffer());
199 ASSERT_TRUE(CompareBusses(bus1
.get(), bus2
.get()));
201 // Pause should return to silence.
203 bus1
->channel(0)[0] = 1;
205 wasp_impl_
->provideInput(audio_data
, params_
.frames_per_buffer());
206 ASSERT_TRUE(CompareBusses(bus1
.get(), bus2
.get()));
210 // Play should return real audio data again...
211 wasp_impl_
->provideInput(audio_data
, params_
.frames_per_buffer());
212 ASSERT_FALSE(CompareBusses(bus1
.get(), bus2
.get()));
214 // Stop() should return silence.
216 bus1
->channel(0)[0] = 1;
217 wasp_impl_
->provideInput(audio_data
, params_
.frames_per_buffer());
218 ASSERT_TRUE(CompareBusses(bus1
.get(), bus2
.get()));
221 } // namespace webkit_media