Bug 1544023 - let AudioNode keep the reference of all AudioParams which belong to itself. r=padenot

When we suspend or resume the `AudioContext`, it should affect ALL media streams which belong to or are related to the `AudioNode` that are created by this `AudioContext`.

As `AudioNode::OutputParams()` can only return the connected AudioParams, it doesn't return the AudioParams which are belong to itself. That means we would miss to apply the suspend/resume operation for those streams, and it would cause imbalancing suspended count.

Therefore, we let `AudioNode` to keep the reference of all its AudioParam, and return them to `AudioContext` in order to do the operation for all streams.

Differential Revision: https://phabricator.services.mozilla.com/D28008

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Alastor Wu 2019-04-23 17:50:54 +00:00
Родитель d547376a66
Коммит c58212fe27
12 изменённых файлов: 70 добавлений и 56 удалений

Просмотреть файл

@ -588,13 +588,12 @@ AudioBufferSourceNode::AudioBufferSourceNode(AudioContext* aContext)
: AudioScheduledSourceNode(aContext, 2, ChannelCountMode::Max,
ChannelInterpretation::Speakers),
mLoopStart(0.0),
mLoopEnd(0.0)
mLoopEnd(0.0),
// mOffset and mDuration are initialized in Start().
,
mPlaybackRate(new AudioParam(this, PLAYBACKRATE, "playbackRate", 1.0f)),
mDetune(new AudioParam(this, DETUNE, "detune", 0.0f)),
mLoop(false),
mStartCalled(false) {
CreateAudioParam(mPlaybackRate, PLAYBACKRATE, "playbackRate", 1.0f);
CreateAudioParam(mDetune, DETUNE, "detune", 0.0f);
AudioBufferSourceNodeEngine* engine =
new AudioBufferSourceNodeEngine(this, aContext->Destination());
mStream = AudioNodeStream::Create(aContext, engine,

Просмотреть файл

@ -904,8 +904,8 @@ nsTArray<MediaStream*> AudioContext::GetAllStreams() const {
if (s) {
streams.AppendElement(s);
}
// Add the streams for the AudioParam that have an AudioNode input.
const nsTArray<RefPtr<AudioParam>>& audioParams = node->OutputParams();
// Add the streams of AudioParam.
const nsTArray<RefPtr<AudioParam>>& audioParams = node->GetAudioParams();
if (!audioParams.IsEmpty()) {
for (auto& param : audioParams) {
s = param->GetStream();

Просмотреть файл

@ -26,12 +26,14 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(AudioNode, DOMEventTargetHelper)
tmp->mContext->UnregisterNode(tmp);
}
NS_IMPL_CYCLE_COLLECTION_UNLINK(mContext)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mParams)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOutputNodes)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOutputParams)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(AudioNode,
DOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mContext)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParams)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOutputNodes)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOutputParams)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
@ -595,5 +597,13 @@ void AudioNode::SetPassThrough(bool aPassThrough) {
}
}
void AudioNode::CreateAudioParam(RefPtr<AudioParam>& aParam, uint32_t aIndex,
const char* aName, float aDefaultValue,
float aMinValue, float aMaxValue) {
aParam =
new AudioParam(this, aIndex, aName, aDefaultValue, aMinValue, aMaxValue);
mParams.AppendElement(aParam);
}
} // namespace dom
} // namespace mozilla

Просмотреть файл

