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