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

Side by Side Diff: Source/modules/webaudio/AudioContext.h

Issue 1214463003: Split "Online" and "Offline" AudioContext processing (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Bring to ToT Created 5 years, 5 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 | Annotate | Revision Log
OLDNEW
1 /* 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 * Copyright (C) 2010, Google Inc. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be
3 * 3 // found in the LICENSE file.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND AN Y
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16 * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR AN Y
17 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND O N
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 */
24 4
25 #ifndef AudioContext_h 5 #ifndef AudioContext_h
26 #define AudioContext_h 6 #define AudioContext_h
27 7
28 #include "bindings/core/v8/ScriptPromise.h" 8 #include "bindings/core/v8/ScriptPromise.h"
29 #include "bindings/core/v8/ScriptPromiseResolver.h" 9 #include "bindings/core/v8/ScriptPromiseResolver.h"
30 #include "core/dom/ActiveDOMObject.h" 10 #include "modules/webaudio/AbstractAudioContext.h"
31 #include "core/dom/DOMTypedArray.h"
32 #include "core/events/EventListener.h"
33 #include "modules/EventTargetModules.h"
34 #include "modules/ModulesExport.h"
35 #include "modules/webaudio/AsyncAudioDecoder.h"
36 #include "modules/webaudio/AudioDestinationNode.h"
37 #include "modules/webaudio/DeferredTaskHandler.h"
38 #include "platform/audio/AudioBus.h"
39 #include "platform/heap/Handle.h" 11 #include "platform/heap/Handle.h"
40 #include "wtf/HashSet.h"
41 #include "wtf/MainThread.h"
42 #include "wtf/RefPtr.h"
43 #include "wtf/Threading.h"
44 #include "wtf/Vector.h"
45 12
46 namespace blink { 13 namespace blink {
47 14
48 class AnalyserNode;
49 class AudioBuffer;
50 class AudioBufferCallback;
51 class AudioBufferSourceNode;
52 class AudioListener;
53 class AudioSummingJunction;
54 class BiquadFilterNode;
55 class ChannelMergerNode;
56 class ChannelSplitterNode;
57 class ConvolverNode;
58 class DelayNode;
59 class Document; 15 class Document;
60 class DynamicsCompressorNode;
61 class ExceptionState; 16 class ExceptionState;
62 class GainNode;
63 class HTMLMediaElement;
64 class MediaElementAudioSourceNode;
65 class MediaStreamAudioDestinationNode;
66 class MediaStreamAudioSourceNode;
67 class OscillatorNode;
68 class PannerNode;
69 class PeriodicWave;
70 class ScriptProcessorNode;
71 class ScriptPromiseResolver;
72 class ScriptState; 17 class ScriptState;
73 class SecurityOrigin;
74 class StereoPannerNode;
75 class WaveShaperNode;
76 18
77 // AudioContext is the cornerstone of the web audio API and all AudioNodes are c reated from it. 19 // This is an AbstractAudioContext which actually plays sound, unlike an
78 // For thread safety between the audio thread and the main thread, it has a rend ering graph locking mechanism. 20 // OfflineAudioContext which renders sound into a buffer.
79 21 class AudioContext : public AbstractAudioContext {
80 class MODULES_EXPORT AudioContext : public RefCountedGarbageCollectedEventTarget WithInlineData<AudioContext>, public ActiveDOMObject {
81 REFCOUNTED_GARBAGE_COLLECTED_EVENT_TARGET(AudioContext);
82 WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(AudioContext);
83 DEFINE_WRAPPERTYPEINFO();
84 public: 22 public:
85 // The state of an audio context. On creation, the state is Suspended. The state is Running if 23 static AbstractAudioContext* create(Document&, ExceptionState&);
86 // audio is being processed (audio graph is being pulled for data). The stat e is Closed if the
87 // audio context has been closed. The valid transitions are from Suspended to either Running or
88 // Closed; Running to Suspended or Closed. Once Closed, there are no valid t ransitions.
89 enum AudioContextState {
90 Suspended,
91 Running,
92 Closed
93 };
94
95 // Create an AudioContext for rendering to the audio hardware.
96 static AudioContext* create(Document&, ExceptionState&);
97 24
98 ~AudioContext() override; 25 ~AudioContext() override;
99
100 DECLARE_VIRTUAL_TRACE(); 26 DECLARE_VIRTUAL_TRACE();
101 27
102 bool isInitialized() const { return m_isInitialized; } 28 ScriptPromise closeContext(ScriptState*) final;
103 bool isOfflineContext() { return m_isOfflineContext; } 29 bool isContextClosed() const final;
104 30
105 // Document notification 31 ScriptPromise suspendContext(ScriptState*) final;
106 void stop() final; 32 ScriptPromise resumeContext(ScriptState*) final;
107 bool hasPendingActivity() const override;
108 33
109 AudioDestinationNode* destination() { return m_destinationNode.get(); } 34 bool hasRealtimeConstraint() final { return true; }
110
111 size_t currentSampleFrame() const
112 {
113 return m_destinationNode ? m_destinationNode->audioDestinationHandler(). currentSampleFrame() : 0;
114 }
115
116 double currentTime() const
117 {
118 return m_destinationNode ? m_destinationNode->audioDestinationHandler(). currentTime() : 0;
119 }
120
121 float sampleRate() const { return m_destinationNode ? m_destinationNode->han dler().sampleRate() : 0; }
122
123 String state() const;
124 AudioContextState contextState() const { return m_contextState; }
125
126 AudioBuffer* createBuffer(unsigned numberOfChannels, size_t numberOfFrames, float sampleRate, ExceptionState&);
127
128 // Asynchronous audio file data decoding.
129 void decodeAudioData(DOMArrayBuffer*, AudioBufferCallback*, AudioBufferCallb ack*, ExceptionState&);
130
131 AudioListener* listener() { return m_listener.get(); }
132
133 // The AudioNode create methods are called on the main thread (from JavaScri pt).
134 AudioBufferSourceNode* createBufferSource(ExceptionState&);
135 MediaElementAudioSourceNode* createMediaElementSource(HTMLMediaElement*, Exc eptionState&);
136 MediaStreamAudioSourceNode* createMediaStreamSource(MediaStream*, ExceptionS tate&);
137 MediaStreamAudioDestinationNode* createMediaStreamDestination(ExceptionState &);
138 GainNode* createGain(ExceptionState&);
139 BiquadFilterNode* createBiquadFilter(ExceptionState&);
140 WaveShaperNode* createWaveShaper(ExceptionState&);
141 DelayNode* createDelay(ExceptionState&);
142 DelayNode* createDelay(double maxDelayTime, ExceptionState&);
143 PannerNode* createPanner(ExceptionState&);
144 ConvolverNode* createConvolver(ExceptionState&);
145 DynamicsCompressorNode* createDynamicsCompressor(ExceptionState&);
146 AnalyserNode* createAnalyser(ExceptionState&);
147 ScriptProcessorNode* createScriptProcessor(ExceptionState&);
148 ScriptProcessorNode* createScriptProcessor(size_t bufferSize, ExceptionState &);
149 ScriptProcessorNode* createScriptProcessor(size_t bufferSize, size_t numberO fInputChannels, ExceptionState&);
150 ScriptProcessorNode* createScriptProcessor(size_t bufferSize, size_t numberO fInputChannels, size_t numberOfOutputChannels, ExceptionState&);
151 StereoPannerNode* createStereoPanner(ExceptionState&);
152 ChannelSplitterNode* createChannelSplitter(ExceptionState&);
153 ChannelSplitterNode* createChannelSplitter(size_t numberOfOutputs, Exception State&);
154 ChannelMergerNode* createChannelMerger(ExceptionState&);
155 ChannelMergerNode* createChannelMerger(size_t numberOfInputs, ExceptionState &);
156 OscillatorNode* createOscillator(ExceptionState&);
157 PeriodicWave* createPeriodicWave(DOMFloat32Array* real, DOMFloat32Array* ima g, ExceptionState&);
158
159 // Close
160 ScriptPromise closeContext(ScriptState*);
161
162 // Suspend/Resume
163 ScriptPromise suspendContext(ScriptState*);
164 ScriptPromise resumeContext(ScriptState*);
165
166 // When a source node has started processing and needs to be protected,
167 // this method tells the context to protect the node.
168 //
169 // The context itself keeps a reference to all source nodes. The source
170 // nodes, then reference all nodes they're connected to. In turn, these
171 // nodes reference all nodes they're connected to. All nodes are ultimately
172 // connected to the AudioDestinationNode. When the context release a source
173 // node, it will be deactivated from the rendering graph along with all
174 // other nodes it is uniquely connected to.
175 void notifySourceNodeStartedProcessing(AudioNode*);
176 // When a source node has no more processing to do (has finished playing),
177 // this method tells the context to release the corresponding node.
178 void notifySourceNodeFinishedProcessing(AudioHandler*);
179
180 // Called at the start of each render quantum.
181 void handlePreRenderTasks();
182
183 // Called at the end of each render quantum.
184 void handlePostRenderTasks();
185
186 // Called periodically at the end of each render quantum to release finished
187 // source nodes.
188 void releaseFinishedSourceNodes();
189
190 // Keeps track of the number of connections made.
191 void incrementConnectionCount()
192 {
193 ASSERT(isMainThread());
194 m_connectionCount++;
195 }
196
197 unsigned connectionCount() const { return m_connectionCount; }
198
199 DeferredTaskHandler& deferredTaskHandler() const { return *m_deferredTaskHan dler; }
200 //
201 // Thread Safety and Graph Locking:
202 //
203 // The following functions call corresponding functions of
204 // DeferredTaskHandler.
205 bool isAudioThread() const { return deferredTaskHandler().isAudioThread(); }
206 void lock() { deferredTaskHandler().lock(); }
207 bool tryLock() { return deferredTaskHandler().tryLock(); }
208 void unlock() { deferredTaskHandler().unlock(); }
209 #if ENABLE(ASSERT)
210 // Returns true if this thread owns the context's lock.
211 bool isGraphOwner() { return deferredTaskHandler().isGraphOwner(); }
212 #endif
213 using AutoLocker = DeferredTaskHandler::AutoLocker;
214
215 // Returns the maximum numuber of channels we can support.
216 static unsigned maxNumberOfChannels() { return MaxNumberOfChannels;}
217
218 // EventTarget
219 const AtomicString& interfaceName() const final;
220 ExecutionContext* executionContext() const final;
221
222 DEFINE_ATTRIBUTE_EVENT_LISTENER(complete);
223 DEFINE_ATTRIBUTE_EVENT_LISTENER(statechange);
224
225 void startRendering();
226 void fireCompletionEvent();
227 void notifyStateChange();
228
229 // A context is considered closed if:
230 // - closeContext() has been called, even if the audio HW has not yet been
231 // stopped. It will be stopped eventually.
232 // - it has been stopped (or is stopping) by its execution context.
233 bool isContextClosed() const { return m_closeResolver || m_isStopScheduled | | m_isCleared; }
234
235 static unsigned s_hardwareContextCount;
236 static unsigned s_contextId;
237
238 // Get the security origin for this audio context.
239 SecurityOrigin* securityOrigin() const;
240 35
241 protected: 36 protected:
242 explicit AudioContext(Document*); 37 AudioContext(Document&);
243 AudioContext(Document*, unsigned numberOfChannels, size_t numberOfFrames, fl oat sampleRate);
244 38
245 RefPtrWillBeMember<ScriptPromiseResolver> m_offlineResolver; 39 void didClose() final;
40
246 private: 41 private:
247 void initialize();
248 void uninitialize();
249
250 // ExecutionContext calls stop twice.
251 // We'd like to schedule only one stop action for them.
252 bool m_isStopScheduled;
253 bool m_isCleared;
254 void clear();
255
256 void throwExceptionForClosedState(ExceptionState&);
257
258 // Set to true when the destination node has been initialized and is ready t o process data.
259 bool m_isInitialized;
260
261 // When the context goes away, there might still be some sources which
262 // haven't finished playing. Make sure to release them here.
263 void releaseActiveSourceNodes();
264
265 Member<AudioDestinationNode> m_destinationNode;
266 Member<AudioListener> m_listener;
267
268 // Only accessed in the audio thread.
269 // These raw pointers are safe because AudioSourceNodes in
270 // m_activeSourceNodes own them.
271 Vector<AudioHandler*> m_finishedSourceHandlers;
272
273 // List of source nodes. This is either accessed when the graph lock is
274 // held, or on the main thread when the audio thread has finished.
275 // Oilpan: This Vector holds connection references. We must call
276 // AudioHandler::makeConnection when we add an AudioNode to this, and must
277 // call AudioHandler::breakConnection() when we remove an AudioNode from
278 // this.
279 HeapVector<Member<AudioNode>> m_activeSourceNodes;
280
281 // Stop rendering the audio graph.
282 void stopRendering(); 42 void stopRendering();
283 43
284 // Handle Promises for resume() and suspend() 44 unsigned m_contextId;
285 void resolvePromisesForResume();
286 void resolvePromisesForResumeOnMainThread();
287
288 // Vector of promises created by resume(). It takes time to handle them, so we collect all of
289 // the promises here until they can be resolved or rejected.
290 WillBeHeapVector<RefPtrWillBeMember<ScriptPromiseResolver>> m_resumeResolver s;
291 void rejectPendingResolvers();
292
293 // True if we're in the process of resolving promises for resume(). Resolvi ng can take some
294 // time and the audio context process loop is very fast, so we don't want to call resolve an
295 // excessive number of times.
296 bool m_isResolvingResumePromises;
297
298 unsigned m_connectionCount;
299
300 // Graph locking.
301 bool m_didInitializeContextGraphMutex;
302 RefPtr<DeferredTaskHandler> m_deferredTaskHandler;
303
304 Member<AudioBuffer> m_renderTarget;
305
306 bool m_isOfflineContext;
307
308 // The state of the AudioContext.
309 AudioContextState m_contextState;
310 void setContextState(AudioContextState);
311
312 AsyncAudioDecoder m_audioDecoder;
313
314 // The Promise that is returned by close();
315 RefPtrWillBeMember<ScriptPromiseResolver> m_closeResolver; 45 RefPtrWillBeMember<ScriptPromiseResolver> m_closeResolver;
316
317 // Tries to handle AudioBufferSourceNodes that were started but became disco nnected or was never
318 // connected. Because these never get pulled anymore, they will stay around forever. So if we
319 // can, try to stop them so they can be collected.
320 void handleStoppableSourceNodes();
321
322 // This is considering 32 is large enough for multiple channels audio.
323 // It is somewhat arbitrary and could be increased if necessary.
324 enum { MaxNumberOfChannels = 32 };
325
326 unsigned m_contextId;
327 }; 46 };
328 47
329 } // namespace blink 48 }
330 49
331 #endif // AudioContext_h 50 #endif // AudioContext_h
OLDNEW
« no previous file with comments | « Source/modules/webaudio/AudioBufferSourceNode.cpp ('k') | Source/modules/webaudio/AudioContext.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698