From e98562dc6db69a4e7c4fb8ebf86ce2ed591f4dbf Mon Sep 17 00:00:00 2001 From: trav90 Date: Wed, 25 Oct 2017 04:34:49 -0500 Subject: [PATCH] Rework MediaDecoder::AddOutputStream and move related code to the MDSM --- dom/media/DecodedStream.cpp | 4 +- dom/media/DecodedStream.h | 4 +- dom/media/MediaDecoder.cpp | 26 +------------ dom/media/MediaDecoder.h | 21 ----------- dom/media/MediaDecoderStateMachine.cpp | 50 ++++++++++++++++++++----- dom/media/MediaDecoderStateMachine.h | 25 ++++++++++++- dom/media/omx/MediaOmxCommonDecoder.cpp | 3 +- 7 files changed, 70 insertions(+), 63 deletions(-) diff --git a/dom/media/DecodedStream.cpp b/dom/media/DecodedStream.cpp index b2e15a6b3c..2c6304f023 100644 --- a/dom/media/DecodedStream.cpp +++ b/dom/media/DecodedStream.cpp @@ -180,7 +180,7 @@ DecodedStream::DecodedStream(ReentrantMonitor& aMonitor) } DecodedStreamData* -DecodedStream::GetData() +DecodedStream::GetData() const { GetReentrantMonitor().AssertCurrentThreadIn(); return mData.get(); @@ -252,7 +252,7 @@ DecodedStream::OutputStreams() } ReentrantMonitor& -DecodedStream::GetReentrantMonitor() +DecodedStream::GetReentrantMonitor() const { return mMonitor; } diff --git a/dom/media/DecodedStream.h b/dom/media/DecodedStream.h index ed20174e80..78166d18d7 100644 --- a/dom/media/DecodedStream.h +++ b/dom/media/DecodedStream.h @@ -90,11 +90,11 @@ public: class DecodedStream { public: explicit DecodedStream(ReentrantMonitor& aMonitor); - DecodedStreamData* GetData(); + DecodedStreamData* GetData() const; void DestroyData(); void RecreateData(int64_t aInitialTime, MediaStreamGraph* aGraph); nsTArray& OutputStreams(); - ReentrantMonitor& GetReentrantMonitor(); + ReentrantMonitor& GetReentrantMonitor() const; void Connect(ProcessedMediaStream* aStream, bool aFinishWhenEnded); private: diff --git a/dom/media/MediaDecoder.cpp b/dom/media/MediaDecoder.cpp index bab636b7a5..db24f161f9 100644 --- a/dom/media/MediaDecoder.cpp +++ b/dom/media/MediaDecoder.cpp @@ -300,29 +300,12 @@ void MediaDecoder::SetVolume(double aVolume) mVolume = aVolume; } -void MediaDecoder::RecreateDecodedStream(int64_t aStartTimeUSecs) -{ - MOZ_ASSERT(NS_IsMainThread()); - ReentrantMonitorAutoEnter mon(GetReentrantMonitor()); - DECODER_LOG("RecreateDecodedStream aStartTimeUSecs=%lld!", aStartTimeUSecs); - - mDecodedStream.RecreateData(aStartTimeUSecs, MediaStreamGraph::GetInstance()); -} - void MediaDecoder::AddOutputStream(ProcessedMediaStream* aStream, bool aFinishWhenEnded) { MOZ_ASSERT(NS_IsMainThread()); - DECODER_LOG("AddOutputStream aStream=%p!", aStream); MOZ_ASSERT(mDecoderStateMachine, "Must be called after Load()."); - - ReentrantMonitorAutoEnter mon(GetReentrantMonitor()); - if (!GetDecodedStream()) { - RecreateDecodedStream(mLogicalPosition); - } - - mDecodedStream.Connect(aStream, aFinishWhenEnded); - mDecoderStateMachine->DispatchAudioCaptured(); + mDecoderStateMachine->AddOutputStream(aStream, aFinishWhenEnded); } double MediaDecoder::GetDuration() @@ -371,7 +354,6 @@ MediaDecoder::MediaDecoder() : mMediaSeekable(true), mSameOriginMedia(false), mReentrantMonitor("media.decoder"), - mDecodedStream(mReentrantMonitor), mEstimatedDuration(AbstractThread::MainThread(), NullableTimeUnit(), "MediaDecoder::mEstimatedDuration (Canonical)"), mExplicitDuration(AbstractThread::MainThread(), Maybe(), @@ -463,12 +445,6 @@ void MediaDecoder::Shutdown() MediaDecoder::~MediaDecoder() { MOZ_ASSERT(NS_IsMainThread()); - { - // Don't destroy the decoded stream until destructor in order to keep the - // invariant that the decoded stream is always available in capture mode. - ReentrantMonitorAutoEnter mon(GetReentrantMonitor()); - mDecodedStream.DestroyData(); - } MediaMemoryTracker::RemoveMediaDecoder(this); UnpinForSeek(); MOZ_COUNT_DTOR(MediaDecoder); diff --git a/dom/media/MediaDecoder.h b/dom/media/MediaDecoder.h index e4685552cc..7ec1d2cada 100644 --- a/dom/media/MediaDecoder.h +++ b/dom/media/MediaDecoder.h @@ -391,20 +391,6 @@ public: // replaying after the input as ended. In the latter case, the new source is // not connected to streams created by captureStreamUntilEnded. - /** - * Recreates mDecodedStream. Call this to create mDecodedStream at first, - * and when seeking, to ensure a new stream is set up with fresh buffers. - * aStartTimeUSecs is relative to the state machine's mStartTime. - * Decoder monitor must be held. - */ - void RecreateDecodedStream(int64_t aStartTimeUSecs); - - DecodedStreamData* GetDecodedStream() - { - GetReentrantMonitor().AssertCurrentThreadIn(); - return mDecodedStream.GetData(); - } - // Add an output stream. All decoder output will be sent to the stream. // The stream is initially blocked. The decoder is responsible for unblocking // it while it is playing back. @@ -977,13 +963,6 @@ private: ReentrantMonitor mReentrantMonitor; protected: - // The SourceMediaStream we are using to feed the mOutputStreams. This stream - // is never exposed outside the decoder. - // Only written on the main thread while holding the monitor. Therefore it - // can be read on any thread while holding the monitor, or on the main thread - // without holding the monitor. - DecodedStream mDecodedStream; - // Media duration according to the demuxer's current estimate. // // Note that it's quite bizarre for this to live on the main thread - it would diff --git a/dom/media/MediaDecoderStateMachine.cpp b/dom/media/MediaDecoderStateMachine.cpp index faaee9b573..8090b6272a 100644 --- a/dom/media/MediaDecoderStateMachine.cpp +++ b/dom/media/MediaDecoderStateMachine.cpp @@ -252,7 +252,8 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder, mDecodingFrozenAtStateDecoding(false), mSentLoadedMetadataEvent(false), mSentFirstFrameLoadedEvent(false), - mSentPlaybackEndedEvent(false) + mSentPlaybackEndedEvent(false), + mDecodedStream(mDecoder->GetReentrantMonitor()) { MOZ_COUNT_CTOR(MediaDecoderStateMachine); NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); @@ -447,7 +448,7 @@ void MediaDecoderStateMachine::SendStreamData() AssertCurrentThreadInMonitor(); MOZ_ASSERT(!mAudioSink, "Should've been stopped in RunStateMachine()"); - DecodedStreamData* stream = mDecoder->GetDecodedStream(); + DecodedStreamData* stream = GetDecodedStream(); bool finished = (!mInfo.HasAudio() || AudioQueue().IsFinished()) && @@ -626,7 +627,7 @@ bool MediaDecoderStateMachine::HaveEnoughDecodedAudio(int64_t aAmpleAudioUSecs) return true; } - DecodedStreamData* stream = mDecoder->GetDecodedStream(); + DecodedStreamData* stream = GetDecodedStream(); if (stream && stream->mStreamInitialized && !stream->mHaveSentFinishAudio) { MOZ_ASSERT(mInfo.HasAudio()); @@ -650,7 +651,7 @@ bool MediaDecoderStateMachine::HaveEnoughDecodedVideo() return false; } - DecodedStreamData* stream = mDecoder->GetDecodedStream(); + DecodedStreamData* stream = GetDecodedStream(); if (stream && stream->mStreamInitialized && !stream->mHaveSentFinishVideo) { MOZ_ASSERT(mInfo.HasVideo()); @@ -1880,8 +1881,9 @@ MediaDecoderStateMachine::InitiateSeek() // as far as fast-seek is concerned. It also fix the problem where stream // clock seems to go backwards during seeking. nsCOMPtr event = - NS_NewRunnableMethodWithArg(mDecoder, &MediaDecoder::RecreateDecodedStream, - seekTime - mStartTime); + NS_NewRunnableMethodWithArg(this, + &MediaDecoderStateMachine::RecreateDecodedStream, + seekTime - mStartTime); AbstractThread::MainThread()->Dispatch(event.forget()); } @@ -2728,7 +2730,7 @@ nsresult MediaDecoderStateMachine::RunStateMachine() // end of the media, and so that we update the readyState. if (VideoQueue().GetSize() > 0 || (HasAudio() && !mAudioCompleted) || - (mAudioCaptured && !mDecoder->GetDecodedStream()->IsFinished())) + (mAudioCaptured && !GetDecodedStream()->IsFinished())) { AdvanceFrame(); NS_ASSERTION(mPlayState != MediaDecoder::PLAY_STATE_PLAYING || @@ -2909,7 +2911,7 @@ int64_t MediaDecoderStateMachine::GetClock() const clock_time = mPlayDuration + mStartTime; } else { if (mAudioCaptured) { - clock_time = mStartTime + mDecoder->GetDecodedStream()->GetClock(); + clock_time = mStartTime + GetDecodedStream()->GetClock(); } else if (HasAudio() && !mAudioCompleted) { clock_time = GetAudioClock(); } else { @@ -3511,6 +3513,12 @@ void MediaDecoderStateMachine::OnAudioSinkError() DecodeError(); } +DecodedStreamData* MediaDecoderStateMachine::GetDecodedStream() const +{ + AssertCurrentThreadInMonitor(); + return mDecodedStream.GetData(); +} + void MediaDecoderStateMachine::DispatchAudioCaptured() { nsRefPtr self = this; @@ -3526,11 +3534,25 @@ void MediaDecoderStateMachine::DispatchAudioCaptured() TaskQueue()->Dispatch(r.forget()); } +void MediaDecoderStateMachine::AddOutputStream(ProcessedMediaStream* aStream, + bool aFinishWhenEnded) +{ + MOZ_ASSERT(NS_IsMainThread()); + DECODER_LOG("AddOutputStream aStream=%p!", aStream); + + ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); + if (!GetDecodedStream()) { + RecreateDecodedStream(mCurrentPosition.ReadOnWrongThread()); + } + mDecodedStream.Connect(aStream, aFinishWhenEnded); + DispatchAudioCaptured(); +} + void MediaDecoderStateMachine::UpdateStreamBlockingForPlayState() { ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); - auto stream = mDecoder->GetDecodedStream(); + auto stream = GetDecodedStream(); if (!stream) { return; } @@ -3547,7 +3569,7 @@ void MediaDecoderStateMachine::UpdateStreamBlockingForStateMachinePlaying() { AssertCurrentThreadInMonitor(); - auto stream = mDecoder->GetDecodedStream(); + auto stream = GetDecodedStream(); if (!stream) { return; } @@ -3559,6 +3581,14 @@ void MediaDecoderStateMachine::UpdateStreamBlockingForStateMachinePlaying() } } +void MediaDecoderStateMachine::RecreateDecodedStream(int64_t aInitialTime) +{ + MOZ_ASSERT(NS_IsMainThread()); + ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); + DECODER_LOG("RecreateDecodedStream aInitialTime=%lld!", aInitialTime); + mDecodedStream.RecreateData(aInitialTime, MediaStreamGraph::GetInstance()); +} + } // namespace mozilla // avoid redefined macro in unified build diff --git a/dom/media/MediaDecoderStateMachine.h b/dom/media/MediaDecoderStateMachine.h index 0bd04446ea..8f1b8f8054 100644 --- a/dom/media/MediaDecoderStateMachine.h +++ b/dom/media/MediaDecoderStateMachine.h @@ -92,6 +92,7 @@ hardware (via AudioStream). #include "mozilla/RollingMean.h" #include "MediaTimer.h" #include "StateMirroring.h" +#include "DecodedStream.h" class nsITimer; @@ -102,7 +103,6 @@ class VideoSegment; class MediaTaskQueue; class SharedThreadPool; class AudioSink; -class DecodedStreamData; class MediaDecoderStateMachineScheduler; /* @@ -150,7 +150,9 @@ public: return mState; } - void DispatchAudioCaptured(); + DecodedStreamData* GetDecodedStream() const; + + void AddOutputStream(ProcessedMediaStream* aStream, bool aFinishWhenEnded); // Check if the decoder needs to become dormant state. bool IsDormantNeeded(); @@ -163,6 +165,8 @@ private: // constructor immediately after the task queue is created. void InitializationTask(); + void DispatchAudioCaptured(); + // Update blocking state of mDecodedStream when mPlayState or // mLogicallySeeking change. Decoder monitor must be held. void UpdateStreamBlockingForPlayState(); @@ -170,6 +174,12 @@ private: // Call this IsPlaying() changes. Decoder monitor must be held. void UpdateStreamBlockingForStateMachinePlaying(); + // Recreates mDecodedStream. Call this to create mDecodedStream at first, + // and when seeking, to ensure a new stream is set up with fresh buffers. + // aInitialTime is relative to mStartTime. + // Decoder monitor must be held. + void RecreateDecodedStream(int64_t aInitialTime); + void Shutdown(); public: @@ -326,6 +336,10 @@ public: if (mReader) { mReader->BreakCycles(); } + { + ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); + mDecodedStream.DestroyData(); + } mDecoder = nullptr; } @@ -1257,6 +1271,13 @@ protected: bool mSentFirstFrameLoadedEvent; bool mSentPlaybackEndedEvent; + + // The SourceMediaStream we are using to feed the mOutputStreams. This stream + // is never exposed outside the decoder. + // Only written on the main thread while holding the monitor. Therefore it + // can be read on any thread while holding the monitor, or on the main thread + // without holding the monitor. + DecodedStream mDecodedStream; }; } // namespace mozilla; diff --git a/dom/media/omx/MediaOmxCommonDecoder.cpp b/dom/media/omx/MediaOmxCommonDecoder.cpp index 0164861d2b..5445fbd4b0 100644 --- a/dom/media/omx/MediaOmxCommonDecoder.cpp +++ b/dom/media/omx/MediaOmxCommonDecoder.cpp @@ -53,7 +53,8 @@ bool MediaOmxCommonDecoder::CheckDecoderCanOffloadAudio() { return (mCanOffloadAudio && !mFallbackToStateMachine && - !GetDecodedStream() && mPlaybackRate == 1.0); + !(GetStateMachine() && GetStateMachine()->GetDecodedStream()) && + mPlaybackRate == 1.0); } void