OMX.cpp revision d59b97223424a3974d2ac31cff998d02eecf2eed
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#include <inttypes.h>
18
19//#define LOG_NDEBUG 0
20#define LOG_TAG "OMX"
21#include <utils/Log.h>
22
23#include <dlfcn.h>
24
25#include "../include/OMX.h"
26
27#include "../include/OMXNodeInstance.h"
28
29#include <media/stagefright/foundation/ADebug.h>
30
31#include "OMXMaster.h"
32#include "OMXUtils.h"
33
34namespace android {
35
36// node ids are created by concatenating the pid with a 16-bit counter
37static size_t kMaxNodeInstances = (1 << 16);
38
39OMX::OMX()
40    : mMaster(new OMXMaster) {
41}
42
43OMX::~OMX() {
44    delete mMaster;
45    mMaster = NULL;
46}
47
48void OMX::binderDied(const wp<IBinder> &the_late_who) {
49    sp<OMXNodeInstance> instance;
50
51    {
52        Mutex::Autolock autoLock(mLock);
53
54        ssize_t index = mLiveNodes.indexOfKey(the_late_who);
55
56        if (index < 0) {
57            ALOGE("b/27597103, nonexistent observer on binderDied");
58            android_errorWriteLog(0x534e4554, "27597103");
59            return;
60        }
61
62        instance = mLiveNodes.editValueAt(index);
63        mLiveNodes.removeItemsAt(index);
64    }
65
66    instance->onObserverDied();
67}
68
69status_t OMX::listNodes(List<ComponentInfo> *list) {
70    list->clear();
71
72    OMX_U32 index = 0;
73    char componentName[256];
74    while (mMaster->enumerateComponents(
75                componentName, sizeof(componentName), index) == OMX_ErrorNone) {
76        list->push_back(ComponentInfo());
77        ComponentInfo &info = *--list->end();
78
79        info.mName = componentName;
80
81        Vector<String8> roles;
82        OMX_ERRORTYPE err =
83            mMaster->getRolesOfComponent(componentName, &roles);
84
85        if (err == OMX_ErrorNone) {
86            for (OMX_U32 i = 0; i < roles.size(); ++i) {
87                info.mRoles.push_back(roles[i]);
88            }
89        }
90
91        ++index;
92    }
93
94    return OK;
95}
96
97status_t OMX::allocateNode(
98        const char *name, const sp<IOMXObserver> &observer,
99        sp<IBinder> *nodeBinder, sp<IOMXNode> *omxNode) {
100    Mutex::Autolock autoLock(mLock);
101
102    omxNode->clear();
103    if (nodeBinder != NULL) {
104        *nodeBinder = NULL;
105    }
106
107    if (mLiveNodes.size() == kMaxNodeInstances) {
108        return NO_MEMORY;
109    }
110
111    sp<OMXNodeInstance> instance = new OMXNodeInstance(this, observer, name);
112
113    OMX_COMPONENTTYPE *handle;
114    OMX_ERRORTYPE err = mMaster->makeComponentInstance(
115            name, &OMXNodeInstance::kCallbacks,
116            instance.get(), &handle);
117
118    if (err != OMX_ErrorNone) {
119        ALOGE("FAILED to allocate omx component '%s' err=%s(%#x)", name, asString(err), err);
120
121        return StatusFromOMXError(err);
122    }
123    instance->setHandle(handle);
124
125    mLiveNodes.add(IInterface::asBinder(observer), instance);
126    IInterface::asBinder(observer)->linkToDeath(this);
127
128    *omxNode = instance;
129
130    return OK;
131}
132
133status_t OMX::freeNode(const sp<OMXNodeInstance> &instance) {
134    if (instance == NULL) {
135        return OK;
136    }
137
138    {
139        Mutex::Autolock autoLock(mLock);
140        ssize_t index = mLiveNodes.indexOfKey(IInterface::asBinder(instance->observer()));
141        if (index < 0) {
142            // This could conceivably happen if the observer dies at roughly the
143            // same time that a client attempts to free the node explicitly.
144            return OK;
145        }
146        mLiveNodes.removeItemsAt(index);
147    }
148
149    IInterface::asBinder(instance->observer())->unlinkToDeath(this);
150
151    OMX_ERRORTYPE err = OMX_ErrorNone;
152    if (instance->handle() != NULL) {
153        err = mMaster->destroyComponentInstance(
154                static_cast<OMX_COMPONENTTYPE *>(instance->handle()));
155    }
156
157    return StatusFromOMXError(err);
158}
159
160status_t OMX::createPersistentInputSurface(
161        sp<IGraphicBufferProducer> *bufferProducer,
162        sp<IGraphicBufferConsumer> *bufferConsumer) {
163    return OMXNodeInstance::createPersistentInputSurface(
164            bufferProducer, bufferConsumer);
165}
166
167}  // namespace android
168