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