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 : #include "OmxPromiseLayer.h"
8 :
9 : #include "ImageContainer.h"
10 :
11 : #include "OmxDataDecoder.h"
12 : #include "OmxPlatformLayer.h"
13 :
14 :
15 : #ifdef LOG
16 : #undef LOG
17 : #endif
18 :
19 : #define LOG(arg, ...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, ("OmxPromiseLayer(%p)::%s: " arg, this, __func__, ##__VA_ARGS__))
20 :
21 : namespace mozilla {
22 :
23 0 : OmxPromiseLayer::OmxPromiseLayer(TaskQueue* aTaskQueue,
24 : OmxDataDecoder* aDataDecoder,
25 0 : layers::ImageContainer* aImageContainer)
26 0 : : mTaskQueue(aTaskQueue)
27 : {
28 : mPlatformLayer = OmxPlatformLayer::Create(aDataDecoder,
29 : this,
30 : aTaskQueue,
31 0 : aImageContainer);
32 0 : MOZ_ASSERT(!!mPlatformLayer);
33 0 : }
34 :
35 : RefPtr<OmxPromiseLayer::OmxCommandPromise>
36 0 : OmxPromiseLayer::Init(const TrackInfo* aInfo)
37 : {
38 0 : MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
39 :
40 0 : OMX_ERRORTYPE err = mPlatformLayer->InitOmxToStateLoaded(aInfo);
41 0 : if (err != OMX_ErrorNone) {
42 0 : OmxCommandFailureHolder failure(OMX_ErrorUndefined, OMX_CommandStateSet);
43 0 : return OmxCommandPromise::CreateAndReject(failure, __func__);
44 : }
45 :
46 0 : OMX_STATETYPE state = GetState();
47 0 : if (state == OMX_StateLoaded) {
48 0 : return OmxCommandPromise::CreateAndResolve(OMX_CommandStateSet, __func__);
49 0 : } if (state == OMX_StateIdle) {
50 0 : return SendCommand(OMX_CommandStateSet, OMX_StateIdle, nullptr);
51 : }
52 :
53 0 : OmxCommandFailureHolder failure(OMX_ErrorUndefined, OMX_CommandStateSet);
54 0 : return OmxCommandPromise::CreateAndReject(failure, __func__);
55 : }
56 :
57 : OMX_ERRORTYPE
58 0 : OmxPromiseLayer::Config()
59 : {
60 0 : MOZ_ASSERT(GetState() == OMX_StateLoaded);
61 :
62 0 : return mPlatformLayer->Config();
63 : }
64 :
65 : RefPtr<OmxPromiseLayer::OmxBufferPromise>
66 0 : OmxPromiseLayer::FillBuffer(BufferData* aData)
67 : {
68 0 : MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
69 0 : LOG("buffer %p", aData->mBuffer);
70 :
71 0 : RefPtr<OmxBufferPromise> p = aData->mPromise.Ensure(__func__);
72 :
73 0 : OMX_ERRORTYPE err = mPlatformLayer->FillThisBuffer(aData);
74 :
75 0 : if (err != OMX_ErrorNone) {
76 0 : OmxBufferFailureHolder failure(err, aData);
77 0 : aData->mPromise.Reject(Move(failure), __func__);
78 : } else {
79 0 : aData->mStatus = BufferData::BufferStatus::OMX_COMPONENT;
80 0 : GetBufferHolders(OMX_DirOutput)->AppendElement(aData);
81 : }
82 :
83 0 : return p;
84 : }
85 :
86 : RefPtr<OmxPromiseLayer::OmxBufferPromise>
87 0 : OmxPromiseLayer::EmptyBuffer(BufferData* aData)
88 : {
89 0 : MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
90 0 : LOG("buffer %p, size %lu", aData->mBuffer, aData->mBuffer->nFilledLen);
91 :
92 0 : RefPtr<OmxBufferPromise> p = aData->mPromise.Ensure(__func__);
93 :
94 0 : OMX_ERRORTYPE err = mPlatformLayer->EmptyThisBuffer(aData);
95 :
96 0 : if (err != OMX_ErrorNone) {
97 0 : OmxBufferFailureHolder failure(err, aData);
98 0 : aData->mPromise.Reject(Move(failure), __func__);
99 : } else {
100 0 : if (aData->mRawData) {
101 0 : mRawDatas.AppendElement(Move(aData->mRawData));
102 : }
103 0 : aData->mStatus = BufferData::BufferStatus::OMX_COMPONENT;
104 0 : GetBufferHolders(OMX_DirInput)->AppendElement(aData);
105 : }
106 :
107 0 : return p;
108 : }
109 :
110 : OmxPromiseLayer::BUFFERLIST*
111 0 : OmxPromiseLayer::GetBufferHolders(OMX_DIRTYPE aType)
112 : {
113 0 : MOZ_ASSERT(aType == OMX_DirInput || aType == OMX_DirOutput);
114 :
115 0 : if (aType == OMX_DirInput) {
116 0 : return &mInbufferHolders;
117 : }
118 :
119 0 : return &mOutbufferHolders;
120 : }
121 :
122 : already_AddRefed<MediaRawData>
123 0 : OmxPromiseLayer::FindAndRemoveRawData(OMX_TICKS aTimecode)
124 : {
125 0 : for (auto raw : mRawDatas) {
126 0 : if (raw->mTime.ToMicroseconds() == aTimecode) {
127 0 : mRawDatas.RemoveElement(raw);
128 0 : return raw.forget();
129 : }
130 : }
131 0 : return nullptr;
132 : }
133 :
134 : already_AddRefed<BufferData>
135 0 : OmxPromiseLayer::FindAndRemoveBufferHolder(OMX_DIRTYPE aType,
136 : BufferData::BufferID aId)
137 : {
138 0 : MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
139 :
140 0 : RefPtr<BufferData> holder;
141 0 : BUFFERLIST* holders = GetBufferHolders(aType);
142 :
143 0 : for (uint32_t i = 0; i < holders->Length(); i++) {
144 0 : if (holders->ElementAt(i)->ID() == aId) {
145 0 : holder = holders->ElementAt(i);
146 0 : holders->RemoveElementAt(i);
147 0 : return holder.forget();
148 : }
149 : }
150 :
151 0 : return nullptr;
152 : }
153 :
154 : already_AddRefed<BufferData>
155 0 : OmxPromiseLayer::FindBufferById(OMX_DIRTYPE aType, BufferData::BufferID aId)
156 : {
157 0 : MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
158 :
159 0 : RefPtr<BufferData> holder;
160 0 : BUFFERLIST* holders = GetBufferHolders(aType);
161 :
162 0 : for (uint32_t i = 0; i < holders->Length(); i++) {
163 0 : if (holders->ElementAt(i)->ID() == aId) {
164 0 : holder = holders->ElementAt(i);
165 0 : return holder.forget();
166 : }
167 : }
168 :
169 0 : return nullptr;
170 : }
171 :
172 : void
173 0 : OmxPromiseLayer::EmptyFillBufferDone(OMX_DIRTYPE aType, BufferData* aData)
174 : {
175 0 : if (aData) {
176 0 : LOG("type %d, buffer %p", aType, aData->mBuffer);
177 0 : if (aType == OMX_DirOutput) {
178 0 : aData->mRawData = nullptr;
179 0 : aData->mRawData = FindAndRemoveRawData(aData->mBuffer->nTimeStamp);
180 : }
181 0 : aData->mStatus = BufferData::BufferStatus::OMX_CLIENT;
182 0 : aData->mPromise.Resolve(aData, __func__);
183 : } else {
184 0 : LOG("type %d, no buffer", aType);
185 : }
186 0 : }
187 :
188 : void
189 0 : OmxPromiseLayer::EmptyFillBufferDone(OMX_DIRTYPE aType, BufferData::BufferID aID)
190 : {
191 0 : RefPtr<BufferData> holder = FindAndRemoveBufferHolder(aType, aID);
192 0 : EmptyFillBufferDone(aType, holder);
193 0 : }
194 :
195 : RefPtr<OmxPromiseLayer::OmxCommandPromise>
196 0 : OmxPromiseLayer::SendCommand(OMX_COMMANDTYPE aCmd, OMX_U32 aParam1, OMX_PTR aCmdData)
197 : {
198 0 : if (aCmd == OMX_CommandFlush) {
199 : // It doesn't support another flush commands before previous one is completed.
200 0 : MOZ_RELEASE_ASSERT(!mFlushCommands.Length());
201 :
202 : // Some coomponents don't send event with OMX_ALL, they send flush complete
203 : // event with input port and another event for output port.
204 : // In prupose of better compatibility, we interpret the OMX_ALL to OMX_DirInput
205 : // and OMX_DirOutput flush separately.
206 0 : OMX_DIRTYPE types[] = {OMX_DIRTYPE::OMX_DirInput, OMX_DIRTYPE::OMX_DirOutput};
207 0 : for(const auto type : types) {
208 0 : if ((aParam1 == type) || (aParam1 == OMX_ALL)) {
209 0 : mFlushCommands.AppendElement(FlushCommand({type, aCmdData}));
210 : }
211 :
212 0 : if (type == OMX_DirInput) {
213 : // Clear all buffered raw data.
214 0 : mRawDatas.Clear();
215 : }
216 : }
217 :
218 : // Don't overlay more than one flush command, some components can't overlay flush commands.
219 : // So here we send another flush after receiving the previous flush completed event.
220 0 : if (mFlushCommands.Length()) {
221 : OMX_ERRORTYPE err =
222 0 : mPlatformLayer->SendCommand(OMX_CommandFlush,
223 0 : mFlushCommands.ElementAt(0).type,
224 0 : mFlushCommands.ElementAt(0).cmd);
225 0 : if (err != OMX_ErrorNone) {
226 0 : OmxCommandFailureHolder failure(OMX_ErrorNotReady, OMX_CommandFlush);
227 0 : return OmxCommandPromise::CreateAndReject(failure, __func__);
228 : }
229 : } else {
230 0 : LOG("OMX_CommandFlush parameter error");
231 0 : OmxCommandFailureHolder failure(OMX_ErrorNotReady, OMX_CommandFlush);
232 0 : return OmxCommandPromise::CreateAndReject(failure, __func__);
233 : }
234 : } else {
235 0 : OMX_ERRORTYPE err = mPlatformLayer->SendCommand(aCmd, aParam1, aCmdData);
236 0 : if (err != OMX_ErrorNone) {
237 0 : OmxCommandFailureHolder failure(OMX_ErrorNotReady, aCmd);
238 0 : return OmxCommandPromise::CreateAndReject(failure, __func__);
239 : }
240 : }
241 :
242 0 : RefPtr<OmxCommandPromise> p;
243 0 : if (aCmd == OMX_CommandStateSet) {
244 0 : p = mCommandStatePromise.Ensure(__func__);
245 0 : } else if (aCmd == OMX_CommandFlush) {
246 0 : p = mFlushPromise.Ensure(__func__);
247 0 : } else if (aCmd == OMX_CommandPortEnable) {
248 0 : p = mPortEnablePromise.Ensure(__func__);
249 0 : } else if (aCmd == OMX_CommandPortDisable) {
250 0 : p = mPortDisablePromise.Ensure(__func__);
251 : } else {
252 0 : LOG("error unsupport command");
253 0 : MOZ_ASSERT(0);
254 : }
255 :
256 0 : return p;
257 : }
258 :
259 : bool
260 0 : OmxPromiseLayer::Event(OMX_EVENTTYPE aEvent, OMX_U32 aData1, OMX_U32 aData2)
261 : {
262 0 : OMX_COMMANDTYPE cmd = (OMX_COMMANDTYPE) aData1;
263 0 : switch (aEvent) {
264 : case OMX_EventCmdComplete:
265 : {
266 0 : if (cmd == OMX_CommandStateSet) {
267 0 : mCommandStatePromise.Resolve(OMX_CommandStateSet, __func__);
268 0 : } else if (cmd == OMX_CommandFlush) {
269 0 : MOZ_RELEASE_ASSERT(mFlushCommands.ElementAt(0).type == aData2);
270 0 : LOG("OMX_CommandFlush completed port type %lu", aData2);
271 0 : mFlushCommands.RemoveElementAt(0);
272 :
273 : // Sending next flush command.
274 0 : if (mFlushCommands.Length()) {
275 : OMX_ERRORTYPE err =
276 0 : mPlatformLayer->SendCommand(OMX_CommandFlush,
277 0 : mFlushCommands.ElementAt(0).type,
278 0 : mFlushCommands.ElementAt(0).cmd);
279 0 : if (err != OMX_ErrorNone) {
280 0 : OmxCommandFailureHolder failure(OMX_ErrorNotReady, OMX_CommandFlush);
281 0 : mFlushPromise.Reject(failure, __func__);
282 : }
283 : } else {
284 0 : mFlushPromise.Resolve(OMX_CommandFlush, __func__);
285 : }
286 0 : } else if (cmd == OMX_CommandPortDisable) {
287 0 : mPortDisablePromise.Resolve(OMX_CommandPortDisable, __func__);
288 0 : } else if (cmd == OMX_CommandPortEnable) {
289 0 : mPortEnablePromise.Resolve(OMX_CommandPortEnable, __func__);
290 : }
291 0 : break;
292 : }
293 : case OMX_EventError:
294 : {
295 0 : if (cmd == OMX_CommandStateSet) {
296 0 : OmxCommandFailureHolder failure(OMX_ErrorUndefined, OMX_CommandStateSet);
297 0 : mCommandStatePromise.Reject(failure, __func__);
298 0 : } else if (cmd == OMX_CommandFlush) {
299 0 : OmxCommandFailureHolder failure(OMX_ErrorUndefined, OMX_CommandFlush);
300 0 : mFlushPromise.Reject(failure, __func__);
301 0 : } else if (cmd == OMX_CommandPortDisable) {
302 0 : OmxCommandFailureHolder failure(OMX_ErrorUndefined, OMX_CommandPortDisable);
303 0 : mPortDisablePromise.Reject(failure, __func__);
304 0 : } else if (cmd == OMX_CommandPortEnable) {
305 0 : OmxCommandFailureHolder failure(OMX_ErrorUndefined, OMX_CommandPortEnable);
306 0 : mPortEnablePromise.Reject(failure, __func__);
307 : } else {
308 0 : return false;
309 : }
310 0 : break;
311 : }
312 : default:
313 : {
314 0 : return false;
315 : }
316 : }
317 0 : return true;
318 : }
319 :
320 : nsresult
321 0 : OmxPromiseLayer::AllocateOmxBuffer(OMX_DIRTYPE aType, BUFFERLIST* aBuffers)
322 : {
323 0 : return mPlatformLayer->AllocateOmxBuffer(aType, aBuffers);
324 : }
325 :
326 : nsresult
327 0 : OmxPromiseLayer::ReleaseOmxBuffer(OMX_DIRTYPE aType, BUFFERLIST* aBuffers)
328 : {
329 0 : return mPlatformLayer->ReleaseOmxBuffer(aType, aBuffers);
330 : }
331 :
332 : OMX_STATETYPE
333 0 : OmxPromiseLayer::GetState()
334 : {
335 : OMX_STATETYPE state;
336 0 : OMX_ERRORTYPE err = mPlatformLayer->GetState(&state);
337 0 : return err == OMX_ErrorNone ? state : OMX_StateInvalid;
338 : }
339 :
340 : OMX_ERRORTYPE
341 0 : OmxPromiseLayer::GetParameter(OMX_INDEXTYPE aParamIndex,
342 : OMX_PTR aComponentParameterStructure,
343 : OMX_U32 aComponentParameterSize)
344 : {
345 0 : return mPlatformLayer->GetParameter(aParamIndex,
346 : aComponentParameterStructure,
347 0 : aComponentParameterSize);
348 : }
349 :
350 : OMX_ERRORTYPE
351 0 : OmxPromiseLayer::SetParameter(OMX_INDEXTYPE aParamIndex,
352 : OMX_PTR aComponentParameterStructure,
353 : OMX_U32 aComponentParameterSize)
354 : {
355 0 : return mPlatformLayer->SetParameter(aParamIndex,
356 : aComponentParameterStructure,
357 0 : aComponentParameterSize);
358 : }
359 :
360 : OMX_U32
361 0 : OmxPromiseLayer::InputPortIndex()
362 : {
363 0 : return mPlatformLayer->InputPortIndex();
364 : }
365 :
366 : OMX_U32
367 0 : OmxPromiseLayer::OutputPortIndex()
368 : {
369 0 : return mPlatformLayer->OutputPortIndex();
370 : }
371 :
372 : nsresult
373 0 : OmxPromiseLayer::Shutdown()
374 : {
375 0 : LOG("");
376 0 : MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
377 0 : MOZ_ASSERT(!GetBufferHolders(OMX_DirInput)->Length());
378 0 : MOZ_ASSERT(!GetBufferHolders(OMX_DirOutput)->Length());
379 0 : return mPlatformLayer->Shutdown();
380 : }
381 :
382 : }
|