зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset 15058cd33731 (bug 1250054) for leaks
--HG-- extra : rebase_source : 4586059d7b80f6d417aa07dbf9877b170a64ccab
This commit is contained in:
Родитель
c7515d6856
Коммит
cee1a58936
|
@ -1,148 +0,0 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
#include "mozilla/MozPromise.h"
|
||||
#include "MediaDecoderReaderWrapper.h"
|
||||
|
||||
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 {
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(StartTimeRendezvous);
|
||||
typedef MediaDecoderReader::AudioDataPromise AudioDataPromise;
|
||||
typedef MediaDecoderReader::VideoDataPromise VideoDataPromise;
|
||||
|
||||
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<typename PromiseType>
|
||||
struct PromiseSampleType {
|
||||
typedef typename PromiseType::ResolveValueType::element_type Type;
|
||||
};
|
||||
|
||||
template<typename PromiseType, MediaData::Type SampleType>
|
||||
RefPtr<PromiseType>
|
||||
ProcessFirstSample(typename PromiseSampleType<PromiseType>::Type* aData)
|
||||
{
|
||||
typedef typename PromiseSampleType<PromiseType>::Type DataType;
|
||||
typedef typename PromiseType::Private PromisePrivate;
|
||||
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
||||
|
||||
MaybeSetChannelStartTime<SampleType>(aData->mTime);
|
||||
|
||||
RefPtr<PromisePrivate> p = new PromisePrivate(__func__);
|
||||
RefPtr<DataType> 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(MediaDecoderReader::CANCELED, __func__);
|
||||
});
|
||||
|
||||
return p.forget();
|
||||
}
|
||||
|
||||
template<MediaData::Type SampleType>
|
||||
void FirstSampleRejected(MediaDecoderReader::NotDecodedReason aReason)
|
||||
{
|
||||
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
||||
if (aReason == MediaDecoderReader::DECODE_ERROR) {
|
||||
mHaveStartTimePromise.RejectIfExists(false, __func__);
|
||||
} else if (aReason == MediaDecoderReader::END_OF_STREAM) {
|
||||
LOG("StartTimeRendezvous=%p SampleType(%d) Has no samples.",
|
||||
this, SampleType);
|
||||
MaybeSetChannelStartTime<SampleType>(INT64_MAX);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
|
@ -1,24 +0,0 @@
|
|||
/* -*- 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 MediaDecoderReaderWrapper_h_
|
||||
#define MediaDecoderReaderWrapper_h_
|
||||
|
||||
#include "mozilla/AbstractThread.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
|
||||
#include "MediaDecoderReader.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class StartTimeRendezvous;
|
||||
|
||||
typedef MozPromise<bool, bool, /* isExclusive = */ false> HaveStartTimePromise;
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // MediaDecoderReaderWrapper_h_
|
|
@ -694,6 +694,133 @@ private:
|
|||
// Used to dispatch another round schedule with specific target time.
|
||||
DelayedScheduler mDelayedScheduler;
|
||||
|
||||
// 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.
|
||||
class StartTimeRendezvous {
|
||||
public:
|
||||
typedef MediaDecoderReader::AudioDataPromise AudioDataPromise;
|
||||
typedef MediaDecoderReader::VideoDataPromise VideoDataPromise;
|
||||
typedef MozPromise<bool, bool, /* isExclusive = */ false> HaveStartTimePromise;
|
||||
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(StartTimeRendezvous);
|
||||
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<typename PromiseType>
|
||||
struct PromiseSampleType {
|
||||
typedef typename PromiseType::ResolveValueType::element_type Type;
|
||||
};
|
||||
|
||||
template<typename PromiseType, MediaData::Type SampleType>
|
||||
RefPtr<PromiseType> ProcessFirstSample(typename PromiseSampleType<PromiseType>::Type* aData)
|
||||
{
|
||||
typedef typename PromiseSampleType<PromiseType>::Type DataType;
|
||||
typedef typename PromiseType::Private PromisePrivate;
|
||||
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
||||
|
||||
MaybeSetChannelStartTime<SampleType>(aData->mTime);
|
||||
|
||||
RefPtr<PromisePrivate> p = new PromisePrivate(__func__);
|
||||
RefPtr<DataType> data = aData;
|
||||
RefPtr<StartTimeRendezvous> self = this;
|
||||
AwaitStartTime()->Then(mOwnerThread, __func__,
|
||||
[p, data, self] () -> void {
|
||||
MOZ_ASSERT(self->mOwnerThread->IsCurrentThreadIn());
|
||||
p->Resolve(data, __func__);
|
||||
},
|
||||
[p] () -> void { p->Reject(MediaDecoderReader::CANCELED, __func__); });
|
||||
|
||||
return p.forget();
|
||||
}
|
||||
|
||||
template<MediaData::Type SampleType>
|
||||
void FirstSampleRejected(MediaDecoderReader::NotDecodedReason aReason)
|
||||
{
|
||||
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
||||
if (aReason == MediaDecoderReader::DECODE_ERROR) {
|
||||
mHaveStartTimePromise.RejectIfExists(false, __func__);
|
||||
} else if (aReason == MediaDecoderReader::END_OF_STREAM) {
|
||||
MOZ_LOG(gMediaDecoderLog, LogLevel::Debug,
|
||||
("StartTimeRendezvous=%p SampleType(%d) Has no samples.", this, SampleType));
|
||||
MaybeSetChannelStartTime<SampleType>(INT64_MAX);
|
||||
}
|
||||
}
|
||||
|
||||
bool HaveStartTime() { return mAudioStartTime.isSome() && mVideoStartTime.isSome(); }
|
||||
int64_t StartTime()
|
||||
{
|
||||
int64_t time = std::min(mAudioStartTime.ref(), mVideoStartTime.ref());
|
||||
return time == INT64_MAX ? 0 : time;
|
||||
}
|
||||
private:
|
||||
virtual ~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;
|
||||
}
|
||||
|
||||
MOZ_LOG(gMediaDecoderLog, LogLevel::Debug,
|
||||
("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;
|
||||
};
|
||||
RefPtr<StartTimeRendezvous> mStartTimeRendezvous;
|
||||
|
||||
bool HaveStartTime() { return mStartTimeRendezvous && mStartTimeRendezvous->HaveStartTime(); }
|
||||
int64_t StartTime() { return mStartTimeRendezvous->StartTime(); }
|
||||
|
||||
// Queue of audio frames. This queue is threadsafe, and is accessed from
|
||||
// the audio, decoder, state machine, and main threads.
|
||||
MediaQueue<MediaData> mAudioQueue;
|
||||
|
|
|
@ -214,7 +214,6 @@ UNIFIED_SOURCES += [
|
|||
'MediaData.cpp',
|
||||
'MediaDecoder.cpp',
|
||||
'MediaDecoderReader.cpp',
|
||||
'MediaDecoderReaderWrapper.cpp',
|
||||
'MediaDecoderStateMachine.cpp',
|
||||
'MediaDeviceInfo.cpp',
|
||||
'MediaDevices.cpp',
|
||||
|
|
Загрузка…
Ссылка в новой задаче