Bug 1274192 part 2 - make MDSM and SeekTask to adopt new MediaDecoderReaderWrapper API; r=jwwang draft
authorKaku Kuo <tkuo@mozilla.com>
Thu, 19 May 2016 19:02:20 +0800
changeset 369083 73a67b50aee6d0446b99675184f2a37ebf74a5b1
parent 369082 fb8f2e5a3578cc19cba610bd8c9c4cb210653c6e
child 521456 4fc724f6ab028ac07f0bd9d113655a5c83bbc607
push id18730
push usertkuo@mozilla.com
push dateFri, 20 May 2016 07:31:38 +0000
reviewersjwwang
bugs1274192
milestone49.0a1
Bug 1274192 part 2 - make MDSM and SeekTask to adopt new MediaDecoderReaderWrapper API; r=jwwang MozReview-Commit-ID: 36QOhD3Hc2f
dom/media/MediaDecoderReaderWrapper.cpp
dom/media/MediaDecoderReaderWrapper.h
dom/media/MediaDecoderStateMachine.cpp
dom/media/MediaDecoderStateMachine.h
dom/media/SeekTask.cpp
dom/media/SeekTask.h
--- a/dom/media/MediaDecoderReaderWrapper.cpp
+++ b/dom/media/MediaDecoderReaderWrapper.cpp
@@ -324,22 +324,51 @@ MediaDecoderReaderWrapper::Seek(SeekTarg
 {
   MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
   aTarget.SetTime(aTarget.GetTime() + StartTime());
   return InvokeAsync(mReader->OwnerThread(), mReader.get(), __func__,
                      &MediaDecoderReader::Seek, aTarget,
                      aEndTime.ToMicroseconds());
 }
 
-RefPtr<MediaDecoderReaderWrapper::WaitForDataPromise>
+void
 MediaDecoderReaderWrapper::WaitForData(MediaData::Type aType)
 {
   MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
-  return InvokeAsync(mReader->OwnerThread(), mReader.get(), __func__,
-                     &MediaDecoderReader::WaitForData, aType);
+  MOZ_ASSERT(WaitCallbackRef(aType));
+
+  auto p = InvokeAsync(mReader->OwnerThread(), mReader.get(), __func__,
+                       &MediaDecoderReader::WaitForData, aType);
+
+  RefPtr<MediaDecoderReaderWrapper> self = this;
+  WaitRequestRef(aType).Begin(p->Then(mOwnerThread, __func__,
+    [self] (MediaData::Type aType) {
+      MOZ_ASSERT(self->WaitCallbackRef(aType));
+      self->WaitRequestRef(aType).Complete();
+      self->WaitCallbackRef(aType)->OnResolved(aType);
+    },
+    [self, aType] (WaitForDataRejectValue aRejection) {
+      MOZ_ASSERT(self->WaitCallbackRef(aType));
+      self->WaitRequestRef(aType).Complete();
+      self->WaitCallbackRef(aType)->OnRejected(aRejection);
+    }));
+}
+
+UniquePtr<MediaDecoderReaderWrapper::WaitForDataCallbackBase>&
+MediaDecoderReaderWrapper::WaitCallbackRef(MediaData::Type aType)
+{
+  MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
+  return aType == MediaData::AUDIO_DATA ? mWaitAudioDataCB : mWaitVideoDataCB;
+}
+
+MozPromiseRequestHolder<MediaDecoderReader::WaitForDataPromise>&
+MediaDecoderReaderWrapper::WaitRequestRef(MediaData::Type aType)
+{
+  MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
+  return aType == MediaData::AUDIO_DATA ? mAudioWaitRequest : mVideoWaitRequest;
 }
 
 RefPtr<MediaDecoderReaderWrapper::BufferedUpdatePromise>
 MediaDecoderReaderWrapper::UpdateBufferedWithPromise()
 {
   MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
   return InvokeAsync(mReader->OwnerThread(), mReader.get(), __func__,
                      &MediaDecoderReader::UpdateBufferedWithPromise);
--- a/dom/media/MediaDecoderReaderWrapper.h
+++ b/dom/media/MediaDecoderReaderWrapper.h
@@ -361,23 +361,25 @@ public:
   void CancelVideoCallback(CallbackID aID);
   void CancelWaitAudioCallback(CallbackID aID);
   void CancelWaitVideoCallback(CallbackID aID);
 
   // NOTE: please set callbacks before requesting audio/video data!
   void RequestAudioData();
   void RequestVideoData(bool aSkipToNextKeyframe, media::TimeUnit aTimeThreshold);
 
+  // NOTE: please set callbacks before invoking WaitForData()!
+  void WaitForData(MediaData::Type aType);
+
   bool IsRequestingAudioData() const;
   bool IsRequestingVideoData() const;
   bool IsWaitingAudioData() const;
   bool IsWaitingVideoData() const;
 
   RefPtr<SeekPromise> Seek(SeekTarget aTarget, media::TimeUnit aEndTime);
-  RefPtr<WaitForDataPromise> WaitForData(MediaData::Type aType);
   RefPtr<BufferedUpdatePromise> UpdateBufferedWithPromise();
   RefPtr<ShutdownPromise> Shutdown();
 
   void ReleaseMediaResources();
   void SetIdle();
   void ResetDecode(TargetQueues aQueues);
 
   nsresult Init() { return mReader->Init(); }
@@ -423,16 +425,19 @@ private:
 
   void OnMetadataRead(MetadataHolder* aMetadata);
   void OnMetadataNotRead() {}
   void OnSampleDecoded(CallbackBase* aCallback, MediaData* aSample,
                        TimeStamp aVideoDecodeStartTime);
   void OnNotDecoded(CallbackBase* aCallback,
                     MediaDecoderReader::NotDecodedReason aReason);
 
+  UniquePtr<WaitForDataCallbackBase>& WaitCallbackRef(MediaData::Type aType);
+  MozPromiseRequestHolder<WaitForDataPromise>& WaitRequestRef(MediaData::Type aType);
+
   const bool mForceZeroStartTime;
   const RefPtr<AbstractThread> mOwnerThread;
   const RefPtr<MediaDecoderReader> mReader;
 
   bool mShutdown = false;
   RefPtr<StartTimeRendezvous> mStartTimeRendezvous;
 
   UniquePtr<CallbackBase> mRequestAudioDataCB;
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -691,31 +691,17 @@ MediaDecoderStateMachine::OnNotDecoded(M
     return;
   }
 
   // If the decoder is waiting for data, we tell it to call us back when the
   // data arrives.
   if (aReason == MediaDecoderReader::WAITING_FOR_DATA) {
     MOZ_ASSERT(mReader->IsWaitForDataSupported(),
                "Readers that send WAITING_FOR_DATA need to implement WaitForData");
-    RefPtr<MediaDecoderStateMachine> self = this;
-    WaitRequestRef(aType).Begin(
-      mReader->WaitForData(aType)
-      ->Then(OwnerThread(), __func__,
-             [self] (MediaData::Type aType) -> void {
-               self->WaitRequestRef(aType).Complete();
-               if (aType == MediaData::AUDIO_DATA) {
-                 self->EnsureAudioDecodeTaskQueued();
-               } else {
-                 self->EnsureVideoDecodeTaskQueued();
-               }
-             },
-             [self] (WaitForDataRejectValue aRejection) -> void {
-               self->WaitRequestRef(aRejection.mType).Complete();
-             }));
+    mReader->WaitForData(aType);
 
     // We are out of data to decode and will enter buffering mode soon.
     // We want to play the frames we have already decoded, so we stop pre-rolling
     // and ensure that loadeddata is fired as required.
     if (isAudio) {
       StopPrerollingAudio();
     } else {
       StopPrerollingVideo();
@@ -934,28 +920,51 @@ MediaDecoderStateMachine::SetMediaDecode
                               &MediaDecoderStateMachine::OnAudioDecoded,
                               &MediaDecoderStateMachine::OnAudioNotDecoded);
 
   mVideoCallbackID =
     mReader->SetVideoCallback(this,
                               &MediaDecoderStateMachine::OnVideoDecoded,
                               &MediaDecoderStateMachine::OnVideoNotDecoded);
 
+  RefPtr<MediaDecoderStateMachine> self = this;
+  mWaitAudioCallbackID =
+    mReader->SetWaitAudioCallback(
+      [self] (MediaData::Type aType) -> void {
+        self->EnsureAudioDecodeTaskQueued();
+      },
+      [self] (WaitForDataRejectValue aRejection) -> void {});
+
+  mWaitVideoCallbackID =
+    mReader->SetWaitVideoCallback(
+      [self] (MediaData::Type aType) -> void {
+        self->EnsureVideoDecodeTaskQueued();
+      },
+      [self] (WaitForDataRejectValue aRejection) -> void {});
+
   DECODER_LOG("MDSM set audio callbacks: mAudioCallbackID = %d\n", (int)mAudioCallbackID);
   DECODER_LOG("MDSM set video callbacks: mVideoCallbackID = %d\n", (int)mVideoCallbackID);
+  DECODER_LOG("MDSM set wait audio callbacks: mWaitAudioCallbackID = %d\n", (int)mWaitAudioCallbackID);
+  DECODER_LOG("MDSM set wait video callbacks: mWaitVideoCallbackID = %d\n", (int)mWaitVideoCallbackID);
 }
 
 void
 MediaDecoderStateMachine::CancelMediaDecoderReaderWrapperCallback()
 {
     DECODER_LOG("MDSM cancel audio callbacks: mVideoCallbackID = %d\n", (int)mAudioCallbackID);
     mReader->CancelAudioCallback(mAudioCallbackID);
 
     DECODER_LOG("MDSM cancel video callbacks: mVideoCallbackID = %d\n", (int)mVideoCallbackID);
     mReader->CancelVideoCallback(mVideoCallbackID);
+
+    DECODER_LOG("MDSM cancel wait audio callbacks: mWaitAudioCallbackID = %d\n", (int)mWaitAudioCallbackID);
+    mReader->CancelWaitAudioCallback(mWaitAudioCallbackID);
+
+    DECODER_LOG("MDSM cancel wait video callbacks: mWaitVideoCallbackID = %d\n", (int)mWaitVideoCallbackID);
+    mReader->CancelWaitVideoCallback(mWaitVideoCallbackID);
 }
 
 void MediaDecoderStateMachine::StopPlayback()
 {
   MOZ_ASSERT(OnTaskQueue());
   DECODER_LOG("StopPlayback()");
 
   mOnPlaybackEvent.Notify(MediaEventType::PlaybackStopped);
@@ -1011,18 +1020,18 @@ MediaDecoderStateMachine::MaybeStartBuff
       mPlayState == MediaDecoder::PLAY_STATE_PLAYING &&
       mResource->IsExpectingMoreData()) {
     bool shouldBuffer;
     if (mReader->UseBufferingHeuristics()) {
       shouldBuffer = HasLowDecodedData(EXHAUSTED_DATA_MARGIN_USECS) &&
                      (JustExitedQuickBuffering() || HasLowUndecodedData());
     } else {
       MOZ_ASSERT(mReader->IsWaitForDataSupported());
-      shouldBuffer = (OutOfDecodedAudio() && mAudioWaitRequest.Exists()) ||
-                     (OutOfDecodedVideo() && mVideoWaitRequest.Exists());
+      shouldBuffer = (OutOfDecodedAudio() && mReader->IsWaitingAudioData()) ||
+                     (OutOfDecodedVideo() && mReader->IsWaitingVideoData());
     }
     if (shouldBuffer) {
       StartBuffering();
       // Don't go straight back to the state machine loop since that might
       // cause us to start decoding again and we could flip-flop between
       // decoding and quick-buffering.
       ScheduleStateMachineIn(USECS_PER_S);
     }
@@ -1272,18 +1281,18 @@ void MediaDecoderStateMachine::StartDeco
   mDecodeStartTime = TimeStamp::Now();
 
   CheckIfDecodeComplete();
   if (mState == DECODER_STATE_COMPLETED) {
     return;
   }
 
   // Reset other state to pristine values before starting decode.
-  mIsAudioPrerolling = !DonePrerollingAudio() && !mAudioWaitRequest.Exists();
-  mIsVideoPrerolling = !DonePrerollingVideo() && !mVideoWaitRequest.Exists();
+  mIsAudioPrerolling = !DonePrerollingAudio() && !mReader->IsWaitingAudioData();
+  mIsVideoPrerolling = !DonePrerollingVideo() && !mReader->IsWaitingVideoData();
 
   // Ensure that we've got tasks enqueued to decode data if we need to.
   DispatchDecodeTasksIfNeeded();
 
   ScheduleStateMachine();
 }
 
 void MediaDecoderStateMachine::PlayStateChanged()
@@ -1702,17 +1711,17 @@ MediaDecoderStateMachine::EnsureAudioDec
               IsAudioDecoding(), AudioRequestStatus());
 
   if (mState != DECODER_STATE_DECODING &&
       mState != DECODER_STATE_BUFFERING) {
     return NS_OK;
   }
 
   if (!IsAudioDecoding() || mReader->IsRequestingAudioData() ||
-      mAudioWaitRequest.Exists()) {
+      mReader->IsWaitingAudioData()) {
     return NS_OK;
   }
 
   RequestAudioData();
   return NS_OK;
 }
 
 void
