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