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