@ -168,10 +168,10 @@ class AudioNode : public DOMEventTargetHelper, public nsSupportsWeakReference {
AudioNodeStream* GetStream() const { return mStream; }
const nsTArray<InputNode>& InputNodes() const { return mInputNodes; }
const nsTArray<RefPtr<AudioNode> >& OutputNodes() const {
const nsTArray<RefPtr<AudioNode>>& OutputNodes() const {
return mOutputNodes;
}
const nsTArray<RefPtr<AudioParam> >& OutputParams() const {
const nsTArray<RefPtr<AudioParam>>& OutputParams() const {
return mOutputParams;
}
@ -202,6 +202,8 @@ class AudioNode : public DOMEventTargetHelper, public nsSupportsWeakReference {
// during document shutdown.
AbstractThread* GetAbstractMainThread() const { return mAbstractMainThread; }
const nsTArray<RefPtr<AudioParam>>& GetAudioParams() const { return mParams; }
private:
// Given:
//
@ -246,6 +248,15 @@ class AudioNode : public DOMEventTargetHelper, public nsSupportsWeakReference {
// Must not become null until finished.
RefPtr<AudioNodeStream> mStream;
// The reference pointing out all audio params which belong to this node.
nsTArray<RefPtr<AudioParam>> mParams;
// Use this function to create a AudioParam, which will automatically add the
// new AudioParam to `mParams`.
void CreateAudioParam(RefPtr<AudioParam>& aParam, uint32_t aIndex,
const char* aName, float aDefaultValue,
float aMinValue = std::numeric_limits<float>::lowest(),
float aMaxValue = std::numeric_limits<float>::max());
private:
// For every InputNode, there is a corresponding entry in mOutputNodes of the
// InputNode's mInputNode.
@ -254,13 +265,13 @@ class AudioNode : public DOMEventTargetHelper, public nsSupportsWeakReference {
// of the mOutputNode entry. We won't necessarily be able to identify the
// exact matching entry, since mOutputNodes doesn't include the port
// identifiers and the same node could be connected on multiple ports.
nsTArray<RefPtr<AudioNode> > mOutputNodes;
nsTArray<RefPtr<AudioNode>> mOutputNodes;
// For every mOutputParams entry, there is a corresponding entry in
// AudioParam::mInputNodes of the mOutputParams entry. We won't necessarily be
// able to identify the exact matching entry, since mOutputParams doesn't
// include the port identifiers and the same node could be connected on
// multiple ports.
nsTArray<RefPtr<AudioParam> > mOutputParams;
nsTArray<RefPtr<AudioParam>> mOutputParams;
uint32_t mChannelCount;
ChannelCountMode mChannelCountMode;
ChannelInterpretation mChannelInterpretation;

Просмотреть файл

@ -224,14 +224,14 @@ class BiquadFilterNodeEngine final : public AudioNodeEngine {
BiquadFilterNode::BiquadFilterNode(AudioContext* aContext)
: AudioNode(aContext, 2, ChannelCountMode::Max,
ChannelInterpretation::Speakers),
mType(BiquadFilterType::Lowpass),
mFrequency(new AudioParam(
this, BiquadFilterNodeEngine::FREQUENCY, "frequency", 350.f,
-(aContext->SampleRate() / 2), aContext->SampleRate() / 2)),
mDetune(
new AudioParam(this, BiquadFilterNodeEngine::DETUNE, "detune", 0.f)),
mQ(new AudioParam(this, BiquadFilterNodeEngine::Q, "Q", 1.f)),
mGain(new AudioParam(this, BiquadFilterNodeEngine::GAIN, "gain", 0.f)) {
mType(BiquadFilterType::Lowpass) {
CreateAudioParam(mFrequency, BiquadFilterNodeEngine::FREQUENCY, "frequency",
350.f, -(aContext->SampleRate() / 2),
aContext->SampleRate() / 2);
CreateAudioParam(mDetune, BiquadFilterNodeEngine::DETUNE, "detune", 0.f);
CreateAudioParam(mQ, BiquadFilterNodeEngine::Q, "Q", 1.f);
CreateAudioParam(mGain, BiquadFilterNodeEngine::GAIN, "gain", 0.f);
uint64_t windowID = 0;
if (aContext->GetParentObject()) {
windowID = aContext->GetParentObject()->WindowID();

Просмотреть файл

@ -156,9 +156,8 @@ class ConstantSourceNodeEngine final : public AudioNodeEngine {
ConstantSourceNode::ConstantSourceNode(AudioContext* aContext)
: AudioScheduledSourceNode(aContext, 2, ChannelCountMode::Max,
ChannelInterpretation::Speakers),
mOffset(new AudioParam(this, ConstantSourceNodeEngine::OFFSET, "offset",
1.0f)),
mStartCalled(false) {
CreateAudioParam(mOffset, ConstantSourceNodeEngine::OFFSET, "offset", 1.0f);
ConstantSourceNodeEngine* engine =
new ConstantSourceNodeEngine(this, aContext->Destination());
mStream = AudioNodeStream::Create(aContext, engine,

Просмотреть файл

@ -172,9 +172,9 @@ class DelayNodeEngine final : public AudioNodeEngine {
DelayNode::DelayNode(AudioContext* aContext, double aMaxDelay)
: AudioNode(aContext, 2, ChannelCountMode::Max,
ChannelInterpretation::Speakers),
mDelay(new AudioParam(this, DelayNodeEngine::DELAY, "delayTime", 0.0f,
0.f, aMaxDelay)) {
ChannelInterpretation::Speakers) {
CreateAudioParam(mDelay, DelayNodeEngine::DELAY, "delayTime", 0.0f, 0.f,
aMaxDelay);
DelayNodeEngine* engine = new DelayNodeEngine(
this, aContext->Destination(), aContext->SampleRate() * aMaxDelay);
mStream = AudioNodeStream::Create(

Просмотреть файл

@ -163,17 +163,17 @@ class DynamicsCompressorNodeEngine final : public AudioNodeEngine {
DynamicsCompressorNode::DynamicsCompressorNode(AudioContext* aContext)
: AudioNode(aContext, 2, ChannelCountMode::Clamped_max,
ChannelInterpretation::Speakers),
mThreshold(new AudioParam(this, DynamicsCompressorNodeEngine::THRESHOLD,
"threshold", -24.f, -100.f, 0.f)),
mKnee(new AudioParam(this, DynamicsCompressorNodeEngine::KNEE, "knee",
30.f, 0.f, 40.f)),
mRatio(new AudioParam(this, DynamicsCompressorNodeEngine::RATIO, "ratio",
12.f, 1.f, 20.f)),
mReduction(0),
mAttack(new AudioParam(this, DynamicsCompressorNodeEngine::ATTACK,
"attack", 0.003f, 0.f, 1.f)),
mRelease(new AudioParam(this, DynamicsCompressorNodeEngine::RELEASE,
"release", 0.25f, 0.f, 1.f)) {
mReduction(0) {
CreateAudioParam(mThreshold, DynamicsCompressorNodeEngine::THRESHOLD,
"threshold", -24.f, -100.f, 0.f);
CreateAudioParam(mKnee, DynamicsCompressorNodeEngine::KNEE, "knee", 30.f, 0.f,
40.f);
CreateAudioParam(mRatio, DynamicsCompressorNodeEngine::RATIO, "ratio", 12.f,
1.f, 20.f);
CreateAudioParam(mAttack, DynamicsCompressorNodeEngine::ATTACK, "attack",
0.003f, 0.f, 1.f);
CreateAudioParam(mRelease, DynamicsCompressorNodeEngine::RELEASE, "release",
0.25f, 0.f, 1.f);
DynamicsCompressorNodeEngine* engine =
new DynamicsCompressorNodeEngine(this, aContext->Destination());
mStream = AudioNodeStream::Create(

Просмотреть файл

@ -108,8 +108,8 @@ class GainNodeEngine final : public AudioNodeEngine {
GainNode::GainNode(AudioContext* aContext)
: AudioNode(aContext, 2, ChannelCountMode::Max,
ChannelInterpretation::Speakers),
mGain(new AudioParam(this, GainNodeEngine::GAIN, "gain", 1.0f)) {
ChannelInterpretation::Speakers) {
CreateAudioParam(mGain, GainNodeEngine::GAIN, "gain", 1.0f);
GainNodeEngine* engine = new GainNodeEngine(this, aContext->Destination());
mStream = AudioNodeStream::Create(
aContext, engine, AudioNodeStream::NO_STREAM_FLAGS, aContext->Graph());

Просмотреть файл

@ -371,12 +371,11 @@ OscillatorNode::OscillatorNode(AudioContext* aContext)
: AudioScheduledSourceNode(aContext, 2, ChannelCountMode::Max,
ChannelInterpretation::Speakers),
mType(OscillatorType::Sine),
mFrequency(new AudioParam(
this, OscillatorNodeEngine::FREQUENCY, "frequency", 440.0f,
-(aContext->SampleRate() / 2), aContext->SampleRate() / 2)),
mDetune(
new AudioParam(this, OscillatorNodeEngine::DETUNE, "detune", 0.0f)),
mStartCalled(false) {
CreateAudioParam(mFrequency, OscillatorNodeEngine::FREQUENCY, "frequency",
440.0f, -(aContext->SampleRate() / 2),
aContext->SampleRate() / 2);
CreateAudioParam(mDetune, OscillatorNodeEngine::DETUNE, "detune", 0.0f);
OscillatorNodeEngine* engine =
new OscillatorNodeEngine(this, aContext->Destination());
mStream = AudioNodeStream::Create(aContext, engine,

Просмотреть файл

@ -296,24 +296,21 @@ PannerNode::PannerNode(AudioContext* aContext)
,
mPanningModel(PanningModelType::Equalpower),
mDistanceModel(DistanceModelType::Inverse),
mPositionX(
new AudioParam(this, PannerNode::POSITIONX, this->NodeType(), 0.f)),
mPositionY(
new AudioParam(this, PannerNode::POSITIONY, this->NodeType(), 0.f)),
mPositionZ(
new AudioParam(this, PannerNode::POSITIONZ, this->NodeType(), 0.f)),
mOrientationX(new AudioParam(this, PannerNode::ORIENTATIONX,
this->NodeType(), 1.0f)),
mOrientationY(new AudioParam(this, PannerNode::ORIENTATIONY,
this->NodeType(), 0.f)),
mOrientationZ(new AudioParam(this, PannerNode::ORIENTATIONZ,
this->NodeType(), 0.f)),
mRefDistance(1.),
mMaxDistance(10000.),
mRolloffFactor(1.),
mConeInnerAngle(360.),
mConeOuterAngle(360.),
mConeOuterGain(0.) {
CreateAudioParam(mPositionX, PannerNode::POSITIONX, this->NodeType(), 0.f);
CreateAudioParam(mPositionY, PannerNode::POSITIONY, this->NodeType(), 0.f);
CreateAudioParam(mPositionZ, PannerNode::POSITIONZ, this->NodeType(), 0.f);
CreateAudioParam(mOrientationX, PannerNode::ORIENTATIONX, this->NodeType(),
1.0f);
CreateAudioParam(mOrientationY, PannerNode::ORIENTATIONY, this->NodeType(),
0.f);
CreateAudioParam(mOrientationZ, PannerNode::ORIENTATIONZ, this->NodeType(),
0.f);
mStream = AudioNodeStream::Create(
aContext,
new PannerNodeEngine(this, aContext->Destination(),

Просмотреть файл

@ -155,9 +155,8 @@ class StereoPannerNodeEngine final : public AudioNodeEngine {
StereoPannerNode::StereoPannerNode(AudioContext* aContext)
: AudioNode(aContext, 2, ChannelCountMode::Clamped_max,
ChannelInterpretation::Speakers),
mPan(new AudioParam(this, StereoPannerNodeEngine::PAN, "pan", 0.f, -1.f,
1.f)) {
ChannelInterpretation::Speakers) {
CreateAudioParam(mPan, StereoPannerNodeEngine::PAN, "pan", 0.f, -1.f, 1.f);
StereoPannerNodeEngine* engine =
new StereoPannerNodeEngine(this, aContext->Destination());
mStream = AudioNodeStream::Create(