bug 1092915 modify mCurrentDecoder on main thread after RemoveDecoder r=karlt
authorMatt Woodrow <mwoodrow@mozilla.com>
Wed, 11 Feb 2015 11:12:39 +1300
changeset 228575 1eed7ad9fbb7
parent 228574 beb74056ac2d
child 228576 88c4ddf14434
push id55458
push userktomlinson@mozilla.com
push dateWed, 11 Feb 2015 08:35:28 +0000
treeherdermozilla-inbound@88c4ddf14434 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskarlt
bugs1092915
milestone38.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 1092915 modify mCurrentDecoder on main thread after RemoveDecoder r=karlt
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()
@@ -837,56 +820,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 */);