OMXNodeInstance.cpp revision 8b1be2ca7cee71a4920d5d31fdcbad2b1d4ca49d
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        {
859            const sp<GraphicBufferSource> &bufferSource =
860                getGraphicBufferSource();
861
862            if (bufferSource == NULL || portIndex != kPortIndexInput) {
863                return ERROR_UNSUPPORTED;
864            }
865
866            if (type == IOMX::INTERNAL_OPTION_SUSPEND) {
867                if (size != sizeof(bool)) {
868                    return INVALID_OPERATION;
869                }
870
871                bool suspend = *(bool *)data;
872                bufferSource->suspend(suspend);
873            } else if (type ==
874                    IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY){
875                if (size != sizeof(int64_t)) {
876                    return INVALID_OPERATION;
877                }
878
879                int64_t delayUs = *(int64_t *)data;
880
881                return bufferSource->setRepeatPreviousFrameDelayUs(delayUs);
882            } else {
883                if (size != sizeof(int64_t)) {
884                    return INVALID_OPERATION;
885                }
886
887                int64_t maxGapUs = *(int64_t *)data;
888
889                return bufferSource->setMaxTimestampGapUs(maxGapUs);
890            }
891
892            return OK;
893        }
894
895        default:
896            return ERROR_UNSUPPORTED;
897    }
898}
899
900void OMXNodeInstance::onMessage(const omx_message &msg) {
901    const sp<GraphicBufferSource>& bufferSource(getGraphicBufferSource());
902
903    if (msg.type == omx_message::FILL_BUFFER_DONE) {
904        OMX_BUFFERHEADERTYPE *buffer =
905            findBufferHeader(msg.u.extended_buffer_data.buffer);
906
907        BufferMeta *buffer_meta =
908            static_cast<BufferMeta *>(buffer->pAppPrivate);
909
910        buffer_meta->CopyFromOMX(buffer);
911
912        if (bufferSource != NULL) {
913            // fix up the buffer info (especially timestamp) if needed
914            bufferSource->codecBufferFilled(buffer);
915
916            omx_message newMsg = msg;
917            newMsg.u.extended_buffer_data.timestamp = buffer->nTimeStamp;
918            mObserver->onMessage(newMsg);
919            return;
920        }
921    } else if (msg.type == omx_message::EMPTY_BUFFER_DONE) {
922        if (bufferSource != NULL) {
923            // This is one of the buffers used exclusively by
924            // GraphicBufferSource.
925            // Don't dispatch a message back to ACodec, since it doesn't
926            // know that anyone asked to have the buffer emptied and will
927            // be very confused.
928
929            OMX_BUFFERHEADERTYPE *buffer =
930                findBufferHeader(msg.u.buffer_data.buffer);
931
932            bufferSource->codecBufferEmptied(buffer);
933            return;
934        }
935    }
936
937    mObserver->onMessage(msg);
938}
939
940void OMXNodeInstance::onObserverDied(OMXMaster *master) {
941    ALOGE("!!! Observer died. Quickly, do something, ... anything...");
942
943    // Try to force shutdown of the node and hope for the best.
944    freeNode(master);
945}
946
947void OMXNodeInstance::onGetHandleFailed() {
948    delete this;
949}
950
951// OMXNodeInstance::OnEvent calls OMX::OnEvent, which then calls here.
952// Don't try to acquire mLock here -- in rare circumstances this will hang.
953void OMXNodeInstance::onEvent(
954        OMX_EVENTTYPE event, OMX_U32 arg1, OMX_U32 arg2) {
955    const sp<GraphicBufferSource>& bufferSource(getGraphicBufferSource());
956
957    if (bufferSource != NULL
958            && event == OMX_EventCmdComplete
959            && arg1 == OMX_CommandStateSet
960            && arg2 == OMX_StateExecuting) {
961        bufferSource->omxExecuting();
962    }
963}
964
965// static
966OMX_ERRORTYPE OMXNodeInstance::OnEvent(
967        OMX_IN OMX_HANDLETYPE /* hComponent */,
968        OMX_IN OMX_PTR pAppData,
969        OMX_IN OMX_EVENTTYPE eEvent,
970        OMX_IN OMX_U32 nData1,
971        OMX_IN OMX_U32 nData2,
972        OMX_IN OMX_PTR pEventData) {
973    OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
974    if (instance->mDying) {
975        return OMX_ErrorNone;
976    }
977    return instance->owner()->OnEvent(
978            instance->nodeID(), eEvent, nData1, nData2, pEventData);
979}
980
981// static
982OMX_ERRORTYPE OMXNodeInstance::OnEmptyBufferDone(
983        OMX_IN OMX_HANDLETYPE /* hComponent */,
984        OMX_IN OMX_PTR pAppData,
985        OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) {
986    OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
987    if (instance->mDying) {
988        return OMX_ErrorNone;
989    }
990    return instance->owner()->OnEmptyBufferDone(instance->nodeID(),
991            instance->findBufferID(pBuffer), pBuffer);
992}
993
994// static
995OMX_ERRORTYPE OMXNodeInstance::OnFillBufferDone(
996        OMX_IN OMX_HANDLETYPE /* hComponent */,
997        OMX_IN OMX_PTR pAppData,
998        OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) {
999    OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
1000    if (instance->mDying) {
1001        return OMX_ErrorNone;
1002    }
1003    return instance->owner()->OnFillBufferDone(instance->nodeID(),
1004            instance->findBufferID(pBuffer), pBuffer);
1005}
1006
1007void OMXNodeInstance::addActiveBuffer(OMX_U32 portIndex, OMX::buffer_id id) {
1008    ActiveBuffer active;
1009    active.mPortIndex = portIndex;
1010    active.mID = id;
1011    mActiveBuffers.push(active);
1012}
1013
1014void OMXNodeInstance::removeActiveBuffer(
1015        OMX_U32 portIndex, OMX::buffer_id id) {
1016    bool found = false;
1017    for (size_t i = 0; i < mActiveBuffers.size(); ++i) {
1018        if (mActiveBuffers[i].mPortIndex == portIndex
1019            && mActiveBuffers[i].mID == id) {
1020            found = true;
1021            mActiveBuffers.removeItemsAt(i);
1022            break;
1023        }
1024    }
1025
1026    if (!found) {
1027        ALOGW("Attempt to remove an active buffer we know nothing about...");
1028    }
1029}
1030
1031void OMXNodeInstance::freeActiveBuffers() {
1032    // Make sure to count down here, as freeBuffer will in turn remove
1033    // the active buffer from the vector...
1034    for (size_t i = mActiveBuffers.size(); i--;) {
1035        freeBuffer(mActiveBuffers[i].mPortIndex, mActiveBuffers[i].mID);
1036    }
1037}
1038
1039#ifdef __LP64__
1040
1041OMX::buffer_id OMXNodeInstance::makeBufferID(OMX_BUFFERHEADERTYPE *bufferHeader) {
1042    if (bufferHeader == NULL) {
1043        return 0;
1044    }
1045    Mutex::Autolock autoLock(mBufferIDLock);
1046    OMX::buffer_id buffer;
1047    do { // handle the very unlikely case of ID overflow
1048        if (++mBufferIDCount == 0) {
1049           ++mBufferIDCount;
1050        }
1051        buffer = (OMX::buffer_id)mBufferIDCount;
1052    } while (mBufferIDToBufferHeader.indexOfKey(buffer) >= 0);
1053    mBufferIDToBufferHeader.add(buffer, bufferHeader);
1054    mBufferHeaderToBufferID.add(bufferHeader, buffer);
1055    return buffer;
1056}
1057
1058OMX_BUFFERHEADERTYPE *OMXNodeInstance::findBufferHeader(OMX::buffer_id buffer) {
1059    if (buffer == 0) {
1060        return NULL;
1061    }
1062    Mutex::Autolock autoLock(mBufferIDLock);
1063    return mBufferIDToBufferHeader.valueFor(buffer);
1064}
1065
1066OMX::buffer_id OMXNodeInstance::findBufferID(OMX_BUFFERHEADERTYPE *bufferHeader) {
1067    if (bufferHeader == NULL) {
1068        return 0;
1069    }
1070    Mutex::Autolock autoLock(mBufferIDLock);
1071    return mBufferHeaderToBufferID.valueFor(bufferHeader);
1072}
1073
1074void OMXNodeInstance::invalidateBufferID(OMX::buffer_id buffer) {
1075    if (buffer == 0) {
1076        return;
1077    }
1078    Mutex::Autolock autoLock(mBufferIDLock);
1079    mBufferHeaderToBufferID.removeItem(mBufferIDToBufferHeader.valueFor(buffer));
1080    mBufferIDToBufferHeader.removeItem(buffer);
1081}
1082
1083#else
1084
1085OMX::buffer_id OMXNodeInstance::makeBufferID(OMX_BUFFERHEADERTYPE *bufferHeader) {
1086    return (OMX::buffer_id)bufferHeader;
1087}
1088
1089OMX_BUFFERHEADERTYPE *OMXNodeInstance::findBufferHeader(OMX::buffer_id buffer) {
1090    return (OMX_BUFFERHEADERTYPE *)buffer;
1091}
1092
1093OMX::buffer_id OMXNodeInstance::findBufferID(OMX_BUFFERHEADERTYPE *bufferHeader) {
1094    return (OMX::buffer_id)bufferHeader;
1095}
1096
1097void OMXNodeInstance::invalidateBufferID(OMX::buffer_id buffer __unused) {
1098}
1099
1100#endif
1101
1102}  // namespace android
1103