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