MFMediaEngineStream.h (8404B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #ifndef DOM_MEDIA_PLATFORM_WMF_MFMEDIAENGINESTREAM_H 6 #define DOM_MEDIA_PLATFORM_WMF_MFMEDIAENGINESTREAM_H 7 8 #include <mfidl.h> 9 #include <wrl.h> 10 11 #include <queue> 12 13 #include "BlankDecoderModule.h" 14 #include "MediaQueue.h" 15 #include "PlatformDecoderModule.h" 16 #include "mozilla/Atomics.h" 17 #include "mozilla/Mutex.h" 18 19 namespace mozilla { 20 21 class MFMediaEngineVideoStream; 22 class MFMediaSource; 23 24 /** 25 * MFMediaEngineStream represents a track which would be responsible to provide 26 * encoded data into the media engine. The media engine can access this stream 27 * by the presentation descriptor which was acquired from the custom media 28 * source. 29 */ 30 class MFMediaEngineStream 31 : public Microsoft::WRL::RuntimeClass< 32 Microsoft::WRL::RuntimeClassFlags< 33 Microsoft::WRL::RuntimeClassType::ClassicCom>, 34 IMFMediaStream> { 35 public: 36 MFMediaEngineStream(); 37 ~MFMediaEngineStream(); 38 39 virtual nsCString GetDescriptionName() const = 0; 40 41 virtual nsCString GetCodecName() const = 0; 42 43 HRESULT RuntimeClassInitialize(uint64_t aStreamId, const TrackInfo& aInfo, 44 bool aIsEncryptedCustomInit, 45 MFMediaSource* aParentSource); 46 47 // Called by MFMediaSource. 48 HRESULT Start(const PROPVARIANT* aPosition); 49 HRESULT Seek(const PROPVARIANT* aPosition); 50 HRESULT Stop(); 51 HRESULT Pause(); 52 void Shutdown(); 53 54 void SetSelected(bool aSelected); 55 bool IsSelected() const { return mIsSelected; } 56 DWORD DescriptorId() const { return mStreamDescriptorId; } 57 58 // Methods for IMFMediaStream 59 IFACEMETHODIMP GetMediaSource(IMFMediaSource** aMediaSource) override; 60 IFACEMETHODIMP GetStreamDescriptor( 61 IMFStreamDescriptor** aStreamDescriptor) override; 62 IFACEMETHODIMP RequestSample(IUnknown* aToken) override; 63 64 // Methods for IMFMediaEventGenerator, IMFMediaStream derives from 65 // IMFMediaEventGenerator. 66 IFACEMETHODIMP GetEvent(DWORD aFlags, IMFMediaEvent** aEvent) override; 67 IFACEMETHODIMP BeginGetEvent(IMFAsyncCallback* aCallback, 68 IUnknown* aState) override; 69 IFACEMETHODIMP EndGetEvent(IMFAsyncResult* aResult, 70 IMFMediaEvent** aEvent) override; 71 IFACEMETHODIMP QueueEvent(MediaEventType aType, REFGUID aExtendedType, 72 HRESULT aStatus, 73 const PROPVARIANT* aValue) override; 74 75 TaskQueue* GetTaskQueue() { return mTaskQueue; } 76 77 void NotifyEndOfStream() { 78 Microsoft::WRL::ComPtr<MFMediaEngineStream> self = this; 79 (void)mTaskQueue->Dispatch(NS_NewRunnableFunction( 80 "MFMediaEngineStream::NotifyEndOfStream", 81 [self]() { self->NotifyEndOfStreamInternal(); })); 82 } 83 84 // Return the type of the track, the result should be either audio or video. 85 virtual TrackInfo::TrackType TrackType() = 0; 86 87 virtual RefPtr<MediaDataDecoder::FlushPromise> Flush(); 88 89 MediaEventProducer<TrackInfo::TrackType>& EndedEvent() { return mEndedEvent; } 90 91 // True if the stream has been shutdown, it's a thread safe method. 92 bool IsShutdown() const { return mIsShutdown; } 93 94 virtual MFMediaEngineVideoStream* AsVideoStream() { return nullptr; } 95 96 virtual RefPtr<MediaDataDecoder::DecodePromise> OutputData( 97 RefPtr<MediaRawData> aSample); 98 99 virtual RefPtr<MediaDataDecoder::DecodePromise> Drain(); 100 101 virtual MediaDataDecoder::ConversionRequired NeedsConversion() const { 102 return MediaDataDecoder::ConversionRequired::kNeedNone; 103 } 104 105 virtual bool IsEncrypted() const = 0; 106 107 protected: 108 HRESULT GenerateStreamDescriptor( 109 Microsoft::WRL::ComPtr<IMFMediaType>& aMediaType); 110 111 // Create a IMFMediaType which includes the details about the stream. 112 // https://docs.microsoft.com/en-us/windows/win32/medfound/media-type-attributes 113 virtual HRESULT CreateMediaType(const TrackInfo& aInfo, 114 IMFMediaType** aMediaType) = 0; 115 116 // True if the stream already has enough raw data. 117 virtual bool HasEnoughRawData() const = 0; 118 119 HRESULT CreateInputSample(IMFSample** aSample); 120 void ReplySampleRequestIfPossible(); 121 bool ShouldServeSamples() const; 122 123 void NotifyNewData(MediaRawData* aSample); 124 void NotifyEndOfStreamInternal(); 125 126 virtual bool IsEnded() const; 127 128 // Overwrite this method if inherited class needs to perform clean up on the 129 // task queue when the stream gets shutdowned. 130 virtual void ShutdownCleanUpOnTaskQueue() {}; 131 132 // Inherited class must implement this method to return decoded data. it 133 // should uses `mRawDataQueueForGeneratingOutput` to generate output. 134 virtual already_AddRefed<MediaData> OutputDataInternal() = 0; 135 136 virtual void SendRequestSampleEvent(bool aIsEnough); 137 138 HRESULT AddEncryptAttributes(IMFSample* aSample, 139 const CryptoSample& aCryptoConfig); 140 141 void NotifyEndEvent(); 142 143 void AssertOnTaskQueue() const; 144 void AssertOnMFThreadPool() const; 145 146 // IMFMediaEventQueue is thread-safe. 147 Microsoft::WRL::ComPtr<IMFMediaEventQueue> mMediaEventQueue; 148 Microsoft::WRL::ComPtr<IMFStreamDescriptor> mStreamDescriptor; 149 Microsoft::WRL::ComPtr<MFMediaSource> mParentSource; 150 151 // This an unique ID retrieved from the IMFStreamDescriptor. 152 DWORD mStreamDescriptorId = 0; 153 154 // A unique ID assigned by MFMediaSource, which won't be changed after first 155 // assignment. 156 uint64_t mStreamId = 0; 157 158 RefPtr<TaskQueue> mTaskQueue; 159 160 // This class would be run on three threads, MF thread pool, the source's 161 // task queue and MediaPDecoder (wrapper thread). Following members would be 162 // used across both threads so they need to be thread-safe. 163 164 // Modify on the MF thread pool, access from any threads. 165 Atomic<bool> mIsShutdown; 166 167 // True if the stream is selected by the media source. 168 // Modify on MF thread pool, access from any threads. 169 Atomic<bool> mIsSelected; 170 171 // A thread-safe queue storing input samples, which provides samples to the 172 // media engine. 173 MediaQueue<MediaRawData> mRawDataQueueForFeedingEngine; 174 175 // A thread-safe queue storing input samples, which would be used to generate 176 // decoded data. 177 MediaQueue<MediaRawData> mRawDataQueueForGeneratingOutput; 178 179 // Thread-safe members END 180 181 // Store sample request token, one token should be related with one output 182 // data. It's used on the task queue only. 183 std::queue<Microsoft::WRL::ComPtr<IUnknown>> mSampleRequestTokens; 184 185 // Notify when playback reachs the end for this track. 186 MediaEventProducer<TrackInfo::TrackType> mEndedEvent; 187 188 // True if the stream has received the last data, but it could be reset if the 189 // stream starts delivering more data. Used on the task queue only. 190 bool mReceivedEOS; 191 192 // https://github.com/w3c/encrypted-media/issues/251#issuecomment-819783073 193 bool mIsEncryptedCustomInit; 194 }; 195 196 /** 197 * This wrapper helps to dispatch task onto the stream's task queue. Its methods 198 * are not thread-safe and would only be called on the IPC decoder manager 199 * thread. 200 */ 201 class MFMediaEngineStreamWrapper final : public MediaDataDecoder { 202 public: 203 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MFMediaEngineStreamWrapper, final); 204 205 MFMediaEngineStreamWrapper(MFMediaEngineStream* aStream, 206 TaskQueue* aTaskQueue, 207 const CreateDecoderParams& aParams) 208 : mStream(aStream), mTaskQueue(aTaskQueue) { 209 MOZ_ASSERT(mStream); 210 MOZ_ASSERT(mTaskQueue); 211 } 212 213 // Methods for MediaDataDecoder, they are all called on the remote 214 // decoder manager thread. 215 RefPtr<InitPromise> Init() override; 216 RefPtr<DecodePromise> Decode(MediaRawData* aSample) override; 217 RefPtr<DecodePromise> Drain() override; 218 RefPtr<FlushPromise> Flush() override; 219 RefPtr<ShutdownPromise> Shutdown() override; 220 nsCString GetDescriptionName() const override; 221 nsCString GetCodecName() const override; 222 ConversionRequired NeedsConversion() const override; 223 bool ShouldDecoderAlwaysBeRecycled() const override; 224 225 bool IsHardwareAccelerated(nsACString& aFailureReason) const override; 226 227 private: 228 ~MFMediaEngineStreamWrapper() = default; 229 230 Microsoft::WRL::ComPtr<MFMediaEngineStream> mStream; 231 RefPtr<TaskQueue> mTaskQueue; 232 }; 233 234 } // namespace mozilla 235 236 #endif // DOM_MEDIA_PLATFORM_WMF_MFMEDIAENGINESTREAM_H