Move more logic from AudioDestinationNode to its subclasses
[WebKit-https.git] / Source / WebCore / Modules / webaudio / BaseAudioContext.cpp
1 /*
2  * Copyright (C) 2010 Google Inc. All rights reserved.
3  * Copyright (C) 2016-2021 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 #include "config.h"
27
28 #if ENABLE(WEB_AUDIO)
29
30 #include "AudioContext.h"
31
32 #include "AnalyserNode.h"
33 #include "AsyncAudioDecoder.h"
34 #include "AudioBuffer.h"
35 #include "AudioBufferCallback.h"
36 #include "AudioBufferOptions.h"
37 #include "AudioBufferSourceNode.h"
38 #include "AudioDestination.h"
39 #include "AudioListener.h"
40 #include "AudioNodeInput.h"
41 #include "AudioNodeOutput.h"
42 #include "AudioParamDescriptor.h"
43 #include "AudioSession.h"
44 #include "AudioWorklet.h"
45 #include "BiquadFilterNode.h"
46 #include "ChannelMergerNode.h"
47 #include "ChannelMergerOptions.h"
48 #include "ChannelSplitterNode.h"
49 #include "ChannelSplitterOptions.h"
50 #include "ConstantSourceNode.h"
51 #include "ConstantSourceOptions.h"
52 #include "ConvolverNode.h"
53 #include "DelayNode.h"
54 #include "DelayOptions.h"
55 #include "Document.h"
56 #include "DynamicsCompressorNode.h"
57 #include "EventNames.h"
58 #include "FFTFrame.h"
59 #include "Frame.h"
60 #include "FrameLoader.h"
61 #include "GainNode.h"
62 #include "HRTFDatabaseLoader.h"
63 #include "HRTFPanner.h"
64 #include "IIRFilterNode.h"
65 #include "IIRFilterOptions.h"
66 #include "JSAudioBuffer.h"
67 #include "JSDOMPromiseDeferred.h"
68 #include "Logging.h"
69 #include "NetworkingContext.h"
70 #include "OscillatorNode.h"
71 #include "Page.h"
72 #include "PannerNode.h"
73 #include "PeriodicWave.h"
74 #include "PeriodicWaveOptions.h"
75 #include "ScriptController.h"
76 #include "ScriptProcessorNode.h"
77 #include "StereoPannerNode.h"
78 #include "StereoPannerOptions.h"
79 #include "WaveShaperNode.h"
80 #include <JavaScriptCore/ArrayBuffer.h>
81 #include <JavaScriptCore/ScriptCallStack.h>
82 #include <wtf/Atomics.h>
83 #include <wtf/IsoMallocInlines.h>
84 #include <wtf/MainThread.h>
85 #include <wtf/Ref.h>
86 #include <wtf/Scope.h>
87 #include <wtf/text/WTFString.h>
88
89 #if DEBUG_AUDIONODE_REFERENCES
90 #include <stdio.h>
91 #endif
92
93 #if USE(GSTREAMER)
94 #include "GStreamerCommon.h"
95 #endif
96
97 namespace WebCore {
98
99 WTF_MAKE_ISO_ALLOCATED_IMPL(BaseAudioContext);
100
101 bool BaseAudioContext::isSupportedSampleRate(float sampleRate)
102 {
103     return sampleRate >= 3000 && sampleRate <= 384000;
104 }
105
106 static uint64_t generateContextID()
107 {
108     ASSERT(isMainThread());
109     static uint64_t contextIDSeed = 0;
110     return ++contextIDSeed;
111 }
112
113 static HashSet<uint64_t>& liveAudioContexts()
114 {
115     ASSERT(isMainThread());
116     static NeverDestroyed<HashSet<uint64_t>> contexts;
117     return contexts;
118 }
119
120 BaseAudioContext::BaseAudioContext(Document& document)
121     : ActiveDOMObject(document)
122 #if !RELEASE_LOG_DISABLED
123     , m_logger(document.logger())
124     , m_logIdentifier(uniqueLogIdentifier())
125 #endif
126     , m_contextID(generateContextID())
127     , m_worklet(AudioWorklet::create(*this))
128     , m_listener(AudioListener::create(*this))
129 {
130     liveAudioContexts().add(m_contextID);
131
132     FFTFrame::initialize();
133 }
134
135 BaseAudioContext::~BaseAudioContext()
136 {
137     liveAudioContexts().remove(m_contextID);
138 #if DEBUG_AUDIONODE_REFERENCES
139     fprintf(stderr, "%p: BaseAudioContext::~AudioContext()\n", this);
140 #endif
141     ASSERT(m_nodesToDelete.isEmpty());
142     ASSERT(m_referencedSourceNodes.isEmpty());
143     ASSERT(m_automaticPullNodes.isEmpty());
144     if (m_automaticPullNodesNeedUpdating)
145         m_renderingAutomaticPullNodes.resize(m_automaticPullNodes.size());
146     ASSERT(m_renderingAutomaticPullNodes.isEmpty());
147     // FIXME: Can we assert that m_deferredBreakConnectionList is empty?
148 }
149
150 bool BaseAudioContext::isContextAlive(uint64_t contextID)
151 {
152     return liveAudioContexts().contains(contextID);
153 }
154
155 void BaseAudioContext::lazyInitialize()
156 {
157     if (isStopped() || isClosed())
158         return;
159
160     if (m_isInitialized)
161         return;
162
163     // Don't allow the context to initialize a second time after it's already been explicitly uninitialized.
164     ASSERT(!m_isAudioThreadFinished);
165     if (m_isAudioThreadFinished)
166         return;
167
168     destination().initialize();
169
170     m_isInitialized = true;
171 }
172
173 void BaseAudioContext::clear()
174 {
175     auto protectedThis = makeRef(*this);
176
177     // Audio thread is dead. Nobody will schedule node deletion action. Let's do it ourselves.
178     do {
179         deleteMarkedNodes();
180         m_nodesToDelete = std::exchange(m_nodesMarkedForDeletion, { });
181     } while (!m_nodesToDelete.isEmpty());
182
183     clearPendingActivity();
184 }
185
186 void BaseAudioContext::uninitialize()
187 {
188     ALWAYS_LOG(LOGIDENTIFIER);
189     
190     ASSERT(isMainThread());
191
192     if (!m_isInitialized)
193         return;
194
195     // This stops the audio thread and all audio rendering.
196     destination().uninitialize();
197
198     // Don't allow the context to initialize a second time after it's already been explicitly uninitialized.
199     m_isAudioThreadFinished = true;
200
201     {
202         AutoLocker locker(*this);
203         // This should have been called from handlePostRenderTasks() at the end of rendering.
204         // However, in case of lock contention, the tryLock() call could have failed in handlePostRenderTasks(),
205         // leaving nodes in m_referencedSourceNodes. Now that the audio thread is gone, make sure we deref those nodes
206         // before the BaseAudioContext gets destroyed.
207         derefFinishedSourceNodes();
208     }
209
210     // Get rid of the sources which may still be playing.
211     derefUnfinishedSourceNodes();
212
213     m_isInitialized = false;
214 }
215
216 void BaseAudioContext::addReaction(State state, DOMPromiseDeferred<void>&& promise)
217 {
218     size_t stateIndex = static_cast<size_t>(state);
219     if (stateIndex >= m_stateReactions.size())
220         m_stateReactions.grow(stateIndex + 1);
221
222     m_stateReactions[stateIndex].append(WTFMove(promise));
223 }
224
225 void BaseAudioContext::setState(State state)
226 {
227     if (m_state != state) {
228         m_state = state;
229         queueTaskToDispatchEvent(*this, TaskSource::MediaElement, Event::create(eventNames().statechangeEvent, Event::CanBubble::Yes, Event::IsCancelable::No));
230     }
231
232     size_t stateIndex = static_cast<size_t>(state);
233     if (stateIndex >= m_stateReactions.size())
234         return;
235
236     Vector<DOMPromiseDeferred<void>> reactions;
237     m_stateReactions[stateIndex].swap(reactions);
238
239     for (auto& promise : reactions)
240         promise.resolve();
241 }
242
243 void BaseAudioContext::stop()
244 {
245     ASSERT(isMainThread());
246     ALWAYS_LOG(LOGIDENTIFIER);
247     
248     // Usually ScriptExecutionContext calls stop twice.
249     if (m_isStopScheduled)
250         return;
251
252     auto protectedThis = makeRef(*this);
253
254     m_isStopScheduled = true;
255
256     ASSERT(document());
257     document()->updateIsPlayingMedia();
258
259     uninitialize();
260     clear();
261 }
262
263 Document* BaseAudioContext::document() const
264 {
265     return downcast<Document>(m_scriptExecutionContext);
266 }
267
268 bool BaseAudioContext::wouldTaintOrigin(const URL& url) const
269 {
270     if (url.protocolIsData())
271         return false;
272
273     if (auto* document = this->document())
274         return !document->securityOrigin().canRequest(url);
275
276     return false;
277 }
278
279 ExceptionOr<Ref<AudioBuffer>> BaseAudioContext::createBuffer(unsigned numberOfChannels, unsigned length, float sampleRate)
280 {
281     return AudioBuffer::create(AudioBufferOptions {numberOfChannels, length, sampleRate});
282 }
283
284 void BaseAudioContext::decodeAudioData(Ref<ArrayBuffer>&& audioData, RefPtr<AudioBufferCallback>&& successCallback, RefPtr<AudioBufferCallback>&& errorCallback, Optional<Ref<DeferredPromise>>&& promise)
285 {
286     if (promise && (!document() || !document()->isFullyActive())) {
287         promise.value()->reject(Exception { InvalidStateError, "Document is not fully active"_s });
288         return;
289     }
290
291     if (!m_audioDecoder)
292         m_audioDecoder = makeUnique<AsyncAudioDecoder>();
293
294     m_audioDecoder->decodeAsync(WTFMove(audioData), sampleRate(), [this, activity = makePendingActivity(*this), successCallback = WTFMove(successCallback), errorCallback = WTFMove(errorCallback), promise = WTFMove(promise)](ExceptionOr<Ref<AudioBuffer>>&& result) mutable {
295         queueTaskKeepingObjectAlive(*this, TaskSource::InternalAsyncTask, [successCallback = WTFMove(successCallback), errorCallback = WTFMove(errorCallback), promise = WTFMove(promise), result = WTFMove(result)]() mutable {
296             if (result.hasException()) {
297                 if (promise)
298                     promise.value()->reject(result.releaseException());
299                 if (errorCallback)
300                     errorCallback->handleEvent(nullptr);
301                 return;
302             }
303             auto audioBuffer = result.releaseReturnValue();
304             if (promise)
305                 promise.value()->resolve<IDLInterface<AudioBuffer>>(audioBuffer.get());
306             if (successCallback)
307                 successCallback->handleEvent(audioBuffer.ptr());
308         });
309     });
310 }
311
312 ExceptionOr<Ref<AudioBufferSourceNode>> BaseAudioContext::createBufferSource()
313 {
314     ALWAYS_LOG(LOGIDENTIFIER);
315
316     ASSERT(isMainThread());
317     return AudioBufferSourceNode::create(*this);
318 }
319
320 ExceptionOr<Ref<ScriptProcessorNode>> BaseAudioContext::createScriptProcessor(size_t bufferSize, size_t numberOfInputChannels, size_t numberOfOutputChannels)
321 {
322     ALWAYS_LOG(LOGIDENTIFIER);
323     
324     ASSERT(isMainThread());
325
326     // W3C Editor's Draft 06 June 2017
327     //  https://webaudio.github.io/web-audio-api/#widl-BaseAudioContext-createScriptProcessor-ScriptProcessorNode-unsigned-long-bufferSize-unsigned-long-numberOfInputChannels-unsigned-long-numberOfOutputChannels
328
329     // The bufferSize parameter determines the buffer size in units of sample-frames. If it's not passed in,
330     // or if the value is 0, then the implementation will choose the best buffer size for the given environment,
331     // which will be constant power of 2 throughout the lifetime of the node. ... If the value of this parameter
332     // is not one of the allowed power-of-2 values listed above, an IndexSizeError must be thrown.
333     switch (bufferSize) {
334     case 0:
335 #if USE(AUDIO_SESSION)
336         // Pick a value between 256 (2^8) and 16384 (2^14), based on the buffer size of the current AudioSession:
337         bufferSize = 1 << std::max<size_t>(8, std::min<size_t>(14, std::log2(AudioSession::sharedSession().bufferSize())));
338 #else
339         bufferSize = 2048;
340 #endif
341         break;
342     case 256:
343     case 512:
344     case 1024:
345     case 2048:
346     case 4096:
347     case 8192:
348     case 16384:
349         break;
350     default:
351         return Exception { IndexSizeError, "Unsupported buffer size for ScriptProcessorNode"_s };
352     }
353
354     // An IndexSizeError exception must be thrown if bufferSize or numberOfInputChannels or numberOfOutputChannels
355     // are outside the valid range. It is invalid for both numberOfInputChannels and numberOfOutputChannels to be zero.
356     // In this case an IndexSizeError must be thrown.
357
358     if (!numberOfInputChannels && !numberOfOutputChannels)
359         return Exception { NotSupportedError, "numberOfInputChannels and numberOfOutputChannels cannot both be 0"_s };
360
361     // This parameter [numberOfInputChannels] determines the number of channels for this node's input. Values of
362     // up to 32 must be supported. A NotSupportedError must be thrown if the number of channels is not supported.
363
364     if (numberOfInputChannels > maxNumberOfChannels)
365         return Exception { NotSupportedError, "numberOfInputChannels exceeds maximum number of channels"_s };
366
367     // This parameter [numberOfOutputChannels] determines the number of channels for this node's output. Values of
368     // up to 32 must be supported. A NotSupportedError must be thrown if the number of channels is not supported.
369
370     if (numberOfOutputChannels > maxNumberOfChannels)
371         return Exception { NotSupportedError, "numberOfOutputChannels exceeds maximum number of channels"_s };
372
373     return ScriptProcessorNode::create(*this, bufferSize, numberOfInputChannels, numberOfOutputChannels);
374 }
375
376 ExceptionOr<Ref<BiquadFilterNode>> BaseAudioContext::createBiquadFilter()
377 {
378     ALWAYS_LOG(LOGIDENTIFIER);
379     
380     ASSERT(isMainThread());
381     return BiquadFilterNode::create(*this);
382 }
383
384 ExceptionOr<Ref<WaveShaperNode>> BaseAudioContext::createWaveShaper()
385 {
386     ALWAYS_LOG(LOGIDENTIFIER);
387     
388     ASSERT(isMainThread());
389     return WaveShaperNode::create(*this);
390 }
391
392 ExceptionOr<Ref<PannerNode>> BaseAudioContext::createPanner()
393 {
394     ALWAYS_LOG(LOGIDENTIFIER);
395     
396     ASSERT(isMainThread());
397     return PannerNode::create(*this);
398 }
399
400 ExceptionOr<Ref<ConvolverNode>> BaseAudioContext::createConvolver()
401 {
402     ALWAYS_LOG(LOGIDENTIFIER);
403     
404     ASSERT(isMainThread());
405     return ConvolverNode::create(*this);
406 }
407
408 ExceptionOr<Ref<DynamicsCompressorNode>> BaseAudioContext::createDynamicsCompressor()
409 {
410     ALWAYS_LOG(LOGIDENTIFIER);
411     
412     ASSERT(isMainThread());
413     return DynamicsCompressorNode::create(*this);
414 }
415
416 ExceptionOr<Ref<AnalyserNode>> BaseAudioContext::createAnalyser()
417 {
418     ALWAYS_LOG(LOGIDENTIFIER);
419     
420     ASSERT(isMainThread());
421     return AnalyserNode::create(*this);
422 }
423
424 ExceptionOr<Ref<GainNode>> BaseAudioContext::createGain()
425 {
426     ALWAYS_LOG(LOGIDENTIFIER);
427     
428     ASSERT(isMainThread());
429     return GainNode::create(*this);
430 }
431
432 ExceptionOr<Ref<DelayNode>> BaseAudioContext::createDelay(double maxDelayTime)
433 {
434     ALWAYS_LOG(LOGIDENTIFIER);
435     
436     ASSERT(isMainThread());
437     DelayOptions options;
438     options.maxDelayTime = maxDelayTime;
439     return DelayNode::create(*this, options);
440 }
441
442 ExceptionOr<Ref<ChannelSplitterNode>> BaseAudioContext::createChannelSplitter(size_t numberOfOutputs)
443 {
444     ALWAYS_LOG(LOGIDENTIFIER);
445     
446     ASSERT(isMainThread());
447
448     ChannelSplitterOptions options;
449     options.numberOfOutputs = numberOfOutputs;
450     return ChannelSplitterNode::create(*this, options);
451 }
452
453 ExceptionOr<Ref<ChannelMergerNode>> BaseAudioContext::createChannelMerger(size_t numberOfInputs)
454 {
455     ALWAYS_LOG(LOGIDENTIFIER);
456     
457     ASSERT(isMainThread());
458
459     ChannelMergerOptions options;
460     options.numberOfInputs = numberOfInputs;
461     return ChannelMergerNode::create(*this, options);
462 }
463
464 ExceptionOr<Ref<OscillatorNode>> BaseAudioContext::createOscillator()
465 {
466     ALWAYS_LOG(LOGIDENTIFIER);
467     
468     ASSERT(isMainThread());
469     return OscillatorNode::create(*this);
470 }
471
472 ExceptionOr<Ref<PeriodicWave>> BaseAudioContext::createPeriodicWave(Vector<float>&& real, Vector<float>&& imaginary, const PeriodicWaveConstraints& constraints)
473 {
474     ALWAYS_LOG(LOGIDENTIFIER);
475     
476     ASSERT(isMainThread());
477     
478     PeriodicWaveOptions options;
479     options.real = WTFMove(real);
480     options.imag = WTFMove(imaginary);
481     options.disableNormalization = constraints.disableNormalization;
482     return PeriodicWave::create(*this, WTFMove(options));
483 }
484
485 ExceptionOr<Ref<ConstantSourceNode>> BaseAudioContext::createConstantSource()
486 {
487     ALWAYS_LOG(LOGIDENTIFIER);
488     
489     ASSERT(isMainThread());
490     return ConstantSourceNode::create(*this);
491 }
492
493 ExceptionOr<Ref<StereoPannerNode>> BaseAudioContext::createStereoPanner()
494 {
495     ALWAYS_LOG(LOGIDENTIFIER);
496     
497     ASSERT(isMainThread());
498     return StereoPannerNode::create(*this);
499 }
500
501 ExceptionOr<Ref<IIRFilterNode>> BaseAudioContext::createIIRFilter(ScriptExecutionContext& scriptExecutionContext, Vector<double>&& feedforward, Vector<double>&& feedback)
502 {
503     ALWAYS_LOG(LOGIDENTIFIER);
504
505     ASSERT(isMainThread());
506     IIRFilterOptions options;
507     options.feedforward = WTFMove(feedforward);
508     options.feedback = WTFMove(feedback);
509     return IIRFilterNode::create(scriptExecutionContext, *this, WTFMove(options));
510 }
511
512 void BaseAudioContext::derefFinishedSourceNodes()
513 {
514     ASSERT(isGraphOwner());
515     ASSERT(isAudioThread() || isAudioThreadFinished());
516
517     if (!m_hasFinishedAudioSourceNodes)
518         return;
519
520     m_referencedSourceNodes.removeAllMatching([](auto& node) { return node->isFinishedSourceNode(); });
521     m_hasFinishedAudioSourceNodes = false;
522 }
523
524 void BaseAudioContext::refSourceNode(AudioNode& node)
525 {
526     ASSERT(isMainThread());
527     AutoLocker locker(*this);
528
529     ASSERT(!m_referencedSourceNodes.contains(&node));
530     // Reference source node to keep it alive and playing even if its JS wrapper gets garbage collected.
531     m_referencedSourceNodes.append(&node);
532 }
533
534 void BaseAudioContext::derefSourceNode(AudioNode& node)
535 {
536     ASSERT(isGraphOwner());
537     
538     ASSERT(m_referencedSourceNodes.contains(&node));
539     m_referencedSourceNodes.removeFirst(&node);
540 }
541
542 void BaseAudioContext::derefUnfinishedSourceNodes()
543 {
544     ASSERT(isMainThread() && isAudioThreadFinished());
545     m_referencedSourceNodes.clear();
546 }
547
548 void BaseAudioContext::lock(bool& mustReleaseLock)
549 {
550     // Don't allow regular lock in real-time audio thread.
551     ASSERT(isMainThread());
552
553     lockInternal(mustReleaseLock);
554 }
555
556 void BaseAudioContext::lockInternal(bool& mustReleaseLock)
557 {
558     Thread& thisThread = Thread::current();
559
560     if (&thisThread == m_graphOwnerThread) {
561         // We already have the lock.
562         mustReleaseLock = false;
563     } else {
564         // Acquire the lock.
565         m_contextGraphLock.lock();
566         m_graphOwnerThread = &thisThread;
567         mustReleaseLock = true;
568     }
569 }
570
571 bool BaseAudioContext::tryLock(bool& mustReleaseLock)
572 {
573     // Try to catch cases of using try lock on main thread - it should use regular lock.
574     ASSERT(isAudioThread() || isAudioThreadFinished());
575     
576     if (!isAudioThread()) {
577         // In release build treat tryLock() as lock() (since above ASSERT(isAudioThread) never fires) - this is the best we can do.
578         lock(mustReleaseLock);
579         return true;
580     }
581     
582     bool hasLock;
583     
584     if (isGraphOwner()) {
585         // Thread already has the lock.
586         hasLock = true;
587         mustReleaseLock = false;
588     } else {
589         // Don't already have the lock - try to acquire it.
590         hasLock = m_contextGraphLock.tryLock();
591         
592         if (hasLock)
593             m_graphOwnerThread = &Thread::current();
594
595         mustReleaseLock = hasLock;
596     }
597     
598     return hasLock;
599 }
600
601 void BaseAudioContext::unlock()
602 {
603     ASSERT(m_graphOwnerThread == &Thread::current());
604
605     m_graphOwnerThread = nullptr;
606     m_contextGraphLock.unlock();
607 }
608
609 void BaseAudioContext::addDeferredDecrementConnectionCount(AudioNode* node)
610 {
611     ASSERT(isAudioThread());
612     m_deferredBreakConnectionList.append(node);
613 }
614
615 void BaseAudioContext::handlePreRenderTasks(const AudioIOPosition& outputPosition)
616 {
617     ASSERT(isAudioThread());
618
619     // At the beginning of every render quantum, try to update the internal rendering graph state (from main thread changes).
620     // It's OK if the tryLock() fails, we'll just take slightly longer to pick up the changes.
621     bool mustReleaseLock;
622     if (tryLock(mustReleaseLock)) {
623         // Fixup the state of any dirty AudioSummingJunctions and AudioNodeOutputs.
624         handleDirtyAudioSummingJunctions();
625         handleDirtyAudioNodeOutputs();
626
627         updateAutomaticPullNodes();
628         m_outputPosition = outputPosition;
629
630         if (mustReleaseLock)
631             unlock();
632     }
633 }
634
635 AudioIOPosition BaseAudioContext::outputPosition()
636 {
637     ASSERT(isMainThread());
638     AutoLocker locker(*this);
639     return m_outputPosition;
640 }
641
642 void BaseAudioContext::handlePostRenderTasks()
643 {
644     ASSERT(isAudioThread());
645
646     // Must use a tryLock() here too. Don't worry, the lock will very rarely be contended and this method is called frequently.
647     // The worst that can happen is that there will be some nodes which will take slightly longer than usual to be deleted or removed
648     // from the render graph (in which case they'll render silence).
649     bool mustReleaseLock;
650     if (!tryLock(mustReleaseLock))
651         return;
652
653     // Take care of finishing any derefs where the tryLock() failed previously.
654     handleDeferredDecrementConnectionCounts();
655
656     // Dynamically clean up nodes which are no longer needed.
657     derefFinishedSourceNodes();
658
659     // Don't delete in the real-time thread. Let the main thread do it.
660     // Ref-counted objects held by certain AudioNodes may not be thread-safe.
661     scheduleNodeDeletion();
662
663     // Fixup the state of any dirty AudioSummingJunctions and AudioNodeOutputs.
664     handleDirtyAudioSummingJunctions();
665     handleDirtyAudioNodeOutputs();
666
667     updateAutomaticPullNodes();
668
669     if (mustReleaseLock)
670         unlock();
671 }
672
673 void BaseAudioContext::handleDeferredDecrementConnectionCounts()
674 {
675     ASSERT(isAudioThread() && isGraphOwner());
676     for (auto& node : m_deferredBreakConnectionList)
677         node->decrementConnectionCountWithLock();
678     
679     m_deferredBreakConnectionList.clear();
680 }
681
682 void BaseAudioContext::markForDeletion(AudioNode& node)
683 {
684     ASSERT(isGraphOwner());
685     ASSERT_WITH_MESSAGE(node.nodeType() != AudioNode::NodeTypeDestination, "Destination node is owned by the BaseAudioContext");
686
687     if (isAudioThreadFinished())
688         m_nodesToDelete.append(&node);
689     else {
690         // Heap allocations are forbidden on the audio thread for performance reasons so we need to
691         // explicitly allow the following allocation(s).
692         DisableMallocRestrictionsForCurrentThreadScope disableMallocRestrictions;
693         m_nodesMarkedForDeletion.append(&node);
694     }
695
696     // This is probably the best time for us to remove the node from automatic pull list,
697     // since all connections are gone and we hold the graph lock. Then when handlePostRenderTasks()
698     // gets a chance to schedule the deletion work, updateAutomaticPullNodes() also gets a chance to
699     // modify m_renderingAutomaticPullNodes.
700     removeAutomaticPullNode(node);
701 }
702
703 void BaseAudioContext::scheduleNodeDeletion()
704 {
705     bool isGood = m_isInitialized && isGraphOwner();
706     ASSERT(isGood);
707     if (!isGood)
708         return;
709
710     // Make sure to call deleteMarkedNodes() on main thread.    
711     if (!m_nodesMarkedForDeletion.isEmpty() && !m_isDeletionScheduled) {
712         ASSERT(m_nodesToDelete.isEmpty());
713         m_nodesToDelete = std::exchange(m_nodesMarkedForDeletion, { });
714
715         m_isDeletionScheduled = true;
716
717         // Heap allocations are forbidden on the audio thread for performance reasons so we need to
718         // explicitly allow the following allocation(s).
719         DisableMallocRestrictionsForCurrentThreadScope disableMallocRestrictions;
720         callOnMainThread([protectedThis = makeRef(*this)]() mutable {
721             protectedThis->deleteMarkedNodes();
722         });
723     }
724 }
725
726 void BaseAudioContext::deleteMarkedNodes()
727 {
728     ASSERT(isMainThread());
729
730     // Protect this object from being deleted before we release the mutex locked by AutoLocker.
731     auto protectedThis = makeRef(*this);
732
733     AutoLocker locker(*this);
734
735     while (m_nodesToDelete.size()) {
736         AudioNode* node = m_nodesToDelete.takeLast();
737
738         // Before deleting the node, clear out any AudioNodeInputs from m_dirtySummingJunctions.
739         unsigned numberOfInputs = node->numberOfInputs();
740         for (unsigned i = 0; i < numberOfInputs; ++i)
741             m_dirtySummingJunctions.remove(node->input(i));
742
743         // Before deleting the node, clear out any AudioNodeOutputs from m_dirtyAudioNodeOutputs.
744         unsigned numberOfOutputs = node->numberOfOutputs();
745         for (unsigned i = 0; i < numberOfOutputs; ++i)
746             m_dirtyAudioNodeOutputs.remove(node->output(i));
747
748         ASSERT_WITH_MESSAGE(node->nodeType() != AudioNode::NodeTypeDestination, "Destination node is owned by the BaseAudioContext");
749
750         // Finally, delete it.
751         delete node;
752     }
753     m_isDeletionScheduled = false;
754 }
755
756 void BaseAudioContext::markSummingJunctionDirty(AudioSummingJunction* summingJunction)
757 {
758     ASSERT(isGraphOwner());
759     // Heap allocations are forbidden on the audio thread for performance reasons so we need to
760     // explicitly allow the following allocation(s).
761     DisableMallocRestrictionsForCurrentThreadScope disableMallocRestrictions;
762     m_dirtySummingJunctions.add(summingJunction);
763 }
764
765 void BaseAudioContext::removeMarkedSummingJunction(AudioSummingJunction* summingJunction)
766 {
767     ASSERT(isMainThread());
768     AutoLocker locker(*this);
769     m_dirtySummingJunctions.remove(summingJunction);
770 }
771
772 EventTargetInterface BaseAudioContext::eventTargetInterface() const
773 {
774     return BaseAudioContextEventTargetInterfaceType;
775 }
776
777 void BaseAudioContext::markAudioNodeOutputDirty(AudioNodeOutput* output)
778 {
779     ASSERT(isGraphOwner());
780     m_dirtyAudioNodeOutputs.add(output);
781 }
782
783 void BaseAudioContext::handleDirtyAudioSummingJunctions()
784 {
785     ASSERT(isGraphOwner());    
786
787     for (auto& junction : m_dirtySummingJunctions)
788         junction->updateRenderingState();
789
790     m_dirtySummingJunctions.clear();
791 }
792
793 void BaseAudioContext::handleDirtyAudioNodeOutputs()
794 {
795     ASSERT(isGraphOwner());    
796
797     for (auto& output : m_dirtyAudioNodeOutputs)
798         output->updateRenderingState();
799
800     m_dirtyAudioNodeOutputs.clear();
801 }
802
803 void BaseAudioContext::addAutomaticPullNode(AudioNode& node)
804 {
805     ASSERT(isGraphOwner());
806
807     // Heap allocations are forbidden on the audio thread for performance reasons so we need to
808     // explicitly allow the following allocation(s).
809     DisableMallocRestrictionsForCurrentThreadScope disableMallocRestrictions;
810     if (m_automaticPullNodes.add(&node).isNewEntry)
811         m_automaticPullNodesNeedUpdating = true;
812 }
813
814 void BaseAudioContext::removeAutomaticPullNode(AudioNode& node)
815 {
816     ASSERT(isGraphOwner());
817
818     if (m_automaticPullNodes.remove(&node))
819         m_automaticPullNodesNeedUpdating = true;
820 }
821
822 void BaseAudioContext::updateAutomaticPullNodes()
823 {
824     ASSERT(isGraphOwner());
825
826     if (!m_automaticPullNodesNeedUpdating)
827         return;
828
829     // Heap allocations are forbidden on the audio thread for performance reasons so we need to
830     // explicitly allow the following allocation(s).
831     DisableMallocRestrictionsForCurrentThreadScope disableMallocRestrictions;
832
833     // Copy from m_automaticPullNodes to m_renderingAutomaticPullNodes.
834     m_renderingAutomaticPullNodes.resize(m_automaticPullNodes.size());
835
836     unsigned i = 0;
837     for (auto& output : m_automaticPullNodes)
838         m_renderingAutomaticPullNodes[i++] = output;
839
840     m_automaticPullNodesNeedUpdating = false;
841 }
842
843 void BaseAudioContext::processAutomaticPullNodes(size_t framesToProcess)
844 {
845     ASSERT(isAudioThread());
846
847     for (auto& node : m_renderingAutomaticPullNodes)
848         node->processIfNecessary(framesToProcess);
849 }
850
851 ScriptExecutionContext* BaseAudioContext::scriptExecutionContext() const
852 {
853     return ActiveDOMObject::scriptExecutionContext();
854 }
855
856 void BaseAudioContext::incrementActiveSourceCount()
857 {
858     ++m_activeSourceCount;
859 }
860
861 void BaseAudioContext::decrementActiveSourceCount()
862 {
863     --m_activeSourceCount;
864 }
865
866 void BaseAudioContext::postTask(Function<void()>&& task)
867 {
868     ASSERT(isMainThread());
869     if (!m_isStopScheduled)
870         queueTaskKeepingObjectAlive(*this, TaskSource::MediaElement, WTFMove(task));
871 }
872
873 const SecurityOrigin* BaseAudioContext::origin() const
874 {
875     return m_scriptExecutionContext ? m_scriptExecutionContext->securityOrigin() : nullptr;
876 }
877
878 void BaseAudioContext::addConsoleMessage(MessageSource source, MessageLevel level, const String& message)
879 {
880     if (m_scriptExecutionContext)
881         m_scriptExecutionContext->addConsoleMessage(source, level, message);
882 }
883
884 void BaseAudioContext::clearPendingActivity()
885 {
886     m_pendingActivity = nullptr;
887 }
888
889 void BaseAudioContext::setPendingActivity()
890 {
891     if (!m_pendingActivity)
892         m_pendingActivity = makePendingActivity(*this);
893 }
894
895 PeriodicWave& BaseAudioContext::periodicWave(OscillatorType type)
896 {
897     switch (type) {
898     case OscillatorType::Square:
899         if (!m_cachedPeriodicWaveSquare)
900             m_cachedPeriodicWaveSquare = PeriodicWave::createSquare(sampleRate());
901         return *m_cachedPeriodicWaveSquare;
902     case OscillatorType::Sawtooth:
903         if (!m_cachedPeriodicWaveSawtooth)
904             m_cachedPeriodicWaveSawtooth = PeriodicWave::createSawtooth(sampleRate());
905         return *m_cachedPeriodicWaveSawtooth;
906     case OscillatorType::Triangle:
907         if (!m_cachedPeriodicWaveTriangle)
908             m_cachedPeriodicWaveTriangle = PeriodicWave::createTriangle(sampleRate());
909         return *m_cachedPeriodicWaveTriangle;
910     case OscillatorType::Custom:
911         RELEASE_ASSERT_NOT_REACHED();
912     case OscillatorType::Sine:
913         if (!m_cachedPeriodicWaveSine)
914             m_cachedPeriodicWaveSine = PeriodicWave::createSine(sampleRate());
915         return *m_cachedPeriodicWaveSine;
916     }
917     RELEASE_ASSERT_NOT_REACHED();
918 }
919
920 void BaseAudioContext::addAudioParamDescriptors(const String& processorName, Vector<AudioParamDescriptor>&& descriptors)
921 {
922     ASSERT(!m_parameterDescriptorMap.contains(processorName));
923     bool wasEmpty = m_parameterDescriptorMap.isEmpty();
924     m_parameterDescriptorMap.add(processorName, WTFMove(descriptors));
925     if (wasEmpty)
926         workletIsReady();
927 }
928
929 void BaseAudioContext::sourceNodeWillBeginPlayback(AudioNode& node)
930 {
931     refSourceNode(node);
932 }
933
934 void BaseAudioContext::sourceNodeDidFinishPlayback(AudioNode& node)
935 {
936     ASSERT(isAudioThread());
937
938     node.setIsFinishedSourceNode();
939     m_hasFinishedAudioSourceNodes = true;
940 }
941
942 void BaseAudioContext::workletIsReady()
943 {
944     ASSERT(isMainThread());
945
946     // If we're already rendering when the worklet becomes ready, we need to restart
947     // rendering in order to switch to the audio worklet thread.
948     destination().restartRendering();
949 }
950
951 #if !RELEASE_LOG_DISABLED
952 WTFLogChannel& BaseAudioContext::logChannel() const
953 {
954     return LogMedia;
955 }
956 #endif
957
958 } // namespace WebCore
959
960 #endif // ENABLE(WEB_AUDIO)