Bug 1407810 - Use DDLogger in media stack - r=jwwang

Mostly-mechanical additions:
- Log constructions&destructions, usually by just inheriting from
  DecoderDoctorLifeLogger, otherwise with explicit log commands (for internal
  classes for which DecoderDoctorTraits can't be specialized),
- Log links between most objects, e.g.: Media element -> decoder -> state
  machine -> reader -> demuxer -> resource, etc.

And logging some important properties and events (JS events, duration change,
frames being decoded, etc.)

More will be added later on, from just converting MOZ_LOGs, and as needed.

MozReview-Commit-ID: KgNhHSz35t0

--HG--
extra : rebase_source : dd7206e350e32671adc6f3b9e54ebf777251de2c
This commit is contained in:
Gerald Squelart 2017-10-10 17:55:27 +11:00
parent 13e84a1120
commit 1b357db99b
85 changed files with 938 additions and 177 deletions

View File

@ -30,10 +30,12 @@ NS_IMPL_ELEMENT_CLONE(HTMLAudioElement)
HTMLAudioElement::HTMLAudioElement(already_AddRefed<NodeInfo>& aNodeInfo)
: HTMLMediaElement(aNodeInfo)
{
DecoderDoctorLogger::LogConstruction(this);
}
HTMLAudioElement::~HTMLAudioElement()
{
DecoderDoctorLogger::LogDestruction(this);
}
bool

View File

@ -1755,6 +1755,7 @@ void HTMLMediaElement::ShutdownDecoder()
mMediaSource->CompletePendingTransactions();
}
mDecoder->Shutdown();
DDUNLINKCHILD(mDecoder.get());
mDecoder = nullptr;
}
@ -1807,6 +1808,8 @@ void HTMLMediaElement::AbortExistingLoads()
RemoveMediaElementFromURITable();
mLoadingSrc = nullptr;
mLoadingSrcTriggeringPrincipal = nullptr;
DDLOG(DDLogCategory::Property, "loading_src", "");
DDUNLINKCHILD(mMediaSource.get());
mMediaSource = nullptr;
if (mNetworkState == nsIDOMHTMLMediaElement::NETWORK_LOADING ||
@ -2079,7 +2082,11 @@ void HTMLMediaElement::SelectResource()
RemoveMediaElementFromURITable();
mLoadingSrc = uri;
mLoadingSrcTriggeringPrincipal = mSrcAttrTriggeringPrincipal;
DDLOG(DDLogCategory::Property,
"loading_src",
nsCString(NS_ConvertUTF16toUTF8(src)));
mMediaSource = mSrcMediaSource;
DDLINKCHILD("mediasource", mMediaSource.get());
UpdatePreloadAction();
if (mPreloadAction == HTMLMediaElement::PRELOAD_NONE &&
!IsMediaStreamURI(mLoadingSrc) && !mMediaSource) {
@ -2403,7 +2410,11 @@ void HTMLMediaElement::LoadFromSourceChildren()
RemoveMediaElementFromURITable();
mLoadingSrc = uri;
mLoadingSrcTriggeringPrincipal = childSrc->GetSrcTriggeringPrincipal();
DDLOG(DDLogCategory::Property,
"loading_src",
nsCString(NS_ConvertUTF16toUTF8(src)));
mMediaSource = childSrc->GetSrcMediaSource();
DDLINKCHILD("mediasource", mMediaSource.get());
NS_ASSERTION(mNetworkState == nsIDOMHTMLMediaElement::NETWORK_LOADING,
"Network state should be loading");
@ -4076,6 +4087,8 @@ HTMLMediaElement::HTMLMediaElement(already_AddRefed<mozilla::dom::NodeInfo>& aNo
MOZ_ASSERT(mMainThreadEventTarget);
MOZ_ASSERT(mAbstractMainThread);
DecoderDoctorLogger::LogConstruction(this);
ErrorResult rv;
double defaultVolume = Preferences::GetFloat("media.default_volume", 1.0);
@ -4151,6 +4164,8 @@ HTMLMediaElement::~HTMLMediaElement()
}
WakeLockRelease();
DecoderDoctorLogger::LogDestruction(this);
}
void HTMLMediaElement::StopSuspendingAfterFirstFrame()
@ -6116,6 +6131,8 @@ HTMLMediaElement::ChangeReadyState(nsMediaReadyState aState)
LOG(LogLevel::Debug,
("%p Ready state changed to %s", this, gReadyStateToString[aState]));
DDLOG(DDLogCategory::Property, "ready_state", gReadyStateToString[aState]);
if (mNetworkState == nsIDOMHTMLMediaElement::NETWORK_EMPTY) {
return;
}
@ -6182,6 +6199,8 @@ void HTMLMediaElement::ChangeNetworkState(nsMediaNetworkState aState)
nsMediaNetworkState oldState = mNetworkState;
mNetworkState = aState;
LOG(LogLevel::Debug, ("%p Network state changed to %s", this, gNetworkStateToString[aState]));
DDLOG(
DDLogCategory::Property, "network_state", gNetworkStateToString[aState]);
if (oldState == nsIDOMHTMLMediaElement::NETWORK_LOADING) {
// Stop progress notification when exiting NETWORK_LOADING.
@ -6399,6 +6418,9 @@ HTMLMediaElement::DispatchAsyncEvent(const nsAString& aName)
{
LOG_EVENT(LogLevel::Debug, ("%p Queuing event %s", this,
NS_ConvertUTF16toUTF8(aName).get()));
DDLOG(DDLogCategory::Event,
"HTMLMediaElement",
nsCString(NS_ConvertUTF16toUTF8(aName)));
// Save events that occur while in the bfcache. These will be dispatched
// if the page comes out of the bfcache.
@ -6649,6 +6671,7 @@ void HTMLMediaElement::NotifyOwnerDocumentActivityChanged()
// If the owning document has become inactive we should shutdown the CDM.
if (!OwnerDoc()->IsCurrentActiveDocument() && mMediaKeys) {
mMediaKeys->Shutdown();
DDUNLINKCHILD(mMediaKeys.get());
mMediaKeys = nullptr;
if (mDecoder) {
ShutdownDecoder();
@ -7549,6 +7572,7 @@ HTMLMediaElement::SetDecoder(MediaDecoder* aDecoder)
ShutdownDecoder();
}
mDecoder = aDecoder;
DDLINKCHILD("decoder", mDecoder.get());
}
float

View File

@ -48,10 +48,12 @@ HTMLVideoElement::HTMLVideoElement(already_AddRefed<NodeInfo>& aNodeInfo)
: HTMLMediaElement(aNodeInfo)
, mIsOrientationLocked(false)
{
DecoderDoctorLogger::LogConstruction(this);
}
HTMLVideoElement::~HTMLVideoElement()
{
DecoderDoctorLogger::LogDestruction(this);
}
nsresult HTMLVideoElement::GetVideoSize(nsIntSize* size)

View File

@ -263,6 +263,7 @@ using media::TimeUnit;
ADTSDemuxer::ADTSDemuxer(MediaResource* aSource)
: mSource(aSource)
{
DDLINKCHILD("source", aSource);
}
bool
@ -270,6 +271,7 @@ ADTSDemuxer::InitInternal()
{
if (!mTrackDemuxer) {
mTrackDemuxer = new ADTSTrackDemuxer(mSource);
DDLINKCHILD("track demuxer", mTrackDemuxer.get());
}
return mTrackDemuxer->Init();
}
@ -326,6 +328,7 @@ ADTSTrackDemuxer::ADTSTrackDemuxer(MediaResource* aSource)
, mSamplesPerSecond(0)
, mChannels(0)
{
DDLINKCHILD("source", aSource);
Reset();
}

View File

@ -21,7 +21,11 @@ class FrameParser;
class ADTSTrackDemuxer;
class ADTSDemuxer : public MediaDataDemuxer
DDLoggedTypeDeclNameAndBase(ADTSDemuxer, MediaDataDemuxer);
class ADTSDemuxer
: public MediaDataDemuxer
, public DecoderDoctorLifeLogger<ADTSDemuxer>
{
public:
// MediaDataDemuxer interface.
@ -42,7 +46,11 @@ private:
RefPtr<ADTSTrackDemuxer> mTrackDemuxer;
};
class ADTSTrackDemuxer : public MediaTrackDemuxer
DDLoggedTypeNameAndBase(ADTSTrackDemuxer, MediaTrackDemuxer);
class ADTSTrackDemuxer
: public MediaTrackDemuxer
, public DecoderDoctorLifeLogger<ADTSTrackDemuxer>
{
public:
explicit ADTSTrackDemuxer(MediaResource* aSource);

View File

@ -17,7 +17,11 @@ class nsIPrincipal;
namespace mozilla {
class BaseMediaResource : public MediaResource
DDLoggedTypeDeclNameAndBase(BaseMediaResource, MediaResource);
class BaseMediaResource
: public MediaResource
, public DecoderDoctorLifeLogger<BaseMediaResource>
{
public:
/**

View File

@ -12,11 +12,15 @@
namespace mozilla {
DDLoggedTypeDeclNameAndBase(BufferMediaResource, MediaResource);
// A simple MediaResource based on an in memory buffer. This class accepts
// the address and the length of the buffer, and simulates a read/seek API
// on top of it. The Read implementation involves copying memory, which is
// unfortunate, but the MediaResource interface mandates that.
class BufferMediaResource : public MediaResource
class BufferMediaResource
: public MediaResource
, public DecoderDoctorLifeLogger<BufferMediaResource>
{
public:
BufferMediaResource(const uint8_t* aBuffer, uint32_t aLength)

View File

@ -23,6 +23,16 @@ ChannelMediaDecoder::ResourceCallback::ResourceCallback(
: mAbstractMainThread(aMainThread)
{
MOZ_ASSERT(aMainThread);
DecoderDoctorLogger::LogConstructionAndBase(
"ChannelMediaDecoder::ResourceCallback",
this,
static_cast<const MediaResourceCallback*>(this));
}
ChannelMediaDecoder::ResourceCallback::~ResourceCallback()
{
DecoderDoctorLogger::LogDestruction("ChannelMediaDecoder::ResourceCallback",
this);
}
void
@ -30,6 +40,8 @@ ChannelMediaDecoder::ResourceCallback::Connect(ChannelMediaDecoder* aDecoder)
{
MOZ_ASSERT(NS_IsMainThread());
mDecoder = aDecoder;
DecoderDoctorLogger::LinkParentAndChild(
"ChannelMediaDecoder::ResourceCallback", this, "decoder", mDecoder);
mTimer = NS_NewTimer(mAbstractMainThread->AsEventTarget());
}
@ -38,6 +50,8 @@ ChannelMediaDecoder::ResourceCallback::Disconnect()
{
MOZ_ASSERT(NS_IsMainThread());
if (mDecoder) {
DecoderDoctorLogger::UnlinkParentAndChild(
"ChannelMediaDecoder::ResourceCallback", this, mDecoder);
mDecoder = nullptr;
mTimer->Cancel();
mTimer = nullptr;
@ -62,6 +76,11 @@ ChannelMediaDecoder::ResourceCallback::NotifyNetworkError(
const MediaResult& aError)
{
MOZ_ASSERT(NS_IsMainThread());
DDLOGEX2("ChannelMediaDecoder::ResourceCallback",
this,
DDLogCategory::Log,
"network_error",
aError);
if (mDecoder) {
mDecoder->NetworkError(aError);
}
@ -82,6 +101,12 @@ void
ChannelMediaDecoder::ResourceCallback::NotifyDataArrived()
{
MOZ_ASSERT(NS_IsMainThread());
DDLOGEX2("ChannelMediaDecoder::ResourceCallback",
this,
DDLogCategory::Log,
"data_arrived",
true);
if (!mDecoder) {
return;
}
@ -104,6 +129,11 @@ ChannelMediaDecoder::ResourceCallback::NotifyDataArrived()
void
ChannelMediaDecoder::ResourceCallback::NotifyDataEnded(nsresult aStatus)
{
DDLOGEX2("ChannelMediaDecoder::ResourceCallback",
this,
DDLogCategory::Log,
"data_ended",
aStatus);
MOZ_ASSERT(NS_IsMainThread());
if (mDecoder) {
mDecoder->NotifyDownloadEnded(aStatus);
@ -114,6 +144,11 @@ void
ChannelMediaDecoder::ResourceCallback::NotifyPrincipalChanged()
{
MOZ_ASSERT(NS_IsMainThread());
DDLOGEX2("ChannelMediaDecoder::ResourceCallback",
this,
DDLogCategory::Log,
"principal_changed",
true);
if (mDecoder) {
mDecoder->NotifyPrincipalChanged();
}
@ -124,6 +159,11 @@ ChannelMediaDecoder::ResourceCallback::NotifySuspendedStatusChanged(
bool aSuspendedByCache)
{
MOZ_ASSERT(NS_IsMainThread());
DDLOGEX2("ChannelMediaDecoder::ResourceCallback",
this,
DDLogCategory::Log,
"suspended_status_changed",
aSuspendedByCache);
MediaDecoderOwner* owner = GetMediaOwner();
if (owner) {
AbstractThread::AutoEnter context(owner->AbstractMainThread());
@ -246,6 +286,7 @@ ChannelMediaDecoder::Load(nsIChannel* aChannel,
if (!mResource) {
return NS_ERROR_FAILURE;
}
DDLINKCHILD("resource", mResource.get());
nsresult rv = MediaShutdownManager::Instance().Register(this);
if (NS_WARN_IF(NS_FAILED(rv))) {
@ -271,6 +312,7 @@ ChannelMediaDecoder::Load(BaseMediaResource* aOriginal)
if (!mResource) {
return NS_ERROR_FAILURE;
}
DDLINKCHILD("resource", mResource.get());
nsresult rv = MediaShutdownManager::Instance().Register(this);
if (NS_WARN_IF(NS_FAILED(rv))) {

View File

@ -18,7 +18,11 @@ namespace mozilla {
class BaseMediaResource;
class ChannelMediaDecoder : public MediaDecoder
DDLoggedTypeDeclNameAndBase(ChannelMediaDecoder, MediaDecoder);
class ChannelMediaDecoder
: public MediaDecoder
, public DecoderDoctorLifeLogger<ChannelMediaDecoder>
{
// Used to register with MediaResource to receive notifications which will
// be forwarded to MediaDecoder.
@ -36,6 +40,8 @@ class ChannelMediaDecoder : public MediaDecoder
void Disconnect();
private:
~ResourceCallback();
/* MediaResourceCallback functions */
AbstractThread* AbstractMainThread() const override;
MediaDecoderOwner* GetMediaOwner() const override;

View File

@ -53,6 +53,8 @@ private:
bool mIsChannelSuspended = false;
};
DDLoggedTypeDeclNameAndBase(ChannelMediaResource, BaseMediaResource);
/**
* This is the MediaResource implementation that wraps Necko channels.
* Much of its functionality is actually delegated to MediaCache via
@ -61,7 +63,9 @@ private:
* All synchronization is performed by MediaCacheStream; all off-main-
* thread operations are delegated directly to that object.
*/
class ChannelMediaResource : public BaseMediaResource
class ChannelMediaResource
: public BaseMediaResource
, public DecoderDoctorLifeLogger<ChannelMediaResource>
{
public:
ChannelMediaResource(MediaResourceCallback* aDecoder,

View File

@ -7,6 +7,7 @@
#ifndef MediaCache_h_
#define MediaCache_h_
#include "DecoderDoctorLogger.h"
#include "Intervals.h"
#include "mozilla/Result.h"
#include "mozilla/UniquePtr.h"
@ -181,13 +182,16 @@ class ReentrantMonitorAutoEnter;
*/
class MediaCache;
DDLoggedTypeDeclName(MediaCacheStream);
/**
* If the cache fails to initialize then Init will fail, so nonstatic
* methods of this class can assume gMediaCache is non-null.
*
* This class can be directly embedded as a value.
*/
class MediaCacheStream {
class MediaCacheStream : public DecoderDoctorLifeLogger<MediaCacheStream>
{
using AutoLock = ReentrantMonitorAutoEnter;
public:

View File

@ -7,6 +7,7 @@
#if !defined(MediaDataDemuxer_h)
#define MediaDataDemuxer_h
#include "DecoderDoctorLogger.h"
#include "mozilla/MozPromise.h"
#include "mozilla/UniquePtr.h"
@ -23,11 +24,14 @@ namespace mozilla {
class MediaTrackDemuxer;
class TrackMetadataHolder;
DDLoggedTypeDeclName(MediaDataDemuxer);
DDLoggedTypeName(MediaTrackDemuxer);
// Allows reading the media data: to retrieve the metadata and demux samples.
// MediaDataDemuxer isn't designed to be thread safe.
// When used by the MediaFormatDecoder, care is taken to ensure that the demuxer
// will never be called from more than one thread at once.
class MediaDataDemuxer
class MediaDataDemuxer : public DecoderDoctorLifeLogger<MediaDataDemuxer>
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaDataDemuxer)
@ -94,7 +98,7 @@ protected:
}
};
class MediaTrackDemuxer
class MediaTrackDemuxer : public DecoderDoctorLifeLogger<MediaTrackDemuxer>
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaTrackDemuxer)

View File

@ -840,6 +840,10 @@ MediaDecoder::ChangeState(PlayState aState)
mNextState = PLAY_STATE_PAUSED;
}
if (mPlayState != aState) {
DDLOG(DDLogCategory::Property, "play_state", ToPlayStateStr(aState));
}
LOG("ChangeState %s => %s", PlayStateStr(), ToPlayStateStr(aState));
mPlayState = aState;
@ -862,6 +866,7 @@ MediaDecoder::UpdateLogicalPositionInternal()
}
bool logicalPositionChanged = mLogicalPosition != currentPosition;
mLogicalPosition = currentPosition;
DDLOG(DDLogCategory::Property, "currentTime", mLogicalPosition);
// Invalidate the frame so any video data is displayed.
// Do this before the timeupdate event so that if that
@ -1151,11 +1156,14 @@ MediaDecoder::SetStateMachine(MediaDecoderStateMachine* aStateMachine)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT_IF(aStateMachine, !mDecoderStateMachine);
mDecoderStateMachine = aStateMachine;
if (aStateMachine) {
mDecoderStateMachine = aStateMachine;
DDLINKCHILD("decoder state machine", mDecoderStateMachine.get());
ConnectMirrors(aStateMachine);
UpdateVideoDecodeMode();
} else {
} else if (mDecoderStateMachine) {
DDUNLINKCHILD(mDecoderStateMachine.get());
mDecoderStateMachine = nullptr;
DisconnectMirrors();
}
}

View File

@ -81,7 +81,9 @@ struct MOZ_STACK_CLASS MediaDecoderInit
}
};
class MediaDecoder
DDLoggedTypeDeclName(MediaDecoder);
class MediaDecoder : public DecoderDoctorLifeLogger<MediaDecoder>
{
public:
typedef MozPromise<bool /* aIgnored */, bool /* aIgnored */,

View File

@ -1931,6 +1931,10 @@ public:
if (mMaster->mDuration.Ref()->IsInfinite()) {
// We have a finite duration when playback reaches the end.
mMaster->mDuration = Some(clockTime);
DDLOGEX(mMaster,
DDLogCategory::Property,
"duration_us",
mMaster->mDuration.Ref()->ToMicroseconds());
}
mMaster->UpdatePlaybackPosition(clockTime);
@ -2173,6 +2177,11 @@ DecodeMetadataState::OnMetadataRead(MetadataHolder&& aMetadata)
mMaster->mDuration = Some(TimeUnit::FromInfinity());
}
DDLOGEX(mMaster,
DDLogCategory::Property,
"duration_us",
mMaster->mDuration.Ref()->ToMicroseconds());
if (mMaster->HasVideo()) {
SLOG("Video decode HWAccel=%d videoQueueSize=%d",
Reader()->VideoIsHardwareAccelerated(),
@ -2687,6 +2696,8 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
InitVideoQueuePrefs();
DDLINKCHILD("reader", aReader);
}
#undef INIT_WATCHABLE
@ -2961,7 +2972,12 @@ MediaDecoderStateMachine::UpdatePlaybackPositionInternal(const TimeUnit& aTime)
mCurrentPosition = aTime;
NS_ASSERTION(mCurrentPosition.Ref() >= TimeUnit::Zero(),
"CurrentTime should be positive!");
mDuration = Some(std::max(mDuration.Ref().ref(), mCurrentPosition.Ref()));
if (mDuration.Ref().ref() < mCurrentPosition.Ref()) {
mDuration = Some(mCurrentPosition.Ref());
DDLOG(DDLogCategory::Property,
"duration_us",
mDuration.Ref()->ToMicroseconds());
}
}
void
@ -3114,6 +3130,9 @@ void MediaDecoderStateMachine::BufferedRangeUpdated()
if (mDuration.Ref().isNothing() || mDuration.Ref()->IsInfinite() ||
end > mDuration.Ref().ref()) {
mDuration = Some(end);
DDLOG(DDLogCategory::Property,
"duration_us",
mDuration.Ref()->ToMicroseconds());
}
}

