1 // Copyright 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. 4 5 #include "base/message_loop/message_loop.h" 6 #include "base/run_loop.h" 7 #include "content/renderer/media/webaudiosourceprovider_impl.h" 8 #include "media/audio/audio_parameters.h" 9 #include "media/base/fake_audio_render_callback.h" 10 #include "media/base/mock_audio_renderer_sink.h" 11 #include "testing/gmock/include/gmock/gmock.h" 12 #include "testing/gtest/include/gtest/gtest.h" 13 #include "third_party/WebKit/public/platform/WebAudioSourceProviderClient.h" 14 15 namespace content { 16 17 namespace { 18 const float kTestVolume = 0.25; 19 } // namespace 20 21 class WebAudioSourceProviderImplTest 22 : public testing::Test, 23 public blink::WebAudioSourceProviderClient { 24 public: 25 WebAudioSourceProviderImplTest() 26 : params_(media::AudioParameters::AUDIO_PCM_LINEAR, 27 media::CHANNEL_LAYOUT_STEREO, 48000, 16, 64), 28 fake_callback_(0.1), 29 mock_sink_(new media::MockAudioRendererSink()), 30 wasp_impl_(new WebAudioSourceProviderImpl(mock_sink_)) { 31 } 32 33 virtual ~WebAudioSourceProviderImplTest() {} 34 35 void CallAllSinkMethodsAndVerify(bool verify) { 36 testing::InSequence s; 37 38 EXPECT_CALL(*mock_sink_.get(), Start()).Times(verify); 39 wasp_impl_->Start(); 40 41 EXPECT_CALL(*mock_sink_.get(), Play()).Times(verify); 42 wasp_impl_->Play(); 43 44 EXPECT_CALL(*mock_sink_.get(), Pause()).Times(verify); 45 wasp_impl_->Pause(); 46 47 EXPECT_CALL(*mock_sink_.get(), SetVolume(kTestVolume)).Times(verify); 48 wasp_impl_->SetVolume(kTestVolume); 49 50 EXPECT_CALL(*mock_sink_.get(), Stop()).Times(verify); 51 wasp_impl_->Stop(); 52 53 testing::Mock::VerifyAndClear(mock_sink_.get()); 54 } 55 56 void SetClient(blink::WebAudioSourceProviderClient* client) { 57 testing::InSequence s; 58 59 if (client) { 60 EXPECT_CALL(*mock_sink_.get(), Stop()); 61 EXPECT_CALL(*this, setFormat(params_.channels(), params_.sample_rate())); 62 } 63 wasp_impl_->setClient(client); 64 base::RunLoop().RunUntilIdle(); 65 66 testing::Mock::VerifyAndClear(mock_sink_.get()); 67 testing::Mock::VerifyAndClear(this); 68 } 69 70 bool CompareBusses(const media::AudioBus* bus1, const media::AudioBus* bus2) { 71 EXPECT_EQ(bus1->channels(), bus2->channels()); 72 EXPECT_EQ(bus1->frames(), bus2->frames()); 73 for (int ch = 0; ch < bus1->channels(); ++ch) { 74 if (memcmp(bus1->channel(ch), bus2->channel(ch), 75 sizeof(*bus1->channel(ch)) * bus1->frames()) != 0) { 76 return false; 77 } 78 } 79 return true; 80 } 81 82 // blink::WebAudioSourceProviderClient implementation. 83 MOCK_METHOD2(setFormat, void(size_t numberOfChannels, float sampleRate)); 84 85 protected: 86 media::AudioParameters params_; 87 media::FakeAudioRenderCallback fake_callback_; 88 scoped_refptr<media::MockAudioRendererSink> mock_sink_; 89 scoped_refptr<WebAudioSourceProviderImpl> wasp_impl_; 90 base::MessageLoop message_loop_; 91 92 DISALLOW_COPY_AND_ASSIGN(WebAudioSourceProviderImplTest); 93 }; 94 95 TEST_F(WebAudioSourceProviderImplTest, SetClientBeforeInitialize) { 96 // setClient() with a NULL client should do nothing if no client is set. 97 wasp_impl_->setClient(NULL); 98 99 EXPECT_CALL(*mock_sink_.get(), Stop()); 100 wasp_impl_->setClient(this); 101 base::RunLoop().RunUntilIdle(); 102 103 // When Initialize() is called after setClient(), the params should propagate 104 // to the client via setFormat() during the call. 105 EXPECT_CALL(*this, setFormat(params_.channels(), params_.sample_rate())); 106 wasp_impl_->Initialize(params_, &fake_callback_); 107 base::RunLoop().RunUntilIdle(); 108 109 // setClient() with the same client should do nothing. 110 wasp_impl_->setClient(this); 111 base::RunLoop().RunUntilIdle(); 112 } 113 114 // Verify AudioRendererSink functionality w/ and w/o a client. 115 TEST_F(WebAudioSourceProviderImplTest, SinkMethods) { 116 wasp_impl_->Initialize(params_, &fake_callback_); 117 ASSERT_EQ(mock_sink_->callback(), &fake_callback_); 118 119 // Without a client all WASP calls should fall through to the underlying sink. 120 CallAllSinkMethodsAndVerify(true); 121 122 // With a client no calls should reach the Stop()'d sink. Also, setClient() 123 // should propagate the params provided during Initialize() at call time. 124 SetClient(this); 125 CallAllSinkMethodsAndVerify(false); 126 127 // Removing the client should cause WASP to revert to the underlying sink. 128 EXPECT_CALL(*mock_sink_.get(), SetVolume(kTestVolume)); 129 SetClient(NULL); 130 CallAllSinkMethodsAndVerify(true); 131 } 132 133 // Verify underlying sink state is restored after client removal. 134 TEST_F(WebAudioSourceProviderImplTest, SinkStateRestored) { 135 wasp_impl_->Initialize(params_, &fake_callback_); 136 137 // Verify state set before the client is set propagates back afterward. 138 EXPECT_CALL(*mock_sink_.get(), Start()); 139 wasp_impl_->Start(); 140 SetClient(this); 141 142 EXPECT_CALL(*mock_sink_.get(), SetVolume(1.0)); 143 EXPECT_CALL(*mock_sink_.get(), Start()); 144 SetClient(NULL); 145 146 // Verify state set while the client was attached propagates back afterward. 147 SetClient(this); 148 wasp_impl_->Play(); 149 wasp_impl_->SetVolume(kTestVolume); 150 151 EXPECT_CALL(*mock_sink_.get(), SetVolume(kTestVolume)); 152 EXPECT_CALL(*mock_sink_.get(), Start()); 153 EXPECT_CALL(*mock_sink_.get(), Play()); 154 SetClient(NULL); 155 } 156 157 // Test the AudioRendererSink state machine and its effects on provideInput(). 158 TEST_F(WebAudioSourceProviderImplTest, ProvideInput) { 159 scoped_ptr<media::AudioBus> bus1 = media::AudioBus::Create(params_); 160 scoped_ptr<media::AudioBus> bus2 = media::AudioBus::Create(params_); 161 162 // Point the WebVector into memory owned by |bus1|. 163 blink::WebVector<float*> audio_data(static_cast<size_t>(bus1->channels())); 164 for (size_t i = 0; i < audio_data.size(); ++i) 165 audio_data[i] = bus1->channel(i); 166 167 // Verify provideInput() works before Initialize() and returns silence. 168 bus1->channel(0)[0] = 1; 169 bus2->Zero(); 170 wasp_impl_->provideInput(audio_data, params_.frames_per_buffer()); 171 ASSERT_TRUE(CompareBusses(bus1.get(), bus2.get())); 172 173 wasp_impl_->Initialize(params_, &fake_callback_); 174 SetClient(this); 175 176 // Verify provideInput() is muted prior to Start() and no calls to the render 177 // callback have occurred. 178 bus1->channel(0)[0] = 1; 179 bus2->Zero(); 180 wasp_impl_->provideInput(audio_data, params_.frames_per_buffer()); 181 ASSERT_TRUE(CompareBusses(bus1.get(), bus2.get())); 182 ASSERT_EQ(fake_callback_.last_audio_delay_milliseconds(), -1); 183 184 wasp_impl_->Start(); 185 186 // Ditto for Play(). 187 bus1->channel(0)[0] = 1; 188 wasp_impl_->provideInput(audio_data, params_.frames_per_buffer()); 189 ASSERT_TRUE(CompareBusses(bus1.get(), bus2.get())); 190 ASSERT_EQ(fake_callback_.last_audio_delay_milliseconds(), -1); 191 192 wasp_impl_->Play(); 193 194 // Now we should get real audio data. 195 wasp_impl_->provideInput(audio_data, params_.frames_per_buffer()); 196 ASSERT_FALSE(CompareBusses(bus1.get(), bus2.get())); 197 198 // Ensure volume adjustment is working. 199 fake_callback_.reset(); 200 fake_callback_.Render(bus2.get(), 0); 201 bus2->Scale(kTestVolume); 202 203 fake_callback_.reset(); 204 wasp_impl_->SetVolume(kTestVolume); 205 wasp_impl_->provideInput(audio_data, params_.frames_per_buffer()); 206 ASSERT_TRUE(CompareBusses(bus1.get(), bus2.get())); 207 208 // Pause should return to silence. 209 wasp_impl_->Pause(); 210 bus1->channel(0)[0] = 1; 211 bus2->Zero(); 212 wasp_impl_->provideInput(audio_data, params_.frames_per_buffer()); 213 ASSERT_TRUE(CompareBusses(bus1.get(), bus2.get())); 214 215 wasp_impl_->Play(); 216 217 // Play should return real audio data again... 218 wasp_impl_->provideInput(audio_data, params_.frames_per_buffer()); 219 ASSERT_FALSE(CompareBusses(bus1.get(), bus2.get())); 220 221 // Stop() should return silence. 222 wasp_impl_->Stop(); 223 bus1->channel(0)[0] = 1; 224 wasp_impl_->provideInput(audio_data, params_.frames_per_buffer()); 225 ASSERT_TRUE(CompareBusses(bus1.get(), bus2.get())); 226 } 227 228 } // namespace content 229