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
OMXMaster()32 OMXMaster::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
~OMXMaster()61 OMXMaster::~OMXMaster() {
62 clearPlugins();
63
64 if (mVendorLibHandle != NULL) {
65 dlclose(mVendorLibHandle);
66 mVendorLibHandle = NULL;
67 }
68 }
69
addVendorPlugin()70 void OMXMaster::addVendorPlugin() {
71 addPlugin("libstagefrighthw.so");
72 }
73
addPlugin(const char * libname)74 void 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
addPlugin(OMXPluginBase * plugin)94 void 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
clearPlugins()123 void 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
makeComponentInstance(const char * name,const OMX_CALLBACKTYPE * callbacks,OMX_PTR appData,OMX_COMPONENTTYPE ** component)145 OMX_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
destroyComponentInstance(OMX_COMPONENTTYPE * component)174 OMX_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
enumerateComponents(OMX_STRING name,size_t size,OMX_U32 index)190 OMX_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
getRolesOfComponent(const char * name,Vector<String8> * roles)210 OMX_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