View File

@ -156,6 +156,8 @@ enum class VideoDecodeMode : uint8_t
Suspend
};
DDLoggedTypeDeclName(MediaDecoderStateMachine);
/*
The state machine class. This manages the decoding and seeking in the
MediaDecoderReader on the decode task queue, and A/V sync on the shared
@ -168,6 +170,7 @@ enum class VideoDecodeMode : uint8_t
See MediaDecoder.h for more details.
*/
class MediaDecoderStateMachine
: public DecoderDoctorLifeLogger<MediaDecoderStateMachine>
{
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaDecoderStateMachine)

View File

@ -529,29 +529,45 @@ MediaFormatReader::DecoderData::Flush()
mShutdownPromise = new SharedShutdownPromiseHolder();
RefPtr<SharedShutdownPromiseHolder> p = mShutdownPromise;
RefPtr<MediaDataDecoder> d = mDecoder;
mDecoder->Flush()
->Then(mOwner->OwnerThread(), __func__,
[type, this, p, d]() {
if (!p->IsEmpty()) {
// Shutdown happened before flush completes. Let's continue to
// shut down the decoder. Note we don't access |this| because
// this decoder is no longer managed by MFR::DecoderData.
d->Shutdown()->ChainTo(p->Steal(), __func__);
return;
}
mFlushing = false;
mShutdownPromise = nullptr;
mOwner->ScheduleUpdate(type);
},
[type, this, p, d](const MediaResult& aError) {
if (!p->IsEmpty()) {
d->Shutdown()->ChainTo(p->Steal(), __func__);
return;
}
mFlushing = false;
mShutdownPromise = nullptr;
mOwner->NotifyError(type, aError);
});
DDLOGEX2("MediaFormatReader::DecoderData",
this,
DDLogCategory::Log,
"flushing",
DDNoValue{});
mDecoder->Flush()->Then(mOwner->OwnerThread(),
__func__,
[type, this, p, d]() {
DDLOGEX2("MediaFormatReader::DecoderData",
this,
DDLogCategory::Log,
"flushed",
DDNoValue{});
if (!p->IsEmpty()) {
// Shutdown happened before flush completes.
// Let's continue to shut down the decoder. Note
// we don't access |this| because this decoder
// is no longer managed by MFR::DecoderData.
d->Shutdown()->ChainTo(p->Steal(), __func__);
return;
}
mFlushing = false;
mShutdownPromise = nullptr;
mOwner->ScheduleUpdate(type);
},
[type, this, p, d](const MediaResult& aError) {
DDLOGEX2("MediaFormatReader::DecoderData",
this,
DDLogCategory::Log,
"flush_error",
aError);
if (!p->IsEmpty()) {
d->Shutdown()->ChainTo(p->Steal(), __func__);
return;
}
mFlushing = false;
mShutdownPromise = nullptr;
mOwner->NotifyError(type, aError);
});
}
mFlushed = true;
}
@ -566,7 +582,19 @@ public:
explicit DecoderFactory(MediaFormatReader* aOwner)
: mAudio(aOwner->mAudio, TrackInfo::kAudioTrack, aOwner->OwnerThread())
, mVideo(aOwner->mVideo, TrackInfo::kVideoTrack, aOwner->OwnerThread())
, mOwner(WrapNotNull(aOwner)) { }
, mOwner(WrapNotNull(aOwner))
{
DecoderDoctorLogger::LogConstruction("MediaFormatReader::DecoderFactory",
this);
DecoderDoctorLogger::LinkParentAndChild(
aOwner, "decoder factory", "MediaFormatReader::DecoderFactory", this);
}
~DecoderFactory()
{
DecoderDoctorLogger::LogDestruction("MediaFormatReader::DecoderFactory",
this);
}
void CreateDecoder(TrackType aTrack);
@ -637,7 +665,25 @@ class MediaFormatReader::DecoderFactory::Wrapper : public MediaDataDecoder
public:
Wrapper(already_AddRefed<MediaDataDecoder> aDecoder,
already_AddRefed<Token> aToken)
: mDecoder(aDecoder), mToken(aToken) {}
: mDecoder(aDecoder)
, mToken(aToken)
{
DecoderDoctorLogger::LogConstructionAndBase(
"MediaFormatReader::DecoderFactory::Wrapper",
this,
static_cast<const MediaDataDecoder*>(this));
DecoderDoctorLogger::LinkParentAndChild(
"MediaFormatReader::DecoderFactory::Wrapper",
this,
"decoder",
mDecoder.get());
}
~Wrapper()
{
DecoderDoctorLogger::LogDestruction(
"MediaFormatReader::DecoderFactory::Wrapper", this);
}
RefPtr<InitPromise> Init() override { return mDecoder->Init(); }
RefPtr<DecodePromise> Decode(MediaRawData* aSample) override
@ -717,11 +763,22 @@ MediaFormatReader::DecoderFactory::RunStage(Data& aData)
aData.mToken = nullptr;
aData.mStage = Stage::None;
aData.mOwnerData.mDescription = rv.Description();
DDLOGEX2("MediaFormatReader::DecoderFactory",
this,
DDLogCategory::Log,
"create_decoder_error",
rv);
mOwner->NotifyError(aData.mTrack, rv);
return;
}
aData.mDecoder = new Wrapper(aData.mDecoder.forget(), aData.mToken.forget());
DecoderDoctorLogger::LinkParentAndChild(
aData.mDecoder.get(),
"decoder",
"MediaFormatReader::DecoderFactory",
this);
DoInitDecoder(aData);
aData.mStage = Stage::WaitForInit;
break;
@ -806,6 +863,11 @@ MediaFormatReader::DecoderFactory::DoInitDecoder(Data& aData)
{
auto& ownerData = aData.mOwnerData;
DDLOGEX2("MediaFormatReader::DecoderFactory",
this,
DDLogCategory::Log,
"initialize_decoder",
DDNoValue{});
aData.mDecoder->Init()
->Then(mOwner->OwnerThread(), __func__,
[this, &aData, &ownerData](TrackType aTrack) {
@ -814,6 +876,16 @@ MediaFormatReader::DecoderFactory::DoInitDecoder(Data& aData)
MutexAutoLock lock(ownerData.mMutex);
ownerData.mDecoder = aData.mDecoder.forget();
ownerData.mDescription = ownerData.mDecoder->GetDescriptionName();
DDLOGEX2("MediaFormatReader::DecoderFactory",
this,
DDLogCategory::Log,
"decoder_initialized",
DDNoValue{});
DecoderDoctorLogger::LinkParentAndChild(
"MediaFormatReader::DecoderData",
&ownerData,
"decoder",
ownerData.mDecoder.get());
mOwner->SetVideoDecodeThreshold();
mOwner->ScheduleUpdate(aTrack);
},
@ -823,6 +895,11 @@ MediaFormatReader::DecoderFactory::DoInitDecoder(Data& aData)
"Can't have a decoder already set");
aData.mStage = Stage::None;
mOwner->mShutdownPromisePool->ShutdownDecoder(aData.mDecoder.forget());
DDLOGEX2("MediaFormatReader::DecoderFactory",
this,
DDLogCategory::Log,
"initialize_decoder_error",
aError);
mOwner->NotifyError(aData.mTrack, aError);
})
->Track(aData.mInitRequest);
@ -974,6 +1051,15 @@ public:
, mInfo(aTrackDemuxer->GetInfo())
, mTrackDemuxer(aTrackDemuxer)
{
DecoderDoctorLogger::LogConstructionAndBase(
"MediaFormatReader::DemuxerProxy::Wrapper",
this,
static_cast<const MediaTrackDemuxer*>(this));
DecoderDoctorLogger::LinkParentAndChild(
"MediaFormatReader::DemuxerProxy::Wrapper",
this,
"track demuxer",
aTrackDemuxer);
}
UniquePtr<TrackInfo> GetInfo() const override
@ -1093,6 +1179,8 @@ private:
"MediaFormatReader::DemuxerProxy::Wrapper::~Wrapper",
[trackDemuxer]() { trackDemuxer->BreakCycles(); }));
MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
DecoderDoctorLogger::LogDestruction(
"MediaFormatReader::DemuxerProxy::Wrapper", this);
}
void UpdateRandomAccessPoint()
@ -1150,6 +1238,11 @@ MediaFormatReader::DemuxerProxy::Init()
new DemuxerProxy::Wrapper(d, taskQueue);
wrapper->UpdateBuffered();
data->mAudioDemuxer = wrapper;
DecoderDoctorLogger::LinkParentAndChild(
data->mDemuxer.get(),
"decoder factory wrapper",
"MediaFormatReader::DecoderFactory::Wrapper",
wrapper.get());
}
}
data->mNumVideoTrack =
@ -1162,6 +1255,11 @@ MediaFormatReader::DemuxerProxy::Init()
new DemuxerProxy::Wrapper(d, taskQueue);
wrapper->UpdateBuffered();
data->mVideoDemuxer = wrapper;
DecoderDoctorLogger::LinkParentAndChild(
data->mDemuxer.get(),
"decoder factory wrapper",
"MediaFormatReader::DecoderFactory::Wrapper",
wrapper.get());
}
}
data->mCrypto = data->mDemuxer->GetCrypto();
@ -1227,6 +1325,11 @@ MediaFormatReader::MediaFormatReader(MediaFormatReaderInit& aInit,
{
MOZ_ASSERT(aDemuxer);
MOZ_COUNT_CTOR(MediaFormatReader);
DDLINKCHILD(
"audio decoder data", "MediaFormatReader::DecoderDataWithPromise", &mAudio);
DDLINKCHILD(
"video decoder data", "MediaFormatReader::DecoderDataWithPromise", &mVideo);
DDLINKCHILD("demuxer", aDemuxer);
mOnTrackWaitingForKeyListener = OnTrackWaitingForKey().Connect(
mTaskQueue, this, &MediaFormatReader::NotifyWaitingForKey);
}
@ -1751,23 +1854,39 @@ MediaFormatReader::OnDemuxFailed(TrackType aTrack, const MediaResult& aError)
decoder.mDemuxRequest.Complete();
switch (aError.Code()) {
case NS_ERROR_DOM_MEDIA_END_OF_STREAM:
DDLOG(DDLogCategory::Log,
aTrack == TrackType::kVideoTrack ? "video_demux_interruption"
: "audio_demux_interruption",
aError);
if (!decoder.mWaitingForData) {
decoder.RequestDrain();
}
NotifyEndOfStream(aTrack);
break;
case NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA:
DDLOG(DDLogCategory::Log,
aTrack == TrackType::kVideoTrack ? "video_demux_interruption"
: "audio_demux_interruption",
aError);
if (!decoder.mWaitingForData) {
decoder.RequestDrain();
}
NotifyWaitingForData(aTrack);
break;
case NS_ERROR_DOM_MEDIA_CANCELED:
DDLOG(DDLogCategory::Log,
aTrack == TrackType::kVideoTrack ? "video_demux_interruption"
: "audio_demux_interruption",
aError);
if (decoder.HasPromise()) {
decoder.RejectPromise(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
}
break;
default:
DDLOG(DDLogCategory::Log,
aTrack == TrackType::kVideoTrack ? "video_demux_error"
: "audio_demux_error",
aError);
NotifyError(aTrack, aError);
break;
}
@ -1778,19 +1897,26 @@ MediaFormatReader::DoDemuxVideo()
{
using SamplesPromise = MediaTrackDemuxer::SamplesPromise;
DDLOG(DDLogCategory::Log, "video_demuxing", DDNoValue{});
auto p = mVideo.mTrackDemuxer->GetSamples(1);
if (mVideo.mFirstDemuxedSampleTime.isNothing()) {
RefPtr<MediaFormatReader> self = this;
p = p->Then(OwnerThread(), __func__,
[self] (RefPtr<MediaTrackDemuxer::SamplesHolder> aSamples) {
self->OnFirstDemuxCompleted(TrackInfo::kVideoTrack, aSamples);
return SamplesPromise::CreateAndResolve(aSamples.forget(), __func__);
},
[self] (const MediaResult& aError) {
self->OnFirstDemuxFailed(TrackInfo::kVideoTrack, aError);
return SamplesPromise::CreateAndReject(aError, __func__);
});
p = p->Then(
OwnerThread(),
__func__,
[self](RefPtr<MediaTrackDemuxer::SamplesHolder> aSamples) {
DDLOGEX(
self.get(), DDLogCategory::Log, "video_first_demuxed", DDNoValue{});
self->OnFirstDemuxCompleted(TrackInfo::kVideoTrack, aSamples);
return SamplesPromise::CreateAndResolve(aSamples.forget(), __func__);
},
[self](const MediaResult& aError) {
DDLOGEX(
self.get(), DDLogCategory::Log, "video_first_demuxing_error", aError);
self->OnFirstDemuxFailed(TrackInfo::kVideoTrack, aError);
return SamplesPromise::CreateAndReject(aError, __func__);
});
}
p->Then(OwnerThread(), __func__, this,
@ -1808,6 +1934,9 @@ MediaFormatReader::OnVideoDemuxCompleted(
aSamples->mSamples[0]->mTrackInfo
? aSamples->mSamples[0]->mTrackInfo->GetID()
: 0);
DDLOG(DDLogCategory::Log,
"video_demuxed_samples",
uint64_t(aSamples->mSamples.Length()));
mVideo.mDemuxRequest.Complete();
mVideo.mQueuedSamples.AppendElements(aSamples->mSamples);
ScheduleUpdate(TrackInfo::kVideoTrack);
@ -1854,19 +1983,26 @@ MediaFormatReader::DoDemuxAudio()
{
using SamplesPromise = MediaTrackDemuxer::SamplesPromise;
DDLOG(DDLogCategory::Log, "audio_demuxing", DDNoValue{});
auto p = mAudio.mTrackDemuxer->GetSamples(1);
if (mAudio.mFirstDemuxedSampleTime.isNothing()) {
RefPtr<MediaFormatReader> self = this;
p = p->Then(OwnerThread(), __func__,
[self] (RefPtr<MediaTrackDemuxer::SamplesHolder> aSamples) {
self->OnFirstDemuxCompleted(TrackInfo::kAudioTrack, aSamples);
return SamplesPromise::CreateAndResolve(aSamples.forget(), __func__);
},
[self] (const MediaResult& aError) {
self->OnFirstDemuxFailed(TrackInfo::kAudioTrack, aError);
return SamplesPromise::CreateAndReject(aError, __func__);
});
p = p->Then(
OwnerThread(),
__func__,
[self](RefPtr<MediaTrackDemuxer::SamplesHolder> aSamples) {
DDLOGEX(
self.get(), DDLogCategory::Log, "audio_first_demuxed", DDNoValue{});
self->OnFirstDemuxCompleted(TrackInfo::kAudioTrack, aSamples);
return SamplesPromise::CreateAndResolve(aSamples.forget(), __func__);
},
[self](const MediaResult& aError) {
DDLOGEX(
self.get(), DDLogCategory::Log, "audio_first_demuxing_error", aError);
self->OnFirstDemuxFailed(TrackInfo::kAudioTrack, aError);
return SamplesPromise::CreateAndReject(aError, __func__);
});
}
p->Then(OwnerThread(), __func__, this,
@ -1884,6 +2020,9 @@ MediaFormatReader::OnAudioDemuxCompleted(
aSamples->mSamples[0]->mTrackInfo
? aSamples->mSamples[0]->mTrackInfo->GetID()
: 0);
DDLOG(DDLogCategory::Log,
"audio_demuxed_samples",
uint64_t(aSamples->mSamples.Length()));
mAudio.mDemuxRequest.Complete();
mAudio.mQueuedSamples.AppendElements(aSamples->mSamples);
ScheduleUpdate(TrackInfo::kAudioTrack);
@ -1895,14 +2034,94 @@ MediaFormatReader::NotifyNewOutput(
{
MOZ_ASSERT(OnTaskQueue());
auto& decoder = GetDecoderData(aTrack);
for (auto& sample : aResults) {
LOGV("Received new %s sample time:%" PRId64 " duration:%" PRId64,
TrackTypeToStr(aTrack), sample->mTime.ToMicroseconds(),
sample->mDuration.ToMicroseconds());
decoder.mOutput.AppendElement(sample);
decoder.mNumSamplesOutput++;
decoder.mNumOfConsecutiveError = 0;
}
if (aResults.IsEmpty()) {
DDLOG(DDLogCategory::Log,
aTrack == TrackInfo::kAudioTrack ? "decoded_audio" : "decoded_video",
"no output samples");
} else
for (auto& sample : aResults) {
if (DecoderDoctorLogger::IsDDLoggingEnabled()) {
switch (sample->mType) {
case MediaData::AUDIO_DATA:
DDLOGPR(DDLogCategory::Log,
aTrack == TrackInfo::kAudioTrack ? "decoded_audio"
: "decoded_got_audio!?",
"{\"type\":\"AudioData\", \"offset\":%" PRIi64
", \"time_us\":%" PRIi64 ", \"timecode_us\":%" PRIi64
", \"duration_us\":%" PRIi64 ", \"frames\":%" PRIu32
", \"kf\":%s, \"channels\":%" PRIu32 ", \"rate\":%" PRIu32
", \"bytes\":%zu}",
sample->mOffset,
sample->mTime.ToMicroseconds(),
sample->mTimecode.ToMicroseconds(),
sample->mDuration.ToMicroseconds(),
sample->mFrames,
sample->mKeyframe ? "true" : "false",
sample->As<AudioData>()->mChannels,
sample->As<AudioData>()->mRate,
sample->As<AudioData>()->mAudioData.Size());
break;
case MediaData::VIDEO_DATA:
DDLOGPR(DDLogCategory::Log,
aTrack == TrackInfo::kVideoTrack ? "decoded_video"
: "decoded_got_video!?",
"{\"type\":\"VideoData\", \"offset\":%" PRIi64
", \"time_us\":%" PRIi64 ", \"timecode_us\":%" PRIi64
", \"duration_us\":%" PRIi64 ", \"frames\":%" PRIu32
", \"kf\":%s, \"size\":[%" PRIi32 ",%" PRIi32 "]}",
sample->mOffset,
sample->mTime.ToMicroseconds(),
sample->mTimecode.ToMicroseconds(),
sample->mDuration.ToMicroseconds(),
sample->mFrames,
sample->mKeyframe ? "true" : "false",
sample->As<VideoData>()->mDisplay.width,
sample->As<VideoData>()->mDisplay.height);
break;
case MediaData::RAW_DATA:
DDLOGPR(DDLogCategory::Log,
aTrack == TrackInfo::kAudioTrack
? "decoded_audio"
: aTrack == TrackInfo::kVideoTrack ? "decoded_video"
: "decoded_?",
"{\"type\":\"RawData\", \"offset\":%" PRIi64
" \"time_us\":%" PRIi64 ", \"timecode_us\":%" PRIi64
", \"duration_us\":%" PRIi64 ", \"frames\":%" PRIu32
", \"kf\":%s}",
sample->mOffset,
sample->mTime.ToMicroseconds(),
sample->mTimecode.ToMicroseconds(),
sample->mDuration.ToMicroseconds(),
sample->mFrames,
sample->mKeyframe ? "true" : "false");
break;
case MediaData::NULL_DATA:
DDLOGPR(DDLogCategory::Log,
aTrack == TrackInfo::kAudioTrack
? "decoded_audio"
: aTrack == TrackInfo::kVideoTrack ? "decoded_video"
: "decoded_?",
"{\"type\":\"NullData\", \"offset\":%" PRIi64
" \"time_us\":%" PRIi64 ", \"timecode_us\":%" PRIi64
", \"duration_us\":%" PRIi64 ", \"frames\":%" PRIu32
", \"kf\":%s}",
sample->mOffset,
sample->mTime.ToMicroseconds(),
sample->mTimecode.ToMicroseconds(),
sample->mDuration.ToMicroseconds(),
sample->mFrames,
sample->mKeyframe ? "true" : "false");
break;
}
}
LOGV("Received new %s sample time:%" PRId64 " duration:%" PRId64,
TrackTypeToStr(aTrack),
sample->mTime.ToMicroseconds(),
sample->mDuration.ToMicroseconds());
decoder.mOutput.AppendElement(sample);
decoder.mNumSamplesOutput++;
decoder.mNumOfConsecutiveError = 0;
}
LOG("Done processing new %s samples", TrackTypeToStr(aTrack));
if (!aResults.IsEmpty()) {
@ -2104,7 +2323,7 @@ MediaFormatReader::RequestDemuxSamples(TrackType aTrack)
if (decoder.mDemuxEOS) {
// Nothing left to demux.
// We do not want to attempt to demux while in waiting for data mode
// as it would retrigger an unecessary drain.
// as it would retrigger an unnecessary drain.
return;
}
@ -2124,6 +2343,21 @@ MediaFormatReader::DecodeDemuxedSamples(TrackType aTrack,
auto& decoder = GetDecoderData(aTrack);
RefPtr<MediaFormatReader> self = this;
decoder.mFlushed = false;
DDLOGPR(DDLogCategory::Log,
aTrack == TrackInfo::kAudioTrack
? "decode_audio"
: aTrack == TrackInfo::kVideoTrack ? "decode_video" : "decode_?",
"{\"type\":\"MediaRawData\", \"offset\":%" PRIi64
", \"bytes\":%zu, \"time_us\":%" PRIi64 ", \"timecode_us\":%" PRIi64
", \"duration_us\":%" PRIi64 ", \"frames\":%" PRIu32 "%s%s}",
aSample->mOffset,
aSample->Size(),
aSample->mTime.ToMicroseconds(),
aSample->mTimecode.ToMicroseconds(),
aSample->mDuration.ToMicroseconds(),
aSample->mFrames,
aSample->mKeyframe ? " kf" : "",
aSample->mEOS ? " eos" : "");
decoder.mDecoder->Decode(aSample)
->Then(mTaskQueue, __func__,
[self, aTrack, &decoder]
@ -2255,39 +2489,50 @@ MediaFormatReader::InternalSeek(TrackType aTrack,
decoder.Flush();
decoder.ResetDemuxer();
decoder.mTimeThreshold = Some(aTarget);
DDLOG(DDLogCategory::Log, "seeking", DDNoValue{});
RefPtr<MediaFormatReader> self = this;
decoder.mTrackDemuxer->Seek(decoder.mTimeThreshold.ref().Time())
->Then(OwnerThread(), __func__,
[self, aTrack] (TimeUnit aTime) {
auto& decoder = self->GetDecoderData(aTrack);
decoder.mSeekRequest.Complete();
MOZ_ASSERT(
decoder.mTimeThreshold,
"Seek promise must be disconnected when timethreshold is reset");
decoder.mTimeThreshold.ref().mHasSeeked = true;
self->SetVideoDecodeThreshold();
self->ScheduleUpdate(aTrack);
},
[self, aTrack] (const MediaResult& aError) {
auto& decoder = self->GetDecoderData(aTrack);
decoder.mSeekRequest.Complete();
switch (aError.Code()) {
case NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA:
self->NotifyWaitingForData(aTrack);
break;
case NS_ERROR_DOM_MEDIA_END_OF_STREAM:
decoder.mTimeThreshold.reset();
self->NotifyEndOfStream(aTrack);
break;
case NS_ERROR_DOM_MEDIA_CANCELED:
decoder.mTimeThreshold.reset();
break;
default:
decoder.mTimeThreshold.reset();
self->NotifyError(aTrack, aError);
break;
}
})
->Then(
OwnerThread(),
__func__,
[self, aTrack](TimeUnit aTime) {
DDLOGEX(self.get(), DDLogCategory::Log, "seeked", DDNoValue{});
auto& decoder = self->GetDecoderData(aTrack);
decoder.mSeekRequest.Complete();
MOZ_ASSERT(
decoder.mTimeThreshold,
"Seek promise must be disconnected when timethreshold is reset");
decoder.mTimeThreshold.ref().mHasSeeked = true;
self->SetVideoDecodeThreshold();
self->ScheduleUpdate(aTrack);
},
[self, aTrack](const MediaResult& aError) {
auto& decoder = self->GetDecoderData(aTrack);
decoder.mSeekRequest.Complete();
switch (aError.Code()) {
case NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA:
DDLOGEX(
self.get(), DDLogCategory::Log, "seeking_interrupted", aError);
self->NotifyWaitingForData(aTrack);
break;
case NS_ERROR_DOM_MEDIA_END_OF_STREAM:
DDLOGEX(
self.get(), DDLogCategory::Log, "seeking_interrupted", aError);
decoder.mTimeThreshold.reset();
self->NotifyEndOfStream(aTrack);
break;
case NS_ERROR_DOM_MEDIA_CANCELED:
DDLOGEX(
self.get(), DDLogCategory::Log, "seeking_interrupted", aError);
decoder.mTimeThreshold.reset();
break;
default:
DDLOGEX(self.get(), DDLogCategory::Log, "seeking_error", aError);
decoder.mTimeThreshold.reset();
self->NotifyError(aTrack, aError);
break;
}
})
->Track(decoder.mSeekRequest);
}
@ -2312,12 +2557,14 @@ MediaFormatReader::DrainDecoder(TrackType aTrack)
decoder.mDrainState = DrainState::Draining;
DDLOG(DDLogCategory::Log, "draining", DDNoValue{});
RefPtr<MediaFormatReader> self = this;
decoder.mDecoder->Drain()
->Then(mTaskQueue, __func__,
[self, aTrack, &decoder]
(const MediaDataDecoder::DecodedData& aResults) {
decoder.mDrainRequest.Complete();
DDLOGEX(self.get(), DDLogCategory::Log, "drained", DDNoValue{});
if (aResults.IsEmpty()) {
decoder.mDrainState = DrainState::DrainCompleted;
} else {
@ -2329,6 +2576,7 @@ MediaFormatReader::DrainDecoder(TrackType aTrack)
},
[self, aTrack, &decoder](const MediaResult& aError) {
decoder.mDrainRequest.Complete();
DDLOGEX(self.get(), DDLogCategory::Log, "draining_error", aError);
self->NotifyError(aTrack, aError);
})
->Track(decoder.mDrainRequest);
@ -2523,6 +2771,7 @@ MediaFormatReader::Update(TrackType aTrack)
decoder.mError.ref() == NS_ERROR_DOM_MEDIA_NEED_NEW_DECODER;
if (!needsNewDecoder &&
++decoder.mNumOfConsecutiveError > decoder.mMaxConsecutiveError) {
DDLOG(DDLogCategory::Log, "too_many_decode_errors", decoder.mError.ref());
NotifyError(aTrack, decoder.mError.ref());
return;
}
@ -2552,6 +2801,7 @@ MediaFormatReader::Update(TrackType aTrack)
} else if (aTrack == TrackType::kAudioTrack) {
decoder.Flush();
} else {
DDLOG(DDLogCategory::Log, "no_keyframe", NS_ERROR_DOM_MEDIA_FATAL_ERR);
// We can't recover from this error.
NotifyError(aTrack, NS_ERROR_DOM_MEDIA_FATAL_ERR);
}
@ -2820,6 +3070,8 @@ MediaFormatReader::OnVideoSkipCompleted(uint32_t aSkipped)
LOG("Skipping succeeded, skipped %u frames", aSkipped);
mSkipRequest.Complete();
DDLOG(DDLogCategory::Log, "video_skipped", DDNoValue());
VideoSkipReset(aSkipped);
ScheduleUpdate(TrackInfo::kVideoTrack);
@ -2836,6 +3088,8 @@ MediaFormatReader::OnVideoSkipFailed(
switch (aFailure.mFailure.Code()) {
case NS_ERROR_DOM_MEDIA_END_OF_STREAM:
case NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA:
DDLOG(
DDLogCategory::Log, "video_skipping_interruption", aFailure.mFailure);
// Some frames may have been output by the decoder since we initiated the
// videoskip process and we know they would be late.
DropDecodedSamples(TrackInfo::kVideoTrack);
@ -2844,11 +3098,14 @@ MediaFormatReader::OnVideoSkipFailed(
ScheduleUpdate(TrackInfo::kVideoTrack);
break;
case NS_ERROR_DOM_MEDIA_CANCELED:
DDLOG(
DDLogCategory::Log, "video_skipping_interruption", aFailure.mFailure);
if (mVideo.HasPromise()) {
mVideo.RejectPromise(aFailure.mFailure, __func__);
}
break;
default:
DDLOG(DDLogCategory::Log, "video_skipping_error", aFailure.mFailure);
NotifyError(TrackType::kVideoTrack, aFailure.mFailure);
break;
}

View File

@ -87,7 +87,10 @@ struct MOZ_STACK_CLASS MediaFormatReaderInit
MediaDecoderOwnerID mMediaDecoderOwnerID = nullptr;
};
DDLoggedTypeDeclName(MediaFormatReader);
class MediaFormatReader final
: public DecoderDoctorLifeLogger<MediaFormatReader>
{
static const bool IsExclusive = true;
typedef TrackInfo::TrackType TrackType;
@ -383,6 +386,14 @@ private:
, mLastStreamSourceID(UINT32_MAX)
, mIsNullDecode(false)
{
DecoderDoctorLogger::LogConstruction("MediaFormatReader::DecoderData",
this);
}
~DecoderData()
{
DecoderDoctorLogger::LogDestruction("MediaFormatReader::DecoderData",
this);
}
MediaFormatReader* mOwner;
@ -617,6 +628,17 @@ private:
: DecoderData(aOwner, aType, aNumOfMaxError)
, mHasPromise(false)
{
DecoderDoctorLogger::LogConstructionAndBase(
"MediaFormatReader::DecoderDataWithPromise",
this,
"MediaFormatReader::DecoderData",
static_cast<const MediaFormatReader::DecoderData*>(this));
}
~DecoderDataWithPromise()
{
DecoderDoctorLogger::LogDestruction(
"MediaFormatReader::DecoderDataWithPromise", this);
}
bool HasPromise() const override

View File

@ -57,6 +57,7 @@ MediaResourceIndex::MediaResourceIndex(MediaResource* aResource)
, mCachedBytes(0)
, mCachedBlock(MakeUnique<char[]>(mCacheBlockSize))
{
DDLINKCHILD("resource", aResource);
}
nsresult

View File

@ -6,6 +6,7 @@
#if !defined(MediaResource_h_)
#define MediaResource_h_
#include "DecoderDoctorLogger.h"
#include "Intervals.h"
#include "MediaData.h"
#include "mozilla/Attributes.h"
@ -22,6 +23,8 @@ namespace mozilla {
typedef media::Interval<int64_t> MediaByteRange;
typedef media::IntervalSet<int64_t> MediaByteRangeSet;
DDLoggedTypeDeclName(MediaResource);
/**
* Provides a thread-safe, seek/read interface to resources
* loaded from a URI. Uses MediaCache to cache data received over
@ -45,7 +48,7 @@ typedef media::IntervalSet<int64_t> MediaByteRangeSet;
* For cross-process blob URL, CloneableWithRangeMediaResource is used.
* MediaResource::Create automatically chooses the best implementation class.
*/
class MediaResource
class MediaResource : public DecoderDoctorLifeLogger<MediaResource>
{
public:
// Our refcounting is threadsafe, and when our refcount drops to zero
@ -147,6 +150,8 @@ private:
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
DDLoggedTypeDeclName(MediaResourceIndex);
/*
* MediaResourceIndex provides a way to access MediaResource objects.
* Read, Seek and Tell must only be called on non-main threads.
@ -154,7 +159,7 @@ private:
* example. You must ensure that no threads are calling these methods once
* the MediaResource has been Closed.
*/
class MediaResourceIndex
class MediaResourceIndex : public DecoderDoctorLifeLogger<MediaResourceIndex>
{
public:
explicit MediaResourceIndex(MediaResource* aResource);

View File

@ -7,6 +7,7 @@
#ifndef MediaResourceCallback_h_
#define MediaResourceCallback_h_
#include "DecoderDoctorLogger.h"
#include "nsError.h"
#include "nsISupportsImpl.h"
#include "MediaResult.h"
@ -17,6 +18,8 @@ class AbstractThread;
class MediaDecoderOwner;
class MediaResource;
DDLoggedTypeDeclName(MediaResourceCallback);
/**
* A callback used by MediaResource (sub-classes like FileMediaResource,
* RtspMediaResource, and ChannelMediaResource) to notify various events.
@ -26,7 +29,9 @@ class MediaResource;
* gtests for the readers without using a mock MediaResource when you don't
* care about the events notified by the MediaResource.
*/
class MediaResourceCallback {
class MediaResourceCallback
: public DecoderDoctorLifeLogger<MediaResourceCallback>
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaResourceCallback);

View File

@ -24,6 +24,12 @@
struct JSContext;
namespace mozilla {
namespace dom {
class MediaKeySession;
} // namespace dom
DDLoggedTypeName(dom::MediaKeySession);
namespace dom {
class ArrayBufferViewOrArrayBuffer;
@ -36,7 +42,9 @@ ToCString(MediaKeySessionType aType);
nsString
ToString(MediaKeySessionType aType);
class MediaKeySession final : public DOMEventTargetHelper
class MediaKeySession final
: public DOMEventTargetHelper
, public DecoderDoctorLifeLogger<MediaKeySession>
{
public:
NS_DECL_ISUPPORTS_INHERITED

View File

@ -498,6 +498,7 @@ MediaKeys::CreateSession(JSContext* aCx,
if (aRv.Failed()) {
return nullptr;
}
DDLINKCHILD("session", session.get());
// Add session to the set of sessions awaiting their sessionId being ready.
mPendingSessions.Put(session->Token(), session);

View File

@ -7,6 +7,7 @@
#ifndef mozilla_dom_mediakeys_h__
#define mozilla_dom_mediakeys_h__
#include "DecoderDoctorLogger.h"
#include "nsWrapperCache.h"
#include "nsISupports.h"
#include "mozilla/Attributes.h"
@ -26,6 +27,11 @@ namespace mozilla {
class CDMProxy;
namespace dom {
class MediaKeys;
} // namespace dom
DDLoggedTypeName(dom::MediaKeys);
namespace dom {
class ArrayBufferViewOrArrayBuffer;
@ -41,9 +47,11 @@ typedef uint32_t PromiseId;
// This class is used on the main thread only.
// Note: its addref/release is not (and can't be) thread safe!
class MediaKeys final : public nsISupports,
public nsWrapperCache,
public SupportsWeakPtr<MediaKeys>
class MediaKeys final
: public nsISupports
, public nsWrapperCache
, public SupportsWeakPtr<MediaKeys>
, public DecoderDoctorLifeLogger<MediaKeys>
{
~MediaKeys();

View File

@ -559,13 +559,18 @@ private:
// FlacDemuxer
FlacDemuxer::FlacDemuxer(MediaResource* aSource) : mSource(aSource) { }
FlacDemuxer::FlacDemuxer(MediaResource* aSource)
: mSource(aSource)
{
DDLINKCHILD("source", aSource);
}
bool
FlacDemuxer::InitInternal()
{
if (!mTrackDemuxer) {
mTrackDemuxer = new FlacTrackDemuxer(mSource);
DDLINKCHILD("track demuxer", mTrackDemuxer.get());
}
return mTrackDemuxer->Init();
}
@ -612,6 +617,7 @@ FlacTrackDemuxer::FlacTrackDemuxer(MediaResource* aSource)
, mParser(new flac::FrameParser())
, mTotalFrameLen(0)
{
DDLINKCHILD("source", aSource);
Reset();
}

View File

@ -18,8 +18,12 @@ class FrameParser;
}
class FlacTrackDemuxer;
DDLoggedTypeDeclNameAndBase(FlacDemuxer, MediaDataDemuxer);
DDLoggedTypeNameAndBase(FlacTrackDemuxer, MediaTrackDemuxer);
class FlacDemuxer : public MediaDataDemuxer
class FlacDemuxer
: public MediaDataDemuxer
, public DecoderDoctorLifeLogger<FlacDemuxer>
{
public:
// MediaDataDemuxer interface.
@ -40,7 +44,9 @@ private:
RefPtr<FlacTrackDemuxer> mTrackDemuxer;
};
class FlacTrackDemuxer : public MediaTrackDemuxer
class FlacTrackDemuxer
: public MediaTrackDemuxer
, public DecoderDoctorLifeLogger<FlacTrackDemuxer>
{
public:
explicit FlacTrackDemuxer(MediaResource* aSource);

View File

@ -9,10 +9,13 @@
#include "nsTArray.h"
#include "mozilla/Atomics.h"
namespace mozilla
{
namespace mozilla {
class MockMediaResource : public MediaResource
DDLoggedTypeDeclNameAndBase(MockMediaResource, MediaResource);
class MockMediaResource
: public MediaResource
, public DecoderDoctorLifeLogger<MockMediaResource>
{
public:
explicit MockMediaResource(const char* aFileName);

View File

@ -10,12 +10,21 @@
#include "mozilla/ArrayUtils.h"
#include "MockMediaResource.h"
class MockMP3MediaResource;
class MockMP3StreamMediaResource;
namespace mozilla {
DDLoggedTypeNameAndBase(::MockMP3MediaResource, MockMediaResource);
DDLoggedTypeNameAndBase(::MockMP3StreamMediaResource, MockMP3MediaResource);
} // namespace mozilla
using namespace mozilla;
using media::TimeUnit;
// Regular MP3 file mock resource.
class MockMP3MediaResource : public MockMediaResource {
class MockMP3MediaResource
: public MockMediaResource
, public DecoderDoctorLifeLogger<MockMP3MediaResource>
{
public:
explicit MockMP3MediaResource(const char* aFileName)
: MockMediaResource(aFileName)
@ -26,7 +35,10 @@ protected:
};
// MP3 stream mock resource.
class MockMP3StreamMediaResource : public MockMP3MediaResource {
class MockMP3StreamMediaResource
: public MockMP3MediaResource
, public DecoderDoctorLifeLogger<MockMP3StreamMediaResource>
{
public:
explicit MockMP3StreamMediaResource(const char* aFileName)
: MockMP3MediaResource(aFileName)

View File

@ -12,11 +12,18 @@
#include "MP4Metadata.h"
#include "MoofParser.h"
class TestStream;
namespace mozilla {
DDLoggedTypeNameAndBase(::TestStream, ByteStream);
} // namespace mozilla
using namespace mozilla;
static const uint32_t E = MP4Metadata::NumberTracksError();
class TestStream : public ByteStream
class TestStream
: public ByteStream
, public DecoderDoctorLifeLogger<TestStream>
{
public:
TestStream(const uint8_t* aBuffer, size_t aSize)

View File

@ -25,7 +25,12 @@ class AbstractThread;
class MediaResult;
class HLSTrackDemuxer;
class HLSDemuxer final : public MediaDataDemuxer
DDLoggedTypeDeclNameAndBase(HLSDemuxer, MediaDataDemuxer);
DDLoggedTypeNameAndBase(HLSTrackDemuxer, MediaTrackDemuxer);
class HLSDemuxer final
: public MediaDataDemuxer
, public DecoderDoctorLifeLogger<HLSDemuxer>
{
class HLSDemuxerCallbacksSupport;
public:
@ -68,7 +73,9 @@ private:
java::GeckoHLSDemuxerWrapper::GlobalRef mHLSDemuxerWrapper;
};
class HLSTrackDemuxer : public MediaTrackDemuxer
class HLSTrackDemuxer
: public MediaTrackDemuxer
, public DecoderDoctorLifeLogger<HLSTrackDemuxer>
{
public:
HLSTrackDemuxer(HLSDemuxer* aParent,

View File

@ -12,6 +12,14 @@
#include "PlatformDecoderModule.h"
namespace mozilla {
namespace dom {
class RemoteVideoDecoder;
}
DDLoggedTypeCustomNameAndBase(dom::RemoteVideoDecoder,
RemoteVideoDecoder,
MediaDataDecoder);
namespace dom {
class VideoDecoderChild;
@ -21,7 +29,9 @@ class RemoteDecoderModule;
// to a 'real' decoder in the GPU process.
// All requests get forwarded to a VideoDecoderChild instance that
// operates solely on the VideoDecoderManagerChild thread.
class RemoteVideoDecoder : public MediaDataDecoder
class RemoteVideoDecoder
: public MediaDataDecoder
, public DecoderDoctorLifeLogger<RemoteVideoDecoder>
{
public:
friend class RemoteDecoderModule;

View File

@ -119,7 +119,11 @@ ContainerParser::MediaSegmentRange()
return mCompleteMediaSegmentRange;
}
class WebMContainerParser : public ContainerParser
DDLoggedTypeDeclNameAndBase(WebMContainerParser, ContainerParser);
class WebMContainerParser
: public ContainerParser
, public DecoderDoctorLifeLogger<WebMContainerParser>
{
public:
explicit WebMContainerParser(const MediaContainerType& aType)
@ -194,6 +198,7 @@ public:
mOverlappedMapping.Clear();
mInitData = new MediaByteBuffer();
mResource = new SourceBufferResource();
DDLINKCHILD("resource", mResource.get());
mCompleteInitSegmentRange = MediaByteRange();
mCompleteMediaHeaderRange = MediaByteRange();
mCompleteMediaSegmentRange = MediaByteRange();
@ -341,7 +346,11 @@ private:
#ifdef MOZ_FMP4
class MP4Stream : public ByteStream
DDLoggedTypeDeclNameAndBase(MP4Stream, ByteStream);
class MP4Stream
: public ByteStream
, public DecoderDoctorLifeLogger<MP4Stream>
{
public:
explicit MP4Stream(SourceBufferResource* aResource);
@ -365,6 +374,7 @@ MP4Stream::MP4Stream(SourceBufferResource* aResource)
{
MOZ_COUNT_CTOR(MP4Stream);
MOZ_ASSERT(aResource);
DDLINKCHILD("resource", aResource);
}
MP4Stream::~MP4Stream()
@ -406,7 +416,11 @@ MP4Stream::Length(int64_t* aSize)
return true;
}
class MP4ContainerParser : public ContainerParser
DDLoggedTypeDeclNameAndBase(MP4ContainerParser, ContainerParser);
class MP4ContainerParser
: public ContainerParser
, public DecoderDoctorLifeLogger<MP4ContainerParser>
{
public:
explicit MP4ContainerParser(const MediaContainerType& aType)
@ -575,12 +589,14 @@ public:
bool initSegment = NS_SUCCEEDED(IsInitSegmentPresent(aData));
if (initSegment) {
mResource = new SourceBufferResource();
DDLINKCHILD("resource", mResource.get());
mStream = new MP4Stream(mResource);
// We use a timestampOffset of 0 for ContainerParser, and require
// consumers of ParseStartAndEndTimestamps to add their timestamp offset
// manually. This allows the ContainerParser to be shared across different
// timestampOffsets.
mParser = new MoofParser(mStream, 0, /* aIsAudio = */ false);
DDLINKCHILD("parser", mParser.get());
mInitData = new MediaByteBuffer();
mCompleteInitSegmentRange = MediaByteRange();
mCompleteMediaHeaderRange = MediaByteRange();
@ -657,7 +673,11 @@ private:
#endif // MOZ_FMP4
#ifdef MOZ_FMP4
class ADTSContainerParser : public ContainerParser
DDLoggedTypeDeclNameAndBase(ADTSContainerParser, ContainerParser);
class ADTSContainerParser
: public ContainerParser
, public DecoderDoctorLifeLogger<ADTSContainerParser>
{
public:
explicit ADTSContainerParser(const MediaContainerType& aType)

View File

@ -17,7 +17,9 @@ namespace mozilla {
class MediaByteBuffer;
class SourceBufferResource;
class ContainerParser
DDLoggedTypeDeclName(ContainerParser);
class ContainerParser : public DecoderDoctorLifeLogger<ContainerParser>
{
public:
explicit ContainerParser(const MediaContainerType& aType);

View File

@ -260,6 +260,7 @@ MediaSource::AddSourceBuffer(const nsAString& aType, ErrorResult& aRv)
return nullptr;
}
mSourceBuffers->Append(sourceBuffer);
DDLINKCHILD("sourcebuffer[]", sourceBuffer.get());
MSE_DEBUG("sourceBuffer=%p", sourceBuffer.get());
return sourceBuffer.forget();
}
@ -335,6 +336,7 @@ MediaSource::RemoveSourceBuffer(SourceBuffer& aSourceBuffer, ErrorResult& aRv)
mActiveSourceBuffers->Remove(sourceBuffer);
}
mSourceBuffers->Remove(sourceBuffer);
DDUNLINKCHILD(sourceBuffer);
// TODO: Free all resources associated with sourceBuffer
}

View File

@ -33,6 +33,11 @@ class ErrorResult;
template <typename T> class AsyncEventRunner;
class MediaResult;
namespace dom {
class MediaSource;
} // namespace dom
DDLoggedTypeName(dom::MediaSource);
namespace dom {
class GlobalObject;
@ -44,7 +49,9 @@ template <typename T> class Optional;
{ 0x3839d699, 0x22c5, 0x439f, \
{ 0x94, 0xca, 0x0e, 0x0b, 0x26, 0xf9, 0xca, 0xbf } }
class MediaSource final : public DOMEventTargetHelper
class MediaSource final
: public DOMEventTargetHelper
, public DecoderDoctorLifeLogger<MediaSource>
{
public:
/** WebIDL Methods. */

View File

@ -184,12 +184,14 @@ MediaSourceDecoder::AttachMediaSource(dom::MediaSource* aMediaSource)
{
MOZ_ASSERT(!mMediaSource && !GetStateMachine() && NS_IsMainThread());
mMediaSource = aMediaSource;
DDLINKCHILD("mediasource", aMediaSource);
}
void
MediaSourceDecoder::DetachMediaSource()
{
MOZ_ASSERT(mMediaSource && NS_IsMainThread());
DDUNLINKCHILD(mMediaSource);
mMediaSource = nullptr;
}

View File

@ -21,7 +21,11 @@ class MediaSource;
} // namespace dom
class MediaSourceDecoder : public MediaDecoder
DDLoggedTypeDeclNameAndBase(MediaSourceDecoder, MediaDecoder);
class MediaSourceDecoder
: public MediaDecoder
, public DecoderDoctorLifeLogger<MediaSourceDecoder>
{
public:
explicit MediaSourceDecoder(MediaDecoderInit& aInit);

View File

@ -144,6 +144,7 @@ MediaSourceDemuxer::GetTrackDemuxer(TrackType aType, uint32_t aTrackNumber)
}
RefPtr<MediaSourceTrackDemuxer> e =
new MediaSourceTrackDemuxer(this, aType, manager);
DDLINKCHILD("track demuxer", e.get());
mDemuxers.AppendElement(e);
return e.forget();
}

View File

@ -23,7 +23,12 @@ class AbstractThread;
class MediaResult;
class MediaSourceTrackDemuxer;
class MediaSourceDemuxer : public MediaDataDemuxer
DDLoggedTypeDeclNameAndBase(MediaSourceDemuxer, MediaDataDemuxer);
DDLoggedTypeNameAndBase(MediaSourceTrackDemuxer, MediaTrackDemuxer);
class MediaSourceDemuxer
: public MediaDataDemuxer
, public DecoderDoctorLifeLogger<MediaSourceDemuxer>
{
public:
explicit MediaSourceDemuxer(AbstractThread* aAbstractMainThread);
@ -87,7 +92,9 @@ private:
MediaInfo mInfo;
};
class MediaSourceTrackDemuxer : public MediaTrackDemuxer
class MediaSourceTrackDemuxer
: public MediaTrackDemuxer
, public DecoderDoctorLifeLogger<MediaSourceTrackDemuxer>
{
public:
MediaSourceTrackDemuxer(MediaSourceDemuxer* aParent,

View File

@ -137,6 +137,7 @@ SourceBuffer::SetAppendWindowStart(double aAppendWindowStart, ErrorResult& aRv)
{
MOZ_ASSERT(NS_IsMainThread());
MSE_API("SetAppendWindowStart(aAppendWindowStart=%f)", aAppendWindowStart);
DDLOG(DDLogCategory::API, "SetAppendWindowStart", aAppendWindowStart);
if (!IsAttached() || mUpdating) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return;
@ -154,6 +155,7 @@ SourceBuffer::SetAppendWindowEnd(double aAppendWindowEnd, ErrorResult& aRv)
{
MOZ_ASSERT(NS_IsMainThread());
MSE_API("SetAppendWindowEnd(aAppendWindowEnd=%f)", aAppendWindowEnd);
DDLOG(DDLogCategory::API, "SetAppendWindowEnd", aAppendWindowEnd);
if (!IsAttached() || mUpdating) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return;
@ -172,6 +174,7 @@ SourceBuffer::AppendBuffer(const ArrayBuffer& aData, ErrorResult& aRv)
MOZ_ASSERT(NS_IsMainThread());
MSE_API("AppendBuffer(ArrayBuffer)");
aData.ComputeLengthAndData();
DDLOG(DDLogCategory::API, "AppendBuffer", aData.Length());
AppendData(aData.Data(), aData.Length(), aRv);
}
@ -181,6 +184,7 @@ SourceBuffer::AppendBuffer(const ArrayBufferView& aData, ErrorResult& aRv)
MOZ_ASSERT(NS_IsMainThread());
MSE_API("AppendBuffer(ArrayBufferView)");
aData.ComputeLengthAndData();
DDLOG(DDLogCategory::API, "AppendBuffer", aData.Length());
AppendData(aData.Data(), aData.Length(), aRv);
}
@ -190,17 +194,21 @@ SourceBuffer::Abort(ErrorResult& aRv)
MOZ_ASSERT(NS_IsMainThread());
MSE_API("Abort()");
if (!IsAttached()) {
DDLOG(DDLogCategory::API, "Abort", NS_ERROR_DOM_INVALID_STATE_ERR);
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return;
}
if (mMediaSource->ReadyState() != MediaSourceReadyState::Open) {
DDLOG(DDLogCategory::API, "Abort", NS_ERROR_DOM_INVALID_STATE_ERR);
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return;
}
if (mPendingRemoval.Exists()) {
DDLOG(DDLogCategory::API, "Abort", NS_ERROR_DOM_INVALID_STATE_ERR);
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return;
}
DDLOG(DDLogCategory::API, "Abort", NS_OK);
AbortBufferAppend();
ResetParserState();
mCurrentAttributes.SetAppendWindowStart(0);
@ -231,6 +239,8 @@ SourceBuffer::Remove(double aStart, double aEnd, ErrorResult& aRv)
{
MOZ_ASSERT(NS_IsMainThread());
MSE_API("Remove(aStart=%f, aEnd=%f)", aStart, aEnd);
DDLOG(DDLogCategory::API, "Remove-from", aStart);
DDLOG(DDLogCategory::API, "Remove-until", aEnd);
if (!IsAttached()) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return;
@ -313,6 +323,7 @@ SourceBuffer::SourceBuffer(MediaSource* aMediaSource,
mTrackBuffersManager =
new TrackBuffersManager(aMediaSource->GetDecoder(), aType);
DDLINKCHILD("track buffers manager", mTrackBuffersManager.get());
MSE_DEBUG("Create mTrackBuffersManager=%p",
mTrackBuffersManager.get());
@ -429,6 +440,7 @@ SourceBuffer::AppendDataCompletedWithSuccess(const SourceBufferTask::AppendBuffe
{
MOZ_ASSERT(mUpdating);
mPendingAppend.Complete();
DDLOG(DDLogCategory::API, "AppendBuffer-completed", NS_OK);
if (aResult.first()) {
if (!mActive) {
@ -465,6 +477,7 @@ SourceBuffer::AppendDataErrored(const MediaResult& aError)
{
MOZ_ASSERT(mUpdating);
mPendingAppend.Complete();
DDLOG(DDLogCategory::API, "AppendBuffer-error", aError);
switch (aError.Code()) {
case NS_ERROR_DOM_MEDIA_CANCELED:

View File

@ -37,11 +37,15 @@ class ErrorResult;
class MediaByteBuffer;
template <typename T> class AsyncEventRunner;
DDLoggedTypeName(dom::SourceBuffer);
namespace dom {
class TimeRanges;
class SourceBuffer final : public DOMEventTargetHelper
class SourceBuffer final
: public DOMEventTargetHelper
, public DecoderDoctorLifeLogger<SourceBuffer>
{
public:
/** WebIDL Methods. */

View File

@ -26,8 +26,12 @@ class SourceBuffer;
} // namespace dom
DDLoggedTypeDeclNameAndBase(SourceBufferResource, MediaResource);
// SourceBufferResource is not thread safe.
class SourceBufferResource final : public MediaResource
class SourceBufferResource final
: public MediaResource
, public DecoderDoctorLifeLogger<SourceBufferResource>
{
public:
SourceBufferResource();

View File

@ -114,6 +114,7 @@ TrackBuffersManager::TrackBuffersManager(MediaSourceDecoder* aParentDecoder,
, mTaskQueue(aParentDecoder->GetDemuxer()->GetTaskQueue())
{
MOZ_ASSERT(NS_IsMainThread(), "Must be instanciated on the main thread");
DDLINKCHILD("parser", mParser.get());
}
TrackBuffersManager::~TrackBuffersManager()
@ -879,6 +880,7 @@ TrackBuffersManager::CreateDemuxerforMIMEType()
if (mType.Type() == MEDIAMIMETYPE("video/webm") ||
mType.Type() == MEDIAMIMETYPE("audio/webm")) {
mInputDemuxer = new WebMDemuxer(mCurrentInputBuffer, true /* IsMediaSource*/ );
DDLINKCHILD("demuxer", mInputDemuxer.get());
return;
}
@ -886,6 +888,7 @@ TrackBuffersManager::CreateDemuxerforMIMEType()
if (mType.Type() == MEDIAMIMETYPE("video/mp4") ||
mType.Type() == MEDIAMIMETYPE("audio/mp4")) {
mInputDemuxer = new MP4Demuxer(mCurrentInputBuffer);
DDLINKCHILD("demuxer", mInputDemuxer.get());
return;
}
#endif
@ -950,6 +953,7 @@ TrackBuffersManager::OnDemuxerResetDone(const MediaResult& aResult)
mVideoTracks.mDemuxer =
mInputDemuxer->GetTrackDemuxer(TrackInfo::kVideoTrack, 0);
MOZ_ASSERT(mVideoTracks.mDemuxer);
DDLINKCHILD("video demuxer", mVideoTracks.mDemuxer.get());
}
uint32_t numAudios = mInputDemuxer->GetNumberTracks(TrackInfo::kAudioTrack);
@ -958,6 +962,7 @@ TrackBuffersManager::OnDemuxerResetDone(const MediaResult& aResult)
mAudioTracks.mDemuxer =
mInputDemuxer->GetTrackDemuxer(TrackInfo::kAudioTrack, 0);
MOZ_ASSERT(mAudioTracks.mDemuxer);
DDLINKCHILD("audio demuxer", mAudioTracks.mDemuxer.get());
}
if (mPendingInputBuffer) {
@ -1043,6 +1048,7 @@ TrackBuffersManager::OnDemuxerInitDone(const MediaResult& aResult)
mVideoTracks.mDemuxer =
mInputDemuxer->GetTrackDemuxer(TrackInfo::kVideoTrack, 0);
MOZ_ASSERT(mVideoTracks.mDemuxer);
DDLINKCHILD("video demuxer", mVideoTracks.mDemuxer.get());
info.mVideo = *mVideoTracks.mDemuxer->GetInfo()->GetAsVideoInfo();
info.mVideo.mTrackId = 2;
}
@ -1053,6 +1059,7 @@ TrackBuffersManager::OnDemuxerInitDone(const MediaResult& aResult)
mAudioTracks.mDemuxer =
mInputDemuxer->GetTrackDemuxer(TrackInfo::kAudioTrack, 0);
MOZ_ASSERT(mAudioTracks.mDemuxer);
DDLINKCHILD("audio demuxer", mAudioTracks.mDemuxer.get());
info.mAudio = *mAudioTracks.mDemuxer->GetInfo()->GetAsAudioInfo();
info.mAudio.mTrackId = 1;
}
@ -2049,7 +2056,11 @@ TrackBuffersManager::RecreateParser(bool aReuseInitData)
// as it has parsed the entire InputBuffer provided.
// Once the old TrackBuffer/MediaSource implementation is removed
// we can optimize this part. TODO
if (mParser) {
DDUNLINKCHILD(mParser.get());
}
mParser = ContainerParser::CreateForMIMEType(mType);
DDLINKCHILD("parser", mParser.get());
if (aReuseInitData && mInitData) {
int64_t start, end;
mParser->ParseStartAndEndTimestamps(mInitData, start, end);

View File

@ -65,7 +65,9 @@ private:
nsTArray<RefPtr<SourceBufferTask>> mQueue;
};
class TrackBuffersManager
DDLoggedTypeDeclName(TrackBuffersManager);
class TrackBuffersManager : public DecoderDoctorLifeLogger<TrackBuffersManager>
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TrackBuffersManager);

View File

@ -30,13 +30,18 @@ namespace mozilla {
// MP3Demuxer
MP3Demuxer::MP3Demuxer(MediaResource* aSource) : mSource(aSource) { }
MP3Demuxer::MP3Demuxer(MediaResource* aSource)
: mSource(aSource)
{
DDLINKCHILD("source", aSource);
}
bool
MP3Demuxer::InitInternal()
{
if (!mTrackDemuxer) {
mTrackDemuxer = new MP3TrackDemuxer(mSource);
DDLINKCHILD("track demuxer", mTrackDemuxer.get());
}
return mTrackDemuxer->Init();
}
@ -107,6 +112,7 @@ MP3TrackDemuxer::MP3TrackDemuxer(MediaResource* aSource)
, mSamplesPerSecond(0)
, mChannels(0)
{
DDLINKCHILD("source", aSource);
Reset();
}

View File

@ -13,7 +13,12 @@ namespace mozilla {
class MP3TrackDemuxer;
class MP3Demuxer : public MediaDataDemuxer
DDLoggedTypeDeclNameAndBase(MP3Demuxer, MediaDataDemuxer);
DDLoggedTypeNameAndBase(MP3TrackDemuxer, MediaTrackDemuxer);
class MP3Demuxer
: public MediaDataDemuxer
, public DecoderDoctorLifeLogger<MP3Demuxer>
{
public:
// MediaDataDemuxer interface.
@ -36,7 +41,9 @@ private:
// The MP3 demuxer used to extract MPEG frames and side information out of
// MPEG streams.
class MP3TrackDemuxer : public MediaTrackDemuxer
class MP3TrackDemuxer
: public MediaTrackDemuxer
, public DecoderDoctorLifeLogger<MP3TrackDemuxer>
{
public:
// Constructor, expecting a valid media resource.

View File

@ -12,7 +12,11 @@
namespace mozilla {
class MediaByteBuffer;
class BufferStream : public ByteStream
DDLoggedTypeDeclNameAndBase(BufferStream, ByteStream);
class BufferStream
: public ByteStream
, public mozilla::DecoderDoctorLifeLogger<BufferStream>
{
public:
/* BufferStream does not take ownership of aData nor does it make a copy.

View File

@ -5,12 +5,14 @@
#ifndef STREAM_H_
#define STREAM_H_
#include "DecoderDoctorLogger.h"
#include "nsISupportsImpl.h"
namespace mozilla
{
namespace mozilla {
class ByteStream
DDLoggedTypeDeclName(ByteStream);
class ByteStream : public DecoderDoctorLifeLogger<ByteStream>
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ByteStream);

View File

@ -33,7 +33,11 @@ mozilla::LogModule* GetDemuxerLog()
namespace mozilla {
class MP4TrackDemuxer : public MediaTrackDemuxer
DDLoggedTypeDeclNameAndBase(MP4TrackDemuxer, MediaTrackDemuxer);
class MP4TrackDemuxer
: public MediaTrackDemuxer
, public DecoderDoctorLifeLogger<MP4TrackDemuxer>
{
public:
MP4TrackDemuxer(MP4Demuxer* aParent,
@ -120,6 +124,8 @@ MP4Demuxer::MP4Demuxer(MediaResource* aResource)
: mResource(aResource)
, mStream(new ResourceStream(aResource))
{
DDLINKCHILD("resource", aResource);
DDLINKCHILD("stream", mStream.get());
}
RefPtr<MP4Demuxer::InitPromise>
@ -147,6 +153,7 @@ MP4Demuxer::Init()
new BufferStream(initData.Ref());
MP4Metadata metadata{bufferstream};
DDLINKCHILD("metadata", &metadata);
nsresult rv = metadata.Parse();
if (NS_FAILED(rv)) {
return InitPromise::CreateAndReject(
@ -222,8 +229,10 @@ MP4Demuxer::Init()
}
continue;
}
mAudioDemuxers.AppendElement(
new MP4TrackDemuxer(this, Move(info.Ref()), *indices.Ref().get()));
RefPtr<MP4TrackDemuxer> demuxer =
new MP4TrackDemuxer(this, Move(info.Ref()), *indices.Ref().get());
DDLINKCHILD("audio demuxer", demuxer.get());
mAudioDemuxers.AppendElement(Move(demuxer));
}
}
@ -256,8 +265,10 @@ MP4Demuxer::Init()
}
continue;
}
mVideoDemuxers.AppendElement(
new MP4TrackDemuxer(this, Move(info.Ref()), *indices.Ref().get()));
RefPtr<MP4TrackDemuxer> demuxer =
new MP4TrackDemuxer(this, Move(info.Ref()), *indices.Ref().get());
DDLINKCHILD("video demuxer", demuxer.get());
mVideoDemuxers.AppendElement(Move(demuxer));
}
}

View File

@ -16,7 +16,11 @@ namespace mozilla {
class MP4TrackDemuxer;
class ResourceStream;
class MP4Demuxer : public MediaDataDemuxer
DDLoggedTypeDeclNameAndBase(MP4Demuxer, MediaDataDemuxer);
class MP4Demuxer
: public MediaDataDemuxer
, public DecoderDoctorLifeLogger<MP4Demuxer>
{
public:
explicit MP4Demuxer(MediaResource* aResource);

View File

@ -103,6 +103,8 @@ MP4Metadata::MP4Metadata(ByteStream* aSource)
: mSource(aSource)
, mSourceAdaptor(aSource)
{
DDLINKCHILD("source", aSource);
Mp4parseIo io = { read_source, &mSourceAdaptor };
mParser.reset(mp4parse_new(&io));
MOZ_ASSERT(mParser);

View File

@ -17,6 +17,8 @@
namespace mozilla {
DDLoggedTypeDeclName(MP4Metadata);
// The memory owner in mIndice.indices is rust mp4 parser, so lifetime of this
// class SHOULD NOT longer than rust parser.
class IndiceWrapper
@ -52,7 +54,7 @@ private:
CheckedInt<size_t> mOffset;
};
class MP4Metadata
class MP4Metadata : public DecoderDoctorLifeLogger<MP4Metadata>
{
public:
explicit MP4Metadata(ByteStream* aSource);

View File

@ -111,10 +111,16 @@ MoofParser::FirstCompleteMediaSegment()
return MediaByteRange();
}
class BlockingStream : public ByteStream {
DDLoggedTypeDeclNameAndBase(BlockingStream, ByteStream);
class BlockingStream
: public ByteStream
, public DecoderDoctorLifeLogger<BlockingStream>
{
public:
explicit BlockingStream(ByteStream* aStream) : mStream(aStream)
{
DDLINKCHILD("stream", aStream);
}
bool ReadAt(int64_t offset, void* data, size_t size, size_t* bytes_read)

View File

@ -14,6 +14,7 @@
#include "MediaResource.h"
namespace mozilla {
typedef int64_t Microseconds;
class Box;
@ -283,7 +284,9 @@ private:
uint64_t mMaxRoundingError;
};
class MoofParser
DDLoggedTypeDeclName(MoofParser);
class MoofParser : public DecoderDoctorLifeLogger<MoofParser>
{
public:
MoofParser(ByteStream* aSource, uint32_t aTrackId, bool aIsAudio)
@ -295,6 +298,7 @@ public:
{
// Setting the mTrex.mTrackId to 0 is a nasty work around for calculating
// the composition range for MSE. We need an array of tracks.
DDLINKCHILD("source", aSource);
}
bool RebuildFragmentedIndex(
const mozilla::MediaByteRangeSet& aByteRanges);

View File

@ -13,6 +13,7 @@ ResourceStream::ResourceStream(mozilla::MediaResource* aResource)
, mPinCount(0)
{
MOZ_ASSERT(aResource);
DDLINKCHILD("resource", &mResource);
}
ResourceStream::~ResourceStream()

View File

@ -12,7 +12,11 @@
namespace mozilla
{
class ResourceStream : public ByteStream
DDLoggedTypeDeclNameAndBase(ResourceStream, ByteStream);
class ResourceStream
: public ByteStream
, public DecoderDoctorLifeLogger<ResourceStream>
{
public:
explicit ResourceStream(mozilla::MediaResource* aResource);

View File

@ -116,6 +116,8 @@ OggDemuxer::OggDemuxer(MediaResource* aResource)
, mOnSeekableEvent(nullptr)
{
MOZ_COUNT_CTOR(OggDemuxer);
// aResource is referenced through inner m{Audio,Video}OffState members.
DDLINKCHILD("resource", aResource);
}
OggDemuxer::~OggDemuxer()
@ -284,6 +286,7 @@ OggDemuxer::GetTrackDemuxer(TrackInfo::TrackType aType, uint32_t aTrackNumber)
return nullptr;
}
RefPtr<OggTrackDemuxer> e = new OggTrackDemuxer(this, aType, aTrackNumber);
DDLINKCHILD("track demuxer", e.get());
mDemuxers.AppendElement(e);
return e.forget();

View File

@ -16,7 +16,12 @@ namespace mozilla {
class OggTrackDemuxer;
class OggDemuxer : public MediaDataDemuxer
DDLoggedTypeDeclNameAndBase(OggDemuxer, MediaDataDemuxer);
DDLoggedTypeNameAndBase(OggTrackDemuxer, MediaTrackDemuxer);
class OggDemuxer
: public MediaDataDemuxer
, public DecoderDoctorLifeLogger<OggDemuxer>
{
public:
explicit OggDemuxer(MediaResource* aResource);
@ -329,7 +334,9 @@ private:
friend class OggTrackDemuxer;
};
class OggTrackDemuxer : public MediaTrackDemuxer
class OggTrackDemuxer
: public MediaTrackDemuxer
, public DecoderDoctorLifeLogger<OggTrackDemuxer>
{
public:
OggTrackDemuxer(OggDemuxer* aParent,

View File

@ -7,6 +7,7 @@
#if !defined(PlatformDecoderModule_h_)
#define PlatformDecoderModule_h_
#include "DecoderDoctorLogger.h"
#include "GMPCrashHelper.h"
#include "MediaEventSource.h"
#include "MediaInfo.h"
@ -226,6 +227,8 @@ protected:
CreateAudioDecoder(const CreateDecoderParams& aParams) = 0;
};
DDLoggedTypeDeclName(MediaDataDecoder);
// MediaDataDecoder is the interface exposed by decoders created by the
// PlatformDecoderModule's Create*Decoder() functions. The type of
// media data that the decoder accepts as valid input and produces as
@ -243,7 +246,7 @@ protected:
// TaskQueue passed into the PlatformDecoderModules's Create*Decoder()
// function. This may not be necessary for platforms with async APIs
// for decoding.
class MediaDataDecoder
class MediaDataDecoder : public DecoderDoctorLifeLogger<MediaDataDecoder>
{
protected:
virtual ~MediaDataDecoder() { }

View File

@ -14,7 +14,11 @@
namespace mozilla {
class AOMDecoder : public MediaDataDecoder
DDLoggedTypeDeclNameAndBase(AOMDecoder, MediaDataDecoder);
class AOMDecoder
: public MediaDataDecoder
, public DecoderDoctorLifeLogger<AOMDecoder>
{
public:
explicit AOMDecoder(const CreateDecoderParams& aParams);

View File

@ -23,9 +23,13 @@ public:
virtual already_AddRefed<MediaData> Create(MediaRawData* aSample) = 0;
};
DDLoggedTypeDeclNameAndBase(DummyMediaDataDecoder, MediaDataDecoder);
// Decoder that uses a passed in object's Create function to create Null
// MediaData objects.
class DummyMediaDataDecoder : public MediaDataDecoder
class DummyMediaDataDecoder
: public MediaDataDecoder
, public DecoderDoctorLifeLogger<DummyMediaDataDecoder>
{
public:
DummyMediaDataDecoder(UniquePtr<DummyDataCreator>&& aCreator,

View File

@ -17,7 +17,11 @@ namespace mozilla {
class OpusParser;
class OpusDataDecoder : public MediaDataDecoder
DDLoggedTypeDeclNameAndBase(OpusDataDecoder, MediaDataDecoder);
class OpusDataDecoder
: public MediaDataDecoder
, public DecoderDoctorLifeLogger<OpusDataDecoder>
{
public:
explicit OpusDataDecoder(const CreateDecoderParams& aParams);

View File

@ -13,7 +13,11 @@
namespace mozilla {
class TheoraDecoder : public MediaDataDecoder
DDLoggedTypeDeclNameAndBase(TheoraDecoder, MediaDataDecoder);
class TheoraDecoder
: public MediaDataDecoder
, public DecoderDoctorLifeLogger<TheoraDecoder>
{
public:
explicit TheoraDecoder(const CreateDecoderParams& aParams);

View File

@ -17,7 +17,11 @@
namespace mozilla {
class VPXDecoder : public MediaDataDecoder
DDLoggedTypeDeclNameAndBase(VPXDecoder, MediaDataDecoder);
class VPXDecoder
: public MediaDataDecoder
, public DecoderDoctorLifeLogger<VPXDecoder>
{
public:
explicit VPXDecoder(const CreateDecoderParams& aParams);

View File

@ -18,7 +18,11 @@
namespace mozilla {
class VorbisDataDecoder : public MediaDataDecoder
DDLoggedTypeDeclNameAndBase(VorbisDataDecoder, MediaDataDecoder);
class VorbisDataDecoder
: public MediaDataDecoder
, public DecoderDoctorLifeLogger<VorbisDataDecoder>
{
public:
explicit VorbisDataDecoder(const CreateDecoderParams& aParams);

View File

@ -11,7 +11,11 @@
namespace mozilla {
class WaveDataDecoder : public MediaDataDecoder
DDLoggedTypeDeclNameAndBase(WaveDataDecoder, MediaDataDecoder);
class WaveDataDecoder
: public MediaDataDecoder
, public DecoderDoctorLifeLogger<WaveDataDecoder>
{
public:
explicit WaveDataDecoder(const CreateDecoderParams& aParams);

View File

@ -15,7 +15,11 @@ namespace mozilla {
class CDMProxy;
struct GMPVideoDecoderParams;
class ChromiumCDMVideoDecoder : public MediaDataDecoder
DDLoggedTypeDeclNameAndBase(ChromiumCDMVideoDecoder, MediaDataDecoder);
class ChromiumCDMVideoDecoder
: public MediaDataDecoder
, public DecoderDoctorLifeLogger<ChromiumCDMVideoDecoder>
{
public:
ChromiumCDMVideoDecoder(const GMPVideoDecoderParams& aParams,

View File

@ -25,7 +25,11 @@ namespace mozilla {
typedef MozPromiseRequestHolder<DecryptPromise> DecryptPromiseRequestHolder;
extern already_AddRefed<PlatformDecoderModule> CreateBlankDecoderModule();
class EMEDecryptor : public MediaDataDecoder
DDLoggedTypeDeclNameAndBase(EMEDecryptor, MediaDataDecoder);
class EMEDecryptor
: public MediaDataDecoder
, public DecoderDoctorLifeLogger<EMEDecryptor>
{
public:
EMEDecryptor(MediaDataDecoder* aDecoder, CDMProxy* aProxy,
@ -39,6 +43,7 @@ public:
, mThroughputLimiter(aDecodeTaskQueue)
, mIsShutdown(false)
{
DDLINKCHILD("decoder", mDecoder.get());
}
RefPtr<InitPromise> Init() override

View File

@ -42,7 +42,11 @@ private:
RefPtr<PDMFactory> mPDM;
};
class EMEMediaDataDecoderProxy : public MediaDataDecoderProxy
DDLoggedTypeDeclNameAndBase(EMEMediaDataDecoderProxy, MediaDataDecoderProxy);
class EMEMediaDataDecoderProxy
: public MediaDataDecoderProxy
, public DecoderDoctorLifeLogger<EMEMediaDataDecoderProxy>
{
public:
EMEMediaDataDecoderProxy(

View File

@ -27,8 +27,12 @@ struct GMPVideoDecoderParams
RefPtr<GMPCrashHelper> mCrashHelper;
};
class GMPVideoDecoder : public MediaDataDecoder,
public GMPVideoDecoderCallbackProxy
DDLoggedTypeDeclNameAndBase(GMPVideoDecoder, MediaDataDecoder);
class GMPVideoDecoder
: public MediaDataDecoder
, public GMPVideoDecoderCallbackProxy
, public DecoderDoctorLifeLogger<GMPVideoDecoder>
{
public:
explicit GMPVideoDecoder(const GMPVideoDecoderParams& aParams);

View File

@ -14,7 +14,11 @@
namespace mozilla {
class RemoteDataDecoder : public MediaDataDecoder
DDLoggedTypeDeclNameAndBase(RemoteDataDecoder, MediaDataDecoder);
class RemoteDataDecoder
: public MediaDataDecoder
, public DecoderDoctorLifeLogger<RemoteDataDecoder>
{
public:
static already_AddRefed<MediaDataDecoder>

View File

@ -17,7 +17,11 @@ namespace mozilla {
class TaskQueue;
class AppleATDecoder : public MediaDataDecoder
DDLoggedTypeDeclNameAndBase(AppleATDecoder, MediaDataDecoder);
class AppleATDecoder
: public MediaDataDecoder
, public DecoderDoctorLifeLogger<AppleATDecoder>
{
public:
AppleATDecoder(const AudioInfo& aConfig,

View File

@ -17,7 +17,11 @@
namespace mozilla {
class AppleVTDecoder : public MediaDataDecoder
DDLoggedTypeDeclNameAndBase(AppleVTDecoder, MediaDataDecoder);
class AppleVTDecoder
: public MediaDataDecoder
, public DecoderDoctorLifeLogger<AppleVTDecoder>
{
public:
AppleVTDecoder(const VideoInfo& aConfig,

View File

@ -16,8 +16,15 @@ template <int V> class FFmpegAudioDecoder
{
};
template <>
class FFmpegAudioDecoder<LIBAV_VER> : public FFmpegDataDecoder<LIBAV_VER>
template<>
class FFmpegAudioDecoder<LIBAV_VER>;
DDLoggedTypeNameAndBase(FFmpegAudioDecoder<LIBAV_VER>,
FFmpegDataDecoder<LIBAV_VER>);
template<>
class FFmpegAudioDecoder<LIBAV_VER>
: public FFmpegDataDecoder<LIBAV_VER>
, public DecoderDoctorLifeLogger<FFmpegAudioDecoder<LIBAV_VER>>
{
public:
FFmpegAudioDecoder(FFmpegLibWrapper* aLib, TaskQueue* aTaskQueue,

View File

@ -19,8 +19,14 @@ class FFmpegDataDecoder : public MediaDataDecoder
{
};
template <>
class FFmpegDataDecoder<LIBAV_VER> : public MediaDataDecoder
template<>
class FFmpegDataDecoder<LIBAV_VER>;
DDLoggedTypeNameAndBase(FFmpegDataDecoder<LIBAV_VER>, MediaDataDecoder);
template<>
class FFmpegDataDecoder<LIBAV_VER>
: public MediaDataDecoder
, public DecoderDoctorLifeLogger<FFmpegDataDecoder<LIBAV_VER>>
{
public:
FFmpegDataDecoder(FFmpegLibWrapper* aLib, TaskQueue* aTaskQueue,

View File

@ -19,8 +19,15 @@ class FFmpegVideoDecoder : public FFmpegDataDecoder<V>
{
};
template <>
class FFmpegVideoDecoder<LIBAV_VER> : public FFmpegDataDecoder<LIBAV_VER>
template<>
class FFmpegVideoDecoder<LIBAV_VER>;
DDLoggedTypeNameAndBase(FFmpegVideoDecoder<LIBAV_VER>,
FFmpegDataDecoder<LIBAV_VER>);
template<>
class FFmpegVideoDecoder<LIBAV_VER>
: public FFmpegDataDecoder<LIBAV_VER>
, public DecoderDoctorLifeLogger<FFmpegVideoDecoder<LIBAV_VER>>
{
typedef mozilla::layers::Image Image;
typedef mozilla::layers::ImageContainer ImageContainer;

View File

@ -30,6 +30,8 @@ typedef OmxPromiseLayer::OmxCommandFailureHolder OmxCommandFailureHolder;
typedef OmxPromiseLayer::BufferData BufferData;
typedef OmxPromiseLayer::BUFFERLIST BUFFERLIST;
DDLoggedTypeDeclNameAndBase(OmxDataDecoder, MediaDataDecoder);
/* OmxDataDecoder is the major class which performs followings:
* 1. Translate PDM function into OMX commands.
* 2. Keeping the buffers between client and component.
@ -56,7 +58,9 @@ typedef OmxPromiseLayer::BUFFERLIST BUFFERLIST;
*
* OmxPlatformLayer acts as the OpenMAX IL core.
*/
class OmxDataDecoder : public MediaDataDecoder
class OmxDataDecoder
: public MediaDataDecoder
, public DecoderDoctorLifeLogger<OmxDataDecoder>
{
protected:
virtual ~OmxDataDecoder();

View File

@ -79,12 +79,16 @@ protected:
Maybe<media::TimeUnit> mSeekTargetThreshold;
};
DDLoggedTypeDeclNameAndBase(WMFMediaDataDecoder, MediaDataDecoder);
// Decodes audio and video using Windows Media Foundation. Samples are decoded
// using the MFTDecoder created by the MFTManager. This class implements
// the higher-level logic that drives mapping the MFT to the async
// MediaDataDecoder interface. The specifics of decoding the exact stream
// type are handled by MFTManager and the MFTDecoder it creates.
class WMFMediaDataDecoder : public MediaDataDecoder
class WMFMediaDataDecoder
: public MediaDataDecoder
, public DecoderDoctorLifeLogger<WMFMediaDataDecoder>
{
public:
WMFMediaDataDecoder(MFTManager* aOutputSource, TaskQueue* aTaskQueue);

View File

@ -294,6 +294,8 @@ H264Converter::CreateDecoder(const VideoInfo& aConfig,
}
}
DDLINKCHILD("decoder", mDecoder.get());
mNeedKeyframe = true;
return NS_OK;

View File

@ -14,6 +14,8 @@ namespace mozilla {
class DecoderDoctorDiagnostics;
DDLoggedTypeDeclNameAndBase(H264Converter, MediaDataDecoder);
// H264Converter is a MediaDataDecoder wrapper used to ensure that
// only AVCC or AnnexB is fed to the underlying MediaDataDecoder.
// The H264Converter allows playback of content where the SPS NAL may not be
@ -21,7 +23,9 @@ class DecoderDoctorDiagnostics;
// H264Converter will monitor the input data, and will delay creation of the
// MediaDataDecoder until a SPS and PPS NALs have been extracted.
class H264Converter : public MediaDataDecoder
class H264Converter
: public MediaDataDecoder
, public DecoderDoctorLifeLogger<H264Converter>
{
public:

View File

@ -15,7 +15,11 @@
namespace mozilla {
class MediaDataDecoderProxy : public MediaDataDecoder
DDLoggedTypeDeclNameAndBase(MediaDataDecoderProxy, MediaDataDecoder);
class MediaDataDecoderProxy
: public MediaDataDecoder
, public DecoderDoctorLifeLogger<MediaDataDecoderProxy>
{
public:
explicit MediaDataDecoderProxy(already_AddRefed<AbstractThread> aProxyThread)
@ -33,12 +37,14 @@ public:
, mIsShutdown(false)
#endif
{
DDLINKCHILD("proxy decoder", mProxyDecoder.get());
}
void SetProxyTarget(MediaDataDecoder* aProxyDecoder)
{
MOZ_ASSERT(aProxyDecoder);
mProxyDecoder = aProxyDecoder;
DDLINKCHILD("proxy decoder", aProxyDecoder);
}
RefPtr<InitPromise> Init() override;

View File

@ -26,6 +26,7 @@ namespace mozilla {
WAVDemuxer::WAVDemuxer(MediaResource* aSource)
: mSource(aSource)
{
DDLINKCHILD("source", aSource);
}
bool
@ -33,6 +34,7 @@ WAVDemuxer::InitInternal()
{
if (!mTrackDemuxer) {
mTrackDemuxer = new WAVTrackDemuxer(mSource.GetResource());
DDLINKCHILD("track demuxer", mTrackDemuxer.get());
}
return mTrackDemuxer->Init();
}
@ -81,6 +83,7 @@ WAVTrackDemuxer::WAVTrackDemuxer(MediaResource* aSource)
, mSamplesPerSecond(0)
, mChannels(0)
{
DDLINKCHILD("source", aSource);
Reset();
}

View File

@ -26,7 +26,12 @@ static const uint16_t DATA_CHUNK_SIZE = 768;
class WAVTrackDemuxer;
class WAVDemuxer : public MediaDataDemuxer
DDLoggedTypeDeclNameAndBase(WAVDemuxer, MediaDataDemuxer);
DDLoggedTypeNameAndBase(WAVTrackDemuxer, MediaTrackDemuxer);
class WAVDemuxer
: public MediaDataDemuxer
, public DecoderDoctorLifeLogger<WAVDemuxer>
{
public:
// MediaDataDemuxer interface.
@ -176,7 +181,9 @@ private:
DataChunk mChunk;
};
class WAVTrackDemuxer : public MediaTrackDemuxer
class WAVTrackDemuxer
: public MediaTrackDemuxer
, public DecoderDoctorLifeLogger<WAVTrackDemuxer>
{
public:
explicit WAVTrackDemuxer(MediaResource* aSource);

View File

@ -178,6 +178,10 @@ WebMDemuxer::WebMDemuxer(MediaResource* aResource, bool aIsMediaSource)
, mLastWebMBlockOffset(-1)
, mIsMediaSource(aIsMediaSource)
{
DDLINKCHILD("resource", aResource);
// Audio/video contexts hold a MediaResourceIndex.
DDLINKCHILD("video context", mVideoContext.GetResource());
DDLINKCHILD("audio context", mAudioContext.GetResource());
}
WebMDemuxer::~WebMDemuxer()
@ -247,6 +251,7 @@ WebMDemuxer::GetTrackDemuxer(TrackInfo::TrackType aType, uint32_t aTrackNumber)
}
RefPtr<WebMTrackDemuxer> e =
new WebMTrackDemuxer(this, aType, aTrackNumber);
DDLINKCHILD("track demuxer", e.get());
mDemuxers.AppendElement(e);
return e.forget();

View File

@ -122,7 +122,12 @@ private:
class WebMTrackDemuxer;
class WebMDemuxer : public MediaDataDemuxer
DDLoggedTypeDeclNameAndBase(WebMDemuxer, MediaDataDemuxer);
DDLoggedTypeNameAndBase(WebMTrackDemuxer, MediaTrackDemuxer);
class WebMDemuxer
: public MediaDataDemuxer
, public DecoderDoctorLifeLogger<WebMDemuxer>
{
public:
explicit WebMDemuxer(MediaResource* aResource);
@ -290,7 +295,9 @@ private:
EncryptionInfo mCrypto;
};
class WebMTrackDemuxer : public MediaTrackDemuxer
class WebMTrackDemuxer
: public MediaTrackDemuxer
, public DecoderDoctorLifeLogger<WebMTrackDemuxer>
{
public:
WebMTrackDemuxer(WebMDemuxer* aParent,