Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(605)

Side by Side Diff: media/blink/webaudiosourceprovider_impl_unittest.cc

Issue 2533443002: fallback to null sink in WebAudioSourceProvider::Initialize() + UMA stats for device status (Closed)
Patch Set: review comments addressed Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « media/blink/webaudiosourceprovider_impl.cc ('k') | media/blink/webmediaplayer_impl.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <stddef.h> 5 #include <stddef.h>
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/macros.h" 8 #include "base/macros.h"
9 #include "base/message_loop/message_loop.h" 9 #include "base/message_loop/message_loop.h"
10 #include "base/run_loop.h" 10 #include "base/run_loop.h"
11 #include "media/base/audio_parameters.h" 11 #include "media/base/audio_parameters.h"
12 #include "media/base/fake_audio_render_callback.h" 12 #include "media/base/fake_audio_render_callback.h"
13 #include "media/base/media_log.h"
13 #include "media/base/mock_audio_renderer_sink.h" 14 #include "media/base/mock_audio_renderer_sink.h"
14 #include "media/blink/webaudiosourceprovider_impl.h" 15 #include "media/blink/webaudiosourceprovider_impl.h"
15 #include "testing/gmock/include/gmock/gmock.h" 16 #include "testing/gmock/include/gmock/gmock.h"
16 #include "testing/gtest/include/gtest/gtest.h" 17 #include "testing/gtest/include/gtest/gtest.h"
17 #include "third_party/WebKit/public/platform/WebAudioSourceProviderClient.h" 18 #include "third_party/WebKit/public/platform/WebAudioSourceProviderClient.h"
18 19
19 using ::testing::_; 20 using ::testing::_;
20 21
21 namespace media { 22 namespace media {
22 23
23 namespace { 24 namespace {
24 const float kTestVolume = 0.25; 25 const float kTestVolume = 0.25;
26
27 class WebAudioSourceProviderImplUnderTest : public WebAudioSourceProviderImpl {
28 public:
29 WebAudioSourceProviderImplUnderTest(
30 scoped_refptr<SwitchableAudioRendererSink> sink)
31 : WebAudioSourceProviderImpl(std::move(sink), new MediaLog()),
32 fallback_sink_(new MockAudioRendererSink()) {}
33
34 MockAudioRendererSink* fallback_sink() { return fallback_sink_.get(); }
35
36 protected:
37 scoped_refptr<SwitchableAudioRendererSink> CreateFallbackSink() override {
38 return fallback_sink_;
39 }
40
41 private:
42 ~WebAudioSourceProviderImplUnderTest() override = default;
43 scoped_refptr<MockAudioRendererSink> fallback_sink_;
44
45 DISALLOW_COPY_AND_ASSIGN(WebAudioSourceProviderImplUnderTest);
46 };
47
48 enum class WaspSinkStatus { WASP_SINK_OK, WASP_SINK_ERROR, WASP_SINK_NULL };
49
50 scoped_refptr<MockAudioRendererSink> CreateWaspMockSink(WaspSinkStatus status) {
51 if (status == WaspSinkStatus::WASP_SINK_NULL)
52 return nullptr;
53 return new MockAudioRendererSink(status == WaspSinkStatus::WASP_SINK_OK
54 ? OUTPUT_DEVICE_STATUS_OK
55 : OUTPUT_DEVICE_STATUS_ERROR_INTERNAL);
56 }
57
25 } // namespace 58 } // namespace
26 59
27 class WebAudioSourceProviderImplTest 60 class WebAudioSourceProviderImplTest
28 : public testing::Test, 61 : public testing::TestWithParam<WaspSinkStatus>,
29 public blink::WebAudioSourceProviderClient { 62 public blink::WebAudioSourceProviderClient {
30 public: 63 public:
31 WebAudioSourceProviderImplTest() 64 WebAudioSourceProviderImplTest()
32 : params_(AudioParameters::AUDIO_PCM_LINEAR, 65 : params_(AudioParameters::AUDIO_PCM_LINEAR,
33 CHANNEL_LAYOUT_STEREO, 48000, 16, 64), 66 CHANNEL_LAYOUT_STEREO,
67 48000,
68 16,
69 64),
34 fake_callback_(0.1), 70 fake_callback_(0.1),
35 mock_sink_(new MockAudioRendererSink()), 71 mock_sink_(CreateWaspMockSink(GetParam())),
36 wasp_impl_(new WebAudioSourceProviderImpl(mock_sink_)) { 72 wasp_impl_(new WebAudioSourceProviderImplUnderTest(mock_sink_)),
37 } 73 expected_sink_(GetParam() == WaspSinkStatus::WASP_SINK_OK
74 ? mock_sink_.get()
75 : wasp_impl_->fallback_sink()) {}
38 76
39 virtual ~WebAudioSourceProviderImplTest() {} 77 virtual ~WebAudioSourceProviderImplTest() {}
40 78
41 void CallAllSinkMethodsAndVerify(bool verify) { 79 void CallAllSinkMethodsAndVerify(bool verify) {
42 testing::InSequence s; 80 testing::InSequence s;
43 81
44 EXPECT_CALL(*mock_sink_.get(), Start()).Times(verify); 82 EXPECT_CALL(*expected_sink_, Start()).Times(verify);
45 wasp_impl_->Start(); 83 wasp_impl_->Start();
46 84
47 EXPECT_CALL(*mock_sink_.get(), Play()).Times(verify); 85 EXPECT_CALL(*expected_sink_, Play()).Times(verify);
48 wasp_impl_->Play(); 86 wasp_impl_->Play();
49 87
50 EXPECT_CALL(*mock_sink_.get(), Pause()).Times(verify); 88 EXPECT_CALL(*expected_sink_, Pause()).Times(verify);
51 wasp_impl_->Pause(); 89 wasp_impl_->Pause();
52 90
53 EXPECT_CALL(*mock_sink_.get(), SetVolume(kTestVolume)).Times(verify); 91 EXPECT_CALL(*expected_sink_, SetVolume(kTestVolume)).Times(verify);
54 wasp_impl_->SetVolume(kTestVolume); 92 wasp_impl_->SetVolume(kTestVolume);
55 93
56 EXPECT_CALL(*mock_sink_.get(), Stop()).Times(verify); 94 EXPECT_CALL(*expected_sink_, Stop()).Times(verify);
57 wasp_impl_->Stop(); 95 wasp_impl_->Stop();
58 96
59 testing::Mock::VerifyAndClear(mock_sink_.get()); 97 testing::Mock::VerifyAndClear(mock_sink_.get());
60 } 98 }
61 99
62 void SetClient(blink::WebAudioSourceProviderClient* client) { 100 void SetClient(blink::WebAudioSourceProviderClient* client) {
63 testing::InSequence s; 101 testing::InSequence s;
64 102
65 if (client) { 103 if (client) {
66 EXPECT_CALL(*mock_sink_.get(), Stop()); 104 EXPECT_CALL(*expected_sink_, Stop());
67 EXPECT_CALL(*this, setFormat(params_.channels(), params_.sample_rate())); 105 EXPECT_CALL(*this, setFormat(params_.channels(), params_.sample_rate()));
68 } 106 }
69 wasp_impl_->setClient(client); 107 wasp_impl_->setClient(client);
70 base::RunLoop().RunUntilIdle(); 108 base::RunLoop().RunUntilIdle();
71 109
72 testing::Mock::VerifyAndClear(mock_sink_.get()); 110 testing::Mock::VerifyAndClear(mock_sink_.get());
111 testing::Mock::VerifyAndClear(wasp_impl_->fallback_sink());
73 testing::Mock::VerifyAndClear(this); 112 testing::Mock::VerifyAndClear(this);
74 } 113 }
75 114
76 bool CompareBusses(const AudioBus* bus1, const AudioBus* bus2) { 115 bool CompareBusses(const AudioBus* bus1, const AudioBus* bus2) {
77 EXPECT_EQ(bus1->channels(), bus2->channels()); 116 EXPECT_EQ(bus1->channels(), bus2->channels());
78 EXPECT_EQ(bus1->frames(), bus2->frames()); 117 EXPECT_EQ(bus1->frames(), bus2->frames());
79 for (int ch = 0; ch < bus1->channels(); ++ch) { 118 for (int ch = 0; ch < bus1->channels(); ++ch) {
80 if (memcmp(bus1->channel(ch), bus2->channel(ch), 119 if (memcmp(bus1->channel(ch), bus2->channel(ch),
81 sizeof(*bus1->channel(ch)) * bus1->frames()) != 0) { 120 sizeof(*bus1->channel(ch)) * bus1->frames()) != 0) {
82 return false; 121 return false;
(...skipping 11 matching lines...) Expand all
94 void OnAudioBus(std::unique_ptr<AudioBus> bus, 133 void OnAudioBus(std::unique_ptr<AudioBus> bus,
95 uint32_t frames_delayed, 134 uint32_t frames_delayed,
96 int sample_rate) { 135 int sample_rate) {
97 DoCopyAudioCB(bus.get(), frames_delayed, sample_rate); 136 DoCopyAudioCB(bus.get(), frames_delayed, sample_rate);
98 } 137 }
99 138
100 int Render(AudioBus* audio_bus) { 139 int Render(AudioBus* audio_bus) {
101 return wasp_impl_->RenderForTesting(audio_bus); 140 return wasp_impl_->RenderForTesting(audio_bus);
102 } 141 }
103 142
143 void ExpectUnhealthySinkToStop() {
144 if (GetParam() == WaspSinkStatus::WASP_SINK_ERROR)
145 EXPECT_CALL(*mock_sink_.get(), Stop());
146 }
147
104 protected: 148 protected:
105 AudioParameters params_; 149 AudioParameters params_;
106 FakeAudioRenderCallback fake_callback_; 150 FakeAudioRenderCallback fake_callback_;
107 scoped_refptr<MockAudioRendererSink> mock_sink_; 151 scoped_refptr<MockAudioRendererSink> mock_sink_;
108 scoped_refptr<WebAudioSourceProviderImpl> wasp_impl_; 152 scoped_refptr<WebAudioSourceProviderImplUnderTest> wasp_impl_;
153 MockAudioRendererSink* expected_sink_;
109 base::MessageLoop message_loop_; 154 base::MessageLoop message_loop_;
110 155
111 DISALLOW_COPY_AND_ASSIGN(WebAudioSourceProviderImplTest); 156 DISALLOW_COPY_AND_ASSIGN(WebAudioSourceProviderImplTest);
112 }; 157 };
113 158
114 TEST_F(WebAudioSourceProviderImplTest, SetClientBeforeInitialize) { 159 TEST_P(WebAudioSourceProviderImplTest, SetClientBeforeInitialize) {
115 // setClient() with a NULL client should do nothing if no client is set. 160 // setClient() with a NULL client should do nothing if no client is set.
116 wasp_impl_->setClient(NULL); 161 wasp_impl_->setClient(NULL);
117 162
118 EXPECT_CALL(*mock_sink_.get(), Stop()); 163 // If |mock_sink_| is not null, it should be stopped during setClient(this).
164 // If it is unhealthy, it should also be stopped during fallback in
165 // Initialize().
166 if (mock_sink_)
167 EXPECT_CALL(*mock_sink_.get(), Stop())
168 .Times(2 + static_cast<int>(GetParam()));
169
119 wasp_impl_->setClient(this); 170 wasp_impl_->setClient(this);
120 base::RunLoop().RunUntilIdle(); 171 base::RunLoop().RunUntilIdle();
121 172
173 if (mock_sink_)
174 EXPECT_CALL(*mock_sink_.get(), SetVolume(1)).Times(1);
175 wasp_impl_->setClient(NULL);
176 base::RunLoop().RunUntilIdle();
177
178 wasp_impl_->setClient(this);
179 base::RunLoop().RunUntilIdle();
180
122 // When Initialize() is called after setClient(), the params should propagate 181 // When Initialize() is called after setClient(), the params should propagate
123 // to the client via setFormat() during the call. 182 // to the client via setFormat() during the call.
124 EXPECT_CALL(*this, setFormat(params_.channels(), params_.sample_rate())); 183 EXPECT_CALL(*this, setFormat(params_.channels(), params_.sample_rate()));
125 wasp_impl_->Initialize(params_, &fake_callback_); 184 wasp_impl_->Initialize(params_, &fake_callback_);
126 base::RunLoop().RunUntilIdle(); 185 base::RunLoop().RunUntilIdle();
127 186
128 // setClient() with the same client should do nothing. 187 // setClient() with the same client should do nothing.
129 wasp_impl_->setClient(this); 188 wasp_impl_->setClient(this);
130 base::RunLoop().RunUntilIdle(); 189 base::RunLoop().RunUntilIdle();
131 } 190 }
132 191
133 // Verify AudioRendererSink functionality w/ and w/o a client. 192 // Verify AudioRendererSink functionality w/ and w/o a client.
134 TEST_F(WebAudioSourceProviderImplTest, SinkMethods) { 193 TEST_P(WebAudioSourceProviderImplTest, SinkMethods) {
194 ExpectUnhealthySinkToStop();
135 wasp_impl_->Initialize(params_, &fake_callback_); 195 wasp_impl_->Initialize(params_, &fake_callback_);
136 196
137 // Without a client all WASP calls should fall through to the underlying sink. 197 // Without a client all WASP calls should fall through to the underlying sink.
138 CallAllSinkMethodsAndVerify(true); 198 CallAllSinkMethodsAndVerify(true);
139 199
140 // With a client no calls should reach the Stop()'d sink. Also, setClient() 200 // With a client no calls should reach the Stop()'d sink. Also, setClient()
141 // should propagate the params provided during Initialize() at call time. 201 // should propagate the params provided during Initialize() at call time.
142 SetClient(this); 202 SetClient(this);
143 CallAllSinkMethodsAndVerify(false); 203 CallAllSinkMethodsAndVerify(false);
144 204
145 // Removing the client should cause WASP to revert to the underlying sink. 205 // Removing the client should cause WASP to revert to the underlying sink.
146 EXPECT_CALL(*mock_sink_.get(), SetVolume(kTestVolume)); 206 EXPECT_CALL(*expected_sink_, SetVolume(kTestVolume));
147 SetClient(NULL); 207 SetClient(NULL);
148 CallAllSinkMethodsAndVerify(true); 208 CallAllSinkMethodsAndVerify(true);
149 } 209 }
150 210
151 // Verify underlying sink state is restored after client removal. 211 // Verify underlying sink state is restored after client removal.
152 TEST_F(WebAudioSourceProviderImplTest, SinkStateRestored) { 212 TEST_P(WebAudioSourceProviderImplTest, SinkStateRestored) {
213 ExpectUnhealthySinkToStop();
153 wasp_impl_->Initialize(params_, &fake_callback_); 214 wasp_impl_->Initialize(params_, &fake_callback_);
154 215
155 // Verify state set before the client is set propagates back afterward. 216 // Verify state set before the client is set propagates back afterward.
156 EXPECT_CALL(*mock_sink_.get(), Start()); 217 EXPECT_CALL(*expected_sink_, Start());
157 wasp_impl_->Start(); 218 wasp_impl_->Start();
158 SetClient(this); 219 SetClient(this);
159 220
160 EXPECT_CALL(*mock_sink_.get(), SetVolume(1.0)); 221 EXPECT_CALL(*expected_sink_, SetVolume(1.0));
161 EXPECT_CALL(*mock_sink_.get(), Start()); 222 EXPECT_CALL(*expected_sink_, Start());
162 SetClient(NULL); 223 SetClient(NULL);
163 224
164 // Verify state set while the client was attached propagates back afterward. 225 // Verify state set while the client was attached propagates back afterward.
165 SetClient(this); 226 SetClient(this);
166 wasp_impl_->Play(); 227 wasp_impl_->Play();
167 wasp_impl_->SetVolume(kTestVolume); 228 wasp_impl_->SetVolume(kTestVolume);
168 229
169 EXPECT_CALL(*mock_sink_.get(), SetVolume(kTestVolume)); 230 EXPECT_CALL(*expected_sink_, SetVolume(kTestVolume));
170 EXPECT_CALL(*mock_sink_.get(), Start()); 231 EXPECT_CALL(*expected_sink_, Start());
171 EXPECT_CALL(*mock_sink_.get(), Play()); 232 EXPECT_CALL(*expected_sink_, Play());
172 SetClient(NULL); 233 SetClient(NULL);
173 } 234 }
174 235
175 // Test the AudioRendererSink state machine and its effects on provideInput(). 236 // Test the AudioRendererSink state machine and its effects on provideInput().
176 TEST_F(WebAudioSourceProviderImplTest, ProvideInput) { 237 TEST_P(WebAudioSourceProviderImplTest, ProvideInput) {
238 ExpectUnhealthySinkToStop();
177 std::unique_ptr<AudioBus> bus1 = AudioBus::Create(params_); 239 std::unique_ptr<AudioBus> bus1 = AudioBus::Create(params_);
178 std::unique_ptr<AudioBus> bus2 = AudioBus::Create(params_); 240 std::unique_ptr<AudioBus> bus2 = AudioBus::Create(params_);
179 241
180 // Point the WebVector into memory owned by |bus1|. 242 // Point the WebVector into memory owned by |bus1|.
181 blink::WebVector<float*> audio_data(static_cast<size_t>(bus1->channels())); 243 blink::WebVector<float*> audio_data(static_cast<size_t>(bus1->channels()));
182 for (size_t i = 0; i < audio_data.size(); ++i) 244 for (size_t i = 0; i < audio_data.size(); ++i)
183 audio_data[i] = bus1->channel(static_cast<int>(i)); 245 audio_data[i] = bus1->channel(static_cast<int>(i));
184 246
185 // Verify provideInput() works before Initialize() and returns silence. 247 // Verify provideInput() works before Initialize() and returns silence.
186 bus1->channel(0)[0] = 1; 248 bus1->channel(0)[0] = 1;
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
252 314
253 // Stop() should return silence. 315 // Stop() should return silence.
254 wasp_impl_->Stop(); 316 wasp_impl_->Stop();
255 bus1->channel(0)[0] = 1; 317 bus1->channel(0)[0] = 1;
256 bus2->Zero(); 318 bus2->Zero();
257 wasp_impl_->provideInput(audio_data, params_.frames_per_buffer()); 319 wasp_impl_->provideInput(audio_data, params_.frames_per_buffer());
258 ASSERT_TRUE(CompareBusses(bus1.get(), bus2.get())); 320 ASSERT_TRUE(CompareBusses(bus1.get(), bus2.get()));
259 } 321 }
260 322
261 // Verify CopyAudioCB is called if registered. 323 // Verify CopyAudioCB is called if registered.
262 TEST_F(WebAudioSourceProviderImplTest, CopyAudioCB) { 324 TEST_P(WebAudioSourceProviderImplTest, CopyAudioCB) {
325 ExpectUnhealthySinkToStop();
326
263 testing::InSequence s; 327 testing::InSequence s;
264 wasp_impl_->Initialize(params_, &fake_callback_); 328 wasp_impl_->Initialize(params_, &fake_callback_);
265 wasp_impl_->SetCopyAudioCallback(base::Bind( 329 wasp_impl_->SetCopyAudioCallback(base::Bind(
266 &WebAudioSourceProviderImplTest::OnAudioBus, base::Unretained(this))); 330 &WebAudioSourceProviderImplTest::OnAudioBus, base::Unretained(this)));
267 331
268 const std::unique_ptr<AudioBus> bus1 = AudioBus::Create(params_); 332 const std::unique_ptr<AudioBus> bus1 = AudioBus::Create(params_);
269 EXPECT_CALL(*this, DoCopyAudioCB(_, 0, params_.sample_rate())).Times(1); 333 EXPECT_CALL(*this, DoCopyAudioCB(_, 0, params_.sample_rate())).Times(1);
270 Render(bus1.get()); 334 Render(bus1.get());
271 335
272 wasp_impl_->ClearCopyAudioCallback(); 336 wasp_impl_->ClearCopyAudioCallback();
273 EXPECT_CALL(*this, DoCopyAudioCB(_, _, _)).Times(0); 337 EXPECT_CALL(*this, DoCopyAudioCB(_, _, _)).Times(0);
274 Render(bus1.get()); 338 Render(bus1.get());
275 339
276 testing::Mock::VerifyAndClear(mock_sink_.get()); 340 testing::Mock::VerifyAndClear(mock_sink_.get());
277 } 341 }
278 342
343 INSTANTIATE_TEST_CASE_P(
344 /* prefix intentionally left blank due to only one parameterization */,
345 WebAudioSourceProviderImplTest,
346 testing::Values(WaspSinkStatus::WASP_SINK_OK,
347 WaspSinkStatus::WASP_SINK_ERROR,
348 WaspSinkStatus::WASP_SINK_NULL));
349
279 } // namespace media 350 } // namespace media
OLDNEW
« no previous file with comments | « media/blink/webaudiosourceprovider_impl.cc ('k') | media/blink/webmediaplayer_impl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698