OmxPromiseLayer.h (7516B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim:set ts=2 sw=2 sts=2 et cindent: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #if !defined(OmxPromiseLayer_h_) 8 # define OmxPromiseLayer_h_ 9 10 # include "OMX_Core.h" 11 # include "OMX_Types.h" 12 # include "mozilla/MozPromise.h" 13 # include "mozilla/TaskQueue.h" 14 15 namespace mozilla { 16 17 namespace layers { 18 class ImageContainer; 19 } 20 21 class MediaData; 22 class MediaRawData; 23 class OmxDataDecoder; 24 class OmxPlatformLayer; 25 class TrackInfo; 26 27 /* This class acts as a middle layer between OmxDataDecoder and the underlying 28 * OmxPlatformLayer. 29 * 30 * This class has two purposes: 31 * 1. Using promise instead of OpenMax async callback function. 32 * For example, OmxCommandPromise is used for OpenMax IL SendCommand. 33 * 2. Manage the buffer exchanged between client and component. 34 * Because omx buffer works crossing threads, so each omx buffer has its own 35 * promise, it is defined in BufferData. 36 * 37 * All of functions and members in this class should be run in the same 38 * TaskQueue. 39 */ 40 class OmxPromiseLayer { 41 protected: 42 virtual ~OmxPromiseLayer() = default; 43 44 public: 45 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(OmxPromiseLayer) 46 47 OmxPromiseLayer(TaskQueue* aTaskQueue, OmxDataDecoder* aDataDecoder, 48 layers::ImageContainer* aImageContainer); 49 50 class BufferData; 51 52 typedef nsTArray<RefPtr<BufferData>> BUFFERLIST; 53 54 class OmxBufferFailureHolder { 55 public: 56 OmxBufferFailureHolder(OMX_ERRORTYPE aError, BufferData* aBuffer) 57 : mError(aError), mBuffer(aBuffer) {} 58 59 OMX_ERRORTYPE mError; 60 BufferData* mBuffer; 61 }; 62 63 typedef MozPromise<BufferData*, OmxBufferFailureHolder, 64 /* IsExclusive = */ false> 65 OmxBufferPromise; 66 67 class OmxCommandFailureHolder { 68 public: 69 OmxCommandFailureHolder(OMX_ERRORTYPE aErrorType, 70 OMX_COMMANDTYPE aCommandType) 71 : mErrorType(aErrorType), mCommandType(aCommandType) {} 72 73 OMX_ERRORTYPE mErrorType; 74 OMX_COMMANDTYPE mCommandType; 75 }; 76 77 typedef MozPromise<OMX_COMMANDTYPE, OmxCommandFailureHolder, 78 /* IsExclusive = */ true> 79 OmxCommandPromise; 80 81 typedef MozPromise<uint32_t, bool, /* IsExclusive = */ true> 82 OmxPortConfigPromise; 83 84 // TODO: maybe a generic promise is good enough for this case? 85 RefPtr<OmxCommandPromise> Init(const TrackInfo* aInfo); 86 87 OMX_ERRORTYPE Config(); 88 89 RefPtr<OmxBufferPromise> FillBuffer(BufferData* aData); 90 91 RefPtr<OmxBufferPromise> EmptyBuffer(BufferData* aData); 92 93 RefPtr<OmxCommandPromise> SendCommand(OMX_COMMANDTYPE aCmd, OMX_U32 aParam1, 94 OMX_PTR aCmdData); 95 96 nsresult AllocateOmxBuffer(OMX_DIRTYPE aType, BUFFERLIST* aBuffers); 97 98 nsresult ReleaseOmxBuffer(OMX_DIRTYPE aType, BUFFERLIST* aBuffers); 99 100 OMX_STATETYPE GetState(); 101 102 OMX_ERRORTYPE GetParameter(OMX_INDEXTYPE aParamIndex, 103 OMX_PTR aComponentParameterStructure, 104 OMX_U32 aComponentParameterSize); 105 106 OMX_ERRORTYPE SetParameter(OMX_INDEXTYPE nIndex, 107 OMX_PTR aComponentParameterStructure, 108 OMX_U32 aComponentParameterSize); 109 110 OMX_U32 InputPortIndex(); 111 112 OMX_U32 OutputPortIndex(); 113 114 nsresult Shutdown(); 115 116 // BufferData maintains the status of OMX buffer (OMX_BUFFERHEADERTYPE). 117 // mStatus tracks the buffer owner. 118 // And a promise because OMX buffer working among different threads. 119 class BufferData { 120 protected: 121 virtual ~BufferData() = default; 122 123 public: 124 explicit BufferData(OMX_BUFFERHEADERTYPE* aBuffer) 125 : mEos(false), mStatus(BufferStatus::FREE), mBuffer(aBuffer) {} 126 127 typedef void* BufferID; 128 129 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BufferData) 130 131 // In most cases, the ID of this buffer is the pointer address of mBuffer. 132 // However, on some platforms it may be another value. 133 virtual BufferID ID() { return mBuffer; } 134 135 // Return the platform dependent MediaData(). 136 // For example, it returns the MediaData with Gralloc texture. 137 // If it returns nullptr, then caller uses the normal way to 138 // create MediaData(). 139 virtual already_AddRefed<MediaData> GetPlatformMediaData() { 140 return nullptr; 141 } 142 143 // The buffer could be used by several objects. And only one object owns the 144 // buffer the same time. 145 // FREE: 146 // nobody uses it. 147 // 148 // OMX_COMPONENT: 149 // buffer is used by OMX component (OmxPlatformLayer). 150 // 151 // OMX_CLIENT: 152 // buffer is used by client which is wait for audio/video playing 153 // (OmxDataDecoder) 154 // 155 // OMX_CLIENT_OUTPUT: 156 // used by client to output decoded data (for example, Gecko layer in 157 // this case) 158 // 159 // For output port buffer, the status transition is: 160 // FREE -> OMX_COMPONENT -> OMX_CLIENT -> OMX_CLIENT_OUTPUT -> FREE 161 // 162 // For input port buffer, the status transition is: 163 // FREE -> OMX_COMPONENT -> OMX_CLIENT -> FREE 164 // 165 enum BufferStatus { 166 FREE, 167 OMX_COMPONENT, 168 OMX_CLIENT, 169 OMX_CLIENT_OUTPUT, 170 INVALID 171 }; 172 173 bool mEos; 174 175 // The raw keeps in OmxPromiseLayer after EmptyBuffer and then passing to 176 // output decoded buffer in EmptyFillBufferDone. It is used to keep the 177 // records of the original data from demuxer, like duration, stream 178 // offset...etc. 179 RefPtr<MediaRawData> mRawData; 180 181 // Because OMX buffer works across threads, so it uses a promise 182 // for each buffer when the buffer is used by Omx component. 183 MozPromiseHolder<OmxBufferPromise> mPromise; 184 BufferStatus mStatus; 185 OMX_BUFFERHEADERTYPE* mBuffer; 186 }; 187 188 void EmptyFillBufferDone(OMX_DIRTYPE aType, BufferData::BufferID aID); 189 190 void EmptyFillBufferDone(OMX_DIRTYPE aType, BufferData* aData); 191 192 already_AddRefed<BufferData> FindBufferById(OMX_DIRTYPE aType, 193 BufferData::BufferID aId); 194 195 already_AddRefed<BufferData> FindAndRemoveBufferHolder( 196 OMX_DIRTYPE aType, BufferData::BufferID aId); 197 198 // Return true if event is handled. 199 bool Event(OMX_EVENTTYPE aEvent, OMX_U32 aData1, OMX_U32 aData2); 200 201 protected: 202 struct FlushCommand { 203 OMX_DIRTYPE type; 204 OMX_PTR cmd; 205 }; 206 207 BUFFERLIST* GetBufferHolders(OMX_DIRTYPE aType); 208 209 already_AddRefed<MediaRawData> FindAndRemoveRawData(OMX_TICKS aTimecode); 210 211 RefPtr<TaskQueue> mTaskQueue; 212 213 MozPromiseHolder<OmxCommandPromise> mCommandStatePromise; 214 215 MozPromiseHolder<OmxCommandPromise> mPortDisablePromise; 216 217 MozPromiseHolder<OmxCommandPromise> mPortEnablePromise; 218 219 MozPromiseHolder<OmxCommandPromise> mFlushPromise; 220 221 nsTArray<FlushCommand> mFlushCommands; 222 223 UniquePtr<OmxPlatformLayer> mPlatformLayer; 224 225 private: 226 // Elements are added to holders when FillBuffer() or FillBuffer(). And 227 // removing element when the promise is resolved. Buffers in these lists 228 // should NOT be used by other component; for example, output it to audio 229 // output. These lists should be empty when engine is about to shutdown. 230 // 231 // Note: 232 // There bufferlist should not be used by other class directly. 233 BUFFERLIST mInbufferHolders; 234 235 BUFFERLIST mOutbufferHolders; 236 237 nsTArray<RefPtr<MediaRawData>> mRawDatas; 238 }; 239 240 } // namespace mozilla 241 242 #endif /* OmxPromiseLayer_h_ */