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