• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2019 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@1.1"
19 #include <android-base/logging.h>
20 
21 #include <codec2/common/BqPoolInvalidateHelper.h>
22 #include <codec2/hidl/1.1/Component.h>
23 #include <codec2/hidl/1.1/ComponentStore.h>
24 #include <codec2/hidl/1.1/InputBufferManager.h>
25 
26 #ifndef __ANDROID_APEX__
27 #include <FilterWrapper.h>
28 #endif
29 
30 #include <hidl/HidlBinderSupport.h>
31 #include <utils/Timers.h>
32 
33 #include <codec2/common/MultiAccessUnitHelper.h>
34 
35 #include <C2BqBufferPriv.h>
36 #include <C2BqPoolInvalidator.h>
37 #include <C2Debug.h>
38 #include <C2PlatformSupport.h>
39 
40 #include <chrono>
41 #include <thread>
42 
43 namespace android {
44 namespace hardware {
45 namespace media {
46 namespace c2 {
47 namespace V1_1 {
48 namespace utils {
49 
50 using namespace ::android;
51 using ::android::MultiAccessUnitInterface;
52 using ::android::MultiAccessUnitHelper;
53 
54 // ComponentListener wrapper
55 struct Component::Listener : public C2Component::Listener {
56 
Listenerandroid::hardware::media::c2::V1_1::utils::Component::Listener57     Listener(const sp<Component>& component) :
58         mComponent(component),
59         mListener(component->mListener) {
60     }
61 
onError_nbandroid::hardware::media::c2::V1_1::utils::Component::Listener62     virtual void onError_nb(
63             std::weak_ptr<C2Component> /* c2component */,
64             uint32_t errorCode) override {
65         sp<IComponentListener> listener = mListener.promote();
66         if (listener) {
67             Return<void> transStatus = listener->onError(Status::OK, errorCode);
68             if (!transStatus.isOk()) {
69                 LOG(ERROR) << "Component::Listener::onError_nb -- "
70                            << "transaction failed.";
71             }
72         }
73     }
74 
onTripped_nbandroid::hardware::media::c2::V1_1::utils::Component::Listener75     virtual void onTripped_nb(
76             std::weak_ptr<C2Component> /* c2component */,
77             std::vector<std::shared_ptr<C2SettingResult>> c2settingResult
78             ) override {
79         sp<IComponentListener> listener = mListener.promote();
80         if (listener) {
81             hidl_vec<SettingResult> settingResults(c2settingResult.size());
82             size_t ix = 0;
83             for (const std::shared_ptr<C2SettingResult> &c2result :
84                     c2settingResult) {
85                 if (c2result) {
86                     if (!objcpy(&settingResults[ix++], *c2result)) {
87                         break;
88                     }
89                 }
90             }
91             settingResults.resize(ix);
92             Return<void> transStatus = listener->onTripped(settingResults);
93             if (!transStatus.isOk()) {
94                 LOG(ERROR) << "Component::Listener::onTripped_nb -- "
95                            << "transaction failed.";
96             }
97         }
98     }
99 
onWorkDone_nbandroid::hardware::media::c2::V1_1::utils::Component::Listener100     virtual void onWorkDone_nb(
101             std::weak_ptr<C2Component> /* c2component */,
102             std::list<std::unique_ptr<C2Work>> c2workItems) override {
103         for (const std::unique_ptr<C2Work>& work : c2workItems) {
104             if (work) {
105                 if (work->worklets.empty()
106                         || !work->worklets.back()
107                         || (work->worklets.back()->output.flags &
108                             C2FrameData::FLAG_INCOMPLETE) == 0) {
109                     InputBufferManager::
110                             unregisterFrameData(mListener, work->input);
111                 }
112             }
113         }
114 
115         sp<IComponentListener> listener = mListener.promote();
116         if (listener) {
117             WorkBundle workBundle;
118 
119             sp<Component> strongComponent = mComponent.promote();
120             beginTransferBufferQueueBlocks(c2workItems, true);
121             if (!objcpy(&workBundle, c2workItems, strongComponent ?
122                     &strongComponent->mBufferPoolSender : nullptr)) {
123                 LOG(ERROR) << "Component::Listener::onWorkDone_nb -- "
124                            << "received corrupted work items.";
125                 endTransferBufferQueueBlocks(c2workItems, false, true);
126                 return;
127             }
128             Return<void> transStatus = listener->onWorkDone(workBundle);
129             if (!transStatus.isOk()) {
130                 LOG(ERROR) << "Component::Listener::onWorkDone_nb -- "
131                            << "transaction failed.";
132                 endTransferBufferQueueBlocks(c2workItems, false, true);
133                 return;
134             }
135             endTransferBufferQueueBlocks(c2workItems, true, true);
136         }
137     }
138 
139 protected:
140     wp<Component> mComponent;
141     wp<IComponentListener> mListener;
142 };
143 
144 // Component listener for handle multiple access-units
145 struct MultiAccessUnitListener : public Component::Listener {
MultiAccessUnitListenerandroid::hardware::media::c2::V1_1::utils::MultiAccessUnitListener146     MultiAccessUnitListener(const sp<Component> &component,
147             const std::shared_ptr<MultiAccessUnitHelper> &helper):
148         Listener(component), mHelper(helper) {
149     }
150 
onError_nbandroid::hardware::media::c2::V1_1::utils::MultiAccessUnitListener151     virtual void onError_nb(
152             std::weak_ptr<C2Component> c2component,
153             uint32_t errorCode) override {
154         if (mHelper) {
155             std::list<std::unique_ptr<C2Work>> worklist;
156             mHelper->error(&worklist);
157             if (!worklist.empty()) {
158                 Listener::onWorkDone_nb(c2component, std::move(worklist));
159             }
160         }
161         Listener::onError_nb(c2component, errorCode);
162     }
163 
onTripped_nbandroid::hardware::media::c2::V1_1::utils::MultiAccessUnitListener164     virtual void onTripped_nb(
165             std::weak_ptr<C2Component> c2component,
166             std::vector<std::shared_ptr<C2SettingResult>> c2settingResult
167             ) override {
168         Listener::onTripped_nb(c2component,
169                 c2settingResult);
170     }
171 
onWorkDone_nbandroid::hardware::media::c2::V1_1::utils::MultiAccessUnitListener172     virtual void onWorkDone_nb(
173             std::weak_ptr<C2Component> c2component,
174             std::list<std::unique_ptr<C2Work>> c2workItems) override {
175         if (mHelper) {
176             std::list<std::unique_ptr<C2Work>> processedWork;
177             mHelper->gather(c2workItems, &processedWork);
178             if (!processedWork.empty()) {
179                 Listener::onWorkDone_nb(c2component, std::move(processedWork));
180             }
181         } else {
182             Listener::onWorkDone_nb(c2component, std::move(c2workItems));
183         }
184     }
185 
186     protected:
187         std::shared_ptr<MultiAccessUnitHelper> mHelper;
188 };
189 
190 // Component::Sink
191 struct Component::Sink : public IInputSink {
192     std::shared_ptr<Component> mComponent;
193     sp<IConfigurable> mConfigurable;
194 
queueandroid::hardware::media::c2::V1_1::utils::Component::Sink195     virtual Return<Status> queue(const WorkBundle& workBundle) override {
196         return mComponent->queue(workBundle);
197     }
198 
getConfigurableandroid::hardware::media::c2::V1_1::utils::Component::Sink199     virtual Return<sp<IConfigurable>> getConfigurable() override {
200         return mConfigurable;
201     }
202 
203     Sink(const std::shared_ptr<Component>& component);
204     virtual ~Sink() override;
205 
206     // Process-wide map: Component::Sink -> C2Component.
207     static std::mutex sSink2ComponentMutex;
208     static std::map<IInputSink*, std::weak_ptr<C2Component>> sSink2Component;
209 
210     static std::shared_ptr<C2Component> findLocalComponent(
211             const sp<IInputSink>& sink);
212 };
213 
214 std::mutex
215         Component::Sink::sSink2ComponentMutex{};
216 std::map<IInputSink*, std::weak_ptr<C2Component>>
217         Component::Sink::sSink2Component{};
218 
Sink(const std::shared_ptr<Component> & component)219 Component::Sink::Sink(const std::shared_ptr<Component>& component)
220         : mComponent{component},
__anon896242100102() 221           mConfigurable{[&component]() -> sp<IConfigurable> {
222               Return<sp<IComponentInterface>> ret1 = component->getInterface();
223               if (!ret1.isOk()) {
224                   LOG(ERROR) << "Sink::Sink -- component's transaction failed.";
225                   return nullptr;
226               }
227               Return<sp<IConfigurable>> ret2 =
228                       static_cast<sp<IComponentInterface>>(ret1)->
229                       getConfigurable();
230               if (!ret2.isOk()) {
231                   LOG(ERROR) << "Sink::Sink -- interface's transaction failed.";
232                   return nullptr;
233               }
234               return static_cast<sp<IConfigurable>>(ret2);
235           }()} {
236     std::lock_guard<std::mutex> lock(sSink2ComponentMutex);
237     sSink2Component.emplace(this, component->mComponent);
238 }
239 
~Sink()240 Component::Sink::~Sink() {
241     std::lock_guard<std::mutex> lock(sSink2ComponentMutex);
242     sSink2Component.erase(this);
243 }
244 
findLocalComponent(const sp<IInputSink> & sink)245 std::shared_ptr<C2Component> Component::Sink::findLocalComponent(
246         const sp<IInputSink>& sink) {
247     std::lock_guard<std::mutex> lock(sSink2ComponentMutex);
248     auto i = sSink2Component.find(sink.get());
249     if (i == sSink2Component.end()) {
250         return nullptr;
251     }
252     return i->second.lock();
253 }
254 
255 // Component
Component(const std::shared_ptr<C2Component> & component,const sp<IComponentListener> & listener,const sp<ComponentStore> & store,const sp<::android::hardware::media::bufferpool::V2_0::IClientManager> & clientPoolManager)256 Component::Component(
257         const std::shared_ptr<C2Component>& component,
258         const sp<IComponentListener>& listener,
259         const sp<ComponentStore>& store,
260         const sp<::android::hardware::media::bufferpool::V2_0::
261         IClientManager>& clientPoolManager)
262       : mComponent{component},
263         mListener{listener},
264         mStore{store},
265         mBufferPoolSender{clientPoolManager} {
266     // Retrieve supported parameters from store
267     // TODO: We could cache this per component/interface type
268     mMultiAccessUnitIntf = store->tryCreateMultiAccessUnitInterface(component->intf());
269     mInterface = new ComponentInterface(
270             component->intf(), mMultiAccessUnitIntf, store->getParameterCache());
271     mInit = mInterface->status();
272 }
273 
status() const274 c2_status_t Component::status() const {
275     return mInit;
276 }
277 
onDeathReceived()278 void Component::onDeathReceived() {
279     std::list<std::shared_ptr<C2BufferQueueBlockPool>> bqPools;
280     {
281         std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
282         mClientDied = true;
283         transform_if(mBlockPools.begin(), mBlockPools.end(), std::back_inserter(bqPools),
284                 BqPoolFilterFn, BqPoolConvertFn);
285     }
286     if (!bqPools.empty()) {
287         std::shared_ptr<C2BqPoolInvalidateItem> bqInvalidateItem =
288                 std::make_shared<C2BqPoolInvalidateItem>(std::move(bqPools));
289         bqInvalidateItem->invalidate();
290     }
291     release();
292 }
293 
294 // Methods from ::android::hardware::media::c2::V1_1::IComponent
queue(const WorkBundle & workBundle)295 Return<Status> Component::queue(const WorkBundle& workBundle) {
296     std::list<std::unique_ptr<C2Work>> c2works;
297 
298     if (!objcpy(&c2works, workBundle)) {
299         return Status::CORRUPTED;
300     }
301 
302     // Register input buffers.
303     for (const std::unique_ptr<C2Work>& work : c2works) {
304         if (work) {
305             InputBufferManager::
306                     registerFrameData(mListener, work->input);
307         }
308     }
309     c2_status_t err = C2_OK;
310     if (mMultiAccessUnitHelper) {
311         std::list<std::list<std::unique_ptr<C2Work>>> c2worklists;
312         mMultiAccessUnitHelper->scatter(c2works, &c2worklists);
313         for (auto &c2worklist : c2worklists) {
314             err = mComponent->queue_nb(&c2worklist);
315             if (err != C2_OK) {
316                 LOG(ERROR) << "Error Queuing to component.";
317                 break;
318             }
319         }
320         return static_cast<Status>(err);
321     }
322 
323     return static_cast<Status>(mComponent->queue_nb(&c2works));
324 }
325 
flush(flush_cb _hidl_cb)326 Return<void> Component::flush(flush_cb _hidl_cb) {
327     std::list<std::unique_ptr<C2Work>> c2flushedWorks;
328     c2_status_t c2res = mComponent->flush_sm(
329             C2Component::FLUSH_COMPONENT,
330             &c2flushedWorks);
331     if (mMultiAccessUnitHelper) {
332         c2res = mMultiAccessUnitHelper->flush(&c2flushedWorks);
333     }
334 
335     // Unregister input buffers.
336     for (const std::unique_ptr<C2Work>& work : c2flushedWorks) {
337         if (work) {
338             if (work->worklets.empty()
339                     || !work->worklets.back()
340                     || (work->worklets.back()->output.flags &
341                         C2FrameData::FLAG_INCOMPLETE) == 0) {
342                 InputBufferManager::
343                         unregisterFrameData(mListener, work->input);
344             }
345         }
346     }
347 
348     WorkBundle flushedWorkBundle;
349     Status res = static_cast<Status>(c2res);
350     beginTransferBufferQueueBlocks(c2flushedWorks, true);
351     if (c2res == C2_OK) {
352         if (!objcpy(&flushedWorkBundle, c2flushedWorks, &mBufferPoolSender)) {
353             res = Status::CORRUPTED;
354         }
355     }
356     _hidl_cb(res, flushedWorkBundle);
357     endTransferBufferQueueBlocks(c2flushedWorks, true, true);
358     return Void();
359 }
360 
drain(bool withEos)361 Return<Status> Component::drain(bool withEos) {
362     return static_cast<Status>(mComponent->drain_nb(withEos ?
363             C2Component::DRAIN_COMPONENT_WITH_EOS :
364             C2Component::DRAIN_COMPONENT_NO_EOS));
365 }
366 
setOutputSurface(uint64_t blockPoolId,const sp<HGraphicBufferProducer2> & surface)367 Return<Status> Component::setOutputSurface(
368         uint64_t blockPoolId,
369         const sp<HGraphicBufferProducer2>& surface) {
370     std::shared_ptr<C2BlockPool> pool;
371     GetCodec2BlockPool(blockPoolId, mComponent, &pool);
372     if (pool && pool->getAllocatorId() == C2PlatformAllocatorStore::BUFFERQUEUE) {
373         std::shared_ptr<C2BufferQueueBlockPool> bqPool =
374                 std::static_pointer_cast<C2BufferQueueBlockPool>(pool);
375         C2BufferQueueBlockPool::OnRenderCallback cb =
376             [this](uint64_t producer, int32_t slot, int64_t nsecs) {
377                 // TODO: batch this
378                 hidl_vec<IComponentListener::RenderedFrame> rendered;
379                 rendered.resize(1);
380                 rendered[0] = { producer, slot, nsecs };
381                 (void)mListener->onFramesRendered(rendered).isOk();
382         };
383         if (bqPool) {
384             bqPool->setRenderCallback(cb);
385             bqPool->configureProducer(surface);
386         }
387     }
388     return Status::OK;
389 }
390 
connectToInputSurface(const sp<IInputSurface> & inputSurface,connectToInputSurface_cb _hidl_cb)391 Return<void> Component::connectToInputSurface(
392         const sp<IInputSurface>& inputSurface,
393         connectToInputSurface_cb _hidl_cb) {
394     Status status;
395     sp<IInputSurfaceConnection> connection;
396     auto transStatus = inputSurface->connect(
397             asInputSink(),
398             [&status, &connection](
399                     Status s, const sp<IInputSurfaceConnection>& c) {
400                 status = s;
401                 connection = c;
402             }
403         );
404     _hidl_cb(status, connection);
405     return Void();
406 }
407 
connectToOmxInputSurface(const sp<HGraphicBufferProducer1> & producer,const sp<::android::hardware::media::omx::V1_0::IGraphicBufferSource> & source,connectToOmxInputSurface_cb _hidl_cb)408 Return<void> Component::connectToOmxInputSurface(
409         const sp<HGraphicBufferProducer1>& producer,
410         const sp<::android::hardware::media::omx::V1_0::
411         IGraphicBufferSource>& source,
412         connectToOmxInputSurface_cb _hidl_cb) {
413     (void)producer;
414     (void)source;
415     (void)_hidl_cb;
416     return Void();
417 }
418 
disconnectFromInputSurface()419 Return<Status> Component::disconnectFromInputSurface() {
420     // TODO implement
421     return Status::OK;
422 }
423 
424 namespace /* unnamed */ {
425 
426 struct BlockPoolIntf : public ConfigurableC2Intf {
BlockPoolIntfandroid::hardware::media::c2::V1_1::utils::__anon896242100411::BlockPoolIntf427     BlockPoolIntf(const std::shared_ptr<C2BlockPool>& pool)
428           : ConfigurableC2Intf{
429                 "C2BlockPool:" +
430                     (pool ? std::to_string(pool->getLocalId()) : "null"),
431                 0},
432             mPool{pool} {
433     }
434 
configandroid::hardware::media::c2::V1_1::utils::__anon896242100411::BlockPoolIntf435     virtual c2_status_t config(
436             const std::vector<C2Param*>& params,
437             c2_blocking_t mayBlock,
438             std::vector<std::unique_ptr<C2SettingResult>>* const failures
439             ) override {
440         (void)params;
441         (void)mayBlock;
442         (void)failures;
443         return C2_OK;
444     }
445 
queryandroid::hardware::media::c2::V1_1::utils::__anon896242100411::BlockPoolIntf446     virtual c2_status_t query(
447             const std::vector<C2Param::Index>& indices,
448             c2_blocking_t mayBlock,
449             std::vector<std::unique_ptr<C2Param>>* const params
450             ) const override {
451         (void)indices;
452         (void)mayBlock;
453         (void)params;
454         return C2_OK;
455     }
456 
querySupportedParamsandroid::hardware::media::c2::V1_1::utils::__anon896242100411::BlockPoolIntf457     virtual c2_status_t querySupportedParams(
458             std::vector<std::shared_ptr<C2ParamDescriptor>>* const params
459             ) const override {
460         (void)params;
461         return C2_OK;
462     }
463 
querySupportedValuesandroid::hardware::media::c2::V1_1::utils::__anon896242100411::BlockPoolIntf464     virtual c2_status_t querySupportedValues(
465             std::vector<C2FieldSupportedValuesQuery>& fields,
466             c2_blocking_t mayBlock) const override {
467         (void)fields;
468         (void)mayBlock;
469         return C2_OK;
470     }
471 
472 protected:
473     std::shared_ptr<C2BlockPool> mPool;
474 };
475 
476 } // unnamed namespace
477 
createBlockPool(uint32_t allocatorId,createBlockPool_cb _hidl_cb)478 Return<void> Component::createBlockPool(
479         uint32_t allocatorId,
480         createBlockPool_cb _hidl_cb) {
481     std::shared_ptr<C2BlockPool> blockPool;
482 #ifdef __ANDROID_APEX__
483     c2_status_t status = CreateCodec2BlockPool(
484             static_cast<C2PlatformAllocatorStore::id_t>(allocatorId),
485             mComponent,
486             &blockPool);
487 #else
488     c2_status_t status = ComponentStore::GetFilterWrapper()->createBlockPool(
489             static_cast<C2PlatformAllocatorStore::id_t>(allocatorId),
490             mComponent,
491             &blockPool);
492 #endif
493     if (status != C2_OK) {
494         blockPool = nullptr;
495     }
496     if (blockPool) {
497         bool emplaced = false;
498         {
499             mBlockPoolsMutex.lock();
500             if (!mClientDied) {
501                 mBlockPools.emplace(blockPool->getLocalId(), blockPool);
502                 emplaced = true;
503             }
504             mBlockPoolsMutex.unlock();
505         }
506         if (!emplaced) {
507             blockPool.reset();
508             status = C2_BAD_STATE;
509         }
510     } else if (status == C2_OK) {
511         status = C2_CORRUPTED;
512     }
513 
514     _hidl_cb(static_cast<Status>(status),
515             blockPool ? blockPool->getLocalId() : 0,
516             new CachedConfigurable(
517             std::make_unique<BlockPoolIntf>(blockPool)));
518     return Void();
519 }
520 
destroyBlockPool(uint64_t blockPoolId)521 Return<Status> Component::destroyBlockPool(uint64_t blockPoolId) {
522     std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
523     return mBlockPools.erase(blockPoolId) == 1 ?
524             Status::OK : Status::CORRUPTED;
525 }
526 
start()527 Return<Status> Component::start() {
528     return static_cast<Status>(mComponent->start());
529 }
530 
stop()531 Return<Status> Component::stop() {
532     InputBufferManager::unregisterFrameData(mListener);
533     Status status = static_cast<Status>(mComponent->stop());
534     {
535         std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
536         for (auto it = mBlockPools.begin(); it != mBlockPools.end(); ++it) {
537             if (it->second->getAllocatorId() == C2PlatformAllocatorStore::BUFFERQUEUE) {
538                 std::shared_ptr<C2BufferQueueBlockPool> bqPool =
539                         std::static_pointer_cast<C2BufferQueueBlockPool>(it->second);
540                 bqPool->clearDeferredBlocks();
541             }
542         }
543     }
544     return status;
545 }
546 
reset()547 Return<Status> Component::reset() {
548     Status status = static_cast<Status>(mComponent->reset());
549     {
550         std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
551         mBlockPools.clear();
552     }
553     if (mMultiAccessUnitHelper) {
554         mMultiAccessUnitHelper->reset();
555     }
556     InputBufferManager::unregisterFrameData(mListener);
557     return status;
558 }
559 
release()560 Return<Status> Component::release() {
561     std::list<std::shared_ptr<C2BufferQueueBlockPool>> bqPools;
562     {
563         std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
564         if (!mClientDied) {
565             transform_if(mBlockPools.begin(), mBlockPools.end(), std::back_inserter(bqPools),
566                     BqPoolFilterFn, BqPoolConvertFn);
567         }
568     }
569     std::shared_ptr<C2BqPoolInvalidateItem> bqInvalidateItem;
570     if (!bqPools.empty()) {
571         // handling rare cases of process death just after release() called.
572         bqInvalidateItem = std::make_shared<C2BqPoolInvalidateItem>(std::move(bqPools));
573         C2BqPoolInvalidator::getInstance().queue(bqInvalidateItem);
574     }
575     Status status = static_cast<Status>(mComponent->release());
576     if (bqInvalidateItem) {
577         // If release is not blocked,
578         // skip invalidation and finish ASAP.
579         bqInvalidateItem->skip();
580     }
581     {
582         std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
583         mBlockPools.clear();
584     }
585     if (mMultiAccessUnitHelper) {
586         mMultiAccessUnitHelper->reset();
587     }
588     InputBufferManager::unregisterFrameData(mListener);
589     return status;
590 }
591 
getInterface()592 Return<sp<IComponentInterface>> Component::getInterface() {
593     return sp<IComponentInterface>(mInterface);
594 }
595 
asInputSink()596 Return<sp<IInputSink>> Component::asInputSink() {
597     std::lock_guard<std::mutex> lock(mSinkMutex);
598     if (!mSink) {
599         mSink = new Sink(shared_from_this());
600     }
601     return {mSink};
602 }
603 
configureVideoTunnel(uint32_t avSyncHwId,configureVideoTunnel_cb _hidl_cb)604 Return<void> Component::configureVideoTunnel(
605         uint32_t avSyncHwId, configureVideoTunnel_cb _hidl_cb) {
606     (void)avSyncHwId;
607     _hidl_cb(Status::OMITTED, hidl_handle{});
608     return Void();
609 }
610 
findLocalComponent(const sp<IInputSink> & sink)611 std::shared_ptr<C2Component> Component::findLocalComponent(
612         const sp<IInputSink>& sink) {
613     return Component::Sink::findLocalComponent(sink);
614 }
615 
initListener(const sp<Component> & self)616 void Component::initListener(const sp<Component>& self) {
617     std::shared_ptr<C2Component::Listener> c2listener;
618     if (mMultiAccessUnitIntf) {
619         std::shared_ptr<C2Allocator> allocator;
620         std::shared_ptr<C2BlockPool> linearPool;
621         std::shared_ptr<C2AllocatorStore> store = ::android::GetCodec2PlatformAllocatorStore();
622         if(store->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &allocator) == C2_OK) {
623             ::android::C2PlatformAllocatorDesc desc;
624             desc.allocatorId = allocator->getId();
625             if (C2_OK == CreateCodec2BlockPool(desc, mComponent, &linearPool)) {
626                 if (linearPool) {
627                     mMultiAccessUnitHelper = std::make_shared<MultiAccessUnitHelper>(
628                             mMultiAccessUnitIntf, linearPool);
629                 }
630             }
631         }
632     }
633     c2listener = mMultiAccessUnitHelper ?
634             std::make_shared<MultiAccessUnitListener>(self, mMultiAccessUnitHelper) :
635             std::make_shared<Listener>(self);
636     c2_status_t res = mComponent->setListener_vb(c2listener, C2_DONT_BLOCK);
637     if (res != C2_OK) {
638         mInit = res;
639     }
640 
641     struct ListenerDeathRecipient : public HwDeathRecipient {
642         ListenerDeathRecipient(const wp<Component>& comp)
643             : component{comp} {
644         }
645 
646         virtual void serviceDied(
647                 uint64_t /* cookie */,
648                 const wp<::android::hidl::base::V1_0::IBase>& /* who */
649                 ) override {
650             auto strongComponent = component.promote();
651             if (strongComponent) {
652                 LOG(INFO) << "Client died ! notify and release the component !!";
653                 strongComponent->onDeathReceived();
654             } else {
655                 LOG(ERROR) << "Client died ! no component to release !!";
656             }
657         }
658 
659         wp<Component> component;
660     };
661 
662     mDeathRecipient = new ListenerDeathRecipient(self);
663     Return<bool> transStatus = mListener->linkToDeath(
664             mDeathRecipient, 0);
665     if (!transStatus.isOk()) {
666         LOG(ERROR) << "Listener linkToDeath() transaction failed.";
667     }
668     if (!static_cast<bool>(transStatus)) {
669         LOG(DEBUG) << "Listener linkToDeath() call failed.";
670     }
671 }
672 
~Component()673 Component::~Component() {
674     std::list<std::shared_ptr<C2BufferQueueBlockPool>> bqPools;
675     {
676         std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
677         transform_if(mBlockPools.begin(), mBlockPools.end(), std::back_inserter(bqPools),
678                 BqPoolFilterFn, BqPoolConvertFn);
679     }
680     if (!bqPools.empty()) {
681         LOG(ERROR) << "blockpools are not cleared yet at dtor";
682         std::shared_ptr<C2BqPoolInvalidateItem> bqInvalidateItem =
683                 std::make_shared<C2BqPoolInvalidateItem>(std::move(bqPools));
684         C2BqPoolInvalidator::getInstance().queue(bqInvalidateItem);
685     }
686     InputBufferManager::unregisterFrameData(mListener);
687     mStore->reportComponentDeath(this);
688 }
689 
690 } // namespace utils
691 } // namespace V1_1
692 } // namespace c2
693 } // namespace media
694 } // namespace hardware
695 } // namespace android
696