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 <inttypes.h>
22
23#include "../include/OMXNodeInstance.h"
24#include "OMXMaster.h"
25#include "OMXUtils.h"
26#include <android/IOMXBufferSource.h>
27
28#include <OMX_Component.h>
29#include <OMX_IndexExt.h>
30#include <OMX_VideoExt.h>
31#include <OMX_AsString.h>
32
33#include <binder/IMemory.h>
34#include <cutils/properties.h>
35#include <gui/BufferQueue.h>
36#include <HardwareAPI.h>
37#include <media/stagefright/foundation/ADebug.h>
38#include <media/stagefright/foundation/ABuffer.h>
39#include <media/stagefright/foundation/ColorUtils.h>
40#include <media/stagefright/MediaErrors.h>
41#include <utils/misc.h>
42#include <utils/NativeHandle.h>
43#include <media/OMXBuffer.h>
44#include <media/vndk/xmlparser/1.0/MediaCodecsXmlParser.h>
45
46#include <hidlmemory/mapping.h>
47
48static const OMX_U32 kPortIndexInput = 0;
49static const OMX_U32 kPortIndexOutput = 1;
50
51#define CLOGW(fmt, ...) ALOGW("[%p:%s] " fmt, mHandle, mName, ##__VA_ARGS__)
52
53#define CLOG_ERROR_IF(cond, fn, err, fmt, ...) \
54    ALOGE_IF(cond, #fn "(%p:%s, " fmt ") ERROR: %s(%#x)", \
55    mHandle, mName, ##__VA_ARGS__, asString(err), err)
56#define CLOG_ERROR(fn, err, fmt, ...) CLOG_ERROR_IF(true, fn, err, fmt, ##__VA_ARGS__)
57#define CLOG_IF_ERROR(fn, err, fmt, ...) \
58    CLOG_ERROR_IF((err) != OMX_ErrorNone, fn, err, fmt, ##__VA_ARGS__)
59
60#define CLOGI_(level, fn, fmt, ...) \
61    ALOGI_IF(DEBUG >= (level), #fn "(%p:%s, " fmt ")", mHandle, mName, ##__VA_ARGS__)
62#define CLOGD_(level, fn, fmt, ...) \
63    ALOGD_IF(DEBUG >= (level), #fn "(%p:%s, " fmt ")", mHandle, mName, ##__VA_ARGS__)
64
65#define CLOG_LIFE(fn, fmt, ...)     CLOGI_(ADebug::kDebugLifeCycle,     fn, fmt, ##__VA_ARGS__)
66#define CLOG_STATE(fn, fmt, ...)    CLOGI_(ADebug::kDebugState,         fn, fmt, ##__VA_ARGS__)
67#define CLOG_CONFIG(fn, fmt, ...)   CLOGI_(ADebug::kDebugConfig,        fn, fmt, ##__VA_ARGS__)
68#define CLOG_INTERNAL(fn, fmt, ...) CLOGD_(ADebug::kDebugInternalState, fn, fmt, ##__VA_ARGS__)
69
70#define CLOG_DEBUG_IF(cond, fn, fmt, ...) \
71    ALOGD_IF(cond, #fn "(%p, " fmt ")", mHandle, ##__VA_ARGS__)
72
73#define CLOG_BUFFER(fn, fmt, ...) \
74    CLOG_DEBUG_IF(DEBUG >= ADebug::kDebugAll, fn, fmt, ##__VA_ARGS__)
75#define CLOG_BUMPED_BUFFER(fn, fmt, ...) \
76    CLOG_DEBUG_IF(DEBUG_BUMP >= ADebug::kDebugAll, fn, fmt, ##__VA_ARGS__)
77
78/* buffer formatting */
79#define BUFFER_FMT(port, fmt, ...) "%s:%u " fmt, portString(port), (port), ##__VA_ARGS__
80#define NEW_BUFFER_FMT(buffer_id, port, fmt, ...) \
81    BUFFER_FMT(port, fmt ") (#%zu => %#x", ##__VA_ARGS__, mActiveBuffers.size(), (buffer_id))
82
83#define SIMPLE_BUFFER(port, size, data) BUFFER_FMT(port, "%zu@%p", (size), (data))
84#define SIMPLE_NEW_BUFFER(buffer_id, port, size, data) \
85    NEW_BUFFER_FMT(buffer_id, port, "%zu@%p", (size), (data))
86
87#define EMPTY_BUFFER(addr, header, fenceFd) "%#x [%u@%p fc=%d]", \
88    (addr), (header)->nAllocLen, (header)->pBuffer, (fenceFd)
89#define FULL_BUFFER(addr, header, fenceFd) "%#" PRIxPTR " [%u@%p (%u..+%u) f=%x ts=%lld fc=%d]", \
90    (intptr_t)(addr), (header)->nAllocLen, (header)->pBuffer, \
91    (header)->nOffset, (header)->nFilledLen, (header)->nFlags, (header)->nTimeStamp, (fenceFd)
92
93#define WITH_STATS_WRAPPER(fmt, ...) fmt " { IN=%zu/%zu OUT=%zu/%zu }", ##__VA_ARGS__, \
94    mInputBuffersWithCodec.size(), mNumPortBuffers[kPortIndexInput], \
95    mOutputBuffersWithCodec.size(), mNumPortBuffers[kPortIndexOutput]
96// TRICKY: this is needed so formatting macros expand before substitution
97#define WITH_STATS(fmt, ...) WITH_STATS_WRAPPER(fmt, ##__VA_ARGS__)
98
99namespace android {
100
101struct BufferMeta {
102    explicit BufferMeta(
103            const sp<IMemory> &mem, const sp<IHidlMemory> &hidlMemory,
104            OMX_U32 portIndex, bool copy, OMX_U8 *backup)
105        : mMem(mem),
106          mHidlMemory(hidlMemory),
107          mCopyFromOmx(portIndex == kPortIndexOutput && copy),
108          mCopyToOmx(portIndex == kPortIndexInput && copy),
109          mPortIndex(portIndex),
110          mBackup(backup) {
111    }
112
113    explicit BufferMeta(OMX_U32 portIndex)
114        : mCopyFromOmx(false),
115          mCopyToOmx(false),
116          mPortIndex(portIndex),
117          mBackup(NULL) {
118    }
119
120    explicit BufferMeta(const sp<GraphicBuffer> &graphicBuffer, OMX_U32 portIndex)
121        : mGraphicBuffer(graphicBuffer),
122          mCopyFromOmx(false),
123          mCopyToOmx(false),
124          mPortIndex(portIndex),
125          mBackup(NULL) {
126    }
127
128    OMX_U8 *getPointer() {
129        return mMem.get() ? static_cast<OMX_U8*>(mMem->pointer()) :
130                mHidlMemory.get() ? static_cast<OMX_U8*>(
131                static_cast<void*>(mHidlMemory->getPointer())) : nullptr;
132    }
133
134    void CopyFromOMX(const OMX_BUFFERHEADERTYPE *header) {
135        if (!mCopyFromOmx) {
136            return;
137        }
138
139        // check component returns proper range
140        sp<ABuffer> codec = getBuffer(header, true /* limit */);
141
142        memcpy(getPointer() + header->nOffset, codec->data(), codec->size());
143    }
144
145    void CopyToOMX(const OMX_BUFFERHEADERTYPE *header) {
146        if (!mCopyToOmx) {
147            return;
148        }
149
150        memcpy(header->pBuffer + header->nOffset,
151                getPointer() + header->nOffset,
152                header->nFilledLen);
153    }
154
155    // return the codec buffer
156    sp<ABuffer> getBuffer(const OMX_BUFFERHEADERTYPE *header, bool limit) {
157        sp<ABuffer> buf = new ABuffer(header->pBuffer, header->nAllocLen);
158        if (limit) {
159            if (header->nOffset + header->nFilledLen > header->nOffset
160                    && header->nOffset + header->nFilledLen <= header->nAllocLen) {
161                buf->setRange(header->nOffset, header->nFilledLen);
162            } else {
163                buf->setRange(0, 0);
164            }
165        }
166        return buf;
167    }
168
169    void setGraphicBuffer(const sp<GraphicBuffer> &graphicBuffer) {
170        mGraphicBuffer = graphicBuffer;
171    }
172
173    void setNativeHandle(const sp<NativeHandle> &nativeHandle) {
174        mNativeHandle = nativeHandle;
175    }
176
177    OMX_U32 getPortIndex() {
178        return mPortIndex;
179    }
180
181    ~BufferMeta() {
182        delete[] mBackup;
183    }
184
185private:
186    sp<GraphicBuffer> mGraphicBuffer;
187    sp<NativeHandle> mNativeHandle;
188    sp<IMemory> mMem;
189    sp<IHidlMemory> mHidlMemory;
190    bool mCopyFromOmx;
191    bool mCopyToOmx;
192    OMX_U32 mPortIndex;
193    OMX_U8 *mBackup;
194
195    BufferMeta(const BufferMeta &);
196    BufferMeta &operator=(const BufferMeta &);
197};
198
199// static
200OMX_CALLBACKTYPE OMXNodeInstance::kCallbacks = {
201    &OnEvent, &OnEmptyBufferDone, &OnFillBufferDone
202};
203
204static inline const char *portString(OMX_U32 portIndex) {
205    switch (portIndex) {
206        case kPortIndexInput:  return "Input";
207        case kPortIndexOutput: return "Output";
208        case ~0U:              return "All";
209        default:               return "port";
210    }
211}
212
213////////////////////////////////////////////////////////////////////////////////
214
215// This provides the underlying Thread used by CallbackDispatcher.
216// Note that deriving CallbackDispatcher from Thread does not work.
217
218struct OMXNodeInstance::CallbackDispatcherThread : public Thread {
219    explicit CallbackDispatcherThread(CallbackDispatcher *dispatcher)
220        : mDispatcher(dispatcher) {
221    }
222
223private:
224    CallbackDispatcher *mDispatcher;
225
226    bool threadLoop();
227
228    CallbackDispatcherThread(const CallbackDispatcherThread &);
229    CallbackDispatcherThread &operator=(const CallbackDispatcherThread &);
230};
231
232////////////////////////////////////////////////////////////////////////////////
233
234struct OMXNodeInstance::CallbackDispatcher : public RefBase {
235    explicit CallbackDispatcher(const sp<OMXNodeInstance> &owner);
236
237    // Posts |msg| to the listener's queue. If |realTime| is true, the listener thread is notified
238    // that a new message is available on the queue. Otherwise, the message stays on the queue, but
239    // the listener is not notified of it. It will process this message when a subsequent message
240    // is posted with |realTime| set to true.
241    void post(const omx_message &msg, bool realTime = true);
242
243    bool loop();
244
245protected:
246    virtual ~CallbackDispatcher();
247
248private:
249    Mutex mLock;
250
251    sp<OMXNodeInstance> const mOwner;
252    bool mDone;
253    Condition mQueueChanged;
254    std::list<omx_message> mQueue;
255
256    sp<CallbackDispatcherThread> mThread;
257
258    void dispatch(std::list<omx_message> &messages);
259
260    CallbackDispatcher(const CallbackDispatcher &);
261    CallbackDispatcher &operator=(const CallbackDispatcher &);
262};
263
264OMXNodeInstance::CallbackDispatcher::CallbackDispatcher(const sp<OMXNodeInstance> &owner)
265    : mOwner(owner),
266      mDone(false) {
267    mThread = new CallbackDispatcherThread(this);
268    mThread->run("OMXCallbackDisp", ANDROID_PRIORITY_FOREGROUND);
269}
270
271OMXNodeInstance::CallbackDispatcher::~CallbackDispatcher() {
272    {
273        Mutex::Autolock autoLock(mLock);
274
275        mDone = true;
276        mQueueChanged.signal();
277    }
278
279    // A join on self can happen if the last ref to CallbackDispatcher
280    // is released within the CallbackDispatcherThread loop
281    status_t status = mThread->join();
282    if (status != WOULD_BLOCK) {
283        // Other than join to self, the only other error return codes are
284        // whatever readyToRun() returns, and we don't override that
285        CHECK_EQ(status, (status_t)NO_ERROR);
286    }
287}
288
289void OMXNodeInstance::CallbackDispatcher::post(const omx_message &msg, bool realTime) {
290    Mutex::Autolock autoLock(mLock);
291
292    mQueue.push_back(msg);
293    if (realTime) {
294        mQueueChanged.signal();
295    }
296}
297
298void OMXNodeInstance::CallbackDispatcher::dispatch(std::list<omx_message> &messages) {
299    if (mOwner == NULL) {
300        ALOGV("Would have dispatched a message to a node that's already gone.");
301        return;
302    }
303    mOwner->onMessages(messages);
304}
305
306bool OMXNodeInstance::CallbackDispatcher::loop() {
307    for (;;) {
308        std::list<omx_message> messages;
309
310        {
311            Mutex::Autolock autoLock(mLock);
312            while (!mDone && mQueue.empty()) {
313                mQueueChanged.wait(mLock);
314            }
315
316            if (mDone) {
317                break;
318            }
319
320            messages.swap(mQueue);
321        }
322
323        dispatch(messages);
324    }
325
326    return false;
327}
328
329////////////////////////////////////////////////////////////////////////////////
330
331bool OMXNodeInstance::CallbackDispatcherThread::threadLoop() {
332    return mDispatcher->loop();
333}
334
335////////////////////////////////////////////////////////////////////////////////
336
337OMXNodeInstance::OMXNodeInstance(
338        OmxNodeOwner *owner, const sp<IOMXObserver> &observer, const char *name)
339    : mOwner(owner),
340      mHandle(NULL),
341      mObserver(observer),
342      mDying(false),
343      mSailed(false),
344      mQueriedProhibitedExtensions(false),
345      mQuirks(0),
346      mBufferIDCount(0),
347      mRestorePtsFailed(false),
348      mMaxTimestampGapUs(-1ll),
349      mPrevOriginalTimeUs(-1ll),
350      mPrevModifiedTimeUs(-1ll)
351{
352    mName = ADebug::GetDebugName(name);
353    DEBUG = ADebug::GetDebugLevelFromProperty(name, "debug.stagefright.omx-debug");
354    ALOGV("debug level for %s is %d", name, DEBUG);
355    DEBUG_BUMP = DEBUG;
356    mNumPortBuffers[0] = 0;
357    mNumPortBuffers[1] = 0;
358    mDebugLevelBumpPendingBuffers[0] = 0;
359    mDebugLevelBumpPendingBuffers[1] = 0;
360    mMetadataType[0] = kMetadataBufferTypeInvalid;
361    mMetadataType[1] = kMetadataBufferTypeInvalid;
362    mPortMode[0] = IOMX::kPortModePresetByteBuffer;
363    mPortMode[1] = IOMX::kPortModePresetByteBuffer;
364    mSecureBufferType[0] = kSecureBufferTypeUnknown;
365    mSecureBufferType[1] = kSecureBufferTypeUnknown;
366    mIsSecure = AString(name).endsWith(".secure");
367    mLegacyAdaptiveExperiment = ADebug::isExperimentEnabled("legacy-adaptive");
368}
369
370OMXNodeInstance::~OMXNodeInstance() {
371    free(mName);
372    CHECK(mHandle == NULL);
373}
374
375void OMXNodeInstance::setHandle(OMX_HANDLETYPE handle) {
376    CLOG_LIFE(allocateNode, "handle=%p", handle);
377    CHECK(mHandle == NULL);
378    mHandle = handle;
379    if (handle != NULL) {
380        mDispatcher = new CallbackDispatcher(this);
381    }
382}
383
384sp<IOMXBufferSource> OMXNodeInstance::getBufferSource() {
385    Mutex::Autolock autoLock(mOMXBufferSourceLock);
386    return mOMXBufferSource;
387}
388
389void OMXNodeInstance::setBufferSource(const sp<IOMXBufferSource>& bufferSource) {
390    Mutex::Autolock autoLock(mOMXBufferSourceLock);
391    CLOG_INTERNAL(setBufferSource, "%p", bufferSource.get());
392    mOMXBufferSource = bufferSource;
393}
394
395OMX_HANDLETYPE OMXNodeInstance::handle() {
396    return mHandle;
397}
398
399sp<IOMXObserver> OMXNodeInstance::observer() {
400    return mObserver;
401}
402
403status_t OMXNodeInstance::freeNode() {
404    CLOG_LIFE(freeNode, "handle=%p", mHandle);
405    static int32_t kMaxNumIterations = 10;
406
407    // Transition the node from its current state all the way down
408    // to "Loaded".
409    // This ensures that all active buffers are properly freed even
410    // for components that don't do this themselves on a call to
411    // "FreeHandle".
412
413    // The code below may trigger some more events to be dispatched
414    // by the OMX component - we want to ignore them as our client
415    // does not expect them.
416    bool expected = false;
417    if (!mDying.compare_exchange_strong(expected, true)) {
418        // exit if we have already freed the node or doing so right now.
419        // NOTE: this ensures that the block below executes at most once.
420        ALOGV("Already dying");
421        return OK;
422    }
423
424    OMX_STATETYPE state;
425    CHECK_EQ(OMX_GetState(mHandle, &state), OMX_ErrorNone);
426    switch (state) {
427        case OMX_StateExecuting:
428        {
429            ALOGV("forcing Executing->Idle");
430            sendCommand(OMX_CommandStateSet, OMX_StateIdle);
431            OMX_ERRORTYPE err;
432            int32_t iteration = 0;
433            while ((err = OMX_GetState(mHandle, &state)) == OMX_ErrorNone
434                    && state != OMX_StateIdle
435                    && state != OMX_StateInvalid) {
436                if (++iteration > kMaxNumIterations) {
437                    CLOGW("failed to enter Idle state (now %s(%d), aborting.",
438                            asString(state), state);
439                    state = OMX_StateInvalid;
440                    break;
441                }
442
443                usleep(100000);
444            }
445            CHECK_EQ(err, OMX_ErrorNone);
446
447            if (state == OMX_StateInvalid) {
448                break;
449            }
450
451            // fall through
452        }
453
454        case OMX_StateIdle:
455        {
456            ALOGV("forcing Idle->Loaded");
457            sendCommand(OMX_CommandStateSet, OMX_StateLoaded);
458
459            freeActiveBuffers();
460
461            OMX_ERRORTYPE err;
462            int32_t iteration = 0;
463            while ((err = OMX_GetState(mHandle, &state)) == OMX_ErrorNone
464                    && state != OMX_StateLoaded
465                    && state != OMX_StateInvalid) {
466                if (++iteration > kMaxNumIterations) {
467                    CLOGW("failed to enter Loaded state (now %s(%d), aborting.",
468                            asString(state), state);
469                    state = OMX_StateInvalid;
470                    break;
471                }
472
473                ALOGV("waiting for Loaded state...");
474                usleep(100000);
475            }
476            CHECK_EQ(err, OMX_ErrorNone);
477
478            // fall through
479        }
480
481        case OMX_StateLoaded:
482        case OMX_StateInvalid:
483            break;
484
485        default:
486            LOG_ALWAYS_FATAL("unknown state %s(%#x).", asString(state), state);
487            break;
488    }
489    status_t err = mOwner->freeNode(this);
490
491    mDispatcher.clear();
492    mOMXBufferSource.clear();
493
494    mHandle = NULL;
495    CLOG_IF_ERROR(freeNode, err, "");
496    free(mName);
497    mName = NULL;
498
499    ALOGV("OMXNodeInstance going away.");
500
501    return err;
502}
503
504status_t OMXNodeInstance::sendCommand(
505        OMX_COMMANDTYPE cmd, OMX_S32 param) {
506    const sp<IOMXBufferSource> bufferSource(getBufferSource());
507    if (bufferSource != NULL && cmd == OMX_CommandStateSet) {
508        if (param == OMX_StateIdle) {
509            // Initiating transition from Executing -> Idle
510            // ACodec is waiting for all buffers to be returned, do NOT
511            // submit any more buffers to the codec.
512            bufferSource->onOmxIdle();
513        } else if (param == OMX_StateLoaded) {
514            // Initiating transition from Idle/Executing -> Loaded
515            // Buffers are about to be freed.
516            bufferSource->onOmxLoaded();
517            setBufferSource(NULL);
518        }
519
520        // fall through
521    }
522
523    Mutex::Autolock autoLock(mLock);
524
525    if (cmd == OMX_CommandStateSet) {
526        // There are no configurations past first StateSet command.
527        mSailed = true;
528    }
529
530    // bump internal-state debug level for 2 input and output frames past a command
531    {
532        Mutex::Autolock _l(mDebugLock);
533        bumpDebugLevel_l(2 /* numInputBuffers */, 2 /* numOutputBuffers */);
534    }
535
536    const char *paramString =
537        cmd == OMX_CommandStateSet ? asString((OMX_STATETYPE)param) : portString(param);
538    CLOG_STATE(sendCommand, "%s(%d), %s(%d)", asString(cmd), cmd, paramString, param);
539    OMX_ERRORTYPE err = OMX_SendCommand(mHandle, cmd, param, NULL);
540    CLOG_IF_ERROR(sendCommand, err, "%s(%d), %s(%d)", asString(cmd), cmd, paramString, param);
541    return StatusFromOMXError(err);
542}
543
544bool OMXNodeInstance::isProhibitedIndex_l(OMX_INDEXTYPE index) {
545    // these extensions can only be used from OMXNodeInstance, not by clients directly.
546    static const char *restricted_extensions[] = {
547        "OMX.google.android.index.storeMetaDataInBuffers",
548        "OMX.google.android.index.storeANWBufferInMetadata",
549        "OMX.google.android.index.prepareForAdaptivePlayback",
550        "OMX.google.android.index.configureVideoTunnelMode",
551        "OMX.google.android.index.useAndroidNativeBuffer2",
552        "OMX.google.android.index.useAndroidNativeBuffer",
553        "OMX.google.android.index.enableAndroidNativeBuffers",
554        "OMX.google.android.index.allocateNativeHandle",
555        "OMX.google.android.index.getAndroidNativeBufferUsage",
556    };
557
558    if ((index > OMX_IndexComponentStartUnused && index < OMX_IndexComponentEndUnused)
559            || (index > OMX_IndexPortStartUnused && index < OMX_IndexPortEndUnused)
560            || (index > OMX_IndexAudioStartUnused && index < OMX_IndexAudioEndUnused)
561            || (index > OMX_IndexVideoStartUnused && index < OMX_IndexVideoEndUnused)
562            || (index > OMX_IndexCommonStartUnused && index < OMX_IndexCommonEndUnused)
563            || (index > (OMX_INDEXTYPE)OMX_IndexExtAudioStartUnused
564                    && index < (OMX_INDEXTYPE)OMX_IndexExtAudioEndUnused)
565            || (index > (OMX_INDEXTYPE)OMX_IndexExtVideoStartUnused
566                    && index < (OMX_INDEXTYPE)OMX_IndexExtVideoEndUnused)
567            || (index > (OMX_INDEXTYPE)OMX_IndexExtOtherStartUnused
568                    && index < (OMX_INDEXTYPE)OMX_IndexExtOtherEndUnused)) {
569        return false;
570    }
571
572    if (!mQueriedProhibitedExtensions) {
573        for (size_t i = 0; i < NELEM(restricted_extensions); ++i) {
574            OMX_INDEXTYPE ext;
575            if (OMX_GetExtensionIndex(mHandle, (OMX_STRING)restricted_extensions[i], &ext) == OMX_ErrorNone) {
576                mProhibitedExtensions.add(ext);
577            }
578        }
579        mQueriedProhibitedExtensions = true;
580    }
581
582    return mProhibitedExtensions.indexOf(index) >= 0;
583}
584
585status_t OMXNodeInstance::getParameter(
586        OMX_INDEXTYPE index, void *params, size_t /* size */) {
587    Mutex::Autolock autoLock(mLock);
588
589    if (isProhibitedIndex_l(index)) {
590        android_errorWriteLog(0x534e4554, "29422020");
591        return BAD_INDEX;
592    }
593
594    OMX_ERRORTYPE err = OMX_GetParameter(mHandle, index, params);
595    OMX_INDEXEXTTYPE extIndex = (OMX_INDEXEXTTYPE)index;
596    // some errors are expected for getParameter
597    if (err != OMX_ErrorNoMore) {
598        CLOG_IF_ERROR(getParameter, err, "%s(%#x)", asString(extIndex), index);
599    }
600    return StatusFromOMXError(err);
601}
602
603status_t OMXNodeInstance::setParameter(
604        OMX_INDEXTYPE index, const void *params, size_t size) {
605    Mutex::Autolock autoLock(mLock);
606    OMX_INDEXEXTTYPE extIndex = (OMX_INDEXEXTTYPE)index;
607    CLOG_CONFIG(setParameter, "%s(%#x), %zu@%p)", asString(extIndex), index, size, params);
608
609    if (extIndex == OMX_IndexParamMaxFrameDurationForBitrateControl) {
610        return setMaxPtsGapUs(params, size);
611    }
612
613    if (isProhibitedIndex_l(index)) {
614        android_errorWriteLog(0x534e4554, "29422020");
615        return BAD_INDEX;
616    }
617
618    OMX_ERRORTYPE err = OMX_SetParameter(
619            mHandle, index, const_cast<void *>(params));
620    CLOG_IF_ERROR(setParameter, err, "%s(%#x)", asString(extIndex), index);
621    return StatusFromOMXError(err);
622}
623
624status_t OMXNodeInstance::getConfig(
625        OMX_INDEXTYPE index, void *params, size_t /* size */) {
626    Mutex::Autolock autoLock(mLock);
627
628    if (isProhibitedIndex_l(index)) {
629        android_errorWriteLog(0x534e4554, "29422020");
630        return BAD_INDEX;
631    }
632
633    OMX_ERRORTYPE err = OMX_GetConfig(mHandle, index, params);
634    OMX_INDEXEXTTYPE extIndex = (OMX_INDEXEXTTYPE)index;
635    // some errors are expected for getConfig
636    if (err != OMX_ErrorNoMore) {
637        CLOG_IF_ERROR(getConfig, err, "%s(%#x)", asString(extIndex), index);
638    }
639    return StatusFromOMXError(err);
640}
641
642status_t OMXNodeInstance::setConfig(
643        OMX_INDEXTYPE index, const void *params, size_t size) {
644    Mutex::Autolock autoLock(mLock);
645    OMX_INDEXEXTTYPE extIndex = (OMX_INDEXEXTTYPE)index;
646    CLOG_CONFIG(setConfig, "%s(%#x), %zu@%p)", asString(extIndex), index, size, params);
647
648    if (isProhibitedIndex_l(index)) {
649        android_errorWriteLog(0x534e4554, "29422020");
650        return BAD_INDEX;
651    }
652
653    OMX_ERRORTYPE err = OMX_SetConfig(
654            mHandle, index, const_cast<void *>(params));
655    CLOG_IF_ERROR(setConfig, err, "%s(%#x)", asString(extIndex), index);
656    return StatusFromOMXError(err);
657}
658
659status_t OMXNodeInstance::setPortMode(OMX_U32 portIndex, IOMX::PortMode mode) {
660    Mutex::Autolock autoLock(mLock);
661
662    if (portIndex >= NELEM(mPortMode)) {
663        ALOGE("b/31385713, portIndex(%u)", portIndex);
664        android_errorWriteLog(0x534e4554, "31385713");
665        return BAD_VALUE;
666    }
667
668    CLOG_CONFIG(setPortMode, "%s(%d), port %d", asString(mode), mode, portIndex);
669
670    switch (mode) {
671    case IOMX::kPortModeDynamicANWBuffer:
672    {
673        if (portIndex == kPortIndexOutput) {
674            if (mLegacyAdaptiveExperiment) {
675                CLOG_INTERNAL(setPortMode, "Legacy adaptive experiment: "
676                        "not setting port mode to %s(%d) on output",
677                        asString(mode), mode);
678                return StatusFromOMXError(OMX_ErrorUnsupportedIndex);
679            }
680
681            status_t err = enableNativeBuffers_l(
682                    portIndex, OMX_TRUE /*graphic*/, OMX_TRUE);
683            if (err != OK) {
684                return err;
685            }
686        }
687        (void)enableNativeBuffers_l(portIndex, OMX_FALSE /*graphic*/, OMX_FALSE);
688        return storeMetaDataInBuffers_l(portIndex, OMX_TRUE, NULL);
689    }
690
691    case IOMX::kPortModeDynamicNativeHandle:
692    {
693        if (portIndex != kPortIndexInput) {
694            CLOG_ERROR(setPortMode, BAD_VALUE,
695                    "%s(%d) mode is only supported on input port", asString(mode), mode);
696            return BAD_VALUE;
697        }
698        (void)enableNativeBuffers_l(portIndex, OMX_TRUE /*graphic*/, OMX_FALSE);
699        (void)enableNativeBuffers_l(portIndex, OMX_FALSE /*graphic*/, OMX_FALSE);
700
701        MetadataBufferType metaType = kMetadataBufferTypeNativeHandleSource;
702        return storeMetaDataInBuffers_l(portIndex, OMX_TRUE, &metaType);
703    }
704
705    case IOMX::kPortModePresetSecureBuffer:
706    {
707        // Allow on both input and output.
708        (void)storeMetaDataInBuffers_l(portIndex, OMX_FALSE, NULL);
709        (void)enableNativeBuffers_l(portIndex, OMX_TRUE /*graphic*/, OMX_FALSE);
710        return enableNativeBuffers_l(portIndex, OMX_FALSE /*graphic*/, OMX_TRUE);
711    }
712
713    case IOMX::kPortModePresetANWBuffer:
714    {
715        if (portIndex != kPortIndexOutput) {
716            CLOG_ERROR(setPortMode, BAD_VALUE,
717                    "%s(%d) mode is only supported on output port", asString(mode), mode);
718            return BAD_VALUE;
719        }
720
721        // Check if we're simulating legacy mode with metadata mode,
722        // if so, enable metadata mode.
723        if (mLegacyAdaptiveExperiment) {
724            if (storeMetaDataInBuffers_l(portIndex, OMX_TRUE, NULL) == OK) {
725                CLOG_INTERNAL(setPortMode, "Legacy adaptive experiment: "
726                        "metdata mode enabled successfully");
727                return OK;
728            }
729
730            CLOG_INTERNAL(setPortMode, "Legacy adaptive experiment: "
731                    "unable to enable metadata mode on output");
732
733            mLegacyAdaptiveExperiment = false;
734        }
735
736        // Disable secure buffer and enable graphic buffer
737        (void)enableNativeBuffers_l(portIndex, OMX_FALSE /*graphic*/, OMX_FALSE);
738        status_t err = enableNativeBuffers_l(portIndex, OMX_TRUE /*graphic*/, OMX_TRUE);
739        if (err != OK) {
740            return err;
741        }
742
743        // Not running experiment, or metadata is not supported.
744        // Disable metadata mode and use legacy mode.
745        (void)storeMetaDataInBuffers_l(portIndex, OMX_FALSE, NULL);
746        return OK;
747    }
748
749    case IOMX::kPortModePresetByteBuffer:
750    {
751        // Disable secure buffer, native buffer and metadata.
752        (void)enableNativeBuffers_l(portIndex, OMX_TRUE /*graphic*/, OMX_FALSE);
753        (void)enableNativeBuffers_l(portIndex, OMX_FALSE /*graphic*/, OMX_FALSE);
754        (void)storeMetaDataInBuffers_l(portIndex, OMX_FALSE, NULL);
755        return OK;
756    }
757
758    default:
759        break;
760    }
761
762    CLOG_ERROR(setPortMode, BAD_VALUE, "invalid port mode %d", mode);
763    return BAD_VALUE;
764}
765
766status_t OMXNodeInstance::enableNativeBuffers_l(
767        OMX_U32 portIndex, OMX_BOOL graphic, OMX_BOOL enable) {
768    if (portIndex >= NELEM(mSecureBufferType)) {
769        ALOGE("b/31385713, portIndex(%u)", portIndex);
770        android_errorWriteLog(0x534e4554, "31385713");
771        return BAD_VALUE;
772    }
773
774    CLOG_CONFIG(enableNativeBuffers, "%s:%u%s, %d", portString(portIndex), portIndex,
775                graphic ? ", graphic" : "", enable);
776    OMX_STRING name = const_cast<OMX_STRING>(
777            graphic ? "OMX.google.android.index.enableAndroidNativeBuffers"
778                    : "OMX.google.android.index.allocateNativeHandle");
779
780    OMX_INDEXTYPE index;
781    OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
782
783    if (err == OMX_ErrorNone) {
784        EnableAndroidNativeBuffersParams params;
785        InitOMXParams(&params);
786        params.nPortIndex = portIndex;
787        params.enable = enable;
788
789        err = OMX_SetParameter(mHandle, index, &params);
790        CLOG_IF_ERROR(setParameter, err, "%s(%#x): %s:%u en=%d", name, index,
791                      portString(portIndex), portIndex, enable);
792        if (!graphic) {
793            if (err == OMX_ErrorNone) {
794                mSecureBufferType[portIndex] =
795                    enable ? kSecureBufferTypeNativeHandle : kSecureBufferTypeOpaque;
796            } else if (mSecureBufferType[portIndex] == kSecureBufferTypeUnknown) {
797                mSecureBufferType[portIndex] = kSecureBufferTypeOpaque;
798            }
799        }
800    } else {
801        CLOG_ERROR_IF(enable, getExtensionIndex, err, "%s", name);
802        if (!graphic) {
803            // Extension not supported, check for manual override with system property
804            // This is a temporary workaround until partners support the OMX extension
805            if (property_get_bool("media.mediadrmservice.enable", false)) {
806                CLOG_CONFIG(enableNativeBuffers, "system property override: using native-handles");
807                mSecureBufferType[portIndex] = kSecureBufferTypeNativeHandle;
808            } else if (mSecureBufferType[portIndex] == kSecureBufferTypeUnknown) {
809                mSecureBufferType[portIndex] = kSecureBufferTypeOpaque;
810            }
811            err = OMX_ErrorNone;
812        }
813    }
814
815    return StatusFromOMXError(err);
816}
817
818status_t OMXNodeInstance::getGraphicBufferUsage(
819        OMX_U32 portIndex, OMX_U32* usage) {
820    Mutex::Autolock autoLock(mLock);
821
822    OMX_INDEXTYPE index;
823    OMX_STRING name = const_cast<OMX_STRING>(
824            "OMX.google.android.index.getAndroidNativeBufferUsage");
825    OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
826
827    if (err != OMX_ErrorNone) {
828        CLOG_ERROR(getExtensionIndex, err, "%s", name);
829        return StatusFromOMXError(err);
830    }
831
832    GetAndroidNativeBufferUsageParams params;
833    InitOMXParams(&params);
834    params.nPortIndex = portIndex;
835
836    err = OMX_GetParameter(mHandle, index, &params);
837    if (err != OMX_ErrorNone) {
838        CLOG_ERROR(getParameter, err, "%s(%#x): %s:%u", name, index,
839                portString(portIndex), portIndex);
840        return StatusFromOMXError(err);
841    }
842
843    *usage = params.nUsage;
844
845    return OK;
846}
847
848status_t OMXNodeInstance::storeMetaDataInBuffers_l(
849        OMX_U32 portIndex, OMX_BOOL enable, MetadataBufferType *type) {
850    if (mSailed) {
851        android_errorWriteLog(0x534e4554, "29422020");
852        return INVALID_OPERATION;
853    }
854    if (portIndex != kPortIndexInput && portIndex != kPortIndexOutput) {
855        android_errorWriteLog(0x534e4554, "26324358");
856        if (type != NULL) {
857            *type = kMetadataBufferTypeInvalid;
858        }
859        return BAD_VALUE;
860    }
861
862    OMX_INDEXTYPE index;
863    OMX_STRING name = const_cast<OMX_STRING>(
864            "OMX.google.android.index.storeMetaDataInBuffers");
865
866    OMX_STRING nativeBufferName = const_cast<OMX_STRING>(
867            "OMX.google.android.index.storeANWBufferInMetadata");
868    MetadataBufferType negotiatedType;
869    MetadataBufferType requestedType = type != NULL ? *type : kMetadataBufferTypeANWBuffer;
870
871    StoreMetaDataInBuffersParams params;
872    InitOMXParams(&params);
873    params.nPortIndex = portIndex;
874    params.bStoreMetaData = enable;
875
876    OMX_ERRORTYPE err =
877        requestedType == kMetadataBufferTypeANWBuffer
878                ? OMX_GetExtensionIndex(mHandle, nativeBufferName, &index)
879                : OMX_ErrorUnsupportedIndex;
880    OMX_ERRORTYPE xerr = err;
881    if (err == OMX_ErrorNone) {
882        err = OMX_SetParameter(mHandle, index, &params);
883        if (err == OMX_ErrorNone) {
884            name = nativeBufferName; // set name for debugging
885            negotiatedType = requestedType;
886        }
887    }
888    if (err != OMX_ErrorNone) {
889        err = OMX_GetExtensionIndex(mHandle, name, &index);
890        xerr = err;
891        if (err == OMX_ErrorNone) {
892            negotiatedType =
893                requestedType == kMetadataBufferTypeANWBuffer
894                        ? kMetadataBufferTypeGrallocSource : requestedType;
895            err = OMX_SetParameter(mHandle, index, &params);
896        }
897        if (err == OMX_ErrorBadParameter) {
898            err = OMX_ErrorUnsupportedIndex;
899        }
900    }
901
902    // don't log loud error if component does not support metadata mode on the output
903    if (err != OMX_ErrorNone) {
904        if (err == OMX_ErrorUnsupportedIndex && portIndex == kPortIndexOutput) {
905            CLOGW("component does not support metadata mode; using fallback");
906        } else if (xerr != OMX_ErrorNone) {
907            CLOG_ERROR(getExtensionIndex, xerr, "%s", name);
908        } else {
909            CLOG_ERROR(setParameter, err, "%s(%#x): %s:%u en=%d type=%d", name, index,
910                    portString(portIndex), portIndex, enable, negotiatedType);
911        }
912        negotiatedType = mMetadataType[portIndex];
913    } else {
914        if (!enable) {
915            negotiatedType = kMetadataBufferTypeInvalid;
916        }
917        mMetadataType[portIndex] = negotiatedType;
918    }
919    CLOG_CONFIG(storeMetaDataInBuffers, "%s:%u %srequested %s:%d negotiated %s:%d",
920            portString(portIndex), portIndex, enable ? "" : "UN",
921            asString(requestedType), requestedType, asString(negotiatedType), negotiatedType);
922
923    if (type != NULL) {
924        *type = negotiatedType;
925    }
926
927    return StatusFromOMXError(err);
928}
929
930status_t OMXNodeInstance::prepareForAdaptivePlayback(
931        OMX_U32 portIndex, OMX_BOOL enable, OMX_U32 maxFrameWidth,
932        OMX_U32 maxFrameHeight) {
933    Mutex::Autolock autolock(mLock);
934    if (mSailed) {
935        android_errorWriteLog(0x534e4554, "29422020");
936        return INVALID_OPERATION;
937    }
938    CLOG_CONFIG(prepareForAdaptivePlayback, "%s:%u en=%d max=%ux%u",
939            portString(portIndex), portIndex, enable, maxFrameWidth, maxFrameHeight);
940
941    if (mLegacyAdaptiveExperiment) {
942        CLOG_INTERNAL(prepareForAdaptivePlayback,
943                "Legacy adaptive experiment: reporting success");
944        return OK;
945    }
946
947    OMX_INDEXTYPE index;
948    OMX_STRING name = const_cast<OMX_STRING>(
949            "OMX.google.android.index.prepareForAdaptivePlayback");
950
951    OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
952    if (err != OMX_ErrorNone) {
953        CLOG_ERROR_IF(enable, getExtensionIndex, err, "%s", name);
954        return StatusFromOMXError(err);
955    }
956
957    PrepareForAdaptivePlaybackParams params;
958    InitOMXParams(&params);
959    params.nPortIndex = portIndex;
960    params.bEnable = enable;
961    params.nMaxFrameWidth = maxFrameWidth;
962    params.nMaxFrameHeight = maxFrameHeight;
963
964    err = OMX_SetParameter(mHandle, index, &params);
965    CLOG_IF_ERROR(setParameter, err, "%s(%#x): %s:%u en=%d max=%ux%u", name, index,
966            portString(portIndex), portIndex, enable, maxFrameWidth, maxFrameHeight);
967    return StatusFromOMXError(err);
968}
969
970status_t OMXNodeInstance::configureVideoTunnelMode(
971        OMX_U32 portIndex, OMX_BOOL tunneled, OMX_U32 audioHwSync,
972        native_handle_t **sidebandHandle) {
973    Mutex::Autolock autolock(mLock);
974    if (mSailed) {
975        android_errorWriteLog(0x534e4554, "29422020");
976        return INVALID_OPERATION;
977    }
978    CLOG_CONFIG(configureVideoTunnelMode, "%s:%u tun=%d sync=%u",
979            portString(portIndex), portIndex, tunneled, audioHwSync);
980
981    OMX_INDEXTYPE index;
982    OMX_STRING name = const_cast<OMX_STRING>(
983            "OMX.google.android.index.configureVideoTunnelMode");
984
985    OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
986    if (err != OMX_ErrorNone) {
987        CLOG_ERROR_IF(tunneled, getExtensionIndex, err, "%s", name);
988        return StatusFromOMXError(err);
989    }
990
991    ConfigureVideoTunnelModeParams tunnelParams;
992    InitOMXParams(&tunnelParams);
993    tunnelParams.nPortIndex = portIndex;
994    tunnelParams.bTunneled = tunneled;
995    tunnelParams.nAudioHwSync = audioHwSync;
996    err = OMX_SetParameter(mHandle, index, &tunnelParams);
997    if (err != OMX_ErrorNone) {
998        CLOG_ERROR(setParameter, err, "%s(%#x): %s:%u tun=%d sync=%u", name, index,
999                portString(portIndex), portIndex, tunneled, audioHwSync);
1000        return StatusFromOMXError(err);
1001    }
1002
1003    err = OMX_GetParameter(mHandle, index, &tunnelParams);
1004    if (err != OMX_ErrorNone) {
1005        CLOG_ERROR(getParameter, err, "%s(%#x): %s:%u tun=%d sync=%u", name, index,
1006                portString(portIndex), portIndex, tunneled, audioHwSync);
1007        return StatusFromOMXError(err);
1008    }
1009    if (sidebandHandle) {
1010        *sidebandHandle = (native_handle_t*)tunnelParams.pSidebandWindow;
1011    }
1012
1013    return OK;
1014}
1015
1016status_t OMXNodeInstance::useBuffer(
1017        OMX_U32 portIndex, const OMXBuffer &omxBuffer, IOMX::buffer_id *buffer) {
1018    if (buffer == NULL) {
1019        ALOGE("b/25884056");
1020        return BAD_VALUE;
1021    }
1022
1023    if (portIndex >= NELEM(mNumPortBuffers)) {
1024        return BAD_VALUE;
1025    }
1026
1027    Mutex::Autolock autoLock(mLock);
1028    if (!mSailed) {
1029        ALOGE("b/35467458");
1030        android_errorWriteLog(0x534e4554, "35467458");
1031        return BAD_VALUE;
1032    }
1033
1034    switch (omxBuffer.mBufferType) {
1035        case OMXBuffer::kBufferTypePreset:
1036            return useBuffer_l(portIndex, NULL, NULL, buffer);
1037
1038        case OMXBuffer::kBufferTypeSharedMem:
1039            return useBuffer_l(portIndex, omxBuffer.mMem, NULL, buffer);
1040
1041        case OMXBuffer::kBufferTypeANWBuffer:
1042            return useGraphicBuffer_l(portIndex, omxBuffer.mGraphicBuffer, buffer);
1043
1044        case OMXBuffer::kBufferTypeHidlMemory: {
1045                sp<IHidlMemory> hidlMemory = mapMemory(omxBuffer.mHidlMemory);
1046                return useBuffer_l(portIndex, NULL, hidlMemory, buffer);
1047            }
1048        default:
1049            break;
1050    }
1051
1052    return BAD_VALUE;
1053}
1054
1055status_t OMXNodeInstance::useBuffer_l(
1056        OMX_U32 portIndex, const sp<IMemory> &params,
1057        const sp<IHidlMemory> &hParams, IOMX::buffer_id *buffer) {
1058    BufferMeta *buffer_meta;
1059    OMX_BUFFERHEADERTYPE *header;
1060    OMX_ERRORTYPE err = OMX_ErrorNone;
1061    bool isMetadata = mMetadataType[portIndex] != kMetadataBufferTypeInvalid;
1062
1063    size_t paramsSize;
1064    void* paramsPointer;
1065    if (params != NULL && hParams != NULL) {
1066        return BAD_VALUE;
1067    }
1068    if (params != NULL) {
1069        paramsPointer = params->pointer();
1070        paramsSize = params->size();
1071    } else if (hParams != NULL) {
1072        paramsPointer = hParams->getPointer();
1073        paramsSize = hParams->getSize();
1074    } else {
1075        paramsPointer = nullptr;
1076    }
1077
1078    OMX_U32 allottedSize;
1079    if (isMetadata) {
1080        if (mMetadataType[portIndex] == kMetadataBufferTypeGrallocSource) {
1081            allottedSize = sizeof(VideoGrallocMetadata);
1082        } else if (mMetadataType[portIndex] == kMetadataBufferTypeANWBuffer) {
1083            allottedSize = sizeof(VideoNativeMetadata);
1084        } else if (mMetadataType[portIndex] == kMetadataBufferTypeNativeHandleSource) {
1085            allottedSize = sizeof(VideoNativeHandleMetadata);
1086        } else {
1087            return BAD_VALUE;
1088        }
1089    } else {
1090        // NULL params is allowed only in metadata mode.
1091        if (paramsPointer == nullptr) {
1092            ALOGE("b/25884056");
1093            return BAD_VALUE;
1094        }
1095        allottedSize = paramsSize;
1096    }
1097
1098    bool isOutputGraphicMetadata = (portIndex == kPortIndexOutput) &&
1099            (mMetadataType[portIndex] == kMetadataBufferTypeGrallocSource ||
1100                    mMetadataType[portIndex] == kMetadataBufferTypeANWBuffer);
1101
1102    uint32_t requiresAllocateBufferBit =
1103        (portIndex == kPortIndexInput)
1104            ? kRequiresAllocateBufferOnInputPorts
1105            : kRequiresAllocateBufferOnOutputPorts;
1106
1107    // we use useBuffer for output metadata regardless of quirks
1108    if (!isOutputGraphicMetadata && (mQuirks & requiresAllocateBufferBit)) {
1109        // metadata buffers are not connected cross process; only copy if not meta.
1110        buffer_meta = new BufferMeta(
1111                    params, hParams, portIndex, !isMetadata /* copy */, NULL /* data */);
1112
1113        err = OMX_AllocateBuffer(
1114                mHandle, &header, portIndex, buffer_meta, allottedSize);
1115
1116        if (err != OMX_ErrorNone) {
1117            CLOG_ERROR(allocateBuffer, err,
1118                    SIMPLE_BUFFER(portIndex, (size_t)allottedSize,
1119                            paramsPointer));
1120        }
1121    } else {
1122        OMX_U8 *data = NULL;
1123
1124        // metadata buffers are not connected cross process
1125        // use a backup buffer instead of the actual buffer
1126        if (isMetadata) {
1127            data = new (std::nothrow) OMX_U8[allottedSize];
1128            if (data == NULL) {
1129                return NO_MEMORY;
1130            }
1131            memset(data, 0, allottedSize);
1132
1133            buffer_meta = new BufferMeta(
1134                    params, hParams, portIndex, false /* copy */, data);
1135        } else {
1136            data = static_cast<OMX_U8 *>(paramsPointer);
1137
1138            buffer_meta = new BufferMeta(
1139                    params, hParams, portIndex, false /* copy */, NULL);
1140        }
1141
1142        err = OMX_UseBuffer(
1143                mHandle, &header, portIndex, buffer_meta,
1144                allottedSize, data);
1145
1146        if (err != OMX_ErrorNone) {
1147            CLOG_ERROR(useBuffer, err, SIMPLE_BUFFER(
1148                    portIndex, (size_t)allottedSize, data));
1149        }
1150    }
1151
1152    if (err != OMX_ErrorNone) {
1153        delete buffer_meta;
1154        buffer_meta = NULL;
1155
1156        *buffer = 0;
1157
1158        return StatusFromOMXError(err);
1159    }
1160
1161    CHECK_EQ(header->pAppPrivate, buffer_meta);
1162
1163    *buffer = makeBufferID(header);
1164
1165    addActiveBuffer(portIndex, *buffer);
1166
1167    sp<IOMXBufferSource> bufferSource(getBufferSource());
1168    if (bufferSource != NULL && portIndex == kPortIndexInput) {
1169        bufferSource->onInputBufferAdded(*buffer);
1170    }
1171
1172    CLOG_BUFFER(useBuffer, NEW_BUFFER_FMT(
1173            *buffer, portIndex, "%u(%zu)@%p", allottedSize, paramsSize, paramsPointer));
1174    return OK;
1175}
1176
1177status_t OMXNodeInstance::useGraphicBuffer2_l(
1178        OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer,
1179        IOMX::buffer_id *buffer) {
1180    if (graphicBuffer == NULL || buffer == NULL) {
1181        ALOGE("b/25884056");
1182        return BAD_VALUE;
1183    }
1184
1185    // port definition
1186    OMX_PARAM_PORTDEFINITIONTYPE def;
1187    InitOMXParams(&def);
1188    def.nPortIndex = portIndex;
1189    OMX_ERRORTYPE err = OMX_GetParameter(mHandle, OMX_IndexParamPortDefinition, &def);
1190    if (err != OMX_ErrorNone) {
1191        OMX_INDEXTYPE index = OMX_IndexParamPortDefinition;
1192        CLOG_ERROR(getParameter, err, "%s(%#x): %s:%u",
1193                asString(index), index, portString(portIndex), portIndex);
1194        return UNKNOWN_ERROR;
1195    }
1196
1197    BufferMeta *bufferMeta = new BufferMeta(graphicBuffer, portIndex);
1198
1199    OMX_BUFFERHEADERTYPE *header = NULL;
1200    OMX_U8* bufferHandle = const_cast<OMX_U8*>(
1201            reinterpret_cast<const OMX_U8*>(graphicBuffer->handle));
1202
1203    err = OMX_UseBuffer(
1204            mHandle,
1205            &header,
1206            portIndex,
1207            bufferMeta,
1208            def.nBufferSize,
1209            bufferHandle);
1210
1211    if (err != OMX_ErrorNone) {
1212        CLOG_ERROR(useBuffer, err, BUFFER_FMT(portIndex, "%u@%p", def.nBufferSize, bufferHandle));
1213        delete bufferMeta;
1214        bufferMeta = NULL;
1215        *buffer = 0;
1216        return StatusFromOMXError(err);
1217    }
1218
1219    CHECK_EQ(header->pBuffer, bufferHandle);
1220    CHECK_EQ(header->pAppPrivate, bufferMeta);
1221
1222    *buffer = makeBufferID(header);
1223
1224    addActiveBuffer(portIndex, *buffer);
1225    CLOG_BUFFER(useGraphicBuffer2, NEW_BUFFER_FMT(
1226            *buffer, portIndex, "%u@%p", def.nBufferSize, bufferHandle));
1227    return OK;
1228}
1229
1230// XXX: This function is here for backwards compatibility.  Once the OMX
1231// implementations have been updated this can be removed and useGraphicBuffer2
1232// can be renamed to useGraphicBuffer.
1233status_t OMXNodeInstance::useGraphicBuffer_l(
1234        OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer,
1235        IOMX::buffer_id *buffer) {
1236    if (graphicBuffer == NULL || buffer == NULL) {
1237        ALOGE("b/25884056");
1238        return BAD_VALUE;
1239    }
1240
1241    // First, see if we're in metadata mode. We could be running an experiment to simulate
1242    // legacy behavior (preallocated buffers) on devices that supports meta.
1243    if (mMetadataType[portIndex] != kMetadataBufferTypeInvalid) {
1244        return useGraphicBufferWithMetadata_l(
1245                portIndex, graphicBuffer, buffer);
1246    }
1247
1248    // See if the newer version of the extension is present.
1249    OMX_INDEXTYPE index;
1250    if (OMX_GetExtensionIndex(
1251            mHandle,
1252            const_cast<OMX_STRING>("OMX.google.android.index.useAndroidNativeBuffer2"),
1253            &index) == OMX_ErrorNone) {
1254        return useGraphicBuffer2_l(portIndex, graphicBuffer, buffer);
1255    }
1256
1257    OMX_STRING name = const_cast<OMX_STRING>(
1258        "OMX.google.android.index.useAndroidNativeBuffer");
1259    OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
1260    if (err != OMX_ErrorNone) {
1261        CLOG_ERROR(getExtensionIndex, err, "%s", name);
1262        return StatusFromOMXError(err);
1263    }
1264
1265    BufferMeta *bufferMeta = new BufferMeta(graphicBuffer, portIndex);
1266
1267    OMX_BUFFERHEADERTYPE *header;
1268
1269    OMX_VERSIONTYPE ver;
1270    ver.s.nVersionMajor = 1;
1271    ver.s.nVersionMinor = 0;
1272    ver.s.nRevision = 0;
1273    ver.s.nStep = 0;
1274    UseAndroidNativeBufferParams params = {
1275        sizeof(UseAndroidNativeBufferParams), ver, portIndex, bufferMeta,
1276        &header, graphicBuffer,
1277    };
1278
1279    err = OMX_SetParameter(mHandle, index, &params);
1280
1281    if (err != OMX_ErrorNone) {
1282        CLOG_ERROR(setParameter, err, "%s(%#x): %s:%u meta=%p GB=%p", name, index,
1283                portString(portIndex), portIndex, bufferMeta, graphicBuffer->handle);
1284
1285        delete bufferMeta;
1286        bufferMeta = NULL;
1287
1288        *buffer = 0;
1289
1290        return StatusFromOMXError(err);
1291    }
1292
1293    CHECK_EQ(header->pAppPrivate, bufferMeta);
1294
1295    *buffer = makeBufferID(header);
1296
1297    addActiveBuffer(portIndex, *buffer);
1298    CLOG_BUFFER(useGraphicBuffer, NEW_BUFFER_FMT(
1299            *buffer, portIndex, "GB=%p", graphicBuffer->handle));
1300    return OK;
1301}
1302
1303status_t OMXNodeInstance::useGraphicBufferWithMetadata_l(
1304        OMX_U32 portIndex, const sp<GraphicBuffer> &graphicBuffer,
1305        IOMX::buffer_id *buffer) {
1306    if (portIndex != kPortIndexOutput) {
1307        return BAD_VALUE;
1308    }
1309
1310    if (mMetadataType[portIndex] != kMetadataBufferTypeGrallocSource &&
1311            mMetadataType[portIndex] != kMetadataBufferTypeANWBuffer) {
1312        return BAD_VALUE;
1313    }
1314
1315    status_t err = useBuffer_l(portIndex, NULL, NULL, buffer);
1316    if (err != OK) {
1317        return err;
1318    }
1319
1320    OMX_BUFFERHEADERTYPE *header = findBufferHeader(*buffer, portIndex);
1321
1322    return updateGraphicBufferInMeta_l(portIndex, graphicBuffer, *buffer, header);
1323
1324}
1325
1326status_t OMXNodeInstance::updateGraphicBufferInMeta_l(
1327        OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer,
1328        IOMX::buffer_id buffer, OMX_BUFFERHEADERTYPE *header) {
1329    // No need to check |graphicBuffer| since NULL is valid for it as below.
1330    if (header == NULL) {
1331        ALOGE("b/25884056");
1332        return BAD_VALUE;
1333    }
1334
1335    if (portIndex != kPortIndexInput && portIndex != kPortIndexOutput) {
1336        return BAD_VALUE;
1337    }
1338
1339    BufferMeta *bufferMeta = (BufferMeta *)(header->pAppPrivate);
1340    sp<ABuffer> data = bufferMeta->getBuffer(header, false /* limit */);
1341    bufferMeta->setGraphicBuffer(graphicBuffer);
1342    MetadataBufferType metaType = mMetadataType[portIndex];
1343    if (metaType == kMetadataBufferTypeGrallocSource
1344            && data->capacity() >= sizeof(VideoGrallocMetadata)) {
1345        VideoGrallocMetadata &metadata = *(VideoGrallocMetadata *)(data->data());
1346        metadata.eType = kMetadataBufferTypeGrallocSource;
1347        metadata.pHandle = graphicBuffer == NULL ? NULL : graphicBuffer->handle;
1348    } else if (metaType == kMetadataBufferTypeANWBuffer
1349            && data->capacity() >= sizeof(VideoNativeMetadata)) {
1350        VideoNativeMetadata &metadata = *(VideoNativeMetadata *)(data->data());
1351        metadata.eType = kMetadataBufferTypeANWBuffer;
1352        metadata.pBuffer = graphicBuffer == NULL ? NULL : graphicBuffer->getNativeBuffer();
1353        metadata.nFenceFd = -1;
1354    } else {
1355        CLOG_ERROR(updateGraphicBufferInMeta, BAD_VALUE, "%s:%u, %#x bad type (%d) or size (%u)",
1356            portString(portIndex), portIndex, buffer, mMetadataType[portIndex], header->nAllocLen);
1357        return BAD_VALUE;
1358    }
1359
1360    CLOG_BUFFER(updateGraphicBufferInMeta, "%s:%u, %#x := %p",
1361            portString(portIndex), portIndex, buffer,
1362            graphicBuffer == NULL ? NULL : graphicBuffer->handle);
1363    return OK;
1364}
1365
1366status_t OMXNodeInstance::updateNativeHandleInMeta_l(
1367        OMX_U32 portIndex, const sp<NativeHandle>& nativeHandle,
1368        IOMX::buffer_id buffer, OMX_BUFFERHEADERTYPE *header) {
1369    // No need to check |nativeHandle| since NULL is valid for it as below.
1370    if (header == NULL) {
1371        ALOGE("b/25884056");
1372        return BAD_VALUE;
1373    }
1374
1375    if (portIndex != kPortIndexInput && portIndex != kPortIndexOutput) {
1376        return BAD_VALUE;
1377    }
1378
1379    BufferMeta *bufferMeta = (BufferMeta *)(header->pAppPrivate);
1380    sp<ABuffer> data = bufferMeta->getBuffer(header, false /* limit */);
1381    bufferMeta->setNativeHandle(nativeHandle);
1382    if (mMetadataType[portIndex] == kMetadataBufferTypeNativeHandleSource
1383            && data->capacity() >= sizeof(VideoNativeHandleMetadata)) {
1384        VideoNativeHandleMetadata &metadata = *(VideoNativeHandleMetadata *)(data->data());
1385        metadata.eType = mMetadataType[portIndex];
1386        metadata.pHandle =
1387            nativeHandle == NULL ? NULL : const_cast<native_handle*>(nativeHandle->handle());
1388    } else {
1389        CLOG_ERROR(updateNativeHandleInMeta, BAD_VALUE, "%s:%u, %#x bad type (%d) or size (%zu)",
1390            portString(portIndex), portIndex, buffer, mMetadataType[portIndex], data->capacity());
1391        return BAD_VALUE;
1392    }
1393
1394    CLOG_BUFFER(updateNativeHandleInMeta, "%s:%u, %#x := %p",
1395            portString(portIndex), portIndex, buffer,
1396            nativeHandle == NULL ? NULL : nativeHandle->handle());
1397    return OK;
1398}
1399
1400status_t OMXNodeInstance::setInputSurface(
1401        const sp<IOMXBufferSource> &bufferSource) {
1402    Mutex::Autolock autolock(mLock);
1403
1404    status_t err;
1405
1406    // only allow graphic source on input port, when there are no allocated buffers yet
1407    if (mNumPortBuffers[kPortIndexInput] > 0) {
1408        android_errorWriteLog(0x534e4554, "29422020");
1409        return INVALID_OPERATION;
1410    }
1411
1412    if (getBufferSource() != NULL) {
1413        return ALREADY_EXISTS;
1414    }
1415
1416    err = storeMetaDataInBuffers_l(kPortIndexInput, OMX_TRUE, NULL);
1417    if (err != OK) {
1418        return err;
1419    }
1420
1421    // Retrieve the width and height of the graphic buffer, set when the
1422    // codec was configured.
1423    OMX_PARAM_PORTDEFINITIONTYPE def;
1424    InitOMXParams(&def);
1425    def.nPortIndex = kPortIndexInput;
1426    OMX_ERRORTYPE oerr = OMX_GetParameter(
1427            mHandle, OMX_IndexParamPortDefinition, &def);
1428    if (oerr != OMX_ErrorNone) {
1429        OMX_INDEXTYPE index = OMX_IndexParamPortDefinition;
1430        CLOG_ERROR(getParameter, oerr, "%s(%#x): %s:%u", asString(index),
1431                index, portString(kPortIndexInput), kPortIndexInput);
1432        return UNKNOWN_ERROR;
1433    }
1434
1435    if (def.format.video.eColorFormat != OMX_COLOR_FormatAndroidOpaque) {
1436        CLOGW("createInputSurface requires COLOR_FormatSurface "
1437                "(AndroidOpaque) color format instead of %s(%#x)",
1438                asString(def.format.video.eColorFormat), def.format.video.eColorFormat);
1439        return INVALID_OPERATION;
1440    }
1441
1442    if (def.format.video.nFrameWidth == 0
1443            || def.format.video.nFrameHeight == 0) {
1444        ALOGE("Invalid video dimension %ux%u",
1445                def.format.video.nFrameWidth,
1446                def.format.video.nFrameHeight);
1447        return BAD_VALUE;
1448    }
1449
1450    setBufferSource(bufferSource);
1451    return OK;
1452}
1453
1454status_t OMXNodeInstance::allocateSecureBuffer(
1455        OMX_U32 portIndex, size_t size, IOMX::buffer_id *buffer,
1456        void **buffer_data, sp<NativeHandle> *native_handle) {
1457    if (buffer == NULL || buffer_data == NULL || native_handle == NULL) {
1458        ALOGE("b/25884056");
1459        return BAD_VALUE;
1460    }
1461
1462    if (portIndex >= NELEM(mSecureBufferType)) {
1463        ALOGE("b/31385713, portIndex(%u)", portIndex);
1464        android_errorWriteLog(0x534e4554, "31385713");
1465        return BAD_VALUE;
1466    }
1467
1468    Mutex::Autolock autoLock(mLock);
1469
1470    if (!mSailed) {
1471        ALOGE("b/35467458");
1472        android_errorWriteLog(0x534e4554, "35467458");
1473        return BAD_VALUE;
1474    }
1475    BufferMeta *buffer_meta = new BufferMeta(portIndex);
1476
1477    OMX_BUFFERHEADERTYPE *header;
1478
1479    OMX_ERRORTYPE err = OMX_AllocateBuffer(
1480            mHandle, &header, portIndex, buffer_meta, size);
1481
1482    if (err != OMX_ErrorNone) {
1483        CLOG_ERROR(allocateBuffer, err, BUFFER_FMT(portIndex, "%zu@", size));
1484        delete buffer_meta;
1485        buffer_meta = NULL;
1486
1487        *buffer = 0;
1488
1489        return StatusFromOMXError(err);
1490    }
1491
1492    CHECK_EQ(header->pAppPrivate, buffer_meta);
1493
1494    *buffer = makeBufferID(header);
1495    if (mSecureBufferType[portIndex] == kSecureBufferTypeNativeHandle) {
1496        *buffer_data = NULL;
1497        *native_handle = NativeHandle::create(
1498                (native_handle_t *)header->pBuffer, false /* ownsHandle */);
1499    } else {
1500        *buffer_data = header->pBuffer;
1501        *native_handle = NULL;
1502    }
1503
1504    addActiveBuffer(portIndex, *buffer);
1505
1506    sp<IOMXBufferSource> bufferSource(getBufferSource());
1507    if (bufferSource != NULL && portIndex == kPortIndexInput) {
1508        bufferSource->onInputBufferAdded(*buffer);
1509    }
1510    CLOG_BUFFER(allocateSecureBuffer, NEW_BUFFER_FMT(
1511            *buffer, portIndex, "%zu@%p:%p", size, *buffer_data,
1512            *native_handle == NULL ? NULL : (*native_handle)->handle()));
1513
1514    return OK;
1515}
1516
1517status_t OMXNodeInstance::freeBuffer(
1518        OMX_U32 portIndex, IOMX::buffer_id buffer) {
1519    Mutex::Autolock autoLock(mLock);
1520    CLOG_BUFFER(freeBuffer, "%s:%u %#x", portString(portIndex), portIndex, buffer);
1521
1522    removeActiveBuffer(portIndex, buffer);
1523
1524    OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer, portIndex);
1525    if (header == NULL) {
1526        ALOGE("b/25884056");
1527        return BAD_VALUE;
1528    }
1529    BufferMeta *buffer_meta = static_cast<BufferMeta *>(header->pAppPrivate);
1530
1531    OMX_ERRORTYPE err = OMX_FreeBuffer(mHandle, portIndex, header);
1532    CLOG_IF_ERROR(freeBuffer, err, "%s:%u %#x", portString(portIndex), portIndex, buffer);
1533
1534    delete buffer_meta;
1535    buffer_meta = NULL;
1536    invalidateBufferID(buffer);
1537
1538    return StatusFromOMXError(err);
1539}
1540
1541status_t OMXNodeInstance::fillBuffer(
1542        IOMX::buffer_id buffer, const OMXBuffer &omxBuffer, int fenceFd) {
1543    Mutex::Autolock autoLock(mLock);
1544
1545    OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer, kPortIndexOutput);
1546    if (header == NULL) {
1547        ALOGE("b/25884056");
1548        return BAD_VALUE;
1549    }
1550
1551    if (omxBuffer.mBufferType == OMXBuffer::kBufferTypeANWBuffer) {
1552        status_t err = updateGraphicBufferInMeta_l(
1553                kPortIndexOutput, omxBuffer.mGraphicBuffer, buffer, header);
1554
1555        if (err != OK) {
1556            CLOG_ERROR(fillBuffer, err, FULL_BUFFER(
1557                    (intptr_t)header->pBuffer, header, fenceFd));
1558            return err;
1559        }
1560    } else if (omxBuffer.mBufferType != OMXBuffer::kBufferTypePreset) {
1561        return BAD_VALUE;
1562    }
1563
1564    header->nFilledLen = 0;
1565    header->nOffset = 0;
1566    header->nFlags = 0;
1567
1568    // meta now owns fenceFd
1569    status_t res = storeFenceInMeta_l(header, fenceFd, kPortIndexOutput);
1570    if (res != OK) {
1571        CLOG_ERROR(fillBuffer::storeFenceInMeta, res, EMPTY_BUFFER(buffer, header, fenceFd));
1572        return res;
1573    }
1574
1575    {
1576        Mutex::Autolock _l(mDebugLock);
1577        mOutputBuffersWithCodec.add(header);
1578        CLOG_BUMPED_BUFFER(fillBuffer, WITH_STATS(EMPTY_BUFFER(buffer, header, fenceFd)));
1579    }
1580
1581    OMX_ERRORTYPE err = OMX_FillThisBuffer(mHandle, header);
1582    if (err != OMX_ErrorNone) {
1583        CLOG_ERROR(fillBuffer, err, EMPTY_BUFFER(buffer, header, fenceFd));
1584        Mutex::Autolock _l(mDebugLock);
1585        mOutputBuffersWithCodec.remove(header);
1586    }
1587    return StatusFromOMXError(err);
1588}
1589
1590status_t OMXNodeInstance::emptyBuffer(
1591        buffer_id buffer, const OMXBuffer &omxBuffer,
1592        OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) {
1593    Mutex::Autolock autoLock(mLock);
1594
1595    switch (omxBuffer.mBufferType) {
1596    case OMXBuffer::kBufferTypePreset:
1597        return emptyBuffer_l(
1598                buffer, omxBuffer.mRangeOffset, omxBuffer.mRangeLength,
1599                flags, timestamp, fenceFd);
1600
1601    case OMXBuffer::kBufferTypeANWBuffer:
1602        return emptyGraphicBuffer_l(
1603                buffer, omxBuffer.mGraphicBuffer, flags, timestamp, fenceFd);
1604
1605    case OMXBuffer::kBufferTypeNativeHandle:
1606        return emptyNativeHandleBuffer_l(
1607                buffer, omxBuffer.mNativeHandle, flags, timestamp, fenceFd);
1608
1609    default:
1610        break;
1611    }
1612
1613    return BAD_VALUE;
1614}
1615
1616status_t OMXNodeInstance::emptyBuffer_l(
1617        IOMX::buffer_id buffer,
1618        OMX_U32 rangeOffset, OMX_U32 rangeLength,
1619        OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) {
1620
1621    // no emptybuffer if using input surface
1622    if (getBufferSource() != NULL) {
1623        android_errorWriteLog(0x534e4554, "29422020");
1624        return INVALID_OPERATION;
1625    }
1626
1627    OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer, kPortIndexInput);
1628    if (header == NULL) {
1629        ALOGE("b/25884056");
1630        return BAD_VALUE;
1631    }
1632    BufferMeta *buffer_meta =
1633        static_cast<BufferMeta *>(header->pAppPrivate);
1634
1635    // set up proper filled length if component is configured for gralloc metadata mode
1636    // ignore rangeOffset in this case (as client may be assuming ANW meta buffers).
1637    if (mMetadataType[kPortIndexInput] == kMetadataBufferTypeGrallocSource) {
1638        header->nFilledLen = rangeLength ? sizeof(VideoGrallocMetadata) : 0;
1639        header->nOffset = 0;
1640    } else {
1641        // rangeLength and rangeOffset must be a subset of the allocated data in the buffer.
1642        // corner case: we permit rangeOffset == end-of-buffer with rangeLength == 0.
1643        if (rangeOffset > header->nAllocLen
1644                || rangeLength > header->nAllocLen - rangeOffset) {
1645            CLOG_ERROR(emptyBuffer, OMX_ErrorBadParameter, FULL_BUFFER(NULL, header, fenceFd));
1646            if (fenceFd >= 0) {
1647                ::close(fenceFd);
1648            }
1649            return BAD_VALUE;
1650        }
1651        header->nFilledLen = rangeLength;
1652        header->nOffset = rangeOffset;
1653
1654        buffer_meta->CopyToOMX(header);
1655    }
1656
1657    return emptyBuffer_l(header, flags, timestamp, (intptr_t)buffer, fenceFd);
1658}
1659
1660// log queued buffer activity for the next few input and/or output frames
1661// if logging at internal state level
1662void OMXNodeInstance::bumpDebugLevel_l(size_t numInputBuffers, size_t numOutputBuffers) {
1663    if (DEBUG == ADebug::kDebugInternalState) {
1664        DEBUG_BUMP = ADebug::kDebugAll;
1665        if (numInputBuffers > 0) {
1666            mDebugLevelBumpPendingBuffers[kPortIndexInput] = numInputBuffers;
1667        }
1668        if (numOutputBuffers > 0) {
1669            mDebugLevelBumpPendingBuffers[kPortIndexOutput] = numOutputBuffers;
1670        }
1671    }
1672}
1673
1674void OMXNodeInstance::unbumpDebugLevel_l(size_t portIndex) {
1675    if (mDebugLevelBumpPendingBuffers[portIndex]) {
1676        --mDebugLevelBumpPendingBuffers[portIndex];
1677    }
1678    if (!mDebugLevelBumpPendingBuffers[0]
1679            && !mDebugLevelBumpPendingBuffers[1]) {
1680        DEBUG_BUMP = DEBUG;
1681    }
1682}
1683
1684status_t OMXNodeInstance::storeFenceInMeta_l(
1685        OMX_BUFFERHEADERTYPE *header, int fenceFd, OMX_U32 portIndex) {
1686    // propagate fence if component supports it; wait for it otherwise
1687    OMX_U32 metaSize = portIndex == kPortIndexInput ? header->nFilledLen : header->nAllocLen;
1688    if (mMetadataType[portIndex] == kMetadataBufferTypeANWBuffer
1689            && metaSize >= sizeof(VideoNativeMetadata)) {
1690        VideoNativeMetadata &nativeMeta = *(VideoNativeMetadata *)(header->pBuffer);
1691        if (nativeMeta.nFenceFd >= 0) {
1692            ALOGE("fence (%d) already exists in meta", nativeMeta.nFenceFd);
1693            if (fenceFd >= 0) {
1694                ::close(fenceFd);
1695            }
1696            return ALREADY_EXISTS;
1697        }
1698        nativeMeta.nFenceFd = fenceFd;
1699    } else if (fenceFd >= 0) {
1700        CLOG_BUFFER(storeFenceInMeta, "waiting for fence %d", fenceFd);
1701        sp<Fence> fence = new Fence(fenceFd);
1702        return fence->wait(IOMX::kFenceTimeoutMs);
1703    }
1704    return OK;
1705}
1706
1707int OMXNodeInstance::retrieveFenceFromMeta_l(
1708        OMX_BUFFERHEADERTYPE *header, OMX_U32 portIndex) {
1709    OMX_U32 metaSize = portIndex == kPortIndexInput ? header->nAllocLen : header->nFilledLen;
1710    int fenceFd = -1;
1711    if (mMetadataType[portIndex] == kMetadataBufferTypeANWBuffer
1712            && header->nAllocLen >= sizeof(VideoNativeMetadata)) {
1713        VideoNativeMetadata &nativeMeta = *(VideoNativeMetadata *)(header->pBuffer);
1714        if (nativeMeta.eType == kMetadataBufferTypeANWBuffer) {
1715            fenceFd = nativeMeta.nFenceFd;
1716            nativeMeta.nFenceFd = -1;
1717        }
1718        if (metaSize < sizeof(nativeMeta) && fenceFd >= 0) {
1719            CLOG_ERROR(foundFenceInEmptyMeta, BAD_VALUE, FULL_BUFFER(
1720                    NULL, header, nativeMeta.nFenceFd));
1721            fenceFd = -1;
1722        }
1723    }
1724    return fenceFd;
1725}
1726
1727status_t OMXNodeInstance::emptyBuffer_l(
1728        OMX_BUFFERHEADERTYPE *header, OMX_U32 flags, OMX_TICKS timestamp,
1729        intptr_t debugAddr, int fenceFd) {
1730    header->nFlags = flags;
1731    header->nTimeStamp = timestamp;
1732
1733    status_t res = storeFenceInMeta_l(header, fenceFd, kPortIndexInput);
1734    if (res != OK) {
1735        CLOG_ERROR(emptyBuffer::storeFenceInMeta, res, WITH_STATS(
1736                FULL_BUFFER(debugAddr, header, fenceFd)));
1737        return res;
1738    }
1739
1740    {
1741        Mutex::Autolock _l(mDebugLock);
1742        mInputBuffersWithCodec.add(header);
1743
1744        // bump internal-state debug level for 2 input frames past a buffer with CSD
1745        if ((flags & OMX_BUFFERFLAG_CODECCONFIG) != 0) {
1746            bumpDebugLevel_l(2 /* numInputBuffers */, 0 /* numOutputBuffers */);
1747        }
1748
1749        CLOG_BUMPED_BUFFER(emptyBuffer, WITH_STATS(FULL_BUFFER(debugAddr, header, fenceFd)));
1750    }
1751
1752    OMX_ERRORTYPE err = OMX_EmptyThisBuffer(mHandle, header);
1753    CLOG_IF_ERROR(emptyBuffer, err, FULL_BUFFER(debugAddr, header, fenceFd));
1754
1755    {
1756        Mutex::Autolock _l(mDebugLock);
1757        if (err != OMX_ErrorNone) {
1758            mInputBuffersWithCodec.remove(header);
1759        } else if (!(flags & OMX_BUFFERFLAG_CODECCONFIG)) {
1760            unbumpDebugLevel_l(kPortIndexInput);
1761        }
1762    }
1763
1764    return StatusFromOMXError(err);
1765}
1766
1767// like emptyBuffer, but the data is already in header->pBuffer
1768status_t OMXNodeInstance::emptyGraphicBuffer_l(
1769        IOMX::buffer_id buffer, const sp<GraphicBuffer> &graphicBuffer,
1770        OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) {
1771    OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer, kPortIndexInput);
1772    if (header == NULL) {
1773        ALOGE("b/25884056");
1774        return BAD_VALUE;
1775    }
1776
1777    status_t err = updateGraphicBufferInMeta_l(
1778            kPortIndexInput, graphicBuffer, buffer, header);
1779    if (err != OK) {
1780        CLOG_ERROR(emptyGraphicBuffer, err, FULL_BUFFER(
1781                (intptr_t)header->pBuffer, header, fenceFd));
1782        return err;
1783    }
1784
1785    int64_t codecTimeUs = getCodecTimestamp(timestamp);
1786
1787    header->nOffset = 0;
1788    if (graphicBuffer == NULL) {
1789        header->nFilledLen = 0;
1790    } else if (mMetadataType[kPortIndexInput] == kMetadataBufferTypeGrallocSource) {
1791        header->nFilledLen = sizeof(VideoGrallocMetadata);
1792    } else {
1793        header->nFilledLen = sizeof(VideoNativeMetadata);
1794    }
1795    return emptyBuffer_l(header, flags, codecTimeUs, (intptr_t)header->pBuffer, fenceFd);
1796}
1797
1798status_t OMXNodeInstance::setMaxPtsGapUs(const void *params, size_t size) {
1799    if (params == NULL || size != sizeof(OMX_PARAM_U32TYPE)) {
1800        CLOG_ERROR(setMaxPtsGapUs, BAD_VALUE, "invalid params (%p,%zu)", params, size);
1801        return BAD_VALUE;
1802    }
1803
1804    mMaxTimestampGapUs = (int64_t)((OMX_PARAM_U32TYPE*)params)->nU32;
1805
1806    return OK;
1807}
1808
1809int64_t OMXNodeInstance::getCodecTimestamp(OMX_TICKS timestamp) {
1810    int64_t originalTimeUs = timestamp;
1811
1812    if (mMaxTimestampGapUs > 0ll) {
1813        /* Cap timestamp gap between adjacent frames to specified max
1814         *
1815         * In the scenario of cast mirroring, encoding could be suspended for
1816         * prolonged periods. Limiting the pts gap to workaround the problem
1817         * where encoder's rate control logic produces huge frames after a
1818         * long period of suspension.
1819         */
1820        if (mPrevOriginalTimeUs >= 0ll) {
1821            int64_t timestampGapUs = originalTimeUs - mPrevOriginalTimeUs;
1822            timestamp = (timestampGapUs < mMaxTimestampGapUs ?
1823                timestampGapUs : mMaxTimestampGapUs) + mPrevModifiedTimeUs;
1824        }
1825        ALOGV("IN  timestamp: %lld -> %lld",
1826            static_cast<long long>(originalTimeUs),
1827            static_cast<long long>(timestamp));
1828    }
1829
1830    mPrevOriginalTimeUs = originalTimeUs;
1831    mPrevModifiedTimeUs = timestamp;
1832
1833    if (mMaxTimestampGapUs > 0ll && !mRestorePtsFailed) {
1834        mOriginalTimeUs.add(timestamp, originalTimeUs);
1835    }
1836
1837    return timestamp;
1838}
1839
1840status_t OMXNodeInstance::emptyNativeHandleBuffer_l(
1841        IOMX::buffer_id buffer, const sp<NativeHandle> &nativeHandle,
1842        OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) {
1843    OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer, kPortIndexInput);
1844    if (header == NULL) {
1845        ALOGE("b/25884056");
1846        return BAD_VALUE;
1847    }
1848
1849    status_t err = updateNativeHandleInMeta_l(
1850            kPortIndexInput, nativeHandle, buffer, header);
1851    if (err != OK) {
1852        CLOG_ERROR(emptyNativeHandleBuffer_l, err, FULL_BUFFER(
1853                (intptr_t)header->pBuffer, header, fenceFd));
1854        return err;
1855    }
1856
1857    header->nOffset = 0;
1858    header->nFilledLen = (nativeHandle == NULL) ? 0 : sizeof(VideoNativeMetadata);
1859
1860    return emptyBuffer_l(header, flags, timestamp, (intptr_t)header->pBuffer, fenceFd);
1861}
1862
1863void OMXNodeInstance::codecBufferFilled(omx_message &msg) {
1864    Mutex::Autolock autoLock(mLock);
1865
1866    if (mMaxTimestampGapUs <= 0ll || mRestorePtsFailed) {
1867        return;
1868    }
1869
1870    OMX_U32 &flags = msg.u.extended_buffer_data.flags;
1871    OMX_TICKS &timestamp = msg.u.extended_buffer_data.timestamp;
1872
1873    if (!(flags & OMX_BUFFERFLAG_CODECCONFIG)) {
1874        ssize_t index = mOriginalTimeUs.indexOfKey(timestamp);
1875        if (index >= 0) {
1876            ALOGV("OUT timestamp: %lld -> %lld",
1877                    static_cast<long long>(timestamp),
1878                    static_cast<long long>(mOriginalTimeUs[index]));
1879            timestamp = mOriginalTimeUs[index];
1880            mOriginalTimeUs.removeItemsAt(index);
1881        } else {
1882            // giving up the effort as encoder doesn't appear to preserve pts
1883            ALOGW("giving up limiting timestamp gap (pts = %lld)", timestamp);
1884            mRestorePtsFailed = true;
1885        }
1886    }
1887}
1888
1889status_t OMXNodeInstance::getExtensionIndex(
1890        const char *parameterName, OMX_INDEXTYPE *index) {
1891    Mutex::Autolock autoLock(mLock);
1892
1893    OMX_ERRORTYPE err = OMX_GetExtensionIndex(
1894            mHandle, const_cast<char *>(parameterName), index);
1895
1896    return StatusFromOMXError(err);
1897}
1898
1899status_t OMXNodeInstance::dispatchMessage(const omx_message &msg) {
1900    mDispatcher->post(msg, true /*realTime*/);
1901    return OK;
1902}
1903
1904status_t OMXNodeInstance::setQuirks(OMX_U32 quirks) {
1905    if (quirks & ~kQuirksMask) {
1906        return BAD_VALUE;
1907    }
1908
1909    mQuirks = quirks;
1910
1911    return OK;
1912}
1913
1914bool OMXNodeInstance::handleMessage(omx_message &msg) {
1915    if (msg.type == omx_message::FILL_BUFFER_DONE) {
1916        OMX_BUFFERHEADERTYPE *buffer =
1917            findBufferHeader(msg.u.extended_buffer_data.buffer, kPortIndexOutput);
1918        if (buffer == NULL) {
1919            ALOGE("b/25884056");
1920            return false;
1921        }
1922
1923        {
1924            Mutex::Autolock _l(mDebugLock);
1925            mOutputBuffersWithCodec.remove(buffer);
1926
1927            CLOG_BUMPED_BUFFER(
1928                    FBD, WITH_STATS(FULL_BUFFER(
1929                            msg.u.extended_buffer_data.buffer, buffer, msg.fenceFd)));
1930
1931            unbumpDebugLevel_l(kPortIndexOutput);
1932        }
1933
1934        BufferMeta *buffer_meta =
1935            static_cast<BufferMeta *>(buffer->pAppPrivate);
1936
1937        if (buffer->nOffset + buffer->nFilledLen < buffer->nOffset
1938                || buffer->nOffset + buffer->nFilledLen > buffer->nAllocLen) {
1939            CLOG_ERROR(onFillBufferDone, OMX_ErrorBadParameter,
1940                    FULL_BUFFER(NULL, buffer, msg.fenceFd));
1941        }
1942        buffer_meta->CopyFromOMX(buffer);
1943
1944        // fix up the buffer info (especially timestamp) if needed
1945        codecBufferFilled(msg);
1946    } else if (msg.type == omx_message::EMPTY_BUFFER_DONE) {
1947        OMX_BUFFERHEADERTYPE *buffer =
1948            findBufferHeader(msg.u.buffer_data.buffer, kPortIndexInput);
1949        if (buffer == NULL) {
1950            return false;
1951        }
1952
1953        {
1954            Mutex::Autolock _l(mDebugLock);
1955            mInputBuffersWithCodec.remove(buffer);
1956
1957            CLOG_BUMPED_BUFFER(
1958                    EBD, WITH_STATS(EMPTY_BUFFER(msg.u.buffer_data.buffer, buffer, msg.fenceFd)));
1959        }
1960
1961        const sp<IOMXBufferSource> bufferSource(getBufferSource());
1962
1963        if (bufferSource != NULL) {
1964            // This is one of the buffers used exclusively by IOMXBufferSource.
1965            // Don't dispatch a message back to ACodec, since it doesn't
1966            // know that anyone asked to have the buffer emptied and will
1967            // be very confused.
1968            bufferSource->onInputBufferEmptied(
1969                    msg.u.buffer_data.buffer, OMXFenceParcelable(msg.fenceFd));
1970            return true;
1971        }
1972    } else if (msg.type == omx_message::EVENT &&
1973            msg.u.event_data.event == OMX_EventDataSpaceChanged) {
1974        handleDataSpaceChanged(msg);
1975    }
1976
1977    return false;
1978}
1979
1980bool OMXNodeInstance::handleDataSpaceChanged(omx_message &msg) {
1981    android_dataspace dataSpace = (android_dataspace) msg.u.event_data.data1;
1982    android_dataspace origDataSpace = dataSpace;
1983
1984    if (!ColorUtils::convertDataSpaceToV0(dataSpace)) {
1985        // Do not process the data space change, don't notify client either
1986        return true;
1987    }
1988
1989    android_pixel_format pixelFormat = (android_pixel_format)msg.u.event_data.data3;
1990
1991    ColorAspects requestedAspects = ColorUtils::unpackToColorAspects(msg.u.event_data.data2);
1992    ColorAspects aspects = requestedAspects; // initially requested aspects
1993
1994    // request color aspects to encode
1995    OMX_INDEXTYPE index;
1996    status_t err = getExtensionIndex(
1997            "OMX.google.android.index.describeColorAspects", &index);
1998    if (err == OK) {
1999        // V0 dataspace
2000        DescribeColorAspectsParams params;
2001        InitOMXParams(&params);
2002        params.nPortIndex = kPortIndexInput;
2003        params.nDataSpace = origDataSpace;
2004        params.nPixelFormat = pixelFormat;
2005        params.bDataSpaceChanged = OMX_TRUE;
2006        params.sAspects = requestedAspects;
2007
2008        err = getConfig(index, &params, sizeof(params));
2009        if (err == OK) {
2010            aspects = params.sAspects;
2011            ALOGD("Codec resolved it to (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) err=%d(%s)",
2012                    params.sAspects.mRange, asString(params.sAspects.mRange),
2013                    params.sAspects.mPrimaries, asString(params.sAspects.mPrimaries),
2014                    params.sAspects.mMatrixCoeffs, asString(params.sAspects.mMatrixCoeffs),
2015                    params.sAspects.mTransfer, asString(params.sAspects.mTransfer),
2016                    err, asString(err));
2017        } else {
2018            params.sAspects = aspects;
2019            err = OK;
2020        }
2021        params.bDataSpaceChanged = OMX_FALSE;
2022        for (int triesLeft = 2; --triesLeft >= 0; ) {
2023            status_t err = setConfig(index, &params, sizeof(params));
2024            if (err == OK) {
2025                err = getConfig(index, &params, sizeof(params));
2026            }
2027            if (err != OK || !ColorUtils::checkIfAspectsChangedAndUnspecifyThem(
2028                    params.sAspects, aspects)) {
2029                // if we can't set or get color aspects, still communicate dataspace to client
2030                break;
2031            }
2032
2033            ALOGW_IF(triesLeft == 0, "Codec repeatedly changed requested ColorAspects.");
2034        }
2035    }
2036
2037    ALOGV("Set color aspects to (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) err=%d(%s)",
2038            aspects.mRange, asString(aspects.mRange),
2039            aspects.mPrimaries, asString(aspects.mPrimaries),
2040            aspects.mMatrixCoeffs, asString(aspects.mMatrixCoeffs),
2041            aspects.mTransfer, asString(aspects.mTransfer),
2042            err, asString(err));
2043
2044    // signal client that the dataspace has changed; this will update the output format
2045    // TODO: we should tie this to an output buffer somehow, and signal the change
2046    // just before the output buffer is returned to the client, but there are many
2047    // ways this could fail (e.g. flushing), and we are not yet supporting this scenario.
2048
2049    msg.u.event_data.data1 = (OMX_U32) dataSpace;
2050    msg.u.event_data.data2 = (OMX_U32) ColorUtils::packToU32(aspects);
2051
2052    return false;
2053}
2054
2055void OMXNodeInstance::onMessages(std::list<omx_message> &messages) {
2056    for (std::list<omx_message>::iterator it = messages.begin(); it != messages.end(); ) {
2057        if (handleMessage(*it)) {
2058            messages.erase(it++);
2059        } else {
2060            ++it;
2061        }
2062    }
2063
2064    if (!messages.empty()) {
2065        mObserver->onMessages(messages);
2066    }
2067}
2068
2069void OMXNodeInstance::onObserverDied() {
2070    ALOGE("!!! Observer died. Quickly, do something, ... anything...");
2071
2072    // Try to force shutdown of the node and hope for the best.
2073    freeNode();
2074}
2075
2076// OMXNodeInstance::OnEvent calls OMX::OnEvent, which then calls here.
2077// Don't try to acquire mLock here -- in rare circumstances this will hang.
2078void OMXNodeInstance::onEvent(
2079        OMX_EVENTTYPE event, OMX_U32 arg1, OMX_U32 arg2) {
2080    const char *arg1String = "??";
2081    const char *arg2String = "??";
2082    ADebug::Level level = ADebug::kDebugInternalState;
2083
2084    switch (event) {
2085        case OMX_EventCmdComplete:
2086            arg1String = asString((OMX_COMMANDTYPE)arg1);
2087            switch (arg1) {
2088                case OMX_CommandStateSet:
2089                    arg2String = asString((OMX_STATETYPE)arg2);
2090                    level = ADebug::kDebugState;
2091                    break;
2092                case OMX_CommandFlush:
2093                case OMX_CommandPortEnable:
2094                {
2095                    // bump internal-state debug level for 2 input and output frames
2096                    Mutex::Autolock _l(mDebugLock);
2097                    bumpDebugLevel_l(2 /* numInputBuffers */, 2 /* numOutputBuffers */);
2098                }
2099                // fall through
2100                default:
2101                    arg2String = portString(arg2);
2102            }
2103            break;
2104        case OMX_EventError:
2105            arg1String = asString((OMX_ERRORTYPE)arg1);
2106            level = ADebug::kDebugLifeCycle;
2107            break;
2108        case OMX_EventPortSettingsChanged:
2109            arg2String = asString((OMX_INDEXEXTTYPE)arg2);
2110            // fall through
2111        default:
2112            arg1String = portString(arg1);
2113    }
2114
2115    CLOGI_(level, onEvent, "%s(%x), %s(%x), %s(%x)",
2116            asString(event), event, arg1String, arg1, arg2String, arg2);
2117    const sp<IOMXBufferSource> bufferSource(getBufferSource());
2118
2119    if (bufferSource != NULL
2120            && event == OMX_EventCmdComplete
2121            && arg1 == OMX_CommandStateSet
2122            && arg2 == OMX_StateExecuting) {
2123        bufferSource->onOmxExecuting();
2124    }
2125
2126    // allow configuration if we return to the loaded state
2127    if (event == OMX_EventCmdComplete
2128            && arg1 == OMX_CommandStateSet
2129            && arg2 == OMX_StateLoaded) {
2130        mSailed = false;
2131    }
2132}
2133
2134// static
2135OMX_ERRORTYPE OMXNodeInstance::OnEvent(
2136        OMX_IN OMX_HANDLETYPE /* hComponent */,
2137        OMX_IN OMX_PTR pAppData,
2138        OMX_IN OMX_EVENTTYPE eEvent,
2139        OMX_IN OMX_U32 nData1,
2140        OMX_IN OMX_U32 nData2,
2141        OMX_IN OMX_PTR pEventData) {
2142    if (pAppData == NULL) {
2143        ALOGE("b/25884056");
2144        return OMX_ErrorBadParameter;
2145    }
2146    OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
2147    if (instance->mDying) {
2148        return OMX_ErrorNone;
2149    }
2150
2151    instance->onEvent(eEvent, nData1, nData2);
2152
2153    // output rendered events are not processed as regular events until they hit the observer
2154    if (eEvent == OMX_EventOutputRendered) {
2155        if (pEventData == NULL) {
2156            return OMX_ErrorBadParameter;
2157        }
2158
2159        // process data from array
2160        OMX_VIDEO_RENDEREVENTTYPE *renderData = (OMX_VIDEO_RENDEREVENTTYPE *)pEventData;
2161        for (size_t i = 0; i < nData1; ++i) {
2162            omx_message msg;
2163            msg.type = omx_message::FRAME_RENDERED;
2164            msg.fenceFd = -1;
2165            msg.u.render_data.timestamp = renderData[i].nMediaTimeUs;
2166            msg.u.render_data.nanoTime = renderData[i].nSystemTimeNs;
2167
2168            instance->mDispatcher->post(msg, false /* realTime */);
2169        }
2170        return OMX_ErrorNone;
2171    }
2172
2173    omx_message msg;
2174    msg.type = omx_message::EVENT;
2175    msg.fenceFd = -1;
2176    msg.u.event_data.event = eEvent;
2177    msg.u.event_data.data1 = nData1;
2178    msg.u.event_data.data2 = nData2;
2179
2180    instance->mDispatcher->post(msg, true /* realTime */);
2181
2182    return OMX_ErrorNone;
2183}
2184
2185// static
2186OMX_ERRORTYPE OMXNodeInstance::OnEmptyBufferDone(
2187        OMX_IN OMX_HANDLETYPE /* hComponent */,
2188        OMX_IN OMX_PTR pAppData,
2189        OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) {
2190    if (pAppData == NULL) {
2191        ALOGE("b/25884056");
2192        return OMX_ErrorBadParameter;
2193    }
2194    OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
2195    if (instance->mDying) {
2196        return OMX_ErrorNone;
2197    }
2198    int fenceFd = instance->retrieveFenceFromMeta_l(pBuffer, kPortIndexOutput);
2199
2200    omx_message msg;
2201    msg.type = omx_message::EMPTY_BUFFER_DONE;
2202    msg.fenceFd = fenceFd;
2203    msg.u.buffer_data.buffer = instance->findBufferID(pBuffer);
2204    instance->mDispatcher->post(msg);
2205
2206    return OMX_ErrorNone;
2207}
2208
2209// static
2210OMX_ERRORTYPE OMXNodeInstance::OnFillBufferDone(
2211        OMX_IN OMX_HANDLETYPE /* hComponent */,
2212        OMX_IN OMX_PTR pAppData,
2213        OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) {
2214    if (pAppData == NULL) {
2215        ALOGE("b/25884056");
2216        return OMX_ErrorBadParameter;
2217    }
2218    OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
2219    if (instance->mDying) {
2220        return OMX_ErrorNone;
2221    }
2222    int fenceFd = instance->retrieveFenceFromMeta_l(pBuffer, kPortIndexOutput);
2223
2224    omx_message msg;
2225    msg.type = omx_message::FILL_BUFFER_DONE;
2226    msg.fenceFd = fenceFd;
2227    msg.u.extended_buffer_data.buffer = instance->findBufferID(pBuffer);
2228    msg.u.extended_buffer_data.range_offset = pBuffer->nOffset;
2229    msg.u.extended_buffer_data.range_length = pBuffer->nFilledLen;
2230    msg.u.extended_buffer_data.flags = pBuffer->nFlags;
2231    msg.u.extended_buffer_data.timestamp = pBuffer->nTimeStamp;
2232    instance->mDispatcher->post(msg);
2233
2234    return OMX_ErrorNone;
2235}
2236
2237void OMXNodeInstance::addActiveBuffer(OMX_U32 portIndex, IOMX::buffer_id id) {
2238    ActiveBuffer active;
2239    active.mPortIndex = portIndex;
2240    active.mID = id;
2241    mActiveBuffers.push(active);
2242
2243    if (portIndex < NELEM(mNumPortBuffers)) {
2244        ++mNumPortBuffers[portIndex];
2245    }
2246}
2247
2248void OMXNodeInstance::removeActiveBuffer(
2249        OMX_U32 portIndex, IOMX::buffer_id id) {
2250    for (size_t i = 0; i < mActiveBuffers.size(); ++i) {
2251        if (mActiveBuffers[i].mPortIndex == portIndex
2252                && mActiveBuffers[i].mID == id) {
2253            mActiveBuffers.removeItemsAt(i);
2254
2255            if (portIndex < NELEM(mNumPortBuffers)) {
2256                --mNumPortBuffers[portIndex];
2257            }
2258            return;
2259        }
2260    }
2261
2262     CLOGW("Attempt to remove an active buffer [%#x] we know nothing about...", id);
2263}
2264
2265void OMXNodeInstance::freeActiveBuffers() {
2266    // Make sure to count down here, as freeBuffer will in turn remove
2267    // the active buffer from the vector...
2268    for (size_t i = mActiveBuffers.size(); i > 0;) {
2269        i--;
2270        freeBuffer(mActiveBuffers[i].mPortIndex, mActiveBuffers[i].mID);
2271    }
2272}
2273
2274IOMX::buffer_id OMXNodeInstance::makeBufferID(OMX_BUFFERHEADERTYPE *bufferHeader) {
2275    if (bufferHeader == NULL) {
2276        return 0;
2277    }
2278    Mutex::Autolock autoLock(mBufferIDLock);
2279    IOMX::buffer_id buffer;
2280    do { // handle the very unlikely case of ID overflow
2281        if (++mBufferIDCount == 0) {
2282            ++mBufferIDCount;
2283        }
2284        buffer = (IOMX::buffer_id)mBufferIDCount;
2285    } while (mBufferIDToBufferHeader.indexOfKey(buffer) >= 0);
2286    mBufferIDToBufferHeader.add(buffer, bufferHeader);
2287    mBufferHeaderToBufferID.add(bufferHeader, buffer);
2288    return buffer;
2289}
2290
2291OMX_BUFFERHEADERTYPE *OMXNodeInstance::findBufferHeader(
2292        IOMX::buffer_id buffer, OMX_U32 portIndex) {
2293    if (buffer == 0) {
2294        return NULL;
2295    }
2296    Mutex::Autolock autoLock(mBufferIDLock);
2297    ssize_t index = mBufferIDToBufferHeader.indexOfKey(buffer);
2298    if (index < 0) {
2299        CLOGW("findBufferHeader: buffer %u not found", buffer);
2300        return NULL;
2301    }
2302    OMX_BUFFERHEADERTYPE *header = mBufferIDToBufferHeader.valueAt(index);
2303    BufferMeta *buffer_meta =
2304        static_cast<BufferMeta *>(header->pAppPrivate);
2305    if (buffer_meta->getPortIndex() != portIndex) {
2306        CLOGW("findBufferHeader: buffer %u found but with incorrect port index.", buffer);
2307        android_errorWriteLog(0x534e4554, "28816827");
2308        return NULL;
2309    }
2310    return header;
2311}
2312
2313IOMX::buffer_id OMXNodeInstance::findBufferID(OMX_BUFFERHEADERTYPE *bufferHeader) {
2314    if (bufferHeader == NULL) {
2315        return 0;
2316    }
2317    Mutex::Autolock autoLock(mBufferIDLock);
2318    ssize_t index = mBufferHeaderToBufferID.indexOfKey(bufferHeader);
2319    if (index < 0) {
2320        CLOGW("findBufferID: bufferHeader %p not found", bufferHeader);
2321        return 0;
2322    }
2323    return mBufferHeaderToBufferID.valueAt(index);
2324}
2325
2326void OMXNodeInstance::invalidateBufferID(IOMX::buffer_id buffer) {
2327    if (buffer == 0) {
2328        return;
2329    }
2330    Mutex::Autolock autoLock(mBufferIDLock);
2331    ssize_t index = mBufferIDToBufferHeader.indexOfKey(buffer);
2332    if (index < 0) {
2333        CLOGW("invalidateBufferID: buffer %u not found", buffer);
2334        return;
2335    }
2336    mBufferHeaderToBufferID.removeItem(mBufferIDToBufferHeader.valueAt(index));
2337    mBufferIDToBufferHeader.removeItemsAt(index);
2338}
2339
2340}  // namespace android
2341