OLD | NEW |
---|---|
(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. | |
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. | |
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 jitter_range_ms) | |
47 : fifo_(fifo), | |
48 jitter_range_ms_(jitter_range_ms), | |
49 client_thread_(WTF::WrapUnique( | |
50 Platform::Current()->CreateThread("client thread"))) {} | |
51 | |
52 void Start(double duration_ms, double interval_ms) { | |
53 duration_ms_ = duration_ms; | |
54 interval_ms_ = interval_ms; | |
55 client_thread_->GetWebTaskRunner()->PostTask( | |
56 BLINK_FROM_HERE, | |
57 CrossThreadBind(&FIFOClient::RunTaskOnOwnThread, | |
58 CrossThreadUnretained(this))); | |
59 } | |
60 | |
61 virtual void RunTask() = 0; | |
62 virtual void Stop() = 0; | |
63 | |
64 protected: | |
65 RefPtr<AudioBus> bus_; | |
66 PushPullFIFO* fifo_; | |
67 double elapesd_ms_ = 0; | |
68 | |
69 private: | |
70 void RunTaskOnOwnThread() { | |
71 double interval_with_jitter = interval_ms_ | |
72 + (static_cast<double>(std::rand()) / RAND_MAX) * jitter_range_ms_; | |
Raymond Toy
2017/04/21 16:26:57
Maybe use std::uniform_real_distribution to genera
hongchan
2017/04/21 20:44:02
Hmm, I think the variable names quite accurate and
| |
73 elapesd_ms_ += interval_with_jitter; | |
Raymond Toy
2017/04/21 16:26:57
elapesd_ms should probably be elapsed_ms
hongchan
2017/04/21 20:44:01
Done.
| |
74 RunTask(); | |
75 if (elapesd_ms_ < duration_ms_) { | |
76 client_thread_->GetWebTaskRunner()->PostDelayedTask( | |
77 BLINK_FROM_HERE, | |
78 CrossThreadBind(&FIFOClient::RunTaskOnOwnThread, | |
79 CrossThreadUnretained(this)), | |
80 interval_with_jitter); | |
Raymond Toy
2017/04/21 16:26:57
The documentation for PostDelayedTask says the del
hongchan
2017/04/21 20:44:02
Not sure if it would matters for anything, but thi
| |
81 } else { | |
82 Stop(); | |
83 } | |
84 } | |
85 | |
86 double duration_ms_; | |
87 double interval_ms_; | |
88 double jitter_range_ms_; | |
89 std::unique_ptr<WebThread> client_thread_; | |
90 }; | |
91 | |
92 // FIFO-pulling client (consumer). This mimics the audio device thread. | |
93 class PullClient : public FIFOClient { | |
94 public: | |
95 PullClient(PushPullFIFO* fifo, size_t frames_to_pull, double jitter_range_ms) | |
96 : FIFOClient(fifo, jitter_range_ms), | |
97 frames_to_pull_(frames_to_pull) { | |
98 bus_ = AudioBus::Create(fifo_->NumberOfChannels(), frames_to_pull_); | |
99 } | |
100 | |
101 void RunTask() override { | |
102 LOG(INFO) << "PullClient::RunTask (" << elapesd_ms_ << ")"; | |
103 fifo_->Pull(bus_.Get(), frames_to_pull_); | |
104 } | |
105 | |
106 void Stop() override { | |
107 LOG(INFO) << "PullClient::Stop (" << elapesd_ms_ << ")"; | |
108 } | |
109 | |
110 private: | |
111 size_t frames_to_pull_; | |
112 }; | |
113 | |
114 // FIFO-pushing client (producer). This mimics the WebAudio rendering thread. | |
115 class PushClient : public FIFOClient { | |
116 public: | |
117 PushClient(PushPullFIFO* fifo, size_t frames_to_push, double jitter_range_ms) | |
118 : FIFOClient(fifo, jitter_range_ms) { | |
119 bus_ = AudioBus::Create(fifo_->NumberOfChannels(), frames_to_push); | |
120 } | |
121 | |
122 void RunTask() override { | |
123 LOG(INFO) << "PushClient::RunTask (" << elapesd_ms_ << ")"; | |
124 fifo_->Push(bus_.Get()); | |
125 } | |
126 | |
127 void Stop() override { | |
128 LOG(INFO) << "PushClient::Stop (" << elapesd_ms_ << ")"; | |
129 } | |
130 }; | |
131 | |
132 class PushPullFIFOSmokeTest : public ::testing::Test {}; | |
133 | |
134 // TODO(hongchan): parameterize this sample test. | |
135 TEST_F(PushPullFIFOSmokeTest, SmokeTest) { | |
136 const double sample_rate = 48000; | |
137 const size_t fifo_length = 8192; | |
138 const size_t pull_buffer_size = 1024; | |
139 const double pull_interval_ms = pull_buffer_size / sample_rate * 1000; | |
Raymond Toy
2017/04/21 16:26:57
pull_buffer_size / sample_rate * 1000 isn't exactl
hongchan
2017/04/21 20:44:02
As we discussed offline, this does not really matt
| |
140 const double pull_jitter_range_ms = 5; | |
Raymond Toy
2017/04/21 16:26:57
Why 5? Please comment on valid values and reason
hongchan
2017/04/21 20:44:02
Multiple test cases with various parameters were a
| |
141 const size_t push_buffer_size = AudioUtilities::kRenderQuantumFrames; | |
142 const double push_interval_ms = push_buffer_size / sample_rate * 1000; | |
143 const double push_jitter_range_ms = 8; | |
144 const unsigned number_of_channels = 2; | |
145 | |
146 const double test_duration_ms = 1000; | |
Raymond Toy
2017/04/21 16:26:57
Is this long enough? I think this means that there
hongchan
2017/04/21 20:44:02
Multiple test cases with various parameters were a
| |
147 | |
148 std::unique_ptr<PushPullFIFO> test_fifo = | |
149 WTF::WrapUnique(new PushPullFIFO(number_of_channels, fifo_length)); | |
150 | |
151 std::unique_ptr<PullClient> pull_client = WTF::WrapUnique( | |
152 new PullClient(test_fifo.get(), pull_buffer_size, pull_jitter_range_ms)); | |
153 std::unique_ptr<PushClient> push_client = WTF::WrapUnique( | |
154 new PushClient(test_fifo.get(), push_buffer_size, push_jitter_range_ms)); | |
155 | |
156 pull_client->Start(test_duration_ms, pull_interval_ms); | |
157 push_client->Start(test_duration_ms, push_interval_ms); | |
158 | |
159 // Give a bit more time for clients to finish the task. | |
160 HoldTestForDuration(test_duration_ms + 250); | |
161 } | |
162 | |
163 } // namespace | |
164 | |
165 } // namespace blink | |
OLD | NEW |