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

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

Issue 2777903005: Add WebThread in AudioDestination to support AudioWorkletThread (Closed)
Patch Set: Refactoring WIP (please ignore) 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
1 // Copyright 2017 The Chromium Authors. All rights reserved. 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 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 "platform/audio/PushPullFIFO.h" 5 #include "platform/audio/PushPullFIFO.h"
6 6
7 #include <memory> 7 #include <memory>
8 #include "platform/audio/AudioUtilities.h" 8 #include "platform/audio/AudioUtilities.h"
9 #include "platform/wtf/PtrUtil.h" 9 #include "platform/wtf/PtrUtil.h"
10 10
11 namespace blink { 11 namespace blink {
12 12
13 namespace { 13 namespace {
14 14
15 // Suppress the warning log if over/underflow happens more than 100 times. 15 // Suppress the warning log if over/underflow happens more than 100 times.
16 const unsigned kMaxMessagesToLog = 100; 16 const unsigned kMaxMessagesToLog = 100;
17 } 17 }
18 18
19 const size_t PushPullFIFO::kMaxFIFOLength = 65536; 19 const size_t PushPullFIFO::kMaxFIFOLength = 65536;
20 20
21 PushPullFIFO::PushPullFIFO(unsigned number_of_channels, size_t fifo_length) 21 PushPullFIFO::PushPullFIFO(unsigned number_of_channels,
22 : fifo_length_(fifo_length), 22 size_t fifo_length,
23 ThreadIdentifier rendering_thread_id,
24 AudioIOCallback& web_audio_render_callback)
25 : rendering_thread_id_(rendering_thread_id),
o1ka 2017/04/13 08:36:53 This is too much information for a FIFO. Also, we
hongchan 2017/04/14 16:31:48 Done.
26 web_audio_render_callback_(web_audio_render_callback),
27 fifo_length_(fifo_length),
23 frames_available_(0), 28 frames_available_(0),
24 index_read_(0), 29 index_read_(0),
25 index_write_(0), 30 index_write_(0),
26 overflow_count_(0), 31 overflow_count_(0),
27 underflow_count_(0) { 32 underflow_count_(0) {
28 CHECK_LE(fifo_length_, kMaxFIFOLength); 33 CHECK_LE(fifo_length_, kMaxFIFOLength);
29 fifo_bus_ = AudioBus::Create(number_of_channels, fifo_length_); 34 fifo_bus_ = AudioBus::Create(number_of_channels, fifo_length_);
35 render_bus_ = AudioBus::Create(number_of_channels,
36 AudioUtilities::kRenderQuantumFrames);
30 } 37 }
31 38
32 PushPullFIFO::~PushPullFIFO() {} 39 PushPullFIFO::~PushPullFIFO() {}
33 40
34 // Push the data from |inputBus| to FIFO. The size of push is determined by 41 void PushPullFIFO::FillRequestedFrames(size_t frames_requested,
35 // the length of |inputBus|. 42 size_t callback_buffer_size,
36 void PushPullFIFO::Push(const AudioBus* input_bus) { 43 AudioIOPosition output_position) {
37 CHECK(input_bus); 44 DCHECK(IsRenderingThread());
38 CHECK_EQ(input_bus->length(), AudioUtilities::kRenderQuantumFrames);
39 SECURITY_CHECK(input_bus->length() <= fifo_length_);
40 SECURITY_CHECK(index_write_ < fifo_length_);
41 45
42 const size_t input_bus_length = input_bus->length(); 46 MutexLocker lock(lock_);
43 const size_t remainder = fifo_length_ - index_write_;
44 47
45 for (unsigned i = 0; i < fifo_bus_->NumberOfChannels(); ++i) { 48 base::TimeTicks output_position_received_timestamp = base::TimeTicks::Now();
46 float* fifo_bus_channel = fifo_bus_->Channel(i)->MutableData(); 49
47 const float* input_bus_channel = input_bus->Channel(i)->Data(); 50 size_t frames_to_render = frames_requested > frames_available_
48 if (remainder >= input_bus_length) { 51 ? frames_requested - frames_available_
49 // The remainder is big enough for the input data. 52 : 0;
50 memcpy(fifo_bus_channel + index_write_, input_bus_channel, 53
51 input_bus_length * sizeof(*fifo_bus_channel)); 54 for (size_t pushed_frames = 0; pushed_frames < frames_to_render;
52 } else { 55 pushed_frames += AudioUtilities::kRenderQuantumFrames) {
53 // The input data overflows the remainder size. Wrap around the index. 56 // If platform buffer is more than two times longer than |framesToProcess|
54 memcpy(fifo_bus_channel + index_write_, input_bus_channel, 57 // we do not want output position to get stuck so we promote it
55 remainder * sizeof(*fifo_bus_channel)); 58 // using the elapsed time from the moment it was initially obtained.
56 memcpy(fifo_bus_channel, input_bus_channel + remainder, 59 if (callback_buffer_size > AudioUtilities::kRenderQuantumFrames * 2) {
57 (input_bus_length - remainder) * sizeof(*fifo_bus_channel)); 60 double delta =
61 (base::TimeTicks::Now() - output_position_received_timestamp)
62 .InSecondsF();
63 output_position.position += delta;
64 output_position.timestamp += delta;
58 } 65 }
66
67 // Some implementations give only rough estimation of |delay| so
68 // we might have negative estimation |outputPosition| value.
69 if (output_position.position < 0.0)
70 output_position.position = 0.0;
71
72 // Process WebAudio graph and push the rendered output to FIFO.
73 web_audio_render_callback_.Render(nullptr,
74 render_bus_.Get(),
75 AudioUtilities::kRenderQuantumFrames,
76 output_position);
77 Push(render_bus_.Get());
59 } 78 }
60
61 // Update the write index; wrap it around if necessary.
62 index_write_ = (index_write_ + input_bus_length) % fifo_length_;
63
64 // In case of overflow, move the |indexRead| to the updated |indexWrite| to
65 // avoid reading overwritten frames by the next pull.
66 if (input_bus_length > fifo_length_ - frames_available_) {
67 index_read_ = index_write_;
68 if (++overflow_count_ < kMaxMessagesToLog) {
69 LOG(WARNING) << "PushPullFIFO: overflow while pushing ("
70 << "overflowCount=" << overflow_count_
71 << ", availableFrames=" << frames_available_
72 << ", inputFrames=" << input_bus_length
73 << ", fifoLength=" << fifo_length_ << ")";
74 }
75 }
76
77 // Update the number of frames available in FIFO.
78 frames_available_ =
79 std::min(frames_available_ + input_bus_length, fifo_length_);
80 DCHECK_EQ((index_read_ + frames_available_) % fifo_length_, index_write_);
81 } 79 }
82 80
83 // Pull the data out of FIFO to |outputBus|. If remaining frame in the FIFO 81 // Pull the data out of FIFO to |outputBus|. If remaining frame in the FIFO
84 // is less than the frames to pull, provides remaining frame plus the silence. 82 // is less than the frames to pull, provides remaining frame plus the silence.
85 void PushPullFIFO::Pull(AudioBus* output_bus, size_t frames_requested) { 83 void PushPullFIFO::Pull(AudioBus* output_bus, size_t frames_requested) {
84 // This runs on audio device thread.
85 DCHECK(!IsRenderingThread());
86
87 MutexLocker lock(lock_);
88
86 #if OS(ANDROID) 89 #if OS(ANDROID)
87 if (!output_bus) { 90 if (!output_bus) {
88 // Log when outputBus or FIFO object is invalid. (crbug.com/692423) 91 // Log when outputBus or FIFO object is invalid. (crbug.com/692423)
89 LOG(WARNING) << "[WebAudio/PushPullFIFO::pull <" << static_cast<void*>(this) 92 LOG(WARNING) << "[WebAudio/PushPullFIFO::pull <" << static_cast<void*>(this)
90 << ">] |outputBus| is invalid."; 93 << ">] |outputBus| is invalid.";
91 // Silently return to avoid crash. 94 // Silently return to avoid crash.
92 return; 95 return;
93 } 96 }
94 97
95 // The following checks are in place to catch the inexplicable crash. 98 // The following checks are in place to catch the inexplicable crash.
96 // (crbug.com/692423) 99 // (crbug.com/692423)
97 if (frames_requested > output_bus->length()) { 100 if (frames_requested > output_bus->length()) {
98 LOG(WARNING) << "[WebAudio/PushPullFIFO::pull <" << static_cast<void*>(this) 101 LOG(WARNING) << "[WebAudio/PushPullFIFO::pull <" << static_cast<void*>(this)
99 << ">] framesRequested > outputBus->length() (" 102 << ">] framesRequested > outputBus->length() ("
100 << frames_requested << " > " << output_bus->length() << ")"; 103 << frames_requested << " > " << output_bus->length() << ")";
101 } 104 }
102 if (frames_requested > fifo_length_) { 105 if (frames_requested > fifo_length_) {
103 LOG(WARNING) << "[WebAudio/PushPullFIFO::pull <" << static_cast<void*>(this) 106 LOG(WARNING) << "[WebAudio/PushPullFIFO::pull <" << static_cast<void*>(this)
104 << ">] framesRequested > m_fifoLength (" << frames_requested 107 << ">] framesRequested > m_fifoLength (" << frames_requested
105 << " > " << fifo_length_ << ")"; 108 << " > " << fifo_length_ << ")";
106 } 109 }
107 if (index_read_ >= fifo_length_) { 110 if (index_read_ >= fifo_length_) {
108 LOG(WARNING) << "[WebAudio/PushPullFIFO::pull <" << static_cast<void*>(this) 111 LOG(WARNING) << "[WebAudio/PushPullFIFO::pull <" << static_cast<void*>(this)
109 << ">] m_indexRead >= m_fifoLength (" << index_read_ 112 << ">] m_indexRead >= m_fifoLength (" << index_read_
110 << " >= " << fifo_length_ << ")"; 113 << " >= " << fifo_length_ << ")";
111 } 114 }
112 #endif 115 #endif
116
113 CHECK(output_bus); 117 CHECK(output_bus);
114 SECURITY_CHECK(frames_requested <= output_bus->length()); 118 SECURITY_CHECK(frames_requested <= output_bus->length());
115 SECURITY_CHECK(frames_requested <= fifo_length_); 119 SECURITY_CHECK(frames_requested <= fifo_length_);
116 SECURITY_CHECK(index_read_ < fifo_length_); 120 SECURITY_CHECK(index_read_ < fifo_length_);
117 121
118 const size_t remainder = fifo_length_ - index_read_; 122 const size_t remainder = fifo_length_ - index_read_;
119 const size_t frames_to_fill = std::min(frames_available_, frames_requested); 123 const size_t frames_to_fill = std::min(frames_available_, frames_requested);
120 124
121 for (unsigned i = 0; i < fifo_bus_->NumberOfChannels(); ++i) { 125 for (unsigned i = 0; i < fifo_bus_->NumberOfChannels(); ++i) {
122 const float* fifo_bus_channel = fifo_bus_->Channel(i)->Data(); 126 const float* fifo_bus_channel = fifo_bus_->Channel(i)->Data();
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
157 << ", requestedFrames=" << frames_requested 161 << ", requestedFrames=" << frames_requested
158 << ", fifoLength=" << fifo_length_ << ")"; 162 << ", fifoLength=" << fifo_length_ << ")";
159 } 163 }
160 } 164 }
161 165
162 // Update the number of frames in FIFO. 166 // Update the number of frames in FIFO.
163 frames_available_ -= frames_to_fill; 167 frames_available_ -= frames_to_fill;
164 DCHECK_EQ((index_read_ + frames_available_) % fifo_length_, index_write_); 168 DCHECK_EQ((index_read_ + frames_available_) % fifo_length_, index_write_);
165 } 169 }
166 170
171 AudioBus* PushPullFIFO::GetFIFOBusForTest() const {
172 MutexLocker lock(lock_);
173 return fifo_bus_.Get();
174 }
175
167 const PushPullFIFOStateForTest PushPullFIFO::GetStateForTest() const { 176 const PushPullFIFOStateForTest PushPullFIFO::GetStateForTest() const {
168 return {length(), NumberOfChannels(), FramesAvailable(), index_read_, 177 return {length(), NumberOfChannels(), frames_available_, index_read_,
169 index_write_, overflow_count_, underflow_count_}; 178 index_write_, overflow_count_, underflow_count_};
179
180 }
181
182 bool PushPullFIFO::IsRenderingThread() {
183 return rendering_thread_id_ == CurrentThread();
184 }
185
186 // Push the data from |inputBus| to FIFO. The size of push is determined by
187 // the length of |inputBus|.
188 void PushPullFIFO::Push(const AudioBus* input_bus) {
189 // This runs on WebAudio rendering thread.
190 DCHECK(IsRenderingThread());
191
192 CHECK(input_bus);
193 CHECK_EQ(input_bus->length(), AudioUtilities::kRenderQuantumFrames);
194 SECURITY_CHECK(input_bus->length() <= fifo_length_);
195 SECURITY_CHECK(index_write_ < fifo_length_);
196
197 const size_t input_bus_length = input_bus->length();
198 const size_t remainder = fifo_length_ - index_write_;
199
200 for (unsigned i = 0; i < fifo_bus_->NumberOfChannels(); ++i) {
201 float* fifo_bus_channel = fifo_bus_->Channel(i)->MutableData();
202 const float* input_bus_channel = input_bus->Channel(i)->Data();
203 if (remainder >= input_bus_length) {
204 // The remainder is big enough for the input data.
205 memcpy(fifo_bus_channel + index_write_, input_bus_channel,
206 input_bus_length * sizeof(*fifo_bus_channel));
207 } else {
208 // The input data overflows the remainder size. Wrap around the index.
209 memcpy(fifo_bus_channel + index_write_, input_bus_channel,
210 remainder * sizeof(*fifo_bus_channel));
211 memcpy(fifo_bus_channel, input_bus_channel + remainder,
212 (input_bus_length - remainder) * sizeof(*fifo_bus_channel));
213 }
214 }
215
216 // Update the write index; wrap it around if necessary.
217 index_write_ = (index_write_ + input_bus_length) % fifo_length_;
218
219 // In case of overflow, move the |indexRead| to the updated |indexWrite| to
220 // avoid reading overwritten frames by the next pull.
221 if (input_bus_length > fifo_length_ - frames_available_) {
222 index_read_ = index_write_;
223 if (++overflow_count_ < kMaxMessagesToLog) {
224 LOG(WARNING) << "PushPullFIFO: overflow while pushing ("
225 << "overflowCount=" << overflow_count_
226 << ", availableFrames=" << frames_available_
227 << ", inputFrames=" << input_bus_length
228 << ", fifoLength=" << fifo_length_ << ")";
229 }
230 }
231
232 // Update the number of frames available in FIFO.
233 frames_available_ =
234 std::min(frames_available_ + input_bus_length, fifo_length_);
235 DCHECK_EQ((index_read_ + frames_available_) % fifo_length_, index_write_);
170 } 236 }
171 237
172 } // namespace blink 238 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698