OMXNodeInstance.cpp revision 0c37f9d1320bb87fd242f9425c67dacd6ce20112
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
296    OMX_INDEXTYPE index;
297    OMX_ERRORTYPE err = OMX_GetExtensionIndex(
298            mHandle,
299            const_cast<OMX_STRING>("OMX.google.android.index.enableAndroidNativeBuffers"),
300            &index);
301
302    if (err != OMX_ErrorNone) {
303        ALOGE("OMX_GetExtensionIndex failed");
304
305        return StatusFromOMXError(err);
306    }
307
308    OMX_VERSIONTYPE ver;
309    ver.s.nVersionMajor = 1;
310    ver.s.nVersionMinor = 0;
311    ver.s.nRevision = 0;
312    ver.s.nStep = 0;
313    EnableAndroidNativeBuffersParams params = {
314        sizeof(EnableAndroidNativeBuffersParams), ver, portIndex, enable,
315    };
316
317    err = OMX_SetParameter(mHandle, index, &params);
318
319    if (err != OMX_ErrorNone) {
320        ALOGE("OMX_EnableAndroidNativeBuffers failed with error %d (0x%08x)",
321                err, err);
322
323        return UNKNOWN_ERROR;
324    }
325
326    return OK;
327}
328
329status_t OMXNodeInstance::getGraphicBufferUsage(
330        OMX_U32 portIndex, OMX_U32* usage) {
331    Mutex::Autolock autoLock(mLock);
332
333    OMX_INDEXTYPE index;
334    OMX_ERRORTYPE err = OMX_GetExtensionIndex(
335            mHandle,
336            const_cast<OMX_STRING>(
337                    "OMX.google.android.index.getAndroidNativeBufferUsage"),
338            &index);
339
340    if (err != OMX_ErrorNone) {
341        ALOGE("OMX_GetExtensionIndex failed");
342
343        return StatusFromOMXError(err);
344    }
345
346    OMX_VERSIONTYPE ver;
347    ver.s.nVersionMajor = 1;
348    ver.s.nVersionMinor = 0;
349    ver.s.nRevision = 0;
350    ver.s.nStep = 0;
351    GetAndroidNativeBufferUsageParams params = {
352        sizeof(GetAndroidNativeBufferUsageParams), ver, portIndex, 0,
353    };
354
355    err = OMX_GetParameter(mHandle, index, &params);
356
357    if (err != OMX_ErrorNone) {
358        ALOGE("OMX_GetAndroidNativeBufferUsage failed with error %d (0x%08x)",
359                err, err);
360        return UNKNOWN_ERROR;
361    }
362
363    *usage = params.nUsage;
364
365    return OK;
366}
367
368status_t OMXNodeInstance::storeMetaDataInBuffers(
369        OMX_U32 portIndex,
370        OMX_BOOL enable) {
371    Mutex::Autolock autolock(mLock);
372    return storeMetaDataInBuffers_l(portIndex, enable);
373}
374
375status_t OMXNodeInstance::storeMetaDataInBuffers_l(
376        OMX_U32 portIndex,
377        OMX_BOOL enable) {
378    OMX_INDEXTYPE index;
379    OMX_STRING name = const_cast<OMX_STRING>(
380            "OMX.google.android.index.storeMetaDataInBuffers");
381
382    OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
383    if (err != OMX_ErrorNone) {
384        ALOGE("OMX_GetExtensionIndex %s failed", name);
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_ERRORTYPE err = OMX_GetExtensionIndex(
511            mHandle,
512            const_cast<OMX_STRING>("OMX.google.android.index.useAndroidNativeBuffer"),
513            &index);
514
515    if (err != OMX_ErrorNone) {
516        ALOGE("OMX_GetExtensionIndex failed");
517
518        return StatusFromOMXError(err);
519    }
520
521    BufferMeta *bufferMeta = new BufferMeta(graphicBuffer);
522
523    OMX_BUFFERHEADERTYPE *header;
524
525    OMX_VERSIONTYPE ver;
526    ver.s.nVersionMajor = 1;
527    ver.s.nVersionMinor = 0;
528    ver.s.nRevision = 0;
529    ver.s.nStep = 0;
530    UseAndroidNativeBufferParams params = {
531        sizeof(UseAndroidNativeBufferParams), ver, portIndex, bufferMeta,
532        &header, graphicBuffer,
533    };
534
535    err = OMX_SetParameter(mHandle, index, &params);
536
537    if (err != OMX_ErrorNone) {
538        ALOGE("OMX_UseAndroidNativeBuffer failed with error %d (0x%08x)", err,
539                err);
540
541        delete bufferMeta;
542        bufferMeta = NULL;
543
544        *buffer = 0;
545
546        return UNKNOWN_ERROR;
547    }
548
549    CHECK_EQ(header->pAppPrivate, bufferMeta);
550
551    *buffer = header;
552
553    addActiveBuffer(portIndex, *buffer);
554
555    return OK;
556}
557
558status_t OMXNodeInstance::createInputSurface(
559        OMX_U32 portIndex, sp<IGraphicBufferProducer> *bufferProducer) {
560    Mutex::Autolock autolock(mLock);
561    status_t err;
562
563    const sp<GraphicBufferSource>& surfaceCheck = getGraphicBufferSource();
564    if (surfaceCheck != NULL) {
565        return ALREADY_EXISTS;
566    }
567
568    // Input buffers will hold meta-data (gralloc references).
569    err = storeMetaDataInBuffers_l(portIndex, OMX_TRUE);
570    if (err != OK) {
571        return err;
572    }
573
574    // Retrieve the width and height of the graphic buffer, set when the
575    // codec was configured.
576    OMX_PARAM_PORTDEFINITIONTYPE def;
577    def.nSize = sizeof(def);
578    def.nVersion.s.nVersionMajor = 1;
579    def.nVersion.s.nVersionMinor = 0;
580    def.nVersion.s.nRevision = 0;
581    def.nVersion.s.nStep = 0;
582    def.nPortIndex = portIndex;
583    OMX_ERRORTYPE oerr = OMX_GetParameter(
584            mHandle, OMX_IndexParamPortDefinition, &def);
585    CHECK(oerr == OMX_ErrorNone);
586
587    if (def.format.video.eColorFormat != OMX_COLOR_FormatAndroidOpaque) {
588        ALOGE("createInputSurface requires AndroidOpaque color format");
589        return INVALID_OPERATION;
590    }
591
592    GraphicBufferSource* bufferSource = new GraphicBufferSource(
593            this, def.format.video.nFrameWidth, def.format.video.nFrameHeight,
594            def.nBufferCountActual);
595    if ((err = bufferSource->initCheck()) != OK) {
596        delete bufferSource;
597        return err;
598    }
599    setGraphicBufferSource(bufferSource);
600
601    *bufferProducer = bufferSource->getIGraphicBufferProducer();
602    return OK;
603}
604
605status_t OMXNodeInstance::signalEndOfInputStream() {
606    // For non-Surface input, the MediaCodec should convert the call to a
607    // pair of requests (dequeue input buffer, queue input buffer with EOS
608    // flag set).  Seems easier than doing the equivalent from here.
609    sp<GraphicBufferSource> bufferSource(getGraphicBufferSource());
610    if (bufferSource == NULL) {
611        ALOGW("signalEndOfInputStream can only be used with Surface input");
612        return INVALID_OPERATION;
613    };
614    return bufferSource->signalEndOfInputStream();
615}
616
617status_t OMXNodeInstance::allocateBuffer(
618        OMX_U32 portIndex, size_t size, OMX::buffer_id *buffer,
619        void **buffer_data) {
620    Mutex::Autolock autoLock(mLock);
621
622    BufferMeta *buffer_meta = new BufferMeta(size);
623
624    OMX_BUFFERHEADERTYPE *header;
625
626    OMX_ERRORTYPE err = OMX_AllocateBuffer(
627            mHandle, &header, portIndex, buffer_meta, size);
628
629    if (err != OMX_ErrorNone) {
630        ALOGE("OMX_AllocateBuffer failed with error %d (0x%08x)", err, err);
631
632        delete buffer_meta;
633        buffer_meta = NULL;
634
635        *buffer = 0;
636
637        return UNKNOWN_ERROR;
638    }
639
640    CHECK_EQ(header->pAppPrivate, buffer_meta);
641
642    *buffer = header;
643    *buffer_data = header->pBuffer;
644
645    addActiveBuffer(portIndex, *buffer);
646
647    sp<GraphicBufferSource> bufferSource(getGraphicBufferSource());
648    if (bufferSource != NULL && portIndex == kPortIndexInput) {
649        bufferSource->addCodecBuffer(header);
650    }
651
652    return OK;
653}
654
655status_t OMXNodeInstance::allocateBufferWithBackup(
656        OMX_U32 portIndex, const sp<IMemory> &params,
657        OMX::buffer_id *buffer) {
658    Mutex::Autolock autoLock(mLock);
659
660    BufferMeta *buffer_meta = new BufferMeta(params, true);
661
662    OMX_BUFFERHEADERTYPE *header;
663
664    OMX_ERRORTYPE err = OMX_AllocateBuffer(
665            mHandle, &header, portIndex, buffer_meta, params->size());
666
667    if (err != OMX_ErrorNone) {
668        ALOGE("OMX_AllocateBuffer failed with error %d (0x%08x)", err, err);
669
670        delete buffer_meta;
671        buffer_meta = NULL;
672
673        *buffer = 0;
674
675        return UNKNOWN_ERROR;
676    }
677
678    CHECK_EQ(header->pAppPrivate, buffer_meta);
679
680    *buffer = header;
681
682    addActiveBuffer(portIndex, *buffer);
683
684    sp<GraphicBufferSource> bufferSource(getGraphicBufferSource());
685    if (bufferSource != NULL && portIndex == kPortIndexInput) {
686        bufferSource->addCodecBuffer(header);
687    }
688
689    return OK;
690}
691
692status_t OMXNodeInstance::freeBuffer(
693        OMX_U32 portIndex, OMX::buffer_id buffer) {
694    Mutex::Autolock autoLock(mLock);
695
696    removeActiveBuffer(portIndex, buffer);
697
698    OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer;
699    BufferMeta *buffer_meta = static_cast<BufferMeta *>(header->pAppPrivate);
700
701    OMX_ERRORTYPE err = OMX_FreeBuffer(mHandle, portIndex, header);
702
703    delete buffer_meta;
704    buffer_meta = NULL;
705
706    return StatusFromOMXError(err);
707}
708
709status_t OMXNodeInstance::fillBuffer(OMX::buffer_id buffer) {
710    Mutex::Autolock autoLock(mLock);
711
712    OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer;
713    header->nFilledLen = 0;
714    header->nOffset = 0;
715    header->nFlags = 0;
716
717    OMX_ERRORTYPE err = OMX_FillThisBuffer(mHandle, header);
718
719    return StatusFromOMXError(err);
720}
721
722status_t OMXNodeInstance::emptyBuffer(
723        OMX::buffer_id buffer,
724        OMX_U32 rangeOffset, OMX_U32 rangeLength,
725        OMX_U32 flags, OMX_TICKS timestamp) {
726    Mutex::Autolock autoLock(mLock);
727
728    OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer;
729    header->nFilledLen = rangeLength;
730    header->nOffset = rangeOffset;
731    header->nFlags = flags;
732    header->nTimeStamp = timestamp;
733
734    BufferMeta *buffer_meta =
735        static_cast<BufferMeta *>(header->pAppPrivate);
736    buffer_meta->CopyToOMX(header);
737
738    OMX_ERRORTYPE err = OMX_EmptyThisBuffer(mHandle, header);
739
740    return StatusFromOMXError(err);
741}
742
743// like emptyBuffer, but the data is already in header->pBuffer
744status_t OMXNodeInstance::emptyDirectBuffer(
745        OMX_BUFFERHEADERTYPE *header,
746        OMX_U32 rangeOffset, OMX_U32 rangeLength,
747        OMX_U32 flags, OMX_TICKS timestamp) {
748    Mutex::Autolock autoLock(mLock);
749
750    header->nFilledLen = rangeLength;
751    header->nOffset = rangeOffset;
752    header->nFlags = flags;
753    header->nTimeStamp = timestamp;
754
755    OMX_ERRORTYPE err = OMX_EmptyThisBuffer(mHandle, header);
756    if (err != OMX_ErrorNone) {
757        ALOGW("emptyDirectBuffer failed, OMX err=0x%x", err);
758    }
759
760    return StatusFromOMXError(err);
761}
762
763status_t OMXNodeInstance::getExtensionIndex(
764        const char *parameterName, OMX_INDEXTYPE *index) {
765    Mutex::Autolock autoLock(mLock);
766
767    OMX_ERRORTYPE err = OMX_GetExtensionIndex(
768            mHandle, const_cast<char *>(parameterName), index);
769
770    return StatusFromOMXError(err);
771}
772
773void OMXNodeInstance::onMessage(const omx_message &msg) {
774    if (msg.type == omx_message::FILL_BUFFER_DONE) {
775        OMX_BUFFERHEADERTYPE *buffer =
776            static_cast<OMX_BUFFERHEADERTYPE *>(
777                    msg.u.extended_buffer_data.buffer);
778
779        BufferMeta *buffer_meta =
780            static_cast<BufferMeta *>(buffer->pAppPrivate);
781
782        buffer_meta->CopyFromOMX(buffer);
783    }
784
785    mObserver->onMessage(msg);
786}
787
788void OMXNodeInstance::onObserverDied(OMXMaster *master) {
789    ALOGE("!!! Observer died. Quickly, do something, ... anything...");
790
791    // Try to force shutdown of the node and hope for the best.
792    freeNode(master);
793}
794
795void OMXNodeInstance::onGetHandleFailed() {
796    delete this;
797}
798
799// OMXNodeInstance::OnEvent calls OMX::OnEvent, which then calls here.
800// Don't try to acquire mLock here -- in rare circumstances this will hang.
801void OMXNodeInstance::onEvent(
802        OMX_EVENTTYPE event, OMX_U32 arg1, OMX_U32 arg2) {
803    const sp<GraphicBufferSource>& bufferSource(getGraphicBufferSource());
804
805    if (bufferSource != NULL && event == OMX_EventCmdComplete &&
806            arg1 == OMX_CommandStateSet) {
807        if (arg2 == OMX_StateExecuting) {
808            bufferSource->omxExecuting();
809        } else if (arg2 == OMX_StateLoaded) {
810            // Must be shutting down -- won't have a GraphicBufferSource
811            // on the way up.
812            bufferSource->omxLoaded();
813            setGraphicBufferSource(NULL);
814        }
815    }
816}
817
818// static
819OMX_ERRORTYPE OMXNodeInstance::OnEvent(
820        OMX_IN OMX_HANDLETYPE hComponent,
821        OMX_IN OMX_PTR pAppData,
822        OMX_IN OMX_EVENTTYPE eEvent,
823        OMX_IN OMX_U32 nData1,
824        OMX_IN OMX_U32 nData2,
825        OMX_IN OMX_PTR pEventData) {
826    OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
827    if (instance->mDying) {
828        return OMX_ErrorNone;
829    }
830    return instance->owner()->OnEvent(
831            instance->nodeID(), eEvent, nData1, nData2, pEventData);
832}
833
834// static
835OMX_ERRORTYPE OMXNodeInstance::OnEmptyBufferDone(
836        OMX_IN OMX_HANDLETYPE hComponent,
837        OMX_IN OMX_PTR pAppData,
838        OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) {
839    OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
840    if (instance->mDying) {
841        return OMX_ErrorNone;
842    }
843    const sp<GraphicBufferSource>& bufferSource(
844            instance->getGraphicBufferSource());
845    if (bufferSource != NULL) {
846        bufferSource->codecBufferEmptied(pBuffer);
847
848        // This is one of the buffers used exclusively by GraphicBufferSource.
849        // Don't dispatch a message back to ACodec, since it doesn't
850        // know that anyone asked to have the buffer emptied and will
851        // be very confused.
852        return OMX_ErrorNone;
853    }
854    return instance->owner()->OnEmptyBufferDone(instance->nodeID(), pBuffer);
855}
856
857// static
858OMX_ERRORTYPE OMXNodeInstance::OnFillBufferDone(
859        OMX_IN OMX_HANDLETYPE hComponent,
860        OMX_IN OMX_PTR pAppData,
861        OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) {
862    OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
863    if (instance->mDying) {
864        return OMX_ErrorNone;
865    }
866    return instance->owner()->OnFillBufferDone(instance->nodeID(), pBuffer);
867}
868
869void OMXNodeInstance::addActiveBuffer(OMX_U32 portIndex, OMX::buffer_id id) {
870    ActiveBuffer active;
871    active.mPortIndex = portIndex;
872    active.mID = id;
873    mActiveBuffers.push(active);
874}
875
876void OMXNodeInstance::removeActiveBuffer(
877        OMX_U32 portIndex, OMX::buffer_id id) {
878    bool found = false;
879    for (size_t i = 0; i < mActiveBuffers.size(); ++i) {
880        if (mActiveBuffers[i].mPortIndex == portIndex
881            && mActiveBuffers[i].mID == id) {
882            found = true;
883            mActiveBuffers.removeItemsAt(i);
884            break;
885        }
886    }
887
888    if (!found) {
889        ALOGW("Attempt to remove an active buffer we know nothing about...");
890    }
891}
892
893void OMXNodeInstance::freeActiveBuffers() {
894    // Make sure to count down here, as freeBuffer will in turn remove
895    // the active buffer from the vector...
896    for (size_t i = mActiveBuffers.size(); i--;) {
897        freeBuffer(mActiveBuffers[i].mPortIndex, mActiveBuffers[i].mID);
898    }
899}
900
901}  // namespace android
902