1e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber/*
2e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber * Copyright (C) 2009 The Android Open Source Project
3e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber *
4e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber * you may not use this file except in compliance with the License.
6e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber * You may obtain a copy of the License at
7e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber *
8e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
9e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber *
10e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber * Unless required by applicable law or agreed to in writing, software
11e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber * See the License for the specific language governing permissions and
14e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber * limitations under the License.
15e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber */
16e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber
171629399bb578fc176613ccaf134d1be6e3047638Andreas Huber//#define LOG_NDEBUG 0
181629399bb578fc176613ccaf134d1be6e3047638Andreas Huber#define LOG_TAG "OMXMaster"
191629399bb578fc176613ccaf134d1be6e3047638Andreas Huber#include <utils/Log.h>
201629399bb578fc176613ccaf134d1be6e3047638Andreas Huber
21e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber#include "OMXMaster.h"
22e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber
23bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber#include "SoftOMXPlugin.h"
24bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
25e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber#include <dlfcn.h>
26e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber
27f1d5aa162c02a16b7195a43a9bcea4d592600ac4James Dong#include <media/stagefright/foundation/ADebug.h>
28e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber
29e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Hubernamespace android {
30e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber
31e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas HuberOMXMaster::OMXMaster()
32e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber    : mVendorLibHandle(NULL) {
33e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber    addVendorPlugin();
34bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    addPlugin(new SoftOMXPlugin);
35e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber}
36e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber
37e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas HuberOMXMaster::~OMXMaster() {
38e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber    clearPlugins();
39e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber
40e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber    if (mVendorLibHandle != NULL) {
41e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber        dlclose(mVendorLibHandle);
42e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber        mVendorLibHandle = NULL;
43e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber    }
44e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber}
45e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber
46e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Hubervoid OMXMaster::addVendorPlugin() {
47bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    addPlugin("libstagefrighthw.so");
48bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
49bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
50bbba88cb1bdc34705d1477208990a06904c022e7Andreas Hubervoid OMXMaster::addPlugin(const char *libname) {
51bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    mVendorLibHandle = dlopen(libname, RTLD_NOW);
52e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber
53e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber    if (mVendorLibHandle == NULL) {
54e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber        return;
55e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber    }
56e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber
57e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber    typedef OMXPluginBase *(*CreateOMXPluginFunc)();
58e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber    CreateOMXPluginFunc createOMXPlugin =
59e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber        (CreateOMXPluginFunc)dlsym(
60673aebfc7e6e8d38ad29a66d68c71ea8e9121eb1Iliyan Malchev                mVendorLibHandle, "createOMXPlugin");
61673aebfc7e6e8d38ad29a66d68c71ea8e9121eb1Iliyan Malchev    if (!createOMXPlugin)
62673aebfc7e6e8d38ad29a66d68c71ea8e9121eb1Iliyan Malchev        createOMXPlugin = (CreateOMXPluginFunc)dlsym(
63e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber                mVendorLibHandle, "_ZN7android15createOMXPluginEv");
64e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber
65f0fb96c352f30b812a4903a1d783a715e1e817bdAndreas Huber    if (createOMXPlugin) {
66f0fb96c352f30b812a4903a1d783a715e1e817bdAndreas Huber        addPlugin((*createOMXPlugin)());
67f0fb96c352f30b812a4903a1d783a715e1e817bdAndreas Huber    }
68e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber}
69e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber
70e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Hubervoid OMXMaster::addPlugin(OMXPluginBase *plugin) {
71e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber    Mutex::Autolock autoLock(mLock);
72e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber
73e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber    mPlugins.push_back(plugin);
74e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber
75e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber    OMX_U32 index = 0;
76e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber
77e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber    char name[128];
78e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber    OMX_ERRORTYPE err;
79e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber    while ((err = plugin->enumerateComponents(
80e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber                    name, sizeof(name), index++)) == OMX_ErrorNone) {
81e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber        String8 name8(name);
82e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber
83e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber        if (mPluginByComponentName.indexOfKey(name8) >= 0) {
8429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("A component of name '%s' already exists, ignoring this one.",
85e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber                 name8.string());
86e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber
87e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber            continue;
88e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber        }
89e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber
90e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber        mPluginByComponentName.add(name8, plugin);
91e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber    }
9281eacb8bbf331501bb68c7f1fdd7ca1811b03f8fAndreas Huber
9381eacb8bbf331501bb68c7f1fdd7ca1811b03f8fAndreas Huber    if (err != OMX_ErrorNoMore) {
94a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGE("OMX plugin failed w/ error 0x%08x after registering %zu "
9581eacb8bbf331501bb68c7f1fdd7ca1811b03f8fAndreas Huber             "components", err, mPluginByComponentName.size());
9681eacb8bbf331501bb68c7f1fdd7ca1811b03f8fAndreas Huber    }
97e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber}
98e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber
99e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Hubervoid OMXMaster::clearPlugins() {
100e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber    Mutex::Autolock autoLock(mLock);
101e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber
102673aebfc7e6e8d38ad29a66d68c71ea8e9121eb1Iliyan Malchev    typedef void (*DestroyOMXPluginFunc)(OMXPluginBase*);
103673aebfc7e6e8d38ad29a66d68c71ea8e9121eb1Iliyan Malchev    DestroyOMXPluginFunc destroyOMXPlugin =
104673aebfc7e6e8d38ad29a66d68c71ea8e9121eb1Iliyan Malchev        (DestroyOMXPluginFunc)dlsym(
105673aebfc7e6e8d38ad29a66d68c71ea8e9121eb1Iliyan Malchev                mVendorLibHandle, "destroyOMXPlugin");
106673aebfc7e6e8d38ad29a66d68c71ea8e9121eb1Iliyan Malchev
107e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber    mPluginByComponentName.clear();
108e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber
109e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber    for (List<OMXPluginBase *>::iterator it = mPlugins.begin();
110673aebfc7e6e8d38ad29a66d68c71ea8e9121eb1Iliyan Malchev            it != mPlugins.end(); ++it) {
111673aebfc7e6e8d38ad29a66d68c71ea8e9121eb1Iliyan Malchev        if (destroyOMXPlugin)
112673aebfc7e6e8d38ad29a66d68c71ea8e9121eb1Iliyan Malchev            destroyOMXPlugin(*it);
113673aebfc7e6e8d38ad29a66d68c71ea8e9121eb1Iliyan Malchev        else
114673aebfc7e6e8d38ad29a66d68c71ea8e9121eb1Iliyan Malchev            delete *it;
115e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber        *it = NULL;
116e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber    }
117e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber
118e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber    mPlugins.clear();
119e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber}
120e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber
121e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas HuberOMX_ERRORTYPE OMXMaster::makeComponentInstance(
122e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber        const char *name,
123e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber        const OMX_CALLBACKTYPE *callbacks,
124e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber        OMX_PTR appData,
125e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber        OMX_COMPONENTTYPE **component) {
126e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber    Mutex::Autolock autoLock(mLock);
127e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber
128e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber    *component = NULL;
129e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber
130e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber    ssize_t index = mPluginByComponentName.indexOfKey(String8(name));
131e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber
132e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber    if (index < 0) {
133e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber        return OMX_ErrorInvalidComponentName;
134e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber    }
135e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber
136e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber    OMXPluginBase *plugin = mPluginByComponentName.valueAt(index);
137f0fb96c352f30b812a4903a1d783a715e1e817bdAndreas Huber    OMX_ERRORTYPE err =
138f0fb96c352f30b812a4903a1d783a715e1e817bdAndreas Huber        plugin->makeComponentInstance(name, callbacks, appData, component);
139f0fb96c352f30b812a4903a1d783a715e1e817bdAndreas Huber
140f0fb96c352f30b812a4903a1d783a715e1e817bdAndreas Huber    if (err != OMX_ErrorNone) {
141f0fb96c352f30b812a4903a1d783a715e1e817bdAndreas Huber        return err;
142f0fb96c352f30b812a4903a1d783a715e1e817bdAndreas Huber    }
143f0fb96c352f30b812a4903a1d783a715e1e817bdAndreas Huber
144f0fb96c352f30b812a4903a1d783a715e1e817bdAndreas Huber    mPluginByInstance.add(*component, plugin);
145f0fb96c352f30b812a4903a1d783a715e1e817bdAndreas Huber
146f0fb96c352f30b812a4903a1d783a715e1e817bdAndreas Huber    return err;
147f0fb96c352f30b812a4903a1d783a715e1e817bdAndreas Huber}
148f0fb96c352f30b812a4903a1d783a715e1e817bdAndreas Huber
149f0fb96c352f30b812a4903a1d783a715e1e817bdAndreas HuberOMX_ERRORTYPE OMXMaster::destroyComponentInstance(
150f0fb96c352f30b812a4903a1d783a715e1e817bdAndreas Huber        OMX_COMPONENTTYPE *component) {
151f0fb96c352f30b812a4903a1d783a715e1e817bdAndreas Huber    Mutex::Autolock autoLock(mLock);
152f0fb96c352f30b812a4903a1d783a715e1e817bdAndreas Huber
153f0fb96c352f30b812a4903a1d783a715e1e817bdAndreas Huber    ssize_t index = mPluginByInstance.indexOfKey(component);
154f0fb96c352f30b812a4903a1d783a715e1e817bdAndreas Huber
155f0fb96c352f30b812a4903a1d783a715e1e817bdAndreas Huber    if (index < 0) {
156f0fb96c352f30b812a4903a1d783a715e1e817bdAndreas Huber        return OMX_ErrorBadParameter;
157f0fb96c352f30b812a4903a1d783a715e1e817bdAndreas Huber    }
158f0fb96c352f30b812a4903a1d783a715e1e817bdAndreas Huber
159f0fb96c352f30b812a4903a1d783a715e1e817bdAndreas Huber    OMXPluginBase *plugin = mPluginByInstance.valueAt(index);
160f0fb96c352f30b812a4903a1d783a715e1e817bdAndreas Huber    mPluginByInstance.removeItemsAt(index);
161f0fb96c352f30b812a4903a1d783a715e1e817bdAndreas Huber
162f0fb96c352f30b812a4903a1d783a715e1e817bdAndreas Huber    return plugin->destroyComponentInstance(component);
163e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber}
164e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber
165e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas HuberOMX_ERRORTYPE OMXMaster::enumerateComponents(
166e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber        OMX_STRING name,
167e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber        size_t size,
168e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber        OMX_U32 index) {
169e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber    Mutex::Autolock autoLock(mLock);
170e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber
171e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber    size_t numComponents = mPluginByComponentName.size();
172e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber
173e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber    if (index >= numComponents) {
174e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber        return OMX_ErrorNoMore;
175e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber    }
176e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber
177e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber    const String8 &name8 = mPluginByComponentName.keyAt(index);
178e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber
179e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber    CHECK(size >= 1 + name8.size());
180e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber    strcpy(name, name8.string());
181e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber
182e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber    return OMX_ErrorNone;
183e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber}
184e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber
1858ae1d0bdcef22f2bdd8d283e0e615f3ba6c3f4cdAndreas HuberOMX_ERRORTYPE OMXMaster::getRolesOfComponent(
1868ae1d0bdcef22f2bdd8d283e0e615f3ba6c3f4cdAndreas Huber        const char *name,
1878ae1d0bdcef22f2bdd8d283e0e615f3ba6c3f4cdAndreas Huber        Vector<String8> *roles) {
1888ae1d0bdcef22f2bdd8d283e0e615f3ba6c3f4cdAndreas Huber    Mutex::Autolock autoLock(mLock);
1898ae1d0bdcef22f2bdd8d283e0e615f3ba6c3f4cdAndreas Huber
1908ae1d0bdcef22f2bdd8d283e0e615f3ba6c3f4cdAndreas Huber    roles->clear();
1918ae1d0bdcef22f2bdd8d283e0e615f3ba6c3f4cdAndreas Huber
1928ae1d0bdcef22f2bdd8d283e0e615f3ba6c3f4cdAndreas Huber    ssize_t index = mPluginByComponentName.indexOfKey(String8(name));
1938ae1d0bdcef22f2bdd8d283e0e615f3ba6c3f4cdAndreas Huber
1948ae1d0bdcef22f2bdd8d283e0e615f3ba6c3f4cdAndreas Huber    if (index < 0) {
1958ae1d0bdcef22f2bdd8d283e0e615f3ba6c3f4cdAndreas Huber        return OMX_ErrorInvalidComponentName;
1968ae1d0bdcef22f2bdd8d283e0e615f3ba6c3f4cdAndreas Huber    }
1978ae1d0bdcef22f2bdd8d283e0e615f3ba6c3f4cdAndreas Huber
1988ae1d0bdcef22f2bdd8d283e0e615f3ba6c3f4cdAndreas Huber    OMXPluginBase *plugin = mPluginByComponentName.valueAt(index);
1998ae1d0bdcef22f2bdd8d283e0e615f3ba6c3f4cdAndreas Huber    return plugin->getRolesOfComponent(name, roles);
2008ae1d0bdcef22f2bdd8d283e0e615f3ba6c3f4cdAndreas Huber}
2018ae1d0bdcef22f2bdd8d283e0e615f3ba6c3f4cdAndreas Huber
202e3ec3cec3a2e27033249ff82964d2cbd441d9873Andreas Huber}  // namespace android
203