bug 1205540 provide querying whether engines need to continue processing even without input r=padenot
☠☠ backed out by eb30e5ee32f0 ☠ ☠
authorKarl Tomlinson <karlt+@karlt.net>
Wed, 09 Sep 2015 08:54:03 +1200
changeset 295828 0d122cb349217abf026e74934883cfe1793ee361
parent 295827 4de5f87180fb7d5b7528db02d8fae3bc0742b7e8
child 295829 b3f6e1db72332e5d9690529404ee1f9a83906b0f
push id5245
push userraliiev@mozilla.com
push dateThu, 29 Oct 2015 11:30:51 +0000
treeherdermozilla-beta@dac831dc1bd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspadenot
bugs1205540
milestone43.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
bug 1205540 provide querying whether engines need to continue processing even without input r=padenot
dom/media/webaudio/AnalyserNode.cpp
dom/media/webaudio/AudioBufferSourceNode.cpp
dom/media/webaudio/AudioDestinationNode.cpp
dom/media/webaudio/AudioNodeEngine.h
dom/media/webaudio/BiquadFilterNode.cpp
dom/media/webaudio/ConvolverNode.cpp
dom/media/webaudio/DelayNode.cpp
dom/media/webaudio/OscillatorNode.cpp
dom/media/webaudio/PannerNode.cpp
dom/media/webaudio/ScriptProcessorNode.cpp
--- a/dom/media/webaudio/AnalyserNode.cpp
+++ b/dom/media/webaudio/AnalyserNode.cpp
@@ -78,16 +78,21 @@ public:
       mChunksToProcess = CHUNK_COUNT;
     }
 
     nsRefPtr<TransferBuffer> transfer =
       new TransferBuffer(aStream, aInput.AsAudioChunk());
     NS_DispatchToMainThread(transfer);
   }
 
+  virtual bool IsActive() const override
+  {
+    return mChunksToProcess != 0;
+  }
+
   virtual size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const override
   {
     return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
   }
 
   size_t mChunksToProcess = 0;
 };
 
--- a/dom/media/webaudio/AudioBufferSourceNode.cpp
+++ b/dom/media/webaudio/AudioBufferSourceNode.cpp
@@ -503,16 +503,22 @@ public:
     // We've finished if we've gone past mStop, or if we're past mDuration when
     // looping is disabled.
     if (streamPosition >= mStop ||
         (!mLoop && mBufferPosition >= mBufferEnd && !mRemainingResamplerTail)) {
       *aFinished = true;
     }
   }
 
+  virtual bool IsActive() const override
+  {
+    // Whether buffer has been set and start() has been called.
+    return mBufferSampleRate != 0;
+  }
+
   virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override
   {
     // Not owned:
     // - mBuffer - shared w/ AudioNode
     // - mPlaybackRateTimeline - shared w/ AudioNode
     // - mDetuneTimeline - shared w/ AudioNode
 
     size_t amount = AudioNodeEngine::SizeOfExcludingThis(aMallocSizeOf);
--- a/dom/media/webaudio/AudioDestinationNode.cpp
+++ b/dom/media/webaudio/AudioDestinationNode.cpp
@@ -107,16 +107,24 @@ public:
       NS_ASSERTION(mWriteIndex == mLength, "Overshot length");
       // Go to finished state. When the graph's current time eventually reaches
       // the end of the stream, then the main thread will be notified and we'll
       // shut down the AudioContext.
       *aFinished = true;
     }
   }
 
+  virtual bool IsActive() const override
+  {
+    // Keep processing to track stream time, which is used for all timelines
+    // associated with the same AudioContext.
+    return true;
+  }
+
+
   class OnCompleteTask final : public nsRunnable
   {
   public:
     OnCompleteTask(AudioContext* aAudioContext, AudioBuffer* aRenderedBuffer)
       : mAudioContext(aAudioContext)
       , mRenderedBuffer(aRenderedBuffer)
     {}
 
@@ -250,16 +258,26 @@ public:
 
       nsRefPtr<InputMutedRunnable> runnable =
         new InputMutedRunnable(aStream, newInputMuted);
       aStream->Graph()->
         DispatchToMainThreadAfterStreamStateUpdate(runnable.forget());
     }
   }
 
+  virtual bool IsActive() const override
+  {
+    // Keep processing to track stream time, which is used for all timelines
+    // associated with the same AudioContext.  If there are no other engines
+    // for the AudioContext, then this could return false to suspend the
+    // stream, but the stream is blocked anyway through
+    // AudioDestinationNode::SetIsOnlyNodeForContext().
+    return true;
+  }
+
   virtual void SetDoubleParameter(uint32_t aIndex, double aParam) override
   {
     if (aIndex == VOLUME) {
       mVolume = aParam;
     }
   }
 
   virtual void SetInt32Parameter(uint32_t aIndex, int32_t aParam) override
--- a/dom/media/webaudio/AudioNodeEngine.h
+++ b/dom/media/webaudio/AudioNodeEngine.h
@@ -341,16 +341,22 @@ public:
    * corresponding AudioNode, in which case it will be interpreted as a channel
    * of silence.
    */
   virtual void ProcessBlocksOnPorts(AudioNodeStream* aStream,
                                     const OutputChunks& aInput,
                                     OutputChunks& aOutput,
                                     bool* aFinished);
 
+  // IsActive() returns true if the engine needs to continue processing an
+  // unfinished stream even when it has silent or no input connections.  This
+  // includes tail-times and when sources have been scheduled to start.  If
+  // returning false, then the stream can be suspended.
+  virtual bool IsActive() const { return false; }
+
   bool HasNode() const
   {
     MOZ_ASSERT(NS_IsMainThread());
     return !!mNode;
   }
 
   dom::AudioNode* NodeMainThread() const
   {
--- a/dom/media/webaudio/BiquadFilterNode.cpp
+++ b/dom/media/webaudio/BiquadFilterNode.cpp
@@ -206,16 +206,21 @@ public:
       SetParamsOnBiquad(mBiquads[i], aStream->SampleRate(), mType, freq, q, gain, detune);
 
       mBiquads[i].process(input,
                           aOutput->ChannelFloatsForWrite(i),
                           aInput.GetDuration());
     }
   }
 
+  virtual bool IsActive() const override
+  {
+    return !mBiquads.IsEmpty();
+  }
+
   virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override
   {
     // Not owned:
     // - mSource - probably not owned
     // - mDestination - probably not owned
     // - AudioParamTimelines - counted in the AudioNode
     size_t amount = AudioNodeEngine::SizeOfExcludingThis(aMallocSizeOf);
     amount += mBiquads.ShallowSizeOfExcludingThis(aMallocSizeOf);
--- a/dom/media/webaudio/ConvolverNode.cpp
+++ b/dom/media/webaudio/ConvolverNode.cpp
@@ -149,16 +149,21 @@ public:
       mLeftOverData = mBufferLength;
       MOZ_ASSERT(mLeftOverData > 0);
     }
     aOutput->AllocateChannels(2);
 
     mReverb->process(&input, aOutput, WEBAUDIO_BLOCK_SIZE);
   }
 
+  virtual bool IsActive() const override
+  {
+    return mLeftOverData != INT32_MIN;
+  }
+
   virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override
   {
     size_t amount = AudioNodeEngine::SizeOfExcludingThis(aMallocSizeOf);
     if (mBuffer && !mBuffer->IsShared()) {
       amount += mBuffer->SizeOfIncludingThis(aMallocSizeOf);
     }
 
     if (mReverb) {
--- a/dom/media/webaudio/DelayNode.cpp
+++ b/dom/media/webaudio/DelayNode.cpp
@@ -156,16 +156,21 @@ public:
     if (mLeftOverData <= 0) {
       aOutput->SetNull(WEBAUDIO_BLOCK_SIZE);
     } else {
       UpdateOutputBlock(aOutput, WEBAUDIO_BLOCK_SIZE);
     }
     mHaveProducedBeforeInput = true;
   }
 
+  virtual bool IsActive() const override
+  {
+    return mLeftOverData != INT32_MIN;
+  }
+
   virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override
   {
     size_t amount = AudioNodeEngine::SizeOfExcludingThis(aMallocSizeOf);
     // Not owned:
     // - mSource - probably not owned
     // - mDestination - probably not owned
     // - mDelay - shares ref with AudioNode, don't count
     amount += mBuffer.SizeOfExcludingThis(aMallocSizeOf);
--- a/dom/media/webaudio/OscillatorNode.cpp
+++ b/dom/media/webaudio/OscillatorNode.cpp
@@ -325,16 +325,22 @@ public:
         ComputeCustom(output, ticks, start, end);
         break;
       default:
         ComputeSilence(aOutput);
     };
 
   }
 
+  virtual bool IsActive() const override
+  {
+    // start() has been called.
+    return mStart != -1;
+  }
+
   virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override
   {
     size_t amount = AudioNodeEngine::SizeOfExcludingThis(aMallocSizeOf);
 
     // Not owned:
     // - mSource
     // - mDestination
     // - mFrequency (internal ref owned by node)
--- a/dom/media/webaudio/PannerNode.cpp
+++ b/dom/media/webaudio/PannerNode.cpp
@@ -167,16 +167,21 @@ public:
           DispatchToMainThreadAfterStreamStateUpdate(refchanged.forget());
       }
       mLeftOverData = mHRTFPanner->maxTailFrames();
     }
 
     (this->*mPanningModelFunction)(aInput, aOutput);
   }
 
+  virtual bool IsActive() const override
+  {
+    return mLeftOverData != INT_MIN;
+  }
+
   void ComputeAzimuthAndElevation(float& aAzimuth, float& aElevation);
   float ComputeConeGain();
   // Compute how much the distance contributes to the gain reduction.
   float ComputeDistanceGain();
 
   void EqualPowerPanningFunction(const AudioBlock& aInput, AudioBlock* aOutput);
   void HRTFPanningFunction(const AudioBlock& aInput, AudioBlock* aOutput);
 
--- a/dom/media/webaudio/ScriptProcessorNode.cpp
+++ b/dom/media/webaudio/ScriptProcessorNode.cpp
@@ -328,16 +328,24 @@ public:
     *aOutput = mSharedBuffers->GetOutputBuffer();
 
     if (mInputWriteIndex >= mBufferSize) {
       SendBuffersToMainThread(aStream);
       mInputWriteIndex -= mBufferSize;
     }
   }
 
+  virtual bool IsActive() const override
+  {
+    // Could return false when !mIsConnected after all output chunks produced
+    // by main thread events calling
+    // SharedBuffers::FinishProducingOutputBuffer() have been processed.
+    return true;
+  }
+
   virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override
   {
     // Not owned:
     // - mSource (probably)
     // - mDestination (probably)
     size_t amount = AudioNodeEngine::SizeOfExcludingThis(aMallocSizeOf);
     amount += mSharedBuffers->SizeOfIncludingThis(aMallocSizeOf);
     amount += mInputBuffer->SizeOfIncludingThis(aMallocSizeOf);