зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1266027 part 1 - make the MediaDecoderReaderWrapper as a proxy of requesting media data; r=jwwang
MozReview-Commit-ID: CgTBPmtbNfh --HG-- extra : transplant_source : %16%86%F676/S%C8%5Dj%86%9C%09%0E%D9%16L%DB%92y
This commit is contained in:
Родитель
c089c3f45c
Коммит
f78f42e9df
|
@ -0,0 +1,50 @@
|
|||
#include "MediaCallbackID.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
char const* CallbackID::INVALID_TAG = "INVALID_TAG";
|
||||
int32_t const CallbackID::INVALID_ID = -1;
|
||||
|
||||
CallbackID::CallbackID()
|
||||
: mTag(INVALID_TAG), mID(INVALID_ID)
|
||||
{
|
||||
}
|
||||
|
||||
CallbackID::CallbackID(char const* aTag, int32_t aID /* = 0*/)
|
||||
: mTag(aTag), mID(aID)
|
||||
{
|
||||
}
|
||||
|
||||
CallbackID&
|
||||
CallbackID::operator++()
|
||||
{
|
||||
++mID;
|
||||
return *this;
|
||||
}
|
||||
|
||||
CallbackID
|
||||
CallbackID::operator++(int)
|
||||
{
|
||||
CallbackID ret = *this;
|
||||
++(*this); // call prefix++
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool
|
||||
CallbackID::operator==(const CallbackID& rhs) const
|
||||
{
|
||||
return (strcmp(mTag, rhs.mTag) == 0) && (mID == rhs.mID);
|
||||
}
|
||||
|
||||
bool
|
||||
CallbackID::operator!=(const CallbackID& rhs) const
|
||||
{
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
CallbackID::operator int() const
|
||||
{
|
||||
return mID;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,38 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef MediaCallbackID_h_
|
||||
#define MediaCallbackID_h_
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
struct CallbackID
|
||||
{
|
||||
static char const* INVALID_TAG;
|
||||
static int32_t const INVALID_ID;
|
||||
|
||||
CallbackID();
|
||||
|
||||
explicit CallbackID(char const* aTag, int32_t aID = 0);
|
||||
|
||||
CallbackID& operator++(); // prefix++
|
||||
|
||||
CallbackID operator++(int); // postfix++
|
||||
|
||||
bool operator==(const CallbackID& rhs) const;
|
||||
|
||||
bool operator!=(const CallbackID& rhs) const;
|
||||
|
||||
operator int() const;
|
||||
|
||||
private:
|
||||
char const* mTag;
|
||||
int32_t mID;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // MediaCallbackID_h_
|
|
@ -144,6 +144,8 @@ MediaDecoderReaderWrapper::MediaDecoderReaderWrapper(bool aIsRealTime,
|
|||
: mForceZeroStartTime(aIsRealTime || aReader->ForceZeroStartTime())
|
||||
, mOwnerThread(aOwnerThread)
|
||||
, mReader(aReader)
|
||||
, mAudioCallbackID("AudioCallbackID")
|
||||
, mVideoCallbackID("VideoCallbackID")
|
||||
{}
|
||||
|
||||
MediaDecoderReaderWrapper::~MediaDecoderReaderWrapper()
|
||||
|
@ -178,11 +180,30 @@ MediaDecoderReaderWrapper::AwaitStartTime()
|
|||
return mStartTimeRendezvous->AwaitStartTime();
|
||||
}
|
||||
|
||||
RefPtr<MediaDecoderReaderWrapper::MediaDataPromise>
|
||||
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::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);
|
||||
|
@ -194,18 +215,31 @@ MediaDecoderReaderWrapper::RequestAudioData()
|
|||
->CompletionPromise();
|
||||
}
|
||||
|
||||
return p->Then(mOwnerThread, __func__, this,
|
||||
&MediaDecoderReaderWrapper::OnSampleDecoded,
|
||||
&MediaDecoderReaderWrapper::OnNotDecoded)
|
||||
->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());
|
||||
},
|
||||
[self] (MediaDecoderReader::NotDecodedReason aReason) {
|
||||
MOZ_ASSERT(self->mRequestAudioDataCB);
|
||||
self->mAudioDataRequest.Complete();
|
||||
self->OnNotDecoded(self->mRequestAudioDataCB.get(), aReason);
|
||||
}));
|
||||
}
|
||||
|
||||
RefPtr<MediaDecoderReaderWrapper::MediaDataPromise>
|
||||
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()) {
|
||||
|
@ -223,10 +257,32 @@ MediaDecoderReaderWrapper::RequestVideoData(bool aSkipToNextKeyframe,
|
|||
->CompletionPromise();
|
||||
}
|
||||
|
||||
return p->Then(mOwnerThread, __func__, this,
|
||||
&MediaDecoderReaderWrapper::OnSampleDecoded,
|
||||
&MediaDecoderReaderWrapper::OnNotDecoded)
|
||||
->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);
|
||||
},
|
||||
[self] (MediaDecoderReader::NotDecodedReason aReason) {
|
||||
MOZ_ASSERT(self->mRequestVideoDataCB);
|
||||
self->mVideoDataRequest.Complete();
|
||||
self->OnNotDecoded(self->mRequestVideoDataCB.get(), aReason);
|
||||
}));
|
||||
}
|
||||
|
||||
bool
|
||||
MediaDecoderReaderWrapper::IsRequestingAudioData() const
|
||||
{
|
||||
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
||||
return mAudioDataRequest.Exists();
|
||||
}
|
||||
|
||||
bool
|
||||
MediaDecoderReaderWrapper::IsRequestingVidoeData() const
|
||||
{
|
||||
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
||||
return mVideoDataRequest.Exists();
|
||||
}
|
||||
|
||||
RefPtr<MediaDecoderReader::SeekPromise>
|
||||
|
@ -277,6 +333,10 @@ void
|
|||
MediaDecoderReaderWrapper::ResetDecode()
|
||||
{
|
||||
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
||||
|
||||
mAudioDataRequest.DisconnectIfExists();
|
||||
mVideoDataRequest.DisconnectIfExists();
|
||||
|
||||
nsCOMPtr<nsIRunnable> r =
|
||||
NS_NewRunnableMethod(mReader, &MediaDecoderReader::ResetDecode);
|
||||
mReader->OwnerThread()->Dispatch(r.forget());
|
||||
|
@ -286,6 +346,11 @@ 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();
|
||||
|
@ -323,12 +388,25 @@ MediaDecoderReaderWrapper::OnMetadataRead(MetadataHolder* aMetadata)
|
|||
}
|
||||
|
||||
void
|
||||
MediaDecoderReaderWrapper::OnSampleDecoded(MediaData* aSample)
|
||||
MediaDecoderReaderWrapper::OnSampleDecoded(CallbackBase* aCallback,
|
||||
MediaData* aSample,
|
||||
TimeStamp aDecodeStartTime)
|
||||
{
|
||||
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
||||
if (!mShutdown) {
|
||||
aSample->AdjustForStartTime(StartTime().ToMicroseconds());
|
||||
}
|
||||
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
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "nsISupportsImpl.h"
|
||||
|
||||
#include "MediaDecoderReader.h"
|
||||
#include "MediaCallbackID.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -33,6 +34,135 @@ class MediaDecoderReaderWrapper {
|
|||
typedef MediaDecoderReader::BufferedUpdatePromise BufferedUpdatePromise;
|
||||
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;
|
||||
};
|
||||
|
||||
public:
|
||||
MediaDecoderReaderWrapper(bool aIsRealTime,
|
||||
AbstractThread* aOwnerThread,
|
||||
|
@ -41,9 +171,83 @@ public:
|
|||
media::TimeUnit StartTime() const;
|
||||
RefPtr<MetadataPromise> ReadMetadata();
|
||||
RefPtr<HaveStartTimePromise> AwaitStartTime();
|
||||
RefPtr<MediaDataPromise> RequestAudioData();
|
||||
RefPtr<MediaDataPromise> RequestVideoData(bool aSkipToNextKeyframe,
|
||||
media::TimeUnit aTimeThreshold);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void CancelAudioCallback(CallbackID aID);
|
||||
void CancelVideoCallback(CallbackID aID);
|
||||
|
||||
// NOTE: please set callbacks before requesting audio/video data!
|
||||
void RequestAudioData();
|
||||
void RequestVideoData(bool aSkipToNextKeyframe, media::TimeUnit aTimeThreshold);
|
||||
|
||||
bool IsRequestingAudioData() const;
|
||||
bool IsRequestingVidoeData() const;
|
||||
|
||||
RefPtr<SeekPromise> Seek(SeekTarget aTarget, media::TimeUnit aEndTime);
|
||||
RefPtr<WaitForDataPromise> WaitForData(MediaData::Type aType);
|
||||
RefPtr<BufferedUpdatePromise> UpdateBufferedWithPromise();
|
||||
|
@ -96,8 +300,10 @@ private:
|
|||
|
||||
void OnMetadataRead(MetadataHolder* aMetadata);
|
||||
void OnMetadataNotRead() {}
|
||||
void OnSampleDecoded(MediaData* aSample);
|
||||
void OnNotDecoded() {}
|
||||
void OnSampleDecoded(CallbackBase* aCallback, MediaData* aSample,
|
||||
TimeStamp aVideoDecodeStartTime);
|
||||
void OnNotDecoded(CallbackBase* aCallback,
|
||||
MediaDecoderReader::NotDecodedReason aReason);
|
||||
|
||||
const bool mForceZeroStartTime;
|
||||
const RefPtr<AbstractThread> mOwnerThread;
|
||||
|
@ -105,6 +311,17 @@ private:
|
|||
|
||||
bool mShutdown = false;
|
||||
RefPtr<StartTimeRendezvous> mStartTimeRendezvous;
|
||||
|
||||
UniquePtr<CallbackBase> mRequestAudioDataCB;
|
||||
UniquePtr<CallbackBase> mRequestVideoDataCB;
|
||||
MozPromiseRequestHolder<MediaDataPromise> mAudioDataRequest;
|
||||
MozPromiseRequestHolder<MediaDataPromise> mVideoDataRequest;
|
||||
|
||||
/*
|
||||
* These callback ids are used to prevent mis-canceling callback.
|
||||
*/
|
||||
CallbackID mAudioCallbackID;
|
||||
CallbackID mVideoCallbackID;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -108,6 +108,7 @@ EXPORTS += [
|
|||
'Intervals.h',
|
||||
'Latency.h',
|
||||
'MediaCache.h',
|
||||
'MediaCallbackID.h',
|
||||
'MediaData.h',
|
||||
'MediaDataDemuxer.h',
|
||||
'MediaDecoder.h',
|
||||
|
@ -218,6 +219,7 @@ UNIFIED_SOURCES += [
|
|||
'GraphDriver.cpp',
|
||||
'Latency.cpp',
|
||||
'MediaCache.cpp',
|
||||
'MediaCallbackID.cpp',
|
||||
'MediaData.cpp',
|
||||
'MediaDecoder.cpp',
|
||||
'MediaDecoderReader.cpp',
|
||||
|
|
|
@ -892,7 +892,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
bool Exists() { return !!mRequest; }
|
||||
bool Exists() const { return !!mRequest; }
|
||||
|
||||
private:
|
||||
RefPtr<typename PromiseType::Request> mRequest;
|
||||
|
|
Загрузка…
Ссылка в новой задаче