OMXNodeInstance.cpp revision 86369364a07c85dd8f0e890b783a7bd434b8ef7c
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#include "GraphicBufferSource.h"
24
25#include <OMX_Component.h>
26#include <OMX_IndexExt.h>
27
28#include <binder/IMemory.h>
29#include <gui/BufferQueue.h>
30#include <utils/misc.h>
31#include <HardwareAPI.h>
32#include <media/stagefright/foundation/ADebug.h>
33#include <media/stagefright/MediaErrors.h>
34
35static const OMX_U32 kPortIndexInput = 0;
36static const OMX_U32 kPortIndexOutput = 1;
37
38namespace android {
39
40struct BufferMeta {
41    BufferMeta(
42            const sp<IMemory> &mem, OMX_U32 portIndex, bool copyToOmx,
43            bool copyFromOmx, OMX_U8 *backup)
44        : mMem(mem),
45          mCopyFromOmx(copyFromOmx),
46          mCopyToOmx(copyToOmx),
47          mPortIndex(portIndex),
48          mBackup(backup) {
49    }
50
51    BufferMeta(size_t size, OMX_U32 portIndex)
52        : mSize(size),
53          mCopyFromOmx(false),
54          mCopyToOmx(false),
55          mPortIndex(portIndex),
56          mBackup(NULL) {
57    }
58
59    BufferMeta(const sp<GraphicBuffer> &graphicBuffer, OMX_U32 portIndex)
60        : mGraphicBuffer(graphicBuffer),
61          mCopyFromOmx(false),
62          mCopyToOmx(false),
63          mPortIndex(portIndex),
64          mBackup(NULL) {
65    }
66
67    void CopyFromOMX(const OMX_BUFFERHEADERTYPE *header) {
68        if (!mCopyFromOmx) {
69            return;
70        }
71
72        memcpy((OMX_U8 *)mMem->pointer() + header->nOffset,
73               header->pBuffer + header->nOffset,
74               header->nFilledLen);
75    }
76
77    void CopyToOMX(const OMX_BUFFERHEADERTYPE *header) {
78        if (!mCopyToOmx) {
79            return;
80        }
81
82        memcpy(header->pBuffer + header->nOffset,
83               (const OMX_U8 *)mMem->pointer() + header->nOffset,
84               header->nFilledLen);
85    }
86
87    void setGraphicBuffer(const sp<GraphicBuffer> &graphicBuffer) {
88        mGraphicBuffer = graphicBuffer;
89    }
90
91    OMX_U32 getPortIndex() {
92        return mPortIndex;
93    }
94
95    ~BufferMeta() {
96        delete[] mBackup;
97    }
98
99private:
100    sp<GraphicBuffer> mGraphicBuffer;
101    sp<IMemory> mMem;
102    size_t mSize;
103    bool mCopyFromOmx;
104    bool mCopyToOmx;
105    OMX_U32 mPortIndex;
106    OMX_U8 *mBackup;
107
108    BufferMeta(const BufferMeta &);
109    BufferMeta &operator=(const BufferMeta &);
110};
111
112// static
113OMX_CALLBACKTYPE OMXNodeInstance::kCallbacks = {
114    &OnEvent, &OnEmptyBufferDone, &OnFillBufferDone
115};
116
117OMXNodeInstance::OMXNodeInstance(
118        OMX *owner, const sp<IOMXObserver> &observer, const char *name)
119    : mOwner(owner),
120      mNodeID(0),
121      mHandle(NULL),
122      mObserver(observer),
123      mDying(false),
124      mSailed(false),
125      mQueriedProhibitedExtensions(false),
126      mBufferIDCount(0)
127{
128    mUsingMetadata[0] = false;
129    mUsingMetadata[1] = false;
130    mIsSecure = AString(name).endsWith(".secure");
131}
132
133OMXNodeInstance::~OMXNodeInstance() {
134    CHECK(mHandle == NULL);
135}
136
137void OMXNodeInstance::setHandle(OMX::node_id node_id, OMX_HANDLETYPE handle) {
138    CHECK(mHandle == NULL);
139    mNodeID = node_id;
140    mHandle = handle;
141}
142
143sp<GraphicBufferSource> OMXNodeInstance::getGraphicBufferSource() {
144    Mutex::Autolock autoLock(mGraphicBufferSourceLock);
145    return mGraphicBufferSource;
146}
147
148void OMXNodeInstance::setGraphicBufferSource(
149        const sp<GraphicBufferSource>& bufferSource) {
150    Mutex::Autolock autoLock(mGraphicBufferSourceLock);
151    mGraphicBufferSource = bufferSource;
152}
153
154OMX *OMXNodeInstance::owner() {
155    return mOwner;
156}
157
158sp<IOMXObserver> OMXNodeInstance::observer() {
159    return mObserver;
160}
161
162OMX::node_id OMXNodeInstance::nodeID() {
163    return mNodeID;
164}
165
166static status_t StatusFromOMXError(OMX_ERRORTYPE err) {
167    switch (err) {
168        case OMX_ErrorNone:
169            return OK;
170        case OMX_ErrorUnsupportedSetting:
171            return ERROR_UNSUPPORTED;
172        default:
173            return UNKNOWN_ERROR;
174    }
175}
176
177status_t OMXNodeInstance::freeNode(OMXMaster *master) {
178    static int32_t kMaxNumIterations = 10;
179
180    // exit if we have already freed the node
181    if (mHandle == NULL) {
182        return OK;
183    }
184
185    // Transition the node from its current state all the way down
186    // to "Loaded".
187    // This ensures that all active buffers are properly freed even
188    // for components that don't do this themselves on a call to
189    // "FreeHandle".
190
191    // The code below may trigger some more events to be dispatched
192    // by the OMX component - we want to ignore them as our client
193    // does not expect them.
194    mDying = true;
195
196    OMX_STATETYPE state;
197    CHECK_EQ(OMX_GetState(mHandle, &state), OMX_ErrorNone);
198    switch (state) {
199        case OMX_StateExecuting:
200        {
201            ALOGV("forcing Executing->Idle");
202            sendCommand(OMX_CommandStateSet, OMX_StateIdle);
203            OMX_ERRORTYPE err;
204            int32_t iteration = 0;
205            while ((err = OMX_GetState(mHandle, &state)) == OMX_ErrorNone
206                   && state != OMX_StateIdle
207                   && state != OMX_StateInvalid) {
208                if (++iteration > kMaxNumIterations) {
209                    ALOGE("component failed to enter Idle state, aborting.");
210                    state = OMX_StateInvalid;
211                    break;
212                }
213
214                usleep(100000);
215            }
216            CHECK_EQ(err, OMX_ErrorNone);
217
218            if (state == OMX_StateInvalid) {
219                break;
220            }
221
222            // fall through
223        }
224
225        case OMX_StateIdle:
226        {
227            ALOGV("forcing Idle->Loaded");
228            sendCommand(OMX_CommandStateSet, OMX_StateLoaded);
229
230            freeActiveBuffers();
231
232            OMX_ERRORTYPE err;
233            int32_t iteration = 0;
234            while ((err = OMX_GetState(mHandle, &state)) == OMX_ErrorNone
235                   && state != OMX_StateLoaded
236                   && state != OMX_StateInvalid) {
237                if (++iteration > kMaxNumIterations) {
238                    ALOGE("component failed to enter Loaded state, aborting.");
239                    state = OMX_StateInvalid;
240                    break;
241                }
242
243                ALOGV("waiting for Loaded state...");
244                usleep(100000);
245            }
246            CHECK_EQ(err, OMX_ErrorNone);
247
248            // fall through
249        }
250
251        case OMX_StateLoaded:
252        case OMX_StateInvalid:
253            break;
254
255        default:
256            CHECK(!"should not be here, unknown state.");
257            break;
258    }
259
260    ALOGV("calling destroyComponentInstance");
261    OMX_ERRORTYPE err = master->destroyComponentInstance(
262            static_cast<OMX_COMPONENTTYPE *>(mHandle));
263    ALOGV("destroyComponentInstance returned err %d", err);
264
265    mHandle = NULL;
266
267    if (err != OMX_ErrorNone) {
268        ALOGE("FreeHandle FAILED with error 0x%08x.", err);
269    }
270
271    mOwner->invalidateNodeID(mNodeID);
272    mNodeID = 0;
273
274    ALOGV("OMXNodeInstance going away.");
275    delete this;
276
277    return StatusFromOMXError(err);
278}
279
280status_t OMXNodeInstance::sendCommand(
281        OMX_COMMANDTYPE cmd, OMX_S32 param) {
282    if (cmd == OMX_CommandStateSet && param != OMX_StateIdle) {
283        // We do not support returning from unloaded state, so there are no configurations past
284        // first StateSet command. However, OMXCodec supports meta configuration past Stateset:Idle.
285        mSailed = true;
286    }
287    const sp<GraphicBufferSource> bufferSource(getGraphicBufferSource());
288    if (bufferSource != NULL && cmd == OMX_CommandStateSet) {
289        if (param == OMX_StateIdle) {
290            // Initiating transition from Executing -> Idle
291            // ACodec is waiting for all buffers to be returned, do NOT
292            // submit any more buffers to the codec.
293            bufferSource->omxIdle();
294        } else if (param == OMX_StateLoaded) {
295            // Initiating transition from Idle/Executing -> Loaded
296            // Buffers are about to be freed.
297            bufferSource->omxLoaded();
298            setGraphicBufferSource(NULL);
299        }
300
301        // fall through
302    }
303
304    Mutex::Autolock autoLock(mLock);
305
306    OMX_ERRORTYPE err = OMX_SendCommand(mHandle, cmd, param, NULL);
307    return StatusFromOMXError(err);
308}
309
310bool OMXNodeInstance::isProhibitedIndex_l(OMX_INDEXTYPE index) {
311    // these extensions can only be used from OMXNodeInstance, not by clients directly.
312    static const char *restricted_extensions[] = {
313        "OMX.google.android.index.storeMetaDataInBuffers",
314        "OMX.google.android.index.prepareForAdaptivePlayback",
315        "OMX.google.android.index.configureVideoTunnelMode",
316        "OMX.google.android.index.useAndroidNativeBuffer2",
317        "OMX.google.android.index.useAndroidNativeBuffer",
318        "OMX.google.android.index.enableAndroidNativeBuffers",
319        "OMX.google.android.index.getAndroidNativeBufferUsage",
320    };
321
322    if ((index > OMX_IndexComponentStartUnused && index <= OMX_IndexParamStandardComponentRole)
323            || (index > OMX_IndexPortStartUnused && index <= OMX_IndexParamCompBufferSupplier)
324            || (index > OMX_IndexAudioStartUnused && index <= OMX_IndexConfigAudioChannelVolume)
325            || (index > OMX_IndexVideoStartUnused && index <= OMX_IndexConfigVideoNalSize)
326            || (index > OMX_IndexCommonStartUnused
327                    && index <= OMX_IndexConfigCommonTransitionEffect)
328            || (index > (OMX_INDEXTYPE)OMX_IndexExtAudioStartUnused
329                    && index <= (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAacPresentation)
330            || (index > (OMX_INDEXTYPE)OMX_IndexExtVideoStartUnused
331                    && index <= (OMX_INDEXTYPE)OMX_IndexParamSliceSegments)) {
332        return false;
333    }
334
335    if (!mQueriedProhibitedExtensions) {
336        for (size_t i = 0; i < NELEM(restricted_extensions); ++i) {
337            OMX_INDEXTYPE ext;
338            if (OMX_GetExtensionIndex(mHandle, (OMX_STRING)restricted_extensions[i], &ext) == OMX_ErrorNone) {
339                mProhibitedExtensions.add(ext);
340            }
341        }
342        mQueriedProhibitedExtensions = true;
343    }
344
345    return mProhibitedExtensions.indexOf(index) >= 0;
346}
347
348status_t OMXNodeInstance::getParameter(
349        OMX_INDEXTYPE index, void *params, size_t /* size */) {
350    Mutex::Autolock autoLock(mLock);
351
352    if (isProhibitedIndex_l(index)) {
353        android_errorWriteLog(0x534e4554, "29422020");
354        return BAD_INDEX;
355    }
356
357    OMX_ERRORTYPE err = OMX_GetParameter(mHandle, index, params);
358    ALOGE_IF(err != OMX_ErrorNone, "getParameter(%d) ERROR: %#x", index, err);
359    return StatusFromOMXError(err);
360}
361
362status_t OMXNodeInstance::setParameter(
363        OMX_INDEXTYPE index, const void *params, size_t /* size */) {
364    Mutex::Autolock autoLock(mLock);
365
366    if (isProhibitedIndex_l(index)) {
367        android_errorWriteLog(0x534e4554, "29422020");
368        return BAD_INDEX;
369    }
370
371    OMX_ERRORTYPE err = OMX_SetParameter(
372            mHandle, index, const_cast<void *>(params));
373    ALOGE_IF(err != OMX_ErrorNone, "setParameter(%d) ERROR: %#x", index, err);
374    return StatusFromOMXError(err);
375}
376
377status_t OMXNodeInstance::getConfig(
378        OMX_INDEXTYPE index, void *params, size_t /* size */) {
379    Mutex::Autolock autoLock(mLock);
380
381    if (isProhibitedIndex_l(index)) {
382        android_errorWriteLog(0x534e4554, "29422020");
383        return BAD_INDEX;
384    }
385
386    OMX_ERRORTYPE err = OMX_GetConfig(mHandle, index, params);
387    return StatusFromOMXError(err);
388}
389
390status_t OMXNodeInstance::setConfig(
391        OMX_INDEXTYPE index, const void *params, size_t /* size */) {
392    Mutex::Autolock autoLock(mLock);
393
394    if (isProhibitedIndex_l(index)) {
395        android_errorWriteLog(0x534e4554, "29422020");
396        return BAD_INDEX;
397    }
398
399    OMX_ERRORTYPE err = OMX_SetConfig(
400            mHandle, index, const_cast<void *>(params));
401
402    return StatusFromOMXError(err);
403}
404
405status_t OMXNodeInstance::getState(OMX_STATETYPE* state) {
406    Mutex::Autolock autoLock(mLock);
407
408    OMX_ERRORTYPE err = OMX_GetState(mHandle, state);
409
410    return StatusFromOMXError(err);
411}
412
413status_t OMXNodeInstance::enableGraphicBuffers(
414        OMX_U32 portIndex, OMX_BOOL enable) {
415    Mutex::Autolock autoLock(mLock);
416    OMX_STRING name = const_cast<OMX_STRING>(
417            "OMX.google.android.index.enableAndroidNativeBuffers");
418
419    OMX_INDEXTYPE index;
420    OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
421
422    if (err != OMX_ErrorNone) {
423        if (enable) {
424            ALOGE("OMX_GetExtensionIndex %s failed", name);
425        }
426
427        return StatusFromOMXError(err);
428    }
429
430    OMX_VERSIONTYPE ver;
431    ver.s.nVersionMajor = 1;
432    ver.s.nVersionMinor = 0;
433    ver.s.nRevision = 0;
434    ver.s.nStep = 0;
435    EnableAndroidNativeBuffersParams params = {
436        sizeof(EnableAndroidNativeBuffersParams), ver, portIndex, enable,
437    };
438
439    err = OMX_SetParameter(mHandle, index, &params);
440
441    if (err != OMX_ErrorNone) {
442        ALOGE("OMX_EnableAndroidNativeBuffers failed with error %d (0x%08x)",
443                err, err);
444
445        return UNKNOWN_ERROR;
446    }
447
448    return OK;
449}
450
451status_t OMXNodeInstance::getGraphicBufferUsage(
452        OMX_U32 portIndex, OMX_U32* usage) {
453    Mutex::Autolock autoLock(mLock);
454
455    OMX_INDEXTYPE index;
456    OMX_STRING name = const_cast<OMX_STRING>(
457            "OMX.google.android.index.getAndroidNativeBufferUsage");
458    OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
459
460    if (err != OMX_ErrorNone) {
461        ALOGE("OMX_GetExtensionIndex %s failed", name);
462
463        return StatusFromOMXError(err);
464    }
465
466    OMX_VERSIONTYPE ver;
467    ver.s.nVersionMajor = 1;
468    ver.s.nVersionMinor = 0;
469    ver.s.nRevision = 0;
470    ver.s.nStep = 0;
471    GetAndroidNativeBufferUsageParams params = {
472        sizeof(GetAndroidNativeBufferUsageParams), ver, portIndex, 0,
473    };
474
475    err = OMX_GetParameter(mHandle, index, &params);
476
477    if (err != OMX_ErrorNone) {
478        ALOGE("OMX_GetAndroidNativeBufferUsage failed with error %d (0x%08x)",
479                err, err);
480        return UNKNOWN_ERROR;
481    }
482
483    *usage = params.nUsage;
484
485    return OK;
486}
487
488status_t OMXNodeInstance::storeMetaDataInBuffers(
489        OMX_U32 portIndex,
490        OMX_BOOL enable) {
491    Mutex::Autolock autolock(mLock);
492    return storeMetaDataInBuffers_l(
493            portIndex, enable,
494            OMX_FALSE /* useGraphicBuffer */, NULL /* usingGraphicBufferInMetadata */);
495}
496
497status_t OMXNodeInstance::storeMetaDataInBuffers_l(
498        OMX_U32 portIndex,
499        OMX_BOOL enable,
500        OMX_BOOL useGraphicBuffer,
501        OMX_BOOL *usingGraphicBufferInMetadata) {
502    if (mSailed) {
503        android_errorWriteLog(0x534e4554, "29422020");
504        return INVALID_OPERATION;
505    }
506    if (portIndex != kPortIndexInput && portIndex != kPortIndexOutput) {
507        android_errorWriteLog(0x534e4554, "26324358");
508        return BAD_VALUE;
509    }
510
511    OMX_INDEXTYPE index;
512    OMX_STRING name = const_cast<OMX_STRING>(
513            "OMX.google.android.index.storeMetaDataInBuffers");
514
515    OMX_STRING graphicBufferName = const_cast<OMX_STRING>(
516            "OMX.google.android.index.storeGraphicBufferInMetaData");
517    if (usingGraphicBufferInMetadata == NULL) {
518        usingGraphicBufferInMetadata = &useGraphicBuffer;
519    }
520
521    OMX_ERRORTYPE err =
522        (useGraphicBuffer && portIndex == kPortIndexInput)
523                ? OMX_GetExtensionIndex(mHandle, graphicBufferName, &index)
524                : OMX_ErrorBadParameter;
525    if (err == OMX_ErrorNone) {
526        *usingGraphicBufferInMetadata = OMX_TRUE;
527    } else {
528        *usingGraphicBufferInMetadata = OMX_FALSE;
529        err = OMX_GetExtensionIndex(mHandle, name, &index);
530    }
531
532    if (err != OMX_ErrorNone) {
533        ALOGE("OMX_GetExtensionIndex %s failed", name);
534        return StatusFromOMXError(err);
535    }
536
537    StoreMetaDataInBuffersParams params;
538    memset(&params, 0, sizeof(params));
539    params.nSize = sizeof(params);
540
541    // Version: 1.0.0.0
542    params.nVersion.s.nVersionMajor = 1;
543
544    params.nPortIndex = portIndex;
545    params.bStoreMetaData = enable;
546    if ((err = OMX_SetParameter(mHandle, index, &params)) != OMX_ErrorNone) {
547        ALOGE("OMX_SetParameter() failed for StoreMetaDataInBuffers: 0x%08x", err);
548        *usingGraphicBufferInMetadata = OMX_FALSE;
549        if (enable) {
550            mUsingMetadata[portIndex] = false;
551        }
552        return UNKNOWN_ERROR;
553    } else {
554        mUsingMetadata[portIndex] = enable;
555    }
556    return err;
557}
558
559status_t OMXNodeInstance::prepareForAdaptivePlayback(
560        OMX_U32 portIndex, OMX_BOOL enable, OMX_U32 maxFrameWidth,
561        OMX_U32 maxFrameHeight) {
562    Mutex::Autolock autolock(mLock);
563    if (mSailed) {
564        android_errorWriteLog(0x534e4554, "29422020");
565        return INVALID_OPERATION;
566    }
567
568    OMX_INDEXTYPE index;
569    OMX_STRING name = const_cast<OMX_STRING>(
570            "OMX.google.android.index.prepareForAdaptivePlayback");
571
572    OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
573    if (err != OMX_ErrorNone) {
574        ALOGW_IF(enable, "OMX_GetExtensionIndex %s failed", name);
575        return StatusFromOMXError(err);
576    }
577
578    PrepareForAdaptivePlaybackParams params;
579    params.nSize = sizeof(params);
580    params.nVersion.s.nVersionMajor = 1;
581    params.nVersion.s.nVersionMinor = 0;
582    params.nVersion.s.nRevision = 0;
583    params.nVersion.s.nStep = 0;
584
585    params.nPortIndex = portIndex;
586    params.bEnable = enable;
587    params.nMaxFrameWidth = maxFrameWidth;
588    params.nMaxFrameHeight = maxFrameHeight;
589    if ((err = OMX_SetParameter(mHandle, index, &params)) != OMX_ErrorNone) {
590        ALOGW("OMX_SetParameter failed for PrepareForAdaptivePlayback "
591              "with error %d (0x%08x)", err, err);
592        return UNKNOWN_ERROR;
593    }
594    return err;
595}
596
597status_t OMXNodeInstance::configureVideoTunnelMode(
598        OMX_U32 portIndex, OMX_BOOL tunneled, OMX_U32 audioHwSync,
599        native_handle_t **sidebandHandle) {
600    Mutex::Autolock autolock(mLock);
601    if (mSailed) {
602        android_errorWriteLog(0x534e4554, "29422020");
603        return INVALID_OPERATION;
604    }
605
606    OMX_INDEXTYPE index;
607    OMX_STRING name = const_cast<OMX_STRING>(
608            "OMX.google.android.index.configureVideoTunnelMode");
609
610    OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
611    if (err != OMX_ErrorNone) {
612        ALOGE("configureVideoTunnelMode extension is missing!");
613        return StatusFromOMXError(err);
614    }
615
616    ConfigureVideoTunnelModeParams tunnelParams;
617    tunnelParams.nSize = sizeof(tunnelParams);
618    tunnelParams.nVersion.s.nVersionMajor = 1;
619    tunnelParams.nVersion.s.nVersionMinor = 0;
620    tunnelParams.nVersion.s.nRevision = 0;
621    tunnelParams.nVersion.s.nStep = 0;
622
623    tunnelParams.nPortIndex = portIndex;
624    tunnelParams.bTunneled = tunneled;
625    tunnelParams.nAudioHwSync = audioHwSync;
626    err = OMX_SetParameter(mHandle, index, &tunnelParams);
627    if (err != OMX_ErrorNone) {
628        ALOGE("configureVideoTunnelMode failed! (err %d).", err);
629        return UNKNOWN_ERROR;
630    }
631
632    err = OMX_GetParameter(mHandle, index, &tunnelParams);
633    if (err != OMX_ErrorNone) {
634        ALOGE("GetVideoTunnelWindow failed! (err %d).", err);
635        return UNKNOWN_ERROR;
636    }
637    if (sidebandHandle) {
638        *sidebandHandle = (native_handle_t*)tunnelParams.pSidebandWindow;
639    }
640
641    return err;
642}
643
644status_t OMXNodeInstance::useBuffer(
645        OMX_U32 portIndex, const sp<IMemory> &params,
646        OMX::buffer_id *buffer, OMX_BOOL crossProcess) {
647    Mutex::Autolock autoLock(mLock);
648    if (portIndex >= NELEM(mUsingMetadata)) {
649        return BAD_VALUE;
650    }
651    // We do not support metadata mode changes past buffer allocation
652    mSailed = true;
653
654    // metadata buffers are not connected cross process
655    BufferMeta *buffer_meta;
656    bool isMeta = mUsingMetadata[portIndex];
657    bool useBackup = crossProcess && isMeta; // use a backup buffer instead of the actual buffer
658    OMX_U8 *data = static_cast<OMX_U8 *>(params->pointer());
659    // allocate backup buffer
660    if (useBackup) {
661        data = new (std::nothrow) OMX_U8[params->size()];
662        if (data == NULL) {
663            return NO_MEMORY;
664        }
665        memset(data, 0, params->size());
666
667        buffer_meta = new BufferMeta(
668                params, portIndex, false /* copyToOmx */, false /* copyFromOmx */, data);
669    } else {
670        buffer_meta = new BufferMeta(
671                params, portIndex, false /* copyFromOmx */, false /* copyToOmx */, NULL);
672    }
673
674    OMX_BUFFERHEADERTYPE *header;
675
676    OMX_ERRORTYPE err = OMX_UseBuffer(
677            mHandle, &header, portIndex, buffer_meta,
678            params->size(), data);
679
680    if (err != OMX_ErrorNone) {
681        ALOGE("OMX_UseBuffer failed with error %d (0x%08x)", err, err);
682
683        delete buffer_meta;
684        buffer_meta = NULL;
685
686        *buffer = 0;
687
688        return UNKNOWN_ERROR;
689    }
690
691    CHECK_EQ(header->pAppPrivate, buffer_meta);
692
693    *buffer = makeBufferID(header);
694
695    addActiveBuffer(portIndex, *buffer);
696
697    sp<GraphicBufferSource> bufferSource(getGraphicBufferSource());
698    if (bufferSource != NULL && portIndex == kPortIndexInput) {
699        bufferSource->addCodecBuffer(header);
700    }
701
702    return OK;
703}
704
705status_t OMXNodeInstance::useGraphicBuffer2_l(
706        OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer,
707        OMX::buffer_id *buffer) {
708
709    // port definition
710    OMX_PARAM_PORTDEFINITIONTYPE def;
711    def.nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
712    def.nVersion.s.nVersionMajor = 1;
713    def.nVersion.s.nVersionMinor = 0;
714    def.nVersion.s.nRevision = 0;
715    def.nVersion.s.nStep = 0;
716    def.nPortIndex = portIndex;
717    OMX_ERRORTYPE err = OMX_GetParameter(mHandle, OMX_IndexParamPortDefinition, &def);
718    if (err != OMX_ErrorNone)
719    {
720        ALOGE("%s::%d:Error getting OMX_IndexParamPortDefinition", __FUNCTION__, __LINE__);
721        return err;
722    }
723
724    BufferMeta *bufferMeta = new BufferMeta(graphicBuffer, portIndex);
725
726    OMX_BUFFERHEADERTYPE *header = NULL;
727    OMX_U8* bufferHandle = const_cast<OMX_U8*>(
728            reinterpret_cast<const OMX_U8*>(graphicBuffer->handle));
729
730    err = OMX_UseBuffer(
731            mHandle,
732            &header,
733            portIndex,
734            bufferMeta,
735            def.nBufferSize,
736            bufferHandle);
737
738    if (err != OMX_ErrorNone) {
739        ALOGE("OMX_UseBuffer failed with error %d (0x%08x)", err, err);
740        delete bufferMeta;
741        bufferMeta = NULL;
742        *buffer = 0;
743        return UNKNOWN_ERROR;
744    }
745
746    CHECK_EQ(header->pBuffer, bufferHandle);
747    CHECK_EQ(header->pAppPrivate, bufferMeta);
748
749    *buffer = makeBufferID(header);
750
751    addActiveBuffer(portIndex, *buffer);
752
753    return OK;
754}
755
756// XXX: This function is here for backwards compatibility.  Once the OMX
757// implementations have been updated this can be removed and useGraphicBuffer2
758// can be renamed to useGraphicBuffer.
759status_t OMXNodeInstance::useGraphicBuffer(
760        OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer,
761        OMX::buffer_id *buffer) {
762    Mutex::Autolock autoLock(mLock);
763
764    // See if the newer version of the extension is present.
765    OMX_INDEXTYPE index;
766    if (OMX_GetExtensionIndex(
767            mHandle,
768            const_cast<OMX_STRING>("OMX.google.android.index.useAndroidNativeBuffer2"),
769            &index) == OMX_ErrorNone) {
770        return useGraphicBuffer2_l(portIndex, graphicBuffer, buffer);
771    }
772
773    OMX_STRING name = const_cast<OMX_STRING>(
774        "OMX.google.android.index.useAndroidNativeBuffer");
775    OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
776
777    if (err != OMX_ErrorNone) {
778        ALOGE("OMX_GetExtensionIndex %s failed", name);
779
780        return StatusFromOMXError(err);
781    }
782
783    BufferMeta *bufferMeta = new BufferMeta(graphicBuffer, portIndex);
784
785    OMX_BUFFERHEADERTYPE *header;
786
787    OMX_VERSIONTYPE ver;
788    ver.s.nVersionMajor = 1;
789    ver.s.nVersionMinor = 0;
790    ver.s.nRevision = 0;
791    ver.s.nStep = 0;
792    UseAndroidNativeBufferParams params = {
793        sizeof(UseAndroidNativeBufferParams), ver, portIndex, bufferMeta,
794        &header, graphicBuffer,
795    };
796
797    err = OMX_SetParameter(mHandle, index, &params);
798
799    if (err != OMX_ErrorNone) {
800        ALOGE("OMX_UseAndroidNativeBuffer failed with error %d (0x%08x)", err,
801                err);
802
803        delete bufferMeta;
804        bufferMeta = NULL;
805
806        *buffer = 0;
807
808        return UNKNOWN_ERROR;
809    }
810
811    CHECK_EQ(header->pAppPrivate, bufferMeta);
812
813    *buffer = makeBufferID(header);
814
815    addActiveBuffer(portIndex, *buffer);
816
817    return OK;
818}
819
820status_t OMXNodeInstance::updateGraphicBufferInMeta(
821        OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer,
822        OMX::buffer_id buffer) {
823    Mutex::Autolock autoLock(mLock);
824
825    OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer, portIndex);
826    if (header == NULL) {
827        return BAD_VALUE;
828    }
829    VideoDecoderOutputMetaData *metadata =
830        (VideoDecoderOutputMetaData *)(header->pBuffer);
831    BufferMeta *bufferMeta = (BufferMeta *)(header->pAppPrivate);
832    bufferMeta->setGraphicBuffer(graphicBuffer);
833    metadata->eType = kMetadataBufferTypeGrallocSource;
834    metadata->pHandle = graphicBuffer->handle;
835
836    return OK;
837}
838
839status_t OMXNodeInstance::createInputSurface(
840        OMX_U32 portIndex, sp<IGraphicBufferProducer> *bufferProducer) {
841    Mutex::Autolock autolock(mLock);
842    status_t err;
843
844    // only allow graphic source on input port, when there are no allocated buffers yet
845    if (portIndex != kPortIndexInput) {
846        android_errorWriteLog(0x534e4554, "29422020");
847        return BAD_VALUE;
848    } else if (mActiveBuffers.size() > 0) {
849        android_errorWriteLog(0x534e4554, "29422020");
850        return INVALID_OPERATION;
851    }
852
853    const sp<GraphicBufferSource> surfaceCheck = getGraphicBufferSource();
854    if (surfaceCheck != NULL) {
855        return ALREADY_EXISTS;
856    }
857
858    // Input buffers will hold meta-data (gralloc references).
859    OMX_BOOL usingGraphicBuffer = OMX_FALSE;
860    err = storeMetaDataInBuffers_l(
861            portIndex, OMX_TRUE,
862            OMX_TRUE /* useGraphicBuffer */, &usingGraphicBuffer);
863    if (err != OK) {
864        return err;
865    }
866
867    // Retrieve the width and height of the graphic buffer, set when the
868    // codec was configured.
869    OMX_PARAM_PORTDEFINITIONTYPE def;
870    def.nSize = sizeof(def);
871    def.nVersion.s.nVersionMajor = 1;
872    def.nVersion.s.nVersionMinor = 0;
873    def.nVersion.s.nRevision = 0;
874    def.nVersion.s.nStep = 0;
875    def.nPortIndex = portIndex;
876    OMX_ERRORTYPE oerr = OMX_GetParameter(
877            mHandle, OMX_IndexParamPortDefinition, &def);
878    CHECK(oerr == OMX_ErrorNone);
879
880    if (def.format.video.eColorFormat != OMX_COLOR_FormatAndroidOpaque) {
881        ALOGE("createInputSurface requires COLOR_FormatSurface "
882              "(AndroidOpaque) color format");
883        return INVALID_OPERATION;
884    }
885
886    GraphicBufferSource* bufferSource = new GraphicBufferSource(
887            this, def.format.video.nFrameWidth, def.format.video.nFrameHeight,
888            def.nBufferCountActual, usingGraphicBuffer);
889    if ((err = bufferSource->initCheck()) != OK) {
890        delete bufferSource;
891        return err;
892    }
893    setGraphicBufferSource(bufferSource);
894
895    *bufferProducer = bufferSource->getIGraphicBufferProducer();
896    return OK;
897}
898
899status_t OMXNodeInstance::signalEndOfInputStream() {
900    // For non-Surface input, the MediaCodec should convert the call to a
901    // pair of requests (dequeue input buffer, queue input buffer with EOS
902    // flag set).  Seems easier than doing the equivalent from here.
903    sp<GraphicBufferSource> bufferSource(getGraphicBufferSource());
904    if (bufferSource == NULL) {
905        ALOGW("signalEndOfInputStream can only be used with Surface input");
906        return INVALID_OPERATION;
907    };
908    return bufferSource->signalEndOfInputStream();
909}
910
911status_t OMXNodeInstance::allocateBuffer(
912        OMX_U32 portIndex, size_t size, OMX::buffer_id *buffer,
913        void **buffer_data) {
914    Mutex::Autolock autoLock(mLock);
915    // We do not support metadata mode changes past buffer allocation
916    mSailed = true;
917
918    BufferMeta *buffer_meta = new BufferMeta(size, portIndex);
919
920    OMX_BUFFERHEADERTYPE *header;
921
922    OMX_ERRORTYPE err = OMX_AllocateBuffer(
923            mHandle, &header, portIndex, buffer_meta, size);
924
925    if (err != OMX_ErrorNone) {
926        ALOGE("OMX_AllocateBuffer failed with error %d (0x%08x)", err, err);
927
928        delete buffer_meta;
929        buffer_meta = NULL;
930
931        *buffer = 0;
932
933        return UNKNOWN_ERROR;
934    }
935
936    CHECK_EQ(header->pAppPrivate, buffer_meta);
937
938    *buffer = makeBufferID(header);
939    *buffer_data = header->pBuffer;
940
941    addActiveBuffer(portIndex, *buffer);
942
943    sp<GraphicBufferSource> bufferSource(getGraphicBufferSource());
944    if (bufferSource != NULL && portIndex == kPortIndexInput) {
945        bufferSource->addCodecBuffer(header);
946    }
947
948    return OK;
949}
950
951status_t OMXNodeInstance::allocateBufferWithBackup(
952        OMX_U32 portIndex, const sp<IMemory> &params,
953        OMX::buffer_id *buffer, OMX_BOOL crossProcess) {
954    Mutex::Autolock autoLock(mLock);
955    if (portIndex >= NELEM(mUsingMetadata)) {
956        return BAD_VALUE;
957    }
958    // We do not support metadata mode changes past buffer allocation
959    mSailed = true;
960
961    // metadata buffers are not connected cross process
962    bool isMeta = mUsingMetadata[portIndex];
963    bool copy = !(crossProcess && isMeta);
964
965    BufferMeta *buffer_meta = new BufferMeta(
966            params, portIndex,
967            (portIndex == kPortIndexInput) && copy /* copyToOmx */,
968            (portIndex == kPortIndexOutput) && copy /* copyFromOmx */,
969            NULL /* data */);
970
971    OMX_BUFFERHEADERTYPE *header;
972
973    OMX_ERRORTYPE err = OMX_AllocateBuffer(
974            mHandle, &header, portIndex, buffer_meta, params->size());
975
976    if (err != OMX_ErrorNone) {
977        ALOGE("OMX_AllocateBuffer failed with error %d (0x%08x)", err, err);
978
979        delete buffer_meta;
980        buffer_meta = NULL;
981
982        *buffer = 0;
983
984        return UNKNOWN_ERROR;
985    }
986
987    CHECK_EQ(header->pAppPrivate, buffer_meta);
988    memset(header->pBuffer, 0, header->nAllocLen);
989
990    *buffer = makeBufferID(header);
991
992    addActiveBuffer(portIndex, *buffer);
993
994    sp<GraphicBufferSource> bufferSource(getGraphicBufferSource());
995    if (bufferSource != NULL && portIndex == kPortIndexInput) {
996        bufferSource->addCodecBuffer(header);
997    }
998
999    return OK;
1000}
1001
1002status_t OMXNodeInstance::freeBuffer(
1003        OMX_U32 portIndex, OMX::buffer_id buffer) {
1004    Mutex::Autolock autoLock(mLock);
1005
1006    removeActiveBuffer(portIndex, buffer);
1007
1008    OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer, portIndex);
1009    if (header == NULL) {
1010        return BAD_VALUE;
1011    }
1012    BufferMeta *buffer_meta = static_cast<BufferMeta *>(header->pAppPrivate);
1013
1014    OMX_ERRORTYPE err = OMX_FreeBuffer(mHandle, portIndex, header);
1015
1016    delete buffer_meta;
1017    buffer_meta = NULL;
1018    invalidateBufferID(buffer);
1019
1020    return StatusFromOMXError(err);
1021}
1022
1023status_t OMXNodeInstance::fillBuffer(OMX::buffer_id buffer) {
1024    Mutex::Autolock autoLock(mLock);
1025
1026    OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer, kPortIndexOutput);
1027    if (header == NULL) {
1028        return BAD_VALUE;
1029    }
1030    header->nFilledLen = 0;
1031    header->nOffset = 0;
1032    header->nFlags = 0;
1033
1034    OMX_ERRORTYPE err = OMX_FillThisBuffer(mHandle, header);
1035
1036    return StatusFromOMXError(err);
1037}
1038
1039status_t OMXNodeInstance::emptyBuffer(
1040        OMX::buffer_id buffer,
1041        OMX_U32 rangeOffset, OMX_U32 rangeLength,
1042        OMX_U32 flags, OMX_TICKS timestamp) {
1043    Mutex::Autolock autoLock(mLock);
1044
1045    // no emptybuffer if using input surface
1046    if (getGraphicBufferSource() != NULL) {
1047        android_errorWriteLog(0x534e4554, "29422020");
1048        return INVALID_OPERATION;
1049    }
1050
1051    OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer, kPortIndexInput);
1052    // rangeLength and rangeOffset must be a subset of the allocated data in the buffer.
1053    // corner case: we permit rangeOffset == end-of-buffer with rangeLength == 0.
1054    if (header == NULL
1055            || rangeOffset > header->nAllocLen
1056            || rangeLength > header->nAllocLen - rangeOffset) {
1057        return BAD_VALUE;
1058    }
1059    header->nFilledLen = rangeLength;
1060    header->nOffset = rangeOffset;
1061    header->nFlags = flags;
1062    header->nTimeStamp = timestamp;
1063
1064    BufferMeta *buffer_meta =
1065        static_cast<BufferMeta *>(header->pAppPrivate);
1066    buffer_meta->CopyToOMX(header);
1067
1068    OMX_ERRORTYPE err = OMX_EmptyThisBuffer(mHandle, header);
1069
1070    return StatusFromOMXError(err);
1071}
1072
1073// like emptyBuffer, but the data is already in header->pBuffer
1074status_t OMXNodeInstance::emptyDirectBuffer(
1075        OMX_BUFFERHEADERTYPE *header,
1076        OMX_U32 rangeOffset, OMX_U32 rangeLength,
1077        OMX_U32 flags, OMX_TICKS timestamp) {
1078    Mutex::Autolock autoLock(mLock);
1079
1080    header->nFilledLen = rangeLength;
1081    header->nOffset = rangeOffset;
1082    header->nFlags = flags;
1083    header->nTimeStamp = timestamp;
1084
1085    OMX_ERRORTYPE err = OMX_EmptyThisBuffer(mHandle, header);
1086    if (err != OMX_ErrorNone) {
1087        ALOGW("emptyDirectBuffer failed, OMX err=0x%x", err);
1088    }
1089
1090    return StatusFromOMXError(err);
1091}
1092
1093status_t OMXNodeInstance::getExtensionIndex(
1094        const char *parameterName, OMX_INDEXTYPE *index) {
1095    Mutex::Autolock autoLock(mLock);
1096
1097    OMX_ERRORTYPE err = OMX_GetExtensionIndex(
1098            mHandle, const_cast<char *>(parameterName), index);
1099
1100    return StatusFromOMXError(err);
1101}
1102
1103status_t OMXNodeInstance::setInternalOption(
1104        OMX_U32 portIndex,
1105        IOMX::InternalOptionType type,
1106        const void *data,
1107        size_t size) {
1108    switch (type) {
1109        case IOMX::INTERNAL_OPTION_SUSPEND:
1110        case IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY:
1111        case IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP:
1112        case IOMX::INTERNAL_OPTION_START_TIME:
1113        case IOMX::INTERNAL_OPTION_TIME_LAPSE:
1114        {
1115            const sp<GraphicBufferSource> &bufferSource =
1116                getGraphicBufferSource();
1117
1118            if (bufferSource == NULL || portIndex != kPortIndexInput) {
1119                return ERROR_UNSUPPORTED;
1120            }
1121
1122            if (type == IOMX::INTERNAL_OPTION_SUSPEND) {
1123                if (size != sizeof(bool)) {
1124                    return INVALID_OPERATION;
1125                }
1126
1127                bool suspend = *(bool *)data;
1128                bufferSource->suspend(suspend);
1129            } else if (type ==
1130                    IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY){
1131                if (size != sizeof(int64_t)) {
1132                    return INVALID_OPERATION;
1133                }
1134
1135                int64_t delayUs = *(int64_t *)data;
1136
1137                return bufferSource->setRepeatPreviousFrameDelayUs(delayUs);
1138            } else if (type ==
1139                    IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP){
1140                if (size != sizeof(int64_t)) {
1141                    return INVALID_OPERATION;
1142                }
1143
1144                int64_t maxGapUs = *(int64_t *)data;
1145
1146                return bufferSource->setMaxTimestampGapUs(maxGapUs);
1147            } else if (type == IOMX::INTERNAL_OPTION_START_TIME) {
1148                if (size != sizeof(int64_t)) {
1149                    return INVALID_OPERATION;
1150                }
1151
1152                int64_t skipFramesBeforeUs = *(int64_t *)data;
1153
1154                bufferSource->setSkipFramesBeforeUs(skipFramesBeforeUs);
1155            } else { // IOMX::INTERNAL_OPTION_TIME_LAPSE
1156                if (size != sizeof(int64_t) * 2) {
1157                    return INVALID_OPERATION;
1158                }
1159
1160                bufferSource->setTimeLapseUs((int64_t *)data);
1161            }
1162
1163            return OK;
1164        }
1165
1166        default:
1167            return ERROR_UNSUPPORTED;
1168    }
1169}
1170
1171void OMXNodeInstance::onMessage(const omx_message &msg) {
1172    const sp<GraphicBufferSource>& bufferSource(getGraphicBufferSource());
1173
1174    if (msg.type == omx_message::FILL_BUFFER_DONE) {
1175        OMX_BUFFERHEADERTYPE *buffer =
1176            findBufferHeader(msg.u.extended_buffer_data.buffer, kPortIndexOutput);
1177        if (buffer == NULL) {
1178            return;
1179        }
1180
1181        BufferMeta *buffer_meta =
1182            static_cast<BufferMeta *>(buffer->pAppPrivate);
1183
1184        buffer_meta->CopyFromOMX(buffer);
1185
1186        if (bufferSource != NULL) {
1187            // fix up the buffer info (especially timestamp) if needed
1188            bufferSource->codecBufferFilled(buffer);
1189
1190            omx_message newMsg = msg;
1191            newMsg.u.extended_buffer_data.timestamp = buffer->nTimeStamp;
1192            mObserver->onMessage(newMsg);
1193            return;
1194        }
1195    } else if (msg.type == omx_message::EMPTY_BUFFER_DONE) {
1196        if (bufferSource != NULL) {
1197            // This is one of the buffers used exclusively by
1198            // GraphicBufferSource.
1199            // Don't dispatch a message back to ACodec, since it doesn't
1200            // know that anyone asked to have the buffer emptied and will
1201            // be very confused.
1202
1203            OMX_BUFFERHEADERTYPE *buffer =
1204                findBufferHeader(msg.u.buffer_data.buffer, kPortIndexInput);
1205            if (buffer == NULL) {
1206                return;
1207            }
1208
1209            bufferSource->codecBufferEmptied(buffer);
1210            return;
1211        }
1212    }
1213
1214    mObserver->onMessage(msg);
1215}
1216
1217void OMXNodeInstance::onObserverDied(OMXMaster *master) {
1218    ALOGE("!!! Observer died. Quickly, do something, ... anything...");
1219
1220    // Try to force shutdown of the node and hope for the best.
1221    freeNode(master);
1222}
1223
1224void OMXNodeInstance::onGetHandleFailed() {
1225    delete this;
1226}
1227
1228// OMXNodeInstance::OnEvent calls OMX::OnEvent, which then calls here.
1229// Don't try to acquire mLock here -- in rare circumstances this will hang.
1230void OMXNodeInstance::onEvent(
1231        OMX_EVENTTYPE event, OMX_U32 arg1, OMX_U32 arg2) {
1232    const sp<GraphicBufferSource>& bufferSource(getGraphicBufferSource());
1233
1234    if (bufferSource != NULL
1235            && event == OMX_EventCmdComplete
1236            && arg1 == OMX_CommandStateSet
1237            && arg2 == OMX_StateExecuting) {
1238        bufferSource->omxExecuting();
1239    }
1240}
1241
1242// static
1243OMX_ERRORTYPE OMXNodeInstance::OnEvent(
1244        OMX_IN OMX_HANDLETYPE /* hComponent */,
1245        OMX_IN OMX_PTR pAppData,
1246        OMX_IN OMX_EVENTTYPE eEvent,
1247        OMX_IN OMX_U32 nData1,
1248        OMX_IN OMX_U32 nData2,
1249        OMX_IN OMX_PTR pEventData) {
1250    OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
1251    if (instance->mDying) {
1252        return OMX_ErrorNone;
1253    }
1254    return instance->owner()->OnEvent(
1255            instance->nodeID(), eEvent, nData1, nData2, pEventData);
1256}
1257
1258// static
1259OMX_ERRORTYPE OMXNodeInstance::OnEmptyBufferDone(
1260        OMX_IN OMX_HANDLETYPE /* hComponent */,
1261        OMX_IN OMX_PTR pAppData,
1262        OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) {
1263    OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
1264    if (instance->mDying) {
1265        return OMX_ErrorNone;
1266    }
1267    return instance->owner()->OnEmptyBufferDone(instance->nodeID(),
1268            instance->findBufferID(pBuffer), pBuffer);
1269}
1270
1271// static
1272OMX_ERRORTYPE OMXNodeInstance::OnFillBufferDone(
1273        OMX_IN OMX_HANDLETYPE /* hComponent */,
1274        OMX_IN OMX_PTR pAppData,
1275        OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) {
1276    OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
1277    if (instance->mDying) {
1278        return OMX_ErrorNone;
1279    }
1280    return instance->owner()->OnFillBufferDone(instance->nodeID(),
1281            instance->findBufferID(pBuffer), pBuffer);
1282}
1283
1284void OMXNodeInstance::addActiveBuffer(OMX_U32 portIndex, OMX::buffer_id id) {
1285    ActiveBuffer active;
1286    active.mPortIndex = portIndex;
1287    active.mID = id;
1288    mActiveBuffers.push(active);
1289}
1290
1291void OMXNodeInstance::removeActiveBuffer(
1292        OMX_U32 portIndex, OMX::buffer_id id) {
1293    bool found = false;
1294    for (size_t i = 0; i < mActiveBuffers.size(); ++i) {
1295        if (mActiveBuffers[i].mPortIndex == portIndex
1296            && mActiveBuffers[i].mID == id) {
1297            found = true;
1298            mActiveBuffers.removeItemsAt(i);
1299            break;
1300        }
1301    }
1302
1303    if (!found) {
1304        ALOGW("Attempt to remove an active buffer we know nothing about...");
1305    }
1306}
1307
1308void OMXNodeInstance::freeActiveBuffers() {
1309    // Make sure to count down here, as freeBuffer will in turn remove
1310    // the active buffer from the vector...
1311    for (size_t i = mActiveBuffers.size(); i--;) {
1312        freeBuffer(mActiveBuffers[i].mPortIndex, mActiveBuffers[i].mID);
1313    }
1314}
1315
1316OMX::buffer_id OMXNodeInstance::makeBufferID(OMX_BUFFERHEADERTYPE *bufferHeader) {
1317    if (bufferHeader == NULL) {
1318        return 0;
1319    }
1320    Mutex::Autolock autoLock(mBufferIDLock);
1321    OMX::buffer_id buffer;
1322    do { // handle the very unlikely case of ID overflow
1323        if (++mBufferIDCount == 0) {
1324           ++mBufferIDCount;
1325        }
1326        buffer = (OMX::buffer_id)mBufferIDCount;
1327    } while (mBufferIDToBufferHeader.indexOfKey(buffer) >= 0);
1328    mBufferIDToBufferHeader.add(buffer, bufferHeader);
1329    mBufferHeaderToBufferID.add(bufferHeader, buffer);
1330    return buffer;
1331}
1332
1333OMX_BUFFERHEADERTYPE *OMXNodeInstance::findBufferHeader(
1334        OMX::buffer_id buffer, OMX_U32 portIndex) {
1335    if (buffer == 0) {
1336        return NULL;
1337    }
1338    Mutex::Autolock autoLock(mBufferIDLock);
1339    ssize_t index = mBufferIDToBufferHeader.indexOfKey(buffer);
1340    if (index < 0) {
1341        ALOGW("findBufferHeader: buffer %u not found", buffer);
1342        return NULL;
1343    }
1344    OMX_BUFFERHEADERTYPE *header = mBufferIDToBufferHeader.valueAt(index);
1345    BufferMeta *buffer_meta =
1346        static_cast<BufferMeta *>(header->pAppPrivate);
1347    if (buffer_meta->getPortIndex() != portIndex) {
1348        ALOGW("findBufferHeader: buffer %u found but with incorrect port index.", buffer);
1349        android_errorWriteLog(0x534e4554, "28816827");
1350        return NULL;
1351    }
1352    return header;
1353}
1354
1355OMX::buffer_id OMXNodeInstance::findBufferID(OMX_BUFFERHEADERTYPE *bufferHeader) {
1356    if (bufferHeader == NULL) {
1357        return 0;
1358    }
1359    Mutex::Autolock autoLock(mBufferIDLock);
1360    return mBufferHeaderToBufferID.valueFor(bufferHeader);
1361}
1362
1363void OMXNodeInstance::invalidateBufferID(OMX::buffer_id buffer) {
1364    if (buffer == 0) {
1365        return;
1366    }
1367    Mutex::Autolock autoLock(mBufferIDLock);
1368    mBufferHeaderToBufferID.removeItem(mBufferIDToBufferHeader.valueFor(buffer));
1369    mBufferIDToBufferHeader.removeItem(buffer);
1370}
1371
1372}  // namespace android
1373