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

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

Issue 2885483002: Expose WebThread rendering only when AudioWorklet flag is enabled (Closed)
Patch Set: Created 3 years, 7 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 /* 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 13 matching lines...) Expand all
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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/RuntimeEnabledFeatures.h"
34 #include "platform/WebTaskRunner.h" 35 #include "platform/WebTaskRunner.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 #include "public/platform/WebThread.h"
(...skipping 25 matching lines...) Expand all
69 : number_of_output_channels_(number_of_output_channels), 70 : number_of_output_channels_(number_of_output_channels),
70 is_playing_(false), 71 is_playing_(false),
71 fifo_(WTF::WrapUnique( 72 fifo_(WTF::WrapUnique(
72 new PushPullFIFO(number_of_output_channels, kFIFOSize))), 73 new PushPullFIFO(number_of_output_channels, kFIFOSize))),
73 output_bus_(AudioBus::Create(number_of_output_channels, 74 output_bus_(AudioBus::Create(number_of_output_channels,
74 AudioUtilities::kRenderQuantumFrames, 75 AudioUtilities::kRenderQuantumFrames,
75 false)), 76 false)),
76 render_bus_(AudioBus::Create(number_of_output_channels, 77 render_bus_(AudioBus::Create(number_of_output_channels,
77 AudioUtilities::kRenderQuantumFrames)), 78 AudioUtilities::kRenderQuantumFrames)),
78 callback_(callback), 79 callback_(callback),
79 frames_elapsed_(0) { 80 frames_elapsed_(0),
81 is_audio_worklet_enabled(RuntimeEnabledFeatures::audioWorkletEnabled()) {
80 // Create WebAudioDevice. blink::WebAudioDevice is designed to support the 82 // Create WebAudioDevice. blink::WebAudioDevice is designed to support the
81 // local input (e.g. loopback from OS audio system), but Chromium's media 83 // local input (e.g. loopback from OS audio system), but Chromium's media
82 // renderer does not support it currently. Thus, we use zero for the number 84 // renderer does not support it currently. Thus, we use zero for the number
83 // of input channels. 85 // of input channels.
84 web_audio_device_ = Platform::Current()->CreateAudioDevice( 86 web_audio_device_ = Platform::Current()->CreateAudioDevice(
85 0, number_of_output_channels, latency_hint, this, String(), 87 0, number_of_output_channels, latency_hint, this, String(),
86 std::move(security_origin)); 88 std::move(security_origin));
87 DCHECK(web_audio_device_); 89 DCHECK(web_audio_device_);
88 90
89 callback_buffer_size_ = web_audio_device_->FramesPerBuffer(); 91 callback_buffer_size_ = web_audio_device_->FramesPerBuffer();
90 if (!CheckBufferSize()) { 92 if (!CheckBufferSize()) {
91 NOTREACHED(); 93 NOTREACHED();
92 } 94 }
95
96 LOG(INFO) << "AudioDestination::IsAudioWorkletEnabled() = "
97 << IsAudioWorkletEnabled();
93 } 98 }
94 99
95 AudioDestination::~AudioDestination() { 100 AudioDestination::~AudioDestination() {
96 Stop(); 101 Stop();
97 } 102 }
98 103
99 void AudioDestination::Render(const WebVector<float*>& destination_data, 104 void AudioDestination::Render(const WebVector<float*>& destination_data,
100 size_t number_of_frames, 105 size_t number_of_frames,
101 double delay, 106 double delay,
102 double delay_timestamp, 107 double delay_timestamp,
103 size_t prior_frames_skipped) { 108 size_t prior_frames_skipped) {
104 TRACE_EVENT1("webaudio", "AudioDestination::Render", 109 TRACE_EVENT1("webaudio", "AudioDestination::Render",
105 "callback_buffer_size", number_of_frames); 110 "callback_buffer_size", number_of_frames);
106 111
107 // This method is called by AudioDeviceThread. 112 DCHECK(!IsMainThread());
108 DCHECK(!IsRenderingThread());
109 113
110 CHECK_EQ(destination_data.size(), number_of_output_channels_); 114 CHECK_EQ(destination_data.size(), number_of_output_channels_);
111 CHECK_EQ(number_of_frames, callback_buffer_size_); 115 CHECK_EQ(number_of_frames, callback_buffer_size_);
112 116
113 // Note that this method is called by AudioDeviceThread. If FIFO is not ready, 117 // Note that this method is called by AudioDeviceThread. If FIFO is not ready,
114 // or the requested render size is greater than FIFO size return here. 118 // or the requested render size is greater than FIFO size return here.
115 // (crbug.com/692423) 119 // (crbug.com/692423)
116 if (!fifo_ || fifo_->length() < number_of_frames) 120 if (!fifo_ || fifo_->length() < number_of_frames)
117 return; 121 return;
118 122
119 // Associate the destination data array with the output bus then fill the 123 // Associate the destination data array with the output bus then fill the
120 // FIFO. 124 // FIFO.
121 for (unsigned i = 0; i < number_of_output_channels_; ++i) 125 for (unsigned i = 0; i < number_of_output_channels_; ++i)
122 output_bus_->SetChannelMemory(i, destination_data[i], number_of_frames); 126 output_bus_->SetChannelMemory(i, destination_data[i], number_of_frames);
123 127
124 size_t frames_to_render = fifo_->Pull(output_bus_.Get(), number_of_frames); 128 size_t frames_to_render = fifo_->Pull(output_bus_.Get(), number_of_frames);
125 129
126 // TODO(hongchan): this check might be redundant, so consider removing later. 130 // If AudioWorklet is enabled, use dual thread rendering.
127 if (frames_to_render != 0 && rendering_thread_) { 131 if (IsAudioWorkletEnabled()) {
128 rendering_thread_->GetWebTaskRunner()->PostTask( 132 // TODO(hongchan): this check might be redundant, so consider removing
129 BLINK_FROM_HERE, 133 // later.
130 CrossThreadBind(&AudioDestination::RequestRenderOnWebThread, 134 if (frames_to_render != 0 && rendering_thread_) {
131 CrossThreadUnretained(this), number_of_frames, 135 rendering_thread_->GetWebTaskRunner()->PostTask(
132 frames_to_render, delay, delay_timestamp, 136 BLINK_FROM_HERE,
133 prior_frames_skipped)); 137 CrossThreadBind(&AudioDestination::RequestRender,
138 CrossThreadUnretained(this), number_of_frames,
139 frames_to_render, delay, delay_timestamp,
140 prior_frames_skipped));
141 }
142 } else {
143 RequestRender(number_of_frames, frames_to_render, delay, delay_timestamp,
144 prior_frames_skipped);
134 } 145 }
135 } 146 }
136 147
137 void AudioDestination::RequestRenderOnWebThread(size_t frames_requested, 148 void AudioDestination::RequestRender(size_t frames_requested,
138 size_t frames_to_render, 149 size_t frames_to_render,
139 double delay, 150 double delay,
140 double delay_timestamp, 151 double delay_timestamp,
141 size_t prior_frames_skipped) { 152 size_t prior_frames_skipped) {
142 TRACE_EVENT1("webaudio", "AudioDestination::RequestRenderOnWebThread", 153 TRACE_EVENT1("webaudio", "AudioDestination::RequestRender",
143 "frames_to_render", frames_to_render); 154 "frames_to_render", frames_to_render);
144 155
145 // This method is called by WebThread.
146 DCHECK(IsRenderingThread());
147
148 frames_elapsed_ -= std::min(frames_elapsed_, prior_frames_skipped); 156 frames_elapsed_ -= std::min(frames_elapsed_, prior_frames_skipped);
149 AudioIOPosition output_position; 157 AudioIOPosition output_position;
150 output_position.position = 158 output_position.position =
151 frames_elapsed_ / static_cast<double>(web_audio_device_->SampleRate()) - 159 frames_elapsed_ / static_cast<double>(web_audio_device_->SampleRate()) -
152 delay; 160 delay;
153 output_position.timestamp = delay_timestamp; 161 output_position.timestamp = delay_timestamp;
154 base::TimeTicks received_timestamp = base::TimeTicks::Now(); 162 base::TimeTicks received_timestamp = base::TimeTicks::Now();
155 163
156 for (size_t pushed_frames = 0; pushed_frames < frames_to_render; 164 for (size_t pushed_frames = 0; pushed_frames < frames_to_render;
157 pushed_frames += AudioUtilities::kRenderQuantumFrames) { 165 pushed_frames += AudioUtilities::kRenderQuantumFrames) {
(...skipping 19 matching lines...) Expand all
177 185
178 frames_elapsed_ += frames_requested; 186 frames_elapsed_ += frames_requested;
179 } 187 }
180 188
181 void AudioDestination::Start() { 189 void AudioDestination::Start() {
182 DCHECK(IsMainThread()); 190 DCHECK(IsMainThread());
183 191
184 // Start the "audio device" after the rendering thread is ready. 192 // Start the "audio device" after the rendering thread is ready.
185 if (web_audio_device_ && !is_playing_) { 193 if (web_audio_device_ && !is_playing_) {
186 TRACE_EVENT0("webaudio", "AudioDestination::Start"); 194 TRACE_EVENT0("webaudio", "AudioDestination::Start");
187 rendering_thread_ = 195
188 Platform::Current()->CreateThread("WebAudio Rendering Thread"); 196 if (IsAudioWorkletEnabled()) {
197 rendering_thread_ =
198 Platform::Current()->CreateThread("WebAudio Rendering Thread");
199 }
200
189 web_audio_device_->Start(); 201 web_audio_device_->Start();
190 is_playing_ = true; 202 is_playing_ = true;
191 } 203 }
192 } 204 }
193 205
194 void AudioDestination::Stop() { 206 void AudioDestination::Stop() {
195 DCHECK(IsMainThread()); 207 DCHECK(IsMainThread());
196 208
197 // This assumes stopping the "audio device" is synchronous and dumping the 209 // This assumes stopping the "audio device" is synchronous and dumping the
198 // rendering thread is safe after that. 210 // rendering thread is safe after that.
199 if (web_audio_device_ && is_playing_) { 211 if (web_audio_device_ && is_playing_) {
200 TRACE_EVENT0("webaudio", "AudioDestination::Stop"); 212 TRACE_EVENT0("webaudio", "AudioDestination::Stop");
201 web_audio_device_->Stop(); 213 web_audio_device_->Stop();
202 rendering_thread_.reset(); 214
215 if (IsAudioWorkletEnabled()) {
216 rendering_thread_.reset();
217 }
218
203 is_playing_ = false; 219 is_playing_ = false;
204 } 220 }
205 } 221 }
206 222
207 size_t AudioDestination::CallbackBufferSize() const { 223 size_t AudioDestination::CallbackBufferSize() const {
208 DCHECK(IsMainThread()); 224 DCHECK(IsMainThread());
209 return callback_buffer_size_; 225 return callback_buffer_size_;
210 } 226 }
211 227
212 bool AudioDestination::IsPlaying() { 228 bool AudioDestination::IsPlaying() {
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
247 hardware_buffer_size_histogram.Sample(HardwareBufferSize()); 263 hardware_buffer_size_histogram.Sample(HardwareBufferSize());
248 callback_buffer_size_histogram.Sample(callback_buffer_size_); 264 callback_buffer_size_histogram.Sample(callback_buffer_size_);
249 265
250 // Check if the requested buffer size is too large. 266 // Check if the requested buffer size is too large.
251 bool is_buffer_size_valid = 267 bool is_buffer_size_valid =
252 callback_buffer_size_ + AudioUtilities::kRenderQuantumFrames <= kFIFOSize; 268 callback_buffer_size_ + AudioUtilities::kRenderQuantumFrames <= kFIFOSize;
253 DCHECK(is_buffer_size_valid); 269 DCHECK(is_buffer_size_valid);
254 return is_buffer_size_valid; 270 return is_buffer_size_valid;
255 } 271 }
256 272
257 bool AudioDestination::IsRenderingThread() {
258 return static_cast<ThreadIdentifier>(rendering_thread_->ThreadId()) ==
259 CurrentThread();
260 }
261
262 } // namespace blink 273 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698