Omx.cpp revision 255735a38b9d5c3755c7b819bdc8fdaf4357d860
18c0d56d55abcc0559f1472979ed31a817e678731Wouter van Oortmerssen/* 29a1f7be6fd318ddd9545926b5925cf0a10a083e4evolutional * Copyright 2016, The Android Open Source Project 39a1f7be6fd318ddd9545926b5925cf0a10a083e4evolutional * 49a1f7be6fd318ddd9545926b5925cf0a10a083e4evolutional * Licensed under the Apache License, Version 2.0 (the "License"); 59a1f7be6fd318ddd9545926b5925cf0a10a083e4evolutional * you may not use this file except in compliance with the License. 69a1f7be6fd318ddd9545926b5925cf0a10a083e4evolutional * You may obtain a copy of the License at 79a1f7be6fd318ddd9545926b5925cf0a10a083e4evolutional * 89a1f7be6fd318ddd9545926b5925cf0a10a083e4evolutional * http://www.apache.org/licenses/LICENSE-2.0 99a1f7be6fd318ddd9545926b5925cf0a10a083e4evolutional * 109a1f7be6fd318ddd9545926b5925cf0a10a083e4evolutional * Unless required by applicable law or agreed to in writing, software 119a1f7be6fd318ddd9545926b5925cf0a10a083e4evolutional * distributed under the License is distributed on an "AS IS" BASIS, 129a1f7be6fd318ddd9545926b5925cf0a10a083e4evolutional * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139a1f7be6fd318ddd9545926b5925cf0a10a083e4evolutional * See the License for the specific language governing permissions and 149a1f7be6fd318ddd9545926b5925cf0a10a083e4evolutional * limitations under the License. 159a1f7be6fd318ddd9545926b5925cf0a10a083e4evolutional */ 169a1f7be6fd318ddd9545926b5925cf0a10a083e4evolutional 179a1f7be6fd318ddd9545926b5925cf0a10a083e4evolutional#include <ios> 189a1f7be6fd318ddd9545926b5925cf0a10a083e4evolutional#include <list> 199a1f7be6fd318ddd9545926b5925cf0a10a083e4evolutional 209a1f7be6fd318ddd9545926b5925cf0a10a083e4evolutional#include <android-base/logging.h> 219a1f7be6fd318ddd9545926b5925cf0a10a083e4evolutional#include <gui/IGraphicBufferProducer.h> 2252ca75506abd82b5616bdef4d28e9535262c1d65Wouter van Oortmerssen#include <media/openmax/OMX_Core.h> 239a1f7be6fd318ddd9545926b5925cf0a10a083e4evolutional#include <media/openmax/OMX_AsString.h> 2452ca75506abd82b5616bdef4d28e9535262c1d65Wouter van Oortmerssen 2552ca75506abd82b5616bdef4d28e9535262c1d65Wouter van Oortmerssen#include <media/stagefright/omx/OMXUtils.h> 269a1f7be6fd318ddd9545926b5925cf0a10a083e4evolutional#include <media/stagefright/omx/OMXMaster.h> 2752ca75506abd82b5616bdef4d28e9535262c1d65Wouter van Oortmerssen#include <media/stagefright/omx/GraphicBufferSource.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 36namespace android { 37namespace hardware { 38namespace media { 39namespace omx { 40namespace V1_0 { 41namespace implementation { 42 43constexpr size_t kMaxNodeInstances = (1 << 16); 44 45Omx::Omx() : 46 mMaster(new OMXMaster()), 47 mParser() { 48} 49 50Omx::~Omx() { 51 delete mMaster; 52} 53 54Return<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 84Return<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 std::vector<AString> quirkVector; 118 if (mParser.getQuirks(name.c_str(), &quirkVector) == OK) { 119 uint32_t quirks = 0; 120 for (const AString quirk : quirkVector) { 121 if (quirk == "requires-allocate-on-input-ports") { 122 quirks |= kRequiresAllocateBufferOnInputPorts; 123 } 124 if (quirk == "requires-allocate-on-output-ports") { 125 quirks |= kRequiresAllocateBufferOnOutputPorts; 126 } 127 } 128 instance->setQuirks(quirks); 129 } 130 131 mLiveNodes.add(observer.get(), instance); 132 mNode2Observer.add(instance.get(), observer.get()); 133 } 134 observer->linkToDeath(this, 0); 135 136 _hidl_cb(toStatus(OK), new TWOmxNode(instance)); 137 return Void(); 138} 139 140Return<void> Omx::createInputSurface(createInputSurface_cb _hidl_cb) { 141 sp<::android::IGraphicBufferProducer> bufferProducer; 142 143 sp<GraphicBufferSource> graphicBufferSource = new GraphicBufferSource(); 144 status_t err = graphicBufferSource->initCheck(); 145 if (err != OK) { 146 LOG(ERROR) << "Failed to create persistent input surface: " 147 << strerror(-err) << " " 148 "(" << int(err) << ")"; 149 _hidl_cb(toStatus(err), nullptr, nullptr); 150 return Void(); 151 } 152 bufferProducer = graphicBufferSource->getIGraphicBufferProducer(); 153 154 _hidl_cb(toStatus(OK), 155 new TWGraphicBufferProducer(bufferProducer), 156 new TWGraphicBufferSource(graphicBufferSource)); 157 return Void(); 158} 159 160void Omx::serviceDied(uint64_t /* cookie */, wp<IBase> const& who) { 161 sp<OMXNodeInstance> instance; 162 { 163 Mutex::Autolock autoLock(mLock); 164 165 ssize_t index = mLiveNodes.indexOfKey(who); 166 167 if (index < 0) { 168 LOG(ERROR) << "b/27597103, nonexistent observer on serviceDied"; 169 android_errorWriteLog(0x534e4554, "27597103"); 170 return; 171 } 172 173 instance = mLiveNodes.editValueAt(index); 174 mLiveNodes.removeItemsAt(index); 175 mNode2Observer.removeItem(instance.get()); 176 } 177 instance->onObserverDied(); 178} 179 180status_t Omx::freeNode(sp<OMXNodeInstance> const& instance) { 181 if (instance == NULL) { 182 return OK; 183 } 184 185 { 186 Mutex::Autolock autoLock(mLock); 187 ssize_t observerIndex = mNode2Observer.indexOfKey(instance.get()); 188 if (observerIndex >= 0) { 189 wp<IBase> observer = mNode2Observer.valueAt(observerIndex); 190 ssize_t nodeIndex = mLiveNodes.indexOfKey(observer); 191 if (nodeIndex >= 0) { 192 mNode2Observer.removeItemsAt(observerIndex); 193 mLiveNodes.removeItemsAt(nodeIndex); 194 sp<IBase> sObserver = observer.promote(); 195 if (sObserver != nullptr) { 196 sObserver->unlinkToDeath(this); 197 } 198 } else { 199 LOG(WARNING) << "Inconsistent observer record"; 200 } 201 } 202 } 203 204 OMX_ERRORTYPE err = OMX_ErrorNone; 205 if (instance->handle() != NULL) { 206 err = mMaster->destroyComponentInstance( 207 static_cast<OMX_COMPONENTTYPE*>(instance->handle())); 208 } 209 return StatusFromOMXError(err); 210} 211 212// Methods from ::android::hidl::base::V1_0::IBase follow. 213 214IOmx* HIDL_FETCH_IOmx(const char* /* name */) { 215 return new Omx(); 216} 217 218} // namespace implementation 219} // namespace V1_0 220} // namespace omx 221} // namespace media 222} // namespace hardware 223} // namespace android 224