OMXNodeInstance.cpp revision 3856b090cd04ba5dd4a59a12430ed724d5995909
1/*
2 * Copyright (C) 2009 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 "OMXNodeInstance"
19#include <utils/Log.h>
20
21#include "../include/OMXNodeInstance.h"
22#include "OMXMaster.h"
23
24#include <OMX_Component.h>
25
26#include <binder/IMemory.h>
27#include <media/stagefright/HardwareAPI.h>
28#include <media/stagefright/MediaDebug.h>
29#include <media/stagefright/MediaErrors.h>
30
31namespace android {
32
33struct BufferMeta {
34    BufferMeta(const sp<IMemory> &mem, bool is_backup = false)
35        : mMem(mem),
36          mIsBackup(is_backup) {
37    }
38
39    BufferMeta(size_t size)
40        : mSize(size),
41          mIsBackup(false) {
42    }
43
44    BufferMeta(const sp<GraphicBuffer> &graphicBuffer)
45        : mGraphicBuffer(graphicBuffer),
46          mIsBackup(false) {
47    }
48
49    void CopyFromOMX(const OMX_BUFFERHEADERTYPE *header) {
50        if (!mIsBackup) {
51            return;
52        }
53
54        memcpy((OMX_U8 *)mMem->pointer() + header->nOffset,
55               header->pBuffer + header->nOffset,
56               header->nFilledLen);
57    }
58
59    void CopyToOMX(const OMX_BUFFERHEADERTYPE *header) {
60        if (!mIsBackup) {
61            return;
62        }
63
64        memcpy(header->pBuffer + header->nOffset,
65               (const OMX_U8 *)mMem->pointer() + header->nOffset,
66               header->nFilledLen);
67    }
68
69private:
70    sp<GraphicBuffer> mGraphicBuffer;
71    sp<IMemory> mMem;
72    size_t mSize;
73    bool mIsBackup;
74
75    BufferMeta(const BufferMeta &);
76    BufferMeta &operator=(const BufferMeta &);
77};
78
79// static
80OMX_CALLBACKTYPE OMXNodeInstance::kCallbacks = {
81    &OnEvent, &OnEmptyBufferDone, &OnFillBufferDone
82};
83
84OMXNodeInstance::OMXNodeInstance(
85        OMX *owner, const sp<IOMXObserver> &observer)
86    : mOwner(owner),
87      mNodeID(NULL),
88      mHandle(NULL),
89      mObserver(observer),
90      mDying(false) {
91}
92
93OMXNodeInstance::~OMXNodeInstance() {
94    CHECK_EQ(mHandle, NULL);
95}
96
97void OMXNodeInstance::setHandle(OMX::node_id node_id, OMX_HANDLETYPE handle) {
98    CHECK_EQ(mHandle, NULL);
99    mNodeID = node_id;
100    mHandle = handle;
101}
102
103OMX *OMXNodeInstance::owner() {
104    return mOwner;
105}
106
107sp<IOMXObserver> OMXNodeInstance::observer() {
108    return mObserver;
109}
110
111OMX::node_id OMXNodeInstance::nodeID() {
112    return mNodeID;
113}
114
115static status_t StatusFromOMXError(OMX_ERRORTYPE err) {
116    switch (err) {
117        case OMX_ErrorNone:
118            return OK;
119        case OMX_ErrorUnsupportedSetting:
120            return ERROR_UNSUPPORTED;
121        default:
122            return UNKNOWN_ERROR;
123    }
124}
125
126status_t OMXNodeInstance::freeNode(OMXMaster *master) {
127    static int32_t kMaxNumIterations = 10;
128
129    // Transition the node from its current state all the way down
130    // to "Loaded".
131    // This ensures that all active buffers are properly freed even
132    // for components that don't do this themselves on a call to
133    // "FreeHandle".
134
135    // The code below may trigger some more events to be dispatched
136    // by the OMX component - we want to ignore them as our client
137    // does not expect them.
138    mDying = true;
139
140    OMX_STATETYPE state;
141    CHECK_EQ(OMX_GetState(mHandle, &state), OMX_ErrorNone);
142    switch (state) {
143        case OMX_StateExecuting:
144        {
145            ALOGV("forcing Executing->Idle");
146            sendCommand(OMX_CommandStateSet, OMX_StateIdle);
147            OMX_ERRORTYPE err;
148            int32_t iteration = 0;
149            while ((err = OMX_GetState(mHandle, &state)) == OMX_ErrorNone
150                   && state != OMX_StateIdle
151                   && state != OMX_StateInvalid) {
152                if (++iteration > kMaxNumIterations) {
153                    LOGE("component failed to enter Idle state, aborting.");
154                    state = OMX_StateInvalid;
155                    break;
156                }
157
158                usleep(100000);
159            }
160            CHECK_EQ(err, OMX_ErrorNone);
161
162            if (state == OMX_StateInvalid) {
163                break;
164            }
165
166            // fall through
167        }
168
169        case OMX_StateIdle:
170        {
171            ALOGV("forcing Idle->Loaded");
172            sendCommand(OMX_CommandStateSet, OMX_StateLoaded);
173
174            freeActiveBuffers();
175
176            OMX_ERRORTYPE err;
177            int32_t iteration = 0;
178            while ((err = OMX_GetState(mHandle, &state)) == OMX_ErrorNone
179                   && state != OMX_StateLoaded
180                   && state != OMX_StateInvalid) {
181                if (++iteration > kMaxNumIterations) {
182                    LOGE("component failed to enter Loaded state, aborting.");
183                    state = OMX_StateInvalid;
184                    break;
185                }
186
187                ALOGV("waiting for Loaded state...");
188                usleep(100000);
189            }
190            CHECK_EQ(err, OMX_ErrorNone);
191
192            // fall through
193        }
194
195        case OMX_StateLoaded:
196        case OMX_StateInvalid:
197            break;
198
199        default:
200            CHECK(!"should not be here, unknown state.");
201            break;
202    }
203
204    ALOGV("calling destroyComponentInstance");
205    OMX_ERRORTYPE err = master->destroyComponentInstance(
206            static_cast<OMX_COMPONENTTYPE *>(mHandle));
207    ALOGV("destroyComponentInstance returned err %d", err);
208
209    mHandle = NULL;
210
211    if (err != OMX_ErrorNone) {
212        LOGE("FreeHandle FAILED with error 0x%08x.", err);
213    }
214
215    mOwner->invalidateNodeID(mNodeID);
216    mNodeID = NULL;
217
218    ALOGV("OMXNodeInstance going away.");
219    delete this;
220
221    return StatusFromOMXError(err);
222}
223
224status_t OMXNodeInstance::sendCommand(
225        OMX_COMMANDTYPE cmd, OMX_S32 param) {
226    Mutex::Autolock autoLock(mLock);
227
228    OMX_ERRORTYPE err = OMX_SendCommand(mHandle, cmd, param, NULL);
229    return StatusFromOMXError(err);
230}
231
232status_t OMXNodeInstance::getParameter(
233        OMX_INDEXTYPE index, void *params, size_t size) {
234    Mutex::Autolock autoLock(mLock);
235
236    OMX_ERRORTYPE err = OMX_GetParameter(mHandle, index, params);
237
238    return StatusFromOMXError(err);
239}
240
241status_t OMXNodeInstance::setParameter(
242        OMX_INDEXTYPE index, const void *params, size_t size) {
243    Mutex::Autolock autoLock(mLock);
244
245    OMX_ERRORTYPE err = OMX_SetParameter(
246            mHandle, index, const_cast<void *>(params));
247
248    return StatusFromOMXError(err);
249}
250
251status_t OMXNodeInstance::getConfig(
252        OMX_INDEXTYPE index, void *params, size_t size) {
253    Mutex::Autolock autoLock(mLock);
254
255    OMX_ERRORTYPE err = OMX_GetConfig(mHandle, index, params);
256    return StatusFromOMXError(err);
257}
258
259status_t OMXNodeInstance::setConfig(
260        OMX_INDEXTYPE index, const void *params, size_t size) {
261    Mutex::Autolock autoLock(mLock);
262
263    OMX_ERRORTYPE err = OMX_SetConfig(
264            mHandle, index, const_cast<void *>(params));
265
266    return StatusFromOMXError(err);
267}
268
269status_t OMXNodeInstance::getState(OMX_STATETYPE* state) {
270    Mutex::Autolock autoLock(mLock);
271
272    OMX_ERRORTYPE err = OMX_GetState(mHandle, state);
273
274    return StatusFromOMXError(err);
275}
276
277status_t OMXNodeInstance::enableGraphicBuffers(
278        OMX_U32 portIndex, OMX_BOOL enable) {
279    Mutex::Autolock autoLock(mLock);
280
281    OMX_INDEXTYPE index;
282    OMX_ERRORTYPE err = OMX_GetExtensionIndex(
283            mHandle,
284            const_cast<OMX_STRING>("OMX.google.android.index.enableAndroidNativeBuffers"),
285            &index);
286
287    if (err != OMX_ErrorNone) {
288        LOGE("OMX_GetExtensionIndex failed");
289
290        return StatusFromOMXError(err);
291    }
292
293    OMX_VERSIONTYPE ver;
294    ver.s.nVersionMajor = 1;
295    ver.s.nVersionMinor = 0;
296    ver.s.nRevision = 0;
297    ver.s.nStep = 0;
298    EnableAndroidNativeBuffersParams params = {
299        sizeof(EnableAndroidNativeBuffersParams), ver, portIndex, enable,
300    };
301
302    err = OMX_SetParameter(mHandle, index, &params);
303
304    if (err != OMX_ErrorNone) {
305        LOGE("OMX_EnableAndroidNativeBuffers failed with error %d (0x%08x)",
306                err, err);
307
308        return UNKNOWN_ERROR;
309    }
310
311    return OK;
312}
313
314status_t OMXNodeInstance::getGraphicBufferUsage(
315        OMX_U32 portIndex, OMX_U32* usage) {
316    Mutex::Autolock autoLock(mLock);
317
318    OMX_INDEXTYPE index;
319    OMX_ERRORTYPE err = OMX_GetExtensionIndex(
320            mHandle,
321            const_cast<OMX_STRING>(
322                    "OMX.google.android.index.getAndroidNativeBufferUsage"),
323            &index);
324
325    if (err != OMX_ErrorNone) {
326        LOGE("OMX_GetExtensionIndex failed");
327
328        return StatusFromOMXError(err);
329    }
330
331    OMX_VERSIONTYPE ver;
332    ver.s.nVersionMajor = 1;
333    ver.s.nVersionMinor = 0;
334    ver.s.nRevision = 0;
335    ver.s.nStep = 0;
336    GetAndroidNativeBufferUsageParams params = {
337        sizeof(GetAndroidNativeBufferUsageParams), ver, portIndex, 0,
338    };
339
340    err = OMX_GetParameter(mHandle, index, &params);
341
342    if (err != OMX_ErrorNone) {
343        LOGE("OMX_GetAndroidNativeBufferUsage failed with error %d (0x%08x)",
344                err, err);
345        return UNKNOWN_ERROR;
346    }
347
348    *usage = params.nUsage;
349
350    return OK;
351}
352
353status_t OMXNodeInstance::storeMetaDataInBuffers(
354        OMX_U32 portIndex,
355        OMX_BOOL enable) {
356    Mutex::Autolock autolock(mLock);
357
358    OMX_INDEXTYPE index;
359    OMX_STRING name = const_cast<OMX_STRING>(
360            "OMX.google.android.index.storeMetaDataInBuffers");
361
362    OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
363    if (err != OMX_ErrorNone) {
364        LOGE("OMX_GetExtensionIndex %s failed", name);
365        return StatusFromOMXError(err);
366    }
367
368    StoreMetaDataInBuffersParams params;
369    memset(&params, 0, sizeof(params));
370    params.nSize = sizeof(params);
371
372    // Version: 1.0.0.0
373    params.nVersion.s.nVersionMajor = 1;
374
375    params.nPortIndex = portIndex;
376    params.bStoreMetaData = enable;
377    if ((err = OMX_SetParameter(mHandle, index, &params)) != OMX_ErrorNone) {
378        LOGE("OMX_SetParameter() failed for StoreMetaDataInBuffers: 0x%08x", err);
379        return UNKNOWN_ERROR;
380    }
381    return err;
382}
383
384status_t OMXNodeInstance::useBuffer(
385        OMX_U32 portIndex, const sp<IMemory> &params,
386        OMX::buffer_id *buffer) {
387    Mutex::Autolock autoLock(mLock);
388
389    BufferMeta *buffer_meta = new BufferMeta(params);
390
391    OMX_BUFFERHEADERTYPE *header;
392
393    OMX_ERRORTYPE err = OMX_UseBuffer(
394            mHandle, &header, portIndex, buffer_meta,
395            params->size(), static_cast<OMX_U8 *>(params->pointer()));
396
397    if (err != OMX_ErrorNone) {
398        LOGE("OMX_UseBuffer failed with error %d (0x%08x)", err, err);
399
400        delete buffer_meta;
401        buffer_meta = NULL;
402
403        *buffer = 0;
404
405        return UNKNOWN_ERROR;
406    }
407
408    CHECK_EQ(header->pAppPrivate, buffer_meta);
409
410    *buffer = header;
411
412    addActiveBuffer(portIndex, *buffer);
413
414    return OK;
415}
416
417status_t OMXNodeInstance::useGraphicBuffer2_l(
418        OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer,
419        OMX::buffer_id *buffer) {
420
421    // port definition
422    OMX_PARAM_PORTDEFINITIONTYPE def;
423    def.nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
424    def.nVersion.s.nVersionMajor = 1;
425    def.nVersion.s.nVersionMinor = 0;
426    def.nVersion.s.nRevision = 0;
427    def.nVersion.s.nStep = 0;
428    def.nPortIndex = portIndex;
429    OMX_ERRORTYPE err = OMX_GetParameter(mHandle, OMX_IndexParamPortDefinition, &def);
430    if (err != OMX_ErrorNone)
431    {
432        LOGE("%s::%d:Error getting OMX_IndexParamPortDefinition", __FUNCTION__, __LINE__);
433        return err;
434    }
435
436    BufferMeta *bufferMeta = new BufferMeta(graphicBuffer);
437
438    OMX_BUFFERHEADERTYPE *header = NULL;
439    OMX_U8* bufferHandle = const_cast<OMX_U8*>(
440            reinterpret_cast<const OMX_U8*>(graphicBuffer->handle));
441
442    err = OMX_UseBuffer(
443            mHandle,
444            &header,
445            portIndex,
446            bufferMeta,
447            def.nBufferSize,
448            bufferHandle);
449
450    if (err != OMX_ErrorNone) {
451        LOGE("OMX_UseBuffer failed with error %d (0x%08x)", err, err);
452        delete bufferMeta;
453        bufferMeta = NULL;
454        *buffer = 0;
455        return UNKNOWN_ERROR;
456    }
457
458    CHECK_EQ(header->pBuffer, bufferHandle);
459    CHECK_EQ(header->pAppPrivate, bufferMeta);
460
461    *buffer = header;
462
463    addActiveBuffer(portIndex, *buffer);
464
465    return OK;
466}
467
468// XXX: This function is here for backwards compatibility.  Once the OMX
469// implementations have been updated this can be removed and useGraphicBuffer2
470// can be renamed to useGraphicBuffer.
471status_t OMXNodeInstance::useGraphicBuffer(
472        OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer,
473        OMX::buffer_id *buffer) {
474    Mutex::Autolock autoLock(mLock);
475
476    // See if the newer version of the extension is present.
477    OMX_INDEXTYPE index;
478    if (OMX_GetExtensionIndex(
479            mHandle,
480            const_cast<OMX_STRING>("OMX.google.android.index.useAndroidNativeBuffer2"),
481            &index) == OMX_ErrorNone) {
482        return useGraphicBuffer2_l(portIndex, graphicBuffer, buffer);
483    }
484
485    OMX_ERRORTYPE err = OMX_GetExtensionIndex(
486            mHandle,
487            const_cast<OMX_STRING>("OMX.google.android.index.useAndroidNativeBuffer"),
488            &index);
489
490    if (err != OMX_ErrorNone) {
491        LOGE("OMX_GetExtensionIndex failed");
492
493        return StatusFromOMXError(err);
494    }
495
496    BufferMeta *bufferMeta = new BufferMeta(graphicBuffer);
497
498    OMX_BUFFERHEADERTYPE *header;
499
500    OMX_VERSIONTYPE ver;
501    ver.s.nVersionMajor = 1;
502    ver.s.nVersionMinor = 0;
503    ver.s.nRevision = 0;
504    ver.s.nStep = 0;
505    UseAndroidNativeBufferParams params = {
506        sizeof(UseAndroidNativeBufferParams), ver, portIndex, bufferMeta,
507        &header, graphicBuffer,
508    };
509
510    err = OMX_SetParameter(mHandle, index, &params);
511
512    if (err != OMX_ErrorNone) {
513        LOGE("OMX_UseAndroidNativeBuffer failed with error %d (0x%08x)", err,
514                err);
515
516        delete bufferMeta;
517        bufferMeta = NULL;
518
519        *buffer = 0;
520
521        return UNKNOWN_ERROR;
522    }
523
524    CHECK_EQ(header->pAppPrivate, bufferMeta);
525
526    *buffer = header;
527
528    addActiveBuffer(portIndex, *buffer);
529
530    return OK;
531}
532
533status_t OMXNodeInstance::allocateBuffer(
534        OMX_U32 portIndex, size_t size, OMX::buffer_id *buffer,
535        void **buffer_data) {
536    Mutex::Autolock autoLock(mLock);
537
538    BufferMeta *buffer_meta = new BufferMeta(size);
539
540    OMX_BUFFERHEADERTYPE *header;
541
542    OMX_ERRORTYPE err = OMX_AllocateBuffer(
543            mHandle, &header, portIndex, buffer_meta, size);
544
545    if (err != OMX_ErrorNone) {
546        LOGE("OMX_AllocateBuffer failed with error %d (0x%08x)", err, err);
547
548        delete buffer_meta;
549        buffer_meta = NULL;
550
551        *buffer = 0;
552
553        return UNKNOWN_ERROR;
554    }
555
556    CHECK_EQ(header->pAppPrivate, buffer_meta);
557
558    *buffer = header;
559    *buffer_data = header->pBuffer;
560
561    addActiveBuffer(portIndex, *buffer);
562
563    return OK;
564}
565
566status_t OMXNodeInstance::allocateBufferWithBackup(
567        OMX_U32 portIndex, const sp<IMemory> &params,
568        OMX::buffer_id *buffer) {
569    Mutex::Autolock autoLock(mLock);
570
571    BufferMeta *buffer_meta = new BufferMeta(params, true);
572
573    OMX_BUFFERHEADERTYPE *header;
574
575    OMX_ERRORTYPE err = OMX_AllocateBuffer(
576            mHandle, &header, portIndex, buffer_meta, params->size());
577
578    if (err != OMX_ErrorNone) {
579        LOGE("OMX_AllocateBuffer failed with error %d (0x%08x)", err, err);
580
581        delete buffer_meta;
582        buffer_meta = NULL;
583
584        *buffer = 0;
585
586        return UNKNOWN_ERROR;
587    }
588
589    CHECK_EQ(header->pAppPrivate, buffer_meta);
590
591    *buffer = header;
592
593    addActiveBuffer(portIndex, *buffer);
594
595    return OK;
596}
597
598status_t OMXNodeInstance::freeBuffer(
599        OMX_U32 portIndex, OMX::buffer_id buffer) {
600    Mutex::Autolock autoLock(mLock);
601
602    removeActiveBuffer(portIndex, buffer);
603
604    OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer;
605    BufferMeta *buffer_meta = static_cast<BufferMeta *>(header->pAppPrivate);
606
607    OMX_ERRORTYPE err = OMX_FreeBuffer(mHandle, portIndex, header);
608
609    delete buffer_meta;
610    buffer_meta = NULL;
611
612    return StatusFromOMXError(err);
613}
614
615status_t OMXNodeInstance::fillBuffer(OMX::buffer_id buffer) {
616    Mutex::Autolock autoLock(mLock);
617
618    OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer;
619    header->nFilledLen = 0;
620    header->nOffset = 0;
621    header->nFlags = 0;
622
623    OMX_ERRORTYPE err = OMX_FillThisBuffer(mHandle, header);
624
625    return StatusFromOMXError(err);
626}
627
628status_t OMXNodeInstance::emptyBuffer(
629        OMX::buffer_id buffer,
630        OMX_U32 rangeOffset, OMX_U32 rangeLength,
631        OMX_U32 flags, OMX_TICKS timestamp) {
632    Mutex::Autolock autoLock(mLock);
633
634    OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer;
635    header->nFilledLen = rangeLength;
636    header->nOffset = rangeOffset;
637    header->nFlags = flags;
638    header->nTimeStamp = timestamp;
639
640    BufferMeta *buffer_meta =
641        static_cast<BufferMeta *>(header->pAppPrivate);
642    buffer_meta->CopyToOMX(header);
643
644    OMX_ERRORTYPE err = OMX_EmptyThisBuffer(mHandle, header);
645
646    return StatusFromOMXError(err);
647}
648
649status_t OMXNodeInstance::getExtensionIndex(
650        const char *parameterName, OMX_INDEXTYPE *index) {
651    Mutex::Autolock autoLock(mLock);
652
653    OMX_ERRORTYPE err = OMX_GetExtensionIndex(
654            mHandle, const_cast<char *>(parameterName), index);
655
656    return StatusFromOMXError(err);
657}
658
659void OMXNodeInstance::onMessage(const omx_message &msg) {
660    if (msg.type == omx_message::FILL_BUFFER_DONE) {
661        OMX_BUFFERHEADERTYPE *buffer =
662            static_cast<OMX_BUFFERHEADERTYPE *>(
663                    msg.u.extended_buffer_data.buffer);
664
665        BufferMeta *buffer_meta =
666            static_cast<BufferMeta *>(buffer->pAppPrivate);
667
668        buffer_meta->CopyFromOMX(buffer);
669    }
670
671    mObserver->onMessage(msg);
672}
673
674void OMXNodeInstance::onObserverDied(OMXMaster *master) {
675    LOGE("!!! Observer died. Quickly, do something, ... anything...");
676
677    // Try to force shutdown of the node and hope for the best.
678    freeNode(master);
679}
680
681void OMXNodeInstance::onGetHandleFailed() {
682    delete this;
683}
684
685// static
686OMX_ERRORTYPE OMXNodeInstance::OnEvent(
687        OMX_IN OMX_HANDLETYPE hComponent,
688        OMX_IN OMX_PTR pAppData,
689        OMX_IN OMX_EVENTTYPE eEvent,
690        OMX_IN OMX_U32 nData1,
691        OMX_IN OMX_U32 nData2,
692        OMX_IN OMX_PTR pEventData) {
693    OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
694    if (instance->mDying) {
695        return OMX_ErrorNone;
696    }
697    return instance->owner()->OnEvent(
698            instance->nodeID(), eEvent, nData1, nData2, pEventData);
699}
700
701// static
702OMX_ERRORTYPE OMXNodeInstance::OnEmptyBufferDone(
703        OMX_IN OMX_HANDLETYPE hComponent,
704        OMX_IN OMX_PTR pAppData,
705        OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) {
706    OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
707    if (instance->mDying) {
708        return OMX_ErrorNone;
709    }
710    return instance->owner()->OnEmptyBufferDone(instance->nodeID(), pBuffer);
711}
712
713// static
714OMX_ERRORTYPE OMXNodeInstance::OnFillBufferDone(
715        OMX_IN OMX_HANDLETYPE hComponent,
716        OMX_IN OMX_PTR pAppData,
717        OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) {
718    OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
719    if (instance->mDying) {
720        return OMX_ErrorNone;
721    }
722    return instance->owner()->OnFillBufferDone(instance->nodeID(), pBuffer);
723}
724
725void OMXNodeInstance::addActiveBuffer(OMX_U32 portIndex, OMX::buffer_id id) {
726    ActiveBuffer active;
727    active.mPortIndex = portIndex;
728    active.mID = id;
729    mActiveBuffers.push(active);
730}
731
732void OMXNodeInstance::removeActiveBuffer(
733        OMX_U32 portIndex, OMX::buffer_id id) {
734    bool found = false;
735    for (size_t i = 0; i < mActiveBuffers.size(); ++i) {
736        if (mActiveBuffers[i].mPortIndex == portIndex
737            && mActiveBuffers[i].mID == id) {
738            found = true;
739            mActiveBuffers.removeItemsAt(i);
740            break;
741        }
742    }
743
744    if (!found) {
745        LOGW("Attempt to remove an active buffer we know nothing about...");
746    }
747}
748
749void OMXNodeInstance::freeActiveBuffers() {
750    // Make sure to count down here, as freeBuffer will in turn remove
751    // the active buffer from the vector...
752    for (size_t i = mActiveBuffers.size(); i--;) {
753        freeBuffer(mActiveBuffers[i].mPortIndex, mActiveBuffers[i].mID);
754    }
755}
756
757}  // namespace android
758