blob: 74ef9ea282d1e2614b5eb891925f61ba7b8a08ec [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,
448 std::shared_ptr<const C2Component> component,
449 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;
469 mComponents[poolId] = component;
470 }
471 break;
472 case C2PlatformAllocatorStore::BLOB:
473 res = allocatorStore->fetchAllocator(
474 C2PlatformAllocatorStore::BLOB, &allocator);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800475 if (res == C2_OK) {
476 std::shared_ptr<C2BlockPool> ptr =
477 std::make_shared<C2PooledBlockPool>(
478 allocator, poolId);
479 *pool = ptr;
480 mBlockPools[poolId] = ptr;
481 mComponents[poolId] = component;
482 }
483 break;
484 case C2PlatformAllocatorStore::GRALLOC:
485 case C2AllocatorStore::DEFAULT_GRAPHIC:
486 res = allocatorStore->fetchAllocator(
487 C2AllocatorStore::DEFAULT_GRAPHIC, &allocator);
488 if (res == C2_OK) {
489 std::shared_ptr<C2BlockPool> ptr =
490 std::make_shared<C2PooledBlockPool>(allocator, poolId);
491 *pool = ptr;
492 mBlockPools[poolId] = ptr;
493 mComponents[poolId] = component;
494 }
495 break;
496 case C2PlatformAllocatorStore::BUFFERQUEUE:
497 res = allocatorStore->fetchAllocator(
498 C2PlatformAllocatorStore::BUFFERQUEUE, &allocator);
499 if (res == C2_OK) {
500 std::shared_ptr<C2BlockPool> ptr =
501 std::make_shared<C2BufferQueueBlockPool>(
502 allocator, poolId);
503 *pool = ptr;
504 mBlockPools[poolId] = ptr;
505 mComponents[poolId] = component;
506 }
507 break;
508 default:
509 // Try to create block pool from platform store plugins.
510 std::shared_ptr<C2BlockPool> ptr;
511 res = C2PlatformStorePluginLoader::GetInstance()->createBlockPool(
512 allocatorId, poolId, &ptr);
513 if (res == C2_OK) {
514 *pool = ptr;
515 mBlockPools[poolId] = ptr;
516 mComponents[poolId] = component;
517 }
518 break;
519 }
520 return res;
521 }
522
523 c2_status_t createBlockPool(
524 C2PlatformAllocatorStore::id_t allocatorId,
525 std::shared_ptr<const C2Component> component,
526 std::shared_ptr<C2BlockPool> *pool) {
527 return _createBlockPool(allocatorId, component, mBlockPoolSeqId++, pool);
528 }
529
530 bool getBlockPool(
531 C2BlockPool::local_id_t blockPoolId,
532 std::shared_ptr<const C2Component> component,
533 std::shared_ptr<C2BlockPool> *pool) {
534 // TODO: use one iterator for multiple blockpool type scalability.
535 std::shared_ptr<C2BlockPool> ptr;
536 auto it = mBlockPools.find(blockPoolId);
537 if (it != mBlockPools.end()) {
538 ptr = it->second.lock();
539 if (!ptr) {
540 mBlockPools.erase(it);
541 mComponents.erase(blockPoolId);
542 } else {
543 auto found = mComponents.find(blockPoolId);
544 if (component == found->second.lock()) {
545 *pool = ptr;
546 return true;
547 }
548 }
549 }
550 return false;
551 }
552
553private:
554 C2BlockPool::local_id_t mBlockPoolSeqId;
555
556 std::map<C2BlockPool::local_id_t, std::weak_ptr<C2BlockPool>> mBlockPools;
557 std::map<C2BlockPool::local_id_t, std::weak_ptr<const C2Component>> mComponents;
558};
559
560static std::unique_ptr<_C2BlockPoolCache> sBlockPoolCache =
561 std::make_unique<_C2BlockPoolCache>();
562static std::mutex sBlockPoolCacheMutex;
563
564} // anynymous namespace
565
566c2_status_t GetCodec2BlockPool(
567 C2BlockPool::local_id_t id, std::shared_ptr<const C2Component> component,
568 std::shared_ptr<C2BlockPool> *pool) {
569 pool->reset();
570 std::lock_guard<std::mutex> lock(sBlockPoolCacheMutex);
571 std::shared_ptr<C2AllocatorStore> allocatorStore = GetCodec2PlatformAllocatorStore();
572 std::shared_ptr<C2Allocator> allocator;
573 c2_status_t res = C2_NOT_FOUND;
574
575 if (id >= C2BlockPool::PLATFORM_START) {
576 if (sBlockPoolCache->getBlockPool(id, component, pool)) {
577 return C2_OK;
578 }
579 }
580
581 switch (id) {
582 case C2BlockPool::BASIC_LINEAR:
583 res = allocatorStore->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &allocator);
584 if (res == C2_OK) {
585 *pool = std::make_shared<C2BasicLinearBlockPool>(allocator);
586 }
587 break;
588 case C2BlockPool::BASIC_GRAPHIC:
589 res = allocatorStore->fetchAllocator(C2AllocatorStore::DEFAULT_GRAPHIC, &allocator);
590 if (res == C2_OK) {
591 *pool = std::make_shared<C2BasicGraphicBlockPool>(allocator);
592 }
593 break;
594 // TODO: remove this. this is temporary
595 case C2BlockPool::PLATFORM_START:
596 res = sBlockPoolCache->_createBlockPool(
597 C2PlatformAllocatorStore::BUFFERQUEUE, component, id, pool);
598 break;
599 default:
600 break;
601 }
602 return res;
603}
604
605c2_status_t CreateCodec2BlockPool(
606 C2PlatformAllocatorStore::id_t allocatorId,
607 std::shared_ptr<const C2Component> component,
608 std::shared_ptr<C2BlockPool> *pool) {
609 pool->reset();
610
611 std::lock_guard<std::mutex> lock(sBlockPoolCacheMutex);
612 return sBlockPoolCache->createBlockPool(allocatorId, component, pool);
613}
614
615class C2PlatformComponentStore : public C2ComponentStore {
616public:
617 virtual std::vector<std::shared_ptr<const C2Component::Traits>> listComponents() override;
618 virtual std::shared_ptr<C2ParamReflector> getParamReflector() const override;
619 virtual C2String getName() const override;
620 virtual c2_status_t querySupportedValues_sm(
621 std::vector<C2FieldSupportedValuesQuery> &fields) const override;
622 virtual c2_status_t querySupportedParams_nb(
623 std::vector<std::shared_ptr<C2ParamDescriptor>> *const params) const override;
624 virtual c2_status_t query_sm(
625 const std::vector<C2Param*> &stackParams,
626 const std::vector<C2Param::Index> &heapParamIndices,
627 std::vector<std::unique_ptr<C2Param>> *const heapParams) const override;
628 virtual c2_status_t createInterface(
629 C2String name, std::shared_ptr<C2ComponentInterface> *const interface) override;
630 virtual c2_status_t createComponent(
631 C2String name, std::shared_ptr<C2Component> *const component) override;
632 virtual c2_status_t copyBuffer(
633 std::shared_ptr<C2GraphicBuffer> src, std::shared_ptr<C2GraphicBuffer> dst) override;
634 virtual c2_status_t config_sm(
635 const std::vector<C2Param*> &params,
636 std::vector<std::unique_ptr<C2SettingResult>> *const failures) override;
637 C2PlatformComponentStore();
638
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530639 // For testing only
640 C2PlatformComponentStore(
641 std::vector<std::tuple<C2String,
642 C2ComponentFactory::CreateCodec2FactoryFunc,
643 C2ComponentFactory::DestroyCodec2FactoryFunc>>);
644
Pawin Vongmasa36653902018-11-15 00:10:25 -0800645 virtual ~C2PlatformComponentStore() override = default;
646
647private:
648
649 /**
650 * An object encapsulating a loaded component module.
651 *
652 * \todo provide a way to add traits to known components here to avoid loading the .so-s
653 * for listComponents
654 */
655 struct ComponentModule : public C2ComponentFactory,
656 public std::enable_shared_from_this<ComponentModule> {
657 virtual c2_status_t createComponent(
658 c2_node_id_t id, std::shared_ptr<C2Component> *component,
659 ComponentDeleter deleter = std::default_delete<C2Component>()) override;
660 virtual c2_status_t createInterface(
661 c2_node_id_t id, std::shared_ptr<C2ComponentInterface> *interface,
662 InterfaceDeleter deleter = std::default_delete<C2ComponentInterface>()) override;
663
664 /**
665 * \returns the traits of the component in this module.
666 */
667 std::shared_ptr<const C2Component::Traits> getTraits();
668
669 /**
670 * Creates an uninitialized component module.
671 *
672 * \param name[in] component name.
673 *
674 * \note Only used by ComponentLoader.
675 */
676 ComponentModule()
677 : mInit(C2_NO_INIT),
678 mLibHandle(nullptr),
679 createFactory(nullptr),
680 destroyFactory(nullptr),
681 mComponentFactory(nullptr) {
682 }
683
684 /**
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530685 * Creates an uninitialized component module.
686 * NOTE: For testing only
687 *
688 * \param name[in] component name.
689 *
690 * \note Only used by ComponentLoader.
691 */
692 ComponentModule(
693 C2ComponentFactory::CreateCodec2FactoryFunc createFactory,
694 C2ComponentFactory::DestroyCodec2FactoryFunc destroyFactory)
695 : mInit(C2_NO_INIT),
696 mLibHandle(nullptr),
697 createFactory(createFactory),
698 destroyFactory(destroyFactory),
699 mComponentFactory(nullptr) {
700 }
701
702 /**
Pawin Vongmasa36653902018-11-15 00:10:25 -0800703 * Initializes a component module with a given library path. Must be called exactly once.
704 *
705 * \note Only used by ComponentLoader.
706 *
Pawin Vongmasa36653902018-11-15 00:10:25 -0800707 * \param libPath[in] library path
708 *
709 * \retval C2_OK the component module has been successfully loaded
710 * \retval C2_NO_MEMORY not enough memory to loading the component module
711 * \retval C2_NOT_FOUND could not locate the component module
712 * \retval C2_CORRUPTED the component module could not be loaded (unexpected)
713 * \retval C2_REFUSED permission denied to load the component module (unexpected)
714 * \retval C2_TIMED_OUT could not load the module within the time limit (unexpected)
715 */
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800716 c2_status_t init(std::string libPath);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800717
718 virtual ~ComponentModule() override;
719
720 protected:
721 std::recursive_mutex mLock; ///< lock protecting mTraits
722 std::shared_ptr<C2Component::Traits> mTraits; ///< cached component traits
723
724 c2_status_t mInit; ///< initialization result
725
726 void *mLibHandle; ///< loaded library handle
727 C2ComponentFactory::CreateCodec2FactoryFunc createFactory; ///< loaded create function
728 C2ComponentFactory::DestroyCodec2FactoryFunc destroyFactory; ///< loaded destroy function
729 C2ComponentFactory *mComponentFactory; ///< loaded/created component factory
730 };
731
732 /**
733 * An object encapsulating a loadable component module.
734 *
735 * \todo make this also work for enumerations
736 */
737 struct ComponentLoader {
738 /**
739 * Load the component module.
740 *
741 * This method simply returns the component module if it is already currently loaded, or
742 * attempts to load it if it is not.
743 *
744 * \param module[out] pointer to the shared pointer where the loaded module shall be stored.
745 * This will be nullptr on error.
746 *
747 * \retval C2_OK the component module has been successfully loaded
748 * \retval C2_NO_MEMORY not enough memory to loading the component module
749 * \retval C2_NOT_FOUND could not locate the component module
750 * \retval C2_CORRUPTED the component module could not be loaded
751 * \retval C2_REFUSED permission denied to load the component module
752 */
753 c2_status_t fetchModule(std::shared_ptr<ComponentModule> *module) {
754 c2_status_t res = C2_OK;
755 std::lock_guard<std::mutex> lock(mMutex);
756 std::shared_ptr<ComponentModule> localModule = mModule.lock();
757 if (localModule == nullptr) {
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530758 if(mCreateFactory) {
759 // For testing only
760 localModule = std::make_shared<ComponentModule>(mCreateFactory,
761 mDestroyFactory);
762 } else {
763 localModule = std::make_shared<ComponentModule>();
764 }
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800765 res = localModule->init(mLibPath);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800766 if (res == C2_OK) {
767 mModule = localModule;
768 }
769 }
770 *module = localModule;
771 return res;
772 }
773
774 /**
775 * Creates a component loader for a specific library path (or name).
776 */
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800777 ComponentLoader(std::string libPath)
778 : mLibPath(libPath) {}
Pawin Vongmasa36653902018-11-15 00:10:25 -0800779
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530780 // For testing only
781 ComponentLoader(std::tuple<C2String,
782 C2ComponentFactory::CreateCodec2FactoryFunc,
783 C2ComponentFactory::DestroyCodec2FactoryFunc> func)
784 : mLibPath(std::get<0>(func)),
785 mCreateFactory(std::get<1>(func)),
786 mDestroyFactory(std::get<2>(func)) {}
787
Pawin Vongmasa36653902018-11-15 00:10:25 -0800788 private:
789 std::mutex mMutex; ///< mutex guarding the module
790 std::weak_ptr<ComponentModule> mModule; ///< weak reference to the loaded module
Pawin Vongmasa36653902018-11-15 00:10:25 -0800791 std::string mLibPath; ///< library path
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530792
793 // For testing only
794 C2ComponentFactory::CreateCodec2FactoryFunc mCreateFactory = nullptr;
795 C2ComponentFactory::DestroyCodec2FactoryFunc mDestroyFactory = nullptr;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800796 };
797
798 struct Interface : public C2InterfaceHelper {
799 std::shared_ptr<C2StoreIonUsageInfo> mIonUsageInfo;
John Stultza7002cb2020-09-04 19:02:30 +0000800 std::shared_ptr<C2StoreDmaBufUsageInfo> mDmaBufUsageInfo;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800801
802 Interface(std::shared_ptr<C2ReflectorHelper> reflector)
803 : C2InterfaceHelper(reflector) {
804 setDerivedInstance(this);
805
806 struct Setter {
807 static C2R setIonUsage(bool /* mayBlock */, C2P<C2StoreIonUsageInfo> &me) {
Wonsik Kimba3db192019-11-22 11:00:48 -0800808#ifdef __ANDROID_APEX__
809 static int32_t defaultHeapMask = [] {
810 int32_t heapmask = base::GetIntProperty(
811 "ro.com.android.media.swcodec.ion.heapmask", int32_t(0xFFFFFFFF));
812 ALOGD("Default ION heapmask = %d", heapmask);
813 return heapmask;
814 }();
815 static int32_t defaultFlags = [] {
816 int32_t flags = base::GetIntProperty(
817 "ro.com.android.media.swcodec.ion.flags", 0);
818 ALOGD("Default ION flags = %d", flags);
819 return flags;
820 }();
821 static uint32_t defaultAlign = [] {
822 uint32_t align = base::GetUintProperty(
823 "ro.com.android.media.swcodec.ion.align", 0u);
824 ALOGD("Default ION align = %d", align);
825 return align;
826 }();
827 me.set().heapMask = defaultHeapMask;
828 me.set().allocFlags = defaultFlags;
829 me.set().minAlignment = defaultAlign;
830#else
Pawin Vongmasa36653902018-11-15 00:10:25 -0800831 me.set().heapMask = ~0;
832 me.set().allocFlags = 0;
833 me.set().minAlignment = 0;
Wonsik Kimba3db192019-11-22 11:00:48 -0800834#endif
Pawin Vongmasa36653902018-11-15 00:10:25 -0800835 return C2R::Ok();
John Stultza7002cb2020-09-04 19:02:30 +0000836 };
837
838 static C2R setDmaBufUsage(bool /* mayBlock */, C2P<C2StoreDmaBufUsageInfo> &me) {
John Stultz9eda9bf2021-01-08 00:41:13 +0000839 long long usage = (long long)me.get().m.usage;
840 if (C2DmaBufAllocator::system_uncached_supported() &&
841 !(usage & (C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE))) {
842 strncpy(me.set().m.heapName, "system-uncached", me.v.flexCount());
843 } else {
844 strncpy(me.set().m.heapName, "system", me.v.flexCount());
845 }
John Stultza7002cb2020-09-04 19:02:30 +0000846 me.set().m.allocFlags = 0;
847 return C2R::Ok();
848 };
Pawin Vongmasa36653902018-11-15 00:10:25 -0800849 };
850
851 addParameter(
852 DefineParam(mIonUsageInfo, "ion-usage")
853 .withDefault(new C2StoreIonUsageInfo())
854 .withFields({
855 C2F(mIonUsageInfo, usage).flags({C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE}),
856 C2F(mIonUsageInfo, capacity).inRange(0, UINT32_MAX, 1024),
857 C2F(mIonUsageInfo, heapMask).any(),
858 C2F(mIonUsageInfo, allocFlags).flags({}),
859 C2F(mIonUsageInfo, minAlignment).equalTo(0)
860 })
861 .withSetter(Setter::setIonUsage)
862 .build());
John Stultza7002cb2020-09-04 19:02:30 +0000863
864 addParameter(
865 DefineParam(mDmaBufUsageInfo, "dmabuf-usage")
866 .withDefault(C2StoreDmaBufUsageInfo::AllocShared(0))
867 .withFields({
868 C2F(mDmaBufUsageInfo, m.usage).flags({C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE}),
869 C2F(mDmaBufUsageInfo, m.capacity).inRange(0, UINT32_MAX, 1024),
870 C2F(mDmaBufUsageInfo, m.allocFlags).flags({}),
871 C2F(mDmaBufUsageInfo, m.heapName).any(),
872 })
873 .withSetter(Setter::setDmaBufUsage)
874 .build());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800875 }
876 };
877
878 /**
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800879 * Retrieves the component module for a component.
Pawin Vongmasa36653902018-11-15 00:10:25 -0800880 *
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800881 * \param module pointer to a shared_pointer where the component module will be stored on
882 * success.
Pawin Vongmasa36653902018-11-15 00:10:25 -0800883 *
884 * \retval C2_OK the component loader has been successfully retrieved
885 * \retval C2_NO_MEMORY not enough memory to locate the component loader
886 * \retval C2_NOT_FOUND could not locate the component to be loaded
887 * \retval C2_CORRUPTED the component loader could not be identified due to some modules being
888 * corrupted (this can happen if the name does not refer to an already
889 * identified component but some components could not be loaded due to
890 * bad library)
891 * \retval C2_REFUSED permission denied to find the component loader for the named component
892 * (this can happen if the name does not refer to an already identified
893 * component but some components could not be loaded due to lack of
894 * permissions)
895 */
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800896 c2_status_t findComponent(C2String name, std::shared_ptr<ComponentModule> *module);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800897
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800898 /**
899 * Loads each component module and discover its contents.
900 */
901 void visitComponents();
902
903 std::mutex mMutex; ///< mutex guarding the component lists during construction
904 bool mVisited; ///< component modules visited
905 std::map<C2String, ComponentLoader> mComponents; ///< path -> component module
906 std::map<C2String, C2String> mComponentNameToPath; ///< name -> path
907 std::vector<std::shared_ptr<const C2Component::Traits>> mComponentList;
908
Pawin Vongmasa36653902018-11-15 00:10:25 -0800909 std::shared_ptr<C2ReflectorHelper> mReflector;
910 Interface mInterface;
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530911
912 // For testing only
913 std::vector<std::tuple<C2String,
914 C2ComponentFactory::CreateCodec2FactoryFunc,
915 C2ComponentFactory::DestroyCodec2FactoryFunc>> mCodec2FactoryFuncs;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800916};
917
918c2_status_t C2PlatformComponentStore::ComponentModule::init(
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800919 std::string libPath) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800920 ALOGV("in %s", __func__);
921 ALOGV("loading dll");
Pawin Vongmasa36653902018-11-15 00:10:25 -0800922
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530923 if(!createFactory) {
924 mLibHandle = dlopen(libPath.c_str(), RTLD_NOW|RTLD_NODELETE);
925 LOG_ALWAYS_FATAL_IF(mLibHandle == nullptr,
926 "could not dlopen %s: %s", libPath.c_str(), dlerror());
Chong Zhangf5c7ca82019-04-23 17:06:21 -0700927
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530928 createFactory =
929 (C2ComponentFactory::CreateCodec2FactoryFunc)dlsym(mLibHandle, "CreateCodec2Factory");
930 LOG_ALWAYS_FATAL_IF(createFactory == nullptr,
931 "createFactory is null in %s", libPath.c_str());
932
933 destroyFactory =
934 (C2ComponentFactory::DestroyCodec2FactoryFunc)dlsym(mLibHandle, "DestroyCodec2Factory");
935 LOG_ALWAYS_FATAL_IF(destroyFactory == nullptr,
936 "destroyFactory is null in %s", libPath.c_str());
937 }
Chong Zhangf5c7ca82019-04-23 17:06:21 -0700938
939 mComponentFactory = createFactory();
940 if (mComponentFactory == nullptr) {
941 ALOGD("could not create factory in %s", libPath.c_str());
942 mInit = C2_NO_MEMORY;
Dongwon Kang673236b2019-05-08 09:02:21 -0700943 } else {
944 mInit = C2_OK;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800945 }
946
Dongwon Kang673236b2019-05-08 09:02:21 -0700947 if (mInit != C2_OK) {
948 return mInit;
949 }
Dongwon Kange55d13c2019-04-24 11:01:49 -0700950
Pawin Vongmasa36653902018-11-15 00:10:25 -0800951 std::shared_ptr<C2ComponentInterface> intf;
952 c2_status_t res = createInterface(0, &intf);
953 if (res != C2_OK) {
954 ALOGD("failed to create interface: %d", res);
955 return mInit;
956 }
957
958 std::shared_ptr<C2Component::Traits> traits(new (std::nothrow) C2Component::Traits);
959 if (traits) {
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800960 traits->name = intf->getName();
Lajos Molnar62d62d62019-01-31 16:26:46 -0800961
962 C2ComponentKindSetting kind;
963 C2ComponentDomainSetting domain;
964 res = intf->query_vb({ &kind, &domain }, {}, C2_MAY_BLOCK, nullptr);
965 bool fixDomain = res != C2_OK;
966 if (res == C2_OK) {
967 traits->kind = kind.value;
968 traits->domain = domain.value;
969 } else {
970 // TODO: remove this fall-back
971 ALOGD("failed to query interface for kind and domain: %d", res);
972
973 traits->kind =
974 (traits->name.find("encoder") != std::string::npos) ? C2Component::KIND_ENCODER :
975 (traits->name.find("decoder") != std::string::npos) ? C2Component::KIND_DECODER :
976 C2Component::KIND_OTHER;
977 }
978
979 uint32_t mediaTypeIndex =
Lajos Molnar3bb81cd2019-02-20 15:10:30 -0800980 traits->kind == C2Component::KIND_ENCODER ? C2PortMediaTypeSetting::output::PARAM_TYPE
981 : C2PortMediaTypeSetting::input::PARAM_TYPE;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800982 std::vector<std::unique_ptr<C2Param>> params;
983 res = intf->query_vb({}, { mediaTypeIndex }, C2_MAY_BLOCK, &params);
984 if (res != C2_OK) {
985 ALOGD("failed to query interface: %d", res);
986 return mInit;
987 }
988 if (params.size() != 1u) {
989 ALOGD("failed to query interface: unexpected vector size: %zu", params.size());
990 return mInit;
991 }
Lajos Molnar3bb81cd2019-02-20 15:10:30 -0800992 C2PortMediaTypeSetting *mediaTypeConfig = C2PortMediaTypeSetting::From(params[0].get());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800993 if (mediaTypeConfig == nullptr) {
994 ALOGD("failed to query media type");
995 return mInit;
996 }
Lajos Molnar62d62d62019-01-31 16:26:46 -0800997 traits->mediaType =
998 std::string(mediaTypeConfig->m.value,
999 strnlen(mediaTypeConfig->m.value, mediaTypeConfig->flexCount()));
Pawin Vongmasa36653902018-11-15 00:10:25 -08001000
Lajos Molnar62d62d62019-01-31 16:26:46 -08001001 if (fixDomain) {
1002 if (strncmp(traits->mediaType.c_str(), "audio/", 6) == 0) {
1003 traits->domain = C2Component::DOMAIN_AUDIO;
1004 } else if (strncmp(traits->mediaType.c_str(), "video/", 6) == 0) {
1005 traits->domain = C2Component::DOMAIN_VIDEO;
1006 } else if (strncmp(traits->mediaType.c_str(), "image/", 6) == 0) {
1007 traits->domain = C2Component::DOMAIN_IMAGE;
1008 } else {
1009 traits->domain = C2Component::DOMAIN_OTHER;
1010 }
1011 }
1012
1013 // TODO: get this properly from the store during emplace
1014 switch (traits->domain) {
1015 case C2Component::DOMAIN_AUDIO:
1016 traits->rank = 8;
1017 break;
1018 default:
1019 traits->rank = 512;
1020 }
1021
1022 params.clear();
1023 res = intf->query_vb({}, { C2ComponentAliasesSetting::PARAM_TYPE }, C2_MAY_BLOCK, &params);
1024 if (res == C2_OK && params.size() == 1u) {
1025 C2ComponentAliasesSetting *aliasesSetting =
1026 C2ComponentAliasesSetting::From(params[0].get());
1027 if (aliasesSetting) {
1028 // Split aliases on ','
1029 // This looks simpler in plain C and even std::string would still make a copy.
1030 char *aliases = ::strndup(aliasesSetting->m.value, aliasesSetting->flexCount());
1031 ALOGD("'%s' has aliases: '%s'", intf->getName().c_str(), aliases);
1032
1033 for (char *tok, *ptr, *str = aliases; (tok = ::strtok_r(str, ",", &ptr));
1034 str = nullptr) {
1035 traits->aliases.push_back(tok);
1036 ALOGD("adding alias: '%s'", tok);
1037 }
1038 free(aliases);
1039 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001040 }
1041 }
1042 mTraits = traits;
1043
1044 return mInit;
1045}
1046
1047C2PlatformComponentStore::ComponentModule::~ComponentModule() {
1048 ALOGV("in %s", __func__);
1049 if (destroyFactory && mComponentFactory) {
1050 destroyFactory(mComponentFactory);
1051 }
1052 if (mLibHandle) {
1053 ALOGV("unloading dll");
1054 dlclose(mLibHandle);
1055 }
1056}
1057
1058c2_status_t C2PlatformComponentStore::ComponentModule::createInterface(
1059 c2_node_id_t id, std::shared_ptr<C2ComponentInterface> *interface,
1060 std::function<void(::C2ComponentInterface*)> deleter) {
1061 interface->reset();
1062 if (mInit != C2_OK) {
1063 return mInit;
1064 }
1065 std::shared_ptr<ComponentModule> module = shared_from_this();
1066 c2_status_t res = mComponentFactory->createInterface(
1067 id, interface, [module, deleter](C2ComponentInterface *p) mutable {
1068 // capture module so that we ensure we still have it while deleting interface
1069 deleter(p); // delete interface first
1070 module.reset(); // remove module ref (not technically needed)
1071 });
1072 return res;
1073}
1074
1075c2_status_t C2PlatformComponentStore::ComponentModule::createComponent(
1076 c2_node_id_t id, std::shared_ptr<C2Component> *component,
1077 std::function<void(::C2Component*)> deleter) {
1078 component->reset();
1079 if (mInit != C2_OK) {
1080 return mInit;
1081 }
1082 std::shared_ptr<ComponentModule> module = shared_from_this();
1083 c2_status_t res = mComponentFactory->createComponent(
1084 id, component, [module, deleter](C2Component *p) mutable {
1085 // capture module so that we ensure we still have it while deleting component
1086 deleter(p); // delete component first
1087 module.reset(); // remove module ref (not technically needed)
1088 });
1089 return res;
1090}
1091
1092std::shared_ptr<const C2Component::Traits> C2PlatformComponentStore::ComponentModule::getTraits() {
1093 std::unique_lock<std::recursive_mutex> lock(mLock);
1094 return mTraits;
1095}
1096
1097C2PlatformComponentStore::C2PlatformComponentStore()
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001098 : mVisited(false),
1099 mReflector(std::make_shared<C2ReflectorHelper>()),
Pawin Vongmasa36653902018-11-15 00:10:25 -08001100 mInterface(mReflector) {
1101
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001102 auto emplace = [this](const char *libPath) {
1103 mComponents.emplace(libPath, libPath);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001104 };
Pawin Vongmasa36653902018-11-15 00:10:25 -08001105
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001106 // TODO: move this also into a .so so it can be updated
1107 emplace("libcodec2_soft_aacdec.so");
1108 emplace("libcodec2_soft_aacenc.so");
1109 emplace("libcodec2_soft_amrnbdec.so");
1110 emplace("libcodec2_soft_amrnbenc.so");
1111 emplace("libcodec2_soft_amrwbdec.so");
1112 emplace("libcodec2_soft_amrwbenc.so");
Ray Essickc2cc4372019-08-21 14:02:28 -07001113 //emplace("libcodec2_soft_av1dec_aom.so"); // deprecated for the gav1 implementation
1114 emplace("libcodec2_soft_av1dec_gav1.so");
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001115 emplace("libcodec2_soft_avcdec.so");
1116 emplace("libcodec2_soft_avcenc.so");
1117 emplace("libcodec2_soft_flacdec.so");
1118 emplace("libcodec2_soft_flacenc.so");
1119 emplace("libcodec2_soft_g711alawdec.so");
1120 emplace("libcodec2_soft_g711mlawdec.so");
1121 emplace("libcodec2_soft_gsmdec.so");
1122 emplace("libcodec2_soft_h263dec.so");
1123 emplace("libcodec2_soft_h263enc.so");
1124 emplace("libcodec2_soft_hevcdec.so");
Roma Kauldfe650a2018-08-02 17:48:51 +05301125 emplace("libcodec2_soft_hevcenc.so");
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001126 emplace("libcodec2_soft_mp3dec.so");
1127 emplace("libcodec2_soft_mpeg2dec.so");
1128 emplace("libcodec2_soft_mpeg4dec.so");
1129 emplace("libcodec2_soft_mpeg4enc.so");
1130 emplace("libcodec2_soft_opusdec.so");
1131 emplace("libcodec2_soft_opusenc.so");
1132 emplace("libcodec2_soft_rawdec.so");
1133 emplace("libcodec2_soft_vorbisdec.so");
1134 emplace("libcodec2_soft_vp8dec.so");
1135 emplace("libcodec2_soft_vp8enc.so");
1136 emplace("libcodec2_soft_vp9dec.so");
1137 emplace("libcodec2_soft_vp9enc.so");
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +05301138
1139}
1140
1141// For testing only
1142C2PlatformComponentStore::C2PlatformComponentStore(
1143 std::vector<std::tuple<C2String,
1144 C2ComponentFactory::CreateCodec2FactoryFunc,
1145 C2ComponentFactory::DestroyCodec2FactoryFunc>> funcs)
1146 : mVisited(false),
1147 mReflector(std::make_shared<C2ReflectorHelper>()),
1148 mInterface(mReflector),
1149 mCodec2FactoryFuncs(funcs) {
1150
1151 for(auto const& func: mCodec2FactoryFuncs) {
1152 mComponents.emplace(std::get<0>(func), func);
1153 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001154}
1155
1156c2_status_t C2PlatformComponentStore::copyBuffer(
1157 std::shared_ptr<C2GraphicBuffer> src, std::shared_ptr<C2GraphicBuffer> dst) {
1158 (void)src;
1159 (void)dst;
1160 return C2_OMITTED;
1161}
1162
1163c2_status_t C2PlatformComponentStore::query_sm(
1164 const std::vector<C2Param*> &stackParams,
1165 const std::vector<C2Param::Index> &heapParamIndices,
1166 std::vector<std::unique_ptr<C2Param>> *const heapParams) const {
1167 return mInterface.query(stackParams, heapParamIndices, C2_MAY_BLOCK, heapParams);
1168}
1169
1170c2_status_t C2PlatformComponentStore::config_sm(
1171 const std::vector<C2Param*> &params,
1172 std::vector<std::unique_ptr<C2SettingResult>> *const failures) {
1173 return mInterface.config(params, C2_MAY_BLOCK, failures);
1174}
1175
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001176void C2PlatformComponentStore::visitComponents() {
1177 std::lock_guard<std::mutex> lock(mMutex);
1178 if (mVisited) {
1179 return;
1180 }
1181 for (auto &pathAndLoader : mComponents) {
1182 const C2String &path = pathAndLoader.first;
1183 ComponentLoader &loader = pathAndLoader.second;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001184 std::shared_ptr<ComponentModule> module;
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001185 if (loader.fetchModule(&module) == C2_OK) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001186 std::shared_ptr<const C2Component::Traits> traits = module->getTraits();
1187 if (traits) {
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001188 mComponentList.push_back(traits);
1189 mComponentNameToPath.emplace(traits->name, path);
1190 for (const C2String &alias : traits->aliases) {
1191 mComponentNameToPath.emplace(alias, path);
1192 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001193 }
1194 }
1195 }
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001196 mVisited = true;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001197}
1198
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001199std::vector<std::shared_ptr<const C2Component::Traits>> C2PlatformComponentStore::listComponents() {
1200 // This method SHALL return within 500ms.
1201 visitComponents();
1202 return mComponentList;
1203}
1204
1205c2_status_t C2PlatformComponentStore::findComponent(
1206 C2String name, std::shared_ptr<ComponentModule> *module) {
1207 (*module).reset();
1208 visitComponents();
1209
1210 auto pos = mComponentNameToPath.find(name);
1211 if (pos != mComponentNameToPath.end()) {
1212 return mComponents.at(pos->second).fetchModule(module);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001213 }
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001214 return C2_NOT_FOUND;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001215}
1216
1217c2_status_t C2PlatformComponentStore::createComponent(
1218 C2String name, std::shared_ptr<C2Component> *const component) {
1219 // This method SHALL return within 100ms.
1220 component->reset();
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001221 std::shared_ptr<ComponentModule> module;
1222 c2_status_t res = findComponent(name, &module);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001223 if (res == C2_OK) {
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001224 // TODO: get a unique node ID
1225 res = module->createComponent(0, component);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001226 }
1227 return res;
1228}
1229
1230c2_status_t C2PlatformComponentStore::createInterface(
1231 C2String name, std::shared_ptr<C2ComponentInterface> *const interface) {
1232 // This method SHALL return within 100ms.
1233 interface->reset();
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001234 std::shared_ptr<ComponentModule> module;
1235 c2_status_t res = findComponent(name, &module);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001236 if (res == C2_OK) {
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001237 // TODO: get a unique node ID
1238 res = module->createInterface(0, interface);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001239 }
1240 return res;
1241}
1242
1243c2_status_t C2PlatformComponentStore::querySupportedParams_nb(
1244 std::vector<std::shared_ptr<C2ParamDescriptor>> *const params) const {
1245 return mInterface.querySupportedParams(params);
1246}
1247
1248c2_status_t C2PlatformComponentStore::querySupportedValues_sm(
1249 std::vector<C2FieldSupportedValuesQuery> &fields) const {
1250 return mInterface.querySupportedValues(fields, C2_MAY_BLOCK);
1251}
1252
1253C2String C2PlatformComponentStore::getName() const {
1254 return "android.componentStore.platform";
1255}
1256
1257std::shared_ptr<C2ParamReflector> C2PlatformComponentStore::getParamReflector() const {
1258 return mReflector;
1259}
1260
1261std::shared_ptr<C2ComponentStore> GetCodec2PlatformComponentStore() {
1262 static std::mutex mutex;
1263 static std::weak_ptr<C2ComponentStore> platformStore;
1264 std::lock_guard<std::mutex> lock(mutex);
1265 std::shared_ptr<C2ComponentStore> store = platformStore.lock();
1266 if (store == nullptr) {
1267 store = std::make_shared<C2PlatformComponentStore>();
1268 platformStore = store;
1269 }
1270 return store;
1271}
1272
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +05301273// For testing only
1274std::shared_ptr<C2ComponentStore> GetTestComponentStore(
1275 std::vector<std::tuple<C2String,
1276 C2ComponentFactory::CreateCodec2FactoryFunc,
1277 C2ComponentFactory::DestroyCodec2FactoryFunc>> funcs) {
1278 return std::shared_ptr<C2ComponentStore>(new C2PlatformComponentStore(funcs));
1279}
Pawin Vongmasa36653902018-11-15 00:10:25 -08001280} // namespace android