blob: fa18c3ee6dd52f3c22b9942293cec49678b716ee [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();
116 // TODO
117 // beginTransferBufferQueueBlocks(c2workItems, true);
118 if (!ToAidl(&workBundle, c2workItems, strongComponent ?
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700119 &strongComponent->mBufferPoolSender : nullptr)) {
120 LOG(ERROR) << "Component::Listener::onWorkDone_nb -- "
121 << "received corrupted work items.";
Wonsik Kimf0032642023-07-20 14:42:27 -0700122 // TODO
123 // endTransferBufferQueueBlocks(c2workItems, false, true);
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700124 return;
125 }
Wonsik Kimf0032642023-07-20 14:42:27 -0700126 ScopedAStatus transStatus = listener->onWorkDone(workBundle);
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700127 if (!transStatus.isOk()) {
128 LOG(ERROR) << "Component::Listener::onWorkDone_nb -- "
129 << "transaction failed.";
Wonsik Kimf0032642023-07-20 14:42:27 -0700130 // TODO
131 // endTransferBufferQueueBlocks(c2workItems, false, true);
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700132 return;
133 }
Wonsik Kimf0032642023-07-20 14:42:27 -0700134 // TODO
135 // endTransferBufferQueueBlocks(c2workItems, true, true);
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700136 }
137 }
138
139protected:
Wonsik Kimf0032642023-07-20 14:42:27 -0700140 std::weak_ptr<Component> mComponent;
141 std::weak_ptr<IComponentListener> mListener;
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700142};
143
Wonsik Kimf0032642023-07-20 14:42:27 -0700144// Component::DeathContext
145struct Component::DeathContext {
146 std::weak_ptr<Component> mWeakComp;
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700147};
148
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700149// Component
150Component::Component(
151 const std::shared_ptr<C2Component>& component,
Wonsik Kimf0032642023-07-20 14:42:27 -0700152 const std::shared_ptr<IComponentListener>& listener,
153 const std::shared_ptr<ComponentStore>& store,
154 const std::shared_ptr<IClientManager>& clientPoolManager)
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700155 : mComponent{component},
Wonsik Kimf0032642023-07-20 14:42:27 -0700156 mInterface{SharedRefBase::make<ComponentInterface>(
157 component->intf(), store->getParameterCache())},
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700158 mListener{listener},
159 mStore{store},
Wonsik Kimf0032642023-07-20 14:42:27 -0700160 mBufferPoolSender{clientPoolManager},
161 mDeathContext(nullptr) {
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700162 // Retrieve supported parameters from store
163 // TODO: We could cache this per component/interface type
164 mInit = mInterface->status();
165}
166
167c2_status_t Component::status() const {
168 return mInit;
169}
170
171// Methods from ::android::hardware::media::c2::V1_1::IComponent
Wonsik Kimf0032642023-07-20 14:42:27 -0700172ScopedAStatus Component::queue(const WorkBundle& workBundle) {
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700173 std::list<std::unique_ptr<C2Work>> c2works;
174
Wonsik Kimf0032642023-07-20 14:42:27 -0700175 if (!FromAidl(&c2works, workBundle)) {
176 return ScopedAStatus::fromServiceSpecificError(Status::CORRUPTED);
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700177 }
178
179 // Register input buffers.
180 for (const std::unique_ptr<C2Work>& work : c2works) {
181 if (work) {
182 InputBufferManager::
183 registerFrameData(mListener, work->input);
184 }
185 }
186
Wonsik Kimf0032642023-07-20 14:42:27 -0700187 c2_status_t err = mComponent->queue_nb(&c2works);
188 if (err == C2_OK) {
189 return ScopedAStatus::ok();
190 }
191 return ScopedAStatus::fromServiceSpecificError(err);
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700192}
193
Wonsik Kimf0032642023-07-20 14:42:27 -0700194ScopedAStatus Component::flush(WorkBundle *flushedWorkBundle) {
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700195 std::list<std::unique_ptr<C2Work>> c2flushedWorks;
196 c2_status_t c2res = mComponent->flush_sm(
197 C2Component::FLUSH_COMPONENT,
198 &c2flushedWorks);
199
200 // Unregister input buffers.
201 for (const std::unique_ptr<C2Work>& work : c2flushedWorks) {
202 if (work) {
203 if (work->worklets.empty()
204 || !work->worklets.back()
205 || (work->worklets.back()->output.flags &
206 C2FrameData::FLAG_INCOMPLETE) == 0) {
207 InputBufferManager::
208 unregisterFrameData(mListener, work->input);
209 }
210 }
211 }
212
Wonsik Kimf0032642023-07-20 14:42:27 -0700213 // TODO
214 // beginTransferBufferQueueBlocks(c2flushedWorks, true);
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700215 if (c2res == C2_OK) {
Wonsik Kimf0032642023-07-20 14:42:27 -0700216 if (!ToAidl(flushedWorkBundle, c2flushedWorks, &mBufferPoolSender)) {
217 c2res = C2_CORRUPTED;
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700218 }
219 }
Wonsik Kimf0032642023-07-20 14:42:27 -0700220 // TODO
221 // endTransferBufferQueueBlocks(c2flushedWorks, true, true);
222 if (c2res == C2_OK) {
223 return ScopedAStatus::ok();
224 }
225 return ScopedAStatus::fromServiceSpecificError(c2res);
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700226}
227
Wonsik Kimf0032642023-07-20 14:42:27 -0700228ScopedAStatus Component::drain(bool withEos) {
229 c2_status_t res = mComponent->drain_nb(withEos ?
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700230 C2Component::DRAIN_COMPONENT_WITH_EOS :
Wonsik Kimf0032642023-07-20 14:42:27 -0700231 C2Component::DRAIN_COMPONENT_NO_EOS);
232 if (res == C2_OK) {
233 return ScopedAStatus::ok();
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700234 }
Wonsik Kimf0032642023-07-20 14:42:27 -0700235 return ScopedAStatus::fromServiceSpecificError(res);
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700236}
237
238namespace /* unnamed */ {
239
240struct BlockPoolIntf : public ConfigurableC2Intf {
241 BlockPoolIntf(const std::shared_ptr<C2BlockPool>& pool)
242 : ConfigurableC2Intf{
243 "C2BlockPool:" +
244 (pool ? std::to_string(pool->getLocalId()) : "null"),
245 0},
246 mPool{pool} {
247 }
248
249 virtual c2_status_t config(
250 const std::vector<C2Param*>& params,
251 c2_blocking_t mayBlock,
252 std::vector<std::unique_ptr<C2SettingResult>>* const failures
253 ) override {
254 (void)params;
255 (void)mayBlock;
256 (void)failures;
257 return C2_OK;
258 }
259
260 virtual c2_status_t query(
261 const std::vector<C2Param::Index>& indices,
262 c2_blocking_t mayBlock,
263 std::vector<std::unique_ptr<C2Param>>* const params
264 ) const override {
265 (void)indices;
266 (void)mayBlock;
267 (void)params;
268 return C2_OK;
269 }
270
271 virtual c2_status_t querySupportedParams(
272 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params
273 ) const override {
274 (void)params;
275 return C2_OK;
276 }
277
278 virtual c2_status_t querySupportedValues(
279 std::vector<C2FieldSupportedValuesQuery>& fields,
280 c2_blocking_t mayBlock) const override {
281 (void)fields;
282 (void)mayBlock;
283 return C2_OK;
284 }
285
286protected:
287 std::shared_ptr<C2BlockPool> mPool;
288};
289
290} // unnamed namespace
291
Wonsik Kimf0032642023-07-20 14:42:27 -0700292ScopedAStatus Component::createBlockPool(
293 const IComponent::BlockPoolAllocator &allocator,
294 IComponent::BlockPool *blockPool) {
295 std::shared_ptr<C2BlockPool> c2BlockPool;
296 static constexpr IComponent::BlockPoolAllocator::Tag ALLOCATOR_ID =
297 IComponent::BlockPoolAllocator::allocatorId;
298 static constexpr IComponent::BlockPoolAllocator::Tag IGBA =
299 IComponent::BlockPoolAllocator::igba;
300 c2_status_t status = C2_OK;
301 switch (allocator.getTag()) {
302 case ALLOCATOR_ID:
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700303#ifdef __ANDROID_APEX__
Wonsik Kimf0032642023-07-20 14:42:27 -0700304 status = CreateCodec2BlockPool(
305 static_cast<::android::C2PlatformAllocatorStore::id_t>(
306 allocator.get<ALLOCATOR_ID>()),
307 mComponent,
308 &c2BlockPool);
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700309#else
Wonsik Kimf0032642023-07-20 14:42:27 -0700310 status = ComponentStore::GetFilterWrapper()->createBlockPool(
311 static_cast<::android::C2PlatformAllocatorStore::id_t>(
312 allocator.get<ALLOCATOR_ID>()),
313 mComponent,
314 &c2BlockPool);
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700315#endif
Wonsik Kimf0032642023-07-20 14:42:27 -0700316 if (status != C2_OK) {
317 blockPool = nullptr;
318 }
319 break;
320 case IGBA:
321 // FIXME
322 break;
323 default:
324 break;
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700325 }
326 if (blockPool) {
327 mBlockPoolsMutex.lock();
Wonsik Kimf0032642023-07-20 14:42:27 -0700328 mBlockPools.emplace(c2BlockPool->getLocalId(), c2BlockPool);
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700329 mBlockPoolsMutex.unlock();
330 } else if (status == C2_OK) {
331 status = C2_CORRUPTED;
332 }
333
Wonsik Kimf0032642023-07-20 14:42:27 -0700334 blockPool->blockPoolId = c2BlockPool ? c2BlockPool->getLocalId() : 0;
335 blockPool->configurable = SharedRefBase::make<CachedConfigurable>(
336 std::make_unique<BlockPoolIntf>(c2BlockPool));
337 if (status == C2_OK) {
338 return ScopedAStatus::ok();
339 }
340 return ScopedAStatus::fromServiceSpecificError(status);
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700341}
342
Wonsik Kimf0032642023-07-20 14:42:27 -0700343ScopedAStatus Component::destroyBlockPool(int64_t blockPoolId) {
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700344 std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
Wonsik Kimf0032642023-07-20 14:42:27 -0700345 if (mBlockPools.erase(blockPoolId) == 1) {
346 return ScopedAStatus::ok();
347 }
348 return ScopedAStatus::fromServiceSpecificError(Status::CORRUPTED);
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700349}
350
Wonsik Kimf0032642023-07-20 14:42:27 -0700351ScopedAStatus Component::start() {
352 c2_status_t status = mComponent->start();
353 if (status == C2_OK) {
354 return ScopedAStatus::ok();
355 }
356 return ScopedAStatus::fromServiceSpecificError(status);
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700357}
358
Wonsik Kimf0032642023-07-20 14:42:27 -0700359ScopedAStatus Component::stop() {
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700360 InputBufferManager::unregisterFrameData(mListener);
Wonsik Kimf0032642023-07-20 14:42:27 -0700361 c2_status_t status = mComponent->stop();
362 if (status == C2_OK) {
363 return ScopedAStatus::ok();
364 }
365 return ScopedAStatus::fromServiceSpecificError(status);
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700366}
367
Wonsik Kimf0032642023-07-20 14:42:27 -0700368ScopedAStatus Component::reset() {
369 c2_status_t status = mComponent->reset();
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700370 {
371 std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
372 mBlockPools.clear();
373 }
374 InputBufferManager::unregisterFrameData(mListener);
Wonsik Kimf0032642023-07-20 14:42:27 -0700375 if (status == C2_OK) {
376 return ScopedAStatus::ok();
377 }
378 return ScopedAStatus::fromServiceSpecificError(status);
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700379}
380
Wonsik Kimf0032642023-07-20 14:42:27 -0700381ScopedAStatus Component::release() {
382 c2_status_t status = mComponent->release();
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700383 {
384 std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
385 mBlockPools.clear();
386 }
387 InputBufferManager::unregisterFrameData(mListener);
Wonsik Kimf0032642023-07-20 14:42:27 -0700388 if (status == C2_OK) {
389 return ScopedAStatus::ok();
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700390 }
Wonsik Kimf0032642023-07-20 14:42:27 -0700391 return ScopedAStatus::fromServiceSpecificError(status);
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700392}
393
Wonsik Kimf0032642023-07-20 14:42:27 -0700394ScopedAStatus Component::getInterface(
395 std::shared_ptr<IComponentInterface> *intf) {
396 *intf = mInterface;
397 return ScopedAStatus::ok();
398}
399
400ScopedAStatus Component::configureVideoTunnel(
401 int32_t avSyncHwId, NativeHandle *handle) {
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700402 (void)avSyncHwId;
Wonsik Kimf0032642023-07-20 14:42:27 -0700403 (void)handle;
404 return ScopedAStatus::fromServiceSpecificError(Status::OMITTED);
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700405}
406
Wonsik Kimf0032642023-07-20 14:42:27 -0700407void Component::initListener(const std::shared_ptr<Component>& self) {
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700408 std::shared_ptr<C2Component::Listener> c2listener =
409 std::make_shared<Listener>(self);
410 c2_status_t res = mComponent->setListener_vb(c2listener, C2_DONT_BLOCK);
411 if (res != C2_OK) {
412 mInit = res;
413 }
414
Wonsik Kimf0032642023-07-20 14:42:27 -0700415 mDeathRecipient = ::ndk::ScopedAIBinder_DeathRecipient(
416 AIBinder_DeathRecipient_new(OnBinderDied));
417 mDeathContext = new DeathContext{weak_from_this()};
418 AIBinder_DeathRecipient_setOnUnlinked(mDeathRecipient.get(), OnBinderUnlinked);
419 AIBinder_linkToDeath(mListener->asBinder().get(), mDeathRecipient.get(), mDeathContext);
420}
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