Bug 1378631. P1 - move the duration mirror from MediaDecoderReader to MediaDecoderReaderWrapper.
So we can remove AbstractMediaDecoder::CanonicalDurationOrNull() later.
MozReview-Commit-ID: 6zJCFDsCZPC
--- a/dom/media/MediaDecoderReader.cpp
+++ b/dom/media/MediaDecoderReader.cpp
@@ -70,53 +70,32 @@ public:
MediaDecoderReader::MediaDecoderReader(const MediaDecoderReaderInit& aInit)
: mAudioCompactor(mAudioQueue)
, mDecoder(aInit.mDecoder)
, mTaskQueue(new TaskQueue(
GetMediaThreadPool(MediaThreadType::PLAYBACK),
"MediaDecoderReader::mTaskQueue",
/* aSupportsTailDispatch = */ true))
- , mWatchManager(this, mTaskQueue)
, mBuffered(mTaskQueue, TimeIntervals(), "MediaDecoderReader::mBuffered (Canonical)")
- , mDuration(mTaskQueue, NullableTimeUnit(), "MediaDecoderReader::mDuration (Mirror)")
, mIgnoreAudioOutputFormat(false)
, mHitAudioDecodeError(false)
, mShutdown(false)
, mResource(aInit.mResource)
{
MOZ_COUNT_CTOR(MediaDecoderReader);
MOZ_ASSERT(NS_IsMainThread());
}
nsresult
MediaDecoderReader::Init()
{
- // Dispatch initialization that needs to happen on that task queue.
- mTaskQueue->Dispatch(
- NewRunnableMethod("MediaDecoderReader::InitializationTask",
- this,
- &MediaDecoderReader::InitializationTask));
return InitInternal();
}
-void
-MediaDecoderReader::InitializationTask()
-{
- if (!mDecoder) {
- return;
- }
- if (mDecoder->CanonicalDurationOrNull()) {
- mDuration.Connect(mDecoder->CanonicalDurationOrNull());
- }
-
- // Initialize watchers.
- mWatchManager.Watch(mDuration, &MediaDecoderReader::UpdateBuffered);
-}
-
MediaDecoderReader::~MediaDecoderReader()
{
MOZ_ASSERT(mShutdown);
MOZ_COUNT_DTOR(MediaDecoderReader);
}
size_t MediaDecoderReader::SizeOfVideoQueueInBytes() const
{
@@ -137,16 +116,24 @@ size_t MediaDecoderReader::SizeOfVideoQu
return mVideoQueue.GetSize();
}
size_t MediaDecoderReader::SizeOfAudioQueueInFrames()
{
return mAudioQueue.GetSize();
}
+void
+MediaDecoderReader::UpdateDuration(const media::TimeUnit& aDuration)
+{
+ MOZ_ASSERT(OnTaskQueue());
+ mDuration = Some(aDuration);
+ UpdateBuffered();
+}
+
nsresult MediaDecoderReader::ResetDecode(TrackSet aTracks)
{
if (aTracks.contains(TrackInfo::kVideoTrack)) {
VideoQueue().Reset();
mBaseVideoPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
}
if (aTracks.contains(TrackInfo::kAudioTrack)) {
@@ -198,23 +185,22 @@ void
MediaDecoderReader::VisibilityChanged()
{}
media::TimeIntervals
MediaDecoderReader::GetBuffered()
{
MOZ_ASSERT(OnTaskQueue());
- AutoPinned<MediaResource> stream(mResource);
-
- if (!mDuration.Ref().isSome()) {
+ if (mDuration.isNothing()) {
return TimeIntervals();
}
- return GetEstimatedBufferedTimeRanges(stream, mDuration.Ref().ref().ToMicroseconds());
+ AutoPinned<MediaResource> stream(mResource);
+ return GetEstimatedBufferedTimeRanges(stream, mDuration->ToMicroseconds());
}
RefPtr<MediaDecoderReader::MetadataPromise>
MediaDecoderReader::AsyncReadMetadata()
{
MOZ_ASSERT(OnTaskQueue());
DECODER_LOG("MediaDecoderReader::AsyncReadMetadata");
@@ -366,20 +352,16 @@ MediaDecoderReader::Shutdown()
{
MOZ_ASSERT(OnTaskQueue());
mShutdown = true;
mBaseAudioPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_END_OF_STREAM, __func__);
mBaseVideoPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_END_OF_STREAM, __func__);
ReleaseResources();
- mDuration.DisconnectIfConnected();
mBuffered.DisconnectAll();
- // Shut down the watch manager before shutting down our task queue.
- mWatchManager.Shutdown();
-
mDecoder = nullptr;
return mTaskQueue->BeginShutdown();
}
} // namespace mozilla
--- a/dom/media/MediaDecoderReader.h
+++ b/dom/media/MediaDecoderReader.h
@@ -127,16 +127,18 @@ public:
// thread.
virtual RefPtr<ShutdownPromise> Shutdown();
virtual bool OnTaskQueue() const
{
return OwnerThread()->IsCurrentThreadIn();
}
+ void UpdateDuration(const media::TimeUnit& aDuration);
+
// Resets all state related to decoding, emptying all buffers etc.
// Cancels all pending Request*Data() request callbacks, rejects any
// outstanding seek promises, and flushes the decode pipeline. The
// decoder must not call any of the callbacks for outstanding
// Request*Data() calls after this is called. Calls to Request*Data()
// made after this should be processed as usual.
//
// Normally this call preceedes a Seek() call, or shutdown.
@@ -296,27 +298,23 @@ protected:
AudioCompactor mAudioCompactor;
// Reference to the owning decoder object.
AbstractMediaDecoder* mDecoder;
// Decode task queue.
RefPtr<TaskQueue> mTaskQueue;
- // State-watching manager.
- WatchManager<MediaDecoderReader> mWatchManager;
-
// Buffered range.
Canonical<media::TimeIntervals> mBuffered;
// Stores presentation info required for playback.
MediaInfo mInfo;
- // Duration, mirrored from the state machine task queue.
- Mirror<media::NullableTimeUnit> mDuration;
+ media::NullableTimeUnit mDuration;
// Whether we should accept media that we know we can't play
// directly, because they have a number of channel higher than
// what we support.
bool mIgnoreAudioOutputFormat;
// This is a quick-and-dirty way for DecodeAudioData implementations to
// communicate the presence of a decoding error to RequestAudioData. We should
@@ -334,22 +332,16 @@ protected:
// Notify if we are waiting for a decryption key.
MediaEventProducer<TrackInfo::TrackType> mOnTrackWaitingForKey;
RefPtr<MediaResource> mResource;
private:
virtual nsresult InitInternal() { return NS_OK; }
- // Does any spinup that needs to happen on this task queue. This runs on a
- // different thread than Init, and there should not be ordering dependencies
- // between the two (even though in practice, Init will always run first right
- // now thanks to the tail dispatcher).
- void InitializationTask();
-
// Read header data for all bitstreams in the file. Fills aInfo with
// the data required to present the media, and optionally fills *aTags
// with tag metadata from the file.
// Returns NS_OK on success, or NS_ERROR_FAILURE on failure.
virtual nsresult ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags)
{
MOZ_CRASH();
}
--- a/dom/media/MediaDecoderReaderWrapper.cpp
+++ b/dom/media/MediaDecoderReaderWrapper.cpp
@@ -8,16 +8,20 @@
#include "MediaDecoderReaderWrapper.h"
namespace mozilla {
MediaDecoderReaderWrapper::MediaDecoderReaderWrapper(AbstractThread* aOwnerThread,
MediaDecoderReader* aReader)
: mOwnerThread(aOwnerThread)
, mReader(aReader)
+ , mWatchManager(this, aReader->OwnerThread())
+ , mDuration(aReader->OwnerThread(),
+ NullableTimeUnit(),
+ "MediaDecoderReaderWrapper::mDuration (Mirror)")
{
// Must support either heuristic buffering or WaitForData().
MOZ_ASSERT(mReader->UseBufferingHeuristics() ||
mReader->IsWaitForDataSupported());
}
MediaDecoderReaderWrapper::~MediaDecoderReaderWrapper()
{}
@@ -129,18 +133,22 @@ MediaDecoderReaderWrapper::ResetDecode(T
mReader->OwnerThread()->Dispatch(r.forget());
}
RefPtr<ShutdownPromise>
MediaDecoderReaderWrapper::Shutdown()
{
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
mShutdown = true;
- return InvokeAsync(mReader->OwnerThread(), mReader.get(), __func__,
- &MediaDecoderReader::Shutdown);
+ RefPtr<MediaDecoderReaderWrapper> self = this;
+ return InvokeAsync(mReader->OwnerThread(), __func__, [self]() {
+ self->mDuration.DisconnectIfConnected();
+ self->mWatchManager.Shutdown();
+ return self->mReader->Shutdown();
+ });
}
RefPtr<MediaDecoderReaderWrapper::MetadataPromise>
MediaDecoderReaderWrapper::OnMetadataRead(MetadataHolder&& aMetadata)
{
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
if (mShutdown) {
return MetadataPromise::CreateAndReject(
@@ -166,9 +174,33 @@ MediaDecoderReaderWrapper::SetVideoBlank
nsCOMPtr<nsIRunnable> r =
NewRunnableMethod<bool>("MediaDecoderReader::SetVideoNullDecode",
mReader,
&MediaDecoderReader::SetVideoNullDecode,
aIsBlankDecode);
mReader->OwnerThread()->Dispatch(r.forget());
}
+void
+MediaDecoderReaderWrapper::UpdateDuration()
+{
+ MOZ_ASSERT(mReader->OwnerThread()->IsCurrentThreadIn());
+ mReader->UpdateDuration(mDuration.Ref().ref());
+}
+
+void
+MediaDecoderReaderWrapper::SetCanonicalDuration(
+ AbstractCanonical<media::NullableTimeUnit>* aCanonical)
+{
+ using DurationT = AbstractCanonical<media::NullableTimeUnit>;
+ RefPtr<MediaDecoderReaderWrapper> self = this;
+ RefPtr<DurationT> canonical = aCanonical;
+ nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
+ "MediaDecoderReaderWrapper::SetCanonicalDuration",
+ [this, self, canonical]() {
+ mDuration.Connect(canonical);
+ mWatchManager.Watch(mDuration,
+ &MediaDecoderReaderWrapper::UpdateDuration);
+ });
+ mReader->OwnerThread()->Dispatch(r.forget());
+}
+
} // namespace mozilla
--- a/dom/media/MediaDecoderReaderWrapper.h
+++ b/dom/media/MediaDecoderReaderWrapper.h
@@ -83,23 +83,33 @@ public:
AbstractCanonical<media::TimeIntervals>* CanonicalBuffered() {
return mReader->CanonicalBuffered();
}
void SetCDMProxy(CDMProxy* aProxy) { mReader->SetCDMProxy(aProxy); }
void SetVideoBlankDecode(bool aIsBlankDecode);
+ void SetCanonicalDuration(
+ AbstractCanonical<media::NullableTimeUnit>* aCanonical);
+
private:
~MediaDecoderReaderWrapper();
RefPtr<MetadataPromise> OnMetadataRead(MetadataHolder&& aMetadata);
RefPtr<MetadataPromise> OnMetadataNotRead(const MediaResult& aError);
+ void UpdateDuration();
const RefPtr<AbstractThread> mOwnerThread;
const RefPtr<MediaDecoderReader> mReader;
bool mShutdown = false;
Maybe<media::TimeUnit> mStartTime;
+
+ // State-watching manager.
+ WatchManager<MediaDecoderReaderWrapper> mWatchManager;
+
+ // Duration, mirrored from the state machine task queue.
+ Mirror<media::NullableTimeUnit> mDuration;
};
} // namespace mozilla
#endif // MediaDecoderReaderWrapper_h_
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -2956,16 +2956,18 @@ nsresult MediaDecoderStateMachine::Init(
OwnerThread(), __func__, this,
&MediaDecoderStateMachine::OnCDMProxyReady,
&MediaDecoderStateMachine::OnCDMProxyNotReady)
->Track(mCDMProxyPromise);
nsresult rv = mReader->Init();
NS_ENSURE_SUCCESS(rv, rv);
+ mReader->SetCanonicalDuration(&mDuration);
+
return NS_OK;
}
void
MediaDecoderStateMachine::StopPlayback()
{
MOZ_ASSERT(OnTaskQueue());
LOG("StopPlayback()");