Bug 1324629. Part 1 - remove audio callback. r?kaku draft
authorJW Wang <jwwang@mozilla.com>
Tue, 20 Dec 2016 12:54:23 +0800
changeset 452799 ce014d0306e0afbfec2cbeaa0b61dd97f1e5d53a
parent 452798 f68dccc48f135cb66104a52994b8b061f4c0f76d
child 452800 fbdd4a258d129a8a24f5d6c2a25f7b440edb76e6
push id39496
push userjwwang@mozilla.com
push dateThu, 22 Dec 2016 08:00:57 +0000
reviewerskaku
bugs1324629
milestone53.0a1
Bug 1324629. Part 1 - remove audio callback. r?kaku MozReview-Commit-ID: DbWwSNpYXLo
dom/media/MediaDecoderReaderWrapper.cpp
dom/media/MediaDecoderReaderWrapper.h
dom/media/MediaDecoderStateMachine.cpp
dom/media/MediaDecoderStateMachine.h
--- a/dom/media/MediaDecoderReaderWrapper.cpp
+++ b/dom/media/MediaDecoderReaderWrapper.cpp
@@ -33,36 +33,30 @@ MediaDecoderReaderWrapper::ReadMetadata(
   MOZ_ASSERT(!mShutdown);
   return InvokeAsync(mReader->OwnerThread(), mReader.get(), __func__,
                      &MediaDecoderReader::AsyncReadMetadata)
          ->Then(mOwnerThread, __func__, this,
                 &MediaDecoderReaderWrapper::OnMetadataRead,
                 &MediaDecoderReaderWrapper::OnMetadataNotRead);
 }
 
-void
+RefPtr<MediaDecoderReaderWrapper::MediaDataPromise>
 MediaDecoderReaderWrapper::RequestAudioData()
 {
   MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
   MOZ_ASSERT(!mShutdown);
 
-  auto p = InvokeAsync(mReader->OwnerThread(), mReader.get(), __func__,
-                       &MediaDecoderReader::RequestAudioData);
-
-  RefPtr<MediaDecoderReaderWrapper> self = this;
-  mAudioDataRequest.Begin(p->Then(mOwnerThread, __func__,
-    [self] (MediaData* aAudioSample) {
-      self->mAudioDataRequest.Complete();
-      aAudioSample->AdjustForStartTime(self->StartTime().ToMicroseconds());
-      self->mAudioCallback.Notify(AsVariant(aAudioSample));
-    },
-    [self] (const MediaResult& aError) {
-      self->mAudioDataRequest.Complete();
-      self->mAudioCallback.Notify(AsVariant(aError));
-    }));
+  int64_t startTime = StartTime().ToMicroseconds();
+  return InvokeAsync(mReader->OwnerThread(), mReader.get(),
+                     __func__, &MediaDecoderReader::RequestAudioData)
+    ->Then(mOwnerThread, __func__,
+           [startTime] (MediaData* aAudio) {
+             aAudio->AdjustForStartTime(startTime);
+           },
+           [] (const MediaResult& aError) {});
 }
 
 void
 MediaDecoderReaderWrapper::RequestVideoData(bool aSkipToNextKeyframe,
                                             media::TimeUnit aTimeThreshold)
 {
   MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
   MOZ_ASSERT(!mShutdown);
@@ -88,23 +82,16 @@ MediaDecoderReaderWrapper::RequestVideoD
     },
     [self] (const MediaResult& aError) {
       self->mVideoDataRequest.Complete();
       self->mVideoCallback.Notify(AsVariant(aError));
     }));
 }
 
 bool
-MediaDecoderReaderWrapper::IsRequestingAudioData() const
-{
-  MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
-  return mAudioDataRequest.Exists();
-}
-
-bool
 MediaDecoderReaderWrapper::IsRequestingVideoData() const
 {
   MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
   return mVideoDataRequest.Exists();
 }
 
 bool
 MediaDecoderReaderWrapper::IsWaitingAudioData() const
@@ -176,17 +163,16 @@ MediaDecoderReaderWrapper::ReleaseResour
 }
 
 void
 MediaDecoderReaderWrapper::ResetDecode(TrackSet aTracks)
 {
   MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
 
   if (aTracks.contains(TrackInfo::kAudioTrack)) {
-    mAudioDataRequest.DisconnectIfExists();
     mAudioWaitRequest.DisconnectIfExists();
   }
 
   if (aTracks.contains(TrackInfo::kVideoTrack)) {
     mVideoDataRequest.DisconnectIfExists();
     mVideoWaitRequest.DisconnectIfExists();
   }
 
@@ -196,17 +182,16 @@ MediaDecoderReaderWrapper::ResetDecode(T
                                 aTracks);
   mReader->OwnerThread()->Dispatch(r.forget());
 }
 
 RefPtr<ShutdownPromise>
 MediaDecoderReaderWrapper::Shutdown()
 {
   MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
-  MOZ_ASSERT(!mAudioDataRequest.Exists());
   MOZ_ASSERT(!mVideoDataRequest.Exists());
 
   mShutdown = true;
   return InvokeAsync(mReader->OwnerThread(), mReader.get(), __func__,
                      &MediaDecoderReader::Shutdown);
 }
 
 void
--- a/dom/media/MediaDecoderReaderWrapper.h
+++ b/dom/media/MediaDecoderReaderWrapper.h
@@ -33,41 +33,38 @@ class MediaDecoderReaderWrapper {
   typedef MediaDecoderReader::MetadataPromise MetadataPromise;
   typedef MediaDecoderReader::MediaDataPromise MediaDataPromise;
   typedef MediaDecoderReader::SeekPromise SeekPromise;
   typedef MediaDecoderReader::WaitForDataPromise WaitForDataPromise;
   typedef MediaDecoderReader::TrackSet TrackSet;
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaDecoderReaderWrapper);
 
 private:
-  MediaCallbackExc<AudioCallbackData> mAudioCallback;
   MediaCallbackExc<VideoCallbackData> mVideoCallback;
   MediaCallbackExc<WaitCallbackData> mAudioWaitCallback;
   MediaCallbackExc<WaitCallbackData> mVideoWaitCallback;
 
 public:
   MediaDecoderReaderWrapper(AbstractThread* aOwnerThread,
                             MediaDecoderReader* aReader);
 
   media::TimeUnit StartTime() const;
   RefPtr<MetadataPromise> ReadMetadata();
 
-  decltype(mAudioCallback)& AudioCallback() { return mAudioCallback; }
   decltype(mVideoCallback)& VideoCallback() { return mVideoCallback; }
   decltype(mAudioWaitCallback)& AudioWaitCallback() { return mAudioWaitCallback; }
   decltype(mVideoWaitCallback)& VideoWaitCallback() { return mVideoWaitCallback; }
 
   // NOTE: please set callbacks before requesting audio/video data!
-  void RequestAudioData();
+  RefPtr<MediaDataPromise> 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(const SeekTarget& aTarget);
   RefPtr<ShutdownPromise> Shutdown();
 
   void ReleaseResources();
@@ -119,17 +116,16 @@ private:
   MozPromiseRequestHolder<WaitForDataPromise>& WaitRequestRef(MediaData::Type aType);
 
   const RefPtr<AbstractThread> mOwnerThread;
   const RefPtr<MediaDecoderReader> mReader;
 
   bool mShutdown = false;
   Maybe<media::TimeUnit> mStartTime;
 
-  MozPromiseRequestHolder<MediaDataPromise> mAudioDataRequest;
   MozPromiseRequestHolder<MediaDataPromise> mVideoDataRequest;
   MozPromiseRequestHolder<WaitForDataPromise> mAudioWaitRequest;
   MozPromiseRequestHolder<WaitForDataPromise> mVideoWaitRequest;
 };
 
 } // namespace mozilla
 
 #endif // MediaDecoderReaderWrapper_h_
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -1059,19 +1059,19 @@ private:
     mSeekRequest.Complete();
     MOZ_ASSERT(NS_FAILED(aError), "Cancels should also disconnect mSeekRequest");
     mMaster->DecodeError(aError);
   }
 
   void RequestAudioData()
   {
     MOZ_ASSERT(!mDoneAudioSeeking);
-    MOZ_ASSERT(!Reader()->IsRequestingAudioData());
+    MOZ_ASSERT(!mMaster->IsRequestingAudioData());
     MOZ_ASSERT(!Reader()->IsWaitingAudioData());
-    Reader()->RequestAudioData();
+    mMaster->RequestAudioData();
   }
 
   void RequestVideoData()
   {
     MOZ_ASSERT(!mDoneVideoSeeking);
     MOZ_ASSERT(!Reader()->IsRequestingVideoData());
     MOZ_ASSERT(!Reader()->IsWaitingVideoData());
     Reader()->RequestVideoData(false, media::TimeUnit());
@@ -2132,17 +2132,17 @@ BufferingState::Step()
       return;
     }
   } else if (mMaster->OutOfDecodedAudio() || mMaster->OutOfDecodedVideo()) {
     MOZ_ASSERT(Reader()->IsWaitForDataSupported(),
                "Don't yet have a strategy for non-heuristic + non-WaitForData");
     mMaster->DispatchDecodeTasksIfNeeded();
     MOZ_ASSERT(mMaster->mMinimizePreroll ||
                !mMaster->OutOfDecodedAudio() ||
-               Reader()->IsRequestingAudioData() ||
+               mMaster->IsRequestingAudioData() ||
                Reader()->IsWaitingAudioData());
     MOZ_ASSERT(mMaster->mMinimizePreroll ||
                !mMaster->OutOfDecodedVideo() ||
                Reader()->IsRequestingVideoData() ||
                Reader()->IsWaitingVideoData());
     SLOG("In buffering mode, waiting to be notified: outOfAudio: %d, "
          "mAudioStatus: %s, outOfVideo: %d, mVideoStatus: %s",
          mMaster->OutOfDecodedAudio(), mMaster->AudioRequestStatus(),
@@ -2182,16 +2182,17 @@ ShutdownState::Enter()
   master->mCDMProxyPromise.DisconnectIfExists();
 
   if (master->IsPlaying()) {
     master->StopPlayback();
   }
 
   // To break the cycle-reference between MediaDecoderReaderWrapper and MDSM.
   master->CancelMediaDecoderReaderWrapperCallback();
+  master->mAudioDataRequest.DisconnectIfExists();
 
   master->Reset();
 
   master->mMediaSink->Shutdown();
 
   // Prevent dangling pointers by disconnecting the listeners.
   master->mAudioQueueListener.Disconnect();
   master->mVideoQueueListener.Disconnect();
@@ -2516,16 +2517,18 @@ MediaDecoderStateMachine::NeedToDecodeAu
 }
 
 void
 MediaDecoderStateMachine::OnAudioDecoded(MediaData* aAudio)
 {
   MOZ_ASSERT(OnTaskQueue());
   MOZ_ASSERT(aAudio);
 
+  mAudioDataRequest.Complete();
+
   // audio->GetEndTime() is not always mono-increasing in chained ogg.
   mDecodedAudioEndTime = std::max(aAudio->GetEndTime(), mDecodedAudioEndTime);
 
   SAMPLE_LOG("OnAudioDecoded [%lld,%lld]", aAudio->mTime, aAudio->GetEndTime());
 
   mStateObj->HandleAudioDecoded(aAudio);
 }
 
@@ -2564,23 +2567,29 @@ void
 MediaDecoderStateMachine::OnVideoPopped(const RefPtr<MediaData>& aSample)
 {
   MOZ_ASSERT(OnTaskQueue());
   mPlaybackOffset = std::max(mPlaybackOffset.Ref(), aSample->mOffset);
   DispatchVideoDecodeTaskIfNeeded();
 }
 
 void
+MediaDecoderStateMachine::OnAudioNotDecoded(const MediaResult& aError)
+{
+  MOZ_ASSERT(OnTaskQueue());
+  mAudioDataRequest.Complete();
+  OnNotDecoded(MediaData::AUDIO_DATA, aError);
+}
+
+void
 MediaDecoderStateMachine::OnNotDecoded(MediaData::Type aType,
                                        const MediaResult& aError)
 {
   MOZ_ASSERT(OnTaskQueue());
-
   SAMPLE_LOG("OnNotDecoded (aType=%u, aError=%u)", aType, aError.Code());
-
   mStateObj->HandleNotDecoded(aType, aError);
 }
 
 void
 MediaDecoderStateMachine::OnVideoDecoded(MediaData* aVideo,
                                          TimeStamp aDecodeStartTime)
 {
   MOZ_ASSERT(OnTaskQueue());
@@ -2691,25 +2700,16 @@ nsresult MediaDecoderStateMachine::Init(
   return NS_OK;
 }
 
 void
 MediaDecoderStateMachine::SetMediaDecoderReaderWrapperCallback()
 {
   MOZ_ASSERT(OnTaskQueue());
 
-  mAudioCallback = mReader->AudioCallback().Connect(
-    mTaskQueue, [this] (AudioCallbackData aData) {
-    if (aData.is<MediaData*>()) {
-      OnAudioDecoded(aData.as<MediaData*>());
-    } else {
-      OnNotDecoded(MediaData::AUDIO_DATA, aData.as<MediaResult>());
-    }
-  });
-
   mVideoCallback = mReader->VideoCallback().Connect(
     mTaskQueue, [this] (VideoCallbackData aData) {
     typedef Tuple<MediaData*, TimeStamp> Type;
     if (aData.is<Type>()) {
       auto&& v = aData.as<Type>();
       OnVideoDecoded(Get<0>(v), Get<1>(v));
     } else {
       OnNotDecoded(MediaData::VIDEO_DATA, aData.as<MediaResult>());
@@ -2734,17 +2734,16 @@ MediaDecoderStateMachine::SetMediaDecode
     }
   });
 }
 
 void
 MediaDecoderStateMachine::CancelMediaDecoderReaderWrapperCallback()
 {
   MOZ_ASSERT(OnTaskQueue());
-  mAudioCallback.Disconnect();
   mVideoCallback.Disconnect();
   mAudioWaitCallback.Disconnect();
   mVideoWaitCallback.Disconnect();
 }
 
 void MediaDecoderStateMachine::StopPlayback()
 {
   MOZ_ASSERT(OnTaskQueue());
@@ -3066,34 +3065,37 @@ MediaDecoderStateMachine::EnsureAudioDec
 
   if (mState != DECODER_STATE_DECODING &&
       mState != DECODER_STATE_DECODING_FIRSTFRAME &&
       mState != DECODER_STATE_BUFFERING) {
     return;
   }
 
   if (!IsAudioDecoding() ||
-      mReader->IsRequestingAudioData() ||
+      IsRequestingAudioData() ||
       mReader->IsWaitingAudioData()) {
     return;
   }
 
   RequestAudioData();
 }
 
 void
 MediaDecoderStateMachine::RequestAudioData()
 {
   MOZ_ASSERT(OnTaskQueue());
-  MOZ_ASSERT(mState != DECODER_STATE_SEEKING);
-
   SAMPLE_LOG("Queueing audio task - queued=%i, decoder-queued=%o",
              AudioQueue().GetSize(), mReader->SizeOfAudioQueueInFrames());
 
-  mReader->RequestAudioData();
+  mAudioDataRequest.Begin(
+    mReader->RequestAudioData()->Then(
+      OwnerThread(), __func__, this,
+      &MediaDecoderStateMachine::OnAudioDecoded,
+      &MediaDecoderStateMachine::OnAudioNotDecoded)
+  );
 }
 
 void
 MediaDecoderStateMachine::DispatchVideoDecodeTaskIfNeeded()
 {
   MOZ_ASSERT(OnTaskQueue());
   if (!IsShutdown() && NeedToDecodeVideo()) {
     EnsureVideoDecodeTaskQueued();
@@ -3373,16 +3375,17 @@ MediaDecoderStateMachine::Reset(TrackSet
     mVideoCompleted = false;
     VideoQueue().Reset();
   }
 
   if (aTracks.contains(TrackInfo::kAudioTrack)) {
     mDecodedAudioEndTime = 0;
     mAudioCompleted = false;
     AudioQueue().Reset();
+    mAudioDataRequest.DisconnectIfExists();
   }
 
   mPlaybackOffset = 0;
 
   mReader->ResetDecode(aTracks);
 }
 
 int64_t
@@ -3775,17 +3778,17 @@ MediaDecoderStateMachine::OnMediaNotSeek
 {
   return mReader->OnMediaNotSeekable();
 }
 
 const char*
 MediaDecoderStateMachine::AudioRequestStatus() const
 {
   MOZ_ASSERT(OnTaskQueue());
-  if (mReader->IsRequestingAudioData()) {
+  if (IsRequestingAudioData()) {
     MOZ_DIAGNOSTIC_ASSERT(!mReader->IsWaitingAudioData());
     return "pending";
   } else if (mReader->IsWaitingAudioData()) {
     return "waiting";
   }
   return "idle";
 }
 
--- a/dom/media/MediaDecoderStateMachine.h
+++ b/dom/media/MediaDecoderStateMachine.h
@@ -324,16 +324,17 @@ private:
   bool IsShutdown() const;
 
   // Returns true if we're currently playing. The decoder monitor must
   // be held.
   bool IsPlaying() const;
 
   void OnAudioDecoded(MediaData* aAudio);
   void OnVideoDecoded(MediaData* aVideo, TimeStamp aDecodeStartTime);
+  void OnAudioNotDecoded(const MediaResult& aError);
   void OnNotDecoded(MediaData::Type aType, const MediaResult& aError);
   void OnAudioWaited(MediaData::Type aType);
   void OnVideoWaited(MediaData::Type aType);
   void OnNotWaited(const WaitForDataRejectValue& aRejection);
 
   // Resets all state related to decoding and playback, emptying all buffers
   // and aborting all pending operations on the decode task queue.
   void Reset(TrackSet aTracks = TrackSet(TrackInfo::kAudioTrack,
@@ -469,16 +470,18 @@ protected:
   // Start a task to decode audio.
   // The decoder monitor must be held.
   void RequestAudioData();
 
   // Start a task to decode video.
   // The decoder monitor must be held.
   void RequestVideoData();
 
+  bool IsRequestingAudioData() const { return mAudioDataRequest.Exists(); }
+
   // Re-evaluates the state and determines whether we need to dispatch
   // events to run the decode, or if not whether we should set the reader
   // to idle mode. This is threadsafe, and can be called from any thread.
   // The decoder monitor must be held.
   void DispatchDecodeTasksIfNeeded();
 
   // Returns the "media time". This is the absolute time which the media
   // playback has reached. i.e. this returns values in the range
@@ -649,21 +652,23 @@ private:
   {
     MOZ_ASSERT(OnTaskQueue());
     return GetAmpleVideoFrames() / 2;
   }
 
   // Only one of a given pair of ({Audio,Video}DataPromise, WaitForDataPromise)
   // should exist at any given moment.
 
-  MediaEventListener mAudioCallback;
   MediaEventListener mVideoCallback;
   MediaEventListener mAudioWaitCallback;
   MediaEventListener mVideoWaitCallback;
 
+  using MediaDataPromise = MediaDecoderReader::MediaDataPromise;
+  MozPromiseRequestHolder<MediaDataPromise> mAudioDataRequest;
+
   const char* AudioRequestStatus() const;
   const char* VideoRequestStatus() const;
 
   void OnSuspendTimerResolved();
   void OnSuspendTimerRejected();
 
   // 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