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