@@ -1760,17 +1769,17 @@ MediaDecoderStateMachine::EnsureVideoDec
   if (IsVideoDecodeSuspended() && !IsDecodingFirstFrame()) {
     // The element is invisible and background videos should be suspended.
     // If the first frame has already been decoded, don't request anymore video
     // frames.
     return NS_OK;
   }
 
   if (!IsVideoDecoding() || mReader->IsRequestingVideoData() ||
-      mVideoWaitRequest.Exists()) {
+      mReader->IsWaitingVideoData()) {
     return NS_OK;
   }
 
   RequestVideoData();
   return NS_OK;
 }
 
 void
@@ -2271,18 +2280,18 @@ nsresult MediaDecoderStateMachine::RunSt
                       (mQuickBuffering ? "(quick exit)" : ""));
           ScheduleStateMachineIn(USECS_PER_S);
           return NS_OK;
         }
       } else if (OutOfDecodedAudio() || OutOfDecodedVideo()) {
         MOZ_ASSERT(mReader->IsWaitForDataSupported(),
                    "Don't yet have a strategy for non-heuristic + non-WaitForData");
         DispatchDecodeTasksIfNeeded();
-        MOZ_ASSERT_IF(!mMinimizePreroll && OutOfDecodedAudio(), mReader->IsRequestingAudioData() || mAudioWaitRequest.Exists());
-        MOZ_ASSERT_IF(!mMinimizePreroll && OutOfDecodedVideo(), mReader->IsRequestingVideoData() || mVideoWaitRequest.Exists());
+        MOZ_ASSERT_IF(!mMinimizePreroll && OutOfDecodedAudio(), mReader->IsRequestingAudioData() || mReader->IsWaitingAudioData());
+        MOZ_ASSERT_IF(!mMinimizePreroll && OutOfDecodedVideo(), mReader->IsRequestingVideoData() || mReader->IsWaitingVideoData());
         DECODER_LOG("In buffering mode, waiting to be notified: outOfAudio: %d, "
                     "mAudioStatus: %s, outOfVideo: %d, mVideoStatus: %s",
                     OutOfDecodedAudio(), AudioRequestStatus(),
                     OutOfDecodedVideo(), VideoRequestStatus());
         return NS_OK;
       }
 
       DECODER_LOG("Changed state from BUFFERING to DECODING");
