OMXNodeInstance.cpp revision 512e979284de984427e5b2f73b9054ae1b5e2b0a
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(
397            portIndex, enable,
398            OMX_FALSE /* useGraphicBuffer */, NULL /* usingGraphicBufferInMetadata */);
399}
400
401status_t OMXNodeInstance::storeMetaDataInBuffers_l(
402        OMX_U32 portIndex,
403        OMX_BOOL enable,
404        OMX_BOOL useGraphicBuffer,
405        OMX_BOOL *usingGraphicBufferInMetadata) {
406    OMX_INDEXTYPE index;
407    OMX_STRING name = const_cast<OMX_STRING>(
408            "OMX.google.android.index.storeMetaDataInBuffers");
409
410    OMX_STRING graphicBufferName = const_cast<OMX_STRING>(
411            "OMX.google.android.index.storeGraphicBufferInMetaData");
412    if (usingGraphicBufferInMetadata == NULL) {
413        usingGraphicBufferInMetadata = &useGraphicBuffer;
414    }
415
416    OMX_ERRORTYPE err =
417        (useGraphicBuffer && portIndex == kPortIndexInput)
418                ? OMX_GetExtensionIndex(mHandle, graphicBufferName, &index)
419                : OMX_ErrorBadParameter;
420    if (err == OMX_ErrorNone) {
421        *usingGraphicBufferInMetadata = OMX_TRUE;
422    } else {
423        *usingGraphicBufferInMetadata = OMX_FALSE;
424        err = OMX_GetExtensionIndex(mHandle, name, &index);
425    }
426
427    if (err != OMX_ErrorNone) {
428        ALOGE("OMX_GetExtensionIndex %s failed", name);
429        return StatusFromOMXError(err);
430    }
431
432    StoreMetaDataInBuffersParams params;
433    memset(&params, 0, sizeof(params));
434    params.nSize = sizeof(params);
435
436    // Version: 1.0.0.0
437    params.nVersion.s.nVersionMajor = 1;
438
439    params.nPortIndex = portIndex;
440    params.bStoreMetaData = enable;
441    if ((err = OMX_SetParameter(mHandle, index, &params)) != OMX_ErrorNone) {
442        ALOGE("OMX_SetParameter() failed for StoreMetaDataInBuffers: 0x%08x", err);
443        *usingGraphicBufferInMetadata = OMX_FALSE;
444        return UNKNOWN_ERROR;
445    }
446    return err;
447}
448
449status_t OMXNodeInstance::prepareForAdaptivePlayback(
450        OMX_U32 portIndex, OMX_BOOL enable, OMX_U32 maxFrameWidth,
451        OMX_U32 maxFrameHeight) {
452    Mutex::Autolock autolock(mLock);
453
454    OMX_INDEXTYPE index;
455    OMX_STRING name = const_cast<OMX_STRING>(
456            "OMX.google.android.index.prepareForAdaptivePlayback");
457
458    OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
459    if (err != OMX_ErrorNone) {
460        ALOGW_IF(enable, "OMX_GetExtensionIndex %s failed", name);
461        return StatusFromOMXError(err);
462    }
463
464    PrepareForAdaptivePlaybackParams params;
465    params.nSize = sizeof(params);
466    params.nVersion.s.nVersionMajor = 1;
467    params.nVersion.s.nVersionMinor = 0;
468    params.nVersion.s.nRevision = 0;
469    params.nVersion.s.nStep = 0;
470
471    params.nPortIndex = portIndex;
472    params.bEnable = enable;
473    params.nMaxFrameWidth = maxFrameWidth;
474    params.nMaxFrameHeight = maxFrameHeight;
475    if ((err = OMX_SetParameter(mHandle, index, &params)) != OMX_ErrorNone) {
476        ALOGW("OMX_SetParameter failed for PrepareForAdaptivePlayback "
477              "with error %d (0x%08x)", err, err);
478        return UNKNOWN_ERROR;
479    }
480    return err;
481}
482
483status_t OMXNodeInstance::configureVideoTunnelMode(
484        OMX_U32 portIndex, OMX_BOOL tunneled, OMX_U32 audioHwSync,
485        native_handle_t **sidebandHandle) {
486    Mutex::Autolock autolock(mLock);
487
488    OMX_INDEXTYPE index;
489    OMX_STRING name = const_cast<OMX_STRING>(
490            "OMX.google.android.index.configureVideoTunnelMode");
491
492    OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
493    if (err != OMX_ErrorNone) {
494        ALOGE("configureVideoTunnelMode extension is missing!");
495        return StatusFromOMXError(err);
496    }
497
498    ConfigureVideoTunnelModeParams tunnelParams;
499    tunnelParams.nSize = sizeof(tunnelParams);
500    tunnelParams.nVersion.s.nVersionMajor = 1;
501    tunnelParams.nVersion.s.nVersionMinor = 0;
502    tunnelParams.nVersion.s.nRevision = 0;
503    tunnelParams.nVersion.s.nStep = 0;
504
505    tunnelParams.nPortIndex = portIndex;
506    tunnelParams.bTunneled = tunneled;
507    tunnelParams.nAudioHwSync = audioHwSync;
508    err = OMX_SetParameter(mHandle, index, &tunnelParams);
509    if (err != OMX_ErrorNone) {
510        ALOGE("configureVideoTunnelMode failed! (err %d).", err);
511        return UNKNOWN_ERROR;
512    }
513
514    err = OMX_GetParameter(mHandle, index, &tunnelParams);
515    if (err != OMX_ErrorNone) {
516        ALOGE("GetVideoTunnelWindow failed! (err %d).", err);
517        return UNKNOWN_ERROR;
518    }
519    if (sidebandHandle) {
520        *sidebandHandle = (native_handle_t*)tunnelParams.pSidebandWindow;
521    }
522
523    return err;
524}
525
526status_t OMXNodeInstance::useBuffer(
527        OMX_U32 portIndex, const sp<IMemory> &params,
528        OMX::buffer_id *buffer) {
529    Mutex::Autolock autoLock(mLock);
530
531    BufferMeta *buffer_meta = new BufferMeta(params);
532
533    OMX_BUFFERHEADERTYPE *header;
534
535    OMX_ERRORTYPE err = OMX_UseBuffer(
536            mHandle, &header, portIndex, buffer_meta,
537            params->size(), static_cast<OMX_U8 *>(params->pointer()));
538
539    if (err != OMX_ErrorNone) {
540        ALOGE("OMX_UseBuffer failed with error %d (0x%08x)", err, err);
541
542        delete buffer_meta;
543        buffer_meta = NULL;
544
545        *buffer = 0;
546
547        return UNKNOWN_ERROR;
548    }
549
550    CHECK_EQ(header->pAppPrivate, buffer_meta);
551
552    *buffer = makeBufferID(header);
553
554    addActiveBuffer(portIndex, *buffer);
555
556    sp<GraphicBufferSource> bufferSource(getGraphicBufferSource());
557    if (bufferSource != NULL && portIndex == kPortIndexInput) {
558        bufferSource->addCodecBuffer(header);
559    }
560
561    return OK;
562}
563
564status_t OMXNodeInstance::useGraphicBuffer2_l(
565        OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer,
566        OMX::buffer_id *buffer) {
567
568    // port definition
569    OMX_PARAM_PORTDEFINITIONTYPE def;
570    def.nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
571    def.nVersion.s.nVersionMajor = 1;
572    def.nVersion.s.nVersionMinor = 0;
573    def.nVersion.s.nRevision = 0;
574    def.nVersion.s.nStep = 0;
575    def.nPortIndex = portIndex;
576    OMX_ERRORTYPE err = OMX_GetParameter(mHandle, OMX_IndexParamPortDefinition, &def);
577    if (err != OMX_ErrorNone)
578    {
579        ALOGE("%s::%d:Error getting OMX_IndexParamPortDefinition", __FUNCTION__, __LINE__);
580        return err;
581    }
582
583    BufferMeta *bufferMeta = new BufferMeta(graphicBuffer);
584
585    OMX_BUFFERHEADERTYPE *header = NULL;
586    OMX_U8* bufferHandle = const_cast<OMX_U8*>(
587            reinterpret_cast<const OMX_U8*>(graphicBuffer->handle));
588
589    err = OMX_UseBuffer(
590            mHandle,
591            &header,
592            portIndex,
593            bufferMeta,
594            def.nBufferSize,
595            bufferHandle);
596
597    if (err != OMX_ErrorNone) {
598        ALOGE("OMX_UseBuffer failed with error %d (0x%08x)", err, err);
599        delete bufferMeta;
600        bufferMeta = NULL;
601        *buffer = 0;
602        return UNKNOWN_ERROR;
603    }
604
605    CHECK_EQ(header->pBuffer, bufferHandle);
606    CHECK_EQ(header->pAppPrivate, bufferMeta);
607
608    *buffer = makeBufferID(header);
609
610    addActiveBuffer(portIndex, *buffer);
611
612    return OK;
613}
614
615// XXX: This function is here for backwards compatibility.  Once the OMX
616// implementations have been updated this can be removed and useGraphicBuffer2
617// can be renamed to useGraphicBuffer.
618status_t OMXNodeInstance::useGraphicBuffer(
619        OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer,
620        OMX::buffer_id *buffer) {
621    Mutex::Autolock autoLock(mLock);
622
623    // See if the newer version of the extension is present.
624    OMX_INDEXTYPE index;
625    if (OMX_GetExtensionIndex(
626            mHandle,
627            const_cast<OMX_STRING>("OMX.google.android.index.useAndroidNativeBuffer2"),
628            &index) == OMX_ErrorNone) {
629        return useGraphicBuffer2_l(portIndex, graphicBuffer, buffer);
630    }
631
632    OMX_STRING name = const_cast<OMX_STRING>(
633        "OMX.google.android.index.useAndroidNativeBuffer");
634    OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
635
636    if (err != OMX_ErrorNone) {
637        ALOGE("OMX_GetExtensionIndex %s failed", name);
638
639        return StatusFromOMXError(err);
640    }
641
642    BufferMeta *bufferMeta = new BufferMeta(graphicBuffer);
643
644    OMX_BUFFERHEADERTYPE *header;
645
646    OMX_VERSIONTYPE ver;
647    ver.s.nVersionMajor = 1;
648    ver.s.nVersionMinor = 0;
649    ver.s.nRevision = 0;
650    ver.s.nStep = 0;
651    UseAndroidNativeBufferParams params = {
652        sizeof(UseAndroidNativeBufferParams), ver, portIndex, bufferMeta,
653        &header, graphicBuffer,
654    };
655
656    err = OMX_SetParameter(mHandle, index, &params);
657
658    if (err != OMX_ErrorNone) {
659        ALOGE("OMX_UseAndroidNativeBuffer failed with error %d (0x%08x)", err,
660                err);
661
662        delete bufferMeta;
663        bufferMeta = NULL;
664
665        *buffer = 0;
666
667        return UNKNOWN_ERROR;
668    }
669
670    CHECK_EQ(header->pAppPrivate, bufferMeta);
671
672    *buffer = makeBufferID(header);
673
674    addActiveBuffer(portIndex, *buffer);
675
676    return OK;
677}
678
679status_t OMXNodeInstance::updateGraphicBufferInMeta(
680        OMX_U32 /* portIndex */, const sp<GraphicBuffer>& graphicBuffer,
681        OMX::buffer_id buffer) {
682    Mutex::Autolock autoLock(mLock);
683
684    OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer);
685    VideoDecoderOutputMetaData *metadata =
686        (VideoDecoderOutputMetaData *)(header->pBuffer);
687    BufferMeta *bufferMeta = (BufferMeta *)(header->pAppPrivate);
688    bufferMeta->setGraphicBuffer(graphicBuffer);
689    metadata->eType = kMetadataBufferTypeGrallocSource;
690    metadata->pHandle = graphicBuffer->handle;
691
692    return OK;
693}
694
695status_t OMXNodeInstance::createInputSurface(
696        OMX_U32 portIndex, sp<IGraphicBufferProducer> *bufferProducer) {
697    Mutex::Autolock autolock(mLock);
698    status_t err;
699
700    const sp<GraphicBufferSource>& surfaceCheck = getGraphicBufferSource();
701    if (surfaceCheck != NULL) {
702        return ALREADY_EXISTS;
703    }
704
705    // Input buffers will hold meta-data (gralloc references).
706    OMX_BOOL usingGraphicBuffer = OMX_FALSE;
707    err = storeMetaDataInBuffers_l(
708            portIndex, OMX_TRUE,
709            OMX_TRUE /* useGraphicBuffer */, &usingGraphicBuffer);
710    if (err != OK) {
711        return err;
712    }
713
714    // Retrieve the width and height of the graphic buffer, set when the
715    // codec was configured.
716    OMX_PARAM_PORTDEFINITIONTYPE def;
717    def.nSize = sizeof(def);
718    def.nVersion.s.nVersionMajor = 1;
719    def.nVersion.s.nVersionMinor = 0;
720    def.nVersion.s.nRevision = 0;
721    def.nVersion.s.nStep = 0;
722    def.nPortIndex = portIndex;
723    OMX_ERRORTYPE oerr = OMX_GetParameter(
724            mHandle, OMX_IndexParamPortDefinition, &def);
725    CHECK(oerr == OMX_ErrorNone);
726
727    if (def.format.video.eColorFormat != OMX_COLOR_FormatAndroidOpaque) {
728        ALOGE("createInputSurface requires COLOR_FormatSurface "
729              "(AndroidOpaque) color format");
730        return INVALID_OPERATION;
731    }
732
733    GraphicBufferSource* bufferSource = new GraphicBufferSource(
734            this, def.format.video.nFrameWidth, def.format.video.nFrameHeight,
735            def.nBufferCountActual, usingGraphicBuffer);
736    if ((err = bufferSource->initCheck()) != OK) {
737        delete bufferSource;
738        return err;
739    }
740    setGraphicBufferSource(bufferSource);
741
742    *bufferProducer = bufferSource->getIGraphicBufferProducer();
743    return OK;
744}
745
746status_t OMXNodeInstance::signalEndOfInputStream() {
747    // For non-Surface input, the MediaCodec should convert the call to a
748    // pair of requests (dequeue input buffer, queue input buffer with EOS
749    // flag set).  Seems easier than doing the equivalent from here.
750    sp<GraphicBufferSource> bufferSource(getGraphicBufferSource());
751    if (bufferSource == NULL) {
752        ALOGW("signalEndOfInputStream can only be used with Surface input");
753        return INVALID_OPERATION;
754    };
755    return bufferSource->signalEndOfInputStream();
756}
757
758status_t OMXNodeInstance::allocateBuffer(
759        OMX_U32 portIndex, size_t size, OMX::buffer_id *buffer,
760        void **buffer_data) {
761    Mutex::Autolock autoLock(mLock);
762
763    BufferMeta *buffer_meta = new BufferMeta(size);
764
765    OMX_BUFFERHEADERTYPE *header;
766
767    OMX_ERRORTYPE err = OMX_AllocateBuffer(
768            mHandle, &header, portIndex, buffer_meta, size);
769
770    if (err != OMX_ErrorNone) {
771        ALOGE("OMX_AllocateBuffer failed with error %d (0x%08x)", err, err);
772
773        delete buffer_meta;
774        buffer_meta = NULL;
775
776        *buffer = 0;
777
778        return UNKNOWN_ERROR;
779    }
780
781    CHECK_EQ(header->pAppPrivate, buffer_meta);
782
783    *buffer = makeBufferID(header);
784    *buffer_data = header->pBuffer;
785
786    addActiveBuffer(portIndex, *buffer);
787
788    sp<GraphicBufferSource> bufferSource(getGraphicBufferSource());
789    if (bufferSource != NULL && portIndex == kPortIndexInput) {
790        bufferSource->addCodecBuffer(header);
791    }
792
793    return OK;
794}
795
796status_t OMXNodeInstance::allocateBufferWithBackup(
797        OMX_U32 portIndex, const sp<IMemory> &params,
798        OMX::buffer_id *buffer) {
799    Mutex::Autolock autoLock(mLock);
800
801    BufferMeta *buffer_meta = new BufferMeta(params, true);
802
803    OMX_BUFFERHEADERTYPE *header;
804
805    OMX_ERRORTYPE err = OMX_AllocateBuffer(
806            mHandle, &header, portIndex, buffer_meta, params->size());
807
808    if (err != OMX_ErrorNone) {
809        ALOGE("OMX_AllocateBuffer failed with error %d (0x%08x)", err, err);
810
811        delete buffer_meta;
812        buffer_meta = NULL;
813
814        *buffer = 0;
815
816        return UNKNOWN_ERROR;
817    }
818
819    CHECK_EQ(header->pAppPrivate, buffer_meta);
820
821    *buffer = makeBufferID(header);
822
823    addActiveBuffer(portIndex, *buffer);
824
825    sp<GraphicBufferSource> bufferSource(getGraphicBufferSource());
826    if (bufferSource != NULL && portIndex == kPortIndexInput) {
827        bufferSource->addCodecBuffer(header);
828    }
829
830    return OK;
831}
832
833status_t OMXNodeInstance::freeBuffer(
834        OMX_U32 portIndex, OMX::buffer_id buffer) {
835    Mutex::Autolock autoLock(mLock);
836
837    removeActiveBuffer(portIndex, buffer);
838
839    OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer);
840    BufferMeta *buffer_meta = static_cast<BufferMeta *>(header->pAppPrivate);
841
842    OMX_ERRORTYPE err = OMX_FreeBuffer(mHandle, portIndex, header);
843
844    delete buffer_meta;
845    buffer_meta = NULL;
846    invalidateBufferID(buffer);
847
848    return StatusFromOMXError(err);
849}
850
851status_t OMXNodeInstance::fillBuffer(OMX::buffer_id buffer) {
852    Mutex::Autolock autoLock(mLock);
853
854    OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer);
855    header->nFilledLen = 0;
856    header->nOffset = 0;
857    header->nFlags = 0;
858
859    OMX_ERRORTYPE err = OMX_FillThisBuffer(mHandle, header);
860
861    return StatusFromOMXError(err);
862}
863
864status_t OMXNodeInstance::emptyBuffer(
865        OMX::buffer_id buffer,
866        OMX_U32 rangeOffset, OMX_U32 rangeLength,
867        OMX_U32 flags, OMX_TICKS timestamp) {
868    Mutex::Autolock autoLock(mLock);
869
870    OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer);
871    header->nFilledLen = rangeLength;
872    header->nOffset = rangeOffset;
873    header->nFlags = flags;
874    header->nTimeStamp = timestamp;
875
876    BufferMeta *buffer_meta =
877        static_cast<BufferMeta *>(header->pAppPrivate);
878    buffer_meta->CopyToOMX(header);
879
880    OMX_ERRORTYPE err = OMX_EmptyThisBuffer(mHandle, header);
881
882    return StatusFromOMXError(err);
883}
884
885// like emptyBuffer, but the data is already in header->pBuffer
886status_t OMXNodeInstance::emptyDirectBuffer(
887        OMX_BUFFERHEADERTYPE *header,
888        OMX_U32 rangeOffset, OMX_U32 rangeLength,
889        OMX_U32 flags, OMX_TICKS timestamp) {
890    Mutex::Autolock autoLock(mLock);
891
892    header->nFilledLen = rangeLength;
893    header->nOffset = rangeOffset;
894    header->nFlags = flags;
895    header->nTimeStamp = timestamp;
896
897    OMX_ERRORTYPE err = OMX_EmptyThisBuffer(mHandle, header);
898    if (err != OMX_ErrorNone) {
899        ALOGW("emptyDirectBuffer failed, OMX err=0x%x", err);
900    }
901
902    return StatusFromOMXError(err);
903}
904
905status_t OMXNodeInstance::getExtensionIndex(
906        const char *parameterName, OMX_INDEXTYPE *index) {
907    Mutex::Autolock autoLock(mLock);
908
909    OMX_ERRORTYPE err = OMX_GetExtensionIndex(
910            mHandle, const_cast<char *>(parameterName), index);
911
912    return StatusFromOMXError(err);
913}
914
915status_t OMXNodeInstance::setInternalOption(
916        OMX_U32 portIndex,
917        IOMX::InternalOptionType type,
918        const void *data,
919        size_t size) {
920    switch (type) {
921        case IOMX::INTERNAL_OPTION_SUSPEND:
922        case IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY:
923        case IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP:
924        case IOMX::INTERNAL_OPTION_START_TIME:
925        case IOMX::INTERNAL_OPTION_TIME_LAPSE:
926        {
927            const sp<GraphicBufferSource> &bufferSource =
928                getGraphicBufferSource();
929
930            if (bufferSource == NULL || portIndex != kPortIndexInput) {
931                return ERROR_UNSUPPORTED;
932            }
933
934            if (type == IOMX::INTERNAL_OPTION_SUSPEND) {
935                if (size != sizeof(bool)) {
936                    return INVALID_OPERATION;
937                }
938
939                bool suspend = *(bool *)data;
940                bufferSource->suspend(suspend);
941            } else if (type ==
942                    IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY){
943                if (size != sizeof(int64_t)) {
944                    return INVALID_OPERATION;
945                }
946
947                int64_t delayUs = *(int64_t *)data;
948
949                return bufferSource->setRepeatPreviousFrameDelayUs(delayUs);
950            } else if (type ==
951                    IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP){
952                if (size != sizeof(int64_t)) {
953                    return INVALID_OPERATION;
954                }
955
956                int64_t maxGapUs = *(int64_t *)data;
957
958                return bufferSource->setMaxTimestampGapUs(maxGapUs);
959            } else if (type == IOMX::INTERNAL_OPTION_START_TIME) {
960                if (size != sizeof(int64_t)) {
961                    return INVALID_OPERATION;
962                }
963
964                int64_t skipFramesBeforeUs = *(int64_t *)data;
965
966                bufferSource->setSkipFramesBeforeUs(skipFramesBeforeUs);
967            } else { // IOMX::INTERNAL_OPTION_TIME_LAPSE
968                if (size != sizeof(int64_t) * 2) {
969                    return INVALID_OPERATION;
970                }
971
972                bufferSource->setTimeLapseUs((int64_t *)data);
973            }
974
975            return OK;
976        }
977
978        default:
979            return ERROR_UNSUPPORTED;
980    }
981}
982
983void OMXNodeInstance::onMessage(const omx_message &msg) {
984    const sp<GraphicBufferSource>& bufferSource(getGraphicBufferSource());
985
986    if (msg.type == omx_message::FILL_BUFFER_DONE) {
987        OMX_BUFFERHEADERTYPE *buffer =
988            findBufferHeader(msg.u.extended_buffer_data.buffer);
989
990        BufferMeta *buffer_meta =
991            static_cast<BufferMeta *>(buffer->pAppPrivate);
992
993        buffer_meta->CopyFromOMX(buffer);
994
995        if (bufferSource != NULL) {
996            // fix up the buffer info (especially timestamp) if needed
997            bufferSource->codecBufferFilled(buffer);
998
999            omx_message newMsg = msg;
1000            newMsg.u.extended_buffer_data.timestamp = buffer->nTimeStamp;
1001            mObserver->onMessage(newMsg);
1002            return;
1003        }
1004    } else if (msg.type == omx_message::EMPTY_BUFFER_DONE) {
1005        if (bufferSource != NULL) {
1006            // This is one of the buffers used exclusively by
1007            // GraphicBufferSource.
1008            // Don't dispatch a message back to ACodec, since it doesn't
1009            // know that anyone asked to have the buffer emptied and will
1010            // be very confused.
1011
1012            OMX_BUFFERHEADERTYPE *buffer =
1013                findBufferHeader(msg.u.buffer_data.buffer);
1014
1015            bufferSource->codecBufferEmptied(buffer);
1016            return;
1017        }
1018    }
1019
1020    mObserver->onMessage(msg);
1021}
1022
1023void OMXNodeInstance::onObserverDied(OMXMaster *master) {
1024    ALOGE("!!! Observer died. Quickly, do something, ... anything...");
1025
1026    // Try to force shutdown of the node and hope for the best.
1027    freeNode(master);
1028}
1029
1030void OMXNodeInstance::onGetHandleFailed() {
1031    delete this;
1032}
1033
1034// OMXNodeInstance::OnEvent calls OMX::OnEvent, which then calls here.
1035// Don't try to acquire mLock here -- in rare circumstances this will hang.
1036void OMXNodeInstance::onEvent(
1037        OMX_EVENTTYPE event, OMX_U32 arg1, OMX_U32 arg2) {
1038    const sp<GraphicBufferSource>& bufferSource(getGraphicBufferSource());
1039
1040    if (bufferSource != NULL
1041            && event == OMX_EventCmdComplete
1042            && arg1 == OMX_CommandStateSet
1043            && arg2 == OMX_StateExecuting) {
1044        bufferSource->omxExecuting();
1045    }
1046}
1047
1048// static
1049OMX_ERRORTYPE OMXNodeInstance::OnEvent(
1050        OMX_IN OMX_HANDLETYPE /* hComponent */,
1051        OMX_IN OMX_PTR pAppData,
1052        OMX_IN OMX_EVENTTYPE eEvent,
1053        OMX_IN OMX_U32 nData1,
1054        OMX_IN OMX_U32 nData2,
1055        OMX_IN OMX_PTR pEventData) {
1056    OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
1057    if (instance->mDying) {
1058        return OMX_ErrorNone;
1059    }
1060    return instance->owner()->OnEvent(
1061            instance->nodeID(), eEvent, nData1, nData2, pEventData);
1062}
1063
1064// static
1065OMX_ERRORTYPE OMXNodeInstance::OnEmptyBufferDone(
1066        OMX_IN OMX_HANDLETYPE /* hComponent */,
1067        OMX_IN OMX_PTR pAppData,
1068        OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) {
1069    OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
1070    if (instance->mDying) {
1071        return OMX_ErrorNone;
1072    }
1073    return instance->owner()->OnEmptyBufferDone(instance->nodeID(),
1074            instance->findBufferID(pBuffer), pBuffer);
1075}
1076
1077// static
1078OMX_ERRORTYPE OMXNodeInstance::OnFillBufferDone(
1079        OMX_IN OMX_HANDLETYPE /* hComponent */,
1080        OMX_IN OMX_PTR pAppData,
1081        OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) {
1082    OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
1083    if (instance->mDying) {
1084        return OMX_ErrorNone;
1085    }
1086    return instance->owner()->OnFillBufferDone(instance->nodeID(),
1087            instance->findBufferID(pBuffer), pBuffer);
1088}
1089
1090void OMXNodeInstance::addActiveBuffer(OMX_U32 portIndex, OMX::buffer_id id) {
1091    ActiveBuffer active;
1092    active.mPortIndex = portIndex;
1093    active.mID = id;
1094    mActiveBuffers.push(active);
1095}
1096
1097void OMXNodeInstance::removeActiveBuffer(
1098        OMX_U32 portIndex, OMX::buffer_id id) {
1099    bool found = false;
1100    for (size_t i = 0; i < mActiveBuffers.size(); ++i) {
1101        if (mActiveBuffers[i].mPortIndex == portIndex
1102            && mActiveBuffers[i].mID == id) {
1103            found = true;
1104            mActiveBuffers.removeItemsAt(i);
1105            break;
1106        }
1107    }
1108
1109    if (!found) {
1110        ALOGW("Attempt to remove an active buffer we know nothing about...");
1111    }
1112}
1113
1114void OMXNodeInstance::freeActiveBuffers() {
1115    // Make sure to count down here, as freeBuffer will in turn remove
1116    // the active buffer from the vector...
1117    for (size_t i = mActiveBuffers.size(); i--;) {
1118        freeBuffer(mActiveBuffers[i].mPortIndex, mActiveBuffers[i].mID);
1119    }
1120}
1121
1122#ifdef __LP64__
1123
1124OMX::buffer_id OMXNodeInstance::makeBufferID(OMX_BUFFERHEADERTYPE *bufferHeader) {
1125    if (bufferHeader == NULL) {
1126        return 0;
1127    }
1128    Mutex::Autolock autoLock(mBufferIDLock);
1129    OMX::buffer_id buffer;
1130    do { // handle the very unlikely case of ID overflow
1131        if (++mBufferIDCount == 0) {
1132           ++mBufferIDCount;
1133        }
1134        buffer = (OMX::buffer_id)mBufferIDCount;
1135    } while (mBufferIDToBufferHeader.indexOfKey(buffer) >= 0);
1136    mBufferIDToBufferHeader.add(buffer, bufferHeader);
1137    mBufferHeaderToBufferID.add(bufferHeader, buffer);
1138    return buffer;
1139}
1140
1141OMX_BUFFERHEADERTYPE *OMXNodeInstance::findBufferHeader(OMX::buffer_id buffer) {
1142    if (buffer == 0) {
1143        return NULL;
1144    }
1145    Mutex::Autolock autoLock(mBufferIDLock);
1146    return mBufferIDToBufferHeader.valueFor(buffer);
1147}
1148
1149OMX::buffer_id OMXNodeInstance::findBufferID(OMX_BUFFERHEADERTYPE *bufferHeader) {
1150    if (bufferHeader == NULL) {
1151        return 0;
1152    }
1153    Mutex::Autolock autoLock(mBufferIDLock);
1154    return mBufferHeaderToBufferID.valueFor(bufferHeader);
1155}
1156
1157void OMXNodeInstance::invalidateBufferID(OMX::buffer_id buffer) {
1158    if (buffer == 0) {
1159        return;
1160    }
1161    Mutex::Autolock autoLock(mBufferIDLock);
1162    mBufferHeaderToBufferID.removeItem(mBufferIDToBufferHeader.valueFor(buffer));
1163    mBufferIDToBufferHeader.removeItem(buffer);
1164}
1165
1166#else
1167
1168OMX::buffer_id OMXNodeInstance::makeBufferID(OMX_BUFFERHEADERTYPE *bufferHeader) {
1169    return (OMX::buffer_id)bufferHeader;
1170}
1171
1172OMX_BUFFERHEADERTYPE *OMXNodeInstance::findBufferHeader(OMX::buffer_id buffer) {
1173    return (OMX_BUFFERHEADERTYPE *)buffer;
1174}
1175
1176OMX::buffer_id OMXNodeInstance::findBufferID(OMX_BUFFERHEADERTYPE *bufferHeader) {
1177    return (OMX::buffer_id)bufferHeader;
1178}
1179
1180void OMXNodeInstance::invalidateBufferID(OMX::buffer_id buffer __unused) {
1181}
1182
1183#endif
1184
1185}  // namespace android
1186