Omx.cpp revision 223b8e36091a48b3963d2ea6fc7e304b71e26553
1/*
2 * Copyright 2016, 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 <ios>
18#include <list>
19
20#include <android-base/logging.h>
21#include <gui/IGraphicBufferProducer.h>
22#include <OMX_Core.h>
23#include <OMX_AsString.h>
24
25#include "../../../OMXUtils.h"
26#include "../../../OMXMaster.h"
27#include "../../../GraphicBufferSource.h"
28
29#include "WOmxNode.h"
30#include "WOmxObserver.h"
31#include "WOmxBufferProducer.h"
32#include "WGraphicBufferSource.h"
33#include "Conversion.h"
34
35#include "Omx.h"
36
37namespace android {
38namespace hardware {
39namespace media {
40namespace omx {
41namespace V1_0 {
42namespace implementation {
43
44constexpr size_t kMaxNodeInstances = (1 << 16);
45
46Omx::Omx() : mMaster(new OMXMaster()) {
47}
48
49Omx::~Omx() {
50    delete mMaster;
51}
52
53Return<void> Omx::listNodes(listNodes_cb _hidl_cb) {
54    std::list<::android::IOMX::ComponentInfo> list;
55    OMX_U32 index = 0;
56    char componentName[256];
57    for (OMX_U32 index = 0;
58            mMaster->enumerateComponents(
59            componentName, sizeof(componentName), index) == OMX_ErrorNone;
60            ++index) {
61        list.push_back(::android::IOMX::ComponentInfo());
62        ::android::IOMX::ComponentInfo& info = list.back();
63        info.mName = componentName;
64        ::android::Vector<::android::String8> roles;
65        OMX_ERRORTYPE err =
66                mMaster->getRolesOfComponent(componentName, &roles);
67        if (err == OMX_ErrorNone) {
68            for (OMX_U32 i = 0; i < roles.size(); ++i) {
69                info.mRoles.push_back(roles[i]);
70            }
71        }
72    }
73
74    hidl_vec<ComponentInfo> tList;
75    tList.resize(list.size());
76    size_t i = 0;
77    for (auto const& info : list) {
78        convertTo(&(tList[i++]), info);
79    }
80    _hidl_cb(toStatus(OK), tList);
81    return Void();
82}
83
84Return<void> Omx::allocateNode(
85        const hidl_string& name,
86        const sp<IOmxObserver>& observer,
87        allocateNode_cb _hidl_cb) {
88
89    using ::android::IOMXNode;
90    using ::android::IOMXObserver;
91
92    Mutex::Autolock autoLock(mLock);
93    if (mLiveNodes.size() == kMaxNodeInstances) {
94        _hidl_cb(toStatus(NO_MEMORY), nullptr);
95        return Void();
96    }
97
98    sp<OMXNodeInstance> instance = new OMXNodeInstance(
99            this, new LWOmxObserver(observer), name);
100
101    OMX_COMPONENTTYPE *handle;
102    OMX_ERRORTYPE err = mMaster->makeComponentInstance(
103            name, &OMXNodeInstance::kCallbacks,
104            instance.get(), &handle);
105
106    if (err != OMX_ErrorNone) {
107        LOG(ERROR) << "Failed to allocate omx component "
108                "'" << name.c_str() << "' "
109                " err=" << asString(err) <<
110                "(0x" << std::hex << unsigned(err) << ")";
111        _hidl_cb(toStatus(StatusFromOMXError(err)), nullptr);
112        return Void();
113    }
114    instance->setHandle(handle);
115
116    mLiveNodes.add(observer.get(), instance);
117    observer->linkToDeath(this, 0);
118    mNode2Observer.add(instance.get(), observer.get());
119
120    _hidl_cb(toStatus(OK), new TWOmxNode(instance));
121    return Void();
122}
123
124Return<void> Omx::createInputSurface(createInputSurface_cb _hidl_cb) {
125    sp<::android::IGraphicBufferProducer> bufferProducer;
126    sp<::android::IGraphicBufferSource> bufferSource;
127
128    sp<GraphicBufferSource> graphicBufferSource = new GraphicBufferSource();
129    status_t err = graphicBufferSource->initCheck();
130    if (err != OK) {
131        LOG(ERROR) << "Failed to create persistent input surface: "
132                << strerror(-err) << " "
133                "(" << int(err) << ")";
134        _hidl_cb(toStatus(err), nullptr, nullptr);
135        return Void();
136    }
137    bufferProducer = graphicBufferSource->getIGraphicBufferProducer();
138    bufferSource = graphicBufferSource;
139
140    _hidl_cb(toStatus(OK),
141            new TWOmxBufferProducer(bufferProducer),
142            new TWGraphicBufferSource(bufferSource));
143    return Void();
144}
145
146void Omx::serviceDied(uint64_t /* cookie */, wp<IBase> const& who) {
147    sp<OMXNodeInstance> instance;
148    {
149        Mutex::Autolock autoLock(mLock);
150
151        ssize_t index = mLiveNodes.indexOfKey(who);
152
153        if (index < 0) {
154            LOG(ERROR) << "b/27597103, nonexistent observer on serviceDied";
155            android_errorWriteLog(0x534e4554, "27597103");
156            return;
157        }
158
159        instance = mLiveNodes.editValueAt(index);
160        mLiveNodes.removeItemsAt(index);
161        mNode2Observer.removeItem(instance.get());
162    }
163    instance->onObserverDied();
164}
165
166status_t Omx::freeNode(sp<OMXNodeInstance> const& instance) {
167    if (instance == NULL) {
168        return OK;
169    }
170
171    wp<IBase> observer;
172    {
173        Mutex::Autolock autoLock(mLock);
174        ssize_t observerIndex = mNode2Observer.indexOfKey(instance.get());
175        if (observerIndex < 0) {
176            return OK;
177        }
178        observer = mNode2Observer.valueAt(observerIndex);
179        ssize_t nodeIndex = mLiveNodes.indexOfKey(observer);
180        if (nodeIndex < 0) {
181            return OK;
182        }
183        mNode2Observer.removeItemsAt(observerIndex);
184        mLiveNodes.removeItemsAt(nodeIndex);
185    }
186
187    {
188        sp<IBase> sObserver = observer.promote();
189        if (sObserver != nullptr) {
190            sObserver->unlinkToDeath(this);
191        }
192    }
193
194    OMX_ERRORTYPE err = OMX_ErrorNone;
195    if (instance->handle() != NULL) {
196        err = mMaster->destroyComponentInstance(
197                static_cast<OMX_COMPONENTTYPE*>(instance->handle()));
198    }
199    return StatusFromOMXError(err);
200}
201
202// Methods from ::android::hidl::base::V1_0::IBase follow.
203
204IOmx* HIDL_FETCH_IOmx(const char* /* name */) {
205    return new Omx();
206}
207
208}  // namespace implementation
209}  // namespace V1_0
210}  // namespace omx
211}  // namespace media
212}  // namespace hardware
213}  // namespace android
214