OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2010 Google Inc. All rights reserved. | 2 * Copyright (C) 2010 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * | 7 * |
8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
(...skipping 14 matching lines...) Expand all Loading... |
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 */ | 27 */ |
28 | 28 |
29 #include "platform/audio/AudioDestination.h" | 29 #include "platform/audio/AudioDestination.h" |
30 | 30 |
31 #include <memory> | 31 #include <memory> |
32 #include "platform/CrossThreadFunctional.h" | 32 #include "platform/CrossThreadFunctional.h" |
33 #include "platform/Histogram.h" | 33 #include "platform/Histogram.h" |
34 #include "platform/WebTaskRunner.h" | 34 #include "platform/WebTaskRunner.h" |
| 35 #include "platform/WebThreadSupportingGC.h" |
35 #include "platform/audio/AudioUtilities.h" | 36 #include "platform/audio/AudioUtilities.h" |
36 #include "platform/audio/PushPullFIFO.h" | 37 #include "platform/audio/PushPullFIFO.h" |
37 #include "platform/instrumentation/tracing/TraceEvent.h" | 38 #include "platform/instrumentation/tracing/TraceEvent.h" |
38 #include "platform/weborigin/SecurityOrigin.h" | 39 #include "platform/weborigin/SecurityOrigin.h" |
39 #include "platform/wtf/PtrUtil.h" | 40 #include "platform/wtf/PtrUtil.h" |
40 #include "public/platform/Platform.h" | 41 #include "public/platform/Platform.h" |
41 #include "public/platform/WebAudioLatencyHint.h" | 42 #include "public/platform/WebAudioLatencyHint.h" |
42 #include "public/platform/WebSecurityOrigin.h" | 43 #include "public/platform/WebSecurityOrigin.h" |
43 #include "public/platform/WebThread.h" | |
44 | 44 |
45 namespace blink { | 45 namespace blink { |
46 | 46 |
47 // FIFO Size. | 47 // FIFO Size. |
48 // | 48 // |
49 // TODO(hongchan): This was estimated based on the largest callback buffer size | 49 // TODO(hongchan): This was estimated based on the largest callback buffer size |
50 // that we would ever need. The current UMA stats indicates that this is, in | 50 // that we would ever need. The current UMA stats indicates that this is, in |
51 // fact, probably too small. There are Android devices out there with a size of | 51 // fact, probably too small. There are Android devices out there with a size of |
52 // 8000 or so. We might need to make this larger. See: crbug.com/670747 | 52 // 8000 or so. We might need to make this larger. See: crbug.com/670747 |
53 const size_t kFIFOSize = 8192; | 53 const size_t kFIFOSize = 8192; |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
118 | 118 |
119 // Associate the destination data array with the output bus then fill the | 119 // Associate the destination data array with the output bus then fill the |
120 // FIFO. | 120 // FIFO. |
121 for (unsigned i = 0; i < number_of_output_channels_; ++i) | 121 for (unsigned i = 0; i < number_of_output_channels_; ++i) |
122 output_bus_->SetChannelMemory(i, destination_data[i], number_of_frames); | 122 output_bus_->SetChannelMemory(i, destination_data[i], number_of_frames); |
123 | 123 |
124 size_t frames_to_render = fifo_->Pull(output_bus_.Get(), number_of_frames); | 124 size_t frames_to_render = fifo_->Pull(output_bus_.Get(), number_of_frames); |
125 | 125 |
126 // TODO(hongchan): this check might be redundant, so consider removing later. | 126 // TODO(hongchan): this check might be redundant, so consider removing later. |
127 if (frames_to_render != 0 && rendering_thread_) { | 127 if (frames_to_render != 0 && rendering_thread_) { |
128 rendering_thread_->GetWebTaskRunner()->PostTask( | 128 rendering_thread_->PostTask( |
129 BLINK_FROM_HERE, | 129 BLINK_FROM_HERE, |
130 CrossThreadBind(&AudioDestination::RequestRenderOnWebThread, | 130 CrossThreadBind(&AudioDestination::RequestRenderOnWorkerThread, |
131 CrossThreadUnretained(this), number_of_frames, | 131 CrossThreadUnretained(this), number_of_frames, |
132 frames_to_render, delay, delay_timestamp, | 132 frames_to_render, delay, delay_timestamp, |
133 prior_frames_skipped)); | 133 prior_frames_skipped)); |
134 } | 134 } |
135 } | 135 } |
136 | 136 |
137 void AudioDestination::RequestRenderOnWebThread(size_t frames_requested, | 137 void AudioDestination::RequestRenderOnWorkerThread(size_t frames_requested, |
138 size_t frames_to_render, | 138 size_t frames_to_render, |
139 double delay, | 139 double delay, |
140 double delay_timestamp, | 140 double delay_timestamp, |
141 size_t prior_frames_skipped) { | 141 size_t prior_frames_skipped) { |
142 TRACE_EVENT1("webaudio", "AudioDestination::RequestRenderOnWebThread", | 142 TRACE_EVENT1("webaudio", "AudioDestination::RequestRenderOnWebThread", |
143 "frames_to_render", frames_to_render); | 143 "frames_to_render", frames_to_render); |
144 | 144 |
145 // This method is called by WebThread. | 145 // This method is called by WebThread. |
146 DCHECK(IsRenderingThread()); | 146 DCHECK(IsRenderingThread()); |
147 | 147 |
(...skipping 23 matching lines...) Expand all Loading... |
171 | 171 |
172 // Process WebAudio graph and push the rendered output to FIFO. | 172 // Process WebAudio graph and push the rendered output to FIFO. |
173 callback_.Render(nullptr, render_bus_.Get(), | 173 callback_.Render(nullptr, render_bus_.Get(), |
174 AudioUtilities::kRenderQuantumFrames, output_position); | 174 AudioUtilities::kRenderQuantumFrames, output_position); |
175 fifo_->Push(render_bus_.Get()); | 175 fifo_->Push(render_bus_.Get()); |
176 } | 176 } |
177 | 177 |
178 frames_elapsed_ += frames_requested; | 178 frames_elapsed_ += frames_requested; |
179 } | 179 } |
180 | 180 |
181 void AudioDestination::Start() { | 181 void AudioDestination::Start(WebThreadSupportingGC* thread) { |
182 DCHECK(IsMainThread()); | 182 DCHECK(IsMainThread()); |
183 | 183 |
184 // Start the "audio device" after the rendering thread is ready. | 184 // Start the "audio device" after the rendering thread is ready. |
185 if (web_audio_device_ && !is_playing_) { | 185 if (web_audio_device_ && !is_playing_) { |
186 TRACE_EVENT0("webaudio", "AudioDestination::Start"); | 186 TRACE_EVENT0("webaudio", "AudioDestination::Start"); |
187 rendering_thread_ = | 187 rendering_thread_ = thread; |
188 Platform::Current()->CreateThread("WebAudio Rendering Thread"); | |
189 web_audio_device_->Start(); | 188 web_audio_device_->Start(); |
190 is_playing_ = true; | 189 is_playing_ = true; |
191 } | 190 } |
192 } | 191 } |
193 | 192 |
194 void AudioDestination::Stop() { | 193 void AudioDestination::Stop() { |
195 DCHECK(IsMainThread()); | 194 DCHECK(IsMainThread()); |
196 | 195 |
197 // This assumes stopping the "audio device" is synchronous and dumping the | 196 // This assumes stopping the "audio device" is synchronous and dumping the |
198 // rendering thread is safe after that. | 197 // rendering thread is safe after that. |
199 if (web_audio_device_ && is_playing_) { | 198 if (web_audio_device_ && is_playing_) { |
200 TRACE_EVENT0("webaudio", "AudioDestination::Stop"); | 199 TRACE_EVENT0("webaudio", "AudioDestination::Stop"); |
201 web_audio_device_->Stop(); | 200 web_audio_device_->Stop(); |
202 rendering_thread_.reset(); | |
203 is_playing_ = false; | 201 is_playing_ = false; |
204 } | 202 } |
205 } | 203 } |
206 | 204 |
207 size_t AudioDestination::CallbackBufferSize() const { | 205 size_t AudioDestination::CallbackBufferSize() const { |
208 DCHECK(IsMainThread()); | 206 DCHECK(IsMainThread()); |
209 return callback_buffer_size_; | 207 return callback_buffer_size_; |
210 } | 208 } |
211 | 209 |
212 bool AudioDestination::IsPlaying() { | 210 bool AudioDestination::IsPlaying() { |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
248 callback_buffer_size_histogram.Sample(callback_buffer_size_); | 246 callback_buffer_size_histogram.Sample(callback_buffer_size_); |
249 | 247 |
250 // Check if the requested buffer size is too large. | 248 // Check if the requested buffer size is too large. |
251 bool is_buffer_size_valid = | 249 bool is_buffer_size_valid = |
252 callback_buffer_size_ + AudioUtilities::kRenderQuantumFrames <= kFIFOSize; | 250 callback_buffer_size_ + AudioUtilities::kRenderQuantumFrames <= kFIFOSize; |
253 DCHECK(is_buffer_size_valid); | 251 DCHECK(is_buffer_size_valid); |
254 return is_buffer_size_valid; | 252 return is_buffer_size_valid; |
255 } | 253 } |
256 | 254 |
257 bool AudioDestination::IsRenderingThread() { | 255 bool AudioDestination::IsRenderingThread() { |
258 return static_cast<ThreadIdentifier>(rendering_thread_->ThreadId()) == | 256 return rendering_thread_->IsCurrentThread(); |
259 CurrentThread(); | |
260 } | 257 } |
261 | 258 |
262 } // namespace blink | 259 } // namespace blink |
OLD | NEW |