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