OMXNodeInstance.cpp revision f779bb50d9746d9526541c3e6dcdf619cac941b7
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    GraphicBufferSource* bufferSource = new GraphicBufferSource(
588            this, def.format.video.nFrameWidth, def.format.video.nFrameHeight);
589    if ((err = bufferSource->initCheck()) != OK) {
590        delete bufferSource;
591        return err;
592    }
593    setGraphicBufferSource(bufferSource);
594
595    *bufferProducer = bufferSource->getIGraphicBufferProducer();
596    return OK;
597}
598
599status_t OMXNodeInstance::signalEndOfInputStream() {
600    // For non-Surface input, the MediaCodec should convert the call to a
601    // pair of requests (dequeue input buffer, queue input buffer with EOS
602    // flag set).  Seems easier than doing the equivalent from here.
603    sp<GraphicBufferSource> bufferSource(getGraphicBufferSource());
604    if (bufferSource == NULL) {
605        ALOGW("signalEndOfInputStream should only be used with Surface input");
606        return INVALID_OPERATION;
607    };
608    bufferSource->signalEndOfInputStream();
609    return OK;
610}
611
612status_t OMXNodeInstance::allocateBuffer(
613        OMX_U32 portIndex, size_t size, OMX::buffer_id *buffer,
614        void **buffer_data) {
615    Mutex::Autolock autoLock(mLock);
616
617    BufferMeta *buffer_meta = new BufferMeta(size);
618
619    OMX_BUFFERHEADERTYPE *header;
620
621    OMX_ERRORTYPE err = OMX_AllocateBuffer(
622            mHandle, &header, portIndex, buffer_meta, size);
623
624    if (err != OMX_ErrorNone) {
625        ALOGE("OMX_AllocateBuffer failed with error %d (0x%08x)", err, err);
626
627        delete buffer_meta;
628        buffer_meta = NULL;
629
630        *buffer = 0;
631
632        return UNKNOWN_ERROR;
633    }
634
635    CHECK_EQ(header->pAppPrivate, buffer_meta);
636
637    *buffer = header;
638    *buffer_data = header->pBuffer;
639
640    addActiveBuffer(portIndex, *buffer);
641
642    sp<GraphicBufferSource> bufferSource(getGraphicBufferSource());
643    if (bufferSource != NULL && portIndex == kPortIndexInput) {
644        bufferSource->addCodecBuffer(header);
645    }
646
647    return OK;
648}
649
650status_t OMXNodeInstance::allocateBufferWithBackup(
651        OMX_U32 portIndex, const sp<IMemory> &params,
652        OMX::buffer_id *buffer) {
653    Mutex::Autolock autoLock(mLock);
654
655    BufferMeta *buffer_meta = new BufferMeta(params, true);
656
657    OMX_BUFFERHEADERTYPE *header;
658
659    OMX_ERRORTYPE err = OMX_AllocateBuffer(
660            mHandle, &header, portIndex, buffer_meta, params->size());
661
662    if (err != OMX_ErrorNone) {
663        ALOGE("OMX_AllocateBuffer failed with error %d (0x%08x)", err, err);
664
665        delete buffer_meta;
666        buffer_meta = NULL;
667
668        *buffer = 0;
669
670        return UNKNOWN_ERROR;
671    }
672
673    CHECK_EQ(header->pAppPrivate, buffer_meta);
674
675    *buffer = header;
676
677    addActiveBuffer(portIndex, *buffer);
678
679    sp<GraphicBufferSource> bufferSource(getGraphicBufferSource());
680    if (bufferSource != NULL && portIndex == kPortIndexInput) {
681        bufferSource->addCodecBuffer(header);
682    }
683
684    return OK;
685}
686
687status_t OMXNodeInstance::freeBuffer(
688        OMX_U32 portIndex, OMX::buffer_id buffer) {
689    Mutex::Autolock autoLock(mLock);
690
691    removeActiveBuffer(portIndex, buffer);
692
693    OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer;
694    BufferMeta *buffer_meta = static_cast<BufferMeta *>(header->pAppPrivate);
695
696    OMX_ERRORTYPE err = OMX_FreeBuffer(mHandle, portIndex, header);
697
698    delete buffer_meta;
699    buffer_meta = NULL;
700
701    return StatusFromOMXError(err);
702}
703
704status_t OMXNodeInstance::fillBuffer(OMX::buffer_id buffer) {
705    Mutex::Autolock autoLock(mLock);
706
707    OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer;
708    header->nFilledLen = 0;
709    header->nOffset = 0;
710    header->nFlags = 0;
711
712    OMX_ERRORTYPE err = OMX_FillThisBuffer(mHandle, header);
713
714    return StatusFromOMXError(err);
715}
716
717status_t OMXNodeInstance::emptyBuffer(
718        OMX::buffer_id buffer,
719        OMX_U32 rangeOffset, OMX_U32 rangeLength,
720        OMX_U32 flags, OMX_TICKS timestamp) {
721    Mutex::Autolock autoLock(mLock);
722
723    OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer;
724    header->nFilledLen = rangeLength;
725    header->nOffset = rangeOffset;
726    header->nFlags = flags;
727    header->nTimeStamp = timestamp;
728
729    BufferMeta *buffer_meta =
730        static_cast<BufferMeta *>(header->pAppPrivate);
731    buffer_meta->CopyToOMX(header);
732
733    OMX_ERRORTYPE err = OMX_EmptyThisBuffer(mHandle, header);
734
735    return StatusFromOMXError(err);
736}
737
738// like emptyBuffer, but the data is already in header->pBuffer
739status_t OMXNodeInstance::emptyDirectBuffer(
740        OMX_BUFFERHEADERTYPE *header,
741        OMX_U32 rangeOffset, OMX_U32 rangeLength,
742        OMX_U32 flags, OMX_TICKS timestamp) {
743    Mutex::Autolock autoLock(mLock);
744
745    header->nFilledLen = rangeLength;
746    header->nOffset = rangeOffset;
747    header->nFlags = flags;
748    header->nTimeStamp = timestamp;
749
750    OMX_ERRORTYPE err = OMX_EmptyThisBuffer(mHandle, header);
751    if (err != OMX_ErrorNone) {
752        ALOGW("emptyDirectBuffer failed, OMX err=0x%x", err);
753    }
754
755    return StatusFromOMXError(err);
756}
757
758status_t OMXNodeInstance::getExtensionIndex(
759        const char *parameterName, OMX_INDEXTYPE *index) {
760    Mutex::Autolock autoLock(mLock);
761
762    OMX_ERRORTYPE err = OMX_GetExtensionIndex(
763            mHandle, const_cast<char *>(parameterName), index);
764
765    return StatusFromOMXError(err);
766}
767
768void OMXNodeInstance::onMessage(const omx_message &msg) {
769    if (msg.type == omx_message::FILL_BUFFER_DONE) {
770        OMX_BUFFERHEADERTYPE *buffer =
771            static_cast<OMX_BUFFERHEADERTYPE *>(
772                    msg.u.extended_buffer_data.buffer);
773
774        BufferMeta *buffer_meta =
775            static_cast<BufferMeta *>(buffer->pAppPrivate);
776
777        buffer_meta->CopyFromOMX(buffer);
778    }
779
780    mObserver->onMessage(msg);
781}
782
783void OMXNodeInstance::onObserverDied(OMXMaster *master) {
784    ALOGE("!!! Observer died. Quickly, do something, ... anything...");
785
786    // Try to force shutdown of the node and hope for the best.
787    freeNode(master);
788}
789
790void OMXNodeInstance::onGetHandleFailed() {
791    delete this;
792}
793
794// OMXNodeInstance::OnEvent calls OMX::OnEvent, which then calls here.
795// Don't try to acquire mLock here -- in rare circumstances this will hang.
796void OMXNodeInstance::onEvent(
797        OMX_EVENTTYPE event, OMX_U32 arg1, OMX_U32 arg2) {
798    const sp<GraphicBufferSource>& bufferSource(getGraphicBufferSource());
799
800    if (bufferSource != NULL && event == OMX_EventCmdComplete &&
801            arg1 == OMX_CommandStateSet) {
802        if (arg2 == OMX_StateExecuting) {
803            bufferSource->omxExecuting();
804        } else if (arg2 == OMX_StateIdle) {
805            bufferSource->omxIdling();
806        }
807    }
808}
809
810// static
811OMX_ERRORTYPE OMXNodeInstance::OnEvent(
812        OMX_IN OMX_HANDLETYPE hComponent,
813        OMX_IN OMX_PTR pAppData,
814        OMX_IN OMX_EVENTTYPE eEvent,
815        OMX_IN OMX_U32 nData1,
816        OMX_IN OMX_U32 nData2,
817        OMX_IN OMX_PTR pEventData) {
818    OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
819    if (instance->mDying) {
820        return OMX_ErrorNone;
821    }
822    return instance->owner()->OnEvent(
823            instance->nodeID(), eEvent, nData1, nData2, pEventData);
824}
825
826// static
827OMX_ERRORTYPE OMXNodeInstance::OnEmptyBufferDone(
828        OMX_IN OMX_HANDLETYPE hComponent,
829        OMX_IN OMX_PTR pAppData,
830        OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) {
831    OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
832    if (instance->mDying) {
833        return OMX_ErrorNone;
834    }
835    const sp<GraphicBufferSource>& bufferSource(
836            instance->getGraphicBufferSource());
837    if (bufferSource != NULL) {
838        bufferSource->codecBufferEmptied(pBuffer);
839
840        // This is one of the buffers used exclusively by GraphicBufferSource.
841        // Don't dispatch a message back to ACodec, since it doesn't
842        // know that anyone asked to have the buffer emptied and will
843        // be very confused.
844        return OMX_ErrorNone;
845    }
846    return instance->owner()->OnEmptyBufferDone(instance->nodeID(), pBuffer);
847}
848
849// static
850OMX_ERRORTYPE OMXNodeInstance::OnFillBufferDone(
851        OMX_IN OMX_HANDLETYPE hComponent,
852        OMX_IN OMX_PTR pAppData,
853        OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) {
854    OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
855    if (instance->mDying) {
856        return OMX_ErrorNone;
857    }
858    return instance->owner()->OnFillBufferDone(instance->nodeID(), pBuffer);
859}
860
861void OMXNodeInstance::addActiveBuffer(OMX_U32 portIndex, OMX::buffer_id id) {
862    ActiveBuffer active;
863    active.mPortIndex = portIndex;
864    active.mID = id;
865    mActiveBuffers.push(active);
866}
867
868void OMXNodeInstance::removeActiveBuffer(
869        OMX_U32 portIndex, OMX::buffer_id id) {
870    bool found = false;
871    for (size_t i = 0; i < mActiveBuffers.size(); ++i) {
872        if (mActiveBuffers[i].mPortIndex == portIndex
873            && mActiveBuffers[i].mID == id) {
874            found = true;
875            mActiveBuffers.removeItemsAt(i);
876            break;
877        }
878    }
879
880    if (!found) {
881        ALOGW("Attempt to remove an active buffer we know nothing about...");
882    }
883}
884
885void OMXNodeInstance::freeActiveBuffers() {
886    // Make sure to count down here, as freeBuffer will in turn remove
887    // the active buffer from the vector...
888    for (size_t i = mActiveBuffers.size(); i--;) {
889        freeBuffer(mActiveBuffers[i].mPortIndex, mActiveBuffers[i].mID);
890    }
891}
892
893}  // namespace android
894