Bug 1247189 - part2 : remove reference to TrackBuffersManagers once detached. draft
authorAlastor Wu <alwu@mozilla.com>
Wed, 11 Oct 2017 10:55:21 +0800
changeset 678303 c39e6eba4a9fea6f5b316c0b98457cc220fd723d
parent 678302 b2c1b804db5c4c3b99eb635b700d502ae70bf228
child 678304 cfefbd92ea67e466340852c8c097188babe0490d
child 678942 27a49e98782c152f169d948c247c9e9e504f7f81
push id83875
push useralwu@mozilla.com
push dateWed, 11 Oct 2017 03:02:08 +0000
bugs1247189
milestone58.0a1
Bug 1247189 - part2 : remove reference to TrackBuffersManagers once detached. Should never access the TrackBuffersManager once the SourceBuffer has been detached. MozReview-Commit-ID: EgVINj9B1vZ
dom/media/mediasource/MediaSourceDemuxer.cpp
dom/media/mediasource/MediaSourceDemuxer.h
--- a/dom/media/mediasource/MediaSourceDemuxer.cpp
+++ b/dom/media/mediasource/MediaSourceDemuxer.cpp
@@ -212,16 +212,22 @@ MediaSourceDemuxer::DoDetachSourceBuffer
     MonitorAutoLock mon(mMonitor);
     if (aSourceBuffer == mAudioTrack) {
       mAudioTrack = nullptr;
     }
     if (aSourceBuffer == mVideoTrack) {
       mVideoTrack = nullptr;
     }
   }
