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