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