@@ -2357,27 +2366,25 @@ MediaDecoderStateMachine::Reset(MediaDec
   MOZ_ASSERT(IsShutdown() ||
              mState == DECODER_STATE_SEEKING ||
              mState == DECODER_STATE_DORMANT);
 
 
   mDecodedVideoEndTime = 0;
   mVideoCompleted = false;
   VideoQueue().Reset();
-  mVideoWaitRequest.DisconnectIfExists();
 
   if (aQueues == MediaDecoderReader::AUDIO_VIDEO) {
     // Stop the audio thread. Otherwise, MediaSink might be accessing AudioQueue
     // outside of the decoder monitor while we are clearing the queue and causes
     // crash for no samples to be popped.
     StopMediaSink();
     mDecodedAudioEndTime = 0;
     mAudioCompleted = false;
     AudioQueue().Reset();
-    mAudioWaitRequest.DisconnectIfExists();
   }
 
   mMetadataRequest.DisconnectIfExists();
   mSeekTaskRequest.DisconnectIfExists();
 
   mPlaybackOffset = 0;
 
   mReader->ResetDecode(aQueues);
@@ -2843,32 +2850,32 @@ MediaDecoderStateMachine::OnMediaNotSeek
   return mReader->OnMediaNotSeekable();
 }
 
 const char*
 MediaDecoderStateMachine::AudioRequestStatus() const
 {
   MOZ_ASSERT(OnTaskQueue());
   if (mReader->IsRequestingAudioData()) {
-    MOZ_DIAGNOSTIC_ASSERT(!mAudioWaitRequest.Exists());
+    MOZ_DIAGNOSTIC_ASSERT(!mReader->IsWaitingAudioData());
     return "pending";
-  } else if (mAudioWaitRequest.Exists()) {
+  } else if (mReader->IsWaitingAudioData()) {
     return "waiting";
   }
   return "idle";
 }
 
 const char*
 MediaDecoderStateMachine::VideoRequestStatus() const
 {
   MOZ_ASSERT(OnTaskQueue());
   if (mReader->IsRequestingVideoData()) {
-    MOZ_DIAGNOSTIC_ASSERT(!mVideoWaitRequest.Exists());
+    MOZ_DIAGNOSTIC_ASSERT(!mReader->IsWaitingVideoData());
     return "pending";
-  } else if (mVideoWaitRequest.Exists()) {
+  } else if (mReader->IsWaitingVideoData()) {
     return "waiting";
   }
   return "idle";
 }
 
 } // namespace mozilla
 
 // avoid redefined macro in unified build
