Bug 1105066 - Chain seeks in MediaSourceReader so that we seek audio to the same time as video; r=kentuckyfriedtakahe
authorMatt Woodrow <mwoodrow@mozilla.com>
Mon, 12 Jan 2015 11:05:08 +1300
changeset 249007 db991158a2fed494e4d36093a620536470b6b6a7
parent 249006 f433e2cda30722dde9556bc96ab34a15dac6a6b1
child 249008 a0954dd9d40ae52531631bba4116f7531175d60d
push id4489
push userraliiev@mozilla.com
push dateMon, 23 Feb 2015 15:17:55 +0000
treeherdermozilla-beta@fd7c3dc24146 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskentuckyfriedtakahe
bugs1105066
milestone37.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 1105066 - Chain seeks in MediaSourceReader so that we seek audio to the same time as video; r=kentuckyfriedtakahe
dom/media/mediasource/MediaSourceReader.cpp
dom/media/mediasource/MediaSourceReader.h
--- a/dom/media/mediasource/MediaSourceReader.cpp
+++ b/dom/media/mediasource/MediaSourceReader.cpp
@@ -48,18 +48,16 @@ MediaSourceReader::MediaSourceReader(Med
   : MediaDecoderReader(aDecoder)
   , mLastAudioTime(0)
   , mLastVideoTime(0)
   , mPendingSeekTime(-1)
   , mPendingStartTime(-1)
   , mPendingEndTime(-1)
   , mPendingCurrentTime(-1)
   , mWaitingForSeekData(false)
-  , mPendingSeeks(0)
-  , mSeekResult(NS_OK)
   , mTimeThreshold(-1)
   , mDropAudioBeforeThreshold(false)
   , mDropVideoBeforeThreshold(false)
   , mEnded(false)
   , mAudioIsSeeking(false)
   , mVideoIsSeeking(false)
   , mHasEssentialTrackBuffers(false)
 #ifdef MOZ_FMP4
@@ -589,63 +587,58 @@ MediaSourceReader::Seek(int64_t aTime, i
   mPendingEndTime = aEndTime;
   mPendingCurrentTime = aCurrentTime;
 
   // Only increment the number of expected OnSeekCompleted
   // notifications if we weren't already waiting for AttemptSeek
   // to complete (and they would have been accounted for already).
   {
     ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
-
-    if (!mWaitingForSeekData) {
-      mWaitingForSeekData = true;
-      if (mAudioTrack) {
-        mPendingSeeks++;
-      }
-      if (mVideoTrack) {
-        mPendingSeeks++;
-      }
-    }
+    mWaitingForSeekData = true;
   }
 
   AttemptSeek();
   return p;
 }
 
 void
-MediaSourceReader::OnSeekCompleted(int64_t aTime)
+MediaSourceReader::OnVideoSeekCompleted(int64_t aTime)
 {
-  mPendingSeeks--;
-  FinalizeSeek();
+  mPendingSeekTime = aTime;
+  if (mAudioTrack) {
+    mAudioIsSeeking = true;
+    SwitchAudioReader(mPendingSeekTime);
+    mAudioReader->Seek(mPendingSeekTime,
+                       mPendingStartTime,
+                       mPendingEndTime,
+                       mPendingCurrentTime)
+                ->Then(GetTaskQueue(), __func__, this,
+                       &MediaSourceReader::OnAudioSeekCompleted,
+                       &MediaSourceReader::OnSeekFailed);
+    MSE_DEBUG("MediaSourceReader(%p)::Seek audio reader=%p", this, mAudioReader.get());
+    return;
+  }
+  mSeekPromise.Resolve(mPendingSeekTime, __func__);
+}
+
+void
+MediaSourceReader::OnAudioSeekCompleted(int64_t aTime)
+{
+  mSeekPromise.Resolve(mPendingSeekTime, __func__);
 }
 
 void
 MediaSourceReader::OnSeekFailed(nsresult aResult)
 {
-  mPendingSeeks--;
   // Keep the most recent failed result (if any)
   if (NS_FAILED(aResult)) {
-    mSeekResult = aResult;
+    mSeekPromise.Reject(aResult, __func__);
+    return;
   }
-  FinalizeSeek();
-}
-
-void
-MediaSourceReader::FinalizeSeek()
-{
-  // Only dispatch the final event onto the state machine
-  // since it's only expecting one response.
-  if (!mPendingSeeks) {
-    if (NS_FAILED(mSeekResult)) {
-      mSeekPromise.Reject(mSeekResult, __func__);
-    } else {
-      mSeekPromise.Resolve(mPendingSeekTime, __func__);
-    }
-    mSeekResult = NS_OK;
-  }
+  mSeekPromise.Resolve(mPendingSeekTime, __func__);
 }
 
 void
 MediaSourceReader::AttemptSeek()
 {
   // Make sure we don't hold the monitor while calling into the reader
   // Seek methods since it can deadlock.
   {
@@ -659,40 +652,31 @@ MediaSourceReader::AttemptSeek()
   for (uint32_t i = 0; i < mTrackBuffers.Length(); ++i) {
     mTrackBuffers[i]->ResetDecode();
   }
 
   // Decoding discontinuity upon seek, reset last times to seek target.
   mLastAudioTime = mPendingSeekTime;
   mLastVideoTime = mPendingSeekTime;
 
-  if (mAudioTrack) {
-    mAudioIsSeeking = true;
-    SwitchAudioReader(mPendingSeekTime);
-    mAudioReader->Seek(mPendingSeekTime,
-                       mPendingStartTime,
-                       mPendingEndTime,
-                       mPendingCurrentTime)
-                ->Then(GetTaskQueue(), __func__, this,
-                       &MediaSourceReader::OnSeekCompleted,
-                       &MediaSourceReader::OnSeekFailed);
-    MSE_DEBUG("MediaSourceReader(%p)::Seek audio reader=%p", this, mAudioReader.get());
-  }
   if (mVideoTrack) {
     mVideoIsSeeking = true;
     SwitchVideoReader(mPendingSeekTime);
     mVideoReader->Seek(mPendingSeekTime,
                        mPendingStartTime,
                        mPendingEndTime,
                        mPendingCurrentTime)
                 ->Then(GetTaskQueue(), __func__, this,
-                       &MediaSourceReader::OnSeekCompleted,
+                       &MediaSourceReader::OnVideoSeekCompleted,
                        &MediaSourceReader::OnSeekFailed);
     MSE_DEBUG("MediaSourceReader(%p)::Seek video reader=%p", this, mVideoReader.get());
+  } else {
+    OnVideoSeekCompleted(mPendingSeekTime);
   }
+
   {
     ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
     mWaitingForSeekData = false;
   }
 }
 
 nsresult
 MediaSourceReader::GetBuffered(dom::TimeRanges* aBuffered)
--- a/dom/media/mediasource/MediaSourceReader.h
+++ b/dom/media/mediasource/MediaSourceReader.h
@@ -53,17 +53,18 @@ public:
   virtual size_t SizeOfVideoQueueInFrames() MOZ_OVERRIDE;
   virtual size_t SizeOfAudioQueueInFrames() MOZ_OVERRIDE;
 
   void OnAudioDecoded(AudioData* aSample);
   void OnAudioNotDecoded(NotDecodedReason aReason);
   void OnVideoDecoded(VideoData* aSample);
   void OnVideoNotDecoded(NotDecodedReason aReason);
 
-  void OnSeekCompleted(int64_t aTime);
+  void OnVideoSeekCompleted(int64_t aTime);
+  void OnAudioSeekCompleted(int64_t aTime);
   void OnSeekFailed(nsresult aResult);
 
   virtual bool IsWaitForDataSupported() MOZ_OVERRIDE { return true; }
   virtual nsRefPtr<WaitForDataPromise> WaitForData(MediaData::Type aType) MOZ_OVERRIDE;
   void MaybeNotifyHaveData();
 
   bool HasVideo() MOZ_OVERRIDE
   {
@@ -139,17 +140,16 @@ private:
   // Return a reader from the set available in aTrackDecoders that has data
   // available in the range requested by aTarget.
   already_AddRefed<MediaDecoderReader> SelectReader(int64_t aTarget,
                                                     int64_t aError,
                                                     const nsTArray<nsRefPtr<SourceBufferDecoder>>& aTrackDecoders);
   bool HaveData(int64_t aTarget, MediaData::Type aType);
 
   void AttemptSeek();
-  void FinalizeSeek();
 
   nsRefPtr<MediaDecoderReader> mAudioReader;
   nsRefPtr<MediaDecoderReader> mVideoReader;
 
   nsTArray<nsRefPtr<TrackBuffer>> mTrackBuffers;
   nsTArray<nsRefPtr<TrackBuffer>> mShutdownTrackBuffers;
   nsTArray<nsRefPtr<TrackBuffer>> mEssentialTrackBuffers;
   nsRefPtr<TrackBuffer> mAudioTrack;
@@ -177,22 +177,16 @@ private:
   // to be added to the track buffer.
   MediaPromiseHolder<SeekPromise> mSeekPromise;
   int64_t mPendingSeekTime;
   int64_t mPendingStartTime;
   int64_t mPendingEndTime;
   int64_t mPendingCurrentTime;
   bool mWaitingForSeekData;
 
-  // Number of outstanding OnSeekCompleted notifications
-  // we're expecting to get from child decoders, and the
-  // result we're going to forward onto our callback.
-  uint32_t mPendingSeeks;
-  nsresult mSeekResult;
-
   int64_t mTimeThreshold;
   bool mDropAudioBeforeThreshold;
   bool mDropVideoBeforeThreshold;
 
   bool mEnded;
 
   // For a seek to complete we need to send a sample with
   // the mDiscontinuity field set to true once we have the