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 //#define LOG_NDEBUG 0 18 #define LOG_TAG "OMXMaster" 19 #include <utils/Log.h> 20 21 #include <media/stagefright/omx/OMXMaster.h> 22 #include <media/stagefright/omx/SoftOMXPlugin.h> 23 #include <media/stagefright/foundation/ADebug.h> 24 25 #include <vndksupport/linker.h> 26 27 #include <dlfcn.h> 28 #include <fcntl.h> 29 30 namespace android { 31 32 OMXMaster::OMXMaster() { 33 34 pid_t pid = getpid(); 35 char filename[20]; 36 snprintf(filename, sizeof(filename), "/proc/%d/comm", pid); 37 int fd = open(filename, O_RDONLY); 38 if (fd < 0) { 39 ALOGW("couldn't determine process name"); 40 strlcpy(mProcessName, "<unknown>", sizeof(mProcessName)); 41 } else { 42 ssize_t len = read(fd, mProcessName, sizeof(mProcessName)); 43 if (len < 2) { 44 ALOGW("couldn't determine process name"); 45 strlcpy(mProcessName, "<unknown>", sizeof(mProcessName)); 46 } else { 47 // the name is newline terminated, so erase the newline 48 mProcessName[len - 1] = 0; 49 } 50 close(fd); 51 } 52 53 addVendorPlugin(); 54 addPlatformPlugin(); 55 } 56 57 OMXMaster::~OMXMaster() { 58 clearPlugins(); 59 } 60 61 void OMXMaster::addVendorPlugin() { 62 addPlugin("libstagefrighthw.so"); 63 } 64 65 void OMXMaster::addPlatformPlugin() { 66 addPlugin("libstagefright_softomx_plugin.so"); 67 } 68 69 void OMXMaster::addPlugin(const char *libname) { 70 void *libHandle = android_load_sphal_library(libname, RTLD_NOW); 71 72 if (libHandle == NULL) { 73 return; 74 } 75 76 typedef OMXPluginBase *(*CreateOMXPluginFunc)(); 77 CreateOMXPluginFunc createOMXPlugin = 78 (CreateOMXPluginFunc)dlsym( 79 libHandle, "createOMXPlugin"); 80 if (!createOMXPlugin) 81 createOMXPlugin = (CreateOMXPluginFunc)dlsym( 82 libHandle, "_ZN7android15createOMXPluginEv"); 83 84 OMXPluginBase *plugin = nullptr; 85 if (createOMXPlugin) { 86 plugin = (*createOMXPlugin)(); 87 } 88 89 if (plugin) { 90 mPlugins.push_back({ plugin, libHandle }); 91 addPlugin(plugin); 92 } else { 93 android_unload_sphal_library(libHandle); 94 } 95 } 96 97 void OMXMaster::addPlugin(OMXPluginBase *plugin) { 98 Mutex::Autolock autoLock(mLock); 99 100 OMX_U32 index = 0; 101 102 char name[128]; 103 OMX_ERRORTYPE err; 104 while ((err = plugin->enumerateComponents( 105 name, sizeof(name), index++)) == OMX_ErrorNone) { 106 String8 name8(name); 107 108 if (mPluginByComponentName.indexOfKey(name8) >= 0) { 109 ALOGE("A component of name '%s' already exists, ignoring this one.", 110 name8.string()); 111 112 continue; 113 } 114 115 mPluginByComponentName.add(name8, plugin); 116 } 117 118 if (err != OMX_ErrorNoMore) { 119 ALOGE("OMX plugin failed w/ error 0x%08x after registering %zu " 120 "components", err, mPluginByComponentName.size()); 121 } 122 } 123 124 void OMXMaster::clearPlugins() { 125 Mutex::Autolock autoLock(mLock); 126 127 mPluginByComponentName.clear(); 128 mPluginByInstance.clear(); 129 130 typedef void (*DestroyOMXPluginFunc)(OMXPluginBase*); 131 for (const Plugin &plugin : mPlugins) { 132 DestroyOMXPluginFunc destroyOMXPlugin = 133 (DestroyOMXPluginFunc)dlsym( 134 plugin.mLibHandle, "destroyOMXPlugin"); 135 if (destroyOMXPlugin) 136 destroyOMXPlugin(plugin.mOmx); 137 else 138 delete plugin.mOmx; 139 140 android_unload_sphal_library(plugin.mLibHandle); 141 } 142 143 mPlugins.clear(); 144 } 145 146 OMX_ERRORTYPE OMXMaster::makeComponentInstance( 147 const char *name, 148 const OMX_CALLBACKTYPE *callbacks, 149 OMX_PTR appData, 150 OMX_COMPONENTTYPE **component) { 151 ALOGI("makeComponentInstance(%s) in %s process", name, mProcessName); 152 Mutex::Autolock autoLock(mLock); 153 154 *component = NULL; 155 156 ssize_t index = mPluginByComponentName.indexOfKey(String8(name)); 157 158 if (index < 0) { 159 return OMX_ErrorInvalidComponentName; 160 } 161 162 OMXPluginBase *plugin = mPluginByComponentName.valueAt(index); 163 OMX_ERRORTYPE err = 164 plugin->makeComponentInstance(name, callbacks, appData, component); 165 166 if (err != OMX_ErrorNone) { 167 return err; 168 } 169 170 mPluginByInstance.add(*component, plugin); 171 172 return err; 173 } 174 175 OMX_ERRORTYPE OMXMaster::destroyComponentInstance( 176 OMX_COMPONENTTYPE *component) { 177 Mutex::Autolock autoLock(mLock); 178 179 ssize_t index = mPluginByInstance.indexOfKey(component); 180 181 if (index < 0) { 182 return OMX_ErrorBadParameter; 183 } 184 185 OMXPluginBase *plugin = mPluginByInstance.valueAt(index); 186 mPluginByInstance.removeItemsAt(index); 187 188 return plugin->destroyComponentInstance(component); 189 } 190 191 OMX_ERRORTYPE OMXMaster::enumerateComponents( 192 OMX_STRING name, 193 size_t size, 194 OMX_U32 index) { 195 Mutex::Autolock autoLock(mLock); 196 197 size_t numComponents = mPluginByComponentName.size(); 198 199 if (index >= numComponents) { 200 return OMX_ErrorNoMore; 201 } 202 203 const String8 &name8 = mPluginByComponentName.keyAt(index); 204 205 CHECK(size >= 1 + name8.size()); 206 strcpy(name, name8.string()); 207 208 return OMX_ErrorNone; 209 } 210 211 OMX_ERRORTYPE OMXMaster::getRolesOfComponent( 212 const char *name, 213 Vector<String8> *roles) { 214 Mutex::Autolock autoLock(mLock); 215 216 roles->clear(); 217 218 ssize_t index = mPluginByComponentName.indexOfKey(String8(name)); 219 220 if (index < 0) { 221 return OMX_ErrorInvalidComponentName; 222 } 223 224 OMXPluginBase *plugin = mPluginByComponentName.valueAt(index); 225 return plugin->getRolesOfComponent(name, roles); 226 } 227 228 } // namespace android 229