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