1b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber/*
2b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber * Copyright (C) 2009 The Android Open Source Project
3b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber *
4b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber * you may not use this file except in compliance with the License.
6b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber * You may obtain a copy of the License at
7b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber *
8b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
9b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber *
10b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber * Unless required by applicable law or agreed to in writing, software
11b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber * See the License for the specific language governing permissions and
14b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber * limitations under the License.
15b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber */
16b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber
17fb41d59595a09f60fd2fa3618e9d5a4937c4555bAndreas Huber//#define LOG_NDEBUG 0
18fb41d59595a09f60fd2fa3618e9d5a4937c4555bAndreas Huber#define LOG_TAG "OMXMaster"
19fb41d59595a09f60fd2fa3618e9d5a4937c4555bAndreas Huber#include <utils/Log.h>
20fb41d59595a09f60fd2fa3618e9d5a4937c4555bAndreas Huber
21b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber#include "OMXMaster.h"
22b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber
234b3913a3e43d3180b21d77cc2f717b446350354fAndreas Huber#include "SoftOMXPlugin.h"
244b3913a3e43d3180b21d77cc2f717b446350354fAndreas Huber
25b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber#include <dlfcn.h>
26b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber
27b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber#include <media/stagefright/MediaDebug.h>
28b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber
29b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Hubernamespace android {
30b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber
31b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas HuberOMXMaster::OMXMaster()
32b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber    : mVendorLibHandle(NULL) {
33b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber    addVendorPlugin();
344b3913a3e43d3180b21d77cc2f717b446350354fAndreas Huber    addPlugin(new SoftOMXPlugin);
35b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber}
36b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber
37b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas HuberOMXMaster::~OMXMaster() {
38b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber    clearPlugins();
39b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber
40b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber    if (mVendorLibHandle != NULL) {
41b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber        dlclose(mVendorLibHandle);
42b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber        mVendorLibHandle = NULL;
43b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber    }
44b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber}
45b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber
46b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Hubervoid OMXMaster::addVendorPlugin() {
474b3913a3e43d3180b21d77cc2f717b446350354fAndreas Huber    addPlugin("libstagefrighthw.so");
484b3913a3e43d3180b21d77cc2f717b446350354fAndreas Huber}
494b3913a3e43d3180b21d77cc2f717b446350354fAndreas Huber
504b3913a3e43d3180b21d77cc2f717b446350354fAndreas Hubervoid OMXMaster::addPlugin(const char *libname) {
514b3913a3e43d3180b21d77cc2f717b446350354fAndreas Huber    mVendorLibHandle = dlopen(libname, RTLD_NOW);
52b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber
53b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber    if (mVendorLibHandle == NULL) {
54b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber        return;
55b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber    }
56b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber
57b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber    typedef OMXPluginBase *(*CreateOMXPluginFunc)();
58b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber    CreateOMXPluginFunc createOMXPlugin =
59b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber        (CreateOMXPluginFunc)dlsym(
60bbe9cb4f5f87e36b886ea3ba72dc514a081f3fe3Iliyan Malchev                mVendorLibHandle, "createOMXPlugin");
61bbe9cb4f5f87e36b886ea3ba72dc514a081f3fe3Iliyan Malchev    if (!createOMXPlugin)
62bbe9cb4f5f87e36b886ea3ba72dc514a081f3fe3Iliyan Malchev        createOMXPlugin = (CreateOMXPluginFunc)dlsym(
63b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber                mVendorLibHandle, "_ZN7android15createOMXPluginEv");
64b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber
65fef6435a0692f3c9b6055903dfb7699e90e19d46Andreas Huber    if (createOMXPlugin) {
66fef6435a0692f3c9b6055903dfb7699e90e19d46Andreas Huber        addPlugin((*createOMXPlugin)());
67fef6435a0692f3c9b6055903dfb7699e90e19d46Andreas Huber    }
68b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber}
69b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber
70b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Hubervoid OMXMaster::addPlugin(OMXPluginBase *plugin) {
71b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber    Mutex::Autolock autoLock(mLock);
72b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber
73b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber    mPlugins.push_back(plugin);
74b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber
75b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber    OMX_U32 index = 0;
76b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber
77b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber    char name[128];
78b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber    OMX_ERRORTYPE err;
79b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber    while ((err = plugin->enumerateComponents(
80b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber                    name, sizeof(name), index++)) == OMX_ErrorNone) {
81b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber        String8 name8(name);
82b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber
83b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber        if (mPluginByComponentName.indexOfKey(name8) >= 0) {
84b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber            LOGE("A component of name '%s' already exists, ignoring this one.",
85b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber                 name8.string());
86b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber
87b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber            continue;
88b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber        }
89b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber
90b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber        mPluginByComponentName.add(name8, plugin);
91b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber    }
92274626469b716560d7539d0d830c41b83f3665a1Andreas Huber
93274626469b716560d7539d0d830c41b83f3665a1Andreas Huber    if (err != OMX_ErrorNoMore) {
94274626469b716560d7539d0d830c41b83f3665a1Andreas Huber        LOGE("OMX plugin failed w/ error 0x%08x after registering %d "
95274626469b716560d7539d0d830c41b83f3665a1Andreas Huber             "components", err, mPluginByComponentName.size());
96274626469b716560d7539d0d830c41b83f3665a1Andreas Huber    }
97b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber}
98b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber
99b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Hubervoid OMXMaster::clearPlugins() {
100b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber    Mutex::Autolock autoLock(mLock);
101b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber
102bbe9cb4f5f87e36b886ea3ba72dc514a081f3fe3Iliyan Malchev    typedef void (*DestroyOMXPluginFunc)(OMXPluginBase*);
103bbe9cb4f5f87e36b886ea3ba72dc514a081f3fe3Iliyan Malchev    DestroyOMXPluginFunc destroyOMXPlugin =
104bbe9cb4f5f87e36b886ea3ba72dc514a081f3fe3Iliyan Malchev        (DestroyOMXPluginFunc)dlsym(
105bbe9cb4f5f87e36b886ea3ba72dc514a081f3fe3Iliyan Malchev                mVendorLibHandle, "destroyOMXPlugin");
106bbe9cb4f5f87e36b886ea3ba72dc514a081f3fe3Iliyan Malchev
107b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber    mPluginByComponentName.clear();
108b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber
109b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber    for (List<OMXPluginBase *>::iterator it = mPlugins.begin();
110bbe9cb4f5f87e36b886ea3ba72dc514a081f3fe3Iliyan Malchev            it != mPlugins.end(); ++it) {
111bbe9cb4f5f87e36b886ea3ba72dc514a081f3fe3Iliyan Malchev        if (destroyOMXPlugin)
112bbe9cb4f5f87e36b886ea3ba72dc514a081f3fe3Iliyan Malchev            destroyOMXPlugin(*it);
113bbe9cb4f5f87e36b886ea3ba72dc514a081f3fe3Iliyan Malchev        else
114bbe9cb4f5f87e36b886ea3ba72dc514a081f3fe3Iliyan Malchev            delete *it;
115b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber        *it = NULL;
116b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber    }
117b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber
118b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber    mPlugins.clear();
119b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber}
120b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber
121b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas HuberOMX_ERRORTYPE OMXMaster::makeComponentInstance(
122b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber        const char *name,
123b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber        const OMX_CALLBACKTYPE *callbacks,
124b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber        OMX_PTR appData,
125b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber        OMX_COMPONENTTYPE **component) {
126b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber    Mutex::Autolock autoLock(mLock);
127b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber
128b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber    *component = NULL;
129b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber
130b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber    ssize_t index = mPluginByComponentName.indexOfKey(String8(name));
131b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber
132b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber    if (index < 0) {
133b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber        return OMX_ErrorInvalidComponentName;
134b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber    }
135b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber
136b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber    OMXPluginBase *plugin = mPluginByComponentName.valueAt(index);
137fef6435a0692f3c9b6055903dfb7699e90e19d46Andreas Huber    OMX_ERRORTYPE err =
138fef6435a0692f3c9b6055903dfb7699e90e19d46Andreas Huber        plugin->makeComponentInstance(name, callbacks, appData, component);
139fef6435a0692f3c9b6055903dfb7699e90e19d46Andreas Huber
140fef6435a0692f3c9b6055903dfb7699e90e19d46Andreas Huber    if (err != OMX_ErrorNone) {
141fef6435a0692f3c9b6055903dfb7699e90e19d46Andreas Huber        return err;
142fef6435a0692f3c9b6055903dfb7699e90e19d46Andreas Huber    }
143fef6435a0692f3c9b6055903dfb7699e90e19d46Andreas Huber
144fef6435a0692f3c9b6055903dfb7699e90e19d46Andreas Huber    mPluginByInstance.add(*component, plugin);
145fef6435a0692f3c9b6055903dfb7699e90e19d46Andreas Huber
146fef6435a0692f3c9b6055903dfb7699e90e19d46Andreas Huber    return err;
147fef6435a0692f3c9b6055903dfb7699e90e19d46Andreas Huber}
148fef6435a0692f3c9b6055903dfb7699e90e19d46Andreas Huber
149fef6435a0692f3c9b6055903dfb7699e90e19d46Andreas HuberOMX_ERRORTYPE OMXMaster::destroyComponentInstance(
150fef6435a0692f3c9b6055903dfb7699e90e19d46Andreas Huber        OMX_COMPONENTTYPE *component) {
151fef6435a0692f3c9b6055903dfb7699e90e19d46Andreas Huber    Mutex::Autolock autoLock(mLock);
152fef6435a0692f3c9b6055903dfb7699e90e19d46Andreas Huber
153fef6435a0692f3c9b6055903dfb7699e90e19d46Andreas Huber    ssize_t index = mPluginByInstance.indexOfKey(component);
154fef6435a0692f3c9b6055903dfb7699e90e19d46Andreas Huber
155fef6435a0692f3c9b6055903dfb7699e90e19d46Andreas Huber    if (index < 0) {
156fef6435a0692f3c9b6055903dfb7699e90e19d46Andreas Huber        return OMX_ErrorBadParameter;
157fef6435a0692f3c9b6055903dfb7699e90e19d46Andreas Huber    }
158fef6435a0692f3c9b6055903dfb7699e90e19d46Andreas Huber
159fef6435a0692f3c9b6055903dfb7699e90e19d46Andreas Huber    OMXPluginBase *plugin = mPluginByInstance.valueAt(index);
160fef6435a0692f3c9b6055903dfb7699e90e19d46Andreas Huber    mPluginByInstance.removeItemsAt(index);
161fef6435a0692f3c9b6055903dfb7699e90e19d46Andreas Huber
162fef6435a0692f3c9b6055903dfb7699e90e19d46Andreas Huber    return plugin->destroyComponentInstance(component);
163b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber}
164b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber
165b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas HuberOMX_ERRORTYPE OMXMaster::enumerateComponents(
166b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber        OMX_STRING name,
167b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber        size_t size,
168b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber        OMX_U32 index) {
169b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber    Mutex::Autolock autoLock(mLock);
170b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber
171b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber    size_t numComponents = mPluginByComponentName.size();
172b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber
173b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber    if (index >= numComponents) {
174b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber        return OMX_ErrorNoMore;
175b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber    }
176b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber
177b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber    const String8 &name8 = mPluginByComponentName.keyAt(index);
178b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber
179b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber    CHECK(size >= 1 + name8.size());
180b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber    strcpy(name, name8.string());
181b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber
182b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber    return OMX_ErrorNone;
183b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber}
184b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber
185c7e91eee2e79e3e4c8f84fd6b8a753215955d4e8Andreas HuberOMX_ERRORTYPE OMXMaster::getRolesOfComponent(
186c7e91eee2e79e3e4c8f84fd6b8a753215955d4e8Andreas Huber        const char *name,
187c7e91eee2e79e3e4c8f84fd6b8a753215955d4e8Andreas Huber        Vector<String8> *roles) {
188c7e91eee2e79e3e4c8f84fd6b8a753215955d4e8Andreas Huber    Mutex::Autolock autoLock(mLock);
189c7e91eee2e79e3e4c8f84fd6b8a753215955d4e8Andreas Huber
190c7e91eee2e79e3e4c8f84fd6b8a753215955d4e8Andreas Huber    roles->clear();
191c7e91eee2e79e3e4c8f84fd6b8a753215955d4e8Andreas Huber
192c7e91eee2e79e3e4c8f84fd6b8a753215955d4e8Andreas Huber    ssize_t index = mPluginByComponentName.indexOfKey(String8(name));
193c7e91eee2e79e3e4c8f84fd6b8a753215955d4e8Andreas Huber
194c7e91eee2e79e3e4c8f84fd6b8a753215955d4e8Andreas Huber    if (index < 0) {
195c7e91eee2e79e3e4c8f84fd6b8a753215955d4e8Andreas Huber        return OMX_ErrorInvalidComponentName;
196c7e91eee2e79e3e4c8f84fd6b8a753215955d4e8Andreas Huber    }
197c7e91eee2e79e3e4c8f84fd6b8a753215955d4e8Andreas Huber
198c7e91eee2e79e3e4c8f84fd6b8a753215955d4e8Andreas Huber    OMXPluginBase *plugin = mPluginByComponentName.valueAt(index);
199c7e91eee2e79e3e4c8f84fd6b8a753215955d4e8Andreas Huber    return plugin->getRolesOfComponent(name, roles);
200c7e91eee2e79e3e4c8f84fd6b8a753215955d4e8Andreas Huber}
201c7e91eee2e79e3e4c8f84fd6b8a753215955d4e8Andreas Huber
202b0caf946b7ae9be519c0cede935ea2ecb44f9bd0Andreas Huber}  // namespace android
203