mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 12:51:06 +00:00
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:
parent
13e84a1120
commit
1b357db99b
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -17,7 +17,11 @@ class nsIPrincipal;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class BaseMediaResource : public MediaResource
|
||||
DDLoggedTypeDeclNameAndBase(BaseMediaResource, MediaResource);
|
||||
|
||||
class BaseMediaResource
|
||||
: public MediaResource
|
||||
, public DecoderDoctorLifeLogger<BaseMediaResource>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
|
@ -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)
|
||||
|
@ -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))) {
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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:
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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 */,
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -57,6 +57,7 @@ MediaResourceIndex::MediaResourceIndex(MediaResource* aResource)
|
||||
, mCachedBytes(0)
|
||||
, mCachedBlock(MakeUnique<char[]>(mCacheBlockSize))
|
||||
{
|
||||
DDLINKCHILD("resource", aResource);
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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. */
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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:
|
||||
|
@ -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. */
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -13,6 +13,7 @@ ResourceStream::ResourceStream(mozilla::MediaResource* aResource)
|
||||
, mPinCount(0)
|
||||
{
|
||||
MOZ_ASSERT(aResource);
|
||||
DDLINKCHILD("resource", &mResource);
|
||||
}
|
||||
|
||||
ResourceStream::~ResourceStream()
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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,
|
||||
|
@ -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() { }
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -42,7 +42,11 @@ private:
|
||||
RefPtr<PDMFactory> mPDM;
|
||||
};
|
||||
|
||||
class EMEMediaDataDecoderProxy : public MediaDataDecoderProxy
|
||||
DDLoggedTypeDeclNameAndBase(EMEMediaDataDecoderProxy, MediaDataDecoderProxy);
|
||||
|
||||
class EMEMediaDataDecoderProxy
|
||||
: public MediaDataDecoderProxy
|
||||
, public DecoderDoctorLifeLogger<EMEMediaDataDecoderProxy>
|
||||
{
|
||||
public:
|
||||
EMEMediaDataDecoderProxy(
|
||||
|
@ -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);
|
||||
|
@ -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>
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -294,6 +294,8 @@ H264Converter::CreateDecoder(const VideoInfo& aConfig,
|
||||
}
|
||||
}
|
||||
|
||||
DDLINKCHILD("decoder", mDecoder.get());
|
||||
|
||||
mNeedKeyframe = true;
|
||||
|
||||
return NS_OK;
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user