--- a/dom/media/MediaDecoderStateMachine.h
+++ b/dom/media/MediaDecoderStateMachine.h
@@ -825,29 +825,23 @@ private:
   // being "prerolled".
   bool mIsAudioPrerolling;
   bool mIsVideoPrerolling;
 
   // Only one of a given pair of ({Audio,Video}DataPromise, WaitForDataPromise)
   // should exist at any given moment.
 
   CallbackID mAudioCallbackID;
-  MozPromiseRequestHolder<MediaDecoderReader::WaitForDataPromise> mAudioWaitRequest;
+  CallbackID mWaitAudioCallbackID;
   const char* AudioRequestStatus() const;
 
   CallbackID mVideoCallbackID;
-  MozPromiseRequestHolder<MediaDecoderReader::WaitForDataPromise> mVideoWaitRequest;
+  CallbackID mWaitVideoCallbackID;
   const char* VideoRequestStatus() const;
 
-  MozPromiseRequestHolder<MediaDecoderReader::WaitForDataPromise>& WaitRequestRef(MediaData::Type aType)
-  {
-    MOZ_ASSERT(OnTaskQueue());
-    return aType == MediaData::AUDIO_DATA ? mAudioWaitRequest : mVideoWaitRequest;
-  }
-
   // True if we shouldn't play our audio (but still write it to any capturing
   // streams). When this is true, the audio thread will never start again after
   // it has stopped.
   bool mAudioCaptured;
 
   // True if the audio playback thread has finished. It is finished
   // when either all the audio frames have completed playing, or we've moved
   // into shutdown state, and the threads are to be
