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