bug 1092915 modify mCurrentDecoder on main thread after RemoveDecoder r=karlt a=lmandel
authorMatt Woodrow <mwoodrow@mozilla.com>
Wed, 11 Feb 2015 11:12:39 +1300
changeset 240842 82ab77166a5f
parent 240841 269ea0da72c3
child 240843 6595ccb73af6
push id7672
push userrgiles@mozilla.com
push dateMon, 23 Feb 2015 06:50:33 +0000
treeherdermozilla-aurora@d8e630336213 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskarlt, lmandel
bugs1092915
milestone37.0a2
bug 1092915 modify mCurrentDecoder on main thread after RemoveDecoder r=karlt a=lmandel
dom/media/mediasource/TrackBuffer.cpp
dom/media/mediasource/TrackBuffer.h
--- a/dom/media/mediasource/TrackBuffer.cpp
+++ b/dom/media/mediasource/TrackBuffer.cpp
@@ -60,33 +60,16 @@ TrackBuffer::TrackBuffer(MediaSourceDeco
   MSE_DEBUG("TrackBuffer(%p) created for parent decoder %p", this, aParentDecoder);
 }
 
 TrackBuffer::~TrackBuffer()
 {
   MOZ_COUNT_DTOR(TrackBuffer);
 }
 
-class ReleaseDecoderTask : public nsRunnable {
-public:
-  explicit ReleaseDecoderTask(SourceBufferDecoder* aDecoder)
-    : mDecoder(aDecoder)
-  {
-  }
-
-  NS_IMETHOD Run() MOZ_OVERRIDE MOZ_FINAL {
-    mDecoder->GetReader()->BreakCycles();
-    mDecoder = nullptr;
-    return NS_OK;
-  }
-
-private:
-  nsRefPtr<SourceBufferDecoder> mDecoder;
-};
-
 class MOZ_STACK_CLASS DecodersToInitialize MOZ_FINAL {
 public:
   explicit DecodersToInitialize(TrackBuffer* aOwner)
     : mOwner(aOwner)
   {
   }
 
   ~DecodersToInitialize()
@@ -834,56 +817,77 @@ TrackBuffer::Dump(const char* aPath)
     PR_snprintf(buf, sizeof(buf), "%s/reader-%p", path, mDecoders[i]->GetReader());
     PR_MkDir(buf, 0700);
 
     mDecoders[i]->GetResource()->Dump(buf);
   }
 }
 #endif
 
+class ReleaseDecoderTask : public nsRunnable {
+public:
+  ReleaseDecoderTask(SourceBufferDecoder* aDecoder, TrackBuffer* aTrackBuffer)
+    : mDecoder(aDecoder)
+    , mTrackBuffer(aTrackBuffer)
+  {
+  }
+
+  NS_IMETHOD Run() MOZ_OVERRIDE MOZ_FINAL {
+    if (mTrackBuffer->mCurrentDecoder == mDecoder) {
+      mTrackBuffer->DiscardCurrentDecoder();
+    }
+
+    mDecoder->GetReader()->BreakCycles();
+    mDecoder = nullptr;
+    return NS_OK;
+  }
+
+private:
+  nsRefPtr<SourceBufferDecoder> mDecoder;
+  nsRefPtr<TrackBuffer> mTrackBuffer;
+};
+
 class DelayedDispatchToMainThread : public nsRunnable {
 public:
-  explicit DelayedDispatchToMainThread(SourceBufferDecoder* aDecoder)
+  DelayedDispatchToMainThread(SourceBufferDecoder* aDecoder, TrackBuffer* aTrackBuffer)
     : mDecoder(aDecoder)
+    , mTrackBuffer(aTrackBuffer)
   {
   }
 
   NS_IMETHOD Run() MOZ_OVERRIDE MOZ_FINAL {
     // Shutdown the reader, and remove its reference to the decoder
     // so that it can't accidentally read it after the decoder
     // is destroyed.
     mDecoder->GetReader()->Shutdown();
     mDecoder->GetReader()->ClearDecoder();
-    RefPtr<nsIRunnable> task = new ReleaseDecoderTask(mDecoder);
+    RefPtr<nsIRunnable> task = new ReleaseDecoderTask(mDecoder, mTrackBuffer);
     mDecoder = nullptr;
     // task now holds the only ref to the decoder.
     NS_DispatchToMainThread(task);
     return NS_OK;
   }
 
 private:
-  RefPtr<SourceBufferDecoder> mDecoder;
+  nsRefPtr<SourceBufferDecoder> mDecoder;
+  nsRefPtr<TrackBuffer> mTrackBuffer;
 };
 
 void
 TrackBuffer::RemoveDecoder(SourceBufferDecoder* aDecoder)
 {
-  RefPtr<nsIRunnable> task = new DelayedDispatchToMainThread(aDecoder);
-
+  MSE_DEBUG("TrackBuffer(%p)::RemoveDecoder(%p, %p)", this, aDecoder, aDecoder->GetReader());
+  RefPtr<nsIRunnable> task = new DelayedDispatchToMainThread(aDecoder, this);
   {
     ReentrantMonitorAutoEnter mon(mParentDecoder->GetReentrantMonitor());
     // There should be no other references to the decoder. Assert that
     // we aren't using it in the MediaSourceReader.
     MOZ_ASSERT(!mParentDecoder->IsActiveReader(aDecoder->GetReader()));
     mInitializedDecoders.RemoveElement(aDecoder);
     mDecoders.RemoveElement(aDecoder);
-
-    if (mCurrentDecoder == aDecoder) {
-      DiscardCurrentDecoder();
-    }
   }
   aDecoder->GetReader()->GetTaskQueue()->Dispatch(task);
 }
 
 bool
 TrackBuffer::RangeRemoval(int64_t aStart, int64_t aEnd)
 {
   MOZ_ASSERT(NS_IsMainThread());
--- a/dom/media/mediasource/TrackBuffer.h
+++ b/dom/media/mediasource/TrackBuffer.h
@@ -109,16 +109,17 @@ public:
 #endif
 
 #if defined(DEBUG)
   void Dump(const char* aPath);
 #endif
 
 private:
   friend class DecodersToInitialize;
+  friend class ReleaseDecoderTask;
   ~TrackBuffer();
 
   // Create a new decoder, set mCurrentDecoder to the new decoder and
   // returns it. The new decoder must be queued using QueueInitializeDecoder
   // for initialization.
   // The decoder is not considered initialized until it is added to
   // mInitializedDecoders.
   already_AddRefed<SourceBufferDecoder> NewDecoder(int64_t aTimestampOffset /* microseconds */);