--- a/dom/media/SeekTask.cpp
+++ b/dom/media/SeekTask.cpp
@@ -152,18 +152,16 @@ SeekTask::Discard()
   // Disconnect MediaDecoder.
   mSeekJob.RejectIfExists(__func__);
 
   // Disconnect MDSM.
   RejectIfExist(__func__);
 
   // Disconnect MediaDecoderReaderWrapper.
   mSeekRequest.DisconnectIfExists();
-  mAudioWaitRequest.DisconnectIfExists();
-  mVideoWaitRequest.DisconnectIfExists();
   CancelMediaDecoderReaderWrapperCallback();
 
   mIsDiscarded = true;
 }
 
 bool
 SeekTask::NeedToResetMDSM() const
 {
@@ -214,17 +212,17 @@ SeekTask::EnsureAudioDecodeTaskQueued()
 {
   AssertOwnerThread();
 
   SAMPLE_LOG("EnsureAudioDecodeTaskQueued isDecoding=%d status=%s",
               IsAudioDecoding(), AudioRequestStatus());
 
   if (!IsAudioDecoding() ||
       mReader->IsRequestingAudioData() ||
-      mAudioWaitRequest.Exists() ||
+      mReader->IsWaitingAudioData() ||
       mSeekRequest.Exists()) {
     return NS_OK;
   }
 
   RequestAudioData();
   return NS_OK;
 }
 
@@ -233,46 +231,46 @@ SeekTask::EnsureVideoDecodeTaskQueued()
 {
   AssertOwnerThread();
 
   SAMPLE_LOG("EnsureVideoDecodeTaskQueued isDecoding=%d status=%s",
              IsVideoDecoding(), VideoRequestStatus());
 
   if (!IsVideoDecoding() ||
       mReader->IsRequestingVideoData() ||
-      mVideoWaitRequest.Exists() ||
+      mReader->IsWaitingVideoData() ||
       mSeekRequest.Exists()) {
     return NS_OK;
   }
 
   RequestVideoData();
   return NS_OK;
 }
 
 const char*
 SeekTask::AudioRequestStatus()
 {
   AssertOwnerThread();
   if (mReader->IsRequestingAudioData()) {
-    MOZ_DIAGNOSTIC_ASSERT(!mAudioWaitRequest.Exists());
+    MOZ_DIAGNOSTIC_ASSERT(!mReader->IsWaitingAudioData());
     return "pending";
-  } else if (mAudioWaitRequest.Exists()) {
+  } else if (mReader->IsWaitingAudioData()) {
     return "waiting";
   }
   return "idle";
 }
 
 const char*
 SeekTask::VideoRequestStatus()
 {
   AssertOwnerThread();
   if (mReader->IsRequestingVideoData()) {
-    MOZ_DIAGNOSTIC_ASSERT(!mVideoWaitRequest.Exists());
+    MOZ_DIAGNOSTIC_ASSERT(!mReader->IsWaitingVideoData());
     return "pending";
-  } else if (mVideoWaitRequest.Exists()) {
+  } else if (mReader->IsWaitingVideoData()) {
     return "waiting";
   }
   return "idle";
 }
 
 void
 SeekTask::RequestAudioData()
 {
@@ -559,26 +557,17 @@ SeekTask::OnAudioNotDecoded(MediaDecoder
     return;
   }
 
   // If the decoder is waiting for data, we tell it to call us back when the
   // data arrives.
   if (aReason == MediaDecoderReader::WAITING_FOR_DATA) {
     MOZ_ASSERT(mReader->IsWaitForDataSupported(),
                "Readers that send WAITING_FOR_DATA need to implement WaitForData");
-    RefPtr<SeekTask> self = this;
-    mAudioWaitRequest.Begin(mReader->WaitForData(MediaData::AUDIO_DATA)
-      ->Then(OwnerThread(), __func__,
-             [self] (MediaData::Type aType) -> void {
-               self->mAudioWaitRequest.Complete();
-               self->EnsureAudioDecodeTaskQueued();
-             },
-             [self] (WaitForDataRejectValue aRejection) -> void {
-               self->mAudioWaitRequest.Complete();
-             }));
+    mReader->WaitForData(MediaData::AUDIO_DATA);
 
     // We are out of data to decode and will enter buffering mode soon.
     // We want to play the frames we have already decoded, so we stop pre-rolling
     // and ensure that loadeddata is fired as required.
     mNeedToStopPrerollingAudio = true;
     return;
   }
 
@@ -661,26 +650,17 @@ SeekTask::OnVideoNotDecoded(MediaDecoder
     return;
   }
 
   // If the decoder is waiting for data, we tell it to call us back when the
   // data arrives.
   if (aReason == MediaDecoderReader::WAITING_FOR_DATA) {
     MOZ_ASSERT(mReader->IsWaitForDataSupported(),
                "Readers that send WAITING_FOR_DATA need to implement WaitForData");
-    RefPtr<SeekTask> self = this;
-    mVideoWaitRequest.Begin(mReader->WaitForData(MediaData::VIDEO_DATA)
-      ->Then(OwnerThread(), __func__,
-             [self] (MediaData::Type aType) -> void {
-               self->mVideoWaitRequest.Complete();
-               self->EnsureVideoDecodeTaskQueued();
-             },
-             [self] (WaitForDataRejectValue aRejection) -> void {
-               self->mVideoWaitRequest.Complete();
-             }));
+    mReader->WaitForData(MediaData::VIDEO_DATA);
 
     // We are out of data to decode and will enter buffering mode soon.
     // We want to play the frames we have already decoded, so we stop pre-rolling
     // and ensure that loadeddata is fired as required.
     mNeedToStopPrerollingVideo = true;
     return;
   }
 
@@ -712,22 +692,45 @@ SeekTask::SetMediaDecoderReaderWrapperCa
   mAudioCallbackID =
     mReader->SetAudioCallback(this, &SeekTask::OnAudioDecoded,
                                     &SeekTask::OnAudioNotDecoded);
 
   mVideoCallbackID =
     mReader->SetVideoCallback(this, &SeekTask::OnVideoDecoded,
                                     &SeekTask::OnVideoNotDecoded);
 
+  RefPtr<SeekTask> self = this;
+  mWaitAudioCallbackID =
+    mReader->SetWaitAudioCallback(
+      [self] (MediaData::Type aType) -> void {
+        self->EnsureAudioDecodeTaskQueued();
+      },
+      [self] (WaitForDataRejectValue aRejection) -> void {});
+
+  mWaitVideoCallbackID =
+    mReader->SetWaitVideoCallback(
+      [self] (MediaData::Type aType) -> void {
+        self->EnsureVideoDecodeTaskQueued();
+      },
+      [self] (WaitForDataRejectValue aRejection) -> void {});
+
   DECODER_LOG("SeekTask set audio callbacks: mAudioCallbackID = %d\n", (int)mAudioCallbackID);
   DECODER_LOG("SeekTask set video callbacks: mVideoCallbackID = %d\n", (int)mAudioCallbackID);
+  DECODER_LOG("SeekTask set wait audio callbacks: mWaitAudioCallbackID = %d\n", (int)mWaitAudioCallbackID);
+  DECODER_LOG("SeekTask set wait video callbacks: mWaitVideoCallbackID = %d\n", (int)mWaitVideoCallbackID);
 }
 
 void
 SeekTask::CancelMediaDecoderReaderWrapperCallback()
 {
     DECODER_LOG("SeekTask cancel audio callbacks: mVideoCallbackID = %d\n", (int)mAudioCallbackID);
     mReader->CancelAudioCallback(mAudioCallbackID);
 
     DECODER_LOG("SeekTask cancel video callbacks: mVideoCallbackID = %d\n", (int)mVideoCallbackID);
     mReader->CancelVideoCallback(mVideoCallbackID);
+
+    DECODER_LOG("SeekTask cancel wait audio callbacks: mWaitAudioCallbackID = %d\n", (int)mWaitAudioCallbackID);
+    mReader->CancelWaitAudioCallback(mWaitAudioCallbackID);
+
+    DECODER_LOG("SeekTask cancel wait video callbacks: mWaitVideoCallbackID = %d\n", (int)mWaitVideoCallbackID);
+    mReader->CancelWaitVideoCallback(mWaitVideoCallbackID);
 }
 } // namespace mozilla
--- a/dom/media/SeekTask.h
+++ b/dom/media/SeekTask.h
@@ -159,18 +159,18 @@ protected:
   RefPtr<MediaData> mFirstVideoFrameAfterSeek;
 
   /*
    * Track the current seek promise made by the reader.
    */
   MozPromiseRequestHolder<MediaDecoderReader::SeekPromise> mSeekRequest;
   CallbackID mAudioCallbackID;
   CallbackID mVideoCallbackID;
-  MozPromiseRequestHolder<MediaDecoderReader::WaitForDataPromise> mAudioWaitRequest;
-  MozPromiseRequestHolder<MediaDecoderReader::WaitForDataPromise> mVideoWaitRequest;
+  CallbackID mWaitAudioCallbackID;
+  CallbackID mWaitVideoCallbackID;
 
   /*
    * Information which are going to be returned to MDSM.
    */
   RefPtr<MediaData> mSeekedAudioData;
   RefPtr<MediaData> mSeekedVideoData;
   bool mIsAudioQueueFinished;
   bool mIsVideoQueueFinished;