1 /*
2 * Copyright (C) 2018 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 //#define LOG_NDEBUG 0
18 #define LOG_TAG "Codec2-Component"
19 #include <log/log.h>
20
21 #include <C2PlatformSupport.h>
22 #include <codec2/hidl/1.0/Component.h>
23 #include <codec2/hidl/1.0/ComponentStore.h>
24 #include <codec2/hidl/1.0/types.h>
25
26 #include <hidl/HidlBinderSupport.h>
27
28 #include <C2BqBufferPriv.h>
29 #include <C2PlatformSupport.h>
30
31 namespace hardware {
32 namespace google {
33 namespace media {
34 namespace c2 {
35 namespace V1_0 {
36 namespace utils {
37
38 using namespace ::android;
39
40 namespace /* unnamed */ {
41
42 // Implementation of ConfigurableC2Intf based on C2ComponentInterface
43 struct CompIntf : public ConfigurableC2Intf {
CompIntfhardware::google::media::c2::V1_0::utils::__anonac6205bf0111::CompIntf44 CompIntf(const std::shared_ptr<C2ComponentInterface>& intf) :
45 ConfigurableC2Intf(intf->getName()),
46 mIntf(intf) {
47 }
48
confighardware::google::media::c2::V1_0::utils::__anonac6205bf0111::CompIntf49 virtual c2_status_t config(
50 const std::vector<C2Param*>& params,
51 c2_blocking_t mayBlock,
52 std::vector<std::unique_ptr<C2SettingResult>>* const failures
53 ) override {
54 ALOGV("config");
55 return mIntf->config_vb(params, mayBlock, failures);
56 }
57
queryhardware::google::media::c2::V1_0::utils::__anonac6205bf0111::CompIntf58 virtual c2_status_t query(
59 const std::vector<C2Param::Index>& indices,
60 c2_blocking_t mayBlock,
61 std::vector<std::unique_ptr<C2Param>>* const params
62 ) const override {
63 ALOGV("query");
64 return mIntf->query_vb({}, indices, mayBlock, params);
65 }
66
querySupportedParamshardware::google::media::c2::V1_0::utils::__anonac6205bf0111::CompIntf67 virtual c2_status_t querySupportedParams(
68 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params
69 ) const override {
70 ALOGV("querySupportedParams");
71 return mIntf->querySupportedParams_nb(params);
72 }
73
querySupportedValueshardware::google::media::c2::V1_0::utils::__anonac6205bf0111::CompIntf74 virtual c2_status_t querySupportedValues(
75 std::vector<C2FieldSupportedValuesQuery>& fields,
76 c2_blocking_t mayBlock) const override {
77 ALOGV("querySupportedValues");
78 return mIntf->querySupportedValues_vb(fields, mayBlock);
79 }
80
81 protected:
82 std::shared_ptr<C2ComponentInterface> mIntf;
83 };
84
85 } // unnamed namespace
86
87 // ComponentInterface
ComponentInterface(const std::shared_ptr<C2ComponentInterface> & intf,const sp<ComponentStore> & store)88 ComponentInterface::ComponentInterface(
89 const std::shared_ptr<C2ComponentInterface>& intf,
90 const sp<ComponentStore>& store) :
91 Configurable(new CachedConfigurable(std::make_unique<CompIntf>(intf))),
92 mInterface(intf) {
93 mInit = init(store.get());
94 }
95
status() const96 c2_status_t ComponentInterface::status() const {
97 return mInit;
98 }
99
100 // ComponentListener wrapper
101 struct Component::Listener : public C2Component::Listener {
102
Listenerhardware::google::media::c2::V1_0::utils::Component::Listener103 Listener(const sp<Component>& component) :
104 mComponent(component),
105 mListener(component->mListener) {
106 }
107
onError_nbhardware::google::media::c2::V1_0::utils::Component::Listener108 virtual void onError_nb(
109 std::weak_ptr<C2Component> /* c2component */,
110 uint32_t errorCode) override {
111 ALOGV("onError");
112 sp<IComponentListener> listener = mListener.promote();
113 if (listener) {
114 Return<void> transStatus = listener->onError(Status::OK, errorCode);
115 if (!transStatus.isOk()) {
116 ALOGE("onError -- transaction failed.");
117 }
118 }
119 }
120
onTripped_nbhardware::google::media::c2::V1_0::utils::Component::Listener121 virtual void onTripped_nb(
122 std::weak_ptr<C2Component> /* c2component */,
123 std::vector<std::shared_ptr<C2SettingResult>> c2settingResult
124 ) override {
125 ALOGV("onTripped");
126 sp<IComponentListener> listener = mListener.promote();
127 if (listener) {
128 hidl_vec<SettingResult> settingResults(c2settingResult.size());
129 size_t ix = 0;
130 for (const std::shared_ptr<C2SettingResult> &c2result :
131 c2settingResult) {
132 if (c2result) {
133 if (objcpy(&settingResults[ix++], *c2result) !=
134 Status::OK) {
135 break;
136 }
137 }
138 }
139 settingResults.resize(ix);
140 Return<void> transStatus = listener->onTripped(settingResults);
141 if (!transStatus.isOk()) {
142 ALOGE("onTripped -- transaction failed.");
143 }
144 }
145 }
146
onWorkDone_nbhardware::google::media::c2::V1_0::utils::Component::Listener147 virtual void onWorkDone_nb(
148 std::weak_ptr<C2Component> /* c2component */,
149 std::list<std::unique_ptr<C2Work>> c2workItems) override {
150 ALOGV("onWorkDone");
151 sp<IComponentListener> listener = mListener.promote();
152 if (listener) {
153 WorkBundle workBundle;
154
155 sp<Component> strongComponent = mComponent.promote();
156 if (objcpy(&workBundle, c2workItems, strongComponent ?
157 &strongComponent->mBufferPoolSender : nullptr)
158 != Status::OK) {
159 ALOGE("onWorkDone() received corrupted work items.");
160 return;
161 }
162 Return<void> transStatus = listener->onWorkDone(workBundle);
163 if (!transStatus.isOk()) {
164 ALOGE("onWorkDone -- transaction failed.");
165 return;
166 }
167 yieldBufferQueueBlocks(c2workItems, true);
168 }
169 }
170
171 protected:
172 wp<Component> mComponent;
173 wp<IComponentListener> mListener;
174 };
175
176 // Component
Component(const std::shared_ptr<C2Component> & component,const sp<IComponentListener> & listener,const sp<ComponentStore> & store,const sp<::android::hardware::media::bufferpool::V1_0::IClientManager> & clientPoolManager)177 Component::Component(
178 const std::shared_ptr<C2Component>& component,
179 const sp<IComponentListener>& listener,
180 const sp<ComponentStore>& store,
181 const sp<::android::hardware::media::bufferpool::V1_0::
182 IClientManager>& clientPoolManager) :
183 Configurable(new CachedConfigurable(
184 std::make_unique<CompIntf>(component->intf()))),
185 mComponent(component),
186 mInterface(component->intf()),
187 mListener(listener),
188 mStore(store),
189 mBufferPoolSender(clientPoolManager) {
190 // Retrieve supported parameters from store
191 // TODO: We could cache this per component/interface type
192 mInit = init(store.get());
193 }
194
status() const195 c2_status_t Component::status() const {
196 return mInit;
197 }
198
199 // Methods from ::android::hardware::media::c2::V1_0::IComponent
queue(const WorkBundle & workBundle)200 Return<Status> Component::queue(const WorkBundle& workBundle) {
201 ALOGV("queue -- converting input");
202 std::list<std::unique_ptr<C2Work>> c2works;
203
204 // TODO: Connect with bufferpool API for buffer transfers
205 if (objcpy(&c2works, workBundle) != C2_OK) {
206 ALOGV("queue -- corrupted");
207 return Status::CORRUPTED;
208 }
209 ALOGV("queue -- calling");
210 return static_cast<Status>(mComponent->queue_nb(&c2works));
211 }
212
flush(flush_cb _hidl_cb)213 Return<void> Component::flush(flush_cb _hidl_cb) {
214 std::list<std::unique_ptr<C2Work>> c2flushedWorks;
215 ALOGV("flush -- calling");
216 c2_status_t c2res = mComponent->flush_sm(
217 C2Component::FLUSH_COMPONENT,
218 &c2flushedWorks);
219 WorkBundle flushedWorkBundle;
220
221 Status res = static_cast<Status>(c2res);
222 if (c2res == C2_OK) {
223 ALOGV("flush -- converting output");
224 res = objcpy(&flushedWorkBundle, c2flushedWorks, &mBufferPoolSender);
225 }
226 _hidl_cb(res, flushedWorkBundle);
227 yieldBufferQueueBlocks(c2flushedWorks, true);
228 return Void();
229 }
230
drain(bool withEos)231 Return<Status> Component::drain(bool withEos) {
232 ALOGV("drain");
233 return static_cast<Status>(mComponent->drain_nb(withEos ?
234 C2Component::DRAIN_COMPONENT_WITH_EOS :
235 C2Component::DRAIN_COMPONENT_NO_EOS));
236 }
237
setOutputSurface(uint64_t blockPoolId,const sp<HGraphicBufferProducer> & surface)238 Return<Status> Component::setOutputSurface(
239 uint64_t blockPoolId,
240 const sp<HGraphicBufferProducer>& surface) {
241 std::shared_ptr<C2BlockPool> pool;
242 GetCodec2BlockPool(blockPoolId, mComponent, &pool);
243 if (pool && pool->getAllocatorId() == C2PlatformAllocatorStore::BUFFERQUEUE) {
244 std::shared_ptr<C2BufferQueueBlockPool> bqPool =
245 std::static_pointer_cast<C2BufferQueueBlockPool>(pool);
246 C2BufferQueueBlockPool::OnRenderCallback cb =
247 [this](uint64_t producer, int32_t slot, int64_t nsecs) {
248 // TODO: batch this
249 hidl_vec<IComponentListener::RenderedFrame> rendered;
250 rendered.resize(1);
251 rendered[0] = { producer, slot, nsecs };
252 mListener->onFramesRendered(rendered);
253 };
254 if (bqPool) {
255 bqPool->setRenderCallback(cb);
256 bqPool->configureProducer(surface);
257 }
258 }
259 return Status::OK;
260 }
261
connectToOmxInputSurface(const sp<HGraphicBufferProducer> & producer,const sp<::android::hardware::media::omx::V1_0::IGraphicBufferSource> & source)262 Return<Status> Component::connectToOmxInputSurface(
263 const sp<HGraphicBufferProducer>& producer,
264 const sp<::android::hardware::media::omx::V1_0::
265 IGraphicBufferSource>& source) {
266 // TODO implement
267 (void)producer;
268 (void)source;
269 return Status::OMITTED;
270 }
271
disconnectFromInputSurface()272 Return<Status> Component::disconnectFromInputSurface() {
273 // TODO implement
274 return Status::OK;
275 }
276
277 namespace /* unnamed */ {
278
279 struct BlockPoolIntf : public ConfigurableC2Intf {
BlockPoolIntfhardware::google::media::c2::V1_0::utils::__anonac6205bf0311::BlockPoolIntf280 BlockPoolIntf(const std::shared_ptr<C2BlockPool>& pool) :
281 ConfigurableC2Intf("C2BlockPool:" + std::to_string(pool->getLocalId())),
282 mPool(pool) {
283 }
284
confighardware::google::media::c2::V1_0::utils::__anonac6205bf0311::BlockPoolIntf285 virtual c2_status_t config(
286 const std::vector<C2Param*>& params,
287 c2_blocking_t mayBlock,
288 std::vector<std::unique_ptr<C2SettingResult>>* const failures
289 ) override {
290 (void)params;
291 (void)mayBlock;
292 (void)failures;
293 return C2_OK;
294 }
295
queryhardware::google::media::c2::V1_0::utils::__anonac6205bf0311::BlockPoolIntf296 virtual c2_status_t query(
297 const std::vector<C2Param::Index>& indices,
298 c2_blocking_t mayBlock,
299 std::vector<std::unique_ptr<C2Param>>* const params
300 ) const override {
301 (void)indices;
302 (void)mayBlock;
303 (void)params;
304 return C2_OK;
305 }
306
querySupportedParamshardware::google::media::c2::V1_0::utils::__anonac6205bf0311::BlockPoolIntf307 virtual c2_status_t querySupportedParams(
308 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params
309 ) const override {
310 (void)params;
311 return C2_OK;
312 }
313
querySupportedValueshardware::google::media::c2::V1_0::utils::__anonac6205bf0311::BlockPoolIntf314 virtual c2_status_t querySupportedValues(
315 std::vector<C2FieldSupportedValuesQuery>& fields,
316 c2_blocking_t mayBlock) const override {
317 (void)fields;
318 (void)mayBlock;
319 return C2_OK;
320 }
321
322 protected:
323 std::shared_ptr<C2BlockPool> mPool;
324 };
325
326 } // unnamed namespace
327
createBlockPool(uint32_t allocatorId,createBlockPool_cb _hidl_cb)328 Return<void> Component::createBlockPool(
329 uint32_t allocatorId,
330 createBlockPool_cb _hidl_cb) {
331 std::shared_ptr<C2BlockPool> blockPool;
332 c2_status_t status = CreateCodec2BlockPool(
333 static_cast<C2PlatformAllocatorStore::id_t>(allocatorId),
334 mComponent,
335 &blockPool);
336 if (status != C2_OK) {
337 blockPool = nullptr;
338 }
339 if (blockPool) {
340 mBlockPoolsMutex.lock();
341 mBlockPools.emplace(blockPool->getLocalId(), blockPool);
342 mBlockPoolsMutex.unlock();
343 } else if (status == C2_OK) {
344 status = C2_CORRUPTED;
345 }
346
347 _hidl_cb(static_cast<Status>(status),
348 blockPool ? blockPool->getLocalId() : 0,
349 new CachedConfigurable(
350 std::make_unique<BlockPoolIntf>(blockPool)));
351 return Void();
352 }
353
destroyBlockPool(uint64_t blockPoolId)354 Return<Status> Component::destroyBlockPool(uint64_t blockPoolId) {
355 std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
356 return mBlockPools.erase(blockPoolId) == 1 ?
357 Status::OK : Status::CORRUPTED;
358 }
359
start()360 Return<Status> Component::start() {
361 ALOGV("start");
362 return static_cast<Status>(mComponent->start());
363 }
364
stop()365 Return<Status> Component::stop() {
366 ALOGV("stop");
367 return static_cast<Status>(mComponent->stop());
368 }
369
reset()370 Return<Status> Component::reset() {
371 ALOGV("reset");
372 Status status = static_cast<Status>(mComponent->reset());
373 {
374 std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
375 mBlockPools.clear();
376 }
377 return status;
378 }
379
release()380 Return<Status> Component::release() {
381 ALOGV("release");
382 Status status = static_cast<Status>(mComponent->release());
383 {
384 std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
385 mBlockPools.clear();
386 }
387 return status;
388 }
389
setLocalId(const Component::LocalId & localId)390 void Component::setLocalId(const Component::LocalId& localId) {
391 mLocalId = localId;
392 }
393
initListener(const sp<Component> & self)394 void Component::initListener(const sp<Component>& self) {
395 std::shared_ptr<C2Component::Listener> c2listener =
396 std::make_shared<Listener>(self);
397 c2_status_t res = mComponent->setListener_vb(c2listener, C2_DONT_BLOCK);
398 if (res != C2_OK) {
399 mInit = res;
400 }
401 }
402
~Component()403 Component::~Component() {
404 mStore->reportComponentDeath(mLocalId);
405 }
406
InterfaceKey(const sp<IComponent> & component)407 Component::InterfaceKey::InterfaceKey(const sp<IComponent>& component) {
408 isRemote = component->isRemote();
409 if (isRemote) {
410 remote = ::android::hardware::toBinder(component);
411 } else {
412 local = component;
413 }
414 }
415
416 } // namespace utils
417 } // namespace V1_0
418 } // namespace c2
419 } // namespace media
420 } // namespace google
421 } // namespace hardware
422