blob: 4f5b8998a8fabab399aa0e7b827dbbea0bac93e0 [file] [log] [blame]
Wonsik Kim5ec480f2023-07-11 14:25:55 -07001/*
2 * Copyright 2021 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
Wonsik Kimf0032642023-07-20 14:42:27 -070018#define LOG_TAG "Codec2-Component-Aidl"
Wonsik Kim5ec480f2023-07-11 14:25:55 -070019#include <android-base/logging.h>
20
Wonsik Kimf0032642023-07-20 14:42:27 -070021#include <codec2/aidl/Component.h>
22#include <codec2/aidl/ComponentStore.h>
23#include <codec2/aidl/InputBufferManager.h>
Wonsik Kim5ec480f2023-07-11 14:25:55 -070024
25#ifndef __ANDROID_APEX__
26#include <FilterWrapper.h>
27#endif
28
Wonsik Kimf0032642023-07-20 14:42:27 -070029#include <android/binder_auto_utils.h>
30#include <android/binder_interface_utils.h>
Wonsik Kim5ec480f2023-07-11 14:25:55 -070031#include <utils/Timers.h>
32
Wonsik Kim5ec480f2023-07-11 14:25:55 -070033#include <C2Debug.h>
34#include <C2PlatformSupport.h>
35
36#include <chrono>
37#include <thread>
38
Wonsik Kimf0032642023-07-20 14:42:27 -070039namespace aidl {
Wonsik Kim5ec480f2023-07-11 14:25:55 -070040namespace android {
41namespace hardware {
42namespace media {
43namespace c2 {
Wonsik Kim5ec480f2023-07-11 14:25:55 -070044namespace utils {
45
Wonsik Kimf0032642023-07-20 14:42:27 -070046using ::aidl::android::hardware::common::NativeHandle;
47using ::aidl::android::hardware::media::bufferpool2::IClientManager;
48using ::ndk::ScopedAStatus;
Wonsik Kim5ec480f2023-07-11 14:25:55 -070049
50// ComponentListener wrapper
51struct Component::Listener : public C2Component::Listener {
52
Wonsik Kimf0032642023-07-20 14:42:27 -070053 Listener(const std::shared_ptr<Component>& component) :
Wonsik Kim5ec480f2023-07-11 14:25:55 -070054 mComponent(component),
55 mListener(component->mListener) {
56 }
57
58 virtual void onError_nb(
59 std::weak_ptr<C2Component> /* c2component */,
60 uint32_t errorCode) override {
Wonsik Kimf0032642023-07-20 14:42:27 -070061 std::shared_ptr<IComponentListener> listener = mListener.lock();
Wonsik Kim5ec480f2023-07-11 14:25:55 -070062 if (listener) {
Wonsik Kimf0032642023-07-20 14:42:27 -070063 ScopedAStatus transStatus = listener->onError(Status{Status::OK}, errorCode);
Wonsik Kim5ec480f2023-07-11 14:25:55 -070064 if (!transStatus.isOk()) {
65 LOG(ERROR) << "Component::Listener::onError_nb -- "
66 << "transaction failed.";
67 }
68 }
69 }
70
71 virtual void onTripped_nb(
72 std::weak_ptr<C2Component> /* c2component */,
73 std::vector<std::shared_ptr<C2SettingResult>> c2settingResult
74 ) override {
Wonsik Kimf0032642023-07-20 14:42:27 -070075 std::shared_ptr<IComponentListener> listener = mListener.lock();
Wonsik Kim5ec480f2023-07-11 14:25:55 -070076 if (listener) {
Wonsik Kimf0032642023-07-20 14:42:27 -070077 std::vector<SettingResult> settingResults(c2settingResult.size());
Wonsik Kim5ec480f2023-07-11 14:25:55 -070078 size_t ix = 0;
79 for (const std::shared_ptr<C2SettingResult> &c2result :
80 c2settingResult) {
81 if (c2result) {
Wonsik Kimf0032642023-07-20 14:42:27 -070082 if (!ToAidl(&settingResults[ix++], *c2result)) {
Wonsik Kim5ec480f2023-07-11 14:25:55 -070083 break;
84 }
85 }
86 }
87 settingResults.resize(ix);
Wonsik Kimf0032642023-07-20 14:42:27 -070088 ScopedAStatus transStatus = listener->onTripped(settingResults);
Wonsik Kim5ec480f2023-07-11 14:25:55 -070089 if (!transStatus.isOk()) {
90 LOG(ERROR) << "Component::Listener::onTripped_nb -- "
91 << "transaction failed.";
92 }
93 }
94 }
95
96 virtual void onWorkDone_nb(
97 std::weak_ptr<C2Component> /* c2component */,
98 std::list<std::unique_ptr<C2Work>> c2workItems) override {
99 for (const std::unique_ptr<C2Work>& work : c2workItems) {
100 if (work) {
101 if (work->worklets.empty()
102 || !work->worklets.back()
103 || (work->worklets.back()->output.flags &
104 C2FrameData::FLAG_INCOMPLETE) == 0) {
105 InputBufferManager::
106 unregisterFrameData(mListener, work->input);
107 }
108 }
109 }
110
Wonsik Kimf0032642023-07-20 14:42:27 -0700111 std::shared_ptr<IComponentListener> listener = mListener.lock();
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700112 if (listener) {
113 WorkBundle workBundle;
114
Wonsik Kimf0032642023-07-20 14:42:27 -0700115 std::shared_ptr<Component> strongComponent = mComponent.lock();
Wonsik Kimf0032642023-07-20 14:42:27 -0700116 if (!ToAidl(&workBundle, c2workItems, strongComponent ?
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700117 &strongComponent->mBufferPoolSender : nullptr)) {
118 LOG(ERROR) << "Component::Listener::onWorkDone_nb -- "
119 << "received corrupted work items.";
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700120 return;
121 }
Wonsik Kimf0032642023-07-20 14:42:27 -0700122 ScopedAStatus transStatus = listener->onWorkDone(workBundle);
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700123 if (!transStatus.isOk()) {
124 LOG(ERROR) << "Component::Listener::onWorkDone_nb -- "
125 << "transaction failed.";
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700126 return;
127 }
Sungtak Lee72dfba62023-09-07 23:26:30 +0000128 // If output blocks are originally owned by the client(not by HAL),
129 // return the ownership to the client. (Since the blocks are
130 // transferred to the client here.)
131 ReturnOutputBlocksToClientIfNeeded(c2workItems);
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700132 }
133 }
134
135protected:
Wonsik Kimf0032642023-07-20 14:42:27 -0700136 std::weak_ptr<Component> mComponent;
137 std::weak_ptr<IComponentListener> mListener;
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700138};
139
Wonsik Kimf0032642023-07-20 14:42:27 -0700140// Component::DeathContext
141struct Component::DeathContext {
142 std::weak_ptr<Component> mWeakComp;
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700143};
144
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700145// Component
146Component::Component(
147 const std::shared_ptr<C2Component>& component,
Wonsik Kimf0032642023-07-20 14:42:27 -0700148 const std::shared_ptr<IComponentListener>& listener,
149 const std::shared_ptr<ComponentStore>& store,
150 const std::shared_ptr<IClientManager>& clientPoolManager)
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700151 : mComponent{component},
Wonsik Kimf0032642023-07-20 14:42:27 -0700152 mInterface{SharedRefBase::make<ComponentInterface>(
153 component->intf(), store->getParameterCache())},
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700154 mListener{listener},
155 mStore{store},
Wonsik Kimf0032642023-07-20 14:42:27 -0700156 mBufferPoolSender{clientPoolManager},
157 mDeathContext(nullptr) {
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700158 // Retrieve supported parameters from store
159 // TODO: We could cache this per component/interface type
160 mInit = mInterface->status();
161}
162
163c2_status_t Component::status() const {
164 return mInit;
165}
166
167// Methods from ::android::hardware::media::c2::V1_1::IComponent
Wonsik Kimf0032642023-07-20 14:42:27 -0700168ScopedAStatus Component::queue(const WorkBundle& workBundle) {
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700169 std::list<std::unique_ptr<C2Work>> c2works;
170
Wonsik Kimf0032642023-07-20 14:42:27 -0700171 if (!FromAidl(&c2works, workBundle)) {
172 return ScopedAStatus::fromServiceSpecificError(Status::CORRUPTED);
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700173 }
174
175 // Register input buffers.
176 for (const std::unique_ptr<C2Work>& work : c2works) {
177 if (work) {
178 InputBufferManager::
179 registerFrameData(mListener, work->input);
180 }
181 }
182
Wonsik Kimf0032642023-07-20 14:42:27 -0700183 c2_status_t err = mComponent->queue_nb(&c2works);
184 if (err == C2_OK) {
185 return ScopedAStatus::ok();
186 }
187 return ScopedAStatus::fromServiceSpecificError(err);
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700188}
189
Wonsik Kimf0032642023-07-20 14:42:27 -0700190ScopedAStatus Component::flush(WorkBundle *flushedWorkBundle) {
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700191 std::list<std::unique_ptr<C2Work>> c2flushedWorks;
192 c2_status_t c2res = mComponent->flush_sm(
193 C2Component::FLUSH_COMPONENT,
194 &c2flushedWorks);
195
196 // Unregister input buffers.
197 for (const std::unique_ptr<C2Work>& work : c2flushedWorks) {
198 if (work) {
199 if (work->worklets.empty()
200 || !work->worklets.back()
201 || (work->worklets.back()->output.flags &
202 C2FrameData::FLAG_INCOMPLETE) == 0) {
203 InputBufferManager::
204 unregisterFrameData(mListener, work->input);
205 }
206 }
207 }
208
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700209 if (c2res == C2_OK) {
Wonsik Kimf0032642023-07-20 14:42:27 -0700210 if (!ToAidl(flushedWorkBundle, c2flushedWorks, &mBufferPoolSender)) {
211 c2res = C2_CORRUPTED;
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700212 }
213 }
Sungtak Lee72dfba62023-09-07 23:26:30 +0000214 // If output blocks are originally owned by the client(not by HAL),
215 // return the ownership to the client. (Since the blocks are
216 // transferred to the client here.)
217 ReturnOutputBlocksToClientIfNeeded(c2flushedWorks);
Wonsik Kimf0032642023-07-20 14:42:27 -0700218 if (c2res == C2_OK) {
219 return ScopedAStatus::ok();
220 }
221 return ScopedAStatus::fromServiceSpecificError(c2res);
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700222}
223
Wonsik Kimf0032642023-07-20 14:42:27 -0700224ScopedAStatus Component::drain(bool withEos) {
225 c2_status_t res = mComponent->drain_nb(withEos ?
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700226 C2Component::DRAIN_COMPONENT_WITH_EOS :
Wonsik Kimf0032642023-07-20 14:42:27 -0700227 C2Component::DRAIN_COMPONENT_NO_EOS);
228 if (res == C2_OK) {
229 return ScopedAStatus::ok();
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700230 }
Wonsik Kimf0032642023-07-20 14:42:27 -0700231 return ScopedAStatus::fromServiceSpecificError(res);
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700232}
233
234namespace /* unnamed */ {
235
236struct BlockPoolIntf : public ConfigurableC2Intf {
237 BlockPoolIntf(const std::shared_ptr<C2BlockPool>& pool)
238 : ConfigurableC2Intf{
239 "C2BlockPool:" +
240 (pool ? std::to_string(pool->getLocalId()) : "null"),
241 0},
242 mPool{pool} {
243 }
244
245 virtual c2_status_t config(
246 const std::vector<C2Param*>& params,
247 c2_blocking_t mayBlock,
248 std::vector<std::unique_ptr<C2SettingResult>>* const failures
249 ) override {
250 (void)params;
251 (void)mayBlock;
252 (void)failures;
253 return C2_OK;
254 }
255
256 virtual c2_status_t query(
257 const std::vector<C2Param::Index>& indices,
258 c2_blocking_t mayBlock,
259 std::vector<std::unique_ptr<C2Param>>* const params
260 ) const override {
261 (void)indices;
262 (void)mayBlock;
263 (void)params;
264 return C2_OK;
265 }
266
267 virtual c2_status_t querySupportedParams(
268 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params
269 ) const override {
270 (void)params;
271 return C2_OK;
272 }
273
274 virtual c2_status_t querySupportedValues(
275 std::vector<C2FieldSupportedValuesQuery>& fields,
276 c2_blocking_t mayBlock) const override {
277 (void)fields;
278 (void)mayBlock;
279 return C2_OK;
280 }
281
282protected:
283 std::shared_ptr<C2BlockPool> mPool;
284};
285
286} // unnamed namespace
287
Wonsik Kimf0032642023-07-20 14:42:27 -0700288ScopedAStatus Component::createBlockPool(
289 const IComponent::BlockPoolAllocator &allocator,
290 IComponent::BlockPool *blockPool) {
291 std::shared_ptr<C2BlockPool> c2BlockPool;
292 static constexpr IComponent::BlockPoolAllocator::Tag ALLOCATOR_ID =
293 IComponent::BlockPoolAllocator::allocatorId;
294 static constexpr IComponent::BlockPoolAllocator::Tag IGBA =
Sungtak Lee0489c872023-10-28 01:18:46 +0000295 IComponent::BlockPoolAllocator::allocator;
Wonsik Kimf0032642023-07-20 14:42:27 -0700296 c2_status_t status = C2_OK;
297 switch (allocator.getTag()) {
298 case ALLOCATOR_ID:
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700299#ifdef __ANDROID_APEX__
Wonsik Kim8e2a19f2023-08-30 11:05:45 -0700300 status = ::android::CreateCodec2BlockPool(
Wonsik Kimf0032642023-07-20 14:42:27 -0700301 static_cast<::android::C2PlatformAllocatorStore::id_t>(
302 allocator.get<ALLOCATOR_ID>()),
303 mComponent,
304 &c2BlockPool);
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700305#else
Wonsik Kimf0032642023-07-20 14:42:27 -0700306 status = ComponentStore::GetFilterWrapper()->createBlockPool(
307 static_cast<::android::C2PlatformAllocatorStore::id_t>(
308 allocator.get<ALLOCATOR_ID>()),
309 mComponent,
310 &c2BlockPool);
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700311#endif
Wonsik Kimf0032642023-07-20 14:42:27 -0700312 if (status != C2_OK) {
313 blockPool = nullptr;
314 }
315 break;
316 case IGBA:
317 // FIXME
318 break;
319 default:
320 break;
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700321 }
322 if (blockPool) {
323 mBlockPoolsMutex.lock();
Wonsik Kimf0032642023-07-20 14:42:27 -0700324 mBlockPools.emplace(c2BlockPool->getLocalId(), c2BlockPool);
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700325 mBlockPoolsMutex.unlock();
326 } else if (status == C2_OK) {
327 status = C2_CORRUPTED;
328 }
329
Wonsik Kimf0032642023-07-20 14:42:27 -0700330 blockPool->blockPoolId = c2BlockPool ? c2BlockPool->getLocalId() : 0;
331 blockPool->configurable = SharedRefBase::make<CachedConfigurable>(
332 std::make_unique<BlockPoolIntf>(c2BlockPool));
333 if (status == C2_OK) {
334 return ScopedAStatus::ok();
335 }
336 return ScopedAStatus::fromServiceSpecificError(status);
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700337}
338
Wonsik Kimf0032642023-07-20 14:42:27 -0700339ScopedAStatus Component::destroyBlockPool(int64_t blockPoolId) {
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700340 std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
Wonsik Kimf0032642023-07-20 14:42:27 -0700341 if (mBlockPools.erase(blockPoolId) == 1) {
342 return ScopedAStatus::ok();
343 }
344 return ScopedAStatus::fromServiceSpecificError(Status::CORRUPTED);
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700345}
346
Wonsik Kimf0032642023-07-20 14:42:27 -0700347ScopedAStatus Component::start() {
348 c2_status_t status = mComponent->start();
349 if (status == C2_OK) {
350 return ScopedAStatus::ok();
351 }
352 return ScopedAStatus::fromServiceSpecificError(status);
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700353}
354
Wonsik Kimf0032642023-07-20 14:42:27 -0700355ScopedAStatus Component::stop() {
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700356 InputBufferManager::unregisterFrameData(mListener);
Wonsik Kimf0032642023-07-20 14:42:27 -0700357 c2_status_t status = mComponent->stop();
358 if (status == C2_OK) {
359 return ScopedAStatus::ok();
360 }
361 return ScopedAStatus::fromServiceSpecificError(status);
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700362}
363
Wonsik Kimf0032642023-07-20 14:42:27 -0700364ScopedAStatus Component::reset() {
365 c2_status_t status = mComponent->reset();
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700366 {
367 std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
368 mBlockPools.clear();
369 }
370 InputBufferManager::unregisterFrameData(mListener);
Wonsik Kimf0032642023-07-20 14:42:27 -0700371 if (status == C2_OK) {
372 return ScopedAStatus::ok();
373 }
374 return ScopedAStatus::fromServiceSpecificError(status);
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700375}
376
Wonsik Kimf0032642023-07-20 14:42:27 -0700377ScopedAStatus Component::release() {
378 c2_status_t status = mComponent->release();
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700379 {
380 std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
381 mBlockPools.clear();
382 }
383 InputBufferManager::unregisterFrameData(mListener);
Wonsik Kimf0032642023-07-20 14:42:27 -0700384 if (status == C2_OK) {
385 return ScopedAStatus::ok();
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700386 }
Wonsik Kimf0032642023-07-20 14:42:27 -0700387 return ScopedAStatus::fromServiceSpecificError(status);
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700388}
389
Wonsik Kimf0032642023-07-20 14:42:27 -0700390ScopedAStatus Component::getInterface(
391 std::shared_ptr<IComponentInterface> *intf) {
392 *intf = mInterface;
393 return ScopedAStatus::ok();
394}
395
396ScopedAStatus Component::configureVideoTunnel(
397 int32_t avSyncHwId, NativeHandle *handle) {
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700398 (void)avSyncHwId;
Wonsik Kimf0032642023-07-20 14:42:27 -0700399 (void)handle;
400 return ScopedAStatus::fromServiceSpecificError(Status::OMITTED);
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700401}
402
Wonsik Kimf0032642023-07-20 14:42:27 -0700403void Component::initListener(const std::shared_ptr<Component>& self) {
Wonsik Kim8e2a19f2023-08-30 11:05:45 -0700404 if (__builtin_available(android __ANDROID_API_T__, *)) {
405 std::shared_ptr<C2Component::Listener> c2listener =
406 std::make_shared<Listener>(self);
407 c2_status_t res = mComponent->setListener_vb(c2listener, C2_DONT_BLOCK);
408 if (res != C2_OK) {
409 mInit = res;
410 }
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700411
Wonsik Kim8e2a19f2023-08-30 11:05:45 -0700412 mDeathRecipient = ::ndk::ScopedAIBinder_DeathRecipient(
413 AIBinder_DeathRecipient_new(OnBinderDied));
Wonsik Kim8e35c062023-10-17 13:40:56 -0700414 mDeathContext = new DeathContext{ref<Component>()};
Wonsik Kim8e2a19f2023-08-30 11:05:45 -0700415 AIBinder_DeathRecipient_setOnUnlinked(mDeathRecipient.get(), OnBinderUnlinked);
416 AIBinder_linkToDeath(mListener->asBinder().get(), mDeathRecipient.get(), mDeathContext);
417 } else {
418 mInit = C2_NO_INIT;
419 }
Wonsik Kimf0032642023-07-20 14:42:27 -0700420}
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700421
Wonsik Kimf0032642023-07-20 14:42:27 -0700422// static
423void Component::OnBinderDied(void *cookie) {
424 DeathContext *context = (DeathContext *)cookie;
425 std::shared_ptr<Component> comp = context->mWeakComp.lock();
426 if (comp) {
427 comp->release();
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700428 }
Wonsik Kimf0032642023-07-20 14:42:27 -0700429}
430
431// static
432void Component::OnBinderUnlinked(void *cookie) {
433 delete (DeathContext *)cookie;
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700434}
435
436Component::~Component() {
437 InputBufferManager::unregisterFrameData(mListener);
438 mStore->reportComponentDeath(this);
Wonsik Kimf0032642023-07-20 14:42:27 -0700439 if (mDeathRecipient.get()) {
440 AIBinder_unlinkToDeath(mListener->asBinder().get(), mDeathRecipient.get(), mDeathContext);
441 }
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700442}
443
444} // namespace utils
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700445} // namespace c2
446} // namespace media
447} // namespace hardware
448} // namespace android
Wonsik Kimf0032642023-07-20 14:42:27 -0700449} // namespace aidl