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