Title: [274767] trunk/Source/WebCore
Revision
274767
Author
[email protected]
Date
2021-03-22 11:51:43 -0700 (Mon, 22 Mar 2021)

Log Message

Avoid heap allocation under AudioNodeInput::disable() / AudioNodeInput::enable()
https://bugs.webkit.org/show_bug.cgi?id=223529

Reviewed by Eric Carlson.

Avoid heap allocation under AudioNodeInput::disable() / AudioNodeInput::enable() since those can
get called on the audio thread.

AudioNodeInput used to have a m_disabledOutputs container to keep disabled outputs separated
from enabled ones (in m_outputs). Instead, we now store all outputs in m_outputs with a 'isEnabled'
flag. As a result, we no longer need to make any heap allocations when enabling/disabling an
output, we merely need to flip a flag in m_outputs.

For convenience, since clients of rendering outputs only care about enabled outputs, I introduced
a new RenderingOutputCollection container with iterators. This way clients do not need to worry
about disabled outputs.

* Modules/webaudio/AudioNodeInput.cpp:
(WebCore::AudioNodeInput::connect):
(WebCore::AudioNodeInput::disconnect):
(WebCore::AudioNodeInput::didDisableOutput):
(WebCore::AudioNodeInput::didEnableOutput):
(WebCore::AudioNodeInput::bus):
(WebCore::AudioNodeInput::sumAllConnections):
(WebCore::AudioNodeInput::pull):
* Modules/webaudio/AudioNodeInput.h:
* Modules/webaudio/AudioNodeOutput.cpp:
(WebCore::AudioNodeOutput::disable):
(WebCore::AudioNodeOutput::enable):
* Modules/webaudio/AudioParam.cpp:
(WebCore::AudioParam::calculateFinalValues):
* Modules/webaudio/AudioSummingJunction.cpp:
(WebCore::AudioSummingJunction::numberOfConnections const):
(WebCore::AudioSummingJunction::addOutput):
(WebCore::AudioSummingJunction::removeOutput):
(WebCore::AudioSummingJunction::updateRenderingState):
(WebCore::AudioSummingJunction::maximumNumberOfChannels const):
(WebCore::AudioSummingJunction::didDisableOutput):
(WebCore::AudioSummingJunction::didEnableOutput):
(WebCore::AudioSummingJunction::RenderingOutputCollection::RenderingOutput::RenderingOutput):
(WebCore::WebCore::AudioSummingJunction::RenderingOutputCollection::remove):
(WebCore::WebCore::AudioSummingJunction::RenderingOutputCollection::setEnabled):
(WebCore::WebCore::AudioSummingJunction::RenderingOutputCollection::RenderingOutputCollection):
* Modules/webaudio/AudioSummingJunction.h:
(WebCore::AudioSummingJunction::RenderingOutputCollection::isEmpty const):
(WebCore::AudioSummingJunction::RenderingOutputCollection::size const):
(WebCore::AudioSummingJunction::RenderingOutputCollection::clear):
(WebCore::AudioSummingJunction::RenderingOutputCollection::append):
(WebCore::AudioSummingJunction::RenderingOutputCollection::ConstIterator::ConstIterator):
(WebCore::AudioSummingJunction::RenderingOutputCollection::ConstIterator::operator* const):
(WebCore::AudioSummingJunction::RenderingOutputCollection::ConstIterator::operator!= const):
(WebCore::AudioSummingJunction::RenderingOutputCollection::ConstIterator::operator++):
(WebCore::AudioSummingJunction::RenderingOutputCollection::begin const):
(WebCore::AudioSummingJunction::RenderingOutputCollection::end const):
(WebCore::AudioSummingJunction::renderingOutputs const):
(WebCore::AudioSummingJunction::isConnected const):
* Modules/webaudio/WebKitAudioPannerNode.cpp:
(WebCore::WebKitAudioPannerNode::notifyAudioSourcesConnectedToNode):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (274766 => 274767)


--- trunk/Source/WebCore/ChangeLog	2021-03-22 18:47:35 UTC (rev 274766)
+++ trunk/Source/WebCore/ChangeLog	2021-03-22 18:51:43 UTC (rev 274767)
@@ -1,3 +1,64 @@
+2021-03-22  Chris Dumez  <[email protected]>
+
+        Avoid heap allocation under AudioNodeInput::disable() / AudioNodeInput::enable()
+        https://bugs.webkit.org/show_bug.cgi?id=223529
+
+        Reviewed by Eric Carlson.
+
+        Avoid heap allocation under AudioNodeInput::disable() / AudioNodeInput::enable() since those can
+        get called on the audio thread.
+
+        AudioNodeInput used to have a m_disabledOutputs container to keep disabled outputs separated
+        from enabled ones (in m_outputs). Instead, we now store all outputs in m_outputs with a 'isEnabled'
+        flag. As a result, we no longer need to make any heap allocations when enabling/disabling an
+        output, we merely need to flip a flag in m_outputs.
+
+        For convenience, since clients of rendering outputs only care about enabled outputs, I introduced
+        a new RenderingOutputCollection container with iterators. This way clients do not need to worry
+        about disabled outputs.
+
+        * Modules/webaudio/AudioNodeInput.cpp:
+        (WebCore::AudioNodeInput::connect):
+        (WebCore::AudioNodeInput::disconnect):
+        (WebCore::AudioNodeInput::didDisableOutput):
+        (WebCore::AudioNodeInput::didEnableOutput):
+        (WebCore::AudioNodeInput::bus):
+        (WebCore::AudioNodeInput::sumAllConnections):
+        (WebCore::AudioNodeInput::pull):
+        * Modules/webaudio/AudioNodeInput.h:
+        * Modules/webaudio/AudioNodeOutput.cpp:
+        (WebCore::AudioNodeOutput::disable):
+        (WebCore::AudioNodeOutput::enable):
+        * Modules/webaudio/AudioParam.cpp:
+        (WebCore::AudioParam::calculateFinalValues):
+        * Modules/webaudio/AudioSummingJunction.cpp:
+        (WebCore::AudioSummingJunction::numberOfConnections const):
+        (WebCore::AudioSummingJunction::addOutput):
+        (WebCore::AudioSummingJunction::removeOutput):
+        (WebCore::AudioSummingJunction::updateRenderingState):
+        (WebCore::AudioSummingJunction::maximumNumberOfChannels const):
+        (WebCore::AudioSummingJunction::didDisableOutput):
+        (WebCore::AudioSummingJunction::didEnableOutput):
+        (WebCore::AudioSummingJunction::RenderingOutputCollection::RenderingOutput::RenderingOutput):
+        (WebCore::WebCore::AudioSummingJunction::RenderingOutputCollection::remove):
+        (WebCore::WebCore::AudioSummingJunction::RenderingOutputCollection::setEnabled):
+        (WebCore::WebCore::AudioSummingJunction::RenderingOutputCollection::RenderingOutputCollection):
+        * Modules/webaudio/AudioSummingJunction.h:
+        (WebCore::AudioSummingJunction::RenderingOutputCollection::isEmpty const):
+        (WebCore::AudioSummingJunction::RenderingOutputCollection::size const):
+        (WebCore::AudioSummingJunction::RenderingOutputCollection::clear):
+        (WebCore::AudioSummingJunction::RenderingOutputCollection::append):
+        (WebCore::AudioSummingJunction::RenderingOutputCollection::ConstIterator::ConstIterator):
+        (WebCore::AudioSummingJunction::RenderingOutputCollection::ConstIterator::operator* const):
+        (WebCore::AudioSummingJunction::RenderingOutputCollection::ConstIterator::operator!= const):
+        (WebCore::AudioSummingJunction::RenderingOutputCollection::ConstIterator::operator++):
+        (WebCore::AudioSummingJunction::RenderingOutputCollection::begin const):
+        (WebCore::AudioSummingJunction::RenderingOutputCollection::end const):
+        (WebCore::AudioSummingJunction::renderingOutputs const):
+        (WebCore::AudioSummingJunction::isConnected const):
+        * Modules/webaudio/WebKitAudioPannerNode.cpp:
+        (WebCore::WebKitAudioPannerNode::notifyAudioSourcesConnectedToNode):
+
 2021-03-22  Youenn Fablet  <[email protected]>
 
         Implement RTCDataChannel transfer out of process

Modified: trunk/Source/WebCore/Modules/webaudio/AudioNodeInput.cpp (274766 => 274767)


--- trunk/Source/WebCore/Modules/webaudio/AudioNodeInput.cpp	2021-03-22 18:47:35 UTC (rev 274766)
+++ trunk/Source/WebCore/Modules/webaudio/AudioNodeInput.cpp	2021-03-22 18:51:43 UTC (rev 274767)
@@ -53,13 +53,7 @@
     if (!output || !node())
         return;
 
-    auto addPotentiallyDisabledOutput = [this](AudioNodeOutput& output) {
-        if (output.isEnabled())
-            return addOutput(output);
-        return m_disabledOutputs.add(&output).isNewEntry;
-    };
-
-    if (addPotentiallyDisabledOutput(*output))
+    if (addOutput(*output))
         output->addInput(this);
 }
 
@@ -76,48 +70,23 @@
         output->removeInput(this); // Note: it's important to return immediately after this since the node may be deleted.
         return;
     }
-    
-    // Otherwise, try to disconnect from disabled connections.
-    if (m_disabledOutputs.remove(output)) {
-        output->removeInput(this); // Note: it's important to return immediately after this since the node may be deleted.
-        return;
-    }
 
     ASSERT_NOT_REACHED();
 }
 
-void AudioNodeInput::disable(AudioNodeOutput* output)
+void AudioNodeInput::outputEnabledStateChanged(AudioNodeOutput& output)
 {
     ASSERT(context().isGraphOwner());
+    AudioSummingJunction::outputEnabledStateChanged(output);
 
-    ASSERT(output && node());
-    if (!output || !node())
-        return;
-
-    m_disabledOutputs.add(output);
-    bool wasRemoved = removeOutput(*output);
-    ASSERT_UNUSED(wasRemoved, wasRemoved);
-
     // Propagate disabled state to outputs.
-    node()->disableOutputsIfNecessary();
-}
-
-void AudioNodeInput::enable(AudioNodeOutput* output)
-{
-    ASSERT(context().isGraphOwner());
-
-    ASSERT(output && node());
-    if (!output || !node())
+    ASSERT(node());
+    if (!node())
         return;
-
-    ASSERT(m_disabledOutputs.contains(output));
-
-    // Move output from disabled list to active list.
-    addOutput(*output);
-    m_disabledOutputs.remove(output);
-
-    // Propagate enabled state to outputs.
-    node()->enableOutputsIfNecessary();
+    if (output.isEnabled())
+        node()->enableOutputsIfNecessary();
+    else
+        node()->disableOutputsIfNecessary();
 }
 
 void AudioNodeInput::didUpdate()
@@ -158,7 +127,7 @@
 
     // Handle single connection specially to allow for in-place processing.
     if (numberOfRenderingConnections() == 1 && node()->channelCountMode() == ChannelCountMode::Max)
-        return renderingOutput(0)->bus();
+        return (*renderingOutputs().begin())->bus();
 
     // Multiple connections case or complex ChannelCountMode (or no connections).
     return internalSummingBus();
@@ -186,7 +155,7 @@
 
     auto interpretation = node()->channelInterpretation();
 
-    for (auto& output : m_renderingOutputs) {
+    for (auto* output : renderingOutputs()) {
         ASSERT(output);
 
         // Render audio from this output.
@@ -201,16 +170,17 @@
 {
     ASSERT(context().isAudioThread());
 
+    auto numberOfRenderingConnections = this->numberOfRenderingConnections();
     // Handle single connection case.
-    if (numberOfRenderingConnections() == 1 && node()->channelCountMode() == ChannelCountMode::Max) {
+    if (numberOfRenderingConnections == 1 && node()->channelCountMode() == ChannelCountMode::Max) {
         // The output will optimize processing using inPlaceBus if it's able.
-        AudioNodeOutput* output = this->renderingOutput(0);
+        AudioNodeOutput* output = *renderingOutputs().begin();
         return output->pull(inPlaceBus, framesToProcess);
     }
 
     AudioBus* internalSummingBus = this->internalSummingBus();
 
-    if (!numberOfRenderingConnections()) {
+    if (!numberOfRenderingConnections) {
         // At least, generate silence if we're not connected to anything.
         // FIXME: if we wanted to get fancy, we could propagate a 'silent hint' here to optimize the downstream graph processing.
         internalSummingBus->zero();

Modified: trunk/Source/WebCore/Modules/webaudio/AudioNodeInput.h (274766 => 274767)


--- trunk/Source/WebCore/Modules/webaudio/AudioNodeInput.h	2021-03-22 18:47:35 UTC (rev 274766)
+++ trunk/Source/WebCore/Modules/webaudio/AudioNodeInput.h	2021-03-22 18:51:43 UTC (rev 274767)
@@ -55,11 +55,8 @@
     void connect(AudioNodeOutput*);
     void disconnect(AudioNodeOutput*);
 
-    // disable() will take the output out of the active connections list and set aside in a disabled list.
-    // enable() will put the output back into the active connections list.
     // Must be called with the context's graph lock.
-    void enable(AudioNodeOutput*);
-    void disable(AudioNodeOutput*);
+    void outputEnabledStateChanged(AudioNodeOutput&) final;
 
     // pull() processes all of the AudioNodes connected to us.
     // In the case of multiple connections it sums the result into an internal summing bus.
@@ -82,11 +79,6 @@
 private:
     AudioNode* m_node;
 
-    // m_disabledOutputs contains the AudioNodeOutputs which are disabled (will not be processed) by the audio graph rendering.
-    // But, from _javascript_'s perspective, these outputs are still connected to us.
-    // Generally, these represent disabled connections from "notes" which have finished playing but are not yet garbage collected.
-    HashSet<AudioNodeOutput*> m_disabledOutputs;
-
     // Called from context's audio thread.
     AudioBus* internalSummingBus();
     void sumAllConnections(AudioBus* summingBus, size_t framesToProcess);

Modified: trunk/Source/WebCore/Modules/webaudio/AudioNodeOutput.cpp (274766 => 274767)


--- trunk/Source/WebCore/Modules/webaudio/AudioNodeOutput.cpp	2021-03-22 18:47:35 UTC (rev 274766)
+++ trunk/Source/WebCore/Modules/webaudio/AudioNodeOutput.cpp	2021-03-22 18:51:43 UTC (rev 274767)
@@ -225,11 +225,12 @@
 {
     ASSERT(context().isGraphOwner());
 
-    if (m_isEnabled) {
-        for (auto& input : m_inputs.keys())
-            input->disable(this);
-        m_isEnabled = false;
-    }
+    if (!m_isEnabled)
+        return;
+
+    m_isEnabled = false;
+    for (auto& input : m_inputs.keys())
+        input->outputEnabledStateChanged(*this);
 }
 
 void AudioNodeOutput::enable()
@@ -236,11 +237,12 @@
 {
     ASSERT(context().isGraphOwner());
 
-    if (!m_isEnabled) {
-        for (auto& input : m_inputs.keys())
-            input->enable(this);
-        m_isEnabled = true;
-    }
+    if (m_isEnabled)
+        return;
+
+    m_isEnabled = true;
+    for (auto& input : m_inputs.keys())
+        input->outputEnabledStateChanged(*this);
 }
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/Modules/webaudio/AudioParam.cpp (274766 => 274767)


--- trunk/Source/WebCore/Modules/webaudio/AudioParam.cpp	2021-03-22 18:47:35 UTC (rev 274766)
+++ trunk/Source/WebCore/Modules/webaudio/AudioParam.cpp	2021-03-22 18:51:43 UTC (rev 274767)
@@ -281,7 +281,7 @@
     ASSERT(numberOfValues <= AudioUtilities::renderQuantumSize);
     m_summingBus->setChannelMemory(0, values, sampleAccurate ? numberOfValues : 1);
 
-    for (auto& output : m_renderingOutputs) {
+    for (auto* output : renderingOutputs()) {
         ASSERT(output);
 
         // Render audio from this output.

Modified: trunk/Source/WebCore/Modules/webaudio/AudioSummingJunction.cpp (274766 => 274767)


--- trunk/Source/WebCore/Modules/webaudio/AudioSummingJunction.cpp	2021-03-22 18:47:35 UTC (rev 274766)
+++ trunk/Source/WebCore/Modules/webaudio/AudioSummingJunction.cpp	2021-03-22 18:51:43 UTC (rev 274767)
@@ -60,10 +60,13 @@
     if (!m_outputs.add(&output).isNewEntry)
         return false;
 
-    if (m_pendingRenderingOutputs.isEmpty())
-        m_pendingRenderingOutputs = copyToVector(m_outputs);
+    if (!output.isEnabled())
+        return true;
+
+    if (!m_pendingRenderingOutputs)
+        m_pendingRenderingOutputs.emplace(m_outputs);
     else
-        m_pendingRenderingOutputs.append(&output);
+        m_pendingRenderingOutputs->append(output);
 
     markRenderingStateAsDirty();
     return true;
@@ -75,11 +78,16 @@
     if (!m_outputs.remove(&output))
         return false;
 
-    if (m_pendingRenderingOutputs.isEmpty())
-        m_pendingRenderingOutputs = copyToVector(m_outputs);
-    else
-        m_pendingRenderingOutputs.removeFirst(&output);
+    if (!output.isEnabled())
+        return true;
 
+    if (!m_pendingRenderingOutputs)
+        m_pendingRenderingOutputs.emplace(m_outputs);
+    else {
+        bool wasRemoved = m_pendingRenderingOutputs->remove(output);
+        ASSERT_UNUSED(wasRemoved, wasRemoved);
+    }
+
     markRenderingStateAsDirty();
     return true;
 }
@@ -90,9 +98,13 @@
 
     if (m_renderingStateNeedUpdating && canUpdateState()) {
         // Copy from m_outputs to m_renderingOutputs.
-        m_renderingOutputs = std::exchange(m_pendingRenderingOutputs, { });
-        for (auto& output : m_renderingOutputs)
-            output->updateRenderingState();
+        if (!m_pendingRenderingOutputs)
+            m_renderingOutputs = { };
+        else {
+            m_renderingOutputs = *std::exchange(m_pendingRenderingOutputs, WTF::nullopt);
+            for (auto* output : m_renderingOutputs)
+                output->updateRenderingState();
+        }
 
         didUpdate();
 
@@ -104,6 +116,9 @@
 {
     unsigned maxChannels = 0;
     for (auto* output : m_outputs) {
+        if (!output->isEnabled())
+            continue;
+
         // Use output()->numberOfChannels() instead of output->bus()->numberOfChannels(),
         // because the calling of AudioNodeOutput::bus() is not safe here.
         maxChannels = std::max(maxChannels, output->numberOfChannels());
@@ -111,6 +126,30 @@
     return maxChannels;
 }
 
+void AudioSummingJunction::outputEnabledStateChanged(AudioNodeOutput& output)
+{
+    ASSERT(context().isGraphOwner());
+    if (!m_pendingRenderingOutputs)
+        m_pendingRenderingOutputs.emplace(m_outputs);
+    else
+        m_pendingRenderingOutputs->updatedEnabledState(output);
+    markRenderingStateAsDirty();
+}
+
+inline AudioSummingJunction::RenderingOutputCollection::RenderingOutput::RenderingOutput(AudioNodeOutput* output)
+    : output(output)
+    , isEnabled(output->isEnabled())
+{ }
+
+void WebCore::AudioSummingJunction::RenderingOutputCollection::updatedEnabledState(AudioNodeOutput& output)
+{
+    auto index = m_outputs.find(&output);
+    ASSERT(index != notFound);
+    if (index == notFound)
+        return;
+    m_outputs[index].isEnabled = output.isEnabled();
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(WEB_AUDIO)

Modified: trunk/Source/WebCore/Modules/webaudio/AudioSummingJunction.h (274766 => 274767)


--- trunk/Source/WebCore/Modules/webaudio/AudioSummingJunction.h	2021-03-22 18:47:35 UTC (rev 274766)
+++ trunk/Source/WebCore/Modules/webaudio/AudioSummingJunction.h	2021-03-22 18:51:43 UTC (rev 274767)
@@ -25,6 +25,7 @@
 #pragma once
 
 #include "AudioBus.h"
+#include <iterator>
 #include <wtf/HashSet.h>
 #include <wtf/Vector.h>
 
@@ -48,11 +49,76 @@
     // This must be called when we own the context's graph lock in the audio thread at the very start or end of the render quantum.
     void updateRenderingState();
 
+    class RenderingOutputCollection {
+    public:
+        RenderingOutputCollection() = default;
+        RenderingOutputCollection(const HashSet<AudioNodeOutput*>& outputs)
+            : m_outputs(copyToVectorOf<RenderingOutput>(outputs))
+        {
+        }
+
+        bool isEmpty() const { return begin() == end(); }
+        size_t size() const { return std::distance(begin(), end()); }
+
+        void append(AudioNodeOutput& output) { m_outputs.append(&output); }
+        bool remove(AudioNodeOutput& output) { return m_outputs.removeFirst(&output); }
+        void updatedEnabledState(AudioNodeOutput&);
+
+        struct RenderingOutput {
+            RenderingOutput(AudioNodeOutput*);
+            bool operator==(const AudioNodeOutput* other) const { return output == other; }
+            AudioNodeOutput* output;
+            bool isEnabled;
+        };
+
+        class ConstIterator {
+        public:
+            using difference_type = size_t;
+            using value_type = AudioNodeOutput*;
+            using pointer = AudioNodeOutput**;
+            using reference = AudioNodeOutput*&;
+            using iterator_category = std::forward_iterator_tag;
+
+            ConstIterator(const Vector<RenderingOutput>& outputs, Vector<RenderingOutput>::const_iterator position)
+                : m_position(position)
+                , m_end(outputs.end())
+            {
+                skipDisabledOutputs();
+            }
+
+            AudioNodeOutput* operator*() const { return m_position->output; }
+            constexpr bool operator==(const ConstIterator& other) const { return m_position == other.m_position; }
+            constexpr bool operator!=(const ConstIterator& other) const { return !(*this == other); }
+            ConstIterator& operator++()
+            {
+                ASSERT(m_position != m_end);
+                ++m_position;
+                skipDisabledOutputs();
+                return *this;
+            }
+
+        private:
+            void skipDisabledOutputs()
+            {
+                while (m_position != m_end && !m_position->isEnabled)
+                    ++m_position;
+            }
+
+            Vector<RenderingOutput>::const_iterator m_position;
+            Vector<RenderingOutput>::const_iterator m_end;
+        };
+
+        ConstIterator begin() const { return ConstIterator { m_outputs, m_outputs.begin() }; }
+        ConstIterator end() const { return ConstIterator { m_outputs, m_outputs.end() }; }
+
+    private:
+        Vector<RenderingOutput> m_outputs;
+    };
+
     // Rendering code accesses its version of the current connections here.
+    const RenderingOutputCollection& renderingOutputs() const { return m_renderingOutputs; }
     unsigned numberOfRenderingConnections() const { return m_renderingOutputs.size(); }
-    AudioNodeOutput* renderingOutput(unsigned i) { return m_renderingOutputs[i]; }
-    const AudioNodeOutput* renderingOutput(unsigned i) const { return m_renderingOutputs[i]; }
-    bool isConnected() const { return numberOfRenderingConnections() > 0; }
+    bool isConnected() const { return !m_renderingOutputs.isEmpty(); }
 
     virtual bool canUpdateState() = 0;
     virtual void didUpdate() = 0;
@@ -62,29 +128,27 @@
 
     void markRenderingStateAsDirty();
 
+    virtual void outputEnabledStateChanged(AudioNodeOutput&);
+
 protected:
+    unsigned maximumNumberOfChannels() const;
+
+private:
     Ref<BaseAudioContext> m_context;
 
-    // numberOfConnections() should never be called from the audio rendering thread.
-    // Instead numberOfRenderingConnections() and renderingOutput() should be used.
-    unsigned numberOfConnections() const { return m_outputs.size(); }
-
-    unsigned maximumNumberOfChannels() const;
-
     // m_renderingOutputs is a copy of m_outputs which will never be modified during the graph rendering on the audio thread.
     // This is the list which is used by the rendering code.
     // Whenever m_outputs is modified, the context is told so it can later update m_renderingOutputs from m_outputs at a safe time.
     // Most of the time, m_renderingOutputs is identical to m_outputs.
-    Vector<AudioNodeOutput*> m_renderingOutputs;
+    RenderingOutputCollection m_renderingOutputs;
 
     // m_renderingStateNeedUpdating keeps track if m_outputs is modified.
     bool m_renderingStateNeedUpdating { false };
 
-private:
     // m_outputs contains the AudioNodeOutputs representing current connections which are not disabled.
     // The rendering code should never use this directly, but instead uses m_renderingOutputs.
     HashSet<AudioNodeOutput*> m_outputs;
-    Vector<AudioNodeOutput*> m_pendingRenderingOutputs;
+    Optional<RenderingOutputCollection> m_pendingRenderingOutputs;
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/Modules/webaudio/WebKitAudioPannerNode.cpp (274766 => 274767)


--- trunk/Source/WebCore/Modules/webaudio/WebKitAudioPannerNode.cpp	2021-03-22 18:47:35 UTC (rev 274766)
+++ trunk/Source/WebCore/Modules/webaudio/WebKitAudioPannerNode.cpp	2021-03-22 18:51:43 UTC (rev 274767)
@@ -319,8 +319,7 @@
             AudioNodeInput* input = node->input(i);
 
             // For each input, go through all of its connections, looking for AudioBufferSourceNodes.
-            for (unsigned j = 0; j < input->numberOfRenderingConnections(); ++j) {
-                AudioNodeOutput* connectedOutput = input->renderingOutput(j);
+            for (auto* connectedOutput : input->renderingOutputs()) {
                 AudioNode* connectedNode = connectedOutput->node();
                 if (visitedNodes.contains(connectedNode))
                     continue;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to