Bug 1274192 part 1 - make the MediaDecoderReaderWrapper as a proxy of WaitForData(); r=jwwang draft
authorKaku Kuo <tkuo@mozilla.com>
Thu, 19 May 2016 17:55:55 +0800
changeset 369082 fb8f2e5a3578cc19cba610bd8c9c4cb210653c6e
parent 369022 c67dc1f9fab86d4f2cf3224307809c44fe3ce820
child 369083 73a67b50aee6d0446b99675184f2a37ebf74a5b1
push id18730
push usertkuo@mozilla.com
push dateFri, 20 May 2016 07:31:38 +0000
reviewersjwwang
bugs1274192
milestone49.0a1
Bug 1274192 part 1 - make the MediaDecoderReaderWrapper as a proxy of WaitForData(); r=jwwang MozReview-Commit-ID: 5wYLuZRKJhA
dom/media/MediaDecoderReaderWrapper.cpp
dom/media/MediaDecoderReaderWrapper.h
--- a/dom/media/MediaDecoderReaderWrapper.cpp
+++ b/dom/media/MediaDecoderReaderWrapper.cpp
@@ -141,16 +141,18 @@ private:
 MediaDecoderReaderWrapper::MediaDecoderReaderWrapper(bool aIsRealTime,
                                                      AbstractThread* aOwnerThread,
                                                      MediaDecoderReader* aReader)
   : mForceZeroStartTime(aIsRealTime || aReader->ForceZeroStartTime())
   , mOwnerThread(aOwnerThread)
   , mReader(aReader)
   , mAudioCallbackID("AudioCallbackID")
   , mVideoCallbackID("VideoCallbackID")
+  , mWaitAudioCallbackID("WaitAudioCallbackID")
+  , mWaitVideoCallbackID("WaitVideoCallbackID")
 {}
 
 MediaDecoderReaderWrapper::~MediaDecoderReaderWrapper()
 {}
 
 media::TimeUnit
 MediaDecoderReaderWrapper::StartTime() const
 {
@@ -194,16 +196,34 @@ MediaDecoderReaderWrapper::CancelVideoCa
 {
   MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
   MOZ_ASSERT(aID == mVideoCallbackID);
   ++mVideoCallbackID;
   mRequestVideoDataCB = nullptr;
 }
 
 void
+MediaDecoderReaderWrapper::CancelWaitAudioCallback(CallbackID aID)
+{
+  MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
+  MOZ_ASSERT(aID == mWaitAudioCallbackID);
+  ++mWaitAudioCallbackID;
+  mWaitAudioDataCB = nullptr;
+}
+
+void
+MediaDecoderReaderWrapper::CancelWaitVideoCallback(CallbackID aID)
+{
+  MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
+  MOZ_ASSERT(aID == mWaitVideoCallbackID);
+  ++mWaitVideoCallbackID;
+  mWaitVideoDataCB = nullptr;
+}
+
+void
 MediaDecoderReaderWrapper::RequestAudioData()
 {
   MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
   MOZ_ASSERT(!mShutdown);
   MOZ_ASSERT(mRequestAudioDataCB, "Request audio data without callback!");
 
   auto p = InvokeAsync(mReader->OwnerThread(), mReader.get(), __func__,
                        &MediaDecoderReader::RequestAudioData);
@@ -280,16 +300,30 @@ MediaDecoderReaderWrapper::IsRequestingA
 
 bool
 MediaDecoderReaderWrapper::IsRequestingVideoData() const
 {
   MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
   return mVideoDataRequest.Exists();
 }
 
+bool
+MediaDecoderReaderWrapper::IsWaitingAudioData() const
+{
+  MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
+  return mAudioWaitRequest.Exists();
+}
+
+bool
+MediaDecoderReaderWrapper::IsWaitingVideoData() const
+{
+  MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
+  return mVideoWaitRequest.Exists();
+}
+
 RefPtr<MediaDecoderReader::SeekPromise>
 MediaDecoderReaderWrapper::Seek(SeekTarget aTarget, media::TimeUnit aEndTime)
 {
   MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
   aTarget.SetTime(aTarget.GetTime() + StartTime());
   return InvokeAsync(mReader->OwnerThread(), mReader.get(), __func__,
                      &MediaDecoderReader::Seek, aTarget,
                      aEndTime.ToMicroseconds());
@@ -331,16 +365,18 @@ MediaDecoderReaderWrapper::SetIdle()
 
 void
 MediaDecoderReaderWrapper::ResetDecode(TargetQueues aQueues)
 {
   MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
 
   mAudioDataRequest.DisconnectIfExists();
   mVideoDataRequest.DisconnectIfExists();
+  mAudioWaitRequest.DisconnectIfExists();
+  mVideoWaitRequest.DisconnectIfExists();
 
   nsCOMPtr<nsIRunnable> r =
     NewRunnableMethod<TargetQueues>(mReader,
                                     &MediaDecoderReader::ResetDecode,
                                     aQueues);
   mReader->OwnerThread()->Dispatch(r.forget());
 }
 
--- a/dom/media/MediaDecoderReaderWrapper.h
+++ b/dom/media/MediaDecoderReaderWrapper.h
@@ -159,16 +159,68 @@ class MediaDecoderReaderWrapper {
     {
       mRejectFunction(aReason);
     }
 
     ResolveFunctionType mResolveFuntion;
     RejectFunctionType mRejectFunction;
   };
 
+  struct WaitForDataCallbackBase
+  {
+    virtual ~WaitForDataCallbackBase() {}
+    virtual void OnResolved(MediaData::Type aType) = 0;
+    virtual void OnRejected(WaitForDataRejectValue aRejection) = 0;
+  };
+
+  template<typename ThisType, typename ResolveMethodType, typename RejectMethodType>
+  struct WaitForDataMethodCallback : public WaitForDataCallbackBase
+  {
+    WaitForDataMethodCallback(ThisType* aThis, ResolveMethodType aResolveMethod, RejectMethodType aRejectMethod)
+      : mThis(aThis), mResolveMethod(aResolveMethod), mRejectMethod(aRejectMethod)
+    {
+    }
+
+    void OnResolved(MediaData::Type aType) override
+    {
+      (mThis->*mResolveMethod)(aType);
+    }
+
+    void OnRejected(WaitForDataRejectValue aRejection) override
+    {
+      (mThis->*mRejectMethod)(aRejection);
+    }
+
+    RefPtr<ThisType> mThis;
+    ResolveMethodType mResolveMethod;
+    RejectMethodType mRejectMethod;
+  };
+
+  template<typename ResolveFunctionType, typename RejectFunctionType>
+  struct WaitForDataFunctionCallback : public WaitForDataCallbackBase
+  {
+    WaitForDataFunctionCallback(ResolveFunctionType&& aResolveFuntion, RejectFunctionType&& aRejectFunction)
+      : mResolveFuntion(Move(aResolveFuntion)), mRejectFunction(Move(aRejectFunction))
+    {
+    }
+
+    void OnResolved(MediaData::Type aType) override
+    {
+      mResolveFuntion(aType);
+    }
+
+    void OnRejected(WaitForDataRejectValue aRejection) override
+    {
+      mRejectFunction(aRejection);
+    }
+
+    ResolveFunctionType mResolveFuntion;
+    RejectFunctionType mRejectFunction;
+  };
+
 public:
   MediaDecoderReaderWrapper(bool aIsRealTime,
                             AbstractThread* aOwnerThread,
                             MediaDecoderReader* aReader);
 
   media::TimeUnit StartTime() const;
   RefPtr<MetadataPromise> ReadMetadata();
   RefPtr<HaveStartTimePromise> AwaitStartTime();
@@ -234,25 +286,95 @@ public:
 
     mRequestVideoDataCB.reset(
       new FunctionCallback<ResolveFunction, RejectFunction>(
             Move(aResolveFunction), Move(aRejectFunction)));
 
     return mVideoCallbackID;
   }
 
+  template<typename ThisType, typename ResolveMethodType, typename RejectMethodType>
+  CallbackID
+  SetWaitAudioCallback(ThisType* aThisVal,
+                       ResolveMethodType aResolveMethod,
+                       RejectMethodType aRejectMethod)
+  {
+    MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
+    MOZ_ASSERT(!mWaitAudioDataCB,
+               "Please cancel the original callback before setting a new one.");
+
+    mWaitAudioDataCB.reset(
+      new WaitForDataMethodCallback<ThisType, ResolveMethodType, RejectMethodType>(
+            aThisVal, aResolveMethod, aRejectMethod));
+
+    return mWaitAudioCallbackID;
+  }
+
+  template<typename ResolveFunction, typename RejectFunction>
+  CallbackID
+  SetWaitAudioCallback(ResolveFunction&& aResolveFunction,
+                       RejectFunction&& aRejectFunction)
+  {
+    MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
+    MOZ_ASSERT(!mWaitAudioDataCB,
+               "Please cancel the original callback before setting a new one.");
+
+    mWaitAudioDataCB.reset(
+      new WaitForDataFunctionCallback<ResolveFunction, RejectFunction>(
+            Move(aResolveFunction), Move(aRejectFunction)));
+
+    return mWaitAudioCallbackID;
+  }
+
+  template<typename ThisType, typename ResolveMethodType, typename RejectMethodType>
+  CallbackID
+  SetWaitVideoCallback(ThisType* aThisVal,
+                       ResolveMethodType aResolveMethod,
+                       RejectMethodType aRejectMethod)
+  {
+    MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
+    MOZ_ASSERT(!mWaitVideoDataCB,
+               "Please cancel the original callback before setting a new one.");
+
+    mWaitVideoDataCB.reset(
+      new WaitForDataMethodCallback<ThisType, ResolveMethodType, RejectMethodType>(
+            aThisVal, aResolveMethod, aRejectMethod));
+
+    return mWaitVideoCallbackID;
+  }
+
+  template<typename ResolveFunction, typename RejectFunction>
+  CallbackID
+  SetWaitVideoCallback(ResolveFunction&& aResolveFunction,
+                       RejectFunction&& aRejectFunction)
+  {
+    MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
+    MOZ_ASSERT(!mWaitVideoDataCB,
+               "Please cancel the original callback before setting a new one.");
+
+    mWaitVideoDataCB.reset(
+      new WaitForDataFunctionCallback<ResolveFunction, RejectFunction>(
+            Move(aResolveFunction), Move(aRejectFunction)));
+
+    return mWaitVideoCallbackID;
+  }
+
   void CancelAudioCallback(CallbackID aID);
   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);
 
   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();
@@ -310,21 +432,27 @@ private:
   const RefPtr<AbstractThread> mOwnerThread;
   const RefPtr<MediaDecoderReader> mReader;
 
   bool mShutdown = false;
   RefPtr<StartTimeRendezvous> mStartTimeRendezvous;
 
   UniquePtr<CallbackBase> mRequestAudioDataCB;
   UniquePtr<CallbackBase> mRequestVideoDataCB;
+  UniquePtr<WaitForDataCallbackBase> mWaitAudioDataCB;
+  UniquePtr<WaitForDataCallbackBase> mWaitVideoDataCB;
   MozPromiseRequestHolder<MediaDataPromise> mAudioDataRequest;
   MozPromiseRequestHolder<MediaDataPromise> mVideoDataRequest;
+  MozPromiseRequestHolder<WaitForDataPromise> mAudioWaitRequest;
+  MozPromiseRequestHolder<WaitForDataPromise> mVideoWaitRequest;
 
   /*
    * These callback ids are used to prevent mis-canceling callback.
    */
   CallbackID mAudioCallbackID;
   CallbackID mVideoCallbackID;
+  CallbackID mWaitAudioCallbackID;
+  CallbackID mWaitVideoCallbackID;
 };
 
 } // namespace mozilla
 
 #endif // MediaDecoderReaderWrapper_h_