Media elements are allowed to continue to load media data after navigation
[WebKit-https.git] / Source / WebCore / Modules / webaudio / AudioContext.h
1 /*
2  * Copyright (C) 2010 Google Inc. All rights reserved.
3  * Copyright (C) 2016 Apple Inc. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1.  Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17  * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
18  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #pragma once
27
28 #include "ActiveDOMObject.h"
29 #include "AsyncAudioDecoder.h"
30 #include "AudioBus.h"
31 #include "AudioDestinationNode.h"
32 #include "EventListener.h"
33 #include "EventTarget.h"
34 #include "JSDOMPromiseDeferred.h"
35 #include "MediaCanStartListener.h"
36 #include "MediaProducer.h"
37 #include "PlatformMediaSession.h"
38 #include "VisibilityChangeClient.h"
39 #include <atomic>
40 #include <wtf/HashSet.h>
41 #include <wtf/MainThread.h>
42 #include <wtf/RefPtr.h>
43 #include <wtf/ThreadSafeRefCounted.h>
44 #include <wtf/Threading.h>
45 #include <wtf/Vector.h>
46 #include <wtf/text/AtomicStringHash.h>
47
48 namespace WebCore {
49
50 class AnalyserNode;
51 class AudioBuffer;
52 class AudioBufferCallback;
53 class AudioBufferSourceNode;
54 class AudioListener;
55 class AudioSummingJunction;
56 class BiquadFilterNode;
57 class ChannelMergerNode;
58 class ChannelSplitterNode;
59 class ConvolverNode;
60 class DelayNode;
61 class Document;
62 class DynamicsCompressorNode;
63 class GainNode;
64 class GenericEventQueue;
65 class HTMLMediaElement;
66 class MediaElementAudioSourceNode;
67 class MediaStream;
68 class MediaStreamAudioDestinationNode;
69 class MediaStreamAudioSourceNode;
70 class OscillatorNode;
71 class PannerNode;
72 class PeriodicWave;
73 class ScriptProcessorNode;
74 class WaveShaperNode;
75
76 // AudioContext is the cornerstone of the web audio API and all AudioNodes are created from it.
77 // For thread safety between the audio thread and the main thread, it has a rendering graph locking mechanism. 
78
79 class AudioContext : public ActiveDOMObject, public ThreadSafeRefCounted<AudioContext>, public EventTargetWithInlineData, public MediaCanStartListener, public MediaProducer, private PlatformMediaSessionClient, private VisibilityChangeClient {
80 public:
81     // Create an AudioContext for rendering to the audio hardware.
82     static RefPtr<AudioContext> create(Document&);
83
84     virtual ~AudioContext();
85
86     bool isInitialized() const;
87     
88     bool isOfflineContext() { return m_isOfflineContext; }
89
90     Document* document() const; // ASSERTs if document no longer exists.
91
92     const Document* hostingDocument() const override;
93
94     AudioDestinationNode* destination() { return m_destinationNode.get(); }
95     size_t currentSampleFrame() const { return m_destinationNode->currentSampleFrame(); }
96     double currentTime() const { return m_destinationNode->currentTime(); }
97     float sampleRate() const { return m_destinationNode->sampleRate(); }
98     unsigned long activeSourceCount() const { return static_cast<unsigned long>(m_activeSourceCount); }
99
100     void incrementActiveSourceCount();
101     void decrementActiveSourceCount();
102     
103     ExceptionOr<Ref<AudioBuffer>> createBuffer(unsigned numberOfChannels, size_t numberOfFrames, float sampleRate);
104     ExceptionOr<Ref<AudioBuffer>> createBuffer(ArrayBuffer&, bool mixToMono);
105
106     // Asynchronous audio file data decoding.
107     void decodeAudioData(Ref<ArrayBuffer>&&, RefPtr<AudioBufferCallback>&&, RefPtr<AudioBufferCallback>&&);
108
109     AudioListener* listener() { return m_listener.get(); }
110
111     using ActiveDOMObject::suspend;
112     using ActiveDOMObject::resume;
113
114     void suspend(DOMPromiseDeferred<void>&&);
115     void resume(DOMPromiseDeferred<void>&&);
116     void close(DOMPromiseDeferred<void>&&);
117
118     enum class State { Suspended, Running, Interrupted, Closed };
119     State state() const;
120
121     // The AudioNode create methods are called on the main thread (from JavaScript).
122     Ref<AudioBufferSourceNode> createBufferSource();
123 #if ENABLE(VIDEO)
124     ExceptionOr<Ref<MediaElementAudioSourceNode>> createMediaElementSource(HTMLMediaElement&);
125 #endif
126 #if ENABLE(MEDIA_STREAM)
127     ExceptionOr<Ref<MediaStreamAudioSourceNode>> createMediaStreamSource(MediaStream&);
128     Ref<MediaStreamAudioDestinationNode> createMediaStreamDestination();
129 #endif
130     Ref<GainNode> createGain();
131     Ref<BiquadFilterNode> createBiquadFilter();
132     Ref<WaveShaperNode> createWaveShaper();
133     ExceptionOr<Ref<DelayNode>> createDelay(double maxDelayTime);
134     Ref<PannerNode> createPanner();
135     Ref<ConvolverNode> createConvolver();
136     Ref<DynamicsCompressorNode> createDynamicsCompressor();
137     Ref<AnalyserNode> createAnalyser();
138     ExceptionOr<Ref<ScriptProcessorNode>> createScriptProcessor(size_t bufferSize, size_t numberOfInputChannels, size_t numberOfOutputChannels);
139     ExceptionOr<Ref<ChannelSplitterNode>> createChannelSplitter(size_t numberOfOutputs);
140     ExceptionOr<Ref<ChannelMergerNode>> createChannelMerger(size_t numberOfInputs);
141     Ref<OscillatorNode> createOscillator();
142     ExceptionOr<Ref<PeriodicWave>> createPeriodicWave(Float32Array& real, Float32Array& imaginary);
143
144     // When a source node has no more processing to do (has finished playing), then it tells the context to dereference it.
145     void notifyNodeFinishedProcessing(AudioNode*);
146
147     // Called at the start of each render quantum.
148     void handlePreRenderTasks();
149
150     // Called at the end of each render quantum.
151     void handlePostRenderTasks();
152
153     // Called periodically at the end of each render quantum to dereference finished source nodes.
154     void derefFinishedSourceNodes();
155
156     // We schedule deletion of all marked nodes at the end of each realtime render quantum.
157     void markForDeletion(AudioNode*);
158     void deleteMarkedNodes();
159
160     // AudioContext can pull node(s) at the end of each render quantum even when they are not connected to any downstream nodes.
161     // These two methods are called by the nodes who want to add/remove themselves into/from the automatic pull lists.
162     void addAutomaticPullNode(AudioNode*);
163     void removeAutomaticPullNode(AudioNode*);
164
165     // Called right before handlePostRenderTasks() to handle nodes which need to be pulled even when they are not connected to anything.
166     void processAutomaticPullNodes(size_t framesToProcess);
167
168     // Keeps track of the number of connections made.
169     void incrementConnectionCount()
170     {
171         ASSERT(isMainThread());
172         m_connectionCount++;
173     }
174
175     unsigned connectionCount() const { return m_connectionCount; }
176
177     //
178     // Thread Safety and Graph Locking:
179     //
180     
181     void setAudioThread(ThreadIdentifier thread) { m_audioThread = thread; } // FIXME: check either not initialized or the same
182     ThreadIdentifier audioThread() const { return m_audioThread; }
183     bool isAudioThread() const;
184
185     // Returns true only after the audio thread has been started and then shutdown.
186     bool isAudioThreadFinished() { return m_isAudioThreadFinished; }
187     
188     // mustReleaseLock is set to true if we acquired the lock in this method call and caller must unlock(), false if it was previously acquired.
189     void lock(bool& mustReleaseLock);
190
191     // Returns true if we own the lock.
192     // mustReleaseLock is set to true if we acquired the lock in this method call and caller must unlock(), false if it was previously acquired.
193     bool tryLock(bool& mustReleaseLock);
194
195     void unlock();
196
197     // Returns true if this thread owns the context's lock.
198     bool isGraphOwner() const;
199
200     // Returns the maximum number of channels we can support.
201     static unsigned maxNumberOfChannels() { return MaxNumberOfChannels; }
202
203     class AutoLocker {
204     public:
205         explicit AutoLocker(AudioContext& context)
206             : m_context(context)
207         {
208             m_context.lock(m_mustReleaseLock);
209         }
210         
211         ~AutoLocker()
212         {
213             if (m_mustReleaseLock)
214                 m_context.unlock();
215         }
216
217     private:
218         AudioContext& m_context;
219         bool m_mustReleaseLock;
220     };
221     
222     // In AudioNode::deref() a tryLock() is used for calling finishDeref(), but if it fails keep track here.
223     void addDeferredFinishDeref(AudioNode*);
224
225     // In the audio thread at the start of each render cycle, we'll call handleDeferredFinishDerefs().
226     void handleDeferredFinishDerefs();
227
228     // Only accessed when the graph lock is held.
229     void markSummingJunctionDirty(AudioSummingJunction*);
230     void markAudioNodeOutputDirty(AudioNodeOutput*);
231
232     // Must be called on main thread.
233     void removeMarkedSummingJunction(AudioSummingJunction*);
234
235     // EventTarget
236     EventTargetInterface eventTargetInterface() const final { return AudioContextEventTargetInterfaceType; }
237     ScriptExecutionContext* scriptExecutionContext() const final;
238
239     // Reconcile ref/deref which are defined both in ThreadSafeRefCounted and EventTarget.
240     using ThreadSafeRefCounted::ref;
241     using ThreadSafeRefCounted::deref;
242
243     void startRendering();
244     void fireCompletionEvent();
245     
246     static unsigned s_hardwareContextCount;
247
248     // Restrictions to change default behaviors.
249     enum BehaviorRestrictionFlags {
250         NoRestrictions = 0,
251         RequireUserGestureForAudioStartRestriction = 1 << 0,
252         RequirePageConsentForAudioStartRestriction = 1 << 1,
253     };
254     typedef unsigned BehaviorRestrictions;
255
256     BehaviorRestrictions behaviorRestrictions() const { return m_restrictions; }
257     void addBehaviorRestriction(BehaviorRestrictions restriction) { m_restrictions |= restriction; }
258     void removeBehaviorRestriction(BehaviorRestrictions restriction) { m_restrictions &= ~restriction; }
259
260     void isPlayingAudioDidChange();
261
262     void nodeWillBeginPlayback();
263
264 protected:
265     explicit AudioContext(Document&);
266     AudioContext(Document&, unsigned numberOfChannels, size_t numberOfFrames, float sampleRate);
267     
268     static bool isSampleRateRangeGood(float sampleRate);
269     
270 private:
271     void constructCommon();
272
273     void lazyInitialize();
274     void uninitialize();
275
276     bool willBeginPlayback();
277     bool willPausePlayback();
278
279     bool userGestureRequiredForAudioStart() const { return m_restrictions & RequireUserGestureForAudioStartRestriction; }
280     bool pageConsentRequiredForAudioStart() const { return m_restrictions & RequirePageConsentForAudioStartRestriction; }
281
282     void setState(State);
283
284     void clear();
285
286     void scheduleNodeDeletion();
287
288     void mediaCanStart(Document&) override;
289
290     // MediaProducer
291     MediaProducer::MediaStateFlags mediaState() const override;
292     void pageMutedStateDidChange() override;
293
294     // The context itself keeps a reference to all source nodes.  The source nodes, then reference all nodes they're connected to.
295     // In turn, these nodes reference all nodes they're connected to.  All nodes are ultimately connected to the AudioDestinationNode.
296     // When the context dereferences a source node, it will be deactivated from the rendering graph along with all other nodes it is
297     // uniquely connected to.  See the AudioNode::ref() and AudioNode::deref() methods for more details.
298     void refNode(AudioNode&);
299     void derefNode(AudioNode&);
300
301     // ActiveDOMObject API.
302     void stop() override;
303     bool canSuspendForDocumentSuspension() const override;
304     const char* activeDOMObjectName() const override;
305
306     // When the context goes away, there might still be some sources which haven't finished playing.
307     // Make sure to dereference them here.
308     void derefUnfinishedSourceNodes();
309
310     // PlatformMediaSessionClient
311     PlatformMediaSession::MediaType mediaType() const override { return PlatformMediaSession::WebAudio; }
312     PlatformMediaSession::MediaType presentationType() const override { return PlatformMediaSession::WebAudio; }
313     PlatformMediaSession::CharacteristicsFlags characteristics() const override { return m_state == State::Running ? PlatformMediaSession::HasAudio : PlatformMediaSession::HasNothing; }
314     void mayResumePlayback(bool shouldResume) override;
315     void suspendPlayback() override;
316     bool canReceiveRemoteControlCommands() const override { return false; }
317     void didReceiveRemoteControlCommand(PlatformMediaSession::RemoteControlCommandType, const PlatformMediaSession::RemoteCommandArgument*) override { }
318     bool supportsSeeking() const override { return false; }
319     bool shouldOverrideBackgroundPlaybackRestriction(PlatformMediaSession::InterruptionType) const override { return false; }
320     String sourceApplicationIdentifier() const override;
321     bool canProduceAudio() const final { return true; }
322     bool isSuspended() const final;
323     bool processingUserGestureForMedia() const final;
324
325     void visibilityStateChanged() final;
326
327     // EventTarget
328     void refEventTarget() override { ref(); }
329     void derefEventTarget() override { deref(); }
330
331     void handleDirtyAudioSummingJunctions();
332     void handleDirtyAudioNodeOutputs();
333
334     void addReaction(State, DOMPromiseDeferred<void>&&);
335     void updateAutomaticPullNodes();
336
337     // Only accessed in the audio thread.
338     Vector<AudioNode*> m_finishedNodes;
339
340     // We don't use RefPtr<AudioNode> here because AudioNode has a more complex ref() / deref() implementation
341     // with an optional argument for refType.  We need to use the special refType: RefTypeConnection
342     // Either accessed when the graph lock is held, or on the main thread when the audio thread has finished.
343     Vector<AudioNode*> m_referencedNodes;
344
345     // Accumulate nodes which need to be deleted here.
346     // This is copied to m_nodesToDelete at the end of a render cycle in handlePostRenderTasks(), where we're assured of a stable graph
347     // state which will have no references to any of the nodes in m_nodesToDelete once the context lock is released
348     // (when handlePostRenderTasks() has completed).
349     Vector<AudioNode*> m_nodesMarkedForDeletion;
350
351     // They will be scheduled for deletion (on the main thread) at the end of a render cycle (in realtime thread).
352     Vector<AudioNode*> m_nodesToDelete;
353
354     bool m_isDeletionScheduled { false };
355     bool m_isStopScheduled { false };
356     bool m_isInitialized { false };
357     bool m_isAudioThreadFinished { false };
358     bool m_automaticPullNodesNeedUpdating { false };
359     bool m_isOfflineContext { false };
360
361     // Only accessed when the graph lock is held.
362     HashSet<AudioSummingJunction*> m_dirtySummingJunctions;
363     HashSet<AudioNodeOutput*> m_dirtyAudioNodeOutputs;
364
365     // For the sake of thread safety, we maintain a seperate Vector of automatic pull nodes for rendering in m_renderingAutomaticPullNodes.
366     // It will be copied from m_automaticPullNodes by updateAutomaticPullNodes() at the very start or end of the rendering quantum.
367     HashSet<AudioNode*> m_automaticPullNodes;
368     Vector<AudioNode*> m_renderingAutomaticPullNodes;
369     // Only accessed in the audio thread.
370     Vector<AudioNode*> m_deferredFinishDerefList;
371     Vector<Vector<DOMPromiseDeferred<void>>> m_stateReactions;
372
373     std::unique_ptr<PlatformMediaSession> m_mediaSession;
374     std::unique_ptr<GenericEventQueue> m_eventQueue;
375
376     RefPtr<AudioBuffer> m_renderTarget;
377     RefPtr<AudioDestinationNode> m_destinationNode;
378     RefPtr<AudioListener> m_listener;
379
380     unsigned m_connectionCount { 0 };
381
382     // Graph locking.
383     Lock m_contextGraphMutex;
384     volatile ThreadIdentifier m_audioThread { 0 };
385     volatile ThreadIdentifier m_graphOwnerThread; // if the lock is held then this is the thread which owns it, otherwise == UndefinedThreadIdentifier
386
387     AsyncAudioDecoder m_audioDecoder;
388
389     // This is considering 32 is large enough for multiple channels audio. 
390     // It is somewhat arbitrary and could be increased if necessary.
391     enum { MaxNumberOfChannels = 32 };
392
393     // Number of AudioBufferSourceNodes that are active (playing).
394     std::atomic<int> m_activeSourceCount { 0 };
395
396     BehaviorRestrictions m_restrictions { NoRestrictions };
397
398     State m_state { State::Suspended };
399 };
400
401 // FIXME: Find out why these ==/!= functions are needed and remove them if possible.
402
403 inline bool operator==(const AudioContext& lhs, const AudioContext& rhs)
404 {
405     return &lhs == &rhs;
406 }
407
408 inline bool operator!=(const AudioContext& lhs, const AudioContext& rhs)
409 {
410     return &lhs != &rhs;
411 }
412
413 inline AudioContext::State AudioContext::state() const
414 {
415     return m_state;
416 }
417
418 } // WebCore