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 <media/stagefright/omx/OMX.h>
     26 #include <media/stagefright/omx/OMXNodeInstance.h>
     27 #include <media/stagefright/omx/BWGraphicBufferSource.h>
     28 #include <media/stagefright/omx/OMXMaster.h>
     29 #include <media/stagefright/omx/OMXUtils.h>
     30 #include <media/stagefright/foundation/ADebug.h>
     31 
     32 namespace android {
     33 
     34 // node ids are created by concatenating the pid with a 16-bit counter
     35 static size_t kMaxNodeInstances = (1 << 16);
     36 
     37 OMX::OMX() : mMaster(new OMXMaster), mParser() {
     38 }
     39 
     40 OMX::~OMX() {
     41     delete mMaster;
     42     mMaster = NULL;
     43 }
     44 
     45 void OMX::binderDied(const wp<IBinder> &the_late_who) {
     46     sp<OMXNodeInstance> instance;
     47 
     48     {
     49         Mutex::Autolock autoLock(mLock);
     50 
     51         ssize_t index = mLiveNodes.indexOfKey(the_late_who);
     52 
     53         if (index < 0) {
     54             ALOGE("b/27597103, nonexistent observer on binderDied");
     55             android_errorWriteLog(0x534e4554, "27597103");
     56             return;
     57         }
     58 
     59         instance = mLiveNodes.editValueAt(index);
     60         mLiveNodes.removeItemsAt(index);
     61     }
     62 
     63     instance->onObserverDied();
     64 }
     65 
     66 status_t OMX::listNodes(List<ComponentInfo> *list) {
     67     list->clear();
     68 
     69     OMX_U32 index = 0;
     70     char componentName[256];
     71     while (mMaster->enumerateComponents(
     72                 componentName, sizeof(componentName), index) == OMX_ErrorNone) {
     73         list->push_back(ComponentInfo());
     74         ComponentInfo &info = *--list->end();
     75 
     76         info.mName = componentName;
     77 
     78         Vector<String8> roles;
     79         OMX_ERRORTYPE err =
     80             mMaster->getRolesOfComponent(componentName, &roles);
     81 
     82         if (err == OMX_ErrorNone) {
     83             for (OMX_U32 i = 0; i < roles.size(); ++i) {
     84                 info.mRoles.push_back(roles[i]);
     85             }
     86         }
     87 
     88         ++index;
     89     }
     90 
     91     return OK;
     92 }
     93 
     94 status_t OMX::allocateNode(
     95         const char *name, const sp<IOMXObserver> &observer,
     96         sp<IOMXNode> *omxNode) {
     97     Mutex::Autolock autoLock(mLock);
     98 
     99     omxNode->clear();
    100 
    101     if (mLiveNodes.size() == kMaxNodeInstances) {
    102         return NO_MEMORY;
    103     }
    104 
    105     sp<OMXNodeInstance> instance = new OMXNodeInstance(this, observer, name);
    106 
    107     OMX_COMPONENTTYPE *handle;
    108     OMX_ERRORTYPE err = mMaster->makeComponentInstance(
    109             name, &OMXNodeInstance::kCallbacks,
    110             instance.get(), &handle);
    111 
    112     if (err != OMX_ErrorNone) {
    113         ALOGE("FAILED to allocate omx component '%s' err=%s(%#x)", name, asString(err), err);
    114 
    115         return StatusFromOMXError(err);
    116     }
    117     instance->setHandle(handle);
    118 
    119     // Find quirks from mParser
    120     const auto& codec = mParser.getCodecMap().find(name);
    121     if (codec == mParser.getCodecMap().cend()) {
    122         ALOGW("Failed to obtain quirks for omx component '%s' from XML files",
    123                 name);
    124     } else {
    125         uint32_t quirks = 0;
    126         for (const auto& quirk : codec->second.quirkSet) {
    127             if (quirk == "requires-allocate-on-input-ports") {
    128                 quirks |= OMXNodeInstance::
    129                         kRequiresAllocateBufferOnInputPorts;
    130             }
    131             if (quirk == "requires-allocate-on-output-ports") {
    132                 quirks |= OMXNodeInstance::
    133                         kRequiresAllocateBufferOnOutputPorts;
    134             }
    135         }
    136         instance->setQuirks(quirks);
    137     }
    138 
    139     mLiveNodes.add(IInterface::asBinder(observer), instance);
    140     IInterface::asBinder(observer)->linkToDeath(this);
    141 
    142     *omxNode = instance;
    143 
    144     return OK;
    145 }
    146 
    147 status_t OMX::freeNode(const sp<OMXNodeInstance> &instance) {
    148     if (instance == NULL) {
    149         return OK;
    150     }
    151 
    152     {
    153         Mutex::Autolock autoLock(mLock);
    154         ssize_t index = mLiveNodes.indexOfKey(IInterface::asBinder(instance->observer()));
    155         if (index < 0) {
    156             // This could conceivably happen if the observer dies at roughly the
    157             // same time that a client attempts to free the node explicitly.
    158 
    159             // NOTE: it's guaranteed that this method is called at most once per
    160             //       instance.
    161             ALOGV("freeNode: instance already removed from book-keeping.");
    162         } else {
    163             mLiveNodes.removeItemsAt(index);
    164             IInterface::asBinder(instance->observer())->unlinkToDeath(this);
    165         }
    166     }
    167 
    168     CHECK(instance->handle() != NULL);
    169     OMX_ERRORTYPE err = mMaster->destroyComponentInstance(
    170             static_cast<OMX_COMPONENTTYPE *>(instance->handle()));
    171     ALOGV("freeNode: handle destroyed: %p", instance->handle());
    172 
    173     return StatusFromOMXError(err);
    174 }
    175 
    176 status_t OMX::createInputSurface(
    177         sp<IGraphicBufferProducer> *bufferProducer,
    178         sp<IGraphicBufferSource> *bufferSource) {
    179     if (bufferProducer == NULL || bufferSource == NULL) {
    180         ALOGE("b/25884056");
    181         return BAD_VALUE;
    182     }
    183 
    184     sp<GraphicBufferSource> graphicBufferSource = new GraphicBufferSource();
    185     status_t err = graphicBufferSource->initCheck();
    186     if (err != OK) {
    187         ALOGE("Failed to create persistent input surface: %s (%d)",
    188                 strerror(-err), err);
    189         return err;
    190     }
    191 
    192     *bufferProducer = graphicBufferSource->getIGraphicBufferProducer();
    193     *bufferSource = new BWGraphicBufferSource(graphicBufferSource);
    194 
    195     return OK;
    196 }
    197 
    198 }  // namespace android
    199