blob: c07c09e1822bd0f4473511a8f443e30fa4634bf7 [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"
18#define LOG_NDEBUG 0
19#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>
Pin-chih Linaa18ea52019-11-19 18:48:50 +080031#include <cutils/properties.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080032#include <util/C2InterfaceHelper.h>
33
34#include <dlfcn.h>
35#include <unistd.h> // getpagesize
36
37#include <map>
38#include <memory>
39#include <mutex>
40
Wonsik Kimba3db192019-11-22 11:00:48 -080041#ifdef __ANDROID_APEX__
42#include <android-base/properties.h>
43#endif
44
Pawin Vongmasa36653902018-11-15 00:10:25 -080045namespace android {
46
47/**
48 * Returns the preferred component store in this process to access its interface.
49 */
50std::shared_ptr<C2ComponentStore> GetPreferredCodec2ComponentStore();
51
52/**
53 * The platform allocator store provides basic allocator-types for the framework based on ion and
54 * gralloc. Allocators are not meant to be updatable.
55 *
56 * \todo Provide allocator based on ashmem
57 * \todo Move ion allocation into its HIDL or provide some mapping from memory usage to ion flags
58 * \todo Make this allocator store extendable
59 */
60class C2PlatformAllocatorStoreImpl : public C2PlatformAllocatorStore {
61public:
62 C2PlatformAllocatorStoreImpl();
63
64 virtual c2_status_t fetchAllocator(
65 id_t id, std::shared_ptr<C2Allocator> *const allocator) override;
66
67 virtual std::vector<std::shared_ptr<const C2Allocator::Traits>> listAllocators_nb()
68 const override {
69 return std::vector<std::shared_ptr<const C2Allocator::Traits>>(); /// \todo
70 }
71
72 virtual C2String getName() const override {
73 return "android.allocator-store";
74 }
75
76 void setComponentStore(std::shared_ptr<C2ComponentStore> store);
77
78 ~C2PlatformAllocatorStoreImpl() override = default;
79
80private:
Pin-chih Linaa18ea52019-11-19 18:48:50 +080081 /// returns a shared-singleton blob allocator (gralloc-backed)
82 std::shared_ptr<C2Allocator> fetchBlobAllocator();
83
Pawin Vongmasa36653902018-11-15 00:10:25 -080084 /// returns a shared-singleton ion allocator
85 std::shared_ptr<C2Allocator> fetchIonAllocator();
John Stultza7002cb2020-09-04 19:02:30 +000086 std::shared_ptr<C2Allocator> fetchDmaBufAllocator();
Pawin Vongmasa36653902018-11-15 00:10:25 -080087
88 /// returns a shared-singleton gralloc allocator
89 std::shared_ptr<C2Allocator> fetchGrallocAllocator();
90
91 /// returns a shared-singleton bufferqueue supporting gralloc allocator
92 std::shared_ptr<C2Allocator> fetchBufferQueueAllocator();
93
94 /// component store to use
95 std::mutex _mComponentStoreSetLock; // protects the entire updating _mComponentStore and its
96 // dependencies
97 std::mutex _mComponentStoreReadLock; // must protect only read/write of _mComponentStore
98 std::shared_ptr<C2ComponentStore> _mComponentStore;
99};
100
101C2PlatformAllocatorStoreImpl::C2PlatformAllocatorStoreImpl() {
102}
103
John Stultza7002cb2020-09-04 19:02:30 +0000104static bool using_ion(void) {
John Stultz3a069352021-01-09 04:11:10 +0000105 static int cached_result = []()->int {
John Stultza7002cb2020-09-04 19:02:30 +0000106 struct stat buffer;
John Stultz3a069352021-01-09 04:11:10 +0000107 int ret = (stat("/dev/ion", &buffer) == 0);
108
109 if (property_get_int32("debug.c2.use_dmabufheaps", 0)) {
110 /*
111 * Double check that the system heap is present so we
112 * can gracefully fail back to ION if we cannot satisfy
113 * the override
114 */
115 ret = (stat("/dev/dma_heap/system", &buffer) != 0);
116 if (ret)
117 ALOGE("debug.c2.use_dmabufheaps set, but no system heap. Ignoring override!");
118 else
119 ALOGD("debug.c2.use_dmabufheaps set, forcing DMABUF Heaps");
120 }
121
122 if (ret)
John Stultza7002cb2020-09-04 19:02:30 +0000123 ALOGD("Using ION\n");
124 else
125 ALOGD("Using DMABUF Heaps\n");
John Stultz3a069352021-01-09 04:11:10 +0000126 return ret;
127 }();
128
John Stultza7002cb2020-09-04 19:02:30 +0000129 return (cached_result == 1);
130}
131
Pawin Vongmasa36653902018-11-15 00:10:25 -0800132c2_status_t C2PlatformAllocatorStoreImpl::fetchAllocator(
133 id_t id, std::shared_ptr<C2Allocator> *const allocator) {
134 allocator->reset();
Pin-chih Linaa18ea52019-11-19 18:48:50 +0800135 if (id == C2AllocatorStore::DEFAULT_LINEAR) {
136 id = GetPreferredLinearAllocatorId(GetCodec2PoolMask());
137 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800138 switch (id) {
139 // TODO: should we implement a generic registry for all, and use that?
John Stultza7002cb2020-09-04 19:02:30 +0000140 case C2PlatformAllocatorStore::ION: /* also ::DMABUFHEAP */
141 if (using_ion())
142 *allocator = fetchIonAllocator();
143 else
144 *allocator = fetchDmaBufAllocator();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800145 break;
146
147 case C2PlatformAllocatorStore::GRALLOC:
148 case C2AllocatorStore::DEFAULT_GRAPHIC:
149 *allocator = fetchGrallocAllocator();
150 break;
151
152 case C2PlatformAllocatorStore::BUFFERQUEUE:
153 *allocator = fetchBufferQueueAllocator();
154 break;
155
Pin-chih Linaa18ea52019-11-19 18:48:50 +0800156 case C2PlatformAllocatorStore::BLOB:
157 *allocator = fetchBlobAllocator();
158 break;
159
Pawin Vongmasa36653902018-11-15 00:10:25 -0800160 default:
161 // Try to create allocator from platform store plugins.
162 c2_status_t res =
163 C2PlatformStorePluginLoader::GetInstance()->createAllocator(id, allocator);
164 if (res != C2_OK) {
165 return res;
166 }
167 break;
168 }
169 if (*allocator == nullptr) {
170 return C2_NO_MEMORY;
171 }
172 return C2_OK;
173}
174
175namespace {
176
177std::mutex gIonAllocatorMutex;
John Stultza7002cb2020-09-04 19:02:30 +0000178std::mutex gDmaBufAllocatorMutex;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800179std::weak_ptr<C2AllocatorIon> gIonAllocator;
John Stultza7002cb2020-09-04 19:02:30 +0000180std::weak_ptr<C2DmaBufAllocator> gDmaBufAllocator;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800181
182void UseComponentStoreForIonAllocator(
183 const std::shared_ptr<C2AllocatorIon> allocator,
184 std::shared_ptr<C2ComponentStore> store) {
185 C2AllocatorIon::UsageMapperFn mapper;
186 uint64_t minUsage = 0;
187 uint64_t maxUsage = C2MemoryUsage(C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE).expected;
188 size_t blockSize = getpagesize();
189
190 // query min and max usage as well as block size via supported values
191 C2StoreIonUsageInfo usageInfo;
192 std::vector<C2FieldSupportedValuesQuery> query = {
193 C2FieldSupportedValuesQuery::Possible(C2ParamField::Make(usageInfo, usageInfo.usage)),
194 C2FieldSupportedValuesQuery::Possible(C2ParamField::Make(usageInfo, usageInfo.capacity)),
195 };
196 c2_status_t res = store->querySupportedValues_sm(query);
197 if (res == C2_OK) {
198 if (query[0].status == C2_OK) {
199 const C2FieldSupportedValues &fsv = query[0].values;
200 if (fsv.type == C2FieldSupportedValues::FLAGS && !fsv.values.empty()) {
201 minUsage = fsv.values[0].u64;
202 maxUsage = 0;
203 for (C2Value::Primitive v : fsv.values) {
204 maxUsage |= v.u64;
205 }
206 }
207 }
208 if (query[1].status == C2_OK) {
209 const C2FieldSupportedValues &fsv = query[1].values;
210 if (fsv.type == C2FieldSupportedValues::RANGE && fsv.range.step.u32 > 0) {
211 blockSize = fsv.range.step.u32;
212 }
213 }
214
215 mapper = [store](C2MemoryUsage usage, size_t capacity,
216 size_t *align, unsigned *heapMask, unsigned *flags) -> c2_status_t {
217 if (capacity > UINT32_MAX) {
218 return C2_BAD_VALUE;
219 }
220 C2StoreIonUsageInfo usageInfo = { usage.expected, capacity };
221 std::vector<std::unique_ptr<C2SettingResult>> failures; // TODO: remove
222 c2_status_t res = store->config_sm({&usageInfo}, &failures);
223 if (res == C2_OK) {
224 *align = usageInfo.minAlignment;
225 *heapMask = usageInfo.heapMask;
226 *flags = usageInfo.allocFlags;
227 }
228 return res;
229 };
230 }
231
232 allocator->setUsageMapper(mapper, minUsage, maxUsage, blockSize);
233}
234
John Stultza7002cb2020-09-04 19:02:30 +0000235void UseComponentStoreForDmaBufAllocator(const std::shared_ptr<C2DmaBufAllocator> allocator,
236 std::shared_ptr<C2ComponentStore> store) {
237 C2DmaBufAllocator::UsageMapperFn mapper;
238 const size_t maxHeapNameLen = 128;
239 uint64_t minUsage = 0;
240 uint64_t maxUsage = C2MemoryUsage(C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE).expected;
241 size_t blockSize = getpagesize();
242
243 // query min and max usage as well as block size via supported values
244 std::unique_ptr<C2StoreDmaBufUsageInfo> usageInfo;
245 usageInfo = C2StoreDmaBufUsageInfo::AllocUnique(maxHeapNameLen);
246
247 std::vector<C2FieldSupportedValuesQuery> query = {
248 C2FieldSupportedValuesQuery::Possible(C2ParamField::Make(*usageInfo, usageInfo->m.usage)),
249 C2FieldSupportedValuesQuery::Possible(
250 C2ParamField::Make(*usageInfo, usageInfo->m.capacity)),
251 };
252 c2_status_t res = store->querySupportedValues_sm(query);
253 if (res == C2_OK) {
254 if (query[0].status == C2_OK) {
255 const C2FieldSupportedValues& fsv = query[0].values;
256 if (fsv.type == C2FieldSupportedValues::FLAGS && !fsv.values.empty()) {
257 minUsage = fsv.values[0].u64;
258 maxUsage = 0;
259 for (C2Value::Primitive v : fsv.values) {
260 maxUsage |= v.u64;
261 }
262 }
263 }
264 if (query[1].status == C2_OK) {
265 const C2FieldSupportedValues& fsv = query[1].values;
266 if (fsv.type == C2FieldSupportedValues::RANGE && fsv.range.step.u32 > 0) {
267 blockSize = fsv.range.step.u32;
268 }
269 }
270
271 mapper = [store](C2MemoryUsage usage, size_t capacity, C2String* heapName,
272 unsigned* flags) -> c2_status_t {
273 if (capacity > UINT32_MAX) {
274 return C2_BAD_VALUE;
275 }
276
277 std::unique_ptr<C2StoreDmaBufUsageInfo> usageInfo;
278 usageInfo = C2StoreDmaBufUsageInfo::AllocUnique(maxHeapNameLen, usage.expected, capacity);
279 std::vector<std::unique_ptr<C2SettingResult>> failures; // TODO: remove
280
281 c2_status_t res = store->config_sm({&*usageInfo}, &failures);
282 if (res == C2_OK) {
283 *heapName = C2String(usageInfo->m.heapName);
284 *flags = usageInfo->m.allocFlags;
285 }
286
287 return res;
288 };
289 }
290
291 allocator->setUsageMapper(mapper, minUsage, maxUsage, blockSize);
292}
293
Pawin Vongmasa36653902018-11-15 00:10:25 -0800294}
295
296void C2PlatformAllocatorStoreImpl::setComponentStore(std::shared_ptr<C2ComponentStore> store) {
297 // technically this set lock is not needed, but is here for safety in case we add more
298 // getter orders
299 std::lock_guard<std::mutex> lock(_mComponentStoreSetLock);
300 {
301 std::lock_guard<std::mutex> lock(_mComponentStoreReadLock);
302 _mComponentStore = store;
303 }
304 std::shared_ptr<C2AllocatorIon> allocator;
305 {
306 std::lock_guard<std::mutex> lock(gIonAllocatorMutex);
307 allocator = gIonAllocator.lock();
308 }
309 if (allocator) {
310 UseComponentStoreForIonAllocator(allocator, store);
311 }
312}
313
314std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchIonAllocator() {
315 std::lock_guard<std::mutex> lock(gIonAllocatorMutex);
316 std::shared_ptr<C2AllocatorIon> allocator = gIonAllocator.lock();
317 if (allocator == nullptr) {
318 std::shared_ptr<C2ComponentStore> componentStore;
319 {
320 std::lock_guard<std::mutex> lock(_mComponentStoreReadLock);
321 componentStore = _mComponentStore;
322 }
323 allocator = std::make_shared<C2AllocatorIon>(C2PlatformAllocatorStore::ION);
324 UseComponentStoreForIonAllocator(allocator, componentStore);
325 gIonAllocator = allocator;
326 }
327 return allocator;
328}
329
John Stultza7002cb2020-09-04 19:02:30 +0000330std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchDmaBufAllocator() {
331 std::lock_guard<std::mutex> lock(gDmaBufAllocatorMutex);
332 std::shared_ptr<C2DmaBufAllocator> allocator = gDmaBufAllocator.lock();
333 if (allocator == nullptr) {
334 std::shared_ptr<C2ComponentStore> componentStore;
335 {
336 std::lock_guard<std::mutex> lock(_mComponentStoreReadLock);
337 componentStore = _mComponentStore;
338 }
339 allocator = std::make_shared<C2DmaBufAllocator>(C2PlatformAllocatorStore::DMABUFHEAP);
340 UseComponentStoreForDmaBufAllocator(allocator, componentStore);
341 gDmaBufAllocator = allocator;
342 }
343 return allocator;
344}
345
Pin-chih Linaa18ea52019-11-19 18:48:50 +0800346std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchBlobAllocator() {
347 static std::mutex mutex;
348 static std::weak_ptr<C2Allocator> blobAllocator;
349 std::lock_guard<std::mutex> lock(mutex);
350 std::shared_ptr<C2Allocator> allocator = blobAllocator.lock();
351 if (allocator == nullptr) {
352 allocator = std::make_shared<C2AllocatorBlob>(C2PlatformAllocatorStore::BLOB);
353 blobAllocator = allocator;
354 }
355 return allocator;
356}
357
Pawin Vongmasa36653902018-11-15 00:10:25 -0800358std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchGrallocAllocator() {
359 static std::mutex mutex;
360 static std::weak_ptr<C2Allocator> grallocAllocator;
361 std::lock_guard<std::mutex> lock(mutex);
362 std::shared_ptr<C2Allocator> allocator = grallocAllocator.lock();
363 if (allocator == nullptr) {
364 allocator = std::make_shared<C2AllocatorGralloc>(C2PlatformAllocatorStore::GRALLOC);
365 grallocAllocator = allocator;
366 }
367 return allocator;
368}
369
370std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchBufferQueueAllocator() {
371 static std::mutex mutex;
372 static std::weak_ptr<C2Allocator> grallocAllocator;
373 std::lock_guard<std::mutex> lock(mutex);
374 std::shared_ptr<C2Allocator> allocator = grallocAllocator.lock();
375 if (allocator == nullptr) {
376 allocator = std::make_shared<C2AllocatorGralloc>(
377 C2PlatformAllocatorStore::BUFFERQUEUE, true);
378 grallocAllocator = allocator;
379 }
380 return allocator;
381}
382
383namespace {
384 std::mutex gPreferredComponentStoreMutex;
385 std::shared_ptr<C2ComponentStore> gPreferredComponentStore;
386
387 std::mutex gPlatformAllocatorStoreMutex;
388 std::weak_ptr<C2PlatformAllocatorStoreImpl> gPlatformAllocatorStore;
389}
390
391std::shared_ptr<C2AllocatorStore> GetCodec2PlatformAllocatorStore() {
392 std::lock_guard<std::mutex> lock(gPlatformAllocatorStoreMutex);
393 std::shared_ptr<C2PlatformAllocatorStoreImpl> store = gPlatformAllocatorStore.lock();
394 if (store == nullptr) {
395 store = std::make_shared<C2PlatformAllocatorStoreImpl>();
396 store->setComponentStore(GetPreferredCodec2ComponentStore());
397 gPlatformAllocatorStore = store;
398 }
399 return store;
400}
401
402void SetPreferredCodec2ComponentStore(std::shared_ptr<C2ComponentStore> componentStore) {
403 static std::mutex mutex;
404 std::lock_guard<std::mutex> lock(mutex); // don't interleve set-s
405
406 // update preferred store
407 {
408 std::lock_guard<std::mutex> lock(gPreferredComponentStoreMutex);
409 gPreferredComponentStore = componentStore;
410 }
411
412 // update platform allocator's store as well if it is alive
413 std::shared_ptr<C2PlatformAllocatorStoreImpl> allocatorStore;
414 {
415 std::lock_guard<std::mutex> lock(gPlatformAllocatorStoreMutex);
416 allocatorStore = gPlatformAllocatorStore.lock();
417 }
418 if (allocatorStore) {
419 allocatorStore->setComponentStore(componentStore);
420 }
421}
422
423std::shared_ptr<C2ComponentStore> GetPreferredCodec2ComponentStore() {
424 std::lock_guard<std::mutex> lock(gPreferredComponentStoreMutex);
425 return gPreferredComponentStore ? gPreferredComponentStore : GetCodec2PlatformComponentStore();
426}
427
Pin-chih Linaa18ea52019-11-19 18:48:50 +0800428int GetCodec2PoolMask() {
429 return property_get_int32(
430 "debug.stagefright.c2-poolmask",
431 1 << C2PlatformAllocatorStore::ION |
432 1 << C2PlatformAllocatorStore::BUFFERQUEUE);
433}
434
435C2PlatformAllocatorStore::id_t GetPreferredLinearAllocatorId(int poolMask) {
436 return ((poolMask >> C2PlatformAllocatorStore::BLOB) & 1) ? C2PlatformAllocatorStore::BLOB
437 : C2PlatformAllocatorStore::ION;
438}
439
Pawin Vongmasa36653902018-11-15 00:10:25 -0800440namespace {
441
442class _C2BlockPoolCache {
443public:
444 _C2BlockPoolCache() : mBlockPoolSeqId(C2BlockPool::PLATFORM_START + 1) {}
445
446 c2_status_t _createBlockPool(
447 C2PlatformAllocatorStore::id_t allocatorId,
Wonsik Kim2fce07922021-02-11 00:16:11 -0800448 std::vector<std::shared_ptr<const C2Component>> components,
Pawin Vongmasa36653902018-11-15 00:10:25 -0800449 C2BlockPool::local_id_t poolId,
450 std::shared_ptr<C2BlockPool> *pool) {
451 std::shared_ptr<C2AllocatorStore> allocatorStore =
452 GetCodec2PlatformAllocatorStore();
453 std::shared_ptr<C2Allocator> allocator;
454 c2_status_t res = C2_NOT_FOUND;
455
Pin-chih Linaa18ea52019-11-19 18:48:50 +0800456 if (allocatorId == C2AllocatorStore::DEFAULT_LINEAR) {
457 allocatorId = GetPreferredLinearAllocatorId(GetCodec2PoolMask());
458 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800459 switch(allocatorId) {
John Stultza7002cb2020-09-04 19:02:30 +0000460 case C2PlatformAllocatorStore::ION: /* also ::DMABUFHEAP */
Pawin Vongmasa36653902018-11-15 00:10:25 -0800461 res = allocatorStore->fetchAllocator(
Pin-chih Linaa18ea52019-11-19 18:48:50 +0800462 C2PlatformAllocatorStore::ION, &allocator);
463 if (res == C2_OK) {
464 std::shared_ptr<C2BlockPool> ptr =
465 std::make_shared<C2PooledBlockPool>(
466 allocator, poolId);
467 *pool = ptr;
468 mBlockPools[poolId] = ptr;
Wonsik Kim2fce07922021-02-11 00:16:11 -0800469 mComponents[poolId].insert(
470 mComponents[poolId].end(),
471 components.begin(), components.end());
Pin-chih Linaa18ea52019-11-19 18:48:50 +0800472 }
473 break;
474 case C2PlatformAllocatorStore::BLOB:
475 res = allocatorStore->fetchAllocator(
476 C2PlatformAllocatorStore::BLOB, &allocator);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800477 if (res == C2_OK) {
478 std::shared_ptr<C2BlockPool> ptr =
479 std::make_shared<C2PooledBlockPool>(
480 allocator, poolId);
481 *pool = ptr;
482 mBlockPools[poolId] = ptr;
Wonsik Kim2fce07922021-02-11 00:16:11 -0800483 mComponents[poolId].insert(
484 mComponents[poolId].end(),
485 components.begin(), components.end());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800486 }
487 break;
488 case C2PlatformAllocatorStore::GRALLOC:
489 case C2AllocatorStore::DEFAULT_GRAPHIC:
490 res = allocatorStore->fetchAllocator(
491 C2AllocatorStore::DEFAULT_GRAPHIC, &allocator);
492 if (res == C2_OK) {
493 std::shared_ptr<C2BlockPool> ptr =
494 std::make_shared<C2PooledBlockPool>(allocator, poolId);
495 *pool = ptr;
496 mBlockPools[poolId] = ptr;
Wonsik Kim2fce07922021-02-11 00:16:11 -0800497 mComponents[poolId].insert(
498 mComponents[poolId].end(),
499 components.begin(), components.end());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800500 }
501 break;
502 case C2PlatformAllocatorStore::BUFFERQUEUE:
503 res = allocatorStore->fetchAllocator(
504 C2PlatformAllocatorStore::BUFFERQUEUE, &allocator);
505 if (res == C2_OK) {
506 std::shared_ptr<C2BlockPool> ptr =
507 std::make_shared<C2BufferQueueBlockPool>(
508 allocator, poolId);
509 *pool = ptr;
510 mBlockPools[poolId] = ptr;
Wonsik Kim2fce07922021-02-11 00:16:11 -0800511 mComponents[poolId].insert(
512 mComponents[poolId].end(),
513 components.begin(), components.end());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800514 }
515 break;
516 default:
517 // Try to create block pool from platform store plugins.
518 std::shared_ptr<C2BlockPool> ptr;
519 res = C2PlatformStorePluginLoader::GetInstance()->createBlockPool(
520 allocatorId, poolId, &ptr);
521 if (res == C2_OK) {
522 *pool = ptr;
523 mBlockPools[poolId] = ptr;
Wonsik Kim2fce07922021-02-11 00:16:11 -0800524 mComponents[poolId].insert(
525 mComponents[poolId].end(),
526 components.begin(), components.end());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800527 }
528 break;
529 }
530 return res;
531 }
532
533 c2_status_t createBlockPool(
534 C2PlatformAllocatorStore::id_t allocatorId,
Wonsik Kim2fce07922021-02-11 00:16:11 -0800535 std::vector<std::shared_ptr<const C2Component>> components,
Pawin Vongmasa36653902018-11-15 00:10:25 -0800536 std::shared_ptr<C2BlockPool> *pool) {
Wonsik Kim2fce07922021-02-11 00:16:11 -0800537 return _createBlockPool(allocatorId, components, mBlockPoolSeqId++, pool);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800538 }
539
540 bool getBlockPool(
541 C2BlockPool::local_id_t blockPoolId,
542 std::shared_ptr<const C2Component> component,
543 std::shared_ptr<C2BlockPool> *pool) {
544 // TODO: use one iterator for multiple blockpool type scalability.
545 std::shared_ptr<C2BlockPool> ptr;
546 auto it = mBlockPools.find(blockPoolId);
547 if (it != mBlockPools.end()) {
548 ptr = it->second.lock();
549 if (!ptr) {
550 mBlockPools.erase(it);
551 mComponents.erase(blockPoolId);
552 } else {
Wonsik Kim2fce07922021-02-11 00:16:11 -0800553 auto found = std::find_if(
554 mComponents[blockPoolId].begin(),
555 mComponents[blockPoolId].end(),
556 [component](const std::weak_ptr<const C2Component> &ptr) {
557 return component == ptr.lock();
558 });
559 if (found != mComponents[blockPoolId].end()) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800560 *pool = ptr;
561 return true;
562 }
563 }
564 }
565 return false;
566 }
567
568private:
569 C2BlockPool::local_id_t mBlockPoolSeqId;
570
571 std::map<C2BlockPool::local_id_t, std::weak_ptr<C2BlockPool>> mBlockPools;
Wonsik Kim2fce07922021-02-11 00:16:11 -0800572 std::map<C2BlockPool::local_id_t, std::vector<std::weak_ptr<const C2Component>>> mComponents;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800573};
574
575static std::unique_ptr<_C2BlockPoolCache> sBlockPoolCache =
576 std::make_unique<_C2BlockPoolCache>();
577static std::mutex sBlockPoolCacheMutex;
578
579} // anynymous namespace
580
581c2_status_t GetCodec2BlockPool(
582 C2BlockPool::local_id_t id, std::shared_ptr<const C2Component> component,
583 std::shared_ptr<C2BlockPool> *pool) {
584 pool->reset();
585 std::lock_guard<std::mutex> lock(sBlockPoolCacheMutex);
586 std::shared_ptr<C2AllocatorStore> allocatorStore = GetCodec2PlatformAllocatorStore();
587 std::shared_ptr<C2Allocator> allocator;
588 c2_status_t res = C2_NOT_FOUND;
589
590 if (id >= C2BlockPool::PLATFORM_START) {
591 if (sBlockPoolCache->getBlockPool(id, component, pool)) {
592 return C2_OK;
593 }
594 }
595
596 switch (id) {
597 case C2BlockPool::BASIC_LINEAR:
598 res = allocatorStore->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &allocator);
599 if (res == C2_OK) {
600 *pool = std::make_shared<C2BasicLinearBlockPool>(allocator);
601 }
602 break;
603 case C2BlockPool::BASIC_GRAPHIC:
604 res = allocatorStore->fetchAllocator(C2AllocatorStore::DEFAULT_GRAPHIC, &allocator);
605 if (res == C2_OK) {
606 *pool = std::make_shared<C2BasicGraphicBlockPool>(allocator);
607 }
608 break;
609 // TODO: remove this. this is temporary
610 case C2BlockPool::PLATFORM_START:
611 res = sBlockPoolCache->_createBlockPool(
Wonsik Kim2fce07922021-02-11 00:16:11 -0800612 C2PlatformAllocatorStore::BUFFERQUEUE, {component}, id, pool);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800613 break;
614 default:
615 break;
616 }
617 return res;
618}
619
620c2_status_t CreateCodec2BlockPool(
621 C2PlatformAllocatorStore::id_t allocatorId,
Wonsik Kim2fce07922021-02-11 00:16:11 -0800622 const std::vector<std::shared_ptr<const C2Component>> &components,
623 std::shared_ptr<C2BlockPool> *pool) {
624 pool->reset();
625
626 std::lock_guard<std::mutex> lock(sBlockPoolCacheMutex);
627 return sBlockPoolCache->createBlockPool(allocatorId, components, pool);
628}
629
630c2_status_t CreateCodec2BlockPool(
631 C2PlatformAllocatorStore::id_t allocatorId,
Pawin Vongmasa36653902018-11-15 00:10:25 -0800632 std::shared_ptr<const C2Component> component,
633 std::shared_ptr<C2BlockPool> *pool) {
634 pool->reset();
635
636 std::lock_guard<std::mutex> lock(sBlockPoolCacheMutex);
Wonsik Kim2fce07922021-02-11 00:16:11 -0800637 return sBlockPoolCache->createBlockPool(allocatorId, {component}, pool);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800638}
639
640class C2PlatformComponentStore : public C2ComponentStore {
641public:
642 virtual std::vector<std::shared_ptr<const C2Component::Traits>> listComponents() override;
643 virtual std::shared_ptr<C2ParamReflector> getParamReflector() const override;
644 virtual C2String getName() const override;
645 virtual c2_status_t querySupportedValues_sm(
646 std::vector<C2FieldSupportedValuesQuery> &fields) const override;
647 virtual c2_status_t querySupportedParams_nb(
648 std::vector<std::shared_ptr<C2ParamDescriptor>> *const params) const override;
649 virtual c2_status_t query_sm(
650 const std::vector<C2Param*> &stackParams,
651 const std::vector<C2Param::Index> &heapParamIndices,
652 std::vector<std::unique_ptr<C2Param>> *const heapParams) const override;
653 virtual c2_status_t createInterface(
654 C2String name, std::shared_ptr<C2ComponentInterface> *const interface) override;
655 virtual c2_status_t createComponent(
656 C2String name, std::shared_ptr<C2Component> *const component) override;
657 virtual c2_status_t copyBuffer(
658 std::shared_ptr<C2GraphicBuffer> src, std::shared_ptr<C2GraphicBuffer> dst) override;
659 virtual c2_status_t config_sm(
660 const std::vector<C2Param*> &params,
661 std::vector<std::unique_ptr<C2SettingResult>> *const failures) override;
662 C2PlatformComponentStore();
663
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530664 // For testing only
665 C2PlatformComponentStore(
666 std::vector<std::tuple<C2String,
667 C2ComponentFactory::CreateCodec2FactoryFunc,
668 C2ComponentFactory::DestroyCodec2FactoryFunc>>);
669
Pawin Vongmasa36653902018-11-15 00:10:25 -0800670 virtual ~C2PlatformComponentStore() override = default;
671
672private:
673
674 /**
675 * An object encapsulating a loaded component module.
676 *
677 * \todo provide a way to add traits to known components here to avoid loading the .so-s
678 * for listComponents
679 */
680 struct ComponentModule : public C2ComponentFactory,
681 public std::enable_shared_from_this<ComponentModule> {
682 virtual c2_status_t createComponent(
683 c2_node_id_t id, std::shared_ptr<C2Component> *component,
684 ComponentDeleter deleter = std::default_delete<C2Component>()) override;
685 virtual c2_status_t createInterface(
686 c2_node_id_t id, std::shared_ptr<C2ComponentInterface> *interface,
687 InterfaceDeleter deleter = std::default_delete<C2ComponentInterface>()) override;
688
689 /**
690 * \returns the traits of the component in this module.
691 */
692 std::shared_ptr<const C2Component::Traits> getTraits();
693
694 /**
695 * Creates an uninitialized component module.
696 *
697 * \param name[in] component name.
698 *
699 * \note Only used by ComponentLoader.
700 */
701 ComponentModule()
702 : mInit(C2_NO_INIT),
703 mLibHandle(nullptr),
704 createFactory(nullptr),
705 destroyFactory(nullptr),
706 mComponentFactory(nullptr) {
707 }
708
709 /**
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530710 * Creates an uninitialized component module.
711 * NOTE: For testing only
712 *
713 * \param name[in] component name.
714 *
715 * \note Only used by ComponentLoader.
716 */
717 ComponentModule(
718 C2ComponentFactory::CreateCodec2FactoryFunc createFactory,
719 C2ComponentFactory::DestroyCodec2FactoryFunc destroyFactory)
720 : mInit(C2_NO_INIT),
721 mLibHandle(nullptr),
722 createFactory(createFactory),
723 destroyFactory(destroyFactory),
724 mComponentFactory(nullptr) {
725 }
726
727 /**
Pawin Vongmasa36653902018-11-15 00:10:25 -0800728 * Initializes a component module with a given library path. Must be called exactly once.
729 *
730 * \note Only used by ComponentLoader.
731 *
Pawin Vongmasa36653902018-11-15 00:10:25 -0800732 * \param libPath[in] library path
733 *
734 * \retval C2_OK the component module has been successfully loaded
735 * \retval C2_NO_MEMORY not enough memory to loading the component module
736 * \retval C2_NOT_FOUND could not locate the component module
737 * \retval C2_CORRUPTED the component module could not be loaded (unexpected)
738 * \retval C2_REFUSED permission denied to load the component module (unexpected)
739 * \retval C2_TIMED_OUT could not load the module within the time limit (unexpected)
740 */
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800741 c2_status_t init(std::string libPath);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800742
743 virtual ~ComponentModule() override;
744
745 protected:
746 std::recursive_mutex mLock; ///< lock protecting mTraits
747 std::shared_ptr<C2Component::Traits> mTraits; ///< cached component traits
748
749 c2_status_t mInit; ///< initialization result
750
751 void *mLibHandle; ///< loaded library handle
752 C2ComponentFactory::CreateCodec2FactoryFunc createFactory; ///< loaded create function
753 C2ComponentFactory::DestroyCodec2FactoryFunc destroyFactory; ///< loaded destroy function
754 C2ComponentFactory *mComponentFactory; ///< loaded/created component factory
755 };
756
757 /**
758 * An object encapsulating a loadable component module.
759 *
760 * \todo make this also work for enumerations
761 */
762 struct ComponentLoader {
763 /**
764 * Load the component module.
765 *
766 * This method simply returns the component module if it is already currently loaded, or
767 * attempts to load it if it is not.
768 *
769 * \param module[out] pointer to the shared pointer where the loaded module shall be stored.
770 * This will be nullptr on error.
771 *
772 * \retval C2_OK the component module has been successfully loaded
773 * \retval C2_NO_MEMORY not enough memory to loading the component module
774 * \retval C2_NOT_FOUND could not locate the component module
775 * \retval C2_CORRUPTED the component module could not be loaded
776 * \retval C2_REFUSED permission denied to load the component module
777 */
778 c2_status_t fetchModule(std::shared_ptr<ComponentModule> *module) {
779 c2_status_t res = C2_OK;
780 std::lock_guard<std::mutex> lock(mMutex);
781 std::shared_ptr<ComponentModule> localModule = mModule.lock();
782 if (localModule == nullptr) {
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530783 if(mCreateFactory) {
784 // For testing only
785 localModule = std::make_shared<ComponentModule>(mCreateFactory,
786 mDestroyFactory);
787 } else {
788 localModule = std::make_shared<ComponentModule>();
789 }
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800790 res = localModule->init(mLibPath);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800791 if (res == C2_OK) {
792 mModule = localModule;
793 }
794 }
795 *module = localModule;
796 return res;
797 }
798
799 /**
800 * Creates a component loader for a specific library path (or name).
801 */
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800802 ComponentLoader(std::string libPath)
803 : mLibPath(libPath) {}
Pawin Vongmasa36653902018-11-15 00:10:25 -0800804
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530805 // For testing only
806 ComponentLoader(std::tuple<C2String,
807 C2ComponentFactory::CreateCodec2FactoryFunc,
808 C2ComponentFactory::DestroyCodec2FactoryFunc> func)
809 : mLibPath(std::get<0>(func)),
810 mCreateFactory(std::get<1>(func)),
811 mDestroyFactory(std::get<2>(func)) {}
812
Pawin Vongmasa36653902018-11-15 00:10:25 -0800813 private:
814 std::mutex mMutex; ///< mutex guarding the module
815 std::weak_ptr<ComponentModule> mModule; ///< weak reference to the loaded module
Pawin Vongmasa36653902018-11-15 00:10:25 -0800816 std::string mLibPath; ///< library path
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530817
818 // For testing only
819 C2ComponentFactory::CreateCodec2FactoryFunc mCreateFactory = nullptr;
820 C2ComponentFactory::DestroyCodec2FactoryFunc mDestroyFactory = nullptr;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800821 };
822
823 struct Interface : public C2InterfaceHelper {
824 std::shared_ptr<C2StoreIonUsageInfo> mIonUsageInfo;
John Stultza7002cb2020-09-04 19:02:30 +0000825 std::shared_ptr<C2StoreDmaBufUsageInfo> mDmaBufUsageInfo;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800826
827 Interface(std::shared_ptr<C2ReflectorHelper> reflector)
828 : C2InterfaceHelper(reflector) {
829 setDerivedInstance(this);
830
831 struct Setter {
832 static C2R setIonUsage(bool /* mayBlock */, C2P<C2StoreIonUsageInfo> &me) {
Wonsik Kimba3db192019-11-22 11:00:48 -0800833#ifdef __ANDROID_APEX__
834 static int32_t defaultHeapMask = [] {
835 int32_t heapmask = base::GetIntProperty(
836 "ro.com.android.media.swcodec.ion.heapmask", int32_t(0xFFFFFFFF));
837 ALOGD("Default ION heapmask = %d", heapmask);
838 return heapmask;
839 }();
840 static int32_t defaultFlags = [] {
841 int32_t flags = base::GetIntProperty(
842 "ro.com.android.media.swcodec.ion.flags", 0);
843 ALOGD("Default ION flags = %d", flags);
844 return flags;
845 }();
846 static uint32_t defaultAlign = [] {
847 uint32_t align = base::GetUintProperty(
848 "ro.com.android.media.swcodec.ion.align", 0u);
849 ALOGD("Default ION align = %d", align);
850 return align;
851 }();
852 me.set().heapMask = defaultHeapMask;
853 me.set().allocFlags = defaultFlags;
854 me.set().minAlignment = defaultAlign;
855#else
Pawin Vongmasa36653902018-11-15 00:10:25 -0800856 me.set().heapMask = ~0;
857 me.set().allocFlags = 0;
858 me.set().minAlignment = 0;
Wonsik Kimba3db192019-11-22 11:00:48 -0800859#endif
Pawin Vongmasa36653902018-11-15 00:10:25 -0800860 return C2R::Ok();
John Stultza7002cb2020-09-04 19:02:30 +0000861 };
862
863 static C2R setDmaBufUsage(bool /* mayBlock */, C2P<C2StoreDmaBufUsageInfo> &me) {
John Stultz9eda9bf2021-01-08 00:41:13 +0000864 long long usage = (long long)me.get().m.usage;
865 if (C2DmaBufAllocator::system_uncached_supported() &&
866 !(usage & (C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE))) {
867 strncpy(me.set().m.heapName, "system-uncached", me.v.flexCount());
868 } else {
869 strncpy(me.set().m.heapName, "system", me.v.flexCount());
870 }
John Stultza7002cb2020-09-04 19:02:30 +0000871 me.set().m.allocFlags = 0;
872 return C2R::Ok();
873 };
Pawin Vongmasa36653902018-11-15 00:10:25 -0800874 };
875
876 addParameter(
877 DefineParam(mIonUsageInfo, "ion-usage")
878 .withDefault(new C2StoreIonUsageInfo())
879 .withFields({
880 C2F(mIonUsageInfo, usage).flags({C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE}),
881 C2F(mIonUsageInfo, capacity).inRange(0, UINT32_MAX, 1024),
882 C2F(mIonUsageInfo, heapMask).any(),
883 C2F(mIonUsageInfo, allocFlags).flags({}),
884 C2F(mIonUsageInfo, minAlignment).equalTo(0)
885 })
886 .withSetter(Setter::setIonUsage)
887 .build());
John Stultza7002cb2020-09-04 19:02:30 +0000888
889 addParameter(
890 DefineParam(mDmaBufUsageInfo, "dmabuf-usage")
891 .withDefault(C2StoreDmaBufUsageInfo::AllocShared(0))
892 .withFields({
893 C2F(mDmaBufUsageInfo, m.usage).flags({C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE}),
894 C2F(mDmaBufUsageInfo, m.capacity).inRange(0, UINT32_MAX, 1024),
895 C2F(mDmaBufUsageInfo, m.allocFlags).flags({}),
896 C2F(mDmaBufUsageInfo, m.heapName).any(),
897 })
898 .withSetter(Setter::setDmaBufUsage)
899 .build());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800900 }
901 };
902
903 /**
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800904 * Retrieves the component module for a component.
Pawin Vongmasa36653902018-11-15 00:10:25 -0800905 *
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800906 * \param module pointer to a shared_pointer where the component module will be stored on
907 * success.
Pawin Vongmasa36653902018-11-15 00:10:25 -0800908 *
909 * \retval C2_OK the component loader has been successfully retrieved
910 * \retval C2_NO_MEMORY not enough memory to locate the component loader
911 * \retval C2_NOT_FOUND could not locate the component to be loaded
912 * \retval C2_CORRUPTED the component loader could not be identified due to some modules being
913 * corrupted (this can happen if the name does not refer to an already
914 * identified component but some components could not be loaded due to
915 * bad library)
916 * \retval C2_REFUSED permission denied to find the component loader for the named component
917 * (this can happen if the name does not refer to an already identified
918 * component but some components could not be loaded due to lack of
919 * permissions)
920 */
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800921 c2_status_t findComponent(C2String name, std::shared_ptr<ComponentModule> *module);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800922
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800923 /**
924 * Loads each component module and discover its contents.
925 */
926 void visitComponents();
927
928 std::mutex mMutex; ///< mutex guarding the component lists during construction
929 bool mVisited; ///< component modules visited
930 std::map<C2String, ComponentLoader> mComponents; ///< path -> component module
931 std::map<C2String, C2String> mComponentNameToPath; ///< name -> path
932 std::vector<std::shared_ptr<const C2Component::Traits>> mComponentList;
933
Pawin Vongmasa36653902018-11-15 00:10:25 -0800934 std::shared_ptr<C2ReflectorHelper> mReflector;
935 Interface mInterface;
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530936
937 // For testing only
938 std::vector<std::tuple<C2String,
939 C2ComponentFactory::CreateCodec2FactoryFunc,
940 C2ComponentFactory::DestroyCodec2FactoryFunc>> mCodec2FactoryFuncs;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800941};
942
943c2_status_t C2PlatformComponentStore::ComponentModule::init(
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800944 std::string libPath) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800945 ALOGV("in %s", __func__);
946 ALOGV("loading dll");
Pawin Vongmasa36653902018-11-15 00:10:25 -0800947
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530948 if(!createFactory) {
949 mLibHandle = dlopen(libPath.c_str(), RTLD_NOW|RTLD_NODELETE);
950 LOG_ALWAYS_FATAL_IF(mLibHandle == nullptr,
951 "could not dlopen %s: %s", libPath.c_str(), dlerror());
Chong Zhangf5c7ca82019-04-23 17:06:21 -0700952
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530953 createFactory =
954 (C2ComponentFactory::CreateCodec2FactoryFunc)dlsym(mLibHandle, "CreateCodec2Factory");
955 LOG_ALWAYS_FATAL_IF(createFactory == nullptr,
956 "createFactory is null in %s", libPath.c_str());
957
958 destroyFactory =
959 (C2ComponentFactory::DestroyCodec2FactoryFunc)dlsym(mLibHandle, "DestroyCodec2Factory");
960 LOG_ALWAYS_FATAL_IF(destroyFactory == nullptr,
961 "destroyFactory is null in %s", libPath.c_str());
962 }
Chong Zhangf5c7ca82019-04-23 17:06:21 -0700963
964 mComponentFactory = createFactory();
965 if (mComponentFactory == nullptr) {
966 ALOGD("could not create factory in %s", libPath.c_str());
967 mInit = C2_NO_MEMORY;
Dongwon Kang673236b2019-05-08 09:02:21 -0700968 } else {
969 mInit = C2_OK;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800970 }
971
Dongwon Kang673236b2019-05-08 09:02:21 -0700972 if (mInit != C2_OK) {
973 return mInit;
974 }
Dongwon Kange55d13c2019-04-24 11:01:49 -0700975
Pawin Vongmasa36653902018-11-15 00:10:25 -0800976 std::shared_ptr<C2ComponentInterface> intf;
977 c2_status_t res = createInterface(0, &intf);
978 if (res != C2_OK) {
979 ALOGD("failed to create interface: %d", res);
980 return mInit;
981 }
982
983 std::shared_ptr<C2Component::Traits> traits(new (std::nothrow) C2Component::Traits);
984 if (traits) {
Wonsik Kimee92b522021-02-07 21:55:31 -0800985 if (!C2InterfaceUtils::FillTraitsFromInterface(traits.get(), intf)) {
986 ALOGD("Failed to fill traits from interface");
Pawin Vongmasa36653902018-11-15 00:10:25 -0800987 return mInit;
988 }
Lajos Molnar62d62d62019-01-31 16:26:46 -0800989
990 // TODO: get this properly from the store during emplace
991 switch (traits->domain) {
992 case C2Component::DOMAIN_AUDIO:
993 traits->rank = 8;
994 break;
995 default:
996 traits->rank = 512;
997 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800998 }
999 mTraits = traits;
1000
1001 return mInit;
1002}
1003
1004C2PlatformComponentStore::ComponentModule::~ComponentModule() {
1005 ALOGV("in %s", __func__);
1006 if (destroyFactory && mComponentFactory) {
1007 destroyFactory(mComponentFactory);
1008 }
1009 if (mLibHandle) {
1010 ALOGV("unloading dll");
1011 dlclose(mLibHandle);
1012 }
1013}
1014
1015c2_status_t C2PlatformComponentStore::ComponentModule::createInterface(
1016 c2_node_id_t id, std::shared_ptr<C2ComponentInterface> *interface,
1017 std::function<void(::C2ComponentInterface*)> deleter) {
1018 interface->reset();
1019 if (mInit != C2_OK) {
1020 return mInit;
1021 }
1022 std::shared_ptr<ComponentModule> module = shared_from_this();
1023 c2_status_t res = mComponentFactory->createInterface(
1024 id, interface, [module, deleter](C2ComponentInterface *p) mutable {
1025 // capture module so that we ensure we still have it while deleting interface
1026 deleter(p); // delete interface first
1027 module.reset(); // remove module ref (not technically needed)
1028 });
1029 return res;
1030}
1031
1032c2_status_t C2PlatformComponentStore::ComponentModule::createComponent(
1033 c2_node_id_t id, std::shared_ptr<C2Component> *component,
1034 std::function<void(::C2Component*)> deleter) {
1035 component->reset();
1036 if (mInit != C2_OK) {
1037 return mInit;
1038 }
1039 std::shared_ptr<ComponentModule> module = shared_from_this();
1040 c2_status_t res = mComponentFactory->createComponent(
1041 id, component, [module, deleter](C2Component *p) mutable {
1042 // capture module so that we ensure we still have it while deleting component
1043 deleter(p); // delete component first
1044 module.reset(); // remove module ref (not technically needed)
1045 });
1046 return res;
1047}
1048
1049std::shared_ptr<const C2Component::Traits> C2PlatformComponentStore::ComponentModule::getTraits() {
1050 std::unique_lock<std::recursive_mutex> lock(mLock);
1051 return mTraits;
1052}
1053
1054C2PlatformComponentStore::C2PlatformComponentStore()
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001055 : mVisited(false),
1056 mReflector(std::make_shared<C2ReflectorHelper>()),
Pawin Vongmasa36653902018-11-15 00:10:25 -08001057 mInterface(mReflector) {
1058
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001059 auto emplace = [this](const char *libPath) {
1060 mComponents.emplace(libPath, libPath);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001061 };
Pawin Vongmasa36653902018-11-15 00:10:25 -08001062
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001063 // TODO: move this also into a .so so it can be updated
1064 emplace("libcodec2_soft_aacdec.so");
1065 emplace("libcodec2_soft_aacenc.so");
1066 emplace("libcodec2_soft_amrnbdec.so");
1067 emplace("libcodec2_soft_amrnbenc.so");
1068 emplace("libcodec2_soft_amrwbdec.so");
1069 emplace("libcodec2_soft_amrwbenc.so");
Ray Essickc2cc4372019-08-21 14:02:28 -07001070 //emplace("libcodec2_soft_av1dec_aom.so"); // deprecated for the gav1 implementation
1071 emplace("libcodec2_soft_av1dec_gav1.so");
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001072 emplace("libcodec2_soft_avcdec.so");
1073 emplace("libcodec2_soft_avcenc.so");
1074 emplace("libcodec2_soft_flacdec.so");
1075 emplace("libcodec2_soft_flacenc.so");
1076 emplace("libcodec2_soft_g711alawdec.so");
1077 emplace("libcodec2_soft_g711mlawdec.so");
1078 emplace("libcodec2_soft_gsmdec.so");
1079 emplace("libcodec2_soft_h263dec.so");
1080 emplace("libcodec2_soft_h263enc.so");
1081 emplace("libcodec2_soft_hevcdec.so");
Roma Kauldfe650a2018-08-02 17:48:51 +05301082 emplace("libcodec2_soft_hevcenc.so");
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001083 emplace("libcodec2_soft_mp3dec.so");
1084 emplace("libcodec2_soft_mpeg2dec.so");
1085 emplace("libcodec2_soft_mpeg4dec.so");
1086 emplace("libcodec2_soft_mpeg4enc.so");
1087 emplace("libcodec2_soft_opusdec.so");
1088 emplace("libcodec2_soft_opusenc.so");
1089 emplace("libcodec2_soft_rawdec.so");
1090 emplace("libcodec2_soft_vorbisdec.so");
1091 emplace("libcodec2_soft_vp8dec.so");
1092 emplace("libcodec2_soft_vp8enc.so");
1093 emplace("libcodec2_soft_vp9dec.so");
1094 emplace("libcodec2_soft_vp9enc.so");
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +05301095
1096}
1097
1098// For testing only
1099C2PlatformComponentStore::C2PlatformComponentStore(
1100 std::vector<std::tuple<C2String,
1101 C2ComponentFactory::CreateCodec2FactoryFunc,
1102 C2ComponentFactory::DestroyCodec2FactoryFunc>> funcs)
1103 : mVisited(false),
1104 mReflector(std::make_shared<C2ReflectorHelper>()),
1105 mInterface(mReflector),
1106 mCodec2FactoryFuncs(funcs) {
1107
1108 for(auto const& func: mCodec2FactoryFuncs) {
1109 mComponents.emplace(std::get<0>(func), func);
1110 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001111}
1112
1113c2_status_t C2PlatformComponentStore::copyBuffer(
1114 std::shared_ptr<C2GraphicBuffer> src, std::shared_ptr<C2GraphicBuffer> dst) {
1115 (void)src;
1116 (void)dst;
1117 return C2_OMITTED;
1118}
1119
1120c2_status_t C2PlatformComponentStore::query_sm(
1121 const std::vector<C2Param*> &stackParams,
1122 const std::vector<C2Param::Index> &heapParamIndices,
1123 std::vector<std::unique_ptr<C2Param>> *const heapParams) const {
1124 return mInterface.query(stackParams, heapParamIndices, C2_MAY_BLOCK, heapParams);
1125}
1126
1127c2_status_t C2PlatformComponentStore::config_sm(
1128 const std::vector<C2Param*> &params,
1129 std::vector<std::unique_ptr<C2SettingResult>> *const failures) {
1130 return mInterface.config(params, C2_MAY_BLOCK, failures);
1131}
1132
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001133void C2PlatformComponentStore::visitComponents() {
1134 std::lock_guard<std::mutex> lock(mMutex);
1135 if (mVisited) {
1136 return;
1137 }
1138 for (auto &pathAndLoader : mComponents) {
1139 const C2String &path = pathAndLoader.first;
1140 ComponentLoader &loader = pathAndLoader.second;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001141 std::shared_ptr<ComponentModule> module;
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001142 if (loader.fetchModule(&module) == C2_OK) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001143 std::shared_ptr<const C2Component::Traits> traits = module->getTraits();
1144 if (traits) {
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001145 mComponentList.push_back(traits);
1146 mComponentNameToPath.emplace(traits->name, path);
1147 for (const C2String &alias : traits->aliases) {
1148 mComponentNameToPath.emplace(alias, path);
1149 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001150 }
1151 }
1152 }
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001153 mVisited = true;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001154}
1155
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001156std::vector<std::shared_ptr<const C2Component::Traits>> C2PlatformComponentStore::listComponents() {
1157 // This method SHALL return within 500ms.
1158 visitComponents();
1159 return mComponentList;
1160}
1161
1162c2_status_t C2PlatformComponentStore::findComponent(
1163 C2String name, std::shared_ptr<ComponentModule> *module) {
1164 (*module).reset();
1165 visitComponents();
1166
1167 auto pos = mComponentNameToPath.find(name);
1168 if (pos != mComponentNameToPath.end()) {
1169 return mComponents.at(pos->second).fetchModule(module);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001170 }
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001171 return C2_NOT_FOUND;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001172}
1173
1174c2_status_t C2PlatformComponentStore::createComponent(
1175 C2String name, std::shared_ptr<C2Component> *const component) {
1176 // This method SHALL return within 100ms.
1177 component->reset();
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001178 std::shared_ptr<ComponentModule> module;
1179 c2_status_t res = findComponent(name, &module);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001180 if (res == C2_OK) {
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001181 // TODO: get a unique node ID
1182 res = module->createComponent(0, component);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001183 }
1184 return res;
1185}
1186
1187c2_status_t C2PlatformComponentStore::createInterface(
1188 C2String name, std::shared_ptr<C2ComponentInterface> *const interface) {
1189 // This method SHALL return within 100ms.
1190 interface->reset();
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001191 std::shared_ptr<ComponentModule> module;
1192 c2_status_t res = findComponent(name, &module);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001193 if (res == C2_OK) {
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001194 // TODO: get a unique node ID
1195 res = module->createInterface(0, interface);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001196 }
1197 return res;
1198}
1199
1200c2_status_t C2PlatformComponentStore::querySupportedParams_nb(
1201 std::vector<std::shared_ptr<C2ParamDescriptor>> *const params) const {
1202 return mInterface.querySupportedParams(params);
1203}
1204
1205c2_status_t C2PlatformComponentStore::querySupportedValues_sm(
1206 std::vector<C2FieldSupportedValuesQuery> &fields) const {
1207 return mInterface.querySupportedValues(fields, C2_MAY_BLOCK);
1208}
1209
1210C2String C2PlatformComponentStore::getName() const {
1211 return "android.componentStore.platform";
1212}
1213
1214std::shared_ptr<C2ParamReflector> C2PlatformComponentStore::getParamReflector() const {
1215 return mReflector;
1216}
1217
1218std::shared_ptr<C2ComponentStore> GetCodec2PlatformComponentStore() {
1219 static std::mutex mutex;
1220 static std::weak_ptr<C2ComponentStore> platformStore;
1221 std::lock_guard<std::mutex> lock(mutex);
1222 std::shared_ptr<C2ComponentStore> store = platformStore.lock();
1223 if (store == nullptr) {
1224 store = std::make_shared<C2PlatformComponentStore>();
1225 platformStore = store;
1226 }
1227 return store;
1228}
1229
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +05301230// For testing only
1231std::shared_ptr<C2ComponentStore> GetTestComponentStore(
1232 std::vector<std::tuple<C2String,
1233 C2ComponentFactory::CreateCodec2FactoryFunc,
1234 C2ComponentFactory::DestroyCodec2FactoryFunc>> funcs) {
1235 return std::shared_ptr<C2ComponentStore>(new C2PlatformComponentStore(funcs));
1236}
Pawin Vongmasa36653902018-11-15 00:10:25 -08001237} // namespace android