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

Side by Side Diff: third_party/WebKit/Source/platform/audio/AudioDestination.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 /* 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 11 matching lines...) Expand all
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
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/Histogram.h" 33 #include "platform/Histogram.h"
34 #include "platform/WebTaskRunner.h"
33 #include "platform/audio/AudioUtilities.h" 35 #include "platform/audio/AudioUtilities.h"
34 #include "platform/audio/PushPullFIFO.h" 36 #include "platform/audio/PushPullFIFO.h"
35 #include "platform/weborigin/SecurityOrigin.h" 37 #include "platform/weborigin/SecurityOrigin.h"
36 #include "platform/wtf/PtrUtil.h" 38 #include "platform/wtf/PtrUtil.h"
37 #include "public/platform/Platform.h" 39 #include "public/platform/Platform.h"
38 #include "public/platform/WebAudioLatencyHint.h" 40 #include "public/platform/WebAudioLatencyHint.h"
39 #include "public/platform/WebSecurityOrigin.h" 41 #include "public/platform/WebSecurityOrigin.h"
42 #include "public/platform/WebThread.h"
40 43
41 namespace blink { 44 namespace blink {
42 45
43 // FIFO Size. 46 // FIFO Size.
44 // 47 //
45 // TODO(hongchan): This was estimated based on the largest callback buffer size 48 // TODO(hongchan): This was estimated based on the largest callback buffer size
46 // that we would ever need. The current UMA stats indicates that this is, in 49 // that we would ever need. The current UMA stats indicates that this is, in
47 // fact, probably too small. There are Android devices out there with a size of 50 // fact, probably too small. There are Android devices out there with a size of
48 // 8000 or so. We might need to make this larger. See: crbug.com/670747 51 // 8000 or so. We might need to make this larger. See: crbug.com/670747
49 const size_t kFIFOSize = 8192; 52 const size_t kFIFOSize = 8192;
50 53
51 std::unique_ptr<AudioDestination> AudioDestination::Create( 54 std::unique_ptr<AudioDestination> AudioDestination::Create(
52 AudioIOCallback& callback, 55 AudioIOCallback& callback,
53 unsigned number_of_output_channels, 56 unsigned number_of_output_channels,
54 const WebAudioLatencyHint& latency_hint, 57 const WebAudioLatencyHint& latency_hint,
55 PassRefPtr<SecurityOrigin> security_origin) { 58 PassRefPtr<SecurityOrigin> security_origin) {
56 return WTF::WrapUnique( 59 return WTF::WrapUnique(
57 new AudioDestination(callback, number_of_output_channels, latency_hint, 60 new AudioDestination(callback, number_of_output_channels, latency_hint,
58 std::move(security_origin))); 61 std::move(security_origin)));
59 } 62 }
60 63
61 AudioDestination::AudioDestination(AudioIOCallback& callback, 64 AudioDestination::AudioDestination(AudioIOCallback& web_audio_render_callback,
62 unsigned number_of_output_channels, 65 unsigned number_of_output_channels,
63 const WebAudioLatencyHint& latency_hint, 66 const WebAudioLatencyHint& latency_hint,
64 PassRefPtr<SecurityOrigin> security_origin) 67 PassRefPtr<SecurityOrigin> security_origin)
65 : number_of_output_channels_(number_of_output_channels), 68 : number_of_output_channels_(number_of_output_channels),
66 is_playing_(false), 69 is_playing_(false),
67 callback_(callback), 70 // callback_(callback),
68 output_bus_(AudioBus::Create(number_of_output_channels, 71 output_bus_(AudioBus::Create(number_of_output_channels,
69 AudioUtilities::kRenderQuantumFrames, 72 AudioUtilities::kRenderQuantumFrames,
70 false)), 73 false)),
71 render_bus_(AudioBus::Create(number_of_output_channels, 74 // render_bus_(AudioBus::Create(number_of_output_channels,
72 AudioUtilities::kRenderQuantumFrames)), 75 // AudioUtilities::kRenderQuantumFrames)),
73 fifo_(WTF::WrapUnique(
74 new PushPullFIFO(number_of_output_channels, kFIFOSize))),
75 frames_elapsed_(0) { 76 frames_elapsed_(0) {
77 // Create a thread |WebThread| for WebAudio graph rendering.
78 rendering_thread_ = WTF::WrapUnique(
79 Platform::Current()->CreateThread("WebAudio Rendering Thread"));
80
81 fifo_ = WTF::WrapUnique(new PushPullFIFO(number_of_output_channels, kFIFOSize,
82 rendering_thread_->ThreadId(),
83 web_audio_render_callback));
84
76 // Create WebAudioDevice. blink::WebAudioDevice is designed to support the 85 // Create WebAudioDevice. blink::WebAudioDevice is designed to support the
77 // local input (e.g. loopback from OS audio system), but Chromium's media 86 // local input (e.g. loopback from OS audio system), but Chromium's media
78 // renderer does not support it currently. Thus, we use zero for the number 87 // renderer does not support it currently. Thus, we use zero for the number
79 // of input channels. 88 // of input channels.
80 web_audio_device_ = WTF::WrapUnique(Platform::Current()->CreateAudioDevice( 89 web_audio_device_ = WTF::WrapUnique(Platform::Current()->CreateAudioDevice(
81 0, number_of_output_channels, latency_hint, this, String(), 90 0, number_of_output_channels, latency_hint, this, String(),
82 std::move(security_origin))); 91 std::move(security_origin)));
83 DCHECK(web_audio_device_); 92 DCHECK(web_audio_device_);
84 93
85 callback_buffer_size_ = web_audio_device_->FramesPerBuffer(); 94 callback_buffer_size_ = web_audio_device_->FramesPerBuffer();
86 if (!CheckBufferSize()) { 95 if (!CheckBufferSize()) {
87 NOTREACHED(); 96 NOTREACHED();
88 } 97 }
89 } 98 }
90 99
91 AudioDestination::~AudioDestination() { 100 AudioDestination::~AudioDestination() {
92 Stop(); 101 Stop();
93 } 102 }
94 103
95 void AudioDestination::Render(const WebVector<float*>& destination_data, 104 void AudioDestination::Render(const WebVector<float*>& destination_data,
96 size_t number_of_frames, 105 size_t number_of_frames,
97 double delay, 106 double delay,
98 double delay_timestamp, 107 double delay_timestamp,
99 size_t prior_frames_skipped) { 108 size_t prior_frames_skipped) {
109 // This this method is called by AudioDeviceThread.
110 DCHECK(!IsRenderingThread());
111
100 CHECK_EQ(destination_data.size(), number_of_output_channels_); 112 CHECK_EQ(destination_data.size(), number_of_output_channels_);
101 CHECK_EQ(number_of_frames, callback_buffer_size_); 113 CHECK_EQ(number_of_frames, callback_buffer_size_);
102 114
103 // Note that this method is called by AudioDeviceThread. If FIFO is not ready, 115 // Note that this method is called by AudioDeviceThread. If FIFO is not ready,
104 // or the requested render size is greater than FIFO size return here. 116 // or the requested render size is greater than FIFO size return here.
105 // (crbug.com/692423) 117 // (crbug.com/692423)
106 if (!fifo_ || fifo_->length() < number_of_frames) 118 if (!fifo_ || fifo_->length() < number_of_frames)
o1ka 2017/04/13 08:36:53 Are you keeping silent returns?
hongchan 2017/04/14 16:31:48 This inexplicable case happens only on Android. If
107 return; 119 return;
108 120
109 frames_elapsed_ -= std::min(frames_elapsed_, prior_frames_skipped);
110 double output_position =
111 frames_elapsed_ / static_cast<double>(web_audio_device_->SampleRate()) -
112 delay;
113 output_position_.position = output_position;
114 output_position_.timestamp = delay_timestamp;
115 output_position_received_timestamp_ = base::TimeTicks::Now();
116
117 // Associate the destination data array with the output bus then fill the 121 // Associate the destination data array with the output bus then fill the
118 // FIFO. 122 // FIFO.
119 for (unsigned i = 0; i < number_of_output_channels_; ++i) 123 for (unsigned i = 0; i < number_of_output_channels_; ++i)
120 output_bus_->SetChannelMemory(i, destination_data[i], number_of_frames); 124 output_bus_->SetChannelMemory(i, destination_data[i], number_of_frames);
121 125
122 // Number of frames to render via WebAudio graph. |framesToRender > 0| means 126 rendering_thread_->GetWebTaskRunner()->PostTask(
127 BLINK_FROM_HERE,
128 CrossThreadBind(&AudioDestination::RequestRenderOnWebThread,
129 CrossThreadUnretained(this), number_of_frames, delay,
130 delay_timestamp, prior_frames_skipped));
131
132 fifo_->Pull(output_bus_.Get(), number_of_frames);
133 }
134
135 void AudioDestination::RequestRenderOnWebThread(size_t number_of_frames,
136 double delay,
137 double delay_timestamp,
138 size_t prior_frames_skipped) {
139 // This this method is called by WebAudio rendering thread.
140 DCHECK(IsRenderingThread());
141
142 frames_elapsed_ -= std::min(frames_elapsed_, prior_frames_skipped);
143
144 AudioIOPosition output_position;
145 output_position.position =
146 frames_elapsed_ / static_cast<double>(web_audio_device_->SampleRate()) -
147 delay;
148 output_position.timestamp = delay_timestamp;
149
150 fifo_->FillRequestedFrames(number_of_frames, callback_buffer_size_,
151 output_position);
152
153 // double output_position =
154 // frames_elapsed_ / static_cast<double>(web_audio_device_->SampleRate()) -
155 // delay;
o1ka 2017/04/13 08:36:53 It's really inconvenient to review patches with co
hongchan 2017/04/14 16:31:48 I am terribly sorry about this mistake. :(
156 // output_position_.position = output_position;
157 // output_position_.timestamp = delay_timestamp;
158 // output_position_received_timestamp_ = base::TimeTicks::Now();
159
160 // Number of frames to render via WebAudio graph. |frames_to_render > 0| means
123 // the frames in FIFO is not enough to fulfill the requested frames from the 161 // the frames in FIFO is not enough to fulfill the requested frames from the
124 // audio device. 162 // audio device.
125 size_t frames_to_render = number_of_frames > fifo_->FramesAvailable() 163 // size_t frames_to_render = fifo_->GetFramesToRender(number_of_frames);
126 ? number_of_frames - fifo_->FramesAvailable()
127 : 0;
128 164
129 for (size_t pushed_frames = 0; pushed_frames < frames_to_render; 165 // for (size_t pushed_frames = 0; pushed_frames < frames_to_render;
130 pushed_frames += AudioUtilities::kRenderQuantumFrames) { 166 // pushed_frames += AudioUtilities::kRenderQuantumFrames) {
131 // If platform buffer is more than two times longer than |framesToProcess| 167 // // If platform buffer is more than two times longer than |framesToProcess |
132 // we do not want output position to get stuck so we promote it 168 // // we do not want output position to get stuck so we promote it
133 // using the elapsed time from the moment it was initially obtained. 169 // // using the elapsed time from the moment it was initially obtained.
134 if (callback_buffer_size_ > AudioUtilities::kRenderQuantumFrames * 2) { 170 // if (callback_buffer_size_ > AudioUtilities::kRenderQuantumFrames * 2) {
135 double delta = 171 // double delta =
136 (base::TimeTicks::Now() - output_position_received_timestamp_) 172 // (base::TimeTicks::Now() - output_position_received_timestamp_)
137 .InSecondsF(); 173 // .InSecondsF();
138 output_position_.position += delta; 174 // output_position_.position += delta;
139 output_position_.timestamp += delta; 175 // output_position_.timestamp += delta;
140 } 176 // }
141 177
142 // Some implementations give only rough estimation of |delay| so 178 // // Some implementations give only rough estimation of |delay| so
143 // we might have negative estimation |outputPosition| value. 179 // // we might have negative estimation |outputPosition| value.
144 if (output_position_.position < 0.0) 180 // if (output_position_.position < 0.0)
145 output_position_.position = 0.0; 181 // output_position_.position = 0.0;
146 182
147 // Process WebAudio graph and push the rendered output to FIFO. 183 // // Process WebAudio graph and push the rendered output to FIFO.
148 callback_.Render(nullptr, render_bus_.Get(), 184 // callback_.Render(nullptr, render_bus_.Get(),
149 AudioUtilities::kRenderQuantumFrames, output_position_); 185 // AudioUtilities::kRenderQuantumFrames, output_position_);
150 fifo_->Push(render_bus_.Get()); 186 // fifo_->Push(render_bus_.Get());
151 } 187 // }
152
153 fifo_->Pull(output_bus_.Get(), number_of_frames);
154 188
155 frames_elapsed_ += number_of_frames; 189 frames_elapsed_ += number_of_frames;
156 } 190 }
157 191
158 void AudioDestination::Start() { 192 void AudioDestination::Start() {
159 if (web_audio_device_ && !is_playing_) { 193 if (web_audio_device_ && !is_playing_) {
160 web_audio_device_->Start(); 194 web_audio_device_->Start();
161 is_playing_ = true; 195 is_playing_ = true;
162 } 196 }
163 } 197 }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
197 hardware_buffer_size_histogram.Sample(HardwareBufferSize()); 231 hardware_buffer_size_histogram.Sample(HardwareBufferSize());
198 callback_buffer_size_histogram.Sample(callback_buffer_size_); 232 callback_buffer_size_histogram.Sample(callback_buffer_size_);
199 233
200 // Check if the requested buffer size is too large. 234 // Check if the requested buffer size is too large.
201 bool is_buffer_size_valid = 235 bool is_buffer_size_valid =
202 callback_buffer_size_ + AudioUtilities::kRenderQuantumFrames <= kFIFOSize; 236 callback_buffer_size_ + AudioUtilities::kRenderQuantumFrames <= kFIFOSize;
203 DCHECK(is_buffer_size_valid); 237 DCHECK(is_buffer_size_valid);
204 return is_buffer_size_valid; 238 return is_buffer_size_valid;
205 } 239 }
206 240
241 bool AudioDestination::IsRenderingThread() {
242 return static_cast<ThreadIdentifier>(rendering_thread_->ThreadId()) ==
243 CurrentThread();
244 }
245
207 } // namespace blink 246 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698