From 58cb3ab298e866344d92344b379aa31fabc885d5 Mon Sep 17 00:00:00 2001 From: Jean-Yves Avenard Date: Wed, 10 Aug 2016 15:30:12 +1000 Subject: [PATCH] Bug 1293646: [MSE] P2. Only reject a seek request with EOS if it's passed the explicit duration. r=gerald With MSE, the actual duration is always exact as it is amended when data is added. We do not want to fire ended when we attempt to seek to unbuffered data once endOfStream has been called. Instead we will fire the waiting event. MozReview-Commit-ID: Cl2uBLk2qRQ --HG-- extra : rebase_source : 6763c6f5a6e15264e276e486fab4d39491ea7f1b --- dom/media/AbstractMediaDecoder.h | 1 + dom/media/MediaDecoder.h | 6 +++--- dom/media/MediaFormatReader.cpp | 29 +++++++++++++++++++++++++++++ dom/media/MediaFormatReader.h | 6 +++++- 4 files changed, 38 insertions(+), 4 deletions(-) diff --git a/dom/media/AbstractMediaDecoder.h b/dom/media/AbstractMediaDecoder.h index b78f00bd4eec..8aa63867adea 100644 --- a/dom/media/AbstractMediaDecoder.h +++ b/dom/media/AbstractMediaDecoder.h @@ -61,6 +61,7 @@ public: virtual void NotifyDecodedFrames(const FrameStatisticsData& aStats) = 0; virtual AbstractCanonical* CanonicalDurationOrNull() { return nullptr; }; + virtual AbstractCanonical>* CanonicalExplicitDuration() { return nullptr; } // Return an event that will be notified when data arrives in MediaResource. // MediaDecoderReader will register with this event to receive notifications diff --git a/dom/media/MediaDecoder.h b/dom/media/MediaDecoder.h index 0811ab4066cc..3c0372570082 100644 --- a/dom/media/MediaDecoder.h +++ b/dom/media/MediaDecoder.h @@ -822,6 +822,9 @@ protected: public: AbstractCanonical* CanonicalDurationOrNull() override; + AbstractCanonical>* CanonicalExplicitDuration() override { + return &mExplicitDuration; + } AbstractCanonical* CanonicalVolume() { return &mVolume; } @@ -834,9 +837,6 @@ public: AbstractCanonical* CanonicalEstimatedDuration() { return &mEstimatedDuration; } - AbstractCanonical>* CanonicalExplicitDuration() { - return &mExplicitDuration; - } AbstractCanonical* CanonicalPlayState() { return &mPlayState; } diff --git a/dom/media/MediaFormatReader.cpp b/dom/media/MediaFormatReader.cpp index 4de058786897..a5dda6b35dbd 100644 --- a/dom/media/MediaFormatReader.cpp +++ b/dom/media/MediaFormatReader.cpp @@ -77,6 +77,7 @@ MediaFormatReader::MediaFormatReader(AbstractMediaDecoder* aDecoder, , mDemuxOnly(false) , mSeekScheduled(false) , mVideoFrameContainer(aVideoFrameContainer) + , mExplicitDuration(mTaskQueue, Maybe(), "MediaFormatReader::mExplicitDuration(Mirror)") { MOZ_ASSERT(aDemuxer); MOZ_COUNT_CTOR(MediaFormatReader); @@ -141,6 +142,8 @@ MediaFormatReader::Shutdown() mPlatform = nullptr; mVideoFrameContainer = nullptr; + mExplicitDuration.DisconnectIfConnected(); + return MediaDecoderReader::Shutdown(); } @@ -253,6 +256,10 @@ MediaFormatReader::AsyncReadMetadata() return MetadataPromise::CreateAndResolve(metadata, __func__); } + if (mDecoder->CanonicalExplicitDuration()) { + mExplicitDuration.Connect(mDecoder->CanonicalExplicitDuration()); + } + RefPtr p = mMetadataPromise.Ensure(__func__); mDemuxerInitRequest.Begin(mDemuxer->Init() @@ -1077,6 +1084,20 @@ MediaFormatReader::InternalSeek(TrackType aTrack, const InternalSeekTarget& aTar [self, aTrack] (DemuxerFailureReason aResult) { auto& decoder = self->GetDecoderData(aTrack); decoder.mSeekRequest.Complete(); + + if (aResult == DemuxerFailureReason::END_OF_STREAM) { + // We want to enter EOS when performing an + // internal seek only if we're attempting to seek past + // the explicit duration to avoid unwanted ended + // event to be fired. + if (self->mExplicitDuration.Ref().isSome() && + decoder.mTimeThreshold.ref().Time() < + TimeUnit::FromSeconds( + self->mExplicitDuration.Ref().ref())) { + aResult = DemuxerFailureReason::WAITING_FOR_DATA; + } + } + switch (aResult) { case DemuxerFailureReason::WAITING_FOR_DATA: self->NotifyWaitingForData(aTrack); @@ -1726,6 +1747,14 @@ MediaFormatReader::OnSeekFailed(TrackType aTrack, DemuxerFailureReason aResult) mAudio.mSeekRequest.Complete(); } + // We want to enter EOS when performing a seek only if we're attempting to + // seek past the explicit duration to avoid unwanted ended + // event to be fired. + if (mExplicitDuration.Ref().isSome() && + mPendingSeekTime.ref() < TimeUnit::FromSeconds(mExplicitDuration.Ref().ref())) { + aResult = DemuxerFailureReason::WAITING_FOR_DATA; + } + if (aResult == DemuxerFailureReason::WAITING_FOR_DATA) { if (HasVideo() && aTrack == TrackType::kAudioTrack && mFallbackSeekTime.isSome() && diff --git a/dom/media/MediaFormatReader.h b/dom/media/MediaFormatReader.h index ed720177c55e..938b27dbe37b 100644 --- a/dom/media/MediaFormatReader.h +++ b/dom/media/MediaFormatReader.h @@ -9,8 +9,9 @@ #include "mozilla/Atomics.h" #include "mozilla/Maybe.h" -#include "mozilla/TaskQueue.h" #include "mozilla/Monitor.h" +#include "mozilla/StateMirroring.h" +#include "mozilla/TaskQueue.h" #include "MediaDataDemuxer.h" #include "MediaDecoderReader.h" @@ -579,6 +580,9 @@ private: RefPtr mCrashHelper; void SetBlankDecode(TrackType aTrack, bool aIsBlankDecode); + + // The duration explicitly set by JS, mirrored from the main thread. + Mirror> mExplicitDuration; }; } // namespace mozilla