зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset 66f39ef1bdce (bug 1309516)
This commit is contained in:
Родитель
b7af1e68a5
Коммит
ec968f913f
|
@ -9,6 +9,135 @@
|
|||
|
||||
namespace mozilla {
|
||||
|
||||
extern LazyLogModule gMediaDecoderLog;
|
||||
|
||||
#undef LOG
|
||||
#define LOG(...) \
|
||||
MOZ_LOG(gMediaDecoderLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
|
||||
|
||||
// StartTimeRendezvous is a helper class that quarantines the first sample
|
||||
// until it gets a sample from both channels, such that we can be guaranteed
|
||||
// to know the start time by the time On{Audio,Video}Decoded is called on MDSM.
|
||||
class StartTimeRendezvous {
|
||||
typedef MediaDecoderReader::MediaDataPromise MediaDataPromise;
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(StartTimeRendezvous);
|
||||
|
||||
public:
|
||||
StartTimeRendezvous(AbstractThread* aOwnerThread,
|
||||
bool aHasAudio,
|
||||
bool aHasVideo,
|
||||
bool aForceZeroStartTime)
|
||||
: mOwnerThread(aOwnerThread)
|
||||
{
|
||||
if (aForceZeroStartTime) {
|
||||
mAudioStartTime.emplace(0);
|
||||
mVideoStartTime.emplace(0);
|
||||
return;
|
||||
}
|
||||
if (!aHasAudio) {
|
||||
mAudioStartTime.emplace(INT64_MAX);
|
||||
}
|
||||
if (!aHasVideo) {
|
||||
mVideoStartTime.emplace(INT64_MAX);
|
||||
}
|
||||
}
|
||||
|
||||
void Destroy()
|
||||
{
|
||||
mAudioStartTime = Some(mAudioStartTime.refOr(INT64_MAX));
|
||||
mVideoStartTime = Some(mVideoStartTime.refOr(INT64_MAX));
|
||||
mHaveStartTimePromise.RejectIfExists(false, __func__);
|
||||
}
|
||||
|
||||
RefPtr<HaveStartTimePromise> AwaitStartTime()
|
||||
{
|
||||
if (HaveStartTime()) {
|
||||
return HaveStartTimePromise::CreateAndResolve(true, __func__);
|
||||
}
|
||||
return mHaveStartTimePromise.Ensure(__func__);
|
||||
}
|
||||
|
||||
template<MediaData::Type SampleType>
|
||||
RefPtr<MediaDataPromise>
|
||||
ProcessFirstSample(MediaData* aData)
|
||||
{
|
||||
typedef typename MediaDataPromise::Private PromisePrivate;
|
||||
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
||||
|
||||
MaybeSetChannelStartTime<SampleType>(aData->mTime);
|
||||
|
||||
RefPtr<PromisePrivate> p = new PromisePrivate(__func__);
|
||||
RefPtr<MediaData> data = aData;
|
||||
RefPtr<StartTimeRendezvous> self = this;
|
||||
AwaitStartTime()->Then(
|
||||
mOwnerThread, __func__,
|
||||
[p, data, self] () {
|
||||
MOZ_ASSERT(self->mOwnerThread->IsCurrentThreadIn());
|
||||
p->Resolve(data, __func__);
|
||||
},
|
||||
[p] () {
|
||||
p->Reject(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
|
||||
});
|
||||
|
||||
return p.forget();
|
||||
}
|
||||
|
||||
template<MediaData::Type SampleType>
|
||||
void FirstSampleRejected(const MediaResult& aError)
|
||||
{
|
||||
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
||||
if (aError == NS_ERROR_DOM_MEDIA_END_OF_STREAM) {
|
||||
LOG("StartTimeRendezvous=%p SampleType(%d) Has no samples.",
|
||||
this, SampleType);
|
||||
MaybeSetChannelStartTime<SampleType>(INT64_MAX);
|
||||
} else if (aError != NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA) {
|
||||
mHaveStartTimePromise.RejectIfExists(false, __func__);
|
||||
}
|
||||
}
|
||||
|
||||
bool HaveStartTime() const
|
||||
{
|
||||
return mAudioStartTime.isSome() && mVideoStartTime.isSome();
|
||||
}
|
||||
|
||||
int64_t StartTime() const
|
||||
{
|
||||
int64_t time = std::min(mAudioStartTime.ref(), mVideoStartTime.ref());
|
||||
return time == INT64_MAX ? 0 : time;
|
||||
}
|
||||
|
||||
private:
|
||||
~StartTimeRendezvous() {}
|
||||
|
||||
template<MediaData::Type SampleType>
|
||||
void MaybeSetChannelStartTime(int64_t aStartTime)
|
||||
{
|
||||
if (ChannelStartTime(SampleType).isSome()) {
|
||||
// If we're initialized with aForceZeroStartTime=true, the channel start
|
||||
// times are already set.
|
||||
return;
|
||||
}
|
||||
|
||||
LOG("StartTimeRendezvous=%p Setting SampleType(%d) start time to %lld",
|
||||
this, SampleType, aStartTime);
|
||||
|
||||
ChannelStartTime(SampleType).emplace(aStartTime);
|
||||
if (HaveStartTime()) {
|
||||
mHaveStartTimePromise.ResolveIfExists(true, __func__);
|
||||
}
|
||||
}
|
||||
|
||||
Maybe<int64_t>& ChannelStartTime(MediaData::Type aType)
|
||||
{
|
||||
return aType == MediaData::AUDIO_DATA ? mAudioStartTime : mVideoStartTime;
|
||||
}
|
||||
|
||||
MozPromiseHolder<HaveStartTimePromise> mHaveStartTimePromise;
|
||||
RefPtr<AbstractThread> mOwnerThread;
|
||||
Maybe<int64_t> mAudioStartTime;
|
||||
Maybe<int64_t> mVideoStartTime;
|
||||
};
|
||||
|
||||
MediaDecoderReaderWrapper::MediaDecoderReaderWrapper(AbstractThread* aOwnerThread,
|
||||
MediaDecoderReader* aReader)
|
||||
: mForceZeroStartTime(aReader->ForceZeroStartTime())
|
||||
|
@ -222,6 +351,10 @@ MediaDecoderReaderWrapper::Shutdown()
|
|||
MOZ_ASSERT(!mVideoDataRequest.Exists());
|
||||
|
||||
mShutdown = true;
|
||||
if (mStartTimeRendezvous) {
|
||||
mStartTimeRendezvous->Destroy();
|
||||
mStartTimeRendezvous = nullptr;
|
||||
}
|
||||
return InvokeAsync(mReader->OwnerThread(), mReader.get(), __func__,
|
||||
&MediaDecoderReader::Shutdown);
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
|
||||
namespace mozilla {
|
||||
|
||||
class StartTimeRendezvous;
|
||||
|
||||
typedef MozPromise<bool, bool, /* isExclusive = */ false> HaveStartTimePromise;
|
||||
|
||||
typedef Variant<MediaData*, MediaResult> AudioCallbackData;
|
||||
|
@ -127,6 +129,7 @@ private:
|
|||
const RefPtr<MediaDecoderReader> mReader;
|
||||
|
||||
bool mShutdown = false;
|
||||
RefPtr<StartTimeRendezvous> mStartTimeRendezvous;
|
||||
Maybe<media::TimeUnit> mStartTime;
|
||||
|
||||
MozPromiseRequestHolder<MediaDataPromise> mAudioDataRequest;
|
||||
|
|
Загрузка…
Ссылка в новой задаче