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

Unified Diff: third_party/WebKit/Source/platform/audio/PushPullFIFOMultithreadTest.cpp

Issue 2777903005: Add WebThread in AudioDestination to support AudioWorkletThread (Closed)
Patch Set: Clean up after l-g-t-m 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 side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/platform/audio/PushPullFIFOMultithreadTest.cpp
diff --git a/third_party/WebKit/Source/platform/audio/PushPullFIFOMultithreadTest.cpp b/third_party/WebKit/Source/platform/audio/PushPullFIFOMultithreadTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..24b0fa91a8b8fb70333625ddbf89b97c459dda16
--- /dev/null
+++ b/third_party/WebKit/Source/platform/audio/PushPullFIFOMultithreadTest.cpp
@@ -0,0 +1,235 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "platform/audio/PushPullFIFO.h"
+
+#include <memory>
+#include <vector>
+#include "platform/CrossThreadFunctional.h"
+#include "platform/WaitableEvent.h"
+#include "platform/WebTaskRunner.h"
+#include "platform/audio/AudioUtilities.h"
+#include "platform/testing/UnitTestHelpers.h"
+#include "platform/wtf/Functional.h"
+#include "platform/wtf/PtrUtil.h"
+#include "public/platform/Platform.h"
+#include "public/platform/WebThread.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace blink {
+
+namespace {
+
+// To forcibly stop the message loop.
+// TODO(hongchan): move this hack into Test class when the solution is found.
+void FinishTest() {
+ LOG(INFO) << "FinishTest";
+ testing::ExitRunLoop();
+}
+
+// To wait for spawned threads to finish their tasks.
+// TODO(hongchan): move this hack into Test class when the solution is found.
+void HoldTestForDuration(double duration_ms) {
+ LOG(INFO) << "HoldTestForDuration";
+ Platform::Current()->CurrentThread()->GetWebTaskRunner()->PostDelayedTask(
+ BLINK_FROM_HERE,
+ WTF::Bind(&FinishTest),
+ duration_ms);
+ testing::EnterRunLoop();
+}
+
+// Base FIFOClient with an extra thread for looping and jitter control. The
+// child class must define a specific task to run on the thread.
+class FIFOClient {
+ public:
+ FIFOClient(PushPullFIFO* fifo, size_t bus_length, size_t jitter_range_ms)
+ : fifo_(fifo),
+ bus_(AudioBus::Create(fifo->NumberOfChannels(), bus_length)),
+ client_thread_(WTF::WrapUnique(
+ Platform::Current()->CreateThread("client thread"))),
+ jitter_range_ms_(jitter_range_ms) {}
+
+ void Start(double duration_ms, double interval_ms) {
+ duration_ms_ = duration_ms;
+ interval_ms_ = interval_ms;
+ client_thread_->GetWebTaskRunner()->PostTask(
+ BLINK_FROM_HERE,
+ CrossThreadBind(&FIFOClient::RunTaskOnOwnThread,
+ CrossThreadUnretained(this)));
+ }
+
+ virtual void Stop(int callback_counter) = 0;
+ virtual void RunTask() = 0;
+
+ void Pull(size_t frames_to_pull) {
+ fifo_->Pull(bus_.Get(), frames_to_pull);
+ }
+
+ void Push() {
+ fifo_->Push(bus_.Get());
+ }
+
+ private:
+ void RunTaskOnOwnThread() {
+ double interval_with_jitter = interval_ms_
+ + (static_cast<double>(std::rand()) / RAND_MAX) * jitter_range_ms_;
+ elapsed_ms_ += interval_with_jitter;
+ ++counter_;
+ RunTask();
+ if (elapsed_ms_ < duration_ms_) {
+ client_thread_->GetWebTaskRunner()->PostDelayedTask(
+ BLINK_FROM_HERE,
+ CrossThreadBind(&FIFOClient::RunTaskOnOwnThread,
+ CrossThreadUnretained(this)),
+ interval_with_jitter);
+ } else {
+ Stop(counter_);
+ }
+ }
+
+ PushPullFIFO* fifo_;
+ RefPtr<AudioBus> bus_;
+ std::unique_ptr<WebThread> client_thread_;
+
+ // Test duration.
+ double duration_ms_;
+
+ // Interval between each callback.
+ double interval_ms_;
+
+ // Jitter added to the regular pushing/pulling interval.
+ // (where j is 0 < j < jitter_range_ms)
+ double jitter_range_ms_;
+
+ // Elapsed test duration.
+ double elapsed_ms_ = 0;
+
+ // Counter variable for the total number of callbacks invoked.
+ int counter_ = 0;
+};
+
+// FIFO-pulling client (consumer). This mimics the audio device thread.
+// |frames_to_pull| is variable.
+class PullClient : public FIFOClient {
+ public:
+ PullClient(PushPullFIFO* fifo, size_t frames_to_pull, double jitter_range_ms)
+ : FIFOClient(fifo, frames_to_pull, jitter_range_ms),
+ frames_to_pull_(frames_to_pull) {
+ }
+
+ void RunTask() override {
+ Pull(frames_to_pull_);
+ }
+
+ void Stop(int callback_counter) override {
+ LOG(INFO) << "PullClient stopped. (" << callback_counter << " calls)";
+ }
+
+ private:
+ size_t frames_to_pull_;
+};
+
+// FIFO-pushing client (producer). This mimics the WebAudio rendering thread.
+// The frames to push are static as 128 frames.
+class PushClient : public FIFOClient {
+ public:
+ PushClient(PushPullFIFO* fifo, size_t frames_to_push, double jitter_range_ms)
+ : FIFOClient(fifo, frames_to_push, jitter_range_ms) {}
+
+ void RunTask() override {
+ Push();
+ }
+
+ void Stop(int callback_counter) override {
+ LOG(INFO) << "PushClient stopped. (" << callback_counter << " calls)";
+ }
+};
+
+struct FIFOSmokeTestParam {
+ const double sample_rate;
+ const unsigned number_of_channels;
+ const size_t fifo_length;
+ const double test_duration_ms;
+ // Buffer size for pulling. Equivalent of |callback_buffer_size|.
+ const size_t pull_buffer_size;
+ // Jitter range for the pulling interval.
+ const double pull_jitter_range_ms;
+ // Buffer size for pushing. Equivalent of WebAudio render quantum.
+ const size_t push_buffer_size;
+ // Jitter range for the pushing interval.
+ const double push_jitter_range_ms;
+};
+
+class PushPullFIFOSmokeTest
+ : public ::testing::TestWithParam<FIFOSmokeTestParam> {};
+
+TEST_P(PushPullFIFOSmokeTest, SmokeTests) {
+ const FIFOSmokeTestParam param = GetParam();
+ const double sample_rate = param.sample_rate * 4;
+
+ const double pull_interval_ms =
+ param.pull_buffer_size / sample_rate * 1000;
+ const double push_interval_ms =
+ param.push_buffer_size / sample_rate * 1000;
+
+ std::unique_ptr<PushPullFIFO> test_fifo = WTF::WrapUnique(
+ new PushPullFIFO(param.number_of_channels, param.fifo_length));
+ std::unique_ptr<PullClient> pull_client = WTF::WrapUnique(new PullClient(
+ test_fifo.get(), param.pull_buffer_size, param.pull_jitter_range_ms));
+ std::unique_ptr<PushClient> push_client = WTF::WrapUnique(new PushClient(
+ test_fifo.get(), param.push_buffer_size, param.push_jitter_range_ms));
+
+ LOG(INFO) << "PushPullFIFOSmokeTest - Start";
+
+ pull_client->Start(param.test_duration_ms, pull_interval_ms);
+ push_client->Start(param.test_duration_ms, push_interval_ms);
+
+ // If the operation does not cause a crash for the test period, it's passed.
+ // Also give a bit more time to finish the tear-down process.
+ HoldTestForDuration(param.test_duration_ms + 150);
+}
+
+FIFOSmokeTestParam smoke_test_params[] = {
+ // Test case 0 (OSX): 256 Pull, 128 Push, Minimal jitter.
+ // WebThread's priority is lower than the device thread, so its jitter range
+ // is slightly bigger than the other.
+ {48000, 2, 8192, 1000, 256, 1, 128, 2},
+
+ // Test case 1 (Windows): 441 Pull, 128 Push. Moderate Jitter.
+ // Windows' audio callback is known to be ~10ms and UMA data shows the
+ // evidence for it. The jitter range was determined speculatively.
+ {44100, 2, 8192, 1000, 441, 2, 128, 3},
+
+ // Test case 2 (Ubuntu/Linux): 512 Pull, 128 Push. Unstable callback, but
+ // fast CPU. A typical configuration for Ubuntu + PulseAudio setup.
+ // PulseAudio's callback is known to be rather unstable.
+ {48000, 2, 8192, 1000, 512, 8, 128, 1},
+
+ // Test case 3 (Android-Reference): 512 Pull, 128 Push. Similar to Linux, but
+ // low profile CPU.
+ {44100, 2, 8192, 1000, 512, 8, 128, 3},
+
+ // Test case 4 (Android-ExternalA): 441 Pull, 128 Push. Extreme jitter with
+ // low profile CPU.
+ {44100, 2, 8192, 1000, 441, 24, 128, 8},
+
+ // Test case 5 (Android-ExternalB): 5768 Pull, 128 Push. Huge callback with
+ // large jitter. Low profile CPU.
+ {44100, 2, 8192, 1000, 5768, 120, 128, 12},
+
+ // Test case 6 (User-specified buffer size): 960 Pull, 128 Push. Minimal
+ // Jitter. 960 frames = 20ms at 48KHz.
+ {48000, 2, 8192, 1000, 960, 1, 128, 1},
+
+ // Test case 7 (Longer test duration): 256 Pull, 128 Push. 10 seconds.
+ {48000, 2, 8192, 10000, 256, 0, 128, 1}
+};
+
+INSTANTIATE_TEST_CASE_P(PushPullFIFOSmokeTest,
+ PushPullFIFOSmokeTest,
+ ::testing::ValuesIn(smoke_test_params));
+
+} // namespace
+
+} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698