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