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