OMXNodeInstance.cpp revision 609b815a3131d22da38b2f452faa9f89daad4039
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
73    void setGraphicBuffer(const sp<GraphicBuffer> &graphicBuffer) {
74        mGraphicBuffer = graphicBuffer;
75    }
76
77private:
78    sp<GraphicBuffer> mGraphicBuffer;
79    sp<IMemory> mMem;
80    size_t mSize;
81    bool mIsBackup;
82
83    BufferMeta(const BufferMeta &);
84    BufferMeta &operator=(const BufferMeta &);
85};
86
87// static
88OMX_CALLBACKTYPE OMXNodeInstance::kCallbacks = {
89    &OnEvent, &OnEmptyBufferDone, &OnFillBufferDone
90};
91
92OMXNodeInstance::OMXNodeInstance(
93        OMX *owner, const sp<IOMXObserver> &observer)
94    : mOwner(owner),
95      mNodeID(0),
96      mHandle(NULL),
97      mObserver(observer),
98      mDying(false)
99#ifdef __LP64__
100      , mBufferIDCount(0)
101#endif
102{
103}
104
105OMXNodeInstance::~OMXNodeInstance() {
106    CHECK(mHandle == NULL);
107}
108
109void OMXNodeInstance::setHandle(OMX::node_id node_id, OMX_HANDLETYPE handle) {
110    CHECK(mHandle == NULL);
111    mNodeID = node_id;
112    mHandle = handle;
113}
114
115sp<GraphicBufferSource> OMXNodeInstance::getGraphicBufferSource() {
116    Mutex::Autolock autoLock(mGraphicBufferSourceLock);
117    return mGraphicBufferSource;
118}
119
120void OMXNodeInstance::setGraphicBufferSource(
121        const sp<GraphicBufferSource>& bufferSource) {
122    Mutex::Autolock autoLock(mGraphicBufferSourceLock);
123    mGraphicBufferSource = bufferSource;
124}
125
126OMX *OMXNodeInstance::owner() {
127    return mOwner;
128}
129
130sp<IOMXObserver> OMXNodeInstance::observer() {
131    return mObserver;
132}
133
134OMX::node_id OMXNodeInstance::nodeID() {
135    return mNodeID;
136}
137
138static status_t StatusFromOMXError(OMX_ERRORTYPE err) {
139    switch (err) {
140        case OMX_ErrorNone:
141            return OK;
142        case OMX_ErrorUnsupportedSetting:
143            return ERROR_UNSUPPORTED;
144        default:
145            return UNKNOWN_ERROR;
146    }
147}
148
149status_t OMXNodeInstance::freeNode(OMXMaster *master) {
150    static int32_t kMaxNumIterations = 10;
151
152    // Transition the node from its current state all the way down
153    // to "Loaded".
154    // This ensures that all active buffers are properly freed even
155    // for components that don't do this themselves on a call to
156    // "FreeHandle".
157
158    // The code below may trigger some more events to be dispatched
159    // by the OMX component - we want to ignore them as our client
160    // does not expect them.
161    mDying = true;
162
163    OMX_STATETYPE state;
164    CHECK_EQ(OMX_GetState(mHandle, &state), OMX_ErrorNone);
165    switch (state) {
166        case OMX_StateExecuting:
167        {
168            ALOGV("forcing Executing->Idle");
169            sendCommand(OMX_CommandStateSet, OMX_StateIdle);
170            OMX_ERRORTYPE err;
171            int32_t iteration = 0;
172            while ((err = OMX_GetState(mHandle, &state)) == OMX_ErrorNone
173                   && state != OMX_StateIdle
174                   && state != OMX_StateInvalid) {
175                if (++iteration > kMaxNumIterations) {
176                    ALOGE("component failed to enter Idle state, aborting.");
177                    state = OMX_StateInvalid;
178                    break;
179                }
180
181                usleep(100000);
182            }
183            CHECK_EQ(err, OMX_ErrorNone);
184
185            if (state == OMX_StateInvalid) {
186                break;
187            }
188
189            // fall through
190        }
191
192        case OMX_StateIdle:
193        {
194            ALOGV("forcing Idle->Loaded");
195            sendCommand(OMX_CommandStateSet, OMX_StateLoaded);
196
197            freeActiveBuffers();
198
199            OMX_ERRORTYPE err;
200            int32_t iteration = 0;
201            while ((err = OMX_GetState(mHandle, &state)) == OMX_ErrorNone
202                   && state != OMX_StateLoaded
203                   && state != OMX_StateInvalid) {
204                if (++iteration > kMaxNumIterations) {
205                    ALOGE("component failed to enter Loaded state, aborting.");
206                    state = OMX_StateInvalid;
207                    break;
208                }
209
210                ALOGV("waiting for Loaded state...");
211                usleep(100000);
212            }
213            CHECK_EQ(err, OMX_ErrorNone);
214
215            // fall through
216        }
217
218        case OMX_StateLoaded:
219        case OMX_StateInvalid:
220            break;
221
222        default:
223            CHECK(!"should not be here, unknown state.");
224            break;
225    }
226
227    ALOGV("calling destroyComponentInstance");
228    OMX_ERRORTYPE err = master->destroyComponentInstance(
229            static_cast<OMX_COMPONENTTYPE *>(mHandle));
230    ALOGV("destroyComponentInstance returned err %d", err);
231
232    mHandle = NULL;
233
234    if (err != OMX_ErrorNone) {
235        ALOGE("FreeHandle FAILED with error 0x%08x.", err);
236    }
237
238    mOwner->invalidateNodeID(mNodeID);
239    mNodeID = 0;
240
241    ALOGV("OMXNodeInstance going away.");
242    delete this;
243
244    return StatusFromOMXError(err);
245}
246
247status_t OMXNodeInstance::sendCommand(
248        OMX_COMMANDTYPE cmd, OMX_S32 param) {
249    const sp<GraphicBufferSource>& bufferSource(getGraphicBufferSource());
250    if (bufferSource != NULL && cmd == OMX_CommandStateSet) {
251        if (param == OMX_StateIdle) {
252            // Initiating transition from Executing -> Idle
253            // ACodec is waiting for all buffers to be returned, do NOT
254            // submit any more buffers to the codec.
255            bufferSource->omxIdle();
256        } else if (param == OMX_StateLoaded) {
257            // Initiating transition from Idle/Executing -> Loaded
258            // Buffers are about to be freed.
259            bufferSource->omxLoaded();
260            setGraphicBufferSource(NULL);
261        }
262
263        // fall through
264    }
265
266    Mutex::Autolock autoLock(mLock);
267
268    OMX_ERRORTYPE err = OMX_SendCommand(mHandle, cmd, param, NULL);
269    return StatusFromOMXError(err);
270}
271
272status_t OMXNodeInstance::getParameter(
273        OMX_INDEXTYPE index, void *params, size_t /* size */) {
274    Mutex::Autolock autoLock(mLock);
275
276    OMX_ERRORTYPE err = OMX_GetParameter(mHandle, index, params);
277    ALOGE_IF(err != OMX_ErrorNone, "getParameter(%d) ERROR: %#x", index, err);
278    return StatusFromOMXError(err);
279}
280
281status_t OMXNodeInstance::setParameter(
282        OMX_INDEXTYPE index, const void *params, size_t /* size */) {
283    Mutex::Autolock autoLock(mLock);
284
285    OMX_ERRORTYPE err = OMX_SetParameter(
286            mHandle, index, const_cast<void *>(params));
287    ALOGE_IF(err != OMX_ErrorNone, "setParameter(%d) ERROR: %#x", index, err);
288    return StatusFromOMXError(err);
289}
290
291status_t OMXNodeInstance::getConfig(
292        OMX_INDEXTYPE index, void *params, size_t /* size */) {
293    Mutex::Autolock autoLock(mLock);
294
295    OMX_ERRORTYPE err = OMX_GetConfig(mHandle, index, params);
296    return StatusFromOMXError(err);
297}
298
299status_t OMXNodeInstance::setConfig(
300        OMX_INDEXTYPE index, const void *params, size_t /* size */) {
301    Mutex::Autolock autoLock(mLock);
302
303    OMX_ERRORTYPE err = OMX_SetConfig(
304            mHandle, index, const_cast<void *>(params));
305
306    return StatusFromOMXError(err);
307}
308
309status_t OMXNodeInstance::getState(OMX_STATETYPE* state) {
310    Mutex::Autolock autoLock(mLock);
311
312    OMX_ERRORTYPE err = OMX_GetState(mHandle, state);
313
314    return StatusFromOMXError(err);
315}
316
317status_t OMXNodeInstance::enableGraphicBuffers(
318        OMX_U32 portIndex, OMX_BOOL enable) {
319    Mutex::Autolock autoLock(mLock);
320    OMX_STRING name = const_cast<OMX_STRING>(
321            "OMX.google.android.index.enableAndroidNativeBuffers");
322
323    OMX_INDEXTYPE index;
324    OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
325
326    if (err != OMX_ErrorNone) {
327        if (enable) {
328            ALOGE("OMX_GetExtensionIndex %s failed", name);
329        }
330
331        return StatusFromOMXError(err);
332    }
333
334    OMX_VERSIONTYPE ver;
335    ver.s.nVersionMajor = 1;
336    ver.s.nVersionMinor = 0;
337    ver.s.nRevision = 0;
338    ver.s.nStep = 0;
339    EnableAndroidNativeBuffersParams params = {
340        sizeof(EnableAndroidNativeBuffersParams), ver, portIndex, enable,
341    };
342
343    err = OMX_SetParameter(mHandle, index, &params);
344
345    if (err != OMX_ErrorNone) {
346        ALOGE("OMX_EnableAndroidNativeBuffers failed with error %d (0x%08x)",
347                err, err);
348
349        return UNKNOWN_ERROR;
350    }
351
352    return OK;
353}
354
355status_t OMXNodeInstance::getGraphicBufferUsage(
356        OMX_U32 portIndex, OMX_U32* usage) {
357    Mutex::Autolock autoLock(mLock);
358
359    OMX_INDEXTYPE index;
360    OMX_STRING name = const_cast<OMX_STRING>(
361            "OMX.google.android.index.getAndroidNativeBufferUsage");
362    OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
363
364    if (err != OMX_ErrorNone) {
365        ALOGE("OMX_GetExtensionIndex %s failed", name);
366
367        return StatusFromOMXError(err);
368    }
369
370    OMX_VERSIONTYPE ver;
371    ver.s.nVersionMajor = 1;
372    ver.s.nVersionMinor = 0;
373    ver.s.nRevision = 0;
374    ver.s.nStep = 0;
375    GetAndroidNativeBufferUsageParams params = {
376        sizeof(GetAndroidNativeBufferUsageParams), ver, portIndex, 0,
377    };
378
379    err = OMX_GetParameter(mHandle, index, &params);
380
381    if (err != OMX_ErrorNone) {
382        ALOGE("OMX_GetAndroidNativeBufferUsage failed with error %d (0x%08x)",
383                err, err);
384        return UNKNOWN_ERROR;
385    }
386
387    *usage = params.nUsage;
388
389    return OK;
390}
391
392status_t OMXNodeInstance::storeMetaDataInBuffers(
393        OMX_U32 portIndex,
394        OMX_BOOL enable) {
395    Mutex::Autolock autolock(mLock);
396    return storeMetaDataInBuffers_l(portIndex, enable);
397}
398
399status_t OMXNodeInstance::storeMetaDataInBuffers_l(
400        OMX_U32 portIndex,
401        OMX_BOOL enable) {
402    OMX_INDEXTYPE index;
403    OMX_STRING name = const_cast<OMX_STRING>(
404            "OMX.google.android.index.storeMetaDataInBuffers");
405
406    OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
407    if (err != OMX_ErrorNone) {
408        ALOGE("OMX_GetExtensionIndex %s failed", name);
409
410        return StatusFromOMXError(err);
411    }
412
413    StoreMetaDataInBuffersParams params;
414    memset(&params, 0, sizeof(params));
415    params.nSize = sizeof(params);
416
417    // Version: 1.0.0.0
418    params.nVersion.s.nVersionMajor = 1;
419
420    params.nPortIndex = portIndex;
421    params.bStoreMetaData = enable;
422    if ((err = OMX_SetParameter(mHandle, index, &params)) != OMX_ErrorNone) {
423        ALOGE("OMX_SetParameter() failed for StoreMetaDataInBuffers: 0x%08x", err);
424        return UNKNOWN_ERROR;
425    }
426    return err;
427}
428
429status_t OMXNodeInstance::prepareForAdaptivePlayback(
430        OMX_U32 portIndex, OMX_BOOL enable, OMX_U32 maxFrameWidth,
431        OMX_U32 maxFrameHeight) {
432    Mutex::Autolock autolock(mLock);
433
434    OMX_INDEXTYPE index;
435    OMX_STRING name = const_cast<OMX_STRING>(
436            "OMX.google.android.index.prepareForAdaptivePlayback");
437
438    OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
439    if (err != OMX_ErrorNone) {
440        ALOGW_IF(enable, "OMX_GetExtensionIndex %s failed", name);
441        return StatusFromOMXError(err);
442    }
443
444    PrepareForAdaptivePlaybackParams params;
445    params.nSize = sizeof(params);
446    params.nVersion.s.nVersionMajor = 1;
447    params.nVersion.s.nVersionMinor = 0;
448    params.nVersion.s.nRevision = 0;
449    params.nVersion.s.nStep = 0;
450
451    params.nPortIndex = portIndex;
452    params.bEnable = enable;
453    params.nMaxFrameWidth = maxFrameWidth;
454    params.nMaxFrameHeight = maxFrameHeight;
455    if ((err = OMX_SetParameter(mHandle, index, &params)) != OMX_ErrorNone) {
456        ALOGW("OMX_SetParameter failed for PrepareForAdaptivePlayback "
457              "with error %d (0x%08x)", err, err);
458        return UNKNOWN_ERROR;
459    }
460    return err;
461}
462
463status_t OMXNodeInstance::useBuffer(
464        OMX_U32 portIndex, const sp<IMemory> &params,
465        OMX::buffer_id *buffer) {
466    Mutex::Autolock autoLock(mLock);
467
468    BufferMeta *buffer_meta = new BufferMeta(params);
469
470    OMX_BUFFERHEADERTYPE *header;
471
472    OMX_ERRORTYPE err = OMX_UseBuffer(
473            mHandle, &header, portIndex, buffer_meta,
474            params->size(), static_cast<OMX_U8 *>(params->pointer()));
475
476    if (err != OMX_ErrorNone) {
477        ALOGE("OMX_UseBuffer failed with error %d (0x%08x)", err, err);
478
479        delete buffer_meta;
480        buffer_meta = NULL;
481
482        *buffer = 0;
483
484        return UNKNOWN_ERROR;
485    }
486
487    CHECK_EQ(header->pAppPrivate, buffer_meta);
488
489    *buffer = makeBufferID(header);
490
491    addActiveBuffer(portIndex, *buffer);
492
493    sp<GraphicBufferSource> bufferSource(getGraphicBufferSource());
494    if (bufferSource != NULL && portIndex == kPortIndexInput) {
495        bufferSource->addCodecBuffer(header);
496    }
497
498    return OK;
499}
500
501status_t OMXNodeInstance::useGraphicBuffer2_l(
502        OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer,
503        OMX::buffer_id *buffer) {
504
505    // port definition
506    OMX_PARAM_PORTDEFINITIONTYPE def;
507    def.nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
508    def.nVersion.s.nVersionMajor = 1;
509    def.nVersion.s.nVersionMinor = 0;
510    def.nVersion.s.nRevision = 0;
511    def.nVersion.s.nStep = 0;
512    def.nPortIndex = portIndex;
513    OMX_ERRORTYPE err = OMX_GetParameter(mHandle, OMX_IndexParamPortDefinition, &def);
514    if (err != OMX_ErrorNone)
515    {
516        ALOGE("%s::%d:Error getting OMX_IndexParamPortDefinition", __FUNCTION__, __LINE__);
517        return err;
518    }
519
520    BufferMeta *bufferMeta = new BufferMeta(graphicBuffer);
521
522    OMX_BUFFERHEADERTYPE *header = NULL;
523    OMX_U8* bufferHandle = const_cast<OMX_U8*>(
524            reinterpret_cast<const OMX_U8*>(graphicBuffer->handle));
525
526    err = OMX_UseBuffer(
527            mHandle,
528            &header,
529            portIndex,
530            bufferMeta,
531            def.nBufferSize,
532            bufferHandle);
533
534    if (err != OMX_ErrorNone) {
535        ALOGE("OMX_UseBuffer failed with error %d (0x%08x)", err, err);
536        delete bufferMeta;
537        bufferMeta = NULL;
538        *buffer = 0;
539        return UNKNOWN_ERROR;
540    }
541
542    CHECK_EQ(header->pBuffer, bufferHandle);
543    CHECK_EQ(header->pAppPrivate, bufferMeta);
544
545    *buffer = makeBufferID(header);
546
547    addActiveBuffer(portIndex, *buffer);
548
549    return OK;
550}
551
552// XXX: This function is here for backwards compatibility.  Once the OMX
553// implementations have been updated this can be removed and useGraphicBuffer2
554// can be renamed to useGraphicBuffer.
555status_t OMXNodeInstance::useGraphicBuffer(
556        OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer,
557        OMX::buffer_id *buffer) {
558    Mutex::Autolock autoLock(mLock);
559
560    // See if the newer version of the extension is present.
561    OMX_INDEXTYPE index;
562    if (OMX_GetExtensionIndex(
563            mHandle,
564            const_cast<OMX_STRING>("OMX.google.android.index.useAndroidNativeBuffer2"),
565            &index) == OMX_ErrorNone) {
566        return useGraphicBuffer2_l(portIndex, graphicBuffer, buffer);
567    }
568
569    OMX_STRING name = const_cast<OMX_STRING>(
570        "OMX.google.android.index.useAndroidNativeBuffer");
571    OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
572
573    if (err != OMX_ErrorNone) {
574        ALOGE("OMX_GetExtensionIndex %s failed", name);
575
576        return StatusFromOMXError(err);
577    }
578
579    BufferMeta *bufferMeta = new BufferMeta(graphicBuffer);
580
581    OMX_BUFFERHEADERTYPE *header;
582
583    OMX_VERSIONTYPE ver;
584    ver.s.nVersionMajor = 1;
585    ver.s.nVersionMinor = 0;
586    ver.s.nRevision = 0;
587    ver.s.nStep = 0;
588    UseAndroidNativeBufferParams params = {
589        sizeof(UseAndroidNativeBufferParams), ver, portIndex, bufferMeta,
590        &header, graphicBuffer,
591    };
592
593    err = OMX_SetParameter(mHandle, index, &params);
594
595    if (err != OMX_ErrorNone) {
596        ALOGE("OMX_UseAndroidNativeBuffer failed with error %d (0x%08x)", err,
597                err);
598
599        delete bufferMeta;
600        bufferMeta = NULL;
601
602        *buffer = 0;
603
604        return UNKNOWN_ERROR;
605    }
606
607    CHECK_EQ(header->pAppPrivate, bufferMeta);
608
609    *buffer = makeBufferID(header);
610
611    addActiveBuffer(portIndex, *buffer);
612
613    return OK;
614}
615
616status_t OMXNodeInstance::updateGraphicBufferInMeta(
617        OMX_U32 /* portIndex */, const sp<GraphicBuffer>& graphicBuffer,
618        OMX::buffer_id buffer) {
619    Mutex::Autolock autoLock(mLock);
620
621    OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer);
622    VideoDecoderOutputMetaData *metadata =
623        (VideoDecoderOutputMetaData *)(header->pBuffer);
624    BufferMeta *bufferMeta = (BufferMeta *)(header->pAppPrivate);
625    bufferMeta->setGraphicBuffer(graphicBuffer);
626    metadata->eType = kMetadataBufferTypeGrallocSource;
627    metadata->pHandle = graphicBuffer->handle;
628
629    return OK;
630}
631
632status_t OMXNodeInstance::createInputSurface(
633        OMX_U32 portIndex, sp<IGraphicBufferProducer> *bufferProducer) {
634    Mutex::Autolock autolock(mLock);
635    status_t err;
636
637    const sp<GraphicBufferSource>& surfaceCheck = getGraphicBufferSource();
638    if (surfaceCheck != NULL) {
639        return ALREADY_EXISTS;
640    }
641
642    // Input buffers will hold meta-data (gralloc references).
643    err = storeMetaDataInBuffers_l(portIndex, OMX_TRUE);
644    if (err != OK) {
645        return err;
646    }
647
648    // Retrieve the width and height of the graphic buffer, set when the
649    // codec was configured.
650    OMX_PARAM_PORTDEFINITIONTYPE def;
651    def.nSize = sizeof(def);
652    def.nVersion.s.nVersionMajor = 1;
653    def.nVersion.s.nVersionMinor = 0;
654    def.nVersion.s.nRevision = 0;
655    def.nVersion.s.nStep = 0;
656    def.nPortIndex = portIndex;
657    OMX_ERRORTYPE oerr = OMX_GetParameter(
658            mHandle, OMX_IndexParamPortDefinition, &def);
659    CHECK(oerr == OMX_ErrorNone);
660
661    if (def.format.video.eColorFormat != OMX_COLOR_FormatAndroidOpaque) {
662        ALOGE("createInputSurface requires COLOR_FormatSurface "
663              "(AndroidOpaque) color format");
664        return INVALID_OPERATION;
665    }
666
667    GraphicBufferSource* bufferSource = new GraphicBufferSource(
668            this, def.format.video.nFrameWidth, def.format.video.nFrameHeight,
669            def.nBufferCountActual);
670    if ((err = bufferSource->initCheck()) != OK) {
671        delete bufferSource;
672        return err;
673    }
674    setGraphicBufferSource(bufferSource);
675
676    *bufferProducer = bufferSource->getIGraphicBufferProducer();
677    return OK;
678}
679
680status_t OMXNodeInstance::signalEndOfInputStream() {
681    // For non-Surface input, the MediaCodec should convert the call to a
682    // pair of requests (dequeue input buffer, queue input buffer with EOS
683    // flag set).  Seems easier than doing the equivalent from here.
684    sp<GraphicBufferSource> bufferSource(getGraphicBufferSource());
685    if (bufferSource == NULL) {
686        ALOGW("signalEndOfInputStream can only be used with Surface input");
687        return INVALID_OPERATION;
688    };
689    return bufferSource->signalEndOfInputStream();
690}
691
692status_t OMXNodeInstance::allocateBuffer(
693        OMX_U32 portIndex, size_t size, OMX::buffer_id *buffer,
694        void **buffer_data) {
695    Mutex::Autolock autoLock(mLock);
696
697    BufferMeta *buffer_meta = new BufferMeta(size);
698
699    OMX_BUFFERHEADERTYPE *header;
700
701    OMX_ERRORTYPE err = OMX_AllocateBuffer(
702            mHandle, &header, portIndex, buffer_meta, size);
703
704    if (err != OMX_ErrorNone) {
705        ALOGE("OMX_AllocateBuffer failed with error %d (0x%08x)", err, err);
706
707        delete buffer_meta;
708        buffer_meta = NULL;
709
710        *buffer = 0;
711
712        return UNKNOWN_ERROR;
713    }
714
715    CHECK_EQ(header->pAppPrivate, buffer_meta);
716
717    *buffer = makeBufferID(header);
718    *buffer_data = header->pBuffer;
719
720    addActiveBuffer(portIndex, *buffer);
721
722    sp<GraphicBufferSource> bufferSource(getGraphicBufferSource());
723    if (bufferSource != NULL && portIndex == kPortIndexInput) {
724        bufferSource->addCodecBuffer(header);
725    }
726
727    return OK;
728}
729
730status_t OMXNodeInstance::allocateBufferWithBackup(
731        OMX_U32 portIndex, const sp<IMemory> &params,
732        OMX::buffer_id *buffer) {
733    Mutex::Autolock autoLock(mLock);
734
735    BufferMeta *buffer_meta = new BufferMeta(params, true);
736
737    OMX_BUFFERHEADERTYPE *header;
738
739    OMX_ERRORTYPE err = OMX_AllocateBuffer(
740            mHandle, &header, portIndex, buffer_meta, params->size());
741
742    if (err != OMX_ErrorNone) {
743        ALOGE("OMX_AllocateBuffer failed with error %d (0x%08x)", err, err);
744
745        delete buffer_meta;
746        buffer_meta = NULL;
747
748        *buffer = 0;
749
750        return UNKNOWN_ERROR;
751    }
752
753    CHECK_EQ(header->pAppPrivate, buffer_meta);
754
755    *buffer = makeBufferID(header);
756
757    addActiveBuffer(portIndex, *buffer);
758
759    sp<GraphicBufferSource> bufferSource(getGraphicBufferSource());
760    if (bufferSource != NULL && portIndex == kPortIndexInput) {
761        bufferSource->addCodecBuffer(header);
762    }
763
764    return OK;
765}
766
767status_t OMXNodeInstance::freeBuffer(
768        OMX_U32 portIndex, OMX::buffer_id buffer) {
769    Mutex::Autolock autoLock(mLock);
770
771    removeActiveBuffer(portIndex, buffer);
772
773    OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer);
774    BufferMeta *buffer_meta = static_cast<BufferMeta *>(header->pAppPrivate);
775
776    OMX_ERRORTYPE err = OMX_FreeBuffer(mHandle, portIndex, header);
777
778    delete buffer_meta;
779    buffer_meta = NULL;
780    invalidateBufferID(buffer);
781
782    return StatusFromOMXError(err);
783}
784
785status_t OMXNodeInstance::fillBuffer(OMX::buffer_id buffer) {
786    Mutex::Autolock autoLock(mLock);
787
788    OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer);
789    header->nFilledLen = 0;
790    header->nOffset = 0;
791    header->nFlags = 0;
792
793    OMX_ERRORTYPE err = OMX_FillThisBuffer(mHandle, header);
794
795    return StatusFromOMXError(err);
796}
797
798status_t OMXNodeInstance::emptyBuffer(
799        OMX::buffer_id buffer,
800        OMX_U32 rangeOffset, OMX_U32 rangeLength,
801        OMX_U32 flags, OMX_TICKS timestamp) {
802    Mutex::Autolock autoLock(mLock);
803
804    OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer);
805    header->nFilledLen = rangeLength;
806    header->nOffset = rangeOffset;
807    header->nFlags = flags;
808    header->nTimeStamp = timestamp;
809
810    BufferMeta *buffer_meta =
811        static_cast<BufferMeta *>(header->pAppPrivate);
812    buffer_meta->CopyToOMX(header);
813
814    OMX_ERRORTYPE err = OMX_EmptyThisBuffer(mHandle, header);
815
816    return StatusFromOMXError(err);
817}
818
819// like emptyBuffer, but the data is already in header->pBuffer
820status_t OMXNodeInstance::emptyDirectBuffer(
821        OMX_BUFFERHEADERTYPE *header,
822        OMX_U32 rangeOffset, OMX_U32 rangeLength,
823        OMX_U32 flags, OMX_TICKS timestamp) {
824    Mutex::Autolock autoLock(mLock);
825
826    header->nFilledLen = rangeLength;
827    header->nOffset = rangeOffset;
828    header->nFlags = flags;
829    header->nTimeStamp = timestamp;
830
831    OMX_ERRORTYPE err = OMX_EmptyThisBuffer(mHandle, header);
832    if (err != OMX_ErrorNone) {
833        ALOGW("emptyDirectBuffer failed, OMX err=0x%x", err);
834    }
835
836    return StatusFromOMXError(err);
837}
838
839status_t OMXNodeInstance::getExtensionIndex(
840        const char *parameterName, OMX_INDEXTYPE *index) {
841    Mutex::Autolock autoLock(mLock);
842
843    OMX_ERRORTYPE err = OMX_GetExtensionIndex(
844            mHandle, const_cast<char *>(parameterName), index);
845
846    return StatusFromOMXError(err);
847}
848
849status_t OMXNodeInstance::setInternalOption(
850        OMX_U32 portIndex,
851        IOMX::InternalOptionType type,
852        const void *data,
853        size_t size) {
854    switch (type) {
855        case IOMX::INTERNAL_OPTION_SUSPEND:
856        case IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY:
857        case IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP:
858        case IOMX::INTERNAL_OPTION_START_TIME:
859        case IOMX::INTERNAL_OPTION_TIME_LAPSE:
860        {
861            const sp<GraphicBufferSource> &bufferSource =
862                getGraphicBufferSource();
863
864            if (bufferSource == NULL || portIndex != kPortIndexInput) {
865                return ERROR_UNSUPPORTED;
866            }
867
868            if (type == IOMX::INTERNAL_OPTION_SUSPEND) {
869                if (size != sizeof(bool)) {
870                    return INVALID_OPERATION;
871                }
872
873                bool suspend = *(bool *)data;
874                bufferSource->suspend(suspend);
875            } else if (type ==
876                    IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY){
877                if (size != sizeof(int64_t)) {
878                    return INVALID_OPERATION;
879                }
880
881                int64_t delayUs = *(int64_t *)data;
882
883                return bufferSource->setRepeatPreviousFrameDelayUs(delayUs);
884            } else if (type ==
885                    IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP){
886                if (size != sizeof(int64_t)) {
887                    return INVALID_OPERATION;
888                }
889
890                int64_t maxGapUs = *(int64_t *)data;
891
892                return bufferSource->setMaxTimestampGapUs(maxGapUs);
893            } else if (type == IOMX::INTERNAL_OPTION_START_TIME) {
894                if (size != sizeof(int64_t)) {
895                    return INVALID_OPERATION;
896                }
897
898                int64_t skipFramesBeforeUs = *(int64_t *)data;
899
900                bufferSource->setSkipFramesBeforeUs(skipFramesBeforeUs);
901            } else { // IOMX::INTERNAL_OPTION_TIME_LAPSE
902                if (size != sizeof(int64_t) * 2) {
903                    return INVALID_OPERATION;
904                }
905
906                bufferSource->setTimeLapseUs((int64_t *)data);
907            }
908
909            return OK;
910        }
911
912        default:
913            return ERROR_UNSUPPORTED;
914    }
915}
916
917void OMXNodeInstance::onMessage(const omx_message &msg) {
918    const sp<GraphicBufferSource>& bufferSource(getGraphicBufferSource());
919
920    if (msg.type == omx_message::FILL_BUFFER_DONE) {
921        OMX_BUFFERHEADERTYPE *buffer =
922            findBufferHeader(msg.u.extended_buffer_data.buffer);
923
924        BufferMeta *buffer_meta =
925            static_cast<BufferMeta *>(buffer->pAppPrivate);
926
927        buffer_meta->CopyFromOMX(buffer);
928
929        if (bufferSource != NULL) {
930            // fix up the buffer info (especially timestamp) if needed
931            bufferSource->codecBufferFilled(buffer);
932
933            omx_message newMsg = msg;
934            newMsg.u.extended_buffer_data.timestamp = buffer->nTimeStamp;
935            mObserver->onMessage(newMsg);
936            return;
937        }
938    } else if (msg.type == omx_message::EMPTY_BUFFER_DONE) {
939        if (bufferSource != NULL) {
940            // This is one of the buffers used exclusively by
941            // GraphicBufferSource.
942            // Don't dispatch a message back to ACodec, since it doesn't
943            // know that anyone asked to have the buffer emptied and will
944            // be very confused.
945
946            OMX_BUFFERHEADERTYPE *buffer =
947                findBufferHeader(msg.u.buffer_data.buffer);
948
949            bufferSource->codecBufferEmptied(buffer);
950            return;
951        }
952    }
953
954    mObserver->onMessage(msg);
955}
956
957void OMXNodeInstance::onObserverDied(OMXMaster *master) {
958    ALOGE("!!! Observer died. Quickly, do something, ... anything...");
959
960    // Try to force shutdown of the node and hope for the best.
961    freeNode(master);
962}
963
964void OMXNodeInstance::onGetHandleFailed() {
965    delete this;
966}
967
968// OMXNodeInstance::OnEvent calls OMX::OnEvent, which then calls here.
969// Don't try to acquire mLock here -- in rare circumstances this will hang.
970void OMXNodeInstance::onEvent(
971        OMX_EVENTTYPE event, OMX_U32 arg1, OMX_U32 arg2) {
972    const sp<GraphicBufferSource>& bufferSource(getGraphicBufferSource());
973
974    if (bufferSource != NULL
975            && event == OMX_EventCmdComplete
976            && arg1 == OMX_CommandStateSet
977            && arg2 == OMX_StateExecuting) {
978        bufferSource->omxExecuting();
979    }
980}
981
982// static
983OMX_ERRORTYPE OMXNodeInstance::OnEvent(
984        OMX_IN OMX_HANDLETYPE /* hComponent */,
985        OMX_IN OMX_PTR pAppData,
986        OMX_IN OMX_EVENTTYPE eEvent,
987        OMX_IN OMX_U32 nData1,
988        OMX_IN OMX_U32 nData2,
989        OMX_IN OMX_PTR pEventData) {
990    OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
991    if (instance->mDying) {
992        return OMX_ErrorNone;
993    }
994    return instance->owner()->OnEvent(
995            instance->nodeID(), eEvent, nData1, nData2, pEventData);
996}
997
998// static
999OMX_ERRORTYPE OMXNodeInstance::OnEmptyBufferDone(
1000        OMX_IN OMX_HANDLETYPE /* hComponent */,
1001        OMX_IN OMX_PTR pAppData,
1002        OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) {
1003    OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
1004    if (instance->mDying) {
1005        return OMX_ErrorNone;
1006    }
1007    return instance->owner()->OnEmptyBufferDone(instance->nodeID(),
1008            instance->findBufferID(pBuffer), pBuffer);
1009}
1010
1011// static
1012OMX_ERRORTYPE OMXNodeInstance::OnFillBufferDone(
1013        OMX_IN OMX_HANDLETYPE /* hComponent */,
1014        OMX_IN OMX_PTR pAppData,
1015        OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) {
1016    OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
1017    if (instance->mDying) {
1018        return OMX_ErrorNone;
1019    }
1020    return instance->owner()->OnFillBufferDone(instance->nodeID(),
1021            instance->findBufferID(pBuffer), pBuffer);
1022}
1023
1024void OMXNodeInstance::addActiveBuffer(OMX_U32 portIndex, OMX::buffer_id id) {
1025    ActiveBuffer active;
1026    active.mPortIndex = portIndex;
1027    active.mID = id;
1028    mActiveBuffers.push(active);
1029}
1030
1031void OMXNodeInstance::removeActiveBuffer(
1032        OMX_U32 portIndex, OMX::buffer_id id) {
1033    bool found = false;
1034    for (size_t i = 0; i < mActiveBuffers.size(); ++i) {
1035        if (mActiveBuffers[i].mPortIndex == portIndex
1036            && mActiveBuffers[i].mID == id) {
1037            found = true;
1038            mActiveBuffers.removeItemsAt(i);
1039            break;
1040        }
1041    }
1042
1043    if (!found) {
1044        ALOGW("Attempt to remove an active buffer we know nothing about...");
1045    }
1046}
1047
1048void OMXNodeInstance::freeActiveBuffers() {
1049    // Make sure to count down here, as freeBuffer will in turn remove
1050    // the active buffer from the vector...
1051    for (size_t i = mActiveBuffers.size(); i--;) {
1052        freeBuffer(mActiveBuffers[i].mPortIndex, mActiveBuffers[i].mID);
1053    }
1054}
1055
1056#ifdef __LP64__
1057
1058OMX::buffer_id OMXNodeInstance::makeBufferID(OMX_BUFFERHEADERTYPE *bufferHeader) {
1059    if (bufferHeader == NULL) {
1060        return 0;
1061    }
1062    Mutex::Autolock autoLock(mBufferIDLock);
1063    OMX::buffer_id buffer;
1064    do { // handle the very unlikely case of ID overflow
1065        if (++mBufferIDCount == 0) {
1066           ++mBufferIDCount;
1067        }
1068        buffer = (OMX::buffer_id)mBufferIDCount;
1069    } while (mBufferIDToBufferHeader.indexOfKey(buffer) >= 0);
1070    mBufferIDToBufferHeader.add(buffer, bufferHeader);
1071    mBufferHeaderToBufferID.add(bufferHeader, buffer);
1072    return buffer;
1073}
1074
1075OMX_BUFFERHEADERTYPE *OMXNodeInstance::findBufferHeader(OMX::buffer_id buffer) {
1076    if (buffer == 0) {
1077        return NULL;
1078    }
1079    Mutex::Autolock autoLock(mBufferIDLock);
1080    return mBufferIDToBufferHeader.valueFor(buffer);
1081}
1082
1083OMX::buffer_id OMXNodeInstance::findBufferID(OMX_BUFFERHEADERTYPE *bufferHeader) {
1084    if (bufferHeader == NULL) {
1085        return 0;
1086    }
1087    Mutex::Autolock autoLock(mBufferIDLock);
1088    return mBufferHeaderToBufferID.valueFor(bufferHeader);
1089}
1090
1091void OMXNodeInstance::invalidateBufferID(OMX::buffer_id buffer) {
1092    if (buffer == 0) {
1093        return;
1094    }
1095    Mutex::Autolock autoLock(mBufferIDLock);
1096    mBufferHeaderToBufferID.removeItem(mBufferIDToBufferHeader.valueFor(buffer));
1097    mBufferIDToBufferHeader.removeItem(buffer);
1098}
1099
1100#else
1101
1102OMX::buffer_id OMXNodeInstance::makeBufferID(OMX_BUFFERHEADERTYPE *bufferHeader) {
1103    return (OMX::buffer_id)bufferHeader;
1104}
1105
1106OMX_BUFFERHEADERTYPE *OMXNodeInstance::findBufferHeader(OMX::buffer_id buffer) {
1107    return (OMX_BUFFERHEADERTYPE *)buffer;
1108}
1109
1110OMX::buffer_id OMXNodeInstance::findBufferID(OMX_BUFFERHEADERTYPE *bufferHeader) {
1111    return (OMX::buffer_id)bufferHeader;
1112}
1113
1114void OMXNodeInstance::invalidateBufferID(OMX::buffer_id buffer __unused) {
1115}
1116
1117#endif
1118
1119}  // namespace android
1120