Bug 914030 - Keep a self reference on destination while offline context is rendering. r=ehsan, a=akeybl
authorKarl Tomlinson <karlt+@karlt.net>
Tue, 10 Sep 2013 17:10:53 +1200
changeset 154095 439302ba8435809c29aea814a246d28c3388b945
parent 154094 2f1d4aea750edf61955f25bfd5d0f89af8af8be0
child 154096 7caeec1e5f7badd0447657a2cdb89ed81959ee8b
push id1
push usersledru@mozilla.com
push dateThu, 04 Dec 2014 17:57:20 +0000
reviewersehsan, akeybl
bugs914030
milestone25.0
Bug 914030 - Keep a self reference on destination while offline context is rendering. r=ehsan, a=akeybl
content/media/webaudio/AudioContext.cpp
content/media/webaudio/AudioDestinationNode.cpp
content/media/webaudio/AudioDestinationNode.h
--- a/content/media/webaudio/AudioContext.cpp
+++ b/content/media/webaudio/AudioContext.cpp
@@ -550,17 +550,17 @@ AudioContext::Shutdown()
   nsTArray<ScriptProcessorNode*> spNodes;
   GetHashtableElements(mScriptProcessorNodes, spNodes);
   for (uint32_t i = 0; i < spNodes.Length(); ++i) {
     spNodes[i]->Stop();
   }
 
   // For offline contexts, we can destroy the MediaStreamGraph at this point.
   if (mIsOffline) {
-    mDestination->DestroyGraph();
+    mDestination->OfflineShutdown();
   }
 }
 
 void
 AudioContext::Suspend()
 {
   MediaStream* ds = DestinationStream();
   if (ds) {
--- a/content/media/webaudio/AudioDestinationNode.cpp
+++ b/content/media/webaudio/AudioDestinationNode.cpp
@@ -120,22 +120,23 @@ public:
         }
 
         nsRefPtr<AudioContext> context;
         {
           MutexAutoLock lock(mStream->Engine()->NodeMutex());
           AudioNode* node = mStream->Engine()->Node();
           if (node) {
             context = node->Context();
+            MOZ_ASSERT(context, "node hasn't kept context alive");
           }
         }
         if (!context) {
           return NS_OK;
         }
-        context->Shutdown();
+        context->Shutdown(); // drops self reference
 
         AutoPushJSContext cx(context->GetJSContext());
         if (cx) {
           JSAutoRequest ar(cx);
 
           // Create the input buffer
           nsRefPtr<AudioBuffer> renderedBuffer = new AudioBuffer(context,
                                                                  mLength,
@@ -276,29 +277,32 @@ AudioDestinationNode::Mute()
 void
 AudioDestinationNode::Unmute()
 {
   MOZ_ASSERT(Context() && !Context()->IsOffline());
   SendDoubleParameterToStream(DestinationNodeEngine::VOLUME, 1.0f);
 }
 
 void
-AudioDestinationNode::DestroyGraph()
+AudioDestinationNode::OfflineShutdown()
 {
   MOZ_ASSERT(Context() && Context()->IsOffline(),
              "Should only be called on a valid OfflineAudioContext");
+
   MediaStreamGraph::DestroyNonRealtimeInstance(mStream->Graph());
+  mOfflineRenderingRef.Drop(this);
 }
 
 JSObject*
 AudioDestinationNode::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
 {
   return AudioDestinationNodeBinding::Wrap(aCx, aScope, this);
 }
 
 void
 AudioDestinationNode::StartRendering()
 {
+  mOfflineRenderingRef.Take(this);
   mStream->Graph()->StartNonRealtimeProcessing(mFramesToProduce);
 }
 
 }
 }
--- a/content/media/webaudio/AudioDestinationNode.h
+++ b/content/media/webaudio/AudioDestinationNode.h
@@ -41,19 +41,20 @@ public:
   virtual void SetChannelCount(uint32_t aChannelCount,
                                ErrorResult& aRv) MOZ_OVERRIDE;
 
   void Mute();
   void Unmute();
 
   void StartRendering();
 
-  void DestroyGraph();
+  void OfflineShutdown();
 
 private:
+  SelfReference<AudioDestinationNode> mOfflineRenderingRef;
   uint32_t mFramesToProduce;
 };
 
 }
 }
 
 #endif