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