+
+  for (auto& demuxer : mDemuxers) {
+    if (demuxer->HasManager(aSourceBuffer)) {
+      demuxer->DetachManager();
+    }
+  }
   ScanSourceBuffersForContent();
 }
 
 TrackInfo*
 MediaSourceDemuxer::GetTrackInfo(TrackType aTrack)
 {
   MonitorAutoLock mon(mMonitor);
   switch (aTrack) {
@@ -346,16 +352,19 @@ void
 MediaSourceTrackDemuxer::Reset()
 {
   MOZ_ASSERT(mParent, "Called after BreackCycle()");
   RefPtr<MediaSourceTrackDemuxer> self = this;
   nsCOMPtr<nsIRunnable> task =
     NS_NewRunnableFunction("MediaSourceTrackDemuxer::Reset", [self]() {
       self->mNextSample.reset();
       self->mReset = true;
+      if (!self->mManager) {
+        return;
+      }
       self->mManager->Seek(self->mType, TimeUnit::Zero(), TimeUnit::Zero());
       {
         MonitorAutoLock mon(self->mMonitor);
         self->mNextRandomAccessPoint = self->mManager->GetNextRandomAccessPoint(
           self->mType, MediaSourceDemuxer::EOS_FUZZ);
       }
     });
   mParent->GetTaskQueue()->Dispatch(task.forget());
@@ -377,34 +386,42 @@ MediaSourceTrackDemuxer::SkipToNextRando
            mParent->GetTaskQueue(), this, __func__,
            &MediaSourceTrackDemuxer::DoSkipToNextRandomAccessPoint,
            aTimeThreshold);
 }
 
 media::TimeIntervals
 MediaSourceTrackDemuxer::GetBuffered()
 {
+  if (!mManager) {
+    return media::TimeIntervals();
+  }
   return mManager->Buffered();
 }
 
 void
 MediaSourceTrackDemuxer::BreakCycles()
 {
   RefPtr<MediaSourceTrackDemuxer> self = this;
   nsCOMPtr<nsIRunnable> task =
     NS_NewRunnableFunction("MediaSourceTrackDemuxer::BreakCycles", [self]() {
       self->mParent = nullptr;
-      self->mManager = nullptr;
+      self->DetachManager();
     });
   mParent->GetTaskQueue()->Dispatch(task.forget());
 }
 
 RefPtr<MediaSourceTrackDemuxer::SeekPromise>
 MediaSourceTrackDemuxer::DoSeek(const TimeUnit& aTime)
 {
+  if (!mManager) {
+    return SeekPromise::CreateAndReject(
+      MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
+                  RESULT_DETAIL("manager is detached.")), __func__);
+  }
   TimeIntervals buffered = mManager->Buffered(mType);
   // Fuzz factor represents a +/- threshold. So when seeking it allows the gap
   // to be twice as big as the fuzz value. We only want to allow EOS_FUZZ gap.
   buffered.SetFuzz(MediaSourceDemuxer::EOS_FUZZ / 2);
   TimeUnit seekTime = std::max(aTime - mPreRoll, TimeUnit::Zero());
 
   if (mManager->IsEnded() && seekTime >= buffered.GetEnd()) {
     // We're attempting to seek past the end time. Cap seekTime so that we seek
@@ -442,16 +459,21 @@ MediaSourceTrackDemuxer::DoSeek(const Ti
       mManager->GetNextRandomAccessPoint(mType, MediaSourceDemuxer::EOS_FUZZ);
   }
   return SeekPromise::CreateAndResolve(seekTime, __func__);
 }
 
 RefPtr<MediaSourceTrackDemuxer::SamplesPromise>
 MediaSourceTrackDemuxer::DoGetSamples(int32_t aNumSamples)
 {
+  if (!mManager) {
+    return SamplesPromise::CreateAndReject(
+      MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
+                  RESULT_DETAIL("manager is detached.")), __func__);
+  }
   if (mReset) {
     // If a seek (or reset) was recently performed, we ensure that the data
     // we are about to retrieve is still available.
     TimeIntervals buffered = mManager->Buffered(mType);
     buffered.SetFuzz(MediaSourceDemuxer::EOS_FUZZ / 2);
 
     if (!buffered.Length() && mManager->IsEnded()) {
       return SamplesPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_END_OF_STREAM,
@@ -490,16 +512,21 @@ MediaSourceTrackDemuxer::DoGetSamples(in
   }
   return SamplesPromise::CreateAndResolve(samples, __func__);
 }
 
 RefPtr<MediaSourceTrackDemuxer::SkipAccessPointPromise>
 MediaSourceTrackDemuxer::DoSkipToNextRandomAccessPoint(
   const TimeUnit& aTimeThreadshold)
 {
+  if (!mManager) {
+    return SkipAccessPointPromise::CreateAndReject(
+      SkipFailureHolder(MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
+                        RESULT_DETAIL("manager is detached.")), 0), __func__);
+  }
   uint32_t parsed = 0;
   // Ensure that the data we are about to skip to is still available.
   TimeIntervals buffered = mManager->Buffered(mType);
   buffered.SetFuzz(MediaSourceDemuxer::EOS_FUZZ / 2);
   if (buffered.ContainsWithStrictEnd(aTimeThreadshold)) {
     bool found;
     parsed = mManager->SkipToNextRandomAccessPoint(mType,
                                                    aTimeThreadshold,
@@ -510,9 +537,21 @@ MediaSourceTrackDemuxer::DoSkipToNextRan
     }
   }
   SkipFailureHolder holder(
     mManager->IsEnded() ? NS_ERROR_DOM_MEDIA_END_OF_STREAM :
                           NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA, parsed);
   return SkipAccessPointPromise::CreateAndReject(holder, __func__);
 }
 
+bool
+MediaSourceTrackDemuxer::HasManager(TrackBuffersManager* aManager) const
+{
+  return mManager == aManager;
+}
+
+void
+MediaSourceTrackDemuxer::DetachManager()
+{
+  mManager = nullptr;
+}
+
 } // namespace mozilla
--- a/dom/media/mediasource/MediaSourceDemuxer.h
+++ b/dom/media/mediasource/MediaSourceDemuxer.h
@@ -113,16 +113,19 @@ public:
 
   void BreakCycles() override;
 
   bool GetSamplesMayBlock() const override
   {
     return false;
   }
 
+  bool HasManager(TrackBuffersManager* aManager) const;
+  void DetachManager();
+
 private:
   RefPtr<SeekPromise> DoSeek(const media::TimeUnit& aTime);
   RefPtr<SamplesPromise> DoGetSamples(int32_t aNumSamples);
   RefPtr<SkipAccessPointPromise> DoSkipToNextRandomAccessPoint(
     const media::TimeUnit& aTimeThreadshold);
   already_AddRefed<MediaRawData> GetSample(MediaResult& aError);
   // Return the timestamp of the next keyframe after mLastSampleIndex.
   media::TimeUnit GetNextRandomAccessPoint();