blob: 76c378d6f717d0490ec0a377577b24535c029bd8 [file] [log] [blame]
Pawin Vongmasa36653902018-11-15 00:10:25 -08001/*
2 * Copyright (C) 2017 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_TAG "C2Store"
Steven Moreland024a6f12023-04-03 20:02:52 +000018// #define LOG_NDEBUG 0
Pawin Vongmasa36653902018-11-15 00:10:25 -080019#include <utils/Log.h>
20
Pin-chih Linaa18ea52019-11-19 18:48:50 +080021#include <C2AllocatorBlob.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080022#include <C2AllocatorGralloc.h>
23#include <C2AllocatorIon.h>
John Stultza7002cb2020-09-04 19:02:30 +000024#include <C2DmaBufAllocator.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080025#include <C2BufferPriv.h>
26#include <C2BqBufferPriv.h>
27#include <C2Component.h>
28#include <C2Config.h>
29#include <C2PlatformStorePluginLoader.h>
30#include <C2PlatformSupport.h>
Wonsik Kim0560d602023-11-15 10:08:21 -080031#include <codec2/common/HalSelection.h>
Pin-chih Linaa18ea52019-11-19 18:48:50 +080032#include <cutils/properties.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080033#include <util/C2InterfaceHelper.h>
34
35#include <dlfcn.h>
36#include <unistd.h> // getpagesize
37
38#include <map>
39#include <memory>
40#include <mutex>
41
Wonsik Kimba3db192019-11-22 11:00:48 -080042#ifdef __ANDROID_APEX__
43#include <android-base/properties.h>
44#endif
45
Pawin Vongmasa36653902018-11-15 00:10:25 -080046namespace android {
47
48/**
49 * Returns the preferred component store in this process to access its interface.
50 */
51std::shared_ptr<C2ComponentStore> GetPreferredCodec2ComponentStore();
52
53/**
54 * The platform allocator store provides basic allocator-types for the framework based on ion and
55 * gralloc. Allocators are not meant to be updatable.
56 *
57 * \todo Provide allocator based on ashmem
58 * \todo Move ion allocation into its HIDL or provide some mapping from memory usage to ion flags
59 * \todo Make this allocator store extendable
60 */
61class C2PlatformAllocatorStoreImpl : public C2PlatformAllocatorStore {
62public:
63 C2PlatformAllocatorStoreImpl();
64
65 virtual c2_status_t fetchAllocator(
66 id_t id, std::shared_ptr<C2Allocator> *const allocator) override;
67
68 virtual std::vector<std::shared_ptr<const C2Allocator::Traits>> listAllocators_nb()
69 const override {
70 return std::vector<std::shared_ptr<const C2Allocator::Traits>>(); /// \todo
71 }
72
73 virtual C2String getName() const override {
74 return "android.allocator-store";
75 }
76
77 void setComponentStore(std::shared_ptr<C2ComponentStore> store);
78
79 ~C2PlatformAllocatorStoreImpl() override = default;
80
81private:
Pin-chih Linaa18ea52019-11-19 18:48:50 +080082 /// returns a shared-singleton blob allocator (gralloc-backed)
83 std::shared_ptr<C2Allocator> fetchBlobAllocator();
84
Pawin Vongmasa36653902018-11-15 00:10:25 -080085 /// returns a shared-singleton ion allocator
86 std::shared_ptr<C2Allocator> fetchIonAllocator();
John Stultza7002cb2020-09-04 19:02:30 +000087 std::shared_ptr<C2Allocator> fetchDmaBufAllocator();
Pawin Vongmasa36653902018-11-15 00:10:25 -080088
89 /// returns a shared-singleton gralloc allocator
90 std::shared_ptr<C2Allocator> fetchGrallocAllocator();
91
92 /// returns a shared-singleton bufferqueue supporting gralloc allocator
93 std::shared_ptr<C2Allocator> fetchBufferQueueAllocator();
94
95 /// component store to use
96 std::mutex _mComponentStoreSetLock; // protects the entire updating _mComponentStore and its
97 // dependencies
98 std::mutex _mComponentStoreReadLock; // must protect only read/write of _mComponentStore
99 std::shared_ptr<C2ComponentStore> _mComponentStore;
100};
101
102C2PlatformAllocatorStoreImpl::C2PlatformAllocatorStoreImpl() {
103}
104
John Stultza7002cb2020-09-04 19:02:30 +0000105static bool using_ion(void) {
John Stultz3a069352021-01-09 04:11:10 +0000106 static int cached_result = []()->int {
John Stultza7002cb2020-09-04 19:02:30 +0000107 struct stat buffer;
John Stultz3a069352021-01-09 04:11:10 +0000108 int ret = (stat("/dev/ion", &buffer) == 0);
109
110 if (property_get_int32("debug.c2.use_dmabufheaps", 0)) {
111 /*
112 * Double check that the system heap is present so we
113 * can gracefully fail back to ION if we cannot satisfy
114 * the override
115 */
116 ret = (stat("/dev/dma_heap/system", &buffer) != 0);
117 if (ret)
118 ALOGE("debug.c2.use_dmabufheaps set, but no system heap. Ignoring override!");
119 else
120 ALOGD("debug.c2.use_dmabufheaps set, forcing DMABUF Heaps");
121 }
122
123 if (ret)
John Stultza7002cb2020-09-04 19:02:30 +0000124 ALOGD("Using ION\n");
125 else
126 ALOGD("Using DMABUF Heaps\n");
John Stultz3a069352021-01-09 04:11:10 +0000127 return ret;
128 }();
129
John Stultza7002cb2020-09-04 19:02:30 +0000130 return (cached_result == 1);
131}
132
Pawin Vongmasa36653902018-11-15 00:10:25 -0800133c2_status_t C2PlatformAllocatorStoreImpl::fetchAllocator(
134 id_t id, std::shared_ptr<C2Allocator> *const allocator) {
135 allocator->reset();
Pin-chih Linaa18ea52019-11-19 18:48:50 +0800136 if (id == C2AllocatorStore::DEFAULT_LINEAR) {
137 id = GetPreferredLinearAllocatorId(GetCodec2PoolMask());
138 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800139 switch (id) {
140 // TODO: should we implement a generic registry for all, and use that?
John Stultza7002cb2020-09-04 19:02:30 +0000141 case C2PlatformAllocatorStore::ION: /* also ::DMABUFHEAP */
142 if (using_ion())
143 *allocator = fetchIonAllocator();
144 else
145 *allocator = fetchDmaBufAllocator();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800146 break;
147
148 case C2PlatformAllocatorStore::GRALLOC:
149 case C2AllocatorStore::DEFAULT_GRAPHIC:
150 *allocator = fetchGrallocAllocator();
151 break;
152
153 case C2PlatformAllocatorStore::BUFFERQUEUE:
154 *allocator = fetchBufferQueueAllocator();
155 break;
156
Pin-chih Linaa18ea52019-11-19 18:48:50 +0800157 case C2PlatformAllocatorStore::BLOB:
158 *allocator = fetchBlobAllocator();
159 break;
160
Pawin Vongmasa36653902018-11-15 00:10:25 -0800161 default:
162 // Try to create allocator from platform store plugins.
163 c2_status_t res =
164 C2PlatformStorePluginLoader::GetInstance()->createAllocator(id, allocator);
165 if (res != C2_OK) {
166 return res;
167 }
168 break;
169 }
170 if (*allocator == nullptr) {
171 return C2_NO_MEMORY;
172 }
173 return C2_OK;
174}
175
176namespace {
177
178std::mutex gIonAllocatorMutex;
John Stultza7002cb2020-09-04 19:02:30 +0000179std::mutex gDmaBufAllocatorMutex;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800180std::weak_ptr<C2AllocatorIon> gIonAllocator;
John Stultza7002cb2020-09-04 19:02:30 +0000181std::weak_ptr<C2DmaBufAllocator> gDmaBufAllocator;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800182
183void UseComponentStoreForIonAllocator(
184 const std::shared_ptr<C2AllocatorIon> allocator,
185 std::shared_ptr<C2ComponentStore> store) {
186 C2AllocatorIon::UsageMapperFn mapper;
187 uint64_t minUsage = 0;
188 uint64_t maxUsage = C2MemoryUsage(C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE).expected;
189 size_t blockSize = getpagesize();
190
191 // query min and max usage as well as block size via supported values
192 C2StoreIonUsageInfo usageInfo;
193 std::vector<C2FieldSupportedValuesQuery> query = {
194 C2FieldSupportedValuesQuery::Possible(C2ParamField::Make(usageInfo, usageInfo.usage)),
195 C2FieldSupportedValuesQuery::Possible(C2ParamField::Make(usageInfo, usageInfo.capacity)),
196 };
197 c2_status_t res = store->querySupportedValues_sm(query);
198 if (res == C2_OK) {
199 if (query[0].status == C2_OK) {
200 const C2FieldSupportedValues &fsv = query[0].values;
201 if (fsv.type == C2FieldSupportedValues::FLAGS && !fsv.values.empty()) {
202 minUsage = fsv.values[0].u64;
203 maxUsage = 0;
204 for (C2Value::Primitive v : fsv.values) {
205 maxUsage |= v.u64;
206 }
207 }
208 }
209 if (query[1].status == C2_OK) {
210 const C2FieldSupportedValues &fsv = query[1].values;
211 if (fsv.type == C2FieldSupportedValues::RANGE && fsv.range.step.u32 > 0) {
212 blockSize = fsv.range.step.u32;
213 }
214 }
215
216 mapper = [store](C2MemoryUsage usage, size_t capacity,
217 size_t *align, unsigned *heapMask, unsigned *flags) -> c2_status_t {
218 if (capacity > UINT32_MAX) {
219 return C2_BAD_VALUE;
220 }
221 C2StoreIonUsageInfo usageInfo = { usage.expected, capacity };
222 std::vector<std::unique_ptr<C2SettingResult>> failures; // TODO: remove
223 c2_status_t res = store->config_sm({&usageInfo}, &failures);
224 if (res == C2_OK) {
225 *align = usageInfo.minAlignment;
226 *heapMask = usageInfo.heapMask;
227 *flags = usageInfo.allocFlags;
228 }
229 return res;
230 };
231 }
232
233 allocator->setUsageMapper(mapper, minUsage, maxUsage, blockSize);
234}
235
John Stultza7002cb2020-09-04 19:02:30 +0000236void UseComponentStoreForDmaBufAllocator(const std::shared_ptr<C2DmaBufAllocator> allocator,
237 std::shared_ptr<C2ComponentStore> store) {
238 C2DmaBufAllocator::UsageMapperFn mapper;
239 const size_t maxHeapNameLen = 128;
240 uint64_t minUsage = 0;
241 uint64_t maxUsage = C2MemoryUsage(C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE).expected;
242 size_t blockSize = getpagesize();
243
244 // query min and max usage as well as block size via supported values
245 std::unique_ptr<C2StoreDmaBufUsageInfo> usageInfo;
246 usageInfo = C2StoreDmaBufUsageInfo::AllocUnique(maxHeapNameLen);
247
248 std::vector<C2FieldSupportedValuesQuery> query = {
249 C2FieldSupportedValuesQuery::Possible(C2ParamField::Make(*usageInfo, usageInfo->m.usage)),
250 C2FieldSupportedValuesQuery::Possible(
251 C2ParamField::Make(*usageInfo, usageInfo->m.capacity)),
252 };
253 c2_status_t res = store->querySupportedValues_sm(query);
254 if (res == C2_OK) {
255 if (query[0].status == C2_OK) {
256 const C2FieldSupportedValues& fsv = query[0].values;
257 if (fsv.type == C2FieldSupportedValues::FLAGS && !fsv.values.empty()) {
258 minUsage = fsv.values[0].u64;
259 maxUsage = 0;
260 for (C2Value::Primitive v : fsv.values) {
261 maxUsage |= v.u64;
262 }
263 }
264 }
265 if (query[1].status == C2_OK) {
266 const C2FieldSupportedValues& fsv = query[1].values;
267 if (fsv.type == C2FieldSupportedValues::RANGE && fsv.range.step.u32 > 0) {
268 blockSize = fsv.range.step.u32;
269 }
270 }
271
272 mapper = [store](C2MemoryUsage usage, size_t capacity, C2String* heapName,
273 unsigned* flags) -> c2_status_t {
274 if (capacity > UINT32_MAX) {
275 return C2_BAD_VALUE;
276 }
277
278 std::unique_ptr<C2StoreDmaBufUsageInfo> usageInfo;
279 usageInfo = C2StoreDmaBufUsageInfo::AllocUnique(maxHeapNameLen, usage.expected, capacity);
280 std::vector<std::unique_ptr<C2SettingResult>> failures; // TODO: remove
281
282 c2_status_t res = store->config_sm({&*usageInfo}, &failures);
283 if (res == C2_OK) {
284 *heapName = C2String(usageInfo->m.heapName);
285 *flags = usageInfo->m.allocFlags;
286 }
287
288 return res;
289 };
290 }
291
292 allocator->setUsageMapper(mapper, minUsage, maxUsage, blockSize);
293}
294
Pawin Vongmasa36653902018-11-15 00:10:25 -0800295}
296
297void C2PlatformAllocatorStoreImpl::setComponentStore(std::shared_ptr<C2ComponentStore> store) {
298 // technically this set lock is not needed, but is here for safety in case we add more
299 // getter orders
300 std::lock_guard<std::mutex> lock(_mComponentStoreSetLock);
301 {
302 std::lock_guard<std::mutex> lock(_mComponentStoreReadLock);
303 _mComponentStore = store;
304 }
Sungtak Lee32429192022-01-07 15:18:51 -0800305 std::shared_ptr<C2AllocatorIon> ionAllocator;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800306 {
307 std::lock_guard<std::mutex> lock(gIonAllocatorMutex);
Sungtak Lee32429192022-01-07 15:18:51 -0800308 ionAllocator = gIonAllocator.lock();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800309 }
Sungtak Lee32429192022-01-07 15:18:51 -0800310 if (ionAllocator) {
311 UseComponentStoreForIonAllocator(ionAllocator, store);
312 }
313 std::shared_ptr<C2DmaBufAllocator> dmaAllocator;
314 {
315 std::lock_guard<std::mutex> lock(gDmaBufAllocatorMutex);
316 dmaAllocator = gDmaBufAllocator.lock();
317 }
318 if (dmaAllocator) {
319 UseComponentStoreForDmaBufAllocator(dmaAllocator, store);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800320 }
321}
322
323std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchIonAllocator() {
324 std::lock_guard<std::mutex> lock(gIonAllocatorMutex);
325 std::shared_ptr<C2AllocatorIon> allocator = gIonAllocator.lock();
326 if (allocator == nullptr) {
327 std::shared_ptr<C2ComponentStore> componentStore;
328 {
329 std::lock_guard<std::mutex> lock(_mComponentStoreReadLock);
330 componentStore = _mComponentStore;
331 }
332 allocator = std::make_shared<C2AllocatorIon>(C2PlatformAllocatorStore::ION);
333 UseComponentStoreForIonAllocator(allocator, componentStore);
334 gIonAllocator = allocator;
335 }
336 return allocator;
337}
338
John Stultza7002cb2020-09-04 19:02:30 +0000339std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchDmaBufAllocator() {
340 std::lock_guard<std::mutex> lock(gDmaBufAllocatorMutex);
341 std::shared_ptr<C2DmaBufAllocator> allocator = gDmaBufAllocator.lock();
342 if (allocator == nullptr) {
343 std::shared_ptr<C2ComponentStore> componentStore;
344 {
345 std::lock_guard<std::mutex> lock(_mComponentStoreReadLock);
346 componentStore = _mComponentStore;
347 }
348 allocator = std::make_shared<C2DmaBufAllocator>(C2PlatformAllocatorStore::DMABUFHEAP);
349 UseComponentStoreForDmaBufAllocator(allocator, componentStore);
350 gDmaBufAllocator = allocator;
351 }
352 return allocator;
353}
354
Pin-chih Linaa18ea52019-11-19 18:48:50 +0800355std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchBlobAllocator() {
356 static std::mutex mutex;
357 static std::weak_ptr<C2Allocator> blobAllocator;
358 std::lock_guard<std::mutex> lock(mutex);
359 std::shared_ptr<C2Allocator> allocator = blobAllocator.lock();
360 if (allocator == nullptr) {
361 allocator = std::make_shared<C2AllocatorBlob>(C2PlatformAllocatorStore::BLOB);
362 blobAllocator = allocator;
363 }
364 return allocator;
365}
366
Pawin Vongmasa36653902018-11-15 00:10:25 -0800367std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchGrallocAllocator() {
368 static std::mutex mutex;
369 static std::weak_ptr<C2Allocator> grallocAllocator;
370 std::lock_guard<std::mutex> lock(mutex);
371 std::shared_ptr<C2Allocator> allocator = grallocAllocator.lock();
372 if (allocator == nullptr) {
373 allocator = std::make_shared<C2AllocatorGralloc>(C2PlatformAllocatorStore::GRALLOC);
374 grallocAllocator = allocator;
375 }
376 return allocator;
377}
378
379std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchBufferQueueAllocator() {
380 static std::mutex mutex;
381 static std::weak_ptr<C2Allocator> grallocAllocator;
382 std::lock_guard<std::mutex> lock(mutex);
383 std::shared_ptr<C2Allocator> allocator = grallocAllocator.lock();
384 if (allocator == nullptr) {
385 allocator = std::make_shared<C2AllocatorGralloc>(
386 C2PlatformAllocatorStore::BUFFERQUEUE, true);
387 grallocAllocator = allocator;
388 }
389 return allocator;
390}
391
392namespace {
393 std::mutex gPreferredComponentStoreMutex;
394 std::shared_ptr<C2ComponentStore> gPreferredComponentStore;
395
396 std::mutex gPlatformAllocatorStoreMutex;
397 std::weak_ptr<C2PlatformAllocatorStoreImpl> gPlatformAllocatorStore;
398}
399
400std::shared_ptr<C2AllocatorStore> GetCodec2PlatformAllocatorStore() {
401 std::lock_guard<std::mutex> lock(gPlatformAllocatorStoreMutex);
402 std::shared_ptr<C2PlatformAllocatorStoreImpl> store = gPlatformAllocatorStore.lock();
403 if (store == nullptr) {
404 store = std::make_shared<C2PlatformAllocatorStoreImpl>();
405 store->setComponentStore(GetPreferredCodec2ComponentStore());
406 gPlatformAllocatorStore = store;
407 }
408 return store;
409}
410
411void SetPreferredCodec2ComponentStore(std::shared_ptr<C2ComponentStore> componentStore) {
412 static std::mutex mutex;
413 std::lock_guard<std::mutex> lock(mutex); // don't interleve set-s
414
415 // update preferred store
416 {
417 std::lock_guard<std::mutex> lock(gPreferredComponentStoreMutex);
418 gPreferredComponentStore = componentStore;
419 }
420
421 // update platform allocator's store as well if it is alive
422 std::shared_ptr<C2PlatformAllocatorStoreImpl> allocatorStore;
423 {
424 std::lock_guard<std::mutex> lock(gPlatformAllocatorStoreMutex);
425 allocatorStore = gPlatformAllocatorStore.lock();
426 }
427 if (allocatorStore) {
428 allocatorStore->setComponentStore(componentStore);
429 }
430}
431
432std::shared_ptr<C2ComponentStore> GetPreferredCodec2ComponentStore() {
433 std::lock_guard<std::mutex> lock(gPreferredComponentStoreMutex);
434 return gPreferredComponentStore ? gPreferredComponentStore : GetCodec2PlatformComponentStore();
435}
436
Pin-chih Linaa18ea52019-11-19 18:48:50 +0800437int GetCodec2PoolMask() {
438 return property_get_int32(
439 "debug.stagefright.c2-poolmask",
440 1 << C2PlatformAllocatorStore::ION |
441 1 << C2PlatformAllocatorStore::BUFFERQUEUE);
442}
443
444C2PlatformAllocatorStore::id_t GetPreferredLinearAllocatorId(int poolMask) {
445 return ((poolMask >> C2PlatformAllocatorStore::BLOB) & 1) ? C2PlatformAllocatorStore::BLOB
446 : C2PlatformAllocatorStore::ION;
447}
448
Pawin Vongmasa36653902018-11-15 00:10:25 -0800449namespace {
450
Wonsik Kim0560d602023-11-15 10:08:21 -0800451static C2PooledBlockPool::BufferPoolVer GetBufferPoolVer() {
452 static C2PooledBlockPool::BufferPoolVer sVer =
453 IsCodec2AidlHalSelected() ? C2PooledBlockPool::VER_AIDL2 : C2PooledBlockPool::VER_HIDL;
454 return sVer;
455}
456
Pawin Vongmasa36653902018-11-15 00:10:25 -0800457class _C2BlockPoolCache {
458public:
459 _C2BlockPoolCache() : mBlockPoolSeqId(C2BlockPool::PLATFORM_START + 1) {}
460
Wonsik Kim17911e32021-08-26 13:57:02 -0700461private:
Pawin Vongmasa36653902018-11-15 00:10:25 -0800462 c2_status_t _createBlockPool(
463 C2PlatformAllocatorStore::id_t allocatorId,
Wonsik Kim2fce07922021-02-11 00:16:11 -0800464 std::vector<std::shared_ptr<const C2Component>> components,
Pawin Vongmasa36653902018-11-15 00:10:25 -0800465 C2BlockPool::local_id_t poolId,
466 std::shared_ptr<C2BlockPool> *pool) {
467 std::shared_ptr<C2AllocatorStore> allocatorStore =
468 GetCodec2PlatformAllocatorStore();
469 std::shared_ptr<C2Allocator> allocator;
470 c2_status_t res = C2_NOT_FOUND;
471
Pin-chih Linaa18ea52019-11-19 18:48:50 +0800472 if (allocatorId == C2AllocatorStore::DEFAULT_LINEAR) {
473 allocatorId = GetPreferredLinearAllocatorId(GetCodec2PoolMask());
474 }
Wonsik Kim17911e32021-08-26 13:57:02 -0700475 auto deleter = [this, poolId](C2BlockPool *pool) {
476 std::unique_lock lock(mMutex);
477 mBlockPools.erase(poolId);
478 mComponents.erase(poolId);
479 delete pool;
480 };
Pawin Vongmasa36653902018-11-15 00:10:25 -0800481 switch(allocatorId) {
John Stultza7002cb2020-09-04 19:02:30 +0000482 case C2PlatformAllocatorStore::ION: /* also ::DMABUFHEAP */
Pawin Vongmasa36653902018-11-15 00:10:25 -0800483 res = allocatorStore->fetchAllocator(
Pin-chih Linaa18ea52019-11-19 18:48:50 +0800484 C2PlatformAllocatorStore::ION, &allocator);
485 if (res == C2_OK) {
Wonsik Kim17911e32021-08-26 13:57:02 -0700486 std::shared_ptr<C2BlockPool> ptr(
Wonsik Kim0560d602023-11-15 10:08:21 -0800487 new C2PooledBlockPool(allocator, poolId, GetBufferPoolVer()), deleter);
Pin-chih Linaa18ea52019-11-19 18:48:50 +0800488 *pool = ptr;
489 mBlockPools[poolId] = ptr;
Wonsik Kim2fce07922021-02-11 00:16:11 -0800490 mComponents[poolId].insert(
491 mComponents[poolId].end(),
492 components.begin(), components.end());
Pin-chih Linaa18ea52019-11-19 18:48:50 +0800493 }
494 break;
495 case C2PlatformAllocatorStore::BLOB:
496 res = allocatorStore->fetchAllocator(
497 C2PlatformAllocatorStore::BLOB, &allocator);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800498 if (res == C2_OK) {
Wonsik Kim17911e32021-08-26 13:57:02 -0700499 std::shared_ptr<C2BlockPool> ptr(
Wonsik Kim0560d602023-11-15 10:08:21 -0800500 new C2PooledBlockPool(allocator, poolId, GetBufferPoolVer()), deleter);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800501 *pool = ptr;
502 mBlockPools[poolId] = ptr;
Wonsik Kim2fce07922021-02-11 00:16:11 -0800503 mComponents[poolId].insert(
504 mComponents[poolId].end(),
505 components.begin(), components.end());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800506 }
507 break;
508 case C2PlatformAllocatorStore::GRALLOC:
509 case C2AllocatorStore::DEFAULT_GRAPHIC:
510 res = allocatorStore->fetchAllocator(
511 C2AllocatorStore::DEFAULT_GRAPHIC, &allocator);
512 if (res == C2_OK) {
Wonsik Kim17911e32021-08-26 13:57:02 -0700513 std::shared_ptr<C2BlockPool> ptr(
Wonsik Kim0560d602023-11-15 10:08:21 -0800514 new C2PooledBlockPool(allocator, poolId, GetBufferPoolVer()), deleter);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800515 *pool = ptr;
516 mBlockPools[poolId] = ptr;
Wonsik Kim2fce07922021-02-11 00:16:11 -0800517 mComponents[poolId].insert(
518 mComponents[poolId].end(),
519 components.begin(), components.end());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800520 }
521 break;
522 case C2PlatformAllocatorStore::BUFFERQUEUE:
523 res = allocatorStore->fetchAllocator(
524 C2PlatformAllocatorStore::BUFFERQUEUE, &allocator);
525 if (res == C2_OK) {
Wonsik Kim17911e32021-08-26 13:57:02 -0700526 std::shared_ptr<C2BlockPool> ptr(
527 new C2BufferQueueBlockPool(allocator, poolId), deleter);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800528 *pool = ptr;
529 mBlockPools[poolId] = ptr;
Wonsik Kim2fce07922021-02-11 00:16:11 -0800530 mComponents[poolId].insert(
531 mComponents[poolId].end(),
532 components.begin(), components.end());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800533 }
534 break;
535 default:
536 // Try to create block pool from platform store plugins.
537 std::shared_ptr<C2BlockPool> ptr;
538 res = C2PlatformStorePluginLoader::GetInstance()->createBlockPool(
Wonsik Kim17911e32021-08-26 13:57:02 -0700539 allocatorId, poolId, &ptr, deleter);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800540 if (res == C2_OK) {
541 *pool = ptr;
542 mBlockPools[poolId] = ptr;
Wonsik Kim2fce07922021-02-11 00:16:11 -0800543 mComponents[poolId].insert(
544 mComponents[poolId].end(),
545 components.begin(), components.end());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800546 }
547 break;
548 }
549 return res;
550 }
551
Wonsik Kim17911e32021-08-26 13:57:02 -0700552public:
Pawin Vongmasa36653902018-11-15 00:10:25 -0800553 c2_status_t createBlockPool(
554 C2PlatformAllocatorStore::id_t allocatorId,
Wonsik Kim2fce07922021-02-11 00:16:11 -0800555 std::vector<std::shared_ptr<const C2Component>> components,
Pawin Vongmasa36653902018-11-15 00:10:25 -0800556 std::shared_ptr<C2BlockPool> *pool) {
Wonsik Kim17911e32021-08-26 13:57:02 -0700557 std::unique_lock lock(mMutex);
Wonsik Kim2fce07922021-02-11 00:16:11 -0800558 return _createBlockPool(allocatorId, components, mBlockPoolSeqId++, pool);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800559 }
560
Wonsik Kim17911e32021-08-26 13:57:02 -0700561 c2_status_t getBlockPool(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800562 C2BlockPool::local_id_t blockPoolId,
563 std::shared_ptr<const C2Component> component,
564 std::shared_ptr<C2BlockPool> *pool) {
Wonsik Kim17911e32021-08-26 13:57:02 -0700565 std::unique_lock lock(mMutex);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800566 // TODO: use one iterator for multiple blockpool type scalability.
567 std::shared_ptr<C2BlockPool> ptr;
568 auto it = mBlockPools.find(blockPoolId);
569 if (it != mBlockPools.end()) {
570 ptr = it->second.lock();
571 if (!ptr) {
572 mBlockPools.erase(it);
573 mComponents.erase(blockPoolId);
574 } else {
Wonsik Kim2fce07922021-02-11 00:16:11 -0800575 auto found = std::find_if(
576 mComponents[blockPoolId].begin(),
577 mComponents[blockPoolId].end(),
578 [component](const std::weak_ptr<const C2Component> &ptr) {
579 return component == ptr.lock();
580 });
581 if (found != mComponents[blockPoolId].end()) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800582 *pool = ptr;
Wonsik Kim17911e32021-08-26 13:57:02 -0700583 return C2_OK;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800584 }
585 }
586 }
Wonsik Kim17911e32021-08-26 13:57:02 -0700587 // TODO: remove this. this is temporary
588 if (blockPoolId == C2BlockPool::PLATFORM_START) {
589 return _createBlockPool(
590 C2PlatformAllocatorStore::BUFFERQUEUE, {component}, blockPoolId, pool);
591 }
592 return C2_NOT_FOUND;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800593 }
594
595private:
Wonsik Kim17911e32021-08-26 13:57:02 -0700596 // Deleter needs to hold this mutex, and there is a small chance that deleter
597 // is invoked while the mutex is held.
598 std::recursive_mutex mMutex;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800599 C2BlockPool::local_id_t mBlockPoolSeqId;
600
601 std::map<C2BlockPool::local_id_t, std::weak_ptr<C2BlockPool>> mBlockPools;
Wonsik Kim2fce07922021-02-11 00:16:11 -0800602 std::map<C2BlockPool::local_id_t, std::vector<std::weak_ptr<const C2Component>>> mComponents;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800603};
604
605static std::unique_ptr<_C2BlockPoolCache> sBlockPoolCache =
606 std::make_unique<_C2BlockPoolCache>();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800607
608} // anynymous namespace
609
610c2_status_t GetCodec2BlockPool(
611 C2BlockPool::local_id_t id, std::shared_ptr<const C2Component> component,
612 std::shared_ptr<C2BlockPool> *pool) {
613 pool->reset();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800614 std::shared_ptr<C2AllocatorStore> allocatorStore = GetCodec2PlatformAllocatorStore();
615 std::shared_ptr<C2Allocator> allocator;
616 c2_status_t res = C2_NOT_FOUND;
617
618 if (id >= C2BlockPool::PLATFORM_START) {
Wonsik Kim17911e32021-08-26 13:57:02 -0700619 return sBlockPoolCache->getBlockPool(id, component, pool);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800620 }
621
622 switch (id) {
623 case C2BlockPool::BASIC_LINEAR:
624 res = allocatorStore->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &allocator);
625 if (res == C2_OK) {
626 *pool = std::make_shared<C2BasicLinearBlockPool>(allocator);
627 }
628 break;
629 case C2BlockPool::BASIC_GRAPHIC:
630 res = allocatorStore->fetchAllocator(C2AllocatorStore::DEFAULT_GRAPHIC, &allocator);
631 if (res == C2_OK) {
632 *pool = std::make_shared<C2BasicGraphicBlockPool>(allocator);
633 }
634 break;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800635 default:
636 break;
637 }
638 return res;
639}
640
641c2_status_t CreateCodec2BlockPool(
642 C2PlatformAllocatorStore::id_t allocatorId,
Wonsik Kim2fce07922021-02-11 00:16:11 -0800643 const std::vector<std::shared_ptr<const C2Component>> &components,
644 std::shared_ptr<C2BlockPool> *pool) {
645 pool->reset();
646
Wonsik Kim2fce07922021-02-11 00:16:11 -0800647 return sBlockPoolCache->createBlockPool(allocatorId, components, pool);
648}
649
650c2_status_t CreateCodec2BlockPool(
651 C2PlatformAllocatorStore::id_t allocatorId,
Pawin Vongmasa36653902018-11-15 00:10:25 -0800652 std::shared_ptr<const C2Component> component,
653 std::shared_ptr<C2BlockPool> *pool) {
654 pool->reset();
655
Wonsik Kim2fce07922021-02-11 00:16:11 -0800656 return sBlockPoolCache->createBlockPool(allocatorId, {component}, pool);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800657}
658
659class C2PlatformComponentStore : public C2ComponentStore {
660public:
661 virtual std::vector<std::shared_ptr<const C2Component::Traits>> listComponents() override;
662 virtual std::shared_ptr<C2ParamReflector> getParamReflector() const override;
663 virtual C2String getName() const override;
664 virtual c2_status_t querySupportedValues_sm(
665 std::vector<C2FieldSupportedValuesQuery> &fields) const override;
666 virtual c2_status_t querySupportedParams_nb(
667 std::vector<std::shared_ptr<C2ParamDescriptor>> *const params) const override;
668 virtual c2_status_t query_sm(
669 const std::vector<C2Param*> &stackParams,
670 const std::vector<C2Param::Index> &heapParamIndices,
671 std::vector<std::unique_ptr<C2Param>> *const heapParams) const override;
672 virtual c2_status_t createInterface(
673 C2String name, std::shared_ptr<C2ComponentInterface> *const interface) override;
674 virtual c2_status_t createComponent(
675 C2String name, std::shared_ptr<C2Component> *const component) override;
676 virtual c2_status_t copyBuffer(
677 std::shared_ptr<C2GraphicBuffer> src, std::shared_ptr<C2GraphicBuffer> dst) override;
678 virtual c2_status_t config_sm(
679 const std::vector<C2Param*> &params,
680 std::vector<std::unique_ptr<C2SettingResult>> *const failures) override;
681 C2PlatformComponentStore();
682
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530683 // For testing only
684 C2PlatformComponentStore(
685 std::vector<std::tuple<C2String,
686 C2ComponentFactory::CreateCodec2FactoryFunc,
687 C2ComponentFactory::DestroyCodec2FactoryFunc>>);
688
Pawin Vongmasa36653902018-11-15 00:10:25 -0800689 virtual ~C2PlatformComponentStore() override = default;
690
691private:
692
693 /**
694 * An object encapsulating a loaded component module.
695 *
696 * \todo provide a way to add traits to known components here to avoid loading the .so-s
697 * for listComponents
698 */
699 struct ComponentModule : public C2ComponentFactory,
700 public std::enable_shared_from_this<ComponentModule> {
701 virtual c2_status_t createComponent(
702 c2_node_id_t id, std::shared_ptr<C2Component> *component,
703 ComponentDeleter deleter = std::default_delete<C2Component>()) override;
704 virtual c2_status_t createInterface(
705 c2_node_id_t id, std::shared_ptr<C2ComponentInterface> *interface,
706 InterfaceDeleter deleter = std::default_delete<C2ComponentInterface>()) override;
707
708 /**
709 * \returns the traits of the component in this module.
710 */
711 std::shared_ptr<const C2Component::Traits> getTraits();
712
713 /**
714 * Creates an uninitialized component module.
715 *
716 * \param name[in] component name.
717 *
718 * \note Only used by ComponentLoader.
719 */
720 ComponentModule()
721 : mInit(C2_NO_INIT),
722 mLibHandle(nullptr),
723 createFactory(nullptr),
724 destroyFactory(nullptr),
725 mComponentFactory(nullptr) {
726 }
727
728 /**
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530729 * Creates an uninitialized component module.
730 * NOTE: For testing only
731 *
732 * \param name[in] component name.
733 *
734 * \note Only used by ComponentLoader.
735 */
736 ComponentModule(
737 C2ComponentFactory::CreateCodec2FactoryFunc createFactory,
738 C2ComponentFactory::DestroyCodec2FactoryFunc destroyFactory)
739 : mInit(C2_NO_INIT),
740 mLibHandle(nullptr),
741 createFactory(createFactory),
742 destroyFactory(destroyFactory),
743 mComponentFactory(nullptr) {
744 }
745
746 /**
Pawin Vongmasa36653902018-11-15 00:10:25 -0800747 * Initializes a component module with a given library path. Must be called exactly once.
748 *
749 * \note Only used by ComponentLoader.
750 *
Pawin Vongmasa36653902018-11-15 00:10:25 -0800751 * \param libPath[in] library path
752 *
753 * \retval C2_OK the component module has been successfully loaded
754 * \retval C2_NO_MEMORY not enough memory to loading the component module
755 * \retval C2_NOT_FOUND could not locate the component module
756 * \retval C2_CORRUPTED the component module could not be loaded (unexpected)
757 * \retval C2_REFUSED permission denied to load the component module (unexpected)
758 * \retval C2_TIMED_OUT could not load the module within the time limit (unexpected)
759 */
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800760 c2_status_t init(std::string libPath);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800761
762 virtual ~ComponentModule() override;
763
764 protected:
765 std::recursive_mutex mLock; ///< lock protecting mTraits
766 std::shared_ptr<C2Component::Traits> mTraits; ///< cached component traits
767
768 c2_status_t mInit; ///< initialization result
769
770 void *mLibHandle; ///< loaded library handle
771 C2ComponentFactory::CreateCodec2FactoryFunc createFactory; ///< loaded create function
772 C2ComponentFactory::DestroyCodec2FactoryFunc destroyFactory; ///< loaded destroy function
773 C2ComponentFactory *mComponentFactory; ///< loaded/created component factory
774 };
775
776 /**
777 * An object encapsulating a loadable component module.
778 *
779 * \todo make this also work for enumerations
780 */
781 struct ComponentLoader {
782 /**
783 * Load the component module.
784 *
785 * This method simply returns the component module if it is already currently loaded, or
786 * attempts to load it if it is not.
787 *
788 * \param module[out] pointer to the shared pointer where the loaded module shall be stored.
789 * This will be nullptr on error.
790 *
791 * \retval C2_OK the component module has been successfully loaded
792 * \retval C2_NO_MEMORY not enough memory to loading the component module
793 * \retval C2_NOT_FOUND could not locate the component module
794 * \retval C2_CORRUPTED the component module could not be loaded
795 * \retval C2_REFUSED permission denied to load the component module
796 */
797 c2_status_t fetchModule(std::shared_ptr<ComponentModule> *module) {
798 c2_status_t res = C2_OK;
799 std::lock_guard<std::mutex> lock(mMutex);
800 std::shared_ptr<ComponentModule> localModule = mModule.lock();
801 if (localModule == nullptr) {
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530802 if(mCreateFactory) {
803 // For testing only
804 localModule = std::make_shared<ComponentModule>(mCreateFactory,
805 mDestroyFactory);
806 } else {
807 localModule = std::make_shared<ComponentModule>();
808 }
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800809 res = localModule->init(mLibPath);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800810 if (res == C2_OK) {
811 mModule = localModule;
812 }
813 }
814 *module = localModule;
815 return res;
816 }
817
818 /**
819 * Creates a component loader for a specific library path (or name).
820 */
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800821 ComponentLoader(std::string libPath)
822 : mLibPath(libPath) {}
Pawin Vongmasa36653902018-11-15 00:10:25 -0800823
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530824 // For testing only
825 ComponentLoader(std::tuple<C2String,
826 C2ComponentFactory::CreateCodec2FactoryFunc,
827 C2ComponentFactory::DestroyCodec2FactoryFunc> func)
828 : mLibPath(std::get<0>(func)),
829 mCreateFactory(std::get<1>(func)),
830 mDestroyFactory(std::get<2>(func)) {}
831
Pawin Vongmasa36653902018-11-15 00:10:25 -0800832 private:
833 std::mutex mMutex; ///< mutex guarding the module
834 std::weak_ptr<ComponentModule> mModule; ///< weak reference to the loaded module
Pawin Vongmasa36653902018-11-15 00:10:25 -0800835 std::string mLibPath; ///< library path
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530836
837 // For testing only
838 C2ComponentFactory::CreateCodec2FactoryFunc mCreateFactory = nullptr;
839 C2ComponentFactory::DestroyCodec2FactoryFunc mDestroyFactory = nullptr;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800840 };
841
842 struct Interface : public C2InterfaceHelper {
843 std::shared_ptr<C2StoreIonUsageInfo> mIonUsageInfo;
John Stultza7002cb2020-09-04 19:02:30 +0000844 std::shared_ptr<C2StoreDmaBufUsageInfo> mDmaBufUsageInfo;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800845
846 Interface(std::shared_ptr<C2ReflectorHelper> reflector)
847 : C2InterfaceHelper(reflector) {
848 setDerivedInstance(this);
849
850 struct Setter {
851 static C2R setIonUsage(bool /* mayBlock */, C2P<C2StoreIonUsageInfo> &me) {
Wonsik Kimba3db192019-11-22 11:00:48 -0800852#ifdef __ANDROID_APEX__
853 static int32_t defaultHeapMask = [] {
854 int32_t heapmask = base::GetIntProperty(
855 "ro.com.android.media.swcodec.ion.heapmask", int32_t(0xFFFFFFFF));
856 ALOGD("Default ION heapmask = %d", heapmask);
857 return heapmask;
858 }();
859 static int32_t defaultFlags = [] {
860 int32_t flags = base::GetIntProperty(
861 "ro.com.android.media.swcodec.ion.flags", 0);
862 ALOGD("Default ION flags = %d", flags);
863 return flags;
864 }();
865 static uint32_t defaultAlign = [] {
866 uint32_t align = base::GetUintProperty(
867 "ro.com.android.media.swcodec.ion.align", 0u);
868 ALOGD("Default ION align = %d", align);
869 return align;
870 }();
871 me.set().heapMask = defaultHeapMask;
872 me.set().allocFlags = defaultFlags;
873 me.set().minAlignment = defaultAlign;
874#else
Pawin Vongmasa36653902018-11-15 00:10:25 -0800875 me.set().heapMask = ~0;
876 me.set().allocFlags = 0;
877 me.set().minAlignment = 0;
Wonsik Kimba3db192019-11-22 11:00:48 -0800878#endif
Pawin Vongmasa36653902018-11-15 00:10:25 -0800879 return C2R::Ok();
John Stultza7002cb2020-09-04 19:02:30 +0000880 };
881
882 static C2R setDmaBufUsage(bool /* mayBlock */, C2P<C2StoreDmaBufUsageInfo> &me) {
John Stultz9eda9bf2021-01-08 00:41:13 +0000883 long long usage = (long long)me.get().m.usage;
884 if (C2DmaBufAllocator::system_uncached_supported() &&
885 !(usage & (C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE))) {
886 strncpy(me.set().m.heapName, "system-uncached", me.v.flexCount());
887 } else {
888 strncpy(me.set().m.heapName, "system", me.v.flexCount());
889 }
John Stultza7002cb2020-09-04 19:02:30 +0000890 me.set().m.allocFlags = 0;
891 return C2R::Ok();
892 };
Pawin Vongmasa36653902018-11-15 00:10:25 -0800893 };
894
895 addParameter(
896 DefineParam(mIonUsageInfo, "ion-usage")
897 .withDefault(new C2StoreIonUsageInfo())
898 .withFields({
899 C2F(mIonUsageInfo, usage).flags({C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE}),
900 C2F(mIonUsageInfo, capacity).inRange(0, UINT32_MAX, 1024),
901 C2F(mIonUsageInfo, heapMask).any(),
902 C2F(mIonUsageInfo, allocFlags).flags({}),
903 C2F(mIonUsageInfo, minAlignment).equalTo(0)
904 })
905 .withSetter(Setter::setIonUsage)
906 .build());
John Stultza7002cb2020-09-04 19:02:30 +0000907
908 addParameter(
909 DefineParam(mDmaBufUsageInfo, "dmabuf-usage")
910 .withDefault(C2StoreDmaBufUsageInfo::AllocShared(0))
911 .withFields({
912 C2F(mDmaBufUsageInfo, m.usage).flags({C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE}),
913 C2F(mDmaBufUsageInfo, m.capacity).inRange(0, UINT32_MAX, 1024),
914 C2F(mDmaBufUsageInfo, m.allocFlags).flags({}),
915 C2F(mDmaBufUsageInfo, m.heapName).any(),
916 })
917 .withSetter(Setter::setDmaBufUsage)
918 .build());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800919 }
920 };
921
922 /**
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800923 * Retrieves the component module for a component.
Pawin Vongmasa36653902018-11-15 00:10:25 -0800924 *
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800925 * \param module pointer to a shared_pointer where the component module will be stored on
926 * success.
Pawin Vongmasa36653902018-11-15 00:10:25 -0800927 *
928 * \retval C2_OK the component loader has been successfully retrieved
929 * \retval C2_NO_MEMORY not enough memory to locate the component loader
930 * \retval C2_NOT_FOUND could not locate the component to be loaded
931 * \retval C2_CORRUPTED the component loader could not be identified due to some modules being
932 * corrupted (this can happen if the name does not refer to an already
933 * identified component but some components could not be loaded due to
934 * bad library)
935 * \retval C2_REFUSED permission denied to find the component loader for the named component
936 * (this can happen if the name does not refer to an already identified
937 * component but some components could not be loaded due to lack of
938 * permissions)
939 */
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800940 c2_status_t findComponent(C2String name, std::shared_ptr<ComponentModule> *module);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800941
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800942 /**
943 * Loads each component module and discover its contents.
944 */
945 void visitComponents();
946
947 std::mutex mMutex; ///< mutex guarding the component lists during construction
948 bool mVisited; ///< component modules visited
949 std::map<C2String, ComponentLoader> mComponents; ///< path -> component module
950 std::map<C2String, C2String> mComponentNameToPath; ///< name -> path
951 std::vector<std::shared_ptr<const C2Component::Traits>> mComponentList;
952
Pawin Vongmasa36653902018-11-15 00:10:25 -0800953 std::shared_ptr<C2ReflectorHelper> mReflector;
954 Interface mInterface;
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530955
956 // For testing only
957 std::vector<std::tuple<C2String,
958 C2ComponentFactory::CreateCodec2FactoryFunc,
959 C2ComponentFactory::DestroyCodec2FactoryFunc>> mCodec2FactoryFuncs;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800960};
961
962c2_status_t C2PlatformComponentStore::ComponentModule::init(
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800963 std::string libPath) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800964 ALOGV("in %s", __func__);
965 ALOGV("loading dll");
Pawin Vongmasa36653902018-11-15 00:10:25 -0800966
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530967 if(!createFactory) {
968 mLibHandle = dlopen(libPath.c_str(), RTLD_NOW|RTLD_NODELETE);
969 LOG_ALWAYS_FATAL_IF(mLibHandle == nullptr,
970 "could not dlopen %s: %s", libPath.c_str(), dlerror());
Chong Zhangf5c7ca82019-04-23 17:06:21 -0700971
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530972 createFactory =
973 (C2ComponentFactory::CreateCodec2FactoryFunc)dlsym(mLibHandle, "CreateCodec2Factory");
974 LOG_ALWAYS_FATAL_IF(createFactory == nullptr,
975 "createFactory is null in %s", libPath.c_str());
976
977 destroyFactory =
978 (C2ComponentFactory::DestroyCodec2FactoryFunc)dlsym(mLibHandle, "DestroyCodec2Factory");
979 LOG_ALWAYS_FATAL_IF(destroyFactory == nullptr,
980 "destroyFactory is null in %s", libPath.c_str());
981 }
Chong Zhangf5c7ca82019-04-23 17:06:21 -0700982
983 mComponentFactory = createFactory();
984 if (mComponentFactory == nullptr) {
985 ALOGD("could not create factory in %s", libPath.c_str());
986 mInit = C2_NO_MEMORY;
Dongwon Kang673236b2019-05-08 09:02:21 -0700987 } else {
988 mInit = C2_OK;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800989 }
990
Dongwon Kang673236b2019-05-08 09:02:21 -0700991 if (mInit != C2_OK) {
992 return mInit;
993 }
Dongwon Kange55d13c2019-04-24 11:01:49 -0700994
Pawin Vongmasa36653902018-11-15 00:10:25 -0800995 std::shared_ptr<C2ComponentInterface> intf;
996 c2_status_t res = createInterface(0, &intf);
997 if (res != C2_OK) {
998 ALOGD("failed to create interface: %d", res);
999 return mInit;
1000 }
1001
1002 std::shared_ptr<C2Component::Traits> traits(new (std::nothrow) C2Component::Traits);
1003 if (traits) {
Wonsik Kimee92b522021-02-07 21:55:31 -08001004 if (!C2InterfaceUtils::FillTraitsFromInterface(traits.get(), intf)) {
1005 ALOGD("Failed to fill traits from interface");
Pawin Vongmasa36653902018-11-15 00:10:25 -08001006 return mInit;
1007 }
Lajos Molnar62d62d62019-01-31 16:26:46 -08001008
1009 // TODO: get this properly from the store during emplace
1010 switch (traits->domain) {
1011 case C2Component::DOMAIN_AUDIO:
1012 traits->rank = 8;
1013 break;
1014 default:
1015 traits->rank = 512;
1016 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001017 }
1018 mTraits = traits;
1019
1020 return mInit;
1021}
1022
1023C2PlatformComponentStore::ComponentModule::~ComponentModule() {
1024 ALOGV("in %s", __func__);
1025 if (destroyFactory && mComponentFactory) {
1026 destroyFactory(mComponentFactory);
1027 }
1028 if (mLibHandle) {
1029 ALOGV("unloading dll");
1030 dlclose(mLibHandle);
1031 }
1032}
1033
1034c2_status_t C2PlatformComponentStore::ComponentModule::createInterface(
1035 c2_node_id_t id, std::shared_ptr<C2ComponentInterface> *interface,
1036 std::function<void(::C2ComponentInterface*)> deleter) {
1037 interface->reset();
1038 if (mInit != C2_OK) {
1039 return mInit;
1040 }
1041 std::shared_ptr<ComponentModule> module = shared_from_this();
1042 c2_status_t res = mComponentFactory->createInterface(
1043 id, interface, [module, deleter](C2ComponentInterface *p) mutable {
1044 // capture module so that we ensure we still have it while deleting interface
1045 deleter(p); // delete interface first
1046 module.reset(); // remove module ref (not technically needed)
1047 });
1048 return res;
1049}
1050
1051c2_status_t C2PlatformComponentStore::ComponentModule::createComponent(
1052 c2_node_id_t id, std::shared_ptr<C2Component> *component,
1053 std::function<void(::C2Component*)> deleter) {
1054 component->reset();
1055 if (mInit != C2_OK) {
1056 return mInit;
1057 }
1058 std::shared_ptr<ComponentModule> module = shared_from_this();
1059 c2_status_t res = mComponentFactory->createComponent(
1060 id, component, [module, deleter](C2Component *p) mutable {
1061 // capture module so that we ensure we still have it while deleting component
1062 deleter(p); // delete component first
1063 module.reset(); // remove module ref (not technically needed)
1064 });
1065 return res;
1066}
1067
1068std::shared_ptr<const C2Component::Traits> C2PlatformComponentStore::ComponentModule::getTraits() {
1069 std::unique_lock<std::recursive_mutex> lock(mLock);
1070 return mTraits;
1071}
1072
1073C2PlatformComponentStore::C2PlatformComponentStore()
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001074 : mVisited(false),
1075 mReflector(std::make_shared<C2ReflectorHelper>()),
Pawin Vongmasa36653902018-11-15 00:10:25 -08001076 mInterface(mReflector) {
1077
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001078 auto emplace = [this](const char *libPath) {
1079 mComponents.emplace(libPath, libPath);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001080 };
Pawin Vongmasa36653902018-11-15 00:10:25 -08001081
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001082 // TODO: move this also into a .so so it can be updated
1083 emplace("libcodec2_soft_aacdec.so");
1084 emplace("libcodec2_soft_aacenc.so");
1085 emplace("libcodec2_soft_amrnbdec.so");
1086 emplace("libcodec2_soft_amrnbenc.so");
1087 emplace("libcodec2_soft_amrwbdec.so");
1088 emplace("libcodec2_soft_amrwbenc.so");
Ray Essickc2cc4372019-08-21 14:02:28 -07001089 //emplace("libcodec2_soft_av1dec_aom.so"); // deprecated for the gav1 implementation
1090 emplace("libcodec2_soft_av1dec_gav1.so");
Harish Mahendrakarf3b4d442023-10-24 17:47:04 +00001091 emplace("libcodec2_soft_av1dec_dav1d.so");
Fyodor Kyslove21a4b72022-09-20 23:25:06 +00001092 emplace("libcodec2_soft_av1enc.so");
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001093 emplace("libcodec2_soft_avcdec.so");
1094 emplace("libcodec2_soft_avcenc.so");
1095 emplace("libcodec2_soft_flacdec.so");
1096 emplace("libcodec2_soft_flacenc.so");
1097 emplace("libcodec2_soft_g711alawdec.so");
1098 emplace("libcodec2_soft_g711mlawdec.so");
1099 emplace("libcodec2_soft_gsmdec.so");
1100 emplace("libcodec2_soft_h263dec.so");
1101 emplace("libcodec2_soft_h263enc.so");
1102 emplace("libcodec2_soft_hevcdec.so");
Roma Kauldfe650a2018-08-02 17:48:51 +05301103 emplace("libcodec2_soft_hevcenc.so");
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001104 emplace("libcodec2_soft_mp3dec.so");
1105 emplace("libcodec2_soft_mpeg2dec.so");
1106 emplace("libcodec2_soft_mpeg4dec.so");
1107 emplace("libcodec2_soft_mpeg4enc.so");
1108 emplace("libcodec2_soft_opusdec.so");
1109 emplace("libcodec2_soft_opusenc.so");
1110 emplace("libcodec2_soft_rawdec.so");
1111 emplace("libcodec2_soft_vorbisdec.so");
1112 emplace("libcodec2_soft_vp8dec.so");
1113 emplace("libcodec2_soft_vp8enc.so");
1114 emplace("libcodec2_soft_vp9dec.so");
1115 emplace("libcodec2_soft_vp9enc.so");
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +05301116
1117}
1118
1119// For testing only
1120C2PlatformComponentStore::C2PlatformComponentStore(
1121 std::vector<std::tuple<C2String,
1122 C2ComponentFactory::CreateCodec2FactoryFunc,
1123 C2ComponentFactory::DestroyCodec2FactoryFunc>> funcs)
1124 : mVisited(false),
1125 mReflector(std::make_shared<C2ReflectorHelper>()),
1126 mInterface(mReflector),
1127 mCodec2FactoryFuncs(funcs) {
1128
1129 for(auto const& func: mCodec2FactoryFuncs) {
1130 mComponents.emplace(std::get<0>(func), func);
1131 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001132}
1133
1134c2_status_t C2PlatformComponentStore::copyBuffer(
1135 std::shared_ptr<C2GraphicBuffer> src, std::shared_ptr<C2GraphicBuffer> dst) {
1136 (void)src;
1137 (void)dst;
1138 return C2_OMITTED;
1139}
1140
1141c2_status_t C2PlatformComponentStore::query_sm(
1142 const std::vector<C2Param*> &stackParams,
1143 const std::vector<C2Param::Index> &heapParamIndices,
1144 std::vector<std::unique_ptr<C2Param>> *const heapParams) const {
1145 return mInterface.query(stackParams, heapParamIndices, C2_MAY_BLOCK, heapParams);
1146}
1147
1148c2_status_t C2PlatformComponentStore::config_sm(
1149 const std::vector<C2Param*> &params,
1150 std::vector<std::unique_ptr<C2SettingResult>> *const failures) {
1151 return mInterface.config(params, C2_MAY_BLOCK, failures);
1152}
1153
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001154void C2PlatformComponentStore::visitComponents() {
1155 std::lock_guard<std::mutex> lock(mMutex);
1156 if (mVisited) {
1157 return;
1158 }
1159 for (auto &pathAndLoader : mComponents) {
1160 const C2String &path = pathAndLoader.first;
1161 ComponentLoader &loader = pathAndLoader.second;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001162 std::shared_ptr<ComponentModule> module;
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001163 if (loader.fetchModule(&module) == C2_OK) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001164 std::shared_ptr<const C2Component::Traits> traits = module->getTraits();
1165 if (traits) {
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001166 mComponentList.push_back(traits);
1167 mComponentNameToPath.emplace(traits->name, path);
1168 for (const C2String &alias : traits->aliases) {
1169 mComponentNameToPath.emplace(alias, path);
1170 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001171 }
1172 }
1173 }
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001174 mVisited = true;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001175}
1176
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001177std::vector<std::shared_ptr<const C2Component::Traits>> C2PlatformComponentStore::listComponents() {
1178 // This method SHALL return within 500ms.
1179 visitComponents();
1180 return mComponentList;
1181}
1182
1183c2_status_t C2PlatformComponentStore::findComponent(
1184 C2String name, std::shared_ptr<ComponentModule> *module) {
1185 (*module).reset();
1186 visitComponents();
1187
1188 auto pos = mComponentNameToPath.find(name);
1189 if (pos != mComponentNameToPath.end()) {
1190 return mComponents.at(pos->second).fetchModule(module);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001191 }
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001192 return C2_NOT_FOUND;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001193}
1194
1195c2_status_t C2PlatformComponentStore::createComponent(
1196 C2String name, std::shared_ptr<C2Component> *const component) {
1197 // This method SHALL return within 100ms.
1198 component->reset();
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001199 std::shared_ptr<ComponentModule> module;
1200 c2_status_t res = findComponent(name, &module);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001201 if (res == C2_OK) {
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001202 // TODO: get a unique node ID
1203 res = module->createComponent(0, component);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001204 }
1205 return res;
1206}
1207
1208c2_status_t C2PlatformComponentStore::createInterface(
1209 C2String name, std::shared_ptr<C2ComponentInterface> *const interface) {
1210 // This method SHALL return within 100ms.
1211 interface->reset();
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001212 std::shared_ptr<ComponentModule> module;
1213 c2_status_t res = findComponent(name, &module);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001214 if (res == C2_OK) {
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001215 // TODO: get a unique node ID
1216 res = module->createInterface(0, interface);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001217 }
1218 return res;
1219}
1220
1221c2_status_t C2PlatformComponentStore::querySupportedParams_nb(
1222 std::vector<std::shared_ptr<C2ParamDescriptor>> *const params) const {
1223 return mInterface.querySupportedParams(params);
1224}
1225
1226c2_status_t C2PlatformComponentStore::querySupportedValues_sm(
1227 std::vector<C2FieldSupportedValuesQuery> &fields) const {
1228 return mInterface.querySupportedValues(fields, C2_MAY_BLOCK);
1229}
1230
1231C2String C2PlatformComponentStore::getName() const {
1232 return "android.componentStore.platform";
1233}
1234
1235std::shared_ptr<C2ParamReflector> C2PlatformComponentStore::getParamReflector() const {
1236 return mReflector;
1237}
1238
1239std::shared_ptr<C2ComponentStore> GetCodec2PlatformComponentStore() {
1240 static std::mutex mutex;
1241 static std::weak_ptr<C2ComponentStore> platformStore;
1242 std::lock_guard<std::mutex> lock(mutex);
1243 std::shared_ptr<C2ComponentStore> store = platformStore.lock();
1244 if (store == nullptr) {
1245 store = std::make_shared<C2PlatformComponentStore>();
1246 platformStore = store;
1247 }
1248 return store;
1249}
1250
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +05301251// For testing only
1252std::shared_ptr<C2ComponentStore> GetTestComponentStore(
1253 std::vector<std::tuple<C2String,
1254 C2ComponentFactory::CreateCodec2FactoryFunc,
1255 C2ComponentFactory::DestroyCodec2FactoryFunc>> funcs) {
1256 return std::shared_ptr<C2ComponentStore>(new C2PlatformComponentStore(funcs));
1257}
Pawin Vongmasa36653902018-11-15 00:10:25 -08001258} // namespace android