Bug 1171311: P6. Use ProxyMediaCall and remove use of monitor. r=cpearce
authorJean-Yves Avenard <jyavenard@mozilla.com>
Fri, 12 Jun 2015 09:26:58 +1000
changeset 279306 13019071a4ab8a5d6adb0a20169968c5e80568df
parent 279305 34d1dedc56c42d4374f759f44eb380262a887d0e
child 279307 0628a6c3be527a5f1793e40c00668978670eebcd
push id4932
push userjlund@mozilla.com
push dateMon, 10 Aug 2015 18:23:06 +0000
treeherdermozilla-beta@6dd5a4f5f745 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscpearce
bugs1171311
milestone41.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 1171311: P6. Use ProxyMediaCall and remove use of monitor. r=cpearce
dom/media/mediasource/MediaSourceDemuxer.cpp
dom/media/mediasource/MediaSourceDemuxer.h
--- a/dom/media/mediasource/MediaSourceDemuxer.cpp
+++ b/dom/media/mediasource/MediaSourceDemuxer.cpp
@@ -23,43 +23,40 @@ MediaSourceDemuxer::MediaSourceDemuxer()
   , mMonitor("MediaSourceDemuxer")
 {
   MOZ_ASSERT(NS_IsMainThread());
 }
 
 nsRefPtr<MediaSourceDemuxer::InitPromise>
 MediaSourceDemuxer::Init()
 {
-  nsRefPtr<InitPromise> p = mInitPromise.Ensure(__func__);
-
-  nsCOMPtr<nsIRunnable> task =
-    NS_NewRunnableMethod(this, &MediaSourceDemuxer::AttemptInit);
-  GetTaskQueue()->Dispatch(task.forget());
-
-  return p;
+  return ProxyMediaCall(GetTaskQueue(), this, __func__,
+                        &MediaSourceDemuxer::AttemptInit);
 }
 
-void
+nsRefPtr<MediaSourceDemuxer::InitPromise>
 MediaSourceDemuxer::AttemptInit()
 {
   MOZ_ASSERT(OnTaskQueue());
-  MonitorAutoLock mon(mMonitor);
+
   ScanSourceBuffersForContent();
 
   if (mInfo.HasAudio() || mInfo.HasVideo()) {
-    mInitPromise.Resolve(NS_OK, __func__);
-  } else {
-    mInitPromise.Reject(DemuxerFailureReason::WAITING_FOR_DATA, __func__);
+    return InitPromise::CreateAndResolve(NS_OK, __func__);
   }
+  return InitPromise::CreateAndReject(DemuxerFailureReason::WAITING_FOR_DATA,
+                                      __func__);
 }
 
 void
 MediaSourceDemuxer::ScanSourceBuffersForContent()
 {
-  mMonitor.AssertCurrentThreadOwns();
+  MOZ_ASSERT(OnTaskQueue());
+
+  MonitorAutoLock mon(mMonitor);
 
   for (const auto& sourceBuffer : mSourceBuffers) {
     MediaInfo info = sourceBuffer->GetMetadata();
     if (info.HasAudio() && !mAudioTrack) {
       mInfo.mAudio = info.mAudio;
       mAudioTrack = sourceBuffer;
     }
     if (info.HasVideo() && !mVideoTrack) {
@@ -71,16 +68,17 @@ MediaSourceDemuxer::ScanSourceBuffersFor
     }
   }
 }
 
 bool
 MediaSourceDemuxer::HasTrackType(TrackType aType) const
 {
   MonitorAutoLock mon(mMonitor);
+
   switch (aType) {
     case TrackType::kAudioTrack:
       return mInfo.HasAudio();
     case TrackType::kVideoTrack:
       return mInfo.HasVideo();
     default:
       return false;
   }
@@ -128,25 +126,45 @@ MediaSourceDemuxer::NotifyTimeRangesChan
   for (uint32_t i = 0; i < mDemuxers.Length(); i++) {
     mDemuxers[i]->NotifyTimeRangesChanged();
   }
 }
 
 void
 MediaSourceDemuxer::AttachSourceBuffer(TrackBuffersManager* aSourceBuffer)
 {
-  MonitorAutoLock mon(mMonitor);
+  nsCOMPtr<nsIRunnable> task =
+    NS_NewRunnableMethodWithArg<TrackBuffersManager*>(
+      this, &MediaSourceDemuxer::DoAttachSourceBuffer,
+      aSourceBuffer);
+  GetTaskQueue()->Dispatch(task.forget());
+}
+
+void
+MediaSourceDemuxer::DoAttachSourceBuffer(mozilla::TrackBuffersManager* aSourceBuffer)
+{
+  MOZ_ASSERT(OnTaskQueue());
   mSourceBuffers.AppendElement(aSourceBuffer);
   ScanSourceBuffersForContent();
 }
 
 void
 MediaSourceDemuxer::DetachSourceBuffer(TrackBuffersManager* aSourceBuffer)
 {
-  MonitorAutoLock mon(mMonitor);
+  nsCOMPtr<nsIRunnable> task =
+    NS_NewRunnableMethodWithArg<TrackBuffersManager*>(
+      this, &MediaSourceDemuxer::DoDetachSourceBuffer,
+      aSourceBuffer);
+  GetTaskQueue()->Dispatch(task.forget());
+}
+
+void
+MediaSourceDemuxer::DoDetachSourceBuffer(TrackBuffersManager* aSourceBuffer)
+{
+  MOZ_ASSERT(OnTaskQueue());
   for (uint32_t i = 0; i < mSourceBuffers.Length(); i++) {
     if (mSourceBuffers[i].get() == aSourceBuffer) {
       mSourceBuffers.RemoveElementAt(i);
     }
   }
   if (aSourceBuffer == mAudioTrack) {
     mAudioTrack = nullptr;
   }
@@ -192,81 +210,73 @@ MediaSourceDemuxer::~MediaSourceDemuxer(
 
 MediaSourceTrackDemuxer::MediaSourceTrackDemuxer(MediaSourceDemuxer* aParent,
                                                  TrackInfo::TrackType aType,
                                                  TrackBuffersManager* aManager)
   : mParent(aParent)
   , mManager(aManager)
   , mType(aType)
   , mNextSampleIndex(0)
-  , mDetached(false)
+  , mMonitor("MediaSourceTrackDemuxer")
 {
 }
 
 UniquePtr<TrackInfo>
 MediaSourceTrackDemuxer::GetInfo() const
 {
   return mParent->GetTrackInfo(mType)->Clone();
 }
 
 nsRefPtr<MediaSourceTrackDemuxer::SeekPromise>
 MediaSourceTrackDemuxer::Seek(media::TimeUnit aTime)
 {
-  nsRefPtr<SeekPromise> p = mSeekPromise.Ensure(__func__);
-
-  nsCOMPtr<nsIRunnable> task =
-    NS_NewRunnableMethodWithArg<TimeUnit>(
-      this, &MediaSourceTrackDemuxer::DoSeek, aTime);
-  mParent->GetTaskQueue()->Dispatch(task.forget());
-
-  return p;
+  MOZ_ASSERT(mParent, "Called after BreackCycle()");
+  return ProxyMediaCall(mParent->GetTaskQueue(), this, __func__,
+                        &MediaSourceTrackDemuxer::DoSeek, aTime);
 }
 
 nsRefPtr<MediaSourceTrackDemuxer::SamplesPromise>
 MediaSourceTrackDemuxer::GetSamples(int32_t aNumSamples)
 {
-  nsRefPtr<SamplesPromise> p = mSamplePromise.Ensure(__func__);
-
-  nsCOMPtr<nsIRunnable> task =
-    NS_NewRunnableMethodWithArg<int32_t>(
-      this, &MediaSourceTrackDemuxer::DoGetSamples, aNumSamples);
-  mParent->GetTaskQueue()->Dispatch(task.forget());
-
-  return p;
+  MOZ_ASSERT(mParent, "Called after BreackCycle()");
+  return ProxyMediaCall(mParent->GetTaskQueue(), this, __func__,
+                        &MediaSourceTrackDemuxer::DoGetSamples, aNumSamples);
 }
 
 void
 MediaSourceTrackDemuxer::Reset()
 {
-  mSamplePromise.RejectIfExists(DemuxerFailureReason::CANCELED, __func__);
-  mSkipPromise.RejectIfExists(SkipFailureHolder(DemuxerFailureReason::CANCELED, 0), __func__);
-  mSeekPromise.RejectIfExists(DemuxerFailureReason::CANCELED, __func__);
+  MOZ_ASSERT(mParent, "Called after BreackCycle()");
+  nsRefPtr<MediaSourceTrackDemuxer> self = this;
   nsCOMPtr<nsIRunnable> task =
-    NS_NewRunnableMethod(this, &MediaSourceTrackDemuxer::DoReset);
+    NS_NewRunnableFunction([self] () {
+      self->mNextSampleTime = TimeUnit();
+      self->mNextSampleIndex = 0;
+      {
+        MonitorAutoLock mon(self->mMonitor);
+        self->mNextRandomAccessPoint = self->GetNextRandomAccessPoint();
+      }
+    });
   mParent->GetTaskQueue()->Dispatch(task.forget());
 }
 
 nsresult
 MediaSourceTrackDemuxer::GetNextRandomAccessPoint(media::TimeUnit* aTime)
 {
+  MonitorAutoLock mon(mMonitor);
   *aTime = mNextRandomAccessPoint;
   return NS_OK;
 }
 
 nsRefPtr<MediaSourceTrackDemuxer::SkipAccessPointPromise>
 MediaSourceTrackDemuxer::SkipToNextRandomAccessPoint(media::TimeUnit aTimeThreshold)
 {
-  nsRefPtr<SkipAccessPointPromise> p = mSkipPromise.Ensure(__func__);
-
-  nsCOMPtr<nsIRunnable> task =
-    NS_NewRunnableMethodWithArg<TimeUnit>(
-      this, &MediaSourceTrackDemuxer::DoSkipToNextRandomAccessPoint, aTimeThreshold);
-  mParent->GetTaskQueue()->Dispatch(task.forget());
-
-  return p;
+  return ProxyMediaCall(mParent->GetTaskQueue(), this, __func__,
+                        &MediaSourceTrackDemuxer::DoSkipToNextRandomAccessPoint,
+                        aTimeThreshold);
 }
 
 int64_t
 MediaSourceTrackDemuxer::GetEvictionOffset(media::TimeUnit aTime)
 {
   // Unused.
   return 0;
 }
@@ -275,105 +285,95 @@ media::TimeIntervals
 MediaSourceTrackDemuxer::GetBuffered()
 {
   return mManager->Buffered();
 }
 
 void
 MediaSourceTrackDemuxer::BreakCycles()
 {
-  mDetached = true;
-  mParent = nullptr;
-  mManager = nullptr;
+  nsRefPtr<MediaSourceTrackDemuxer> self = this;
+  nsCOMPtr<nsIRunnable> task =
+    NS_NewRunnableFunction([self]() { self->mParent = nullptr; } );
+  mParent->GetTaskQueue()->Dispatch(task.forget());
 }
 
-void
-MediaSourceTrackDemuxer::DoSeek(const media::TimeUnit& aTime)
+nsRefPtr<MediaSourceTrackDemuxer::SeekPromise>
+MediaSourceTrackDemuxer::DoSeek(media::TimeUnit aTime)
 {
-  MOZ_ASSERT(mParent->OnTaskQueue());
-  if (mSeekPromise.IsEmpty()) {
-    // Got reset.
-    return;
-  }
-  const TrackBuffersManager::TrackBuffer& track = mManager->GetTrackBuffer(mType);
+  const TrackBuffersManager::TrackBuffer& track =
+    mManager->GetTrackBuffer(mType);
   TimeUnit lastKeyFrameTime;
   uint32_t lastKeyFrameIndex = 0;
   for (uint32_t i = 0; i < track.Length(); i++) {
     const nsRefPtr<MediaRawData>& sample = track[i];
     if (sample->mKeyframe) {
       lastKeyFrameTime = TimeUnit::FromMicroseconds(sample->mTime);
       lastKeyFrameIndex = i;
     }
     if (sample->mTime >= aTime.ToMicroseconds()) {
       break;
     }
   }
   mNextSampleIndex = lastKeyFrameIndex;
   mNextSampleTime = lastKeyFrameTime;
-  mNextRandomAccessPoint = GetNextRandomAccessPoint();
-  mSeekPromise.ResolveIfExists(mNextSampleTime, __func__);
+  {
+    MonitorAutoLock mon(mMonitor);
+    mNextRandomAccessPoint = GetNextRandomAccessPoint();
+  }
+  return SeekPromise::CreateAndResolve(mNextSampleTime, __func__);
 }
 
-void
+nsRefPtr<MediaSourceTrackDemuxer::SamplesPromise>
 MediaSourceTrackDemuxer::DoGetSamples(int32_t aNumSamples)
 {
-  MOZ_ASSERT(mParent->OnTaskQueue());
-  if (mSamplePromise.IsEmpty()) {
-    // Got reset.
-    return;
-  }
-
   DemuxerFailureReason failure;
   nsRefPtr<MediaRawData> sample = GetSample(failure);
-  if (sample) {
-    nsRefPtr<SamplesHolder> samples = new SamplesHolder;
-    samples->mSamples.AppendElement(sample);
+  if (!sample) {
+    return SamplesPromise::CreateAndReject(failure, __func__);
+  }
+  nsRefPtr<SamplesHolder> samples = new SamplesHolder;
+  samples->mSamples.AppendElement(sample);
+  {
+    MonitorAutoLock mon(mMonitor);
     mNextRandomAccessPoint = GetNextRandomAccessPoint();
-    mSamplePromise.ResolveIfExists(samples, __func__);
-  } else {
-    mSamplePromise.RejectIfExists(failure, __func__);
   }
+  return SamplesPromise::CreateAndResolve(samples, __func__);
 }
 
-void
-MediaSourceTrackDemuxer::DoSkipToNextRandomAccessPoint(const media::TimeUnit& aTimeThreadshold)
+nsRefPtr<MediaSourceTrackDemuxer::SkipAccessPointPromise>
+MediaSourceTrackDemuxer::DoSkipToNextRandomAccessPoint(media::TimeUnit aTimeThreadshold)
 {
-  MOZ_ASSERT(mParent->OnTaskQueue());
-  if (mSkipPromise.IsEmpty()) {
-    // Got reset.
-    return;
-  }
   bool found = false;
   int32_t parsed = 0;
   const TrackBuffersManager::TrackBuffer& track =
     mManager->GetTrackBuffer(mType);
   for (uint32_t i = mNextSampleIndex; i < track.Length(); i++) {
     const nsRefPtr<MediaRawData>& sample = track[i];
-    if (sample->mKeyframe && sample->mTime >= aTimeThreadshold.ToMicroseconds()) {
+    if (sample->mKeyframe &&
+        sample->mTime >= aTimeThreadshold.ToMicroseconds()) {
       mNextSampleTime = TimeUnit::FromMicroseconds(sample->GetEndTime());
       found = true;
       break;
     }
     parsed++;
   }
 
   if (found) {
-    mSkipPromise.ResolveIfExists(parsed, __func__);
-  } else {
-    SkipFailureHolder holder(
-      mManager->IsEnded() ? DemuxerFailureReason::END_OF_STREAM :
-                            DemuxerFailureReason::WAITING_FOR_DATA, parsed);
-    mSkipPromise.RejectIfExists(holder, __func__);
+    return SkipAccessPointPromise::CreateAndResolve(parsed, __func__);
   }
+  SkipFailureHolder holder(
+    mManager->IsEnded() ? DemuxerFailureReason::END_OF_STREAM :
+                          DemuxerFailureReason::WAITING_FOR_DATA, parsed);
+  return SkipAccessPointPromise::CreateAndReject(holder, __func__);
 }
 
 already_AddRefed<MediaRawData>
 MediaSourceTrackDemuxer::GetSample(DemuxerFailureReason& aFailure)
 {
-  MOZ_ASSERT(mParent->OnTaskQueue());
   const TrackBuffersManager::TrackBuffer& track =
     mManager->GetTrackBuffer(mType);
   const TimeIntervals& ranges = mManager->Buffered(mType);
   if (mNextSampleTime >= ranges.GetEnd()) {
     if (mManager->IsEnded()) {
       aFailure = DemuxerFailureReason::END_OF_STREAM;
     } else {
       aFailure = DemuxerFailureReason::WAITING_FOR_DATA;
@@ -415,42 +415,29 @@ MediaSourceTrackDemuxer::GetSample(Demux
   }
   aFailure = DemuxerFailureReason::DEMUXER_ERROR;
   return nullptr;
 }
 
 TimeUnit
 MediaSourceTrackDemuxer::GetNextRandomAccessPoint()
 {
-  MOZ_ASSERT(mParent->OnTaskQueue());
   const TrackBuffersManager::TrackBuffer& track = mManager->GetTrackBuffer(mType);
   for (uint32_t i = mNextSampleIndex; i < track.Length(); i++) {
     const nsRefPtr<MediaRawData>& sample = track[i];
     if (sample->mKeyframe) {
       return TimeUnit::FromMicroseconds(sample->mTime);
     }
   }
   return media::TimeUnit::FromInfinity();
 }
 
 void
 MediaSourceTrackDemuxer::NotifyTimeRangesChanged()
 {
-  if (mDetached) {
+  if (!mParent) {
     return;
   }
   MOZ_ASSERT(mParent->OnTaskQueue());
   mNextSampleIndex = 0;
 }
 
-void
-MediaSourceTrackDemuxer::DoReset()
-{
-  if (mDetached) {
-    return;
-  }
-  MOZ_ASSERT(mParent->OnTaskQueue());
-  mNextSampleTime = TimeUnit();
-  mNextRandomAccessPoint = TimeUnit();
-  mNextSampleIndex = 0;
-}
-
 } // namespace mozilla
--- a/dom/media/mediasource/MediaSourceDemuxer.h
+++ b/dom/media/mediasource/MediaSourceDemuxer.h
@@ -55,34 +55,36 @@ public:
   MediaTaskQueue* GetTaskQueue() { return mTaskQueue; }
   void NotifyTimeRangesChanged();
 
 private:
   ~MediaSourceDemuxer();
   friend class MediaSourceTrackDemuxer;
   // Scan source buffers and update information. Must own lock.
   void ScanSourceBuffersForContent();
-  void AttemptInit();
+  nsRefPtr<InitPromise> AttemptInit();
   TrackBuffersManager* GetManager(TrackInfo::TrackType aType);
   TrackInfo* GetTrackInfo(TrackInfo::TrackType);
+  void DoAttachSourceBuffer(TrackBuffersManager* aSourceBuffer);
+  void DoDetachSourceBuffer(TrackBuffersManager* aSourceBuffer);
   bool OnTaskQueue()
   {
     return !GetTaskQueue() || GetTaskQueue()->IsCurrentThreadIn();
   }
 
   RefPtr<MediaTaskQueue> mTaskQueue;
   nsTArray<nsRefPtr<MediaSourceTrackDemuxer>> mDemuxers;
-  MediaPromiseHolder<InitPromise> mInitPromise;
+
+  nsTArray<nsRefPtr<TrackBuffersManager>> mSourceBuffers;
 
   // Monitor to protect members below across multiple threads.
   mutable Monitor mMonitor;
-  MediaInfo mInfo;
-  nsTArray<nsRefPtr<TrackBuffersManager>> mSourceBuffers;
   nsRefPtr<TrackBuffersManager> mAudioTrack;
   nsRefPtr<TrackBuffersManager> mVideoTrack;
+  MediaInfo mInfo;
 };
 
 class MediaSourceTrackDemuxer : public MediaTrackDemuxer
 {
 public:
   MediaSourceTrackDemuxer(MediaSourceDemuxer* aParent,
                           TrackInfo::TrackType aType,
                           TrackBuffersManager* aManager);
@@ -105,31 +107,28 @@ public:
 
   void BreakCycles() override;
 
   // Called by TrackBuffersManager to indicate that new frames were added or
   // removed.
   void NotifyTimeRangesChanged();
 
 private:
-  void DoReset();
-  void DoSeek(const media::TimeUnit& aTime);
-  void DoGetSamples(int32_t aNumSamples);
-  void DoSkipToNextRandomAccessPoint(const TimeUnit& aTimeThreadshold);
+  nsRefPtr<SeekPromise> DoSeek(media::TimeUnit aTime);
+  nsRefPtr<SamplesPromise> DoGetSamples(int32_t aNumSamples);
+  nsRefPtr<SkipAccessPointPromise> DoSkipToNextRandomAccessPoint(TimeUnit aTimeThreadshold);
   already_AddRefed<MediaRawData> GetSample(DemuxerFailureReason& aFailure);
   // Return the timestamp of the next keyframe after mLastSampleIndex.
   TimeUnit GetNextRandomAccessPoint();
 
   nsRefPtr<MediaSourceDemuxer> mParent;
   nsRefPtr<TrackBuffersManager> mManager;
   TrackInfo::TrackType mType;
   uint32_t mNextSampleIndex;
   media::TimeUnit mNextSampleTime;
+  // Monitor protecting members below accessed from multiple threads.
+  Monitor mMonitor;
   media::TimeUnit mNextRandomAccessPoint;
-  MediaPromiseHolder<SeekPromise> mSeekPromise;
-  MediaPromiseHolder<SamplesPromise> mSamplePromise;
-  MediaPromiseHolder<SkipAccessPointPromise> mSkipPromise;
-  Atomic<bool> mDetached;
 };
 
 } // namespace mozilla
 
 #endif