diff options
author | trav90 <travawine@openmailbox.org> | 2017-10-20 18:20:01 -0500 |
---|---|---|
committer | trav90 <travawine@openmailbox.org> | 2017-10-20 18:52:30 -0500 |
commit | 124b2d57db4cb8c3d3941611ae6fa226477b0cdc (patch) | |
tree | e4a69ed4c02fed2686080d879baea97e0a07d42e | |
parent | c09757d59d8807fdf5e0b9a6faf8fc592340a772 (diff) | |
download | palemoon-gre-124b2d57db4cb8c3d3941611ae6fa226477b0cdc.tar.gz |
Move MediaDecoder::DecodedStreamData and related code to its own file
-rw-r--r-- | dom/media/DecodedStream.cpp | 186 | ||||
-rw-r--r-- | dom/media/DecodedStream.h | 96 | ||||
-rw-r--r-- | dom/media/MediaDecoder.cpp | 131 | ||||
-rw-r--r-- | dom/media/MediaDecoder.h | 110 | ||||
-rw-r--r-- | dom/media/MediaDecoderStateMachine.cpp | 1 | ||||
-rw-r--r-- | dom/media/MediaDecoderStateMachine.h | 6 | ||||
-rw-r--r-- | dom/media/moz.build | 2 |
7 files changed, 289 insertions, 243 deletions
diff --git a/dom/media/DecodedStream.cpp b/dom/media/DecodedStream.cpp new file mode 100644 index 000000000..f60c61c57 --- /dev/null +++ b/dom/media/DecodedStream.cpp @@ -0,0 +1,186 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "DecodedStream.h" +#include "MediaStreamGraph.h" +#include "MediaDecoder.h" + +namespace mozilla { + +class DecodedStreamGraphListener : public MediaStreamListener { + typedef MediaStreamListener::MediaStreamGraphEvent MediaStreamGraphEvent; +public: + DecodedStreamGraphListener(MediaStream* aStream, DecodedStreamData* aData) + : mData(aData) + , mMutex("DecodedStreamGraphListener::mMutex") + , mStream(aStream) + , mLastOutputTime(aStream->StreamTimeToMicroseconds(aStream->GetCurrentTime())) + , mStreamFinishedOnMainThread(false) {} + + void NotifyOutput(MediaStreamGraph* aGraph, GraphTime aCurrentTime) override + { + MutexAutoLock lock(mMutex); + if (mStream) { + mLastOutputTime = mStream->StreamTimeToMicroseconds(mStream->GraphTimeToStreamTime(aCurrentTime)); + } + } + + void NotifyEvent(MediaStreamGraph* aGraph, MediaStreamGraphEvent event) override + { + if (event == EVENT_FINISHED) { + nsCOMPtr<nsIRunnable> event = + NS_NewRunnableMethod(this, &DecodedStreamGraphListener::DoNotifyFinished); + aGraph->DispatchToMainThreadAfterStreamStateUpdate(event.forget()); + } + } + + void DoNotifyFinished() + { + MutexAutoLock lock(mMutex); + mStreamFinishedOnMainThread = true; + } + + int64_t GetLastOutputTime() + { + MutexAutoLock lock(mMutex); + return mLastOutputTime; + } + + void Forget() + { + MOZ_ASSERT(NS_IsMainThread()); + mData = nullptr; + MutexAutoLock lock(mMutex); + mStream = nullptr; + } + + bool IsFinishedOnMainThread() + { + MutexAutoLock lock(mMutex); + return mStreamFinishedOnMainThread; + } + +private: + // Main thread only + DecodedStreamData* mData; + + Mutex mMutex; + // Members below are protected by mMutex. + nsRefPtr<MediaStream> mStream; + int64_t mLastOutputTime; // microseconds + bool mStreamFinishedOnMainThread; +}; + +DecodedStreamData::DecodedStreamData(MediaDecoder* aDecoder, + int64_t aInitialTime, + SourceMediaStream* aStream) + : mAudioFramesWritten(0) + , mInitialTime(aInitialTime) + , mNextVideoTime(-1) + , mNextAudioTime(-1) + , mDecoder(aDecoder) + , mStreamInitialized(false) + , mHaveSentFinish(false) + , mHaveSentFinishAudio(false) + , mHaveSentFinishVideo(false) + , mStream(aStream) + , mHaveBlockedForPlayState(false) + , mHaveBlockedForStateMachineNotPlaying(false) +{ + mListener = new DecodedStreamGraphListener(mStream, this); + mStream->AddListener(mListener); +} + +DecodedStreamData::~DecodedStreamData() +{ + mListener->Forget(); + mStream->Destroy(); +} + +bool +DecodedStreamData::IsFinished() const +{ + return mListener->IsFinishedOnMainThread(); +} + +int64_t +DecodedStreamData::GetClock() const +{ + return mInitialTime + mListener->GetLastOutputTime(); +} + +class OutputStreamListener : public MediaStreamListener { + typedef MediaStreamListener::MediaStreamGraphEvent MediaStreamGraphEvent; +public: + OutputStreamListener(MediaDecoder* aDecoder, MediaStream* aStream) + : mDecoder(aDecoder), mStream(aStream) {} + + void NotifyEvent(MediaStreamGraph* aGraph, MediaStreamGraphEvent event) override + { + if (event == EVENT_FINISHED) { + nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethod( + this, &OutputStreamListener::DoNotifyFinished); + aGraph->DispatchToMainThreadAfterStreamStateUpdate(r.forget()); + } + } + + void Forget() + { + MOZ_ASSERT(NS_IsMainThread()); + mDecoder = nullptr; + } + +private: + void DoNotifyFinished() + { + MOZ_ASSERT(NS_IsMainThread()); + if (!mDecoder) { + return; + } + + // Remove the finished stream so it won't block the decoded stream. + ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); + auto& streams = mDecoder->OutputStreams(); + // Don't read |mDecoder| in the loop since removing the element will lead + // to ~OutputStreamData() which will call Forget() to reset |mDecoder|. + for (int32_t i = streams.Length() - 1; i >= 0; --i) { + auto& os = streams[i]; + MediaStream* p = os.mStream.get(); + if (p == mStream.get()) { + if (os.mPort) { + os.mPort->Destroy(); + os.mPort = nullptr; + } + streams.RemoveElementAt(i); + break; + } + } + } + + // Main thread only + MediaDecoder* mDecoder; + nsRefPtr<MediaStream> mStream; +}; + +OutputStreamData::OutputStreamData() +{ + // +} + +OutputStreamData::~OutputStreamData() +{ + mListener->Forget(); +} + +void +OutputStreamData::Init(MediaDecoder* aDecoder, ProcessedMediaStream* aStream) +{ + mStream = aStream; + mListener = new OutputStreamListener(aDecoder, aStream); + aStream->AddListener(mListener); +} + +} // namespace mozilla diff --git a/dom/media/DecodedStream.h b/dom/media/DecodedStream.h new file mode 100644 index 000000000..823419fea --- /dev/null +++ b/dom/media/DecodedStream.h @@ -0,0 +1,96 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef DecodedStream_h_ +#define DecodedStream_h_ + +#include "nsRefPtr.h" +#include "mozilla/gfx/Point.h" + +namespace mozilla { + +class MediaDecoder; +class MediaInputPort; +class SourceMediaStream; +class ProcessedMediaStream; +class DecodedStreamGraphListener; +class OutputStreamData; +class OutputStreamListener; + +namespace layers { +class Image; +} + +/* + * All MediaStream-related data is protected by the decoder's monitor. + * We have at most one DecodedStreamDaata per MediaDecoder. Its stream + * is used as the input for each ProcessedMediaStream created by calls to + * captureStream(UntilEnded). Seeking creates a new source stream, as does + * replaying after the input as ended. In the latter case, the new source is + * not connected to streams created by captureStreamUntilEnded. + */ +class DecodedStreamData { +public: + DecodedStreamData(MediaDecoder* aDecoder, int64_t aInitialTime, + SourceMediaStream* aStream); + ~DecodedStreamData(); + bool IsFinished() const; + int64_t GetClock() const; + + /* The following group of fields are protected by the decoder's monitor + * and can be read or written on any thread. + */ + // Count of audio frames written to the stream + int64_t mAudioFramesWritten; + // Saved value of aInitialTime. Timestamp of the first audio and/or + // video packet written. + const int64_t mInitialTime; // microseconds + // mNextVideoTime is the end timestamp for the last packet sent to the stream. + // Therefore video packets starting at or after this time need to be copied + // to the output stream. + int64_t mNextVideoTime; // microseconds + int64_t mNextAudioTime; // microseconds + MediaDecoder* mDecoder; + // The last video image sent to the stream. Useful if we need to replicate + // the image. + nsRefPtr<layers::Image> mLastVideoImage; + gfx::IntSize mLastVideoImageDisplaySize; + // This is set to true when the stream is initialized (audio and + // video tracks added). + bool mStreamInitialized; + bool mHaveSentFinish; + bool mHaveSentFinishAudio; + bool mHaveSentFinishVideo; + + // The decoder is responsible for calling Destroy() on this stream. + const nsRefPtr<SourceMediaStream> mStream; + nsRefPtr<DecodedStreamGraphListener> mListener; + // True when we've explicitly blocked this stream because we're + // not in PLAY_STATE_PLAYING. Used on the main thread only. + bool mHaveBlockedForPlayState; + // We also have an explicit blocker on the stream when + // mDecoderStateMachine is non-null and MediaDecoderStateMachine is false. + bool mHaveBlockedForStateMachineNotPlaying; +}; + +class OutputStreamData { +public: + // Compiler-generated default constructor needs the complete definition + // of OutputStreamListener when constructing OutputStreamData. Provide our + // own default constructor for forward declaration of OutputStreamListener + // to work. + OutputStreamData(); + ~OutputStreamData(); + void Init(MediaDecoder* aDecoder, ProcessedMediaStream* aStream); + nsRefPtr<ProcessedMediaStream> mStream; + // mPort connects DecodedStreamData::mStream to our mStream. + nsRefPtr<MediaInputPort> mPort; + nsRefPtr<OutputStreamListener> mListener; +}; + +} // namespace mozilla + +#endif // DecodedStream_h_ diff --git a/dom/media/MediaDecoder.cpp b/dom/media/MediaDecoder.cpp index da170820d..d09095ac9 100644 --- a/dom/media/MediaDecoder.cpp +++ b/dom/media/MediaDecoder.cpp @@ -313,137 +313,6 @@ void MediaDecoder::ConnectDecodedStreamToOutputStream(OutputStreamData* aStream) aStream->mStream->ChangeExplicitBlockerCount(-1); } -MediaDecoder::DecodedStreamData::DecodedStreamData(MediaDecoder* aDecoder, - int64_t aInitialTime, - SourceMediaStream* aStream) - : mAudioFramesWritten(0), - mInitialTime(aInitialTime), - mNextVideoTime(-1), - mNextAudioTime(-1), - mDecoder(aDecoder), - mStreamInitialized(false), - mHaveSentFinish(false), - mHaveSentFinishAudio(false), - mHaveSentFinishVideo(false), - mStream(aStream), - mHaveBlockedForPlayState(false), - mHaveBlockedForStateMachineNotPlaying(false) -{ - mListener = new DecodedStreamGraphListener(mStream, this); - mStream->AddListener(mListener); -} - -MediaDecoder::DecodedStreamData::~DecodedStreamData() -{ - mListener->Forget(); - mStream->Destroy(); -} - -MediaDecoder::DecodedStreamGraphListener::DecodedStreamGraphListener(MediaStream* aStream, - DecodedStreamData* aData) - : mData(aData), - mMutex("MediaDecoder::DecodedStreamData::mMutex"), - mStream(aStream), - mLastOutputTime(aStream-> - StreamTimeToMicroseconds(aStream->GetCurrentTime())), - mStreamFinishedOnMainThread(false) -{ -} - -void -MediaDecoder::DecodedStreamGraphListener::NotifyOutput(MediaStreamGraph* aGraph, - GraphTime aCurrentTime) -{ - MutexAutoLock lock(mMutex); - if (mStream) { - mLastOutputTime = mStream-> - StreamTimeToMicroseconds(mStream->GraphTimeToStreamTime(aCurrentTime)); - } -} - -void -MediaDecoder::DecodedStreamGraphListener::DoNotifyFinished() -{ - MutexAutoLock lock(mMutex); - mStreamFinishedOnMainThread = true; -} - -void -MediaDecoder::DecodedStreamGraphListener::NotifyEvent(MediaStreamGraph* aGraph, - MediaStreamListener::MediaStreamGraphEvent event) -{ - if (event == EVENT_FINISHED) { - nsCOMPtr<nsIRunnable> event = - NS_NewRunnableMethod(this, &DecodedStreamGraphListener::DoNotifyFinished); - aGraph->DispatchToMainThreadAfterStreamStateUpdate(event.forget()); - } -} - -class MediaDecoder::OutputStreamListener : public MediaStreamListener { -public: - OutputStreamListener(MediaDecoder* aDecoder, MediaStream* aStream) - : mDecoder(aDecoder), mStream(aStream) {} - - virtual void NotifyEvent( - MediaStreamGraph* aGraph, - MediaStreamListener::MediaStreamGraphEvent event) override { - if (event == EVENT_FINISHED) { - nsRefPtr<nsIRunnable> r = NS_NewRunnableMethod( - this, &OutputStreamListener::DoNotifyFinished); - aGraph->DispatchToMainThreadAfterStreamStateUpdate(r.forget()); - } - } - - void Forget() { - MOZ_ASSERT(NS_IsMainThread()); - mDecoder = nullptr; - } - -private: - void DoNotifyFinished() { - MOZ_ASSERT(NS_IsMainThread()); - if (!mDecoder) { - return; - } - - // Remove the finished stream so it won't block the decoded stream. - ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); - auto& streams = mDecoder->OutputStreams(); - // Don't read |mDecoder| in the loop since removing the element will lead - // to ~OutputStreamData() which will call Forget() to reset |mDecoder|. - for (int32_t i = streams.Length() - 1; i >= 0; --i) { - auto& os = streams[i]; - MediaStream* p = os.mStream.get(); - if (p == mStream.get()) { - if (os.mPort) { - os.mPort->Destroy(); - os.mPort = nullptr; - } - streams.RemoveElementAt(i); - break; - } - } - } - - // Main thread only - MediaDecoder* mDecoder; - nsRefPtr<MediaStream> mStream; -}; - -void -MediaDecoder::OutputStreamData::Init(MediaDecoder* aDecoder, - ProcessedMediaStream* aStream) -{ - mStream = aStream; - mListener = new OutputStreamListener(aDecoder, aStream); - aStream->AddListener(mListener); -} - -MediaDecoder::OutputStreamData::~OutputStreamData() -{ - mListener->Forget(); -} - void MediaDecoder::UpdateDecodedStream() { MOZ_ASSERT(NS_IsMainThread()); diff --git a/dom/media/MediaDecoder.h b/dom/media/MediaDecoder.h index 9d82f99de..34008ed82 100644 --- a/dom/media/MediaDecoder.h +++ b/dom/media/MediaDecoder.h @@ -192,11 +192,11 @@ destroying the MediaDecoder object. #include "MediaPromise.h" #include "MediaResource.h" #include "mozilla/dom/AudioChannelBinding.h" -#include "mozilla/gfx/Rect.h" #include "mozilla/ReentrantMonitor.h" #include "MediaDecoderOwner.h" #include "MediaStreamGraph.h" #include "AbstractMediaDecoder.h" +#include "DecodedStream.h" #include "StateMirroring.h" #include "StateWatching.h" #include "necko-config.h" @@ -206,9 +206,6 @@ class nsIStreamListener; class nsIPrincipal; namespace mozilla { -namespace layers { -class Image; -} //namespace layers class VideoFrameContainer; class MediaDecoderStateMachine; @@ -275,7 +272,6 @@ public: }; typedef MediaPromise<SeekResolveValue, bool /* aIgnored */, /* IsExclusive = */ true> SeekPromise; - class DecodedStreamGraphListener; NS_DECL_THREADSAFE_ISUPPORTS NS_DECL_NSIOBSERVER @@ -395,110 +391,6 @@ public: // replaying after the input as ended. In the latter case, the new source is // not connected to streams created by captureStreamUntilEnded. - struct DecodedStreamData { - typedef gfx::IntSize IntSize; - - DecodedStreamData(MediaDecoder* aDecoder, - int64_t aInitialTime, SourceMediaStream* aStream); - ~DecodedStreamData(); - - // microseconds - bool IsFinished() const { - return mListener->IsFinishedOnMainThread(); - } - - int64_t GetClock() const { - return mInitialTime + mListener->GetLastOutputTime(); - } - - // The following group of fields are protected by the decoder's monitor - // and can be read or written on any thread. - // Count of audio frames written to the stream - int64_t mAudioFramesWritten; - // Saved value of aInitialTime. Timestamp of the first audio and/or - // video packet written. - const int64_t mInitialTime; // microseconds - // mNextVideoTime is the end timestamp for the last packet sent to the stream. - // Therefore video packets starting at or after this time need to be copied - // to the output stream. - int64_t mNextVideoTime; // microseconds - int64_t mNextAudioTime; // microseconds - MediaDecoder* mDecoder; - // The last video image sent to the stream. Useful if we need to replicate - // the image. - nsRefPtr<layers::Image> mLastVideoImage; - IntSize mLastVideoImageDisplaySize; - // This is set to true when the stream is initialized (audio and - // video tracks added). - bool mStreamInitialized; - bool mHaveSentFinish; - bool mHaveSentFinishAudio; - bool mHaveSentFinishVideo; - - // The decoder is responsible for calling Destroy() on this stream. - // Can be read from any thread. - const nsRefPtr<SourceMediaStream> mStream; - // Can be read from any thread. - nsRefPtr<DecodedStreamGraphListener> mListener; - // True when we've explicitly blocked this stream because we're - // not in PLAY_STATE_PLAYING. Used on the main thread only. - bool mHaveBlockedForPlayState; - // We also have an explicit blocker on the stream when - // mDecoderStateMachine is non-null and MediaDecoderStateMachine is false. - bool mHaveBlockedForStateMachineNotPlaying; - }; - - class DecodedStreamGraphListener : public MediaStreamListener { - public: - DecodedStreamGraphListener(MediaStream* aStream, DecodedStreamData* aData); - virtual void NotifyOutput(MediaStreamGraph* aGraph, GraphTime aCurrentTime) override; - virtual void NotifyEvent(MediaStreamGraph* aGraph, - MediaStreamListener::MediaStreamGraphEvent event) override; - - void DoNotifyFinished(); - - int64_t GetLastOutputTime() // microseconds - { - MutexAutoLock lock(mMutex); - return mLastOutputTime; - } - void Forget() - { - NS_ASSERTION(NS_IsMainThread(), "Main thread only"); - mData = nullptr; - - MutexAutoLock lock(mMutex); - mStream = nullptr; - } - bool IsFinishedOnMainThread() - { - MutexAutoLock lock(mMutex); - return mStreamFinishedOnMainThread; - } - private: - // Main thread only - DecodedStreamData* mData; - - Mutex mMutex; - // Protected by mMutex - nsRefPtr<MediaStream> mStream; - // Protected by mMutex - int64_t mLastOutputTime; // microseconds - // Protected by mMutex - bool mStreamFinishedOnMainThread; - }; - - class OutputStreamListener; - - struct OutputStreamData { - void Init(MediaDecoder* aDecoder, ProcessedMediaStream* aStream); - ~OutputStreamData(); - nsRefPtr<ProcessedMediaStream> mStream; - // mPort connects mDecodedStream->mStream to our mStream. - nsRefPtr<MediaInputPort> mPort; - nsRefPtr<OutputStreamListener> mListener; - }; - /** * Connects mDecodedStream->mStream to aStream->mStream. */ diff --git a/dom/media/MediaDecoderStateMachine.cpp b/dom/media/MediaDecoderStateMachine.cpp index 274a42b4e..fcda25116 100644 --- a/dom/media/MediaDecoderStateMachine.cpp +++ b/dom/media/MediaDecoderStateMachine.cpp @@ -38,6 +38,7 @@ #include "gfx2DGlue.h" #include "nsPrintfCString.h" #include "DOMMediaStream.h" +#include "DecodedStream.h" #include <algorithm> diff --git a/dom/media/MediaDecoderStateMachine.h b/dom/media/MediaDecoderStateMachine.h index d6abb13e4..89ee36c01 100644 --- a/dom/media/MediaDecoderStateMachine.h +++ b/dom/media/MediaDecoderStateMachine.h @@ -102,6 +102,7 @@ class VideoSegment; class MediaTaskQueue; class SharedThreadPool; class AudioSink; +class DecodedStreamData; class MediaDecoderStateMachineScheduler; /* @@ -122,10 +123,9 @@ class MediaDecoderStateMachine NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaDecoderStateMachine) public: typedef MediaDecoderOwner::NextFrameStatus NextFrameStatus; - typedef MediaDecoder::DecodedStreamData DecodedStreamData; MediaDecoderStateMachine(MediaDecoder* aDecoder, - MediaDecoderReader* aReader, - bool aRealTime = false); + MediaDecoderReader* aReader, + bool aRealTime = false); nsresult Init(MediaDecoderStateMachine* aCloneDonor); diff --git a/dom/media/moz.build b/dom/media/moz.build index d7f8e0909..776cd600c 100644 --- a/dom/media/moz.build +++ b/dom/media/moz.build @@ -87,6 +87,7 @@ EXPORTS += [ 'AudioStream.h', 'BufferMediaResource.h', 'CubebUtils.h', + 'DecodedStream.h', 'DecoderTraits.h', 'DOMMediaStream.h', 'EncodedBufferCache.h', @@ -175,6 +176,7 @@ UNIFIED_SOURCES += [ 'AudioTrack.cpp', 'AudioTrackList.cpp', 'CubebUtils.cpp', + 'DecodedStream.cpp', 'DOMMediaStream.cpp', 'EncodedBufferCache.cpp', 'FileBlockCache.cpp', |