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

Side by Side Diff: third_party/WebKit/Source/platform/audio/PushPullFIFOSmokeTest.cpp

Issue 2777903005: Add WebThread in AudioDestination to support AudioWorkletThread (Closed)
Patch Set: Addressed feedback Created 3 years, 8 months 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
OLDNEW
(Empty)
1 // Copyright 2017 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 "platform/audio/PushPullFIFO.h"
6
7 #include <memory>
8 #include <vector>
9 #include "platform/CrossThreadFunctional.h"
10 #include "platform/WaitableEvent.h"
11 #include "platform/WebTaskRunner.h"
12 #include "platform/audio/AudioUtilities.h"
13 #include "platform/testing/UnitTestHelpers.h"
14 #include "platform/wtf/Functional.h"
15 #include "platform/wtf/PtrUtil.h"
16 #include "public/platform/Platform.h"
17 #include "public/platform/WebThread.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19
20 namespace blink {
21
22 namespace {
23
24 // To forcibly stop the message loop.
25 // TODO(hongchan): move this hack into Test class when the solution is found.
26 void FinishTest() {
27 LOG(INFO) << "FinishTest";
28 testing::ExitRunLoop();
29 }
30
31 // To wait for spawned threads to finish their tasks.
32 // TODO(hongchan): move this hack into Test class when the solution is found.
33 void HoldTestForDuration(double duration_ms) {
34 LOG(INFO) << "HoldTestForDuration";
35 Platform::Current()->CurrentThread()->GetWebTaskRunner()->PostDelayedTask(
36 BLINK_FROM_HERE,
37 WTF::Bind(&FinishTest),
38 duration_ms);
39 testing::EnterRunLoop();
40 }
41
42 // Base FIFOClient with an extra thread for looping and jitter control. The
43 // child class must define a specific task to run on the thread.
44 class FIFOClient {
45 public:
46 FIFOClient(PushPullFIFO* fifo, size_t bus_length, size_t jitter_range_ms)
47 : fifo_(fifo),
48 bus_(AudioBus::Create(fifo->NumberOfChannels(), bus_length)),
49 client_thread_(WTF::WrapUnique(
50 Platform::Current()->CreateThread("client thread"))),
51 jitter_range_ms_(jitter_range_ms) {}
52
53 void Start(double duration_ms, double interval_ms) {
54 duration_ms_ = duration_ms;
55 interval_ms_ = interval_ms;
56 client_thread_->GetWebTaskRunner()->PostTask(
57 BLINK_FROM_HERE,
58 CrossThreadBind(&FIFOClient::RunTaskOnOwnThread,
59 CrossThreadUnretained(this)));
60 }
61
62 virtual void Stop(int callback_counter) = 0;
63 virtual void RunTask() = 0;
64
65 void Pull(size_t frames_to_pull) {
66 fifo_->Pull(bus_.Get(), frames_to_pull);
67 }
68
69 void Push() {
70 fifo_->Push(bus_.Get());
71 }
72
73 private:
74 void RunTaskOnOwnThread() {
75 double interval_with_jitter = interval_ms_
76 + (static_cast<double>(std::rand()) / RAND_MAX) * jitter_range_ms_;
77 elapsed_ms_ += interval_with_jitter;
78 ++counter_;
79 RunTask();
80 if (elapsed_ms_ < duration_ms_) {
81 client_thread_->GetWebTaskRunner()->PostDelayedTask(
82 BLINK_FROM_HERE,
83 CrossThreadBind(&FIFOClient::RunTaskOnOwnThread,
84 CrossThreadUnretained(this)),
85 interval_with_jitter);
86 } else {
87 Stop(counter_);
88 }
89 }
90
91 PushPullFIFO* fifo_;
92 RefPtr<AudioBus> bus_;
93 std::unique_ptr<WebThread> client_thread_;
94
95 // Test duration.
96 double duration_ms_;
97
98 // Interval between each callback.
99 double interval_ms_;
100
101 // Jitter added to the regular pushing/pulling interval.
102 // (where j is 0 < j < jitter_range_ms)
103 double jitter_range_ms_;
104
105 // Elapsed test duration.
106 double elapsed_ms_ = 0;
107
108 // Counter variable for the total number of callbacks invoked.
109 int counter_ = 0;
110 };
111
112 // FIFO-pulling client (consumer). This mimics the audio device thread.
113 // |frames_to_pull| is variable.
114 class PullClient : public FIFOClient {
115 public:
116 PullClient(PushPullFIFO* fifo, size_t frames_to_pull, double jitter_range_ms)
117 : FIFOClient(fifo, frames_to_pull, jitter_range_ms),
118 frames_to_pull_(frames_to_pull) {
119 }
120
121 void RunTask() override {
122 Pull(frames_to_pull_);
123 }
124
125 void Stop(int callback_counter) override {
126 LOG(INFO) << "PullClient stopped. (" << callback_counter << " calls)";
127 }
128
129 private:
130 size_t frames_to_pull_;
131 };
132
133 // FIFO-pushing client (producer). This mimics the WebAudio rendering thread.
134 // The frames to push are static as 128 frames.
135 class PushClient : public FIFOClient {
136 public:
137 PushClient(PushPullFIFO* fifo, size_t frames_to_push, double jitter_range_ms)
138 : FIFOClient(fifo, frames_to_push, jitter_range_ms) {}
139
140 void RunTask() override {
141 Push();
142 }
143
144 void Stop(int callback_counter) override {
145 LOG(INFO) << "PushClient stopped. (" << callback_counter << " calls)";
146 }
147 };
148
149 struct FIFOSmokeTestParam {
150 const double sample_rate;
151 const unsigned number_of_channels;
152 const size_t fifo_length;
153 const double test_duration_ms;
154 // Buffer size for pulling. Equivalent of |callback_buffer_size|.
155 const size_t pull_buffer_size;
156 // Jitter range for the pulling interval.
157 const double pull_jitter_range_ms;
158 // Buffer size for pushing. Equivalent of WebAudio render quantum.
159 const size_t push_buffer_size;
160 // Jitter range for the pushing interval.
161 const double push_jitter_range_ms;
162 };
163
164 class PushPullFIFOSmokeTest
165 : public ::testing::TestWithParam<FIFOSmokeTestParam> {};
166
167 TEST_P(PushPullFIFOSmokeTest, SmokeTests) {
168 const FIFOSmokeTestParam param = GetParam();
169 const double sample_rate = param.sample_rate * 4;
170
171 const double pull_interval_ms =
172 param.pull_buffer_size / sample_rate * 1000;
173 const double push_interval_ms =
174 param.push_buffer_size / sample_rate * 1000;
175
176 std::unique_ptr<PushPullFIFO> test_fifo = WTF::WrapUnique(
177 new PushPullFIFO(param.number_of_channels, param.fifo_length));
178 std::unique_ptr<PullClient> pull_client = WTF::WrapUnique(new PullClient(
179 test_fifo.get(), param.pull_buffer_size, param.pull_jitter_range_ms));
180 std::unique_ptr<PushClient> push_client = WTF::WrapUnique(new PushClient(
181 test_fifo.get(), param.push_buffer_size, param.push_jitter_range_ms));
182
183 LOG(INFO) << "PushPullFIFOSmokeTest - Start";
184
185 pull_client->Start(param.test_duration_ms, pull_interval_ms);
186 push_client->Start(param.test_duration_ms, push_interval_ms);
187
188 // If the operation does not cause a crash for the test period, it's passed.
189 // Also give a bit more time to finish the tear-down process.
190 HoldTestForDuration(param.test_duration_ms + 150);
191 }
192
193 FIFOSmokeTestParam smoke_test_params[] = {
194 // Test case 0 (OSX): 256 Pull, 128 Push, Minimal jitter.
195 // WebThread's priority is lower than the device thread, so its jitter range
196 // is slightly bigger than the other.
197 {48000, 2, 8192, 1000, 256, 1, 128, 2},
198
199 // Test case 1 (Windows): 480 Pull, 128 Push. Moderate Jitter.
200 // Windows' audio callback is known to be ~10ms and UMA data shows the
201 // evidence for it. The jitter range was determined speculatively.
202 {48000, 2, 8192, 1000, 480, 2, 128, 3},
203
204 // Test case 2 (Ubuntu/Linux): 512 Pull, 128 Push. Unstable callback, but
205 // fast CPU. A typical configuration for Ubuntu + PulseAudio setup.
206 // PulseAudio's callback is known to be rather unstable.
207 {48000, 2, 8192, 1000, 512, 8, 128, 1},
208
209 // Test case 3 (Android-Reference): 512 Pull, 128 Push. Similar to Linux, but
210 // low profile CPU.
211 {44100, 2, 8192, 1000, 512, 8, 128, 3},
212
213 // Test case 4 (Android-ExternalA): 441 Pull, 128 Push. Extreme jitter with
214 // low profile CPU.
215 {44100, 2, 8192, 1000, 441, 24, 128, 8},
216
217 // Test case 5 (Android-ExternalB): 5768 Pull, 128 Push. Huge callback with
218 // large jitter. Low profile CPU.
219 {44100, 2, 8192, 1000, 5768, 120, 128, 12},
220
221 // Test case 6 (User-specified buffer size): 960 Pull, 128 Push. Minimal
222 // Jitter. 960 frames = 20ms at 48KHz.
223 {48000, 2, 8192, 1000, 960, 1, 128, 1},
224
225 // Test case 7 (Longer test duration): 256 Pull, 128 Push. 10 seconds.
226 {48000, 2, 8192, 10000, 256, 0, 128, 1}
o1ka 2017/04/26 12:32:57 44100 / 441 might be a better example since pull w
Raymond Toy 2017/04/26 19:12:00 I agree, that's a test we really need.
227 };
228
229 INSTANTIATE_TEST_CASE_P(PushPullFIFOSmokeTest,
230 PushPullFIFOSmokeTest,
231 ::testing::ValuesIn(smoke_test_params));
232
233 } // namespace
234
235 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698