xref: /aosp_15_r20/frameworks/av/media/libstagefright/omx/1.0/Omx.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
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 <media/openmax/OMX_Core.h>
22 #include <media/openmax/OMX_AsString.h>
23 
24 #include <media/stagefright/omx/OMXUtils.h>
25 #include <media/stagefright/omx/OMXStore.h>
26 #include <media/stagefright/omx/OmxGraphicBufferSource.h>
27 
28 #include <media/stagefright/omx/1.0/WOmxNode.h>
29 #include <media/stagefright/omx/1.0/WOmxObserver.h>
30 #include <media/stagefright/omx/1.0/WGraphicBufferSource.h>
31 #include <media/stagefright/omx/1.0/Conversion.h>
32 #include <media/stagefright/omx/1.0/Omx.h>
33 
34 namespace android {
35 namespace hardware {
36 namespace media {
37 namespace omx {
38 namespace V1_0 {
39 namespace implementation {
40 
41 constexpr size_t kMaxNodeInstances = (1 << 16);
42 
Omx()43 Omx::Omx() :
44     mStore(new OMXStore()),
45     mParser() {
46     (void)mParser.parseXmlFilesInSearchDirs();
47     (void)mParser.parseXmlPath(mParser.defaultProfilingResultsXmlPath);
48 }
49 
~Omx()50 Omx::~Omx() {
51     delete mStore;
52 }
53 
listNodes(listNodes_cb _hidl_cb)54 Return<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             mStore->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                 mStore->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 
allocateNode(const hidl_string & name,const sp<IOmxObserver> & observer,allocateNode_cb _hidl_cb)84 Return<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 = mStore->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 
118         // Find quirks from mParser
119         const auto& codec = mParser.getCodecMap().find(name.c_str());
120         if (codec == mParser.getCodecMap().cend()) {
121             LOG(WARNING) << "Failed to obtain quirks for omx component "
122                     "'" << name.c_str() << "' "
123                     "from XML files";
124         } else {
125             uint32_t quirks = 0;
126             for (const auto& quirk : codec->second.quirkSet) {
127                 if (quirk == "quirk::requires-allocate-on-input-ports") {
128                     quirks |= OMXNodeInstance::
129                             kRequiresAllocateBufferOnInputPorts;
130                 }
131                 if (quirk == "quirk::requires-allocate-on-output-ports") {
132                     quirks |= OMXNodeInstance::
133                             kRequiresAllocateBufferOnOutputPorts;
134                 }
135             }
136             instance->setQuirks(quirks);
137         }
138 
139         mLiveNodes.add(observer.get(), instance);
140         mNode2Observer.add(instance.get(), observer.get());
141     }
142     observer->linkToDeath(this, 0);
143 
144     _hidl_cb(toStatus(OK), new TWOmxNode(instance));
145     return Void();
146 }
147 
createInputSurface(createInputSurface_cb _hidl_cb)148 Return<void> Omx::createInputSurface(createInputSurface_cb _hidl_cb) {
149     sp<OmxGraphicBufferSource> graphicBufferSource = new OmxGraphicBufferSource();
150     status_t err = graphicBufferSource->initCheck();
151     if (err != OK) {
152         LOG(ERROR) << "Failed to create persistent input surface: "
153                 << strerror(-err) << " "
154                 "(" << int(err) << ")";
155         _hidl_cb(toStatus(err), nullptr, nullptr);
156         return Void();
157     }
158 
159     _hidl_cb(toStatus(OK),
160             graphicBufferSource->getHGraphicBufferProducer_V1_0(),
161             new TWGraphicBufferSource(graphicBufferSource));
162     return Void();
163 }
164 
serviceDied(uint64_t,wp<IBase> const & who)165 void Omx::serviceDied(uint64_t /* cookie */, wp<IBase> const& who) {
166     sp<OMXNodeInstance> instance;
167     {
168         Mutex::Autolock autoLock(mLock);
169 
170         ssize_t index = mLiveNodes.indexOfKey(who);
171 
172         if (index < 0) {
173             LOG(ERROR) << "b/27597103, nonexistent observer on serviceDied";
174             android_errorWriteLog(0x534e4554, "27597103");
175             return;
176         }
177 
178         instance = mLiveNodes.editValueAt(index);
179         mLiveNodes.removeItemsAt(index);
180         mNode2Observer.removeItem(instance.get());
181     }
182     instance->onObserverDied();
183 }
184 
freeNode(sp<OMXNodeInstance> const & instance)185 status_t Omx::freeNode(sp<OMXNodeInstance> const& instance) {
186     if (instance == NULL) {
187         return OK;
188     }
189 
190     {
191         Mutex::Autolock autoLock(mLock);
192         ssize_t observerIndex = mNode2Observer.indexOfKey(instance.get());
193         if (observerIndex >= 0) {
194             wp<IBase> observer = mNode2Observer.valueAt(observerIndex);
195             ssize_t nodeIndex = mLiveNodes.indexOfKey(observer);
196             if (nodeIndex >= 0) {
197                 mNode2Observer.removeItemsAt(observerIndex);
198                 mLiveNodes.removeItemsAt(nodeIndex);
199                 sp<IBase> sObserver = observer.promote();
200                 if (sObserver != nullptr) {
201                     sObserver->unlinkToDeath(this);
202                 }
203             } else {
204                 LOG(WARNING) << "Inconsistent observer record";
205             }
206         }
207     }
208 
209     OMX_ERRORTYPE err = OMX_ErrorNone;
210     if (instance->handle() != NULL) {
211         err = mStore->destroyComponentInstance(
212                 static_cast<OMX_COMPONENTTYPE*>(instance->handle()));
213     }
214     return StatusFromOMXError(err);
215 }
216 
217 // Methods from ::android::hidl::base::V1_0::IBase follow.
218 
HIDL_FETCH_IOmx(const char *)219 IOmx* HIDL_FETCH_IOmx(const char* /* name */) {
220     return new Omx();
221 }
222 
223 }  // namespace implementation
224 }  // namespace V1_0
225 }  // namespace omx
226 }  // namespace media
227 }  // namespace hardware
228 }  // namespace android
229