bug 1191649 determine ScriptProcessor connected status on main thread r=padenot
authorKarl Tomlinson <karlt+@karlt.net>
Thu, 06 Aug 2015 16:22:56 +1200
changeset 277817 bc6a1a195d0490ee87ecb59da690b743b3771aa7
parent 277816 fe4f843ba68f8b189549b563703ba966dfc7a100
child 277818 b2852b6ae7db3e9449a1f25a17febca91a419cca
push id8456
push userraliiev@mozilla.com
push dateMon, 21 Sep 2015 14:31:52 +0000
treeherdermozilla-aurora@7f2f0fb041b1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspadenot
bugs1191649
milestone43.0a1
bug 1191649 determine ScriptProcessor connected status on main thread r=padenot because stream inputs may be removed when only providing null data. The ScriptProcessor is also kept alive when it has only input nodes so that it is not garbage collected when its input nodes are collected.
dom/media/webaudio/ScriptProcessorNode.cpp
dom/media/webaudio/ScriptProcessorNode.h
--- a/dom/media/webaudio/ScriptProcessorNode.cpp
+++ b/dom/media/webaudio/ScriptProcessorNode.cpp
@@ -263,26 +263,40 @@ public:
     mSharedBuffers = new SharedBuffers(mSource->SampleRate());
   }
 
   SharedBuffers* GetSharedBuffers() const
   {
     return mSharedBuffers;
   }
 
+  enum {
+    IS_CONNECTED,
+  };
+
+  virtual void SetInt32Parameter(uint32_t aIndex, int32_t aParam) override
+  {
+    switch (aIndex) {
+      case IS_CONNECTED:
+        mIsConnected = aParam;
+        break;
+      default:
+        NS_ERROR("Bad Int32Parameter");
+    } // End index switch.
+  }
+
   virtual void ProcessBlock(AudioNodeStream* aStream,
                             const AudioChunk& aInput,
                             AudioChunk* aOutput,
                             bool* aFinished) override
   {
     // This node is not connected to anything. Per spec, we don't fire the
     // onaudioprocess event. We also want to clear out the input and output
     // buffer queue, and output a null buffer.
-    if (!(aStream->ConsumerCount() ||
-          aStream->AsProcessedStream()->InputPortCount())) {
+    if (!mIsConnected) {
       aOutput->SetNull(WEBAUDIO_BLOCK_SIZE);
       mSharedBuffers->Reset();
       mSeenNonSilenceInput = false;
       mInputWriteIndex = 0;
       return;
     }
 
     // First, record our input buffer
@@ -478,16 +492,17 @@ private:
 
   nsAutoPtr<SharedBuffers> mSharedBuffers;
   AudioNodeStream* mSource;
   AudioNodeStream* mDestination;
   InputChannels mInputChannels;
   const uint32_t mBufferSize;
   // The write index into the current input buffer
   uint32_t mInputWriteIndex;
+  bool mIsConnected = false;
   bool mSeenNonSilenceInput;
 };
 
 ScriptProcessorNode::ScriptProcessorNode(AudioContext* aContext,
                                          uint32_t aBufferSize,
                                          uint32_t aNumberOfInputChannels,
                                          uint32_t aNumberOfOutputChannels)
   : AudioNode(aContext,
@@ -548,17 +563,24 @@ JSObject*
 ScriptProcessorNode::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return ScriptProcessorNodeBinding::Wrap(aCx, this, aGivenProto);
 }
 
 void
 ScriptProcessorNode::UpdateConnectedStatus()
 {
-  bool isConnected = !(OutputNodes().IsEmpty() && OutputParams().IsEmpty());
+  bool isConnected = !(OutputNodes().IsEmpty() && OutputParams().IsEmpty()
+                       && InputNodes().IsEmpty());
+
+  // Events are queued even when there is no listener because a listener
+  // may be added while events are in the queue.
+  SendInt32ParameterToStream(ScriptProcessorNodeEngine::IS_CONNECTED,
+                             isConnected);
+
   if (isConnected && HasListenersFor(nsGkAtoms::onaudioprocess)) {
     MarkActive();
   } else {
     MarkInactive();
   }
 }
 
 } // namespace dom
--- a/dom/media/webaudio/ScriptProcessorNode.h
+++ b/dom/media/webaudio/ScriptProcessorNode.h
@@ -53,16 +53,20 @@ public:
 
   virtual void Disconnect(uint32_t aOutput, ErrorResult& aRv) override
   {
     AudioNode::Disconnect(aOutput, aRv);
     if (!aRv.Failed()) {
       UpdateConnectedStatus();
     }
   }
+  virtual void NotifyInputsChanged() override
+  {
+    UpdateConnectedStatus();
+  }
 
   virtual void SetChannelCount(uint32_t aChannelCount, ErrorResult& aRv) override
   {
     if (aChannelCount != ChannelCount()) {
       aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
     }
     return;
   }