Home | History | Annotate | Download | only in 1.0
      1 /*
      2  * Copyright 2016, 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 <ios>
     18 #include <list>
     19 
     20 #include <android-base/logging.h>
     21 #include <gui/IGraphicBufferProducer.h>
     22 #include <media/openmax/OMX_Core.h>
     23 #include <media/openmax/OMX_AsString.h>
     24 
     25 #include <media/stagefright/omx/OMXUtils.h>
     26 #include <media/stagefright/omx/OMXMaster.h>
     27 #include <media/stagefright/omx/OmxGraphicBufferSource.h>
     28 
     29 #include <media/stagefright/omx/1.0/WOmxNode.h>
     30 #include <media/stagefright/omx/1.0/WOmxObserver.h>
     31 #include <media/stagefright/omx/1.0/WGraphicBufferProducer.h>
     32 #include <media/stagefright/omx/1.0/WGraphicBufferSource.h>
     33 #include <media/stagefright/omx/1.0/Conversion.h>
     34 #include <media/stagefright/omx/1.0/Omx.h>
     35 
     36 namespace android {
     37 namespace hardware {
     38 namespace media {
     39 namespace omx {
     40 namespace V1_0 {
     41 namespace implementation {
     42 
     43 constexpr size_t kMaxNodeInstances = (1 << 16);
     44 
     45 Omx::Omx() :
     46     mMaster(new OMXMaster()),
     47     mParser() {
     48 }
     49 
     50 Omx::~Omx() {
     51     delete mMaster;
     52 }
     53 
     54 Return<void> Omx::listNodes(listNodes_cb _hidl_cb) {
     55     std::list<::android::IOMX::ComponentInfo> list;
     56     char componentName[256];
     57     for (OMX_U32 index = 0;
     58             mMaster->enumerateComponents(
     59             componentName, sizeof(componentName), index) == OMX_ErrorNone;
     60             ++index) {
     61         list.push_back(::android::IOMX::ComponentInfo());
     62         ::android::IOMX::ComponentInfo& info = list.back();
     63         info.mName = componentName;
     64         ::android::Vector<::android::String8> roles;
     65         OMX_ERRORTYPE err =
     66                 mMaster->getRolesOfComponent(componentName, &roles);
     67         if (err == OMX_ErrorNone) {
     68             for (OMX_U32 i = 0; i < roles.size(); ++i) {
     69                 info.mRoles.push_back(roles[i]);
     70             }
     71         }
     72     }
     73 
     74     hidl_vec<ComponentInfo> tList;
     75     tList.resize(list.size());
     76     size_t i = 0;
     77     for (auto const& info : list) {
     78         convertTo(&(tList[i++]), info);
     79     }
     80     _hidl_cb(toStatus(OK), tList);
     81     return Void();
     82 }
     83 
     84 Return<void> Omx::allocateNode(
     85         const hidl_string& name,
     86         const sp<IOmxObserver>& observer,
     87         allocateNode_cb _hidl_cb) {
     88 
     89     using ::android::IOMXNode;
     90     using ::android::IOMXObserver;
     91 
     92     sp<OMXNodeInstance> instance;
     93     {
     94         Mutex::Autolock autoLock(mLock);
     95         if (mLiveNodes.size() == kMaxNodeInstances) {
     96             _hidl_cb(toStatus(NO_MEMORY), nullptr);
     97             return Void();
     98         }
     99 
    100         instance = new OMXNodeInstance(
    101                 this, new LWOmxObserver(observer), name.c_str());
    102 
    103         OMX_COMPONENTTYPE *handle;
    104         OMX_ERRORTYPE err = mMaster->makeComponentInstance(
    105                 name.c_str(), &OMXNodeInstance::kCallbacks,
    106                 instance.get(), &handle);
    107 
    108         if (err != OMX_ErrorNone) {
    109             LOG(ERROR) << "Failed to allocate omx component "
    110                     "'" << name.c_str() << "' "
    111                     " err=" << asString(err) <<
    112                     "(0x" << std::hex << unsigned(err) << ")";
    113             _hidl_cb(toStatus(StatusFromOMXError(err)), nullptr);
    114             return Void();
    115         }
    116         instance->setHandle(handle);
    117 
    118         // Find quirks from mParser
    119         const auto& codec = mParser.getCodecMap().find(name.c_str());
    120         if (codec == mParser.getCodecMap().cend()) {
    121             LOG(WARNING) << "Failed to obtain quirks for omx component "
    122                     "'" << name.c_str() << "' "
    123                     "from XML files";
    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(observer.get(), instance);
    140         mNode2Observer.add(instance.get(), observer.get());
    141     }
    142     observer->linkToDeath(this, 0);
    143 
    144     _hidl_cb(toStatus(OK), new TWOmxNode(instance));
    145     return Void();
    146 }
    147 
    148 Return<void> Omx::createInputSurface(createInputSurface_cb _hidl_cb) {
    149     sp<::android::IGraphicBufferProducer> bufferProducer;
    150 
    151     sp<OmxGraphicBufferSource> graphicBufferSource = new OmxGraphicBufferSource();
    152     status_t err = graphicBufferSource->initCheck();
    153     if (err != OK) {
    154         LOG(ERROR) << "Failed to create persistent input surface: "
    155                 << strerror(-err) << " "
    156                 "(" << int(err) << ")";
    157         _hidl_cb(toStatus(err), nullptr, nullptr);
    158         return Void();
    159     }
    160     bufferProducer = graphicBufferSource->getIGraphicBufferProducer();
    161 
    162     _hidl_cb(toStatus(OK),
    163             new TWGraphicBufferProducer(bufferProducer),
    164             new TWGraphicBufferSource(graphicBufferSource));
    165     return Void();
    166 }
    167 
    168 void Omx::serviceDied(uint64_t /* cookie */, wp<IBase> const& who) {
    169     sp<OMXNodeInstance> instance;
    170     {
    171         Mutex::Autolock autoLock(mLock);
    172 
    173         ssize_t index = mLiveNodes.indexOfKey(who);
    174 
    175         if (index < 0) {
    176             LOG(ERROR) << "b/27597103, nonexistent observer on serviceDied";
    177             android_errorWriteLog(0x534e4554, "27597103");
    178             return;
    179         }
    180 
    181         instance = mLiveNodes.editValueAt(index);
    182         mLiveNodes.removeItemsAt(index);
    183         mNode2Observer.removeItem(instance.get());
    184     }
    185     instance->onObserverDied();
    186 }
    187 
    188 status_t Omx::freeNode(sp<OMXNodeInstance> const& instance) {
    189     if (instance == NULL) {
    190         return OK;
    191     }
    192 
    193     {
    194         Mutex::Autolock autoLock(mLock);
    195         ssize_t observerIndex = mNode2Observer.indexOfKey(instance.get());
    196         if (observerIndex >= 0) {
    197             wp<IBase> observer = mNode2Observer.valueAt(observerIndex);
    198             ssize_t nodeIndex = mLiveNodes.indexOfKey(observer);
    199             if (nodeIndex >= 0) {
    200                 mNode2Observer.removeItemsAt(observerIndex);
    201                 mLiveNodes.removeItemsAt(nodeIndex);
    202                 sp<IBase> sObserver = observer.promote();
    203                 if (sObserver != nullptr) {
    204                     sObserver->unlinkToDeath(this);
    205                 }
    206             } else {
    207                 LOG(WARNING) << "Inconsistent observer record";
    208             }
    209         }
    210     }
    211 
    212     OMX_ERRORTYPE err = OMX_ErrorNone;
    213     if (instance->handle() != NULL) {
    214         err = mMaster->destroyComponentInstance(
    215                 static_cast<OMX_COMPONENTTYPE*>(instance->handle()));
    216     }
    217     return StatusFromOMXError(err);
    218 }
    219 
    220 // Methods from ::android::hidl::base::V1_0::IBase follow.
    221 
    222 IOmx* HIDL_FETCH_IOmx(const char* /* name */) {
    223     return new Omx();
    224 }
    225 
    226 }  // namespace implementation
    227 }  // namespace V1_0
    228 }  // namespace omx
    229 }  // namespace media
    230 }  // namespace hardware
    231 }  // namespace android
    232