Home | History | Annotate | Download | only in omx
      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 #include <inttypes.h>
     18 
     19 //#define LOG_NDEBUG 0
     20 #define LOG_TAG "OMX"
     21 #include <utils/Log.h>
     22 
     23 #include <dlfcn.h>
     24 
     25 #include "../include/OMX.h"
     26 
     27 #include "../include/OMXNodeInstance.h"
     28 
     29 #include <binder/IMemory.h>
     30 #include <media/stagefright/foundation/ADebug.h>
     31 #include <utils/threads.h>
     32 
     33 #include "OMXMaster.h"
     34 
     35 #include <OMX_AsString.h>
     36 #include <OMX_Component.h>
     37 #include <OMX_VideoExt.h>
     38 
     39 namespace android {
     40 
     41 ////////////////////////////////////////////////////////////////////////////////
     42 
     43 // This provides the underlying Thread used by CallbackDispatcher.
     44 // Note that deriving CallbackDispatcher from Thread does not work.
     45 
     46 struct OMX::CallbackDispatcherThread : public Thread {
     47     CallbackDispatcherThread(CallbackDispatcher *dispatcher)
     48         : mDispatcher(dispatcher) {
     49     }
     50 
     51 private:
     52     CallbackDispatcher *mDispatcher;
     53 
     54     bool threadLoop();
     55 
     56     CallbackDispatcherThread(const CallbackDispatcherThread &);
     57     CallbackDispatcherThread &operator=(const CallbackDispatcherThread &);
     58 };
     59 
     60 ////////////////////////////////////////////////////////////////////////////////
     61 
     62 struct OMX::CallbackDispatcher : public RefBase {
     63     CallbackDispatcher(OMXNodeInstance *owner);
     64 
     65     // Posts |msg| to the listener's queue. If |realTime| is true, the listener thread is notified
     66     // that a new message is available on the queue. Otherwise, the message stays on the queue, but
     67     // the listener is not notified of it. It will process this message when a subsequent message
     68     // is posted with |realTime| set to true.
     69     void post(const omx_message &msg, bool realTime = true);
     70 
     71     bool loop();
     72 
     73 protected:
     74     virtual ~CallbackDispatcher();
     75 
     76 private:
     77     Mutex mLock;
     78 
     79     OMXNodeInstance *mOwner;
     80     bool mDone;
     81     Condition mQueueChanged;
     82     std::list<omx_message> mQueue;
     83 
     84     sp<CallbackDispatcherThread> mThread;
     85 
     86     void dispatch(std::list<omx_message> &messages);
     87 
     88     CallbackDispatcher(const CallbackDispatcher &);
     89     CallbackDispatcher &operator=(const CallbackDispatcher &);
     90 };
     91 
     92 OMX::CallbackDispatcher::CallbackDispatcher(OMXNodeInstance *owner)
     93     : mOwner(owner),
     94       mDone(false) {
     95     mThread = new CallbackDispatcherThread(this);
     96     mThread->run("OMXCallbackDisp", ANDROID_PRIORITY_FOREGROUND);
     97 }
     98 
     99 OMX::CallbackDispatcher::~CallbackDispatcher() {
    100     {
    101         Mutex::Autolock autoLock(mLock);
    102 
    103         mDone = true;
    104         mQueueChanged.signal();
    105     }
    106 
    107     // A join on self can happen if the last ref to CallbackDispatcher
    108     // is released within the CallbackDispatcherThread loop
    109     status_t status = mThread->join();
    110     if (status != WOULD_BLOCK) {
    111         // Other than join to self, the only other error return codes are
    112         // whatever readyToRun() returns, and we don't override that
    113         CHECK_EQ(status, (status_t)NO_ERROR);
    114     }
    115 }
    116 
    117 void OMX::CallbackDispatcher::post(const omx_message &msg, bool realTime) {
    118     Mutex::Autolock autoLock(mLock);
    119 
    120     mQueue.push_back(msg);
    121     if (realTime) {
    122         mQueueChanged.signal();
    123     }
    124 }
    125 
    126 void OMX::CallbackDispatcher::dispatch(std::list<omx_message> &messages) {
    127     if (mOwner == NULL) {
    128         ALOGV("Would have dispatched a message to a node that's already gone.");
    129         return;
    130     }
    131     mOwner->onMessages(messages);
    132 }
    133 
    134 bool OMX::CallbackDispatcher::loop() {
    135     for (;;) {
    136         std::list<omx_message> messages;
    137 
    138         {
    139             Mutex::Autolock autoLock(mLock);
    140             while (!mDone && mQueue.empty()) {
    141                 mQueueChanged.wait(mLock);
    142             }
    143 
    144             if (mDone) {
    145                 break;
    146             }
    147 
    148             messages.swap(mQueue);
    149         }
    150 
    151         dispatch(messages);
    152     }
    153 
    154     return false;
    155 }
    156 
    157 ////////////////////////////////////////////////////////////////////////////////
    158 
    159 bool OMX::CallbackDispatcherThread::threadLoop() {
    160     return mDispatcher->loop();
    161 }
    162 
    163 ////////////////////////////////////////////////////////////////////////////////
    164 
    165 OMX::OMX()
    166     : mMaster(new OMXMaster),
    167       mNodeCounter(0) {
    168 }
    169 
    170 OMX::~OMX() {
    171     delete mMaster;
    172     mMaster = NULL;
    173 }
    174 
    175 void OMX::binderDied(const wp<IBinder> &the_late_who) {
    176     OMXNodeInstance *instance;
    177 
    178     {
    179         Mutex::Autolock autoLock(mLock);
    180 
    181         ssize_t index = mLiveNodes.indexOfKey(the_late_who);
    182         CHECK(index >= 0);
    183 
    184         instance = mLiveNodes.editValueAt(index);
    185         mLiveNodes.removeItemsAt(index);
    186 
    187         index = mDispatchers.indexOfKey(instance->nodeID());
    188         CHECK(index >= 0);
    189         mDispatchers.removeItemsAt(index);
    190 
    191         invalidateNodeID_l(instance->nodeID());
    192     }
    193 
    194     instance->onObserverDied(mMaster);
    195 }
    196 
    197 bool OMX::livesLocally(node_id /* node */, pid_t pid) {
    198     return pid == getpid();
    199 }
    200 
    201 status_t OMX::listNodes(List<ComponentInfo> *list) {
    202     list->clear();
    203 
    204     OMX_U32 index = 0;
    205     char componentName[256];
    206     while (mMaster->enumerateComponents(
    207                 componentName, sizeof(componentName), index) == OMX_ErrorNone) {
    208         list->push_back(ComponentInfo());
    209         ComponentInfo &info = *--list->end();
    210 
    211         info.mName = componentName;
    212 
    213         Vector<String8> roles;
    214         OMX_ERRORTYPE err =
    215             mMaster->getRolesOfComponent(componentName, &roles);
    216 
    217         if (err == OMX_ErrorNone) {
    218             for (OMX_U32 i = 0; i < roles.size(); ++i) {
    219                 info.mRoles.push_back(roles[i]);
    220             }
    221         }
    222 
    223         ++index;
    224     }
    225 
    226     return OK;
    227 }
    228 
    229 status_t OMX::allocateNode(
    230         const char *name, const sp<IOMXObserver> &observer, node_id *node) {
    231     Mutex::Autolock autoLock(mLock);
    232 
    233     *node = 0;
    234 
    235     OMXNodeInstance *instance = new OMXNodeInstance(this, observer, name);
    236 
    237     OMX_COMPONENTTYPE *handle;
    238     OMX_ERRORTYPE err = mMaster->makeComponentInstance(
    239             name, &OMXNodeInstance::kCallbacks,
    240             instance, &handle);
    241 
    242     if (err != OMX_ErrorNone) {
    243         ALOGE("FAILED to allocate omx component '%s' err=%s(%#x)", name, asString(err), err);
    244 
    245         instance->onGetHandleFailed();
    246 
    247         return StatusFromOMXError(err);
    248     }
    249 
    250     *node = makeNodeID(instance);
    251     mDispatchers.add(*node, new CallbackDispatcher(instance));
    252 
    253     instance->setHandle(*node, handle);
    254 
    255     mLiveNodes.add(IInterface::asBinder(observer), instance);
    256     IInterface::asBinder(observer)->linkToDeath(this);
    257 
    258     return OK;
    259 }
    260 
    261 status_t OMX::freeNode(node_id node) {
    262     OMXNodeInstance *instance = findInstance(node);
    263 
    264     {
    265         Mutex::Autolock autoLock(mLock);
    266         ssize_t index = mLiveNodes.indexOfKey(IInterface::asBinder(instance->observer()));
    267         if (index < 0) {
    268             // This could conceivably happen if the observer dies at roughly the
    269             // same time that a client attempts to free the node explicitly.
    270             return OK;
    271         }
    272         mLiveNodes.removeItemsAt(index);
    273     }
    274 
    275     IInterface::asBinder(instance->observer())->unlinkToDeath(this);
    276 
    277     status_t err = instance->freeNode(mMaster);
    278 
    279     {
    280         Mutex::Autolock autoLock(mLock);
    281         ssize_t index = mDispatchers.indexOfKey(node);
    282         CHECK(index >= 0);
    283         mDispatchers.removeItemsAt(index);
    284     }
    285 
    286     return err;
    287 }
    288 
    289 status_t OMX::sendCommand(
    290         node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) {
    291     return findInstance(node)->sendCommand(cmd, param);
    292 }
    293 
    294 status_t OMX::getParameter(
    295         node_id node, OMX_INDEXTYPE index,
    296         void *params, size_t size) {
    297     ALOGV("getParameter(%u %#x %p %zd)", node, index, params, size);
    298     return findInstance(node)->getParameter(
    299             index, params, size);
    300 }
    301 
    302 status_t OMX::setParameter(
    303         node_id node, OMX_INDEXTYPE index,
    304         const void *params, size_t size) {
    305     ALOGV("setParameter(%u %#x %p %zd)", node, index, params, size);
    306     return findInstance(node)->setParameter(
    307             index, params, size);
    308 }
    309 
    310 status_t OMX::getConfig(
    311         node_id node, OMX_INDEXTYPE index,
    312         void *params, size_t size) {
    313     return findInstance(node)->getConfig(
    314             index, params, size);
    315 }
    316 
    317 status_t OMX::setConfig(
    318         node_id node, OMX_INDEXTYPE index,
    319         const void *params, size_t size) {
    320     return findInstance(node)->setConfig(
    321             index, params, size);
    322 }
    323 
    324 status_t OMX::getState(
    325         node_id node, OMX_STATETYPE* state) {
    326     return findInstance(node)->getState(
    327             state);
    328 }
    329 
    330 status_t OMX::enableGraphicBuffers(
    331         node_id node, OMX_U32 port_index, OMX_BOOL enable) {
    332     return findInstance(node)->enableGraphicBuffers(port_index, enable);
    333 }
    334 
    335 status_t OMX::getGraphicBufferUsage(
    336         node_id node, OMX_U32 port_index, OMX_U32* usage) {
    337     return findInstance(node)->getGraphicBufferUsage(port_index, usage);
    338 }
    339 
    340 status_t OMX::storeMetaDataInBuffers(
    341         node_id node, OMX_U32 port_index, OMX_BOOL enable, MetadataBufferType *type) {
    342     return findInstance(node)->storeMetaDataInBuffers(port_index, enable, type);
    343 }
    344 
    345 status_t OMX::prepareForAdaptivePlayback(
    346         node_id node, OMX_U32 portIndex, OMX_BOOL enable,
    347         OMX_U32 maxFrameWidth, OMX_U32 maxFrameHeight) {
    348     return findInstance(node)->prepareForAdaptivePlayback(
    349             portIndex, enable, maxFrameWidth, maxFrameHeight);
    350 }
    351 
    352 status_t OMX::configureVideoTunnelMode(
    353         node_id node, OMX_U32 portIndex, OMX_BOOL tunneled,
    354         OMX_U32 audioHwSync, native_handle_t **sidebandHandle) {
    355     return findInstance(node)->configureVideoTunnelMode(
    356             portIndex, tunneled, audioHwSync, sidebandHandle);
    357 }
    358 
    359 status_t OMX::useBuffer(
    360         node_id node, OMX_U32 port_index, const sp<IMemory> &params,
    361         buffer_id *buffer, OMX_U32 allottedSize) {
    362     return findInstance(node)->useBuffer(
    363             port_index, params, buffer, allottedSize);
    364 }
    365 
    366 status_t OMX::useGraphicBuffer(
    367         node_id node, OMX_U32 port_index,
    368         const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer) {
    369     return findInstance(node)->useGraphicBuffer(
    370             port_index, graphicBuffer, buffer);
    371 }
    372 
    373 status_t OMX::updateGraphicBufferInMeta(
    374         node_id node, OMX_U32 port_index,
    375         const sp<GraphicBuffer> &graphicBuffer, buffer_id buffer) {
    376     return findInstance(node)->updateGraphicBufferInMeta(
    377             port_index, graphicBuffer, buffer);
    378 }
    379 
    380 status_t OMX::createInputSurface(
    381         node_id node, OMX_U32 port_index,
    382         sp<IGraphicBufferProducer> *bufferProducer, MetadataBufferType *type) {
    383     return findInstance(node)->createInputSurface(
    384             port_index, bufferProducer, type);
    385 }
    386 
    387 status_t OMX::createPersistentInputSurface(
    388         sp<IGraphicBufferProducer> *bufferProducer,
    389         sp<IGraphicBufferConsumer> *bufferConsumer) {
    390     return OMXNodeInstance::createPersistentInputSurface(
    391             bufferProducer, bufferConsumer);
    392 }
    393 
    394 status_t OMX::setInputSurface(
    395         node_id node, OMX_U32 port_index,
    396         const sp<IGraphicBufferConsumer> &bufferConsumer, MetadataBufferType *type) {
    397     return findInstance(node)->setInputSurface(port_index, bufferConsumer, type);
    398 }
    399 
    400 
    401 status_t OMX::signalEndOfInputStream(node_id node) {
    402     return findInstance(node)->signalEndOfInputStream();
    403 }
    404 
    405 status_t OMX::allocateBuffer(
    406         node_id node, OMX_U32 port_index, size_t size,
    407         buffer_id *buffer, void **buffer_data) {
    408     return findInstance(node)->allocateBuffer(
    409             port_index, size, buffer, buffer_data);
    410 }
    411 
    412 status_t OMX::allocateBufferWithBackup(
    413         node_id node, OMX_U32 port_index, const sp<IMemory> &params,
    414         buffer_id *buffer, OMX_U32 allottedSize) {
    415     return findInstance(node)->allocateBufferWithBackup(
    416             port_index, params, buffer, allottedSize);
    417 }
    418 
    419 status_t OMX::freeBuffer(node_id node, OMX_U32 port_index, buffer_id buffer) {
    420     return findInstance(node)->freeBuffer(
    421             port_index, buffer);
    422 }
    423 
    424 status_t OMX::fillBuffer(node_id node, buffer_id buffer, int fenceFd) {
    425     return findInstance(node)->fillBuffer(buffer, fenceFd);
    426 }
    427 
    428 status_t OMX::emptyBuffer(
    429         node_id node,
    430         buffer_id buffer,
    431         OMX_U32 range_offset, OMX_U32 range_length,
    432         OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) {
    433     return findInstance(node)->emptyBuffer(
    434             buffer, range_offset, range_length, flags, timestamp, fenceFd);
    435 }
    436 
    437 status_t OMX::getExtensionIndex(
    438         node_id node,
    439         const char *parameter_name,
    440         OMX_INDEXTYPE *index) {
    441     return findInstance(node)->getExtensionIndex(
    442             parameter_name, index);
    443 }
    444 
    445 status_t OMX::setInternalOption(
    446         node_id node,
    447         OMX_U32 port_index,
    448         InternalOptionType type,
    449         const void *data,
    450         size_t size) {
    451     return findInstance(node)->setInternalOption(port_index, type, data, size);
    452 }
    453 
    454 OMX_ERRORTYPE OMX::OnEvent(
    455         node_id node,
    456         OMX_IN OMX_EVENTTYPE eEvent,
    457         OMX_IN OMX_U32 nData1,
    458         OMX_IN OMX_U32 nData2,
    459         OMX_IN OMX_PTR pEventData) {
    460     ALOGV("OnEvent(%d, %" PRIu32", %" PRIu32 ")", eEvent, nData1, nData2);
    461 
    462     // Forward to OMXNodeInstance.
    463     findInstance(node)->onEvent(eEvent, nData1, nData2);
    464 
    465     sp<OMX::CallbackDispatcher> dispatcher = findDispatcher(node);
    466 
    467     // output rendered events are not processed as regular events until they hit the observer
    468     if (eEvent == OMX_EventOutputRendered) {
    469         if (pEventData == NULL) {
    470             return OMX_ErrorBadParameter;
    471         }
    472 
    473         // process data from array
    474         OMX_VIDEO_RENDEREVENTTYPE *renderData = (OMX_VIDEO_RENDEREVENTTYPE *)pEventData;
    475         for (size_t i = 0; i < nData1; ++i) {
    476             omx_message msg;
    477             msg.type = omx_message::FRAME_RENDERED;
    478             msg.node = node;
    479             msg.fenceFd = -1;
    480             msg.u.render_data.timestamp = renderData[i].nMediaTimeUs;
    481             msg.u.render_data.nanoTime = renderData[i].nSystemTimeNs;
    482 
    483             dispatcher->post(msg, false /* realTime */);
    484         }
    485         return OMX_ErrorNone;
    486     }
    487 
    488     omx_message msg;
    489     msg.type = omx_message::EVENT;
    490     msg.node = node;
    491     msg.fenceFd = -1;
    492     msg.u.event_data.event = eEvent;
    493     msg.u.event_data.data1 = nData1;
    494     msg.u.event_data.data2 = nData2;
    495 
    496     dispatcher->post(msg, true /* realTime */);
    497 
    498     return OMX_ErrorNone;
    499 }
    500 
    501 OMX_ERRORTYPE OMX::OnEmptyBufferDone(
    502         node_id node, buffer_id buffer, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer, int fenceFd) {
    503     ALOGV("OnEmptyBufferDone buffer=%p", pBuffer);
    504 
    505     omx_message msg;
    506     msg.type = omx_message::EMPTY_BUFFER_DONE;
    507     msg.node = node;
    508     msg.fenceFd = fenceFd;
    509     msg.u.buffer_data.buffer = buffer;
    510 
    511     findDispatcher(node)->post(msg);
    512 
    513     return OMX_ErrorNone;
    514 }
    515 
    516 OMX_ERRORTYPE OMX::OnFillBufferDone(
    517         node_id node, buffer_id buffer, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer, int fenceFd) {
    518     ALOGV("OnFillBufferDone buffer=%p", pBuffer);
    519 
    520     omx_message msg;
    521     msg.type = omx_message::FILL_BUFFER_DONE;
    522     msg.node = node;
    523     msg.fenceFd = fenceFd;
    524     msg.u.extended_buffer_data.buffer = buffer;
    525     msg.u.extended_buffer_data.range_offset = pBuffer->nOffset;
    526     msg.u.extended_buffer_data.range_length = pBuffer->nFilledLen;
    527     msg.u.extended_buffer_data.flags = pBuffer->nFlags;
    528     msg.u.extended_buffer_data.timestamp = pBuffer->nTimeStamp;
    529 
    530     findDispatcher(node)->post(msg);
    531 
    532     return OMX_ErrorNone;
    533 }
    534 
    535 OMX::node_id OMX::makeNodeID(OMXNodeInstance *instance) {
    536     // mLock is already held.
    537 
    538     node_id node = (node_id)++mNodeCounter;
    539     mNodeIDToInstance.add(node, instance);
    540 
    541     return node;
    542 }
    543 
    544 OMXNodeInstance *OMX::findInstance(node_id node) {
    545     Mutex::Autolock autoLock(mLock);
    546 
    547     ssize_t index = mNodeIDToInstance.indexOfKey(node);
    548 
    549     return index < 0 ? NULL : mNodeIDToInstance.valueAt(index);
    550 }
    551 
    552 sp<OMX::CallbackDispatcher> OMX::findDispatcher(node_id node) {
    553     Mutex::Autolock autoLock(mLock);
    554 
    555     ssize_t index = mDispatchers.indexOfKey(node);
    556 
    557     return index < 0 ? NULL : mDispatchers.valueAt(index);
    558 }
    559 
    560 void OMX::invalidateNodeID(node_id node) {
    561     Mutex::Autolock autoLock(mLock);
    562     invalidateNodeID_l(node);
    563 }
    564 
    565 void OMX::invalidateNodeID_l(node_id node) {
    566     // mLock is held.
    567     mNodeIDToInstance.removeItem(node);
    568 }
    569 
    570 }  // namespace android
    571