Omx.cpp revision 223b8e36091a48b3963d2ea6fc7e304b71e26553
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 "WOmxBufferProducer.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() : mMaster(new OMXMaster()) { 47} 48 49Omx::~Omx() { 50 delete mMaster; 51} 52 53Return<void> Omx::listNodes(listNodes_cb _hidl_cb) { 54 std::list<::android::IOMX::ComponentInfo> list; 55 OMX_U32 index = 0; 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 Mutex::Autolock autoLock(mLock); 93 if (mLiveNodes.size() == kMaxNodeInstances) { 94 _hidl_cb(toStatus(NO_MEMORY), nullptr); 95 return Void(); 96 } 97 98 sp<OMXNodeInstance> instance = new OMXNodeInstance( 99 this, new LWOmxObserver(observer), name); 100 101 OMX_COMPONENTTYPE *handle; 102 OMX_ERRORTYPE err = mMaster->makeComponentInstance( 103 name, &OMXNodeInstance::kCallbacks, 104 instance.get(), &handle); 105 106 if (err != OMX_ErrorNone) { 107 LOG(ERROR) << "Failed to allocate omx component " 108 "'" << name.c_str() << "' " 109 " err=" << asString(err) << 110 "(0x" << std::hex << unsigned(err) << ")"; 111 _hidl_cb(toStatus(StatusFromOMXError(err)), nullptr); 112 return Void(); 113 } 114 instance->setHandle(handle); 115 116 mLiveNodes.add(observer.get(), instance); 117 observer->linkToDeath(this, 0); 118 mNode2Observer.add(instance.get(), observer.get()); 119 120 _hidl_cb(toStatus(OK), new TWOmxNode(instance)); 121 return Void(); 122} 123 124Return<void> Omx::createInputSurface(createInputSurface_cb _hidl_cb) { 125 sp<::android::IGraphicBufferProducer> bufferProducer; 126 sp<::android::IGraphicBufferSource> bufferSource; 127 128 sp<GraphicBufferSource> graphicBufferSource = new GraphicBufferSource(); 129 status_t err = graphicBufferSource->initCheck(); 130 if (err != OK) { 131 LOG(ERROR) << "Failed to create persistent input surface: " 132 << strerror(-err) << " " 133 "(" << int(err) << ")"; 134 _hidl_cb(toStatus(err), nullptr, nullptr); 135 return Void(); 136 } 137 bufferProducer = graphicBufferSource->getIGraphicBufferProducer(); 138 bufferSource = graphicBufferSource; 139 140 _hidl_cb(toStatus(OK), 141 new TWOmxBufferProducer(bufferProducer), 142 new TWGraphicBufferSource(bufferSource)); 143 return Void(); 144} 145 146void Omx::serviceDied(uint64_t /* cookie */, wp<IBase> const& who) { 147 sp<OMXNodeInstance> instance; 148 { 149 Mutex::Autolock autoLock(mLock); 150 151 ssize_t index = mLiveNodes.indexOfKey(who); 152 153 if (index < 0) { 154 LOG(ERROR) << "b/27597103, nonexistent observer on serviceDied"; 155 android_errorWriteLog(0x534e4554, "27597103"); 156 return; 157 } 158 159 instance = mLiveNodes.editValueAt(index); 160 mLiveNodes.removeItemsAt(index); 161 mNode2Observer.removeItem(instance.get()); 162 } 163 instance->onObserverDied(); 164} 165 166status_t Omx::freeNode(sp<OMXNodeInstance> const& instance) { 167 if (instance == NULL) { 168 return OK; 169 } 170 171 wp<IBase> observer; 172 { 173 Mutex::Autolock autoLock(mLock); 174 ssize_t observerIndex = mNode2Observer.indexOfKey(instance.get()); 175 if (observerIndex < 0) { 176 return OK; 177 } 178 observer = mNode2Observer.valueAt(observerIndex); 179 ssize_t nodeIndex = mLiveNodes.indexOfKey(observer); 180 if (nodeIndex < 0) { 181 return OK; 182 } 183 mNode2Observer.removeItemsAt(observerIndex); 184 mLiveNodes.removeItemsAt(nodeIndex); 185 } 186 187 { 188 sp<IBase> sObserver = observer.promote(); 189 if (sObserver != nullptr) { 190 sObserver->unlinkToDeath(this); 191 } 192 } 193 194 OMX_ERRORTYPE err = OMX_ErrorNone; 195 if (instance->handle() != NULL) { 196 err = mMaster->destroyComponentInstance( 197 static_cast<OMX_COMPONENTTYPE*>(instance->handle())); 198 } 199 return StatusFromOMXError(err); 200} 201 202// Methods from ::android::hidl::base::V1_0::IBase follow. 203 204IOmx* HIDL_FETCH_IOmx(const char* /* name */) { 205 return new Omx(); 206} 207 208} // namespace implementation 209} // namespace V1_0 210} // namespace omx 211} // namespace media 212} // namespace hardware 213} // namespace android 214