1 /*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 //#define LOG_NDEBUG 0
18 #define LOG_TAG "SimpleSoftOMXComponent"
19 #include <utils/Log.h>
20
21 #include <media/stagefright/omx/SimpleSoftOMXComponent.h>
22 #include <media/stagefright/foundation/ADebug.h>
23 #include <media/stagefright/foundation/ALooper.h>
24 #include <media/stagefright/foundation/AMessage.h>
25
26 namespace android {
27
SimpleSoftOMXComponent(const char * name,const OMX_CALLBACKTYPE * callbacks,OMX_PTR appData,OMX_COMPONENTTYPE ** component)28 SimpleSoftOMXComponent::SimpleSoftOMXComponent(
29 const char *name,
30 const OMX_CALLBACKTYPE *callbacks,
31 OMX_PTR appData,
32 OMX_COMPONENTTYPE **component)
33 : SoftOMXComponent(name, callbacks, appData, component),
34 mLooper(new ALooper),
35 mHandler(new AHandlerReflector<SimpleSoftOMXComponent>(this)),
36 mState(OMX_StateLoaded),
37 mTargetState(OMX_StateLoaded),
38 mFrameConfig(false) {
39 mLooper->setName(name);
40 mLooper->registerHandler(mHandler);
41
42 mLooper->start(
43 false, // runOnCallingThread
44 false, // canCallJava
45 ANDROID_PRIORITY_VIDEO);
46 }
47
prepareForDestruction()48 void SimpleSoftOMXComponent::prepareForDestruction() {
49 // The looper's queue may still contain messages referencing this
50 // object. Make sure those are flushed before returning so that
51 // a subsequent dlunload() does not pull out the rug from under us.
52
53 mLooper->unregisterHandler(mHandler->id());
54 mLooper->stop();
55 }
56
sendCommand(OMX_COMMANDTYPE cmd,OMX_U32 param,OMX_PTR data)57 OMX_ERRORTYPE SimpleSoftOMXComponent::sendCommand(
58 OMX_COMMANDTYPE cmd, OMX_U32 param, OMX_PTR data) {
59 CHECK(data == NULL);
60
61 sp<AMessage> msg = new AMessage(kWhatSendCommand, mHandler);
62 msg->setInt32("cmd", cmd);
63 msg->setInt32("param", param);
64 msg->post();
65
66 return OMX_ErrorNone;
67 }
68
isSetParameterAllowed(OMX_INDEXTYPE index,const OMX_PTR params) const69 bool SimpleSoftOMXComponent::isSetParameterAllowed(
70 OMX_INDEXTYPE index, const OMX_PTR params) const {
71 if (mState == OMX_StateLoaded) {
72 return true;
73 }
74
75 OMX_U32 portIndex;
76
77 switch (index) {
78 case OMX_IndexParamPortDefinition:
79 {
80 const OMX_PARAM_PORTDEFINITIONTYPE *portDefs =
81 (const OMX_PARAM_PORTDEFINITIONTYPE *) params;
82 if (!isValidOMXParam(portDefs)) {
83 return false;
84 }
85 portIndex = portDefs->nPortIndex;
86 break;
87 }
88
89 case OMX_IndexParamAudioPcm:
90 {
91 const OMX_AUDIO_PARAM_PCMMODETYPE *pcmMode =
92 (const OMX_AUDIO_PARAM_PCMMODETYPE *) params;
93 if (!isValidOMXParam(pcmMode)) {
94 return false;
95 }
96 portIndex = pcmMode->nPortIndex;
97 break;
98 }
99
100 case OMX_IndexParamAudioAac:
101 {
102 const OMX_AUDIO_PARAM_AACPROFILETYPE *aacMode =
103 (const OMX_AUDIO_PARAM_AACPROFILETYPE *) params;
104 if (!isValidOMXParam(aacMode)) {
105 return false;
106 }
107 portIndex = aacMode->nPortIndex;
108 break;
109 }
110
111 default:
112 return false;
113 }
114
115 CHECK(portIndex < mPorts.size());
116
117 return !mPorts.itemAt(portIndex).mDef.bEnabled;
118 }
119
getParameter(OMX_INDEXTYPE index,OMX_PTR params)120 OMX_ERRORTYPE SimpleSoftOMXComponent::getParameter(
121 OMX_INDEXTYPE index, OMX_PTR params) {
122 Mutex::Autolock autoLock(mLock);
123 return internalGetParameter(index, params);
124 }
125
setParameter(OMX_INDEXTYPE index,const OMX_PTR params)126 OMX_ERRORTYPE SimpleSoftOMXComponent::setParameter(
127 OMX_INDEXTYPE index, const OMX_PTR params) {
128 Mutex::Autolock autoLock(mLock);
129
130 CHECK(isSetParameterAllowed(index, params));
131
132 return internalSetParameter(index, params);
133 }
134
internalGetParameter(OMX_INDEXTYPE index,OMX_PTR params)135 OMX_ERRORTYPE SimpleSoftOMXComponent::internalGetParameter(
136 OMX_INDEXTYPE index, OMX_PTR params) {
137 switch (index) {
138 case OMX_IndexParamPortDefinition:
139 {
140 OMX_PARAM_PORTDEFINITIONTYPE *defParams =
141 (OMX_PARAM_PORTDEFINITIONTYPE *)params;
142
143 if (!isValidOMXParam(defParams)) {
144 return OMX_ErrorBadParameter;
145 }
146
147 if (defParams->nPortIndex >= mPorts.size()
148 || defParams->nSize
149 != sizeof(OMX_PARAM_PORTDEFINITIONTYPE)) {
150 return OMX_ErrorUndefined;
151 }
152
153 const PortInfo *port =
154 &mPorts.itemAt(defParams->nPortIndex);
155
156 memcpy(defParams, &port->mDef, sizeof(port->mDef));
157
158 return OMX_ErrorNone;
159 }
160
161 default:
162 return OMX_ErrorUnsupportedIndex;
163 }
164 }
165
internalSetParameter(OMX_INDEXTYPE index,const OMX_PTR params)166 OMX_ERRORTYPE SimpleSoftOMXComponent::internalSetParameter(
167 OMX_INDEXTYPE index, const OMX_PTR params) {
168 switch (index) {
169 case OMX_IndexParamPortDefinition:
170 {
171 OMX_PARAM_PORTDEFINITIONTYPE *defParams =
172 (OMX_PARAM_PORTDEFINITIONTYPE *)params;
173
174 if (!isValidOMXParam(defParams)) {
175 return OMX_ErrorBadParameter;
176 }
177
178 if (defParams->nPortIndex >= mPorts.size()) {
179 return OMX_ErrorBadPortIndex;
180 }
181 if (defParams->nSize != sizeof(OMX_PARAM_PORTDEFINITIONTYPE)) {
182 return OMX_ErrorUnsupportedSetting;
183 }
184
185 PortInfo *port =
186 &mPorts.editItemAt(defParams->nPortIndex);
187
188 // default behavior is that we only allow buffer size to increase
189 if (defParams->nBufferSize > port->mDef.nBufferSize) {
190 port->mDef.nBufferSize = defParams->nBufferSize;
191 }
192
193 if (defParams->nBufferCountActual < port->mDef.nBufferCountMin) {
194 ALOGW("component requires at least %u buffers (%u requested)",
195 port->mDef.nBufferCountMin, defParams->nBufferCountActual);
196 return OMX_ErrorUnsupportedSetting;
197 }
198
199 port->mDef.nBufferCountActual = defParams->nBufferCountActual;
200 return OMX_ErrorNone;
201 }
202
203 default:
204 return OMX_ErrorUnsupportedIndex;
205 }
206 }
207
internalSetConfig(OMX_INDEXTYPE index,const OMX_PTR params,bool * frameConfig)208 OMX_ERRORTYPE SimpleSoftOMXComponent::internalSetConfig(
209 OMX_INDEXTYPE index, const OMX_PTR params, bool *frameConfig) {
210 return OMX_ErrorUndefined;
211 }
212
setConfig(OMX_INDEXTYPE index,const OMX_PTR params)213 OMX_ERRORTYPE SimpleSoftOMXComponent::setConfig(
214 OMX_INDEXTYPE index, const OMX_PTR params) {
215 bool frameConfig = mFrameConfig;
216 OMX_ERRORTYPE err = internalSetConfig(index, params, &frameConfig);
217 if (err == OMX_ErrorNone) {
218 mFrameConfig = frameConfig;
219 }
220 return err;
221 }
222
useBuffer(OMX_BUFFERHEADERTYPE ** header,OMX_U32 portIndex,OMX_PTR appPrivate,OMX_U32 size,OMX_U8 * ptr)223 OMX_ERRORTYPE SimpleSoftOMXComponent::useBuffer(
224 OMX_BUFFERHEADERTYPE **header,
225 OMX_U32 portIndex,
226 OMX_PTR appPrivate,
227 OMX_U32 size,
228 OMX_U8 *ptr) {
229 Mutex::Autolock autoLock(mLock);
230 CHECK_LT(portIndex, mPorts.size());
231
232 PortInfo *port = &mPorts.editItemAt(portIndex);
233 if (size < port->mDef.nBufferSize) {
234 ALOGE("b/63522430, Buffer size is too small.");
235 android_errorWriteLog(0x534e4554, "63522430");
236 return OMX_ErrorBadParameter;
237 }
238
239 *header = new OMX_BUFFERHEADERTYPE;
240 (*header)->nSize = sizeof(OMX_BUFFERHEADERTYPE);
241 (*header)->nVersion.s.nVersionMajor = 1;
242 (*header)->nVersion.s.nVersionMinor = 0;
243 (*header)->nVersion.s.nRevision = 0;
244 (*header)->nVersion.s.nStep = 0;
245 (*header)->pBuffer = ptr;
246 (*header)->nAllocLen = size;
247 (*header)->nFilledLen = 0;
248 (*header)->nOffset = 0;
249 (*header)->pAppPrivate = appPrivate;
250 (*header)->pPlatformPrivate = NULL;
251 (*header)->pInputPortPrivate = NULL;
252 (*header)->pOutputPortPrivate = NULL;
253 (*header)->hMarkTargetComponent = NULL;
254 (*header)->pMarkData = NULL;
255 (*header)->nTickCount = 0;
256 (*header)->nTimeStamp = 0;
257 (*header)->nFlags = 0;
258 (*header)->nOutputPortIndex = portIndex;
259 (*header)->nInputPortIndex = portIndex;
260
261 CHECK(mState == OMX_StateLoaded || port->mDef.bEnabled == OMX_FALSE);
262
263 CHECK_LT(port->mBuffers.size(), port->mDef.nBufferCountActual);
264
265 port->mBuffers.push();
266
267 BufferInfo *buffer =
268 &port->mBuffers.editItemAt(port->mBuffers.size() - 1);
269
270 buffer->mHeader = *header;
271 buffer->mOwnedByUs = false;
272
273 if (port->mBuffers.size() == port->mDef.nBufferCountActual) {
274 port->mDef.bPopulated = OMX_TRUE;
275 checkTransitions();
276 }
277
278 return OMX_ErrorNone;
279 }
280
allocateBuffer(OMX_BUFFERHEADERTYPE ** header,OMX_U32 portIndex,OMX_PTR appPrivate,OMX_U32 size)281 OMX_ERRORTYPE SimpleSoftOMXComponent::allocateBuffer(
282 OMX_BUFFERHEADERTYPE **header,
283 OMX_U32 portIndex,
284 OMX_PTR appPrivate,
285 OMX_U32 size) {
286 OMX_U8 *ptr = new OMX_U8[size];
287
288 OMX_ERRORTYPE err =
289 useBuffer(header, portIndex, appPrivate, size, ptr);
290
291 if (err != OMX_ErrorNone) {
292 delete[] ptr;
293 ptr = NULL;
294
295 return err;
296 }
297
298 CHECK((*header)->pPlatformPrivate == NULL);
299 (*header)->pPlatformPrivate = ptr;
300
301 return OMX_ErrorNone;
302 }
303
freeBuffer(OMX_U32 portIndex,OMX_BUFFERHEADERTYPE * header)304 OMX_ERRORTYPE SimpleSoftOMXComponent::freeBuffer(
305 OMX_U32 portIndex,
306 OMX_BUFFERHEADERTYPE *header) {
307 Mutex::Autolock autoLock(mLock);
308
309 CHECK_LT(portIndex, mPorts.size());
310
311 PortInfo *port = &mPorts.editItemAt(portIndex);
312
313 #if 0 // XXX
314 CHECK((mState == OMX_StateIdle && mTargetState == OMX_StateLoaded)
315 || port->mDef.bEnabled == OMX_FALSE);
316 #endif
317
318 bool found = false;
319 for (size_t i = 0; i < port->mBuffers.size(); ++i) {
320 BufferInfo *buffer = &port->mBuffers.editItemAt(i);
321
322 if (buffer->mHeader == header) {
323 CHECK(!buffer->mOwnedByUs);
324
325 if (header->pPlatformPrivate != NULL) {
326 // This buffer's data was allocated by us.
327 CHECK(header->pPlatformPrivate == header->pBuffer);
328
329 delete[] header->pBuffer;
330 header->pBuffer = NULL;
331 }
332
333 delete header;
334 header = NULL;
335
336 port->mBuffers.removeAt(i);
337 port->mDef.bPopulated = OMX_FALSE;
338
339 checkTransitions();
340
341 found = true;
342 break;
343 }
344 }
345
346 CHECK(found);
347
348 return OMX_ErrorNone;
349 }
350
emptyThisBuffer(OMX_BUFFERHEADERTYPE * buffer)351 OMX_ERRORTYPE SimpleSoftOMXComponent::emptyThisBuffer(
352 OMX_BUFFERHEADERTYPE *buffer) {
353 sp<AMessage> msg = new AMessage(kWhatEmptyThisBuffer, mHandler);
354 msg->setPointer("header", buffer);
355 if (mFrameConfig) {
356 msg->setInt32("frame-config", mFrameConfig);
357 mFrameConfig = false;
358 }
359 msg->post();
360
361 return OMX_ErrorNone;
362 }
363
fillThisBuffer(OMX_BUFFERHEADERTYPE * buffer)364 OMX_ERRORTYPE SimpleSoftOMXComponent::fillThisBuffer(
365 OMX_BUFFERHEADERTYPE *buffer) {
366 sp<AMessage> msg = new AMessage(kWhatFillThisBuffer, mHandler);
367 msg->setPointer("header", buffer);
368 msg->post();
369
370 return OMX_ErrorNone;
371 }
372
getState(OMX_STATETYPE * state)373 OMX_ERRORTYPE SimpleSoftOMXComponent::getState(OMX_STATETYPE *state) {
374 Mutex::Autolock autoLock(mLock);
375
376 *state = mState;
377
378 return OMX_ErrorNone;
379 }
380
onMessageReceived(const sp<AMessage> & msg)381 void SimpleSoftOMXComponent::onMessageReceived(const sp<AMessage> &msg) {
382 Mutex::Autolock autoLock(mLock);
383 uint32_t msgType = msg->what();
384 ALOGV("msgType = %d", msgType);
385 switch (msgType) {
386 case kWhatSendCommand:
387 {
388 int32_t cmd, param;
389 CHECK(msg->findInt32("cmd", &cmd));
390 CHECK(msg->findInt32("param", ¶m));
391
392 onSendCommand((OMX_COMMANDTYPE)cmd, (OMX_U32)param);
393 break;
394 }
395
396 case kWhatEmptyThisBuffer:
397 case kWhatFillThisBuffer:
398 {
399 OMX_BUFFERHEADERTYPE *header;
400 CHECK(msg->findPointer("header", (void **)&header));
401 int32_t frameConfig;
402 if (!msg->findInt32("frame-config", &frameConfig)) {
403 frameConfig = 0;
404 }
405
406 CHECK(mState == OMX_StateExecuting && mTargetState == mState);
407
408 bool found = false;
409 size_t portIndex = (kWhatEmptyThisBuffer == msgType)?
410 header->nInputPortIndex: header->nOutputPortIndex;
411 PortInfo *port = &mPorts.editItemAt(portIndex);
412
413 for (size_t j = 0; j < port->mBuffers.size(); ++j) {
414 BufferInfo *buffer = &port->mBuffers.editItemAt(j);
415
416 if (buffer->mHeader == header) {
417 CHECK(!buffer->mOwnedByUs);
418
419 buffer->mOwnedByUs = true;
420 buffer->mFrameConfig = (bool)frameConfig;
421
422 CHECK((msgType == kWhatEmptyThisBuffer
423 && port->mDef.eDir == OMX_DirInput)
424 || (port->mDef.eDir == OMX_DirOutput));
425
426 port->mQueue.push_back(buffer);
427 onQueueFilled(portIndex);
428
429 found = true;
430 break;
431 }
432 }
433
434 CHECK(found);
435 break;
436 }
437
438 default:
439 TRESPASS();
440 break;
441 }
442 }
443
onSendCommand(OMX_COMMANDTYPE cmd,OMX_U32 param)444 void SimpleSoftOMXComponent::onSendCommand(
445 OMX_COMMANDTYPE cmd, OMX_U32 param) {
446 switch (cmd) {
447 case OMX_CommandStateSet:
448 {
449 onChangeState((OMX_STATETYPE)param);
450 break;
451 }
452
453 case OMX_CommandPortEnable:
454 case OMX_CommandPortDisable:
455 {
456 onPortEnable(param, cmd == OMX_CommandPortEnable);
457 break;
458 }
459
460 case OMX_CommandFlush:
461 {
462 onPortFlush(param, true /* sendFlushComplete */);
463 break;
464 }
465
466 default:
467 TRESPASS();
468 break;
469 }
470 }
471
onChangeState(OMX_STATETYPE state)472 void SimpleSoftOMXComponent::onChangeState(OMX_STATETYPE state) {
473 ALOGV("%p requesting change from %d to %d", this, mState, state);
474 // We shouldn't be in a state transition already.
475
476 if (mState == OMX_StateLoaded
477 && mTargetState == OMX_StateIdle
478 && state == OMX_StateLoaded) {
479 // OMX specifically allows "canceling" a state transition from loaded
480 // to idle. Pretend we made it to idle, and go back to loaded
481 ALOGV("load->idle canceled");
482 mState = mTargetState = OMX_StateIdle;
483 state = OMX_StateLoaded;
484 }
485
486 if (mState != mTargetState) {
487 ALOGE("State change to state %d requested while still transitioning from state %d to %d",
488 state, mState, mTargetState);
489 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
490 return;
491 }
492
493 switch (mState) {
494 case OMX_StateLoaded:
495 CHECK_EQ((int)state, (int)OMX_StateIdle);
496 break;
497 case OMX_StateIdle:
498 CHECK(state == OMX_StateLoaded || state == OMX_StateExecuting);
499 break;
500 case OMX_StateExecuting:
501 {
502 CHECK_EQ((int)state, (int)OMX_StateIdle);
503
504 for (size_t i = 0; i < mPorts.size(); ++i) {
505 onPortFlush(i, false /* sendFlushComplete */);
506 }
507
508 mState = OMX_StateIdle;
509 notify(OMX_EventCmdComplete, OMX_CommandStateSet, state, NULL);
510 break;
511 }
512
513 default:
514 TRESPASS();
515 }
516
517 mTargetState = state;
518
519 checkTransitions();
520 }
521
onReset()522 void SimpleSoftOMXComponent::onReset() {
523 // no-op
524 }
525
onPortEnable(OMX_U32 portIndex,bool enable)526 void SimpleSoftOMXComponent::onPortEnable(OMX_U32 portIndex, bool enable) {
527 CHECK_LT(portIndex, mPorts.size());
528
529 PortInfo *port = &mPorts.editItemAt(portIndex);
530 CHECK_EQ((int)port->mTransition, (int)PortInfo::NONE);
531 CHECK(port->mDef.bEnabled == !enable);
532
533 if (port->mDef.eDir != OMX_DirOutput) {
534 ALOGE("Port enable/disable allowed only on output ports.");
535 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
536 android_errorWriteLog(0x534e4554, "29421804");
537 return;
538 }
539
540 if (!enable) {
541 port->mDef.bEnabled = OMX_FALSE;
542 port->mTransition = PortInfo::DISABLING;
543
544 for (size_t i = 0; i < port->mBuffers.size(); ++i) {
545 BufferInfo *buffer = &port->mBuffers.editItemAt(i);
546
547 if (buffer->mOwnedByUs) {
548 buffer->mOwnedByUs = false;
549
550 if (port->mDef.eDir == OMX_DirInput) {
551 notifyEmptyBufferDone(buffer->mHeader);
552 } else {
553 CHECK_EQ(port->mDef.eDir, OMX_DirOutput);
554 notifyFillBufferDone(buffer->mHeader);
555 }
556 }
557 }
558
559 port->mQueue.clear();
560 } else {
561 port->mTransition = PortInfo::ENABLING;
562 }
563
564 checkTransitions();
565 }
566
onPortFlush(OMX_U32 portIndex,bool sendFlushComplete)567 void SimpleSoftOMXComponent::onPortFlush(
568 OMX_U32 portIndex, bool sendFlushComplete) {
569 if (portIndex == OMX_ALL) {
570 for (size_t i = 0; i < mPorts.size(); ++i) {
571 onPortFlush(i, sendFlushComplete);
572 }
573
574 if (sendFlushComplete) {
575 notify(OMX_EventCmdComplete, OMX_CommandFlush, OMX_ALL, NULL);
576 }
577
578 return;
579 }
580
581 CHECK_LT(portIndex, mPorts.size());
582
583 PortInfo *port = &mPorts.editItemAt(portIndex);
584 // Ideally, the port should not in transitioning state when flushing.
585 // However, in error handling case, e.g., the client can't allocate buffers
586 // when it tries to re-enable the port, the port will be stuck in ENABLING.
587 // The client will then transition the component from Executing to Idle,
588 // which leads to flushing ports. At this time, it should be ok to notify
589 // the client of the error and still clear all buffers on the port.
590 if (port->mTransition != PortInfo::NONE) {
591 notify(OMX_EventError, OMX_ErrorUndefined, 0, 0);
592 }
593
594 for (size_t i = 0; i < port->mBuffers.size(); ++i) {
595 BufferInfo *buffer = &port->mBuffers.editItemAt(i);
596
597 if (!buffer->mOwnedByUs) {
598 continue;
599 }
600
601 buffer->mHeader->nFilledLen = 0;
602 buffer->mHeader->nOffset = 0;
603 buffer->mHeader->nFlags = 0;
604
605 buffer->mOwnedByUs = false;
606
607 if (port->mDef.eDir == OMX_DirInput) {
608 notifyEmptyBufferDone(buffer->mHeader);
609 } else {
610 CHECK_EQ(port->mDef.eDir, OMX_DirOutput);
611
612 notifyFillBufferDone(buffer->mHeader);
613 }
614 }
615
616 port->mQueue.clear();
617
618 if (sendFlushComplete) {
619 notify(OMX_EventCmdComplete, OMX_CommandFlush, portIndex, NULL);
620
621 onPortFlushCompleted(portIndex);
622 }
623 }
624
checkTransitions()625 void SimpleSoftOMXComponent::checkTransitions() {
626 if (mState != mTargetState) {
627 bool transitionComplete = true;
628
629 if (mState == OMX_StateLoaded) {
630 CHECK_EQ((int)mTargetState, (int)OMX_StateIdle);
631
632 for (size_t i = 0; i < mPorts.size(); ++i) {
633 const PortInfo &port = mPorts.itemAt(i);
634 if (port.mDef.bEnabled == OMX_FALSE) {
635 continue;
636 }
637
638 if (port.mDef.bPopulated == OMX_FALSE) {
639 transitionComplete = false;
640 break;
641 }
642 }
643 } else if (mTargetState == OMX_StateLoaded) {
644 CHECK_EQ((int)mState, (int)OMX_StateIdle);
645
646 for (size_t i = 0; i < mPorts.size(); ++i) {
647 const PortInfo &port = mPorts.itemAt(i);
648 if (port.mDef.bEnabled == OMX_FALSE) {
649 continue;
650 }
651
652 size_t n = port.mBuffers.size();
653
654 if (n > 0) {
655 CHECK_LE(n, port.mDef.nBufferCountActual);
656
657 if (n == port.mDef.nBufferCountActual) {
658 CHECK_EQ((int)port.mDef.bPopulated, (int)OMX_TRUE);
659 } else {
660 CHECK_EQ((int)port.mDef.bPopulated, (int)OMX_FALSE);
661 }
662
663 transitionComplete = false;
664 break;
665 }
666 }
667 }
668
669 if (transitionComplete) {
670 ALOGV("state transition from %d to %d complete", mState, mTargetState);
671 mState = mTargetState;
672
673 if (mState == OMX_StateLoaded) {
674 onReset();
675 }
676
677 notify(OMX_EventCmdComplete, OMX_CommandStateSet, mState, NULL);
678 } else {
679 ALOGV("state transition from %d to %d not yet complete", mState, mTargetState);
680 }
681 }
682
683 for (size_t i = 0; i < mPorts.size(); ++i) {
684 PortInfo *port = &mPorts.editItemAt(i);
685
686 if (port->mTransition == PortInfo::DISABLING) {
687 if (port->mBuffers.empty()) {
688 ALOGV("Port %zu now disabled.", i);
689
690 port->mTransition = PortInfo::NONE;
691 notify(OMX_EventCmdComplete, OMX_CommandPortDisable, i, NULL);
692
693 onPortEnableCompleted(i, false /* enabled */);
694 }
695 } else if (port->mTransition == PortInfo::ENABLING) {
696 if (port->mDef.bPopulated == OMX_TRUE) {
697 ALOGV("Port %zu now enabled.", i);
698
699 port->mTransition = PortInfo::NONE;
700 port->mDef.bEnabled = OMX_TRUE;
701 notify(OMX_EventCmdComplete, OMX_CommandPortEnable, i, NULL);
702
703 onPortEnableCompleted(i, true /* enabled */);
704 }
705 }
706 }
707 }
708
addPort(const OMX_PARAM_PORTDEFINITIONTYPE & def)709 void SimpleSoftOMXComponent::addPort(const OMX_PARAM_PORTDEFINITIONTYPE &def) {
710 CHECK_EQ(def.nPortIndex, mPorts.size());
711
712 mPorts.push();
713 PortInfo *info = &mPorts.editItemAt(mPorts.size() - 1);
714 info->mDef = def;
715 info->mTransition = PortInfo::NONE;
716 }
717
onQueueFilled(OMX_U32 portIndex __unused)718 void SimpleSoftOMXComponent::onQueueFilled(OMX_U32 portIndex __unused) {
719 }
720
onPortFlushCompleted(OMX_U32 portIndex __unused)721 void SimpleSoftOMXComponent::onPortFlushCompleted(OMX_U32 portIndex __unused) {
722 }
723
onPortEnableCompleted(OMX_U32 portIndex __unused,bool enabled __unused)724 void SimpleSoftOMXComponent::onPortEnableCompleted(
725 OMX_U32 portIndex __unused, bool enabled __unused) {
726 }
727
728 List<SimpleSoftOMXComponent::BufferInfo *> &
getPortQueue(OMX_U32 portIndex)729 SimpleSoftOMXComponent::getPortQueue(OMX_U32 portIndex) {
730 CHECK_LT(portIndex, mPorts.size());
731 return mPorts.editItemAt(portIndex).mQueue;
732 }
733
editPortInfo(OMX_U32 portIndex)734 SimpleSoftOMXComponent::PortInfo *SimpleSoftOMXComponent::editPortInfo(
735 OMX_U32 portIndex) {
736 CHECK_LT(portIndex, mPorts.size());
737 return &mPorts.editItemAt(portIndex);
738 }
739
740 } // namespace android
741