diff options
Diffstat (limited to 'dom/media/platforms/wmf/MFMediaEngineStream.h')
-rw-r--r-- | dom/media/platforms/wmf/MFMediaEngineStream.h | 228 |
1 files changed, 228 insertions, 0 deletions
diff --git a/dom/media/platforms/wmf/MFMediaEngineStream.h b/dom/media/platforms/wmf/MFMediaEngineStream.h new file mode 100644 index 0000000000..aa3bf7e65d --- /dev/null +++ b/dom/media/platforms/wmf/MFMediaEngineStream.h @@ -0,0 +1,228 @@ +/* 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 DOM_MEDIA_PLATFORM_WMF_MFMEDIAENGINESTREAM_H +#define DOM_MEDIA_PLATFORM_WMF_MFMEDIAENGINESTREAM_H + +#include <mfidl.h> +#include <wrl.h> + +#include <queue> + +#include "BlankDecoderModule.h" +#include "MediaQueue.h" +#include "PlatformDecoderModule.h" +#include "mozilla/Atomics.h" +#include "mozilla/Mutex.h" +#include "mozilla/SPSCQueue.h" + +namespace mozilla { + +class MFMediaEngineVideoStream; +class MFMediaSource; + +/** + * MFMediaEngineStream represents a track which would be responsible to provide + * encoded data into the media engine. The media engine can access this stream + * by the presentation descriptor which was acquired from the custom media + * source. + */ +class MFMediaEngineStream + : public Microsoft::WRL::RuntimeClass< + Microsoft::WRL::RuntimeClassFlags< + Microsoft::WRL::RuntimeClassType::ClassicCom>, + IMFMediaStream> { + public: + MFMediaEngineStream(); + ~MFMediaEngineStream(); + + virtual nsCString GetDescriptionName() const = 0; + + virtual nsCString GetCodecName() const = 0; + + HRESULT RuntimeClassInitialize(uint64_t aStreamId, const TrackInfo& aInfo, + MFMediaSource* aParentSource); + + // Called by MFMediaSource. + HRESULT Start(const PROPVARIANT* aPosition); + HRESULT Seek(const PROPVARIANT* aPosition); + HRESULT Stop(); + HRESULT Pause(); + void Shutdown(); + + void SetSelected(bool aSelected); + bool IsSelected() const { return mIsSelected; } + DWORD DescriptorId() const { return mStreamDescriptorId; } + + // Methods for IMFMediaStream + IFACEMETHODIMP GetMediaSource(IMFMediaSource** aMediaSource) override; + IFACEMETHODIMP GetStreamDescriptor( + IMFStreamDescriptor** aStreamDescriptor) override; + IFACEMETHODIMP RequestSample(IUnknown* aToken) override; + + // Methods for IMFMediaEventGenerator, IMFMediaStream derives from + // IMFMediaEventGenerator. + IFACEMETHODIMP GetEvent(DWORD aFlags, IMFMediaEvent** aEvent) override; + IFACEMETHODIMP BeginGetEvent(IMFAsyncCallback* aCallback, + IUnknown* aState) override; + IFACEMETHODIMP EndGetEvent(IMFAsyncResult* aResult, + IMFMediaEvent** aEvent) override; + IFACEMETHODIMP QueueEvent(MediaEventType aType, REFGUID aExtendedType, + HRESULT aStatus, + const PROPVARIANT* aValue) override; + + TaskQueue* GetTaskQueue() { return mTaskQueue; } + + void NotifyEndOfStream() { + Microsoft::WRL::ComPtr<MFMediaEngineStream> self = this; + Unused << mTaskQueue->Dispatch(NS_NewRunnableFunction( + "MFMediaEngineStream::NotifyEndOfStream", + [self]() { self->NotifyEndOfStreamInternal(); })); + } + + // Return the type of the track, the result should be either audio or video. + virtual TrackInfo::TrackType TrackType() = 0; + + RefPtr<MediaDataDecoder::FlushPromise> Flush(); + + MediaEventProducer<TrackInfo::TrackType>& EndedEvent() { return mEndedEvent; } + + // True if the stream has been shutdown, it's a thread safe method. + bool IsShutdown() const { return mIsShutdown; } + + virtual MFMediaEngineVideoStream* AsVideoStream() { return nullptr; } + + RefPtr<MediaDataDecoder::DecodePromise> OutputData( + RefPtr<MediaRawData> aSample); + + virtual RefPtr<MediaDataDecoder::DecodePromise> Drain(); + + virtual MediaDataDecoder::ConversionRequired NeedsConversion() const { + return MediaDataDecoder::ConversionRequired::kNeedNone; + } + + virtual bool IsEncrypted() const = 0; + + protected: + HRESULT GenerateStreamDescriptor( + Microsoft::WRL::ComPtr<IMFMediaType>& aMediaType); + + // Create a IMFMediaType which includes the details about the stream. + // https://docs.microsoft.com/en-us/windows/win32/medfound/media-type-attributes + virtual HRESULT CreateMediaType(const TrackInfo& aInfo, + IMFMediaType** aMediaType) = 0; + + // True if the stream already has enough raw data. + virtual bool HasEnoughRawData() const = 0; + + HRESULT CreateInputSample(IMFSample** aSample); + void ReplySampleRequestIfPossible(); + bool ShouldServeSamples() const; + + void NotifyNewData(MediaRawData* aSample); + void NotifyEndOfStreamInternal(); + + virtual bool IsEnded() const; + + // Overwrite this method if inherited class needs to perform clean up on the + // task queue when the stream gets shutdowned. + virtual void ShutdownCleanUpOnTaskQueue(){}; + + // Inherited class must implement this method to return decoded data. it + // should uses `mRawDataQueueForGeneratingOutput` to generate output. + virtual already_AddRefed<MediaData> OutputDataInternal() = 0; + + void SendRequestSampleEvent(bool aIsEnough); + + HRESULT AddEncryptAttributes(IMFSample* aSample, + const CryptoSample& aCryptoConfig); + + void AssertOnTaskQueue() const; + void AssertOnMFThreadPool() const; + + // IMFMediaEventQueue is thread-safe. + Microsoft::WRL::ComPtr<IMFMediaEventQueue> mMediaEventQueue; + Microsoft::WRL::ComPtr<IMFStreamDescriptor> mStreamDescriptor; + Microsoft::WRL::ComPtr<MFMediaSource> mParentSource; + + // This an unique ID retrieved from the IMFStreamDescriptor. + DWORD mStreamDescriptorId = 0; + + // A unique ID assigned by MFMediaSource, which won't be changed after first + // assignment. + uint64_t mStreamId = 0; + + RefPtr<TaskQueue> mTaskQueue; + + // This class would be run on three threads, MF thread pool, the source's + // task queue and MediaPDecoder (wrapper thread). Following members would be + // used across both threads so they need to be thread-safe. + + // Modify on the MF thread pool, access from any threads. + Atomic<bool> mIsShutdown; + + // True if the stream is selected by the media source. + // Modify on MF thread pool, access from any threads. + Atomic<bool> mIsSelected; + + // A thread-safe queue storing input samples, which provides samples to the + // media engine. + MediaQueue<MediaRawData> mRawDataQueueForFeedingEngine; + + // A thread-safe queue storing input samples, which would be used to generate + // decoded data. + MediaQueue<MediaRawData> mRawDataQueueForGeneratingOutput; + + // Thread-safe members END + + // Store sample request token, one token should be related with one output + // data. It's used on the task queue only. + std::queue<Microsoft::WRL::ComPtr<IUnknown>> mSampleRequestTokens; + + // Notify when playback reachs the end for this track. + MediaEventProducer<TrackInfo::TrackType> mEndedEvent; + + // True if the stream has received the last data, but it could be reset if the + // stream starts delivering more data. Used on the task queue only. + bool mReceivedEOS; +}; + +/** + * This wrapper helps to dispatch task onto the stream's task queue. Its methods + * are not thread-safe and would only be called on the IPC decoder manager + * thread. + */ +class MFMediaEngineStreamWrapper final : public MediaDataDecoder { + public: + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MFMediaEngineStreamWrapper, final); + + MFMediaEngineStreamWrapper(MFMediaEngineStream* aStream, + TaskQueue* aTaskQueue, + const CreateDecoderParams& aParams) + : mStream(aStream), mTaskQueue(aTaskQueue) { + MOZ_ASSERT(mStream); + MOZ_ASSERT(mTaskQueue); + } + + // Methods for MediaDataDecoder, they are all called on the remote + // decoder manager thread. + RefPtr<InitPromise> Init() override; + RefPtr<DecodePromise> Decode(MediaRawData* aSample) override; + RefPtr<DecodePromise> Drain() override; + RefPtr<FlushPromise> Flush() override; + RefPtr<ShutdownPromise> Shutdown() override; + nsCString GetDescriptionName() const override; + nsCString GetCodecName() const override; + ConversionRequired NeedsConversion() const override; + + private: + ~MFMediaEngineStreamWrapper() = default; + + Microsoft::WRL::ComPtr<MFMediaEngineStream> mStream; + RefPtr<TaskQueue> mTaskQueue; +}; + +} // namespace mozilla + +#endif // DOM_MEDIA_PLATFORM_WMF_MFMEDIAENGINESTREAM_H |