--- a/dom/media/AccurateSeekTask.cpp
+++ b/dom/media/AccurateSeekTask.cpp
@@ -619,61 +619,52 @@ AccurateSeekTask::OnVideoNotDecoded(Medi
}
}
void
AccurateSeekTask::SetMediaDecoderReaderWrapperCallback()
{
AssertOwnerThread();
- mAudioCallbackID =
- mReader->SetAudioCallback(this, &AccurateSeekTask::OnAudioDecoded,
- &AccurateSeekTask::OnAudioNotDecoded);
-
- mVideoCallbackID =
- mReader->SetVideoCallback(this, &AccurateSeekTask::OnVideoDecoded,
- &AccurateSeekTask::OnVideoNotDecoded);
+ mAudioCallback = mReader->AudioCallback().Connect(
+ OwnerThread(), [this] (AudioCallbackData aData) {
+ if (aData.is<MediaData*>()) {
+ OnAudioDecoded(aData.as<MediaData*>());
+ } else {
+ OnAudioNotDecoded(aData.as<MediaDecoderReader::NotDecodedReason>());
+ }
+ });
- RefPtr<AccurateSeekTask> self = this;
- mWaitAudioCallbackID =
- mReader->SetWaitAudioCallback(
- [self] (MediaData::Type aType) -> void {
- self->AssertOwnerThread();
- self->EnsureAudioDecodeTaskQueued();
- },
- [self] (WaitForDataRejectValue aRejection) -> void {
- self->AssertOwnerThread();
- });
+ mVideoCallback = mReader->VideoCallback().Connect(
+ OwnerThread(), [this] (VideoCallbackData aData) {
+ typedef Tuple<MediaData*, TimeStamp> Type;
+ if (aData.is<Type>()) {
+ OnVideoDecoded(Get<0>(aData.as<Type>()));
+ } else {
+ OnVideoNotDecoded(aData.as<MediaDecoderReader::NotDecodedReason>());
+ }
+ });
- mWaitVideoCallbackID =
- mReader->SetWaitVideoCallback(
- [self] (MediaData::Type aType) -> void {
- self->AssertOwnerThread();
- self->EnsureVideoDecodeTaskQueued();
- },
- [self] (WaitForDataRejectValue aRejection) -> void {
- self->AssertOwnerThread();
- });
+ mAudioWaitCallback = mReader->AudioWaitCallback().Connect(
+ OwnerThread(), [this] (WaitCallbackData aData) {
+ if (aData.is<MediaData::Type>()) {
+ EnsureAudioDecodeTaskQueued();
+ }
+ });
- 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);
+ mVideoWaitCallback = mReader->VideoWaitCallback().Connect(
+ OwnerThread(), [this] (WaitCallbackData aData) {
+ if (aData.is<MediaData::Type>()) {
+ EnsureVideoDecodeTaskQueued();
+ }
+ });
}
void
AccurateSeekTask::CancelMediaDecoderReaderWrapperCallback()
{
AssertOwnerThread();
-
- 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);
+ mAudioCallback.Disconnect();
+ mVideoCallback.Disconnect();
+ mAudioWaitCallback.Disconnect();
+ mVideoWaitCallback.Disconnect();
}
} // namespace mozilla
--- a/dom/media/AccurateSeekTask.h
+++ b/dom/media/AccurateSeekTask.h
@@ -94,17 +94,18 @@ private:
// the seek target, we will still have a frame that we can display as the
// last frame in the media.
RefPtr<MediaData> mFirstVideoFrameAfterSeek;
/*
* Track the current seek promise made by the reader.
*/
MozPromiseRequestHolder<MediaDecoderReader::SeekPromise> mSeekRequest;
- CallbackID mAudioCallbackID;
- CallbackID mVideoCallbackID;
- CallbackID mWaitAudioCallbackID;
- CallbackID mWaitVideoCallbackID;
+
+ MediaEventListener mAudioCallback;
+ MediaEventListener mVideoCallback;
+ MediaEventListener mAudioWaitCallback;
+ MediaEventListener mVideoWaitCallback;
};
} // namespace mozilla
#endif /* ACCURATE_SEEK_TASK_H */
--- a/dom/media/MediaDecoderReaderWrapper.cpp
+++ b/dom/media/MediaDecoderReaderWrapper.cpp
@@ -139,20 +139,16 @@ 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
{
@@ -178,89 +174,50 @@ RefPtr<HaveStartTimePromise>
MediaDecoderReaderWrapper::AwaitStartTime()
{
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
MOZ_ASSERT(!mShutdown);
return mStartTimeRendezvous->AwaitStartTime();
}
void
-MediaDecoderReaderWrapper::CancelAudioCallback(CallbackID aID)
-{
- MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
- MOZ_ASSERT(aID == mAudioCallbackID);
- ++mAudioCallbackID;
- mRequestAudioDataCB = nullptr;
-}
-
-void
-MediaDecoderReaderWrapper::CancelVideoCallback(CallbackID aID)
-{
- 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);
if (!mStartTimeRendezvous->HaveStartTime()) {
p = p->Then(mOwnerThread, __func__, mStartTimeRendezvous.get(),
&StartTimeRendezvous::ProcessFirstSample<MediaData::AUDIO_DATA>,
&StartTimeRendezvous::FirstSampleRejected<MediaData::AUDIO_DATA>)
->CompletionPromise();
}
RefPtr<MediaDecoderReaderWrapper> self = this;
mAudioDataRequest.Begin(p->Then(mOwnerThread, __func__,
[self] (MediaData* aAudioSample) {
- MOZ_ASSERT(self->mRequestAudioDataCB);
self->mAudioDataRequest.Complete();
- self->OnSampleDecoded(self->mRequestAudioDataCB.get(), aAudioSample, TimeStamp());
+ aAudioSample->AdjustForStartTime(self->StartTime().ToMicroseconds());
+ self->mAudioCallback.Notify(AsVariant(aAudioSample));
},
[self] (MediaDecoderReader::NotDecodedReason aReason) {
- MOZ_ASSERT(self->mRequestAudioDataCB);
self->mAudioDataRequest.Complete();
- self->OnNotDecoded(self->mRequestAudioDataCB.get(), aReason);
+ self->mAudioCallback.Notify(AsVariant(aReason));
}));
}
void
MediaDecoderReaderWrapper::RequestVideoData(bool aSkipToNextKeyframe,
media::TimeUnit aTimeThreshold)
{
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
MOZ_ASSERT(!mShutdown);
- MOZ_ASSERT(mRequestVideoDataCB, "Request video data without callback!");
// Time the video decode and send this value back to callbacks who accept
// a TimeStamp as its second parameter.
TimeStamp videoDecodeStartTime = TimeStamp::Now();
if (aTimeThreshold.ToMicroseconds() > 0 &&
mStartTimeRendezvous->HaveStartTime()) {
aTimeThreshold += StartTime();
@@ -275,24 +232,23 @@ MediaDecoderReaderWrapper::RequestVideoD
&StartTimeRendezvous::ProcessFirstSample<MediaData::VIDEO_DATA>,
&StartTimeRendezvous::FirstSampleRejected<MediaData::VIDEO_DATA>)
->CompletionPromise();
}
RefPtr<MediaDecoderReaderWrapper> self = this;
mVideoDataRequest.Begin(p->Then(mOwnerThread, __func__,
[self, videoDecodeStartTime] (MediaData* aVideoSample) {
- MOZ_ASSERT(self->mRequestVideoDataCB);
self->mVideoDataRequest.Complete();
- self->OnSampleDecoded(self->mRequestVideoDataCB.get(), aVideoSample, videoDecodeStartTime);
+ aVideoSample->AdjustForStartTime(self->StartTime().ToMicroseconds());
+ self->mVideoCallback.Notify(AsVariant(MakeTuple(aVideoSample, videoDecodeStartTime)));
},
[self] (MediaDecoderReader::NotDecodedReason aReason) {
- MOZ_ASSERT(self->mRequestVideoDataCB);
self->mVideoDataRequest.Complete();
- self->OnNotDecoded(self->mRequestVideoDataCB.get(), aReason);
+ self->mVideoCallback.Notify(AsVariant(aReason));
}));
}
bool
MediaDecoderReaderWrapper::IsRequestingAudioData() const
{
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
return mAudioDataRequest.Exists();
@@ -328,40 +284,37 @@ MediaDecoderReaderWrapper::Seek(SeekTarg
&MediaDecoderReader::Seek, aTarget,
aEndTime.ToMicroseconds());
}
void
MediaDecoderReaderWrapper::WaitForData(MediaData::Type aType)
{
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
- 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->WaitCallbackRef(aType).Notify(AsVariant(aType));
},
[self, aType] (WaitForDataRejectValue aRejection) {
- MOZ_ASSERT(self->WaitCallbackRef(aType));
self->WaitRequestRef(aType).Complete();
- self->WaitCallbackRef(aType)->OnRejected(aRejection);
+ self->WaitCallbackRef(aType).Notify(AsVariant(aRejection));
}));
}
-UniquePtr<MediaDecoderReaderWrapper::WaitForDataCallbackBase>&
+MediaCallbackExc<WaitCallbackData>&
MediaDecoderReaderWrapper::WaitCallbackRef(MediaData::Type aType)
{
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
- return aType == MediaData::AUDIO_DATA ? mWaitAudioDataCB : mWaitVideoDataCB;
+ return aType == MediaData::AUDIO_DATA ? mAudioWaitCallback : mVideoWaitCallback;
}
MozPromiseRequestHolder<MediaDecoderReader::WaitForDataPromise>&
MediaDecoderReaderWrapper::WaitRequestRef(MediaData::Type aType)
{
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
return aType == MediaData::AUDIO_DATA ? mAudioWaitRequest : mVideoWaitRequest;
}
@@ -413,18 +366,16 @@ MediaDecoderReaderWrapper::ResetDecode(T
aTracks);
mReader->OwnerThread()->Dispatch(r.forget());
}
RefPtr<ShutdownPromise>
MediaDecoderReaderWrapper::Shutdown()
{
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
- MOZ_ASSERT(!mRequestAudioDataCB);
- MOZ_ASSERT(!mRequestVideoDataCB);
MOZ_ASSERT(!mAudioDataRequest.Exists());
MOZ_ASSERT(!mVideoDataRequest.Exists());
mShutdown = true;
if (mStartTimeRendezvous) {
mStartTimeRendezvous->Destroy();
mStartTimeRendezvous = nullptr;
}
@@ -454,31 +405,9 @@ MediaDecoderReaderWrapper::OnMetadataRea
self->mReader->DispatchSetStartTime(self->StartTime().ToMicroseconds());
},
[] () {
NS_WARNING("Setting start time on reader failed");
});
}
}
-void
-MediaDecoderReaderWrapper::OnSampleDecoded(CallbackBase* aCallback,
- MediaData* aSample,
- TimeStamp aDecodeStartTime)
-{
- MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
- MOZ_ASSERT(!mShutdown);
-
- aSample->AdjustForStartTime(StartTime().ToMicroseconds());
- aCallback->OnResolved(aSample, aDecodeStartTime);
-}
-
-void
-MediaDecoderReaderWrapper::OnNotDecoded(CallbackBase* aCallback,
- MediaDecoderReader::NotDecodedReason aReason)
-{
- MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
- MOZ_ASSERT(!mShutdown);
-
- aCallback->OnRejected(aReason);
-}
-
} // namespace mozilla
--- a/dom/media/MediaDecoderReaderWrapper.h
+++ b/dom/media/MediaDecoderReaderWrapper.h
@@ -7,365 +7,62 @@
#ifndef MediaDecoderReaderWrapper_h_
#define MediaDecoderReaderWrapper_h_
#include "mozilla/AbstractThread.h"
#include "mozilla/RefPtr.h"
#include "nsISupportsImpl.h"
#include "MediaDecoderReader.h"
-#include "MediaCallbackID.h"
+#include "MediaEventSource.h"
namespace mozilla {
class StartTimeRendezvous;
typedef MozPromise<bool, bool, /* isExclusive = */ false> HaveStartTimePromise;
+typedef Variant<MediaData*, MediaDecoderReader::NotDecodedReason> AudioCallbackData;
+typedef Variant<Tuple<MediaData*, TimeStamp>, MediaDecoderReader::NotDecodedReason> VideoCallbackData;
+typedef Variant<MediaData::Type, WaitForDataRejectValue> WaitCallbackData;
+
/**
* A wrapper around MediaDecoderReader to offset the timestamps of Audio/Video
* samples by the start time to ensure MDSM can always assume zero start time.
* It also adjusts the seek target passed to Seek() to ensure correct seek time
* is passed to the underlying reader.
*/
class MediaDecoderReaderWrapper {
typedef MediaDecoderReader::MetadataPromise MetadataPromise;
typedef MediaDecoderReader::MediaDataPromise MediaDataPromise;
typedef MediaDecoderReader::SeekPromise SeekPromise;
typedef MediaDecoderReader::WaitForDataPromise WaitForDataPromise;
typedef MediaDecoderReader::BufferedUpdatePromise BufferedUpdatePromise;
typedef MediaDecoderReader::TrackSet TrackSet;
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaDecoderReaderWrapper);
- /*
- * Type 1: void(MediaData*)
- * void(RefPtr<MediaData>)
- */
- template <typename T>
- class ArgType1CheckHelper {
- template<typename C, typename... Ts>
- static TrueType
- test(void(C::*aMethod)(Ts...),
- decltype((DeclVal<C>().*aMethod)(DeclVal<MediaData*>()), 0));
-
- template <typename F>
- static TrueType
- test(F&&, decltype(DeclVal<F>()(DeclVal<MediaData*>()), 0));
-
- static FalseType test(...);
- public:
- typedef decltype(test(DeclVal<T>(), 0)) Type;
- };
-
- template <typename T>
- struct ArgType1Check : public ArgType1CheckHelper<T>::Type {};
-
- /*
- * Type 2: void(MediaData*, TimeStamp)
- * void(RefPtr<MediaData>, TimeStamp)
- * void(MediaData*, TimeStamp&)
- * void(RefPtr<MediaData>, const TimeStamp&&)
- */
- template <typename T>
- class ArgType2CheckHelper {
-
- template<typename C, typename... Ts>
- static TrueType
- test(void(C::*aMethod)(Ts...),
- decltype((DeclVal<C>().*aMethod)(DeclVal<MediaData*>(), DeclVal<TimeStamp>()), 0));
-
- template <typename F>
- static TrueType
- test(F&&, decltype(DeclVal<F>()(DeclVal<MediaData*>(), DeclVal<TimeStamp>()), 0));
-
- static FalseType test(...);
- public:
- typedef decltype(test(DeclVal<T>(), 0)) Type;
- };
-
- template <typename T>
- struct ArgType2Check : public ArgType2CheckHelper<T>::Type {};
-
- struct CallbackBase
- {
- virtual ~CallbackBase() {}
- virtual void OnResolved(MediaData*, TimeStamp) = 0;
- virtual void OnRejected(MediaDecoderReader::NotDecodedReason) = 0;
- };
-
- template<typename ThisType, typename ResolveMethodType, typename RejectMethodType>
- struct MethodCallback : public CallbackBase
- {
- MethodCallback(ThisType* aThis, ResolveMethodType aResolveMethod, RejectMethodType aRejectMethod)
- : mThis(aThis), mResolveMethod(aResolveMethod), mRejectMethod(aRejectMethod)
- {
- }
-
- template<typename F>
- typename EnableIf<ArgType1Check<F>::value, void>::Type
- CallHelper(MediaData* aSample, TimeStamp)
- {
- (mThis->*mResolveMethod)(aSample);
- }
-
- template<typename F>
- typename EnableIf<ArgType2Check<F>::value, void>::Type
- CallHelper(MediaData* aSample, TimeStamp aDecodeStartTime)
- {
- (mThis->*mResolveMethod)(aSample, aDecodeStartTime);
- }
-
- void OnResolved(MediaData* aSample, TimeStamp aDecodeStartTime) override
- {
- CallHelper<ResolveMethodType>(aSample, aDecodeStartTime);
- }
-
- void OnRejected(MediaDecoderReader::NotDecodedReason aReason) override
- {
- (mThis->*mRejectMethod)(aReason);
- }
-
- RefPtr<ThisType> mThis;
- ResolveMethodType mResolveMethod;
- RejectMethodType mRejectMethod;
- };
-
- template<typename ResolveFunctionType, typename RejectFunctionType>
- struct FunctionCallback : public CallbackBase
- {
- FunctionCallback(ResolveFunctionType&& aResolveFuntion, RejectFunctionType&& aRejectFunction)
- : mResolveFuntion(Move(aResolveFuntion)), mRejectFunction(Move(aRejectFunction))
- {
- }
-
- template<typename F>
- typename EnableIf<ArgType1Check<F>::value, void>::Type
- CallHelper(MediaData* aSample, TimeStamp)
- {
- mResolveFuntion(aSample);
- }
-
- template<typename F>
- typename EnableIf<ArgType2Check<F>::value, void>::Type
- CallHelper(MediaData* aSample, TimeStamp aDecodeStartTime)
- {
- mResolveFuntion(aSample, aDecodeStartTime);
- }
-
- void OnResolved(MediaData* aSample, TimeStamp aDecodeStartTime) override
- {
- CallHelper<ResolveFunctionType>(aSample, aDecodeStartTime);
- }
-
- void OnRejected(MediaDecoderReader::NotDecodedReason aReason) override
- {
- 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;
- };
+private:
+ MediaCallbackExc<AudioCallbackData> mAudioCallback;
+ MediaCallbackExc<VideoCallbackData> mVideoCallback;
+ MediaCallbackExc<WaitCallbackData> mAudioWaitCallback;
+ MediaCallbackExc<WaitCallbackData> mVideoWaitCallback;
public:
MediaDecoderReaderWrapper(bool aIsRealTime,
AbstractThread* aOwnerThread,
MediaDecoderReader* aReader);
media::TimeUnit StartTime() const;
RefPtr<MetadataPromise> ReadMetadata();
RefPtr<HaveStartTimePromise> AwaitStartTime();
- template<typename ThisType, typename ResolveMethodType, typename RejectMethodType>
- CallbackID
- SetAudioCallback(ThisType* aThisVal,
- ResolveMethodType aResolveMethod,
- RejectMethodType aRejectMethod)
- {
- MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
- MOZ_ASSERT(!mRequestAudioDataCB,
- "Please cancel the original callback before setting a new one.");
-
- mRequestAudioDataCB.reset(
- new MethodCallback<ThisType, ResolveMethodType, RejectMethodType>(
- aThisVal, aResolveMethod, aRejectMethod));
-
- return mAudioCallbackID;
- }
-
- template<typename ResolveFunction, typename RejectFunction>
- CallbackID
- SetAudioCallback(ResolveFunction&& aResolveFunction,
- RejectFunction&& aRejectFunction)
- {
- MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
- MOZ_ASSERT(!mRequestAudioDataCB,
- "Please cancel the original callback before setting a new one.");
-
- mRequestAudioDataCB.reset(
- new FunctionCallback<ResolveFunction, RejectFunction>(
- Move(aResolveFunction), Move(aRejectFunction)));
-
- return mAudioCallbackID;
- }
-
- template<typename ThisType, typename ResolveMethodType, typename RejectMethodType>
- CallbackID
- SetVideoCallback(ThisType* aThisVal,
- ResolveMethodType aResolveMethod,
- RejectMethodType aRejectMethod)
- {
- MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
- MOZ_ASSERT(!mRequestVideoDataCB,
- "Please cancel the original callback before setting a new one.");
-
- mRequestVideoDataCB.reset(
- new MethodCallback<ThisType, ResolveMethodType, RejectMethodType>(
- aThisVal, aResolveMethod, aRejectMethod));
-
- return mVideoCallbackID;
- }
-
- template<typename ResolveFunction, typename RejectFunction>
- CallbackID
- SetVideoCallback(ResolveFunction&& aResolveFunction,
- RejectFunction&& aRejectFunction)
- {
- MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
- MOZ_ASSERT(!mRequestVideoDataCB,
- "Please cancel the original callback before setting a new one.");
-
- 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);
+ 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();
void RequestVideoData(bool aSkipToNextKeyframe, media::TimeUnit aTimeThreshold);
// NOTE: please set callbacks before invoking WaitForData()!
void WaitForData(MediaData::Type aType);
@@ -423,44 +120,27 @@ public:
void SetCDMProxy(CDMProxy* aProxy) { mReader->SetCDMProxy(aProxy); }
#endif
private:
~MediaDecoderReaderWrapper();
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);
+ MediaCallbackExc<WaitCallbackData>& 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;
- 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_
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -913,61 +913,61 @@ nsresult MediaDecoderStateMachine::Init(
OwnerThread()->Dispatch(NewRunnableMethod(this, &MediaDecoderStateMachine::ReadMetadata));
return NS_OK;
}
void
MediaDecoderStateMachine::SetMediaDecoderReaderWrapperCallback()
{
- mAudioCallbackID =
- mReader->SetAudioCallback(this,
- &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);
+ 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<MediaDecoderReader::NotDecodedReason>());
+ }
+ });
+
+ 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<MediaDecoderReader::NotDecodedReason>());
+ }
+ });
+
+ mAudioWaitCallback = mReader->AudioWaitCallback().Connect(
+ mTaskQueue, [this] (WaitCallbackData aData) {
+ if (aData.is<MediaData::Type>()) {
+ EnsureAudioDecodeTaskQueued();
+ }
+ });
+
+ mVideoWaitCallback = mReader->VideoWaitCallback().Connect(
+ mTaskQueue, [this] (WaitCallbackData aData) {
+ if (aData.is<MediaData::Type>()) {
+ EnsureVideoDecodeTaskQueued();
+ }
+ });
}
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);
+ MOZ_ASSERT(OnTaskQueue());
+ mAudioCallback.Disconnect();
+ mVideoCallback.Disconnect();
+ mAudioWaitCallback.Disconnect();
+ mVideoWaitCallback.Disconnect();
}
void MediaDecoderStateMachine::StopPlayback()
{
MOZ_ASSERT(OnTaskQueue());
DECODER_LOG("StopPlayback()");
mOnPlaybackEvent.Notify(MediaEventType::PlaybackStopped);
--- a/dom/media/MediaDecoderStateMachine.h
+++ b/dom/media/MediaDecoderStateMachine.h
@@ -354,26 +354,16 @@ private:
// be held.
bool IsPlaying() const;
// TODO: Those callback function may receive demuxed-only data.
// Need to figure out a suitable API name for this case.
void OnAudioDecoded(MediaData* aAudioSample);
void OnVideoDecoded(MediaData* aVideoSample, TimeStamp aDecodeStartTime);
void OnNotDecoded(MediaData::Type aType, MediaDecoderReader::NotDecodedReason aReason);
- void OnAudioNotDecoded(MediaDecoderReader::NotDecodedReason aReason)
- {
- MOZ_ASSERT(OnTaskQueue());
- OnNotDecoded(MediaData::AUDIO_DATA, aReason);
- }
- void OnVideoNotDecoded(MediaDecoderReader::NotDecodedReason aReason)
- {
- MOZ_ASSERT(OnTaskQueue());
- OnNotDecoded(MediaData::VIDEO_DATA, aReason);
- }
// 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,
TrackInfo::kVideoTrack));
protected:
virtual ~MediaDecoderStateMachine();
@@ -832,22 +822,22 @@ private:
// playback. The flags below are true when the corresponding stream is
// 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;
- CallbackID mWaitAudioCallbackID;
+ MediaEventListener mAudioCallback;
+ MediaEventListener mVideoCallback;
+ MediaEventListener mAudioWaitCallback;
+ MediaEventListener mVideoWaitCallback;
+
const char* AudioRequestStatus() const;
-
- CallbackID mVideoCallbackID;
- CallbackID mWaitVideoCallbackID;
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
// it has stopped.
--- a/dom/media/NextFrameSeekTask.cpp
+++ b/dom/media/NextFrameSeekTask.cpp
@@ -412,68 +412,57 @@ NextFrameSeekTask::OnVideoNotDecoded(Med
void
NextFrameSeekTask::SetMediaDecoderReaderWrapperCallback()
{
AssertOwnerThread();
// Register dummy callbcak for audio decoding since we don't need to handle
// the decoded audio samples.
- mAudioCallbackID =
- mReader->SetAudioCallback(this, &NextFrameSeekTask::OnAudioDecoded,
- &NextFrameSeekTask::OnAudioNotDecoded);
-
- mVideoCallbackID =
- mReader->SetVideoCallback(this, &NextFrameSeekTask::OnVideoDecoded,
- &NextFrameSeekTask::OnVideoNotDecoded);
+ mAudioCallback = mReader->AudioCallback().Connect(
+ OwnerThread(), [this] (AudioCallbackData aData) {
+ if (aData.is<MediaData*>()) {
+ OnAudioDecoded(aData.as<MediaData*>());
+ } else {
+ OnAudioNotDecoded(aData.as<MediaDecoderReader::NotDecodedReason>());
+ }
+ });
- RefPtr<NextFrameSeekTask> self = this;
- mWaitAudioCallbackID =
- mReader->SetWaitAudioCallback(
- [self] (MediaData::Type aType) -> void {
- self->AssertOwnerThread();
- // We don't make an audio decode request here, instead, let MDSM to
- // trigger further audio decode tasks if MDSM itself needs to play audio.
- },
- [self] (WaitForDataRejectValue aRejection) -> void {
- self->AssertOwnerThread();
- });
+ mVideoCallback = mReader->VideoCallback().Connect(
+ OwnerThread(), [this] (VideoCallbackData aData) {
+ typedef Tuple<MediaData*, TimeStamp> Type;
+ if (aData.is<Type>()) {
+ OnVideoDecoded(Get<0>(aData.as<Type>()));
+ } else {
+ OnVideoNotDecoded(aData.as<MediaDecoderReader::NotDecodedReason>());
+ }
+ });
- mWaitVideoCallbackID =
- mReader->SetWaitVideoCallback(
- [self] (MediaData::Type aType) -> void {
- self->AssertOwnerThread();
- self->EnsureVideoDecodeTaskQueued();
- },
- [self] (WaitForDataRejectValue aRejection) -> void {
- self->AssertOwnerThread();
- });
+ mAudioWaitCallback = mReader->AudioWaitCallback().Connect(
+ OwnerThread(), [this] (WaitCallbackData aData) {
+ // We don't make an audio decode request here, instead, let MDSM to
+ // trigger further audio decode tasks if MDSM itself needs to play audio.
+ });
- DECODER_LOG("NextFrameSeekTask set audio callbacks: mVideoCallbackID = %d\n", (int)mAudioCallbackID);
- DECODER_LOG("NextFrameSeekTask set video callbacks: mVideoCallbackID = %d\n", (int)mVideoCallbackID);
- DECODER_LOG("NextFrameSeekTask set wait audio callbacks: mWaitAudioCallbackID = %d\n", (int)mWaitAudioCallbackID);
- DECODER_LOG("NextFrameSeekTask set wait video callbacks: mWaitVideoCallbackID = %d\n", (int)mWaitVideoCallbackID);
+ mVideoWaitCallback = mReader->VideoWaitCallback().Connect(
+ OwnerThread(), [this] (WaitCallbackData aData) {
+ if (aData.is<MediaData::Type>()) {
+ EnsureVideoDecodeTaskQueued();
+ }
+ });
}
void
NextFrameSeekTask::CancelMediaDecoderReaderWrapperCallback()
{
AssertOwnerThread();
-
- DECODER_LOG("NextFrameSeekTask cancel audio callbacks: mAudioCallbackID = %d\n", (int)mAudioCallbackID);
- mReader->CancelAudioCallback(mAudioCallbackID);
-
- DECODER_LOG("NextFrameSeekTask cancel video callbacks: mVideoCallbackID = %d\n", (int)mVideoCallbackID);
- mReader->CancelVideoCallback(mVideoCallbackID);
-
- DECODER_LOG("NextFrameSeekTask cancel wait audio callbacks: mWaitAudioCallbackID = %d\n", (int)mWaitAudioCallbackID);
- mReader->CancelWaitAudioCallback(mWaitAudioCallbackID);
-
- DECODER_LOG("NextFrameSeekTask cancel wait video callbacks: mWaitVideoCallbackID = %d\n", (int)mWaitVideoCallbackID);
- mReader->CancelWaitVideoCallback(mWaitVideoCallbackID);
+ mAudioCallback.Disconnect();
+ mVideoCallback.Disconnect();
+ mAudioWaitCallback.Disconnect();
+ mVideoWaitCallback.Disconnect();
}
void
NextFrameSeekTask::UpdateSeekTargetTime()
{
AssertOwnerThread();
RefPtr<MediaData> data = mVideoQueue.PeekFront();
--- a/dom/media/NextFrameSeekTask.h
+++ b/dom/media/NextFrameSeekTask.h
@@ -86,21 +86,18 @@ private:
/*
* Internal state.
*/
const int64_t mCurrentTimeBeforeSeek;
const bool mHasAudio;
const bool mHasVideo;
media::TimeUnit mDuration;
- /*
- * Track the current seek promise made by the reader.
- */
- CallbackID mAudioCallbackID;
- CallbackID mVideoCallbackID;
- CallbackID mWaitAudioCallbackID;
- CallbackID mWaitVideoCallbackID;
+ MediaEventListener mAudioCallback;
+ MediaEventListener mVideoCallback;
+ MediaEventListener mAudioWaitCallback;
+ MediaEventListener mVideoWaitCallback;
};
} // namespace media
} // namespace mozilla
#endif /* NEXTFRAME_SEEK_TASK_H */