Omx.cpp revision 255735a38b9d5c3755c7b819bdc8fdaf4357d860
18c0d56d55abcc0559f1472979ed31a817e678731Wouter van Oortmerssen/*
29a1f7be6fd318ddd9545926b5925cf0a10a083e4evolutional * Copyright 2016, The Android Open Source Project
39a1f7be6fd318ddd9545926b5925cf0a10a083e4evolutional *
49a1f7be6fd318ddd9545926b5925cf0a10a083e4evolutional * Licensed under the Apache License, Version 2.0 (the "License");
59a1f7be6fd318ddd9545926b5925cf0a10a083e4evolutional * you may not use this file except in compliance with the License.
69a1f7be6fd318ddd9545926b5925cf0a10a083e4evolutional * You may obtain a copy of the License at
79a1f7be6fd318ddd9545926b5925cf0a10a083e4evolutional *
89a1f7be6fd318ddd9545926b5925cf0a10a083e4evolutional *      http://www.apache.org/licenses/LICENSE-2.0
99a1f7be6fd318ddd9545926b5925cf0a10a083e4evolutional *
109a1f7be6fd318ddd9545926b5925cf0a10a083e4evolutional * Unless required by applicable law or agreed to in writing, software
119a1f7be6fd318ddd9545926b5925cf0a10a083e4evolutional * distributed under the License is distributed on an "AS IS" BASIS,
129a1f7be6fd318ddd9545926b5925cf0a10a083e4evolutional * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139a1f7be6fd318ddd9545926b5925cf0a10a083e4evolutional * See the License for the specific language governing permissions and
149a1f7be6fd318ddd9545926b5925cf0a10a083e4evolutional * limitations under the License.
159a1f7be6fd318ddd9545926b5925cf0a10a083e4evolutional */
169a1f7be6fd318ddd9545926b5925cf0a10a083e4evolutional
179a1f7be6fd318ddd9545926b5925cf0a10a083e4evolutional#include <ios>
189a1f7be6fd318ddd9545926b5925cf0a10a083e4evolutional#include <list>
199a1f7be6fd318ddd9545926b5925cf0a10a083e4evolutional
209a1f7be6fd318ddd9545926b5925cf0a10a083e4evolutional#include <android-base/logging.h>
219a1f7be6fd318ddd9545926b5925cf0a10a083e4evolutional#include <gui/IGraphicBufferProducer.h>
2252ca75506abd82b5616bdef4d28e9535262c1d65Wouter van Oortmerssen#include <media/openmax/OMX_Core.h>
239a1f7be6fd318ddd9545926b5925cf0a10a083e4evolutional#include <media/openmax/OMX_AsString.h>
2452ca75506abd82b5616bdef4d28e9535262c1d65Wouter van Oortmerssen
2552ca75506abd82b5616bdef4d28e9535262c1d65Wouter van Oortmerssen#include <media/stagefright/omx/OMXUtils.h>
269a1f7be6fd318ddd9545926b5925cf0a10a083e4evolutional#include <media/stagefright/omx/OMXMaster.h>
2752ca75506abd82b5616bdef4d28e9535262c1d65Wouter van Oortmerssen#include <media/stagefright/omx/GraphicBufferSource.h>
28
29#include <media/stagefright/omx/1.0/WOmxNode.h>
30#include <media/stagefright/omx/1.0/WOmxObserver.h>
31#include <media/stagefright/omx/1.0/WGraphicBufferProducer.h>
32#include <media/stagefright/omx/1.0/WGraphicBufferSource.h>
33#include <media/stagefright/omx/1.0/Conversion.h>
34#include <media/stagefright/omx/1.0/Omx.h>
35
36namespace android {
37namespace hardware {
38namespace media {
39namespace omx {
40namespace V1_0 {
41namespace implementation {
42
43constexpr size_t kMaxNodeInstances = (1 << 16);
44
45Omx::Omx() :
46    mMaster(new OMXMaster()),
47    mParser() {
48}
49
50Omx::~Omx() {
51    delete mMaster;
52}
53
54Return<void> Omx::listNodes(listNodes_cb _hidl_cb) {
55    std::list<::android::IOMX::ComponentInfo> list;
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    sp<OMXNodeInstance> instance;
93    {
94        Mutex::Autolock autoLock(mLock);
95        if (mLiveNodes.size() == kMaxNodeInstances) {
96            _hidl_cb(toStatus(NO_MEMORY), nullptr);
97            return Void();
98        }
99
100        instance = new OMXNodeInstance(
101                this, new LWOmxObserver(observer), name.c_str());
102
103        OMX_COMPONENTTYPE *handle;
104        OMX_ERRORTYPE err = mMaster->makeComponentInstance(
105                name.c_str(), &OMXNodeInstance::kCallbacks,
106                instance.get(), &handle);
107
108        if (err != OMX_ErrorNone) {
109            LOG(ERROR) << "Failed to allocate omx component "
110                    "'" << name.c_str() << "' "
111                    " err=" << asString(err) <<
112                    "(0x" << std::hex << unsigned(err) << ")";
113            _hidl_cb(toStatus(StatusFromOMXError(err)), nullptr);
114            return Void();
115        }
116        instance->setHandle(handle);
117        std::vector<AString> quirkVector;
118        if (mParser.getQuirks(name.c_str(), &quirkVector) == OK) {
119            uint32_t quirks = 0;
120            for (const AString quirk : quirkVector) {
121                if (quirk == "requires-allocate-on-input-ports") {
122                    quirks |= kRequiresAllocateBufferOnInputPorts;
123                }
124                if (quirk == "requires-allocate-on-output-ports") {
125                    quirks |= kRequiresAllocateBufferOnOutputPorts;
126                }
127            }
128            instance->setQuirks(quirks);
129        }
130
131        mLiveNodes.add(observer.get(), instance);
132        mNode2Observer.add(instance.get(), observer.get());
133    }
134    observer->linkToDeath(this, 0);
135
136    _hidl_cb(toStatus(OK), new TWOmxNode(instance));
137    return Void();
138}
139
140Return<void> Omx::createInputSurface(createInputSurface_cb _hidl_cb) {
141    sp<::android::IGraphicBufferProducer> bufferProducer;
142
143    sp<GraphicBufferSource> graphicBufferSource = new GraphicBufferSource();
144    status_t err = graphicBufferSource->initCheck();
145    if (err != OK) {
146        LOG(ERROR) << "Failed to create persistent input surface: "
147                << strerror(-err) << " "
148                "(" << int(err) << ")";
149        _hidl_cb(toStatus(err), nullptr, nullptr);
150        return Void();
151    }
152    bufferProducer = graphicBufferSource->getIGraphicBufferProducer();
153
154    _hidl_cb(toStatus(OK),
155            new TWGraphicBufferProducer(bufferProducer),
156            new TWGraphicBufferSource(graphicBufferSource));
157    return Void();
158}
159
160void Omx::serviceDied(uint64_t /* cookie */, wp<IBase> const& who) {
161    sp<OMXNodeInstance> instance;
162    {
163        Mutex::Autolock autoLock(mLock);
164
165        ssize_t index = mLiveNodes.indexOfKey(who);
166
167        if (index < 0) {
168            LOG(ERROR) << "b/27597103, nonexistent observer on serviceDied";
169            android_errorWriteLog(0x534e4554, "27597103");
170            return;
171        }
172
173        instance = mLiveNodes.editValueAt(index);
174        mLiveNodes.removeItemsAt(index);
175        mNode2Observer.removeItem(instance.get());
176    }
177    instance->onObserverDied();
178}
179
180status_t Omx::freeNode(sp<OMXNodeInstance> const& instance) {
181    if (instance == NULL) {
182        return OK;
183    }
184
185    {
186        Mutex::Autolock autoLock(mLock);
187        ssize_t observerIndex = mNode2Observer.indexOfKey(instance.get());
188        if (observerIndex >= 0) {
189            wp<IBase> observer = mNode2Observer.valueAt(observerIndex);
190            ssize_t nodeIndex = mLiveNodes.indexOfKey(observer);
191            if (nodeIndex >= 0) {
192                mNode2Observer.removeItemsAt(observerIndex);
193                mLiveNodes.removeItemsAt(nodeIndex);
194                sp<IBase> sObserver = observer.promote();
195                if (sObserver != nullptr) {
196                    sObserver->unlinkToDeath(this);
197                }
198            } else {
199                LOG(WARNING) << "Inconsistent observer record";
200            }
201        }
202    }
203
204    OMX_ERRORTYPE err = OMX_ErrorNone;
205    if (instance->handle() != NULL) {
206        err = mMaster->destroyComponentInstance(
207                static_cast<OMX_COMPONENTTYPE*>(instance->handle()));
208    }
209    return StatusFromOMXError(err);
210}
211
212// Methods from ::android::hidl::base::V1_0::IBase follow.
213
214IOmx* HIDL_FETCH_IOmx(const char* /* name */) {
215    return new Omx();
216}
217
218}  // namespace implementation
219}  // namespace V1_0
220}  // namespace omx
221}  // namespace media
222}  // namespace hardware
223}  // namespace android
224