| 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 // TODO(andrew.macpherson): This either needs to be bigger since some OSes allow | 53 // TODO(andrew.macpherson): This either needs to be bigger since some OSes allow |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 124 | 124 |
| 125 // Associate the destination data array with the output bus then fill the | 125 // Associate the destination data array with the output bus then fill the |
| 126 // FIFO. | 126 // FIFO. |
| 127 for (unsigned i = 0; i < number_of_output_channels_; ++i) | 127 for (unsigned i = 0; i < number_of_output_channels_; ++i) |
| 128 output_bus_->SetChannelMemory(i, destination_data[i], number_of_frames); | 128 output_bus_->SetChannelMemory(i, destination_data[i], number_of_frames); |
| 129 | 129 |
| 130 size_t frames_to_render = fifo_->Pull(output_bus_.Get(), number_of_frames); | 130 size_t frames_to_render = fifo_->Pull(output_bus_.Get(), number_of_frames); |
| 131 | 131 |
| 132 // TODO(hongchan): this check might be redundant, so consider removing later. | 132 // TODO(hongchan): this check might be redundant, so consider removing later. |
| 133 if (frames_to_render != 0 && rendering_thread_) { | 133 if (frames_to_render != 0 && rendering_thread_) { |
| 134 rendering_thread_->GetWebTaskRunner()->PostTask( | 134 rendering_thread_->PostTask( |
| 135 BLINK_FROM_HERE, | 135 BLINK_FROM_HERE, |
| 136 CrossThreadBind(&AudioDestination::RequestRenderOnWebThread, | 136 CrossThreadBind(&AudioDestination::RequestRenderOnWorkerThread, |
| 137 CrossThreadUnretained(this), number_of_frames, | 137 CrossThreadUnretained(this), number_of_frames, |
| 138 frames_to_render, delay, delay_timestamp, | 138 frames_to_render, delay, delay_timestamp, |
| 139 prior_frames_skipped)); | 139 prior_frames_skipped)); |
| 140 } | 140 } |
| 141 } | 141 } |
| 142 | 142 |
| 143 void AudioDestination::RequestRenderOnWebThread(size_t frames_requested, | 143 void AudioDestination::RequestRenderOnWorkerThread(size_t frames_requested, |
| 144 size_t frames_to_render, | 144 size_t frames_to_render, |
| 145 double delay, | 145 double delay, |
| 146 double delay_timestamp, | 146 double delay_timestamp, |
| 147 size_t prior_frames_skipped) { | 147 size_t prior_frames_skipped) { |
| 148 TRACE_EVENT1("webaudio", "AudioDestination::RequestRenderOnWebThread", | 148 TRACE_EVENT1("webaudio", "AudioDestination::RequestRenderOnWebThread", |
| 149 "frames_to_render", frames_to_render); | 149 "frames_to_render", frames_to_render); |
| 150 | 150 |
| 151 // This method is called by WebThread. | 151 // This method is called by WebThread. |
| 152 DCHECK(IsRenderingThread()); | 152 DCHECK(IsRenderingThread()); |
| 153 | 153 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 177 | 177 |
| 178 // Process WebAudio graph and push the rendered output to FIFO. | 178 // Process WebAudio graph and push the rendered output to FIFO. |
| 179 callback_.Render(nullptr, render_bus_.Get(), | 179 callback_.Render(nullptr, render_bus_.Get(), |
| 180 AudioUtilities::kRenderQuantumFrames, output_position); | 180 AudioUtilities::kRenderQuantumFrames, output_position); |
| 181 fifo_->Push(render_bus_.Get()); | 181 fifo_->Push(render_bus_.Get()); |
| 182 } | 182 } |
| 183 | 183 |
| 184 frames_elapsed_ += frames_requested; | 184 frames_elapsed_ += frames_requested; |
| 185 } | 185 } |
| 186 | 186 |
| 187 void AudioDestination::Start() { | 187 void AudioDestination::Start(WebThreadSupportingGC* thread) { |
| 188 DCHECK(IsMainThread()); | 188 DCHECK(IsMainThread()); |
| 189 | 189 |
| 190 // Start the "audio device" after the rendering thread is ready. | 190 // Start the "audio device" after the rendering thread is ready. |
| 191 if (web_audio_device_ && !is_playing_) { | 191 if (web_audio_device_ && !is_playing_) { |
| 192 TRACE_EVENT0("webaudio", "AudioDestination::Start"); | 192 TRACE_EVENT0("webaudio", "AudioDestination::Start"); |
| 193 rendering_thread_ = | 193 rendering_thread_ = thread; |
| 194 Platform::Current()->CreateThread("WebAudio Rendering Thread"); | |
| 195 web_audio_device_->Start(); | 194 web_audio_device_->Start(); |
| 196 is_playing_ = true; | 195 is_playing_ = true; |
| 197 } | 196 } |
| 198 } | 197 } |
| 199 | 198 |
| 200 void AudioDestination::Stop() { | 199 void AudioDestination::Stop() { |
| 201 DCHECK(IsMainThread()); | 200 DCHECK(IsMainThread()); |
| 202 | 201 |
| 203 // This assumes stopping the "audio device" is synchronous and dumping the | 202 // This assumes stopping the "audio device" is synchronous and dumping the |
| 204 // rendering thread is safe after that. | 203 // rendering thread is safe after that. |
| 205 if (web_audio_device_ && is_playing_) { | 204 if (web_audio_device_ && is_playing_) { |
| 206 TRACE_EVENT0("webaudio", "AudioDestination::Stop"); | 205 TRACE_EVENT0("webaudio", "AudioDestination::Stop"); |
| 207 web_audio_device_->Stop(); | 206 web_audio_device_->Stop(); |
| 208 rendering_thread_.reset(); | |
| 209 is_playing_ = false; | 207 is_playing_ = false; |
| 210 } | 208 } |
| 211 } | 209 } |
| 212 | 210 |
| 213 size_t AudioDestination::CallbackBufferSize() const { | 211 size_t AudioDestination::CallbackBufferSize() const { |
| 214 DCHECK(IsMainThread()); | 212 DCHECK(IsMainThread()); |
| 215 return callback_buffer_size_; | 213 return callback_buffer_size_; |
| 216 } | 214 } |
| 217 | 215 |
| 218 bool AudioDestination::IsPlaying() { | 216 bool AudioDestination::IsPlaying() { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 254 callback_buffer_size_histogram.Sample(callback_buffer_size_); | 252 callback_buffer_size_histogram.Sample(callback_buffer_size_); |
| 255 | 253 |
| 256 // Check if the requested buffer size is too large. | 254 // Check if the requested buffer size is too large. |
| 257 bool is_buffer_size_valid = | 255 bool is_buffer_size_valid = |
| 258 callback_buffer_size_ + AudioUtilities::kRenderQuantumFrames <= kFIFOSize; | 256 callback_buffer_size_ + AudioUtilities::kRenderQuantumFrames <= kFIFOSize; |
| 259 DCHECK(is_buffer_size_valid); | 257 DCHECK(is_buffer_size_valid); |
| 260 return is_buffer_size_valid; | 258 return is_buffer_size_valid; |
| 261 } | 259 } |
| 262 | 260 |
| 263 bool AudioDestination::IsRenderingThread() { | 261 bool AudioDestination::IsRenderingThread() { |
| 264 return static_cast<ThreadIdentifier>(rendering_thread_->ThreadId()) == | 262 return rendering_thread_->IsCurrentThread(); |
| 265 CurrentThread(); | |
| 266 } | 263 } |
| 267 | 264 |
| 268 } // namespace blink | 265 } // namespace blink |
| OLD | NEW |