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