author | Paul Adenot <paul@paul.cx> |
Fri, 09 Sep 2016 13:41:01 +0200 | |
changeset 318833 | 4c6215e05eccb53a3500c1d63b038c03b606785f |
parent 318832 | 37434b4379d9b9891cbbb6157a709e45b64f2a41 |
child 318834 | 0be26309f50b477ec9f0ef800c5f2475e097125f |
push id | 30854 |
push user | ryanvm@gmail.com |
push date | Fri, 21 Oct 2016 21:08:02 +0000 |
treeherder | mozilla-central@806054dd12bd [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | karlt |
bugs | 1291702 |
milestone | 52.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
dom/media/webaudio/AudioNode.cpp | file | annotate | diff | comparison | revisions | |
dom/media/webaudio/AudioNode.h | file | annotate | diff | comparison | revisions |
--- a/dom/media/webaudio/AudioNode.cpp +++ b/dom/media/webaudio/AudioNode.cpp @@ -287,22 +287,22 @@ AudioNode::SendChannelMixingParametersTo { if (mStream) { mStream->SetChannelMixingParameters(mChannelCount, mChannelCountMode, mChannelInterpretation); } } bool -AudioNode::DisconnectFromOutputIfConnected(AudioNode& aDestination, uint32_t aOutputIndex, uint32_t aInputIndex) +AudioNode::DisconnectFromOutputIfConnected(AudioNode& aDestination, uint32_t aOutputNodeIndex, uint32_t aInputIndex) { WEB_AUDIO_API_LOG("%f: %s %u Disconnect()", Context()->CurrentTime(), NodeType(), Id()); - MOZ_ASSERT(aOutputIndex < mOutputNodes.Length()); + MOZ_ASSERT(aOutputNodeIndex < mOutputNodes.Length()); MOZ_ASSERT(aInputIndex < aDestination.InputNodes().Length()); // An upstream node may be starting to play on the graph thread, and the // engine for a downstream node may be sending a PlayingRefChangeHandler // ADDREF message to this (main) thread. Wait for a round trip before // releasing nodes, to give engines receiving sound now time to keep their // nodes alive. class RunnableRelease final : public Runnable @@ -327,99 +327,104 @@ AudioNode::DisconnectFromOutputIfConnect // Destroying the InputNode here sends a message to the graph thread // to disconnect the streams, which should be sent before the // RunAfterPendingUpdates() call below. aDestination.mInputNodes.RemoveElementAt(aInputIndex); // Remove one instance of 'dest' from mOutputNodes. There could be // others, and it's not correct to remove them all since some of them // could be for different output ports. - RefPtr<AudioNode> output = mOutputNodes[aOutputIndex].forget(); - mOutputNodes.RemoveElementAt(aOutputIndex); + RefPtr<AudioNode> output = mOutputNodes[aOutputNodeIndex].forget(); + mOutputNodes.RemoveElementAt(aOutputNodeIndex); output->NotifyInputsChanged(); if (mStream) { nsCOMPtr<nsIRunnable> runnable = new RunnableRelease(output.forget()); mStream->RunAfterPendingUpdates(runnable.forget()); } return true; } bool -AudioNode::DisconnectFromParamIfConnected(AudioParam& aDestination, uint32_t aOutputIndex, uint32_t aInputIndex) +AudioNode::DisconnectFromOutputIfConnected(AudioParam& aDestination, uint32_t aOutputParamIndex, uint32_t aInputIndex) { - MOZ_ASSERT(aOutputIndex < mOutputParams.Length()); + MOZ_ASSERT(aOutputParamIndex < mOutputParams.Length()); MOZ_ASSERT(aInputIndex < aDestination.InputNodes().Length()); const InputNode& input = aDestination.InputNodes()[aInputIndex]; if (input.mInputNode != this) { return false; } aDestination.RemoveInputNode(aInputIndex); // Remove one instance of 'dest' from mOutputParams. There could be // others, and it's not correct to remove them all since some of them // could be for different output ports. - mOutputParams.RemoveElementAt(aOutputIndex); + mOutputParams.RemoveElementAt(aOutputParamIndex); return true; } +template<typename DestinationType, typename Predicate> +bool +AudioNode::DisconnectMatchingDestinationInputs(DestinationType& aDestination, + uint32_t aDestinationIndex, + Predicate aPredicate) +{ + bool wasConnected = false; + for (int32_t inputIndex = aDestination.InputNodes().Length() - 1; inputIndex >= 0; --inputIndex) { + const InputNode& input = aDestination.InputNodes()[inputIndex]; + if (aPredicate(input)) { + if (DisconnectFromOutputIfConnected(aDestination, aDestinationIndex, inputIndex)) { + wasConnected = true; + break; + } + } + } + return wasConnected; +} + void AudioNode::Disconnect(ErrorResult& aRv) { for (int32_t outputIndex = mOutputNodes.Length() - 1; outputIndex >= 0; --outputIndex) { AudioNode* dest = mOutputNodes[outputIndex]; - for (int32_t inputIndex = dest->mInputNodes.Length() - 1; inputIndex >= 0; --inputIndex) { - if (DisconnectFromOutputIfConnected(*dest, outputIndex, inputIndex)) { - break; - } - } + DisconnectMatchingDestinationInputs(*dest, outputIndex, + [](const InputNode&) { return true; }); } for (int32_t outputIndex = mOutputParams.Length() - 1; outputIndex >= 0; --outputIndex) { AudioParam* dest = mOutputParams[outputIndex]; - for (int32_t inputIndex = dest->InputNodes().Length() - 1; inputIndex >= 0; --inputIndex) { - if (DisconnectFromParamIfConnected(*dest, outputIndex, inputIndex)) { - break; - } - } + DisconnectMatchingDestinationInputs(*dest, outputIndex, + [](const InputNode&) { return true; }); } // This disconnection may have disconnected a panner and a source. Context()->UpdatePannerSource(); } void AudioNode::Disconnect(uint32_t aOutput, ErrorResult& aRv) { if (aOutput >= NumberOfOutputs()) { aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR); return; } for (int32_t outputIndex = mOutputNodes.Length() - 1; outputIndex >= 0; --outputIndex) { AudioNode* dest = mOutputNodes[outputIndex]; - for (int32_t inputIndex = dest->mInputNodes.Length() - 1; inputIndex >= 0; --inputIndex) { - InputNode& input = dest->mInputNodes[inputIndex]; - if (input.mOutputPort == aOutput) { - if (DisconnectFromOutputIfConnected(*dest, outputIndex, inputIndex)) { - break; - } - } - } + DisconnectMatchingDestinationInputs(*dest, outputIndex, + [aOutput](const InputNode& aInput) { + return aInput.mOutputPort == aOutput; + }); } for (int32_t outputIndex = mOutputParams.Length() - 1; outputIndex >= 0; --outputIndex) { AudioParam* dest = mOutputParams[outputIndex]; - for (int32_t inputIndex = dest->InputNodes().Length() - 1; inputIndex >= 0; --inputIndex) { - const InputNode& input = dest->InputNodes()[inputIndex]; - if (input.mOutputPort == aOutput) { - if (DisconnectFromParamIfConnected(*dest, outputIndex, inputIndex)) { - break; - } - } - } + DisconnectMatchingDestinationInputs(*dest, outputIndex, + [aOutput](const InputNode& aInput) { + return aInput.mOutputPort == aOutput; + }); } // This disconnection may have disconnected a panner and a source. Context()->UpdatePannerSource(); } void AudioNode::Disconnect(AudioNode& aDestination, ErrorResult& aRv) @@ -450,25 +455,21 @@ AudioNode::Disconnect(AudioNode& aDestin if (aOutput >= NumberOfOutputs()) { aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR); return; } bool wasConnected = false; for (int32_t outputIndex = mOutputNodes.Length() - 1; outputIndex >= 0; --outputIndex) { - for (int32_t inputIndex = aDestination.mInputNodes.Length() - 1; inputIndex >= 0; --inputIndex) { - InputNode& input = aDestination.mInputNodes[inputIndex]; - if (input.mOutputPort == aOutput) { - if (DisconnectFromOutputIfConnected(aDestination, outputIndex, inputIndex)) { - wasConnected = true; - break; - } - } - } + wasConnected |= + DisconnectMatchingDestinationInputs(aDestination, outputIndex, + [aOutput](const InputNode& aInput) { + return aInput.mOutputPort == aOutput; + }); } if (!wasConnected) { aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR); return; } // This disconnection may have disconnected a panner and a source. @@ -486,23 +487,22 @@ AudioNode::Disconnect(AudioNode& aDestin if (aInput >= aDestination.NumberOfInputs()) { aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR); return; } bool wasConnected = false; for (int32_t outputIndex = mOutputNodes.Length() - 1; outputIndex >= 0; --outputIndex) { - for (int32_t inputIndex = aDestination.mInputNodes.Length() - 1; inputIndex >= 0; --inputIndex) { - InputNode& input = aDestination.mInputNodes[inputIndex]; - if (input.mOutputPort == aOutput && input.mInputPort == aInput) { - wasConnected |= DisconnectFromOutputIfConnected(aDestination, outputIndex, inputIndex); - break; - } - } + wasConnected |= + DisconnectMatchingDestinationInputs(aDestination, outputIndex, + [aOutput, aInput](const InputNode& aInputNode) { + return aInputNode.mOutputPort == aOutput && + aInputNode.mInputPort == aInput; + }); } if (!wasConnected) { aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR); return; } // This disconnection may have disconnected a panner and a source. @@ -510,22 +510,19 @@ AudioNode::Disconnect(AudioNode& aDestin } void AudioNode::Disconnect(AudioParam& aDestination, ErrorResult& aRv) { bool wasConnected = false; for (int32_t outputIndex = mOutputParams.Length() - 1; outputIndex >= 0; --outputIndex) { - for (int32_t inputIndex = aDestination.InputNodes().Length() - 1; inputIndex >= 0; --inputIndex) { - if (DisconnectFromParamIfConnected(aDestination, outputIndex, inputIndex)) { - wasConnected = true; - break; - } - } + wasConnected |= + DisconnectMatchingDestinationInputs(aDestination, outputIndex, + [](const InputNode&) { return true; }); } if (!wasConnected) { aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR); return; } } @@ -535,25 +532,21 @@ AudioNode::Disconnect(AudioParam& aDesti if (aOutput >= NumberOfOutputs()) { aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR); return; } bool wasConnected = false; for (int32_t outputIndex = mOutputParams.Length() - 1; outputIndex >= 0; --outputIndex) { - for (int32_t inputIndex = aDestination.InputNodes().Length() - 1; inputIndex >= 0; --inputIndex) { - const InputNode& input = aDestination.InputNodes()[inputIndex]; - if (input.mOutputPort == aOutput) { - if (DisconnectFromParamIfConnected(aDestination, outputIndex, inputIndex)) { - wasConnected = true; - break; - } - } - } + wasConnected |= + DisconnectMatchingDestinationInputs(aDestination, outputIndex, + [aOutput](const InputNode& aNode) { + return aNode.mOutputPort == aOutput; + }); } if (!wasConnected) { aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR); return; } }
--- a/dom/media/webaudio/AudioNode.h +++ b/dom/media/webaudio/AudioNode.h @@ -217,26 +217,39 @@ public: virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const; virtual size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const; // Returns a string from constant static storage identifying the dom node // type. virtual const char* NodeType() const = 0; private: + // Given: + // + // - a DestinationType, that can be an AudioNode or an AudioParam ; + // - a Predicate, a function that takes an InputNode& and returns a bool ; + // + // This method iterates on the InputNodes() of aDestination, and calls + // `DisconnectFromOutputIfConnected` with this input node, if aPredicate + // returns true. + template<typename DestinationType, typename Predicate> + bool DisconnectMatchingDestinationInputs(DestinationType& aDestination, + uint32_t aDestinationIndex, + Predicate aPredicate); + virtual void LastRelease() override { // We are about to be deleted, disconnect the object from the graph before // the derived type is destroyed. DisconnectFromGraph(); } // Callers must hold a reference to 'this'. void DisconnectFromGraph(); bool DisconnectFromOutputIfConnected(AudioNode& aDestination, uint32_t aOutputIndex, uint32_t aInputIndex); - bool DisconnectFromParamIfConnected(AudioParam& aDestination, uint32_t aOutputIndex, uint32_t aInputIndex); + bool DisconnectFromOutputIfConnected(AudioParam& aDestination, uint32_t aOutputIndex, uint32_t aInputIndex); protected: // Helpers for sending different value types to streams void SendDoubleParameterToStream(uint32_t aIndex, double aValue); void SendInt32ParameterToStream(uint32_t aIndex, int32_t aValue); void SendThreeDPointParameterToStream(uint32_t aIndex, const ThreeDPoint& aValue); void SendChannelMixingParametersToStream();