blob: 499ab72318b0f108fb70dc310d359764148ad37e [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) {
105 static int cached_result = -1;
106
107 if (cached_result == -1) {
108 struct stat buffer;
109 cached_result = (stat("/dev/ion", &buffer) == 0);
110 if (cached_result)
111 ALOGD("Using ION\n");
112 else
113 ALOGD("Using DMABUF Heaps\n");
114 }
115 return (cached_result == 1);
116}
117
Pawin Vongmasa36653902018-11-15 00:10:25 -0800118c2_status_t C2PlatformAllocatorStoreImpl::fetchAllocator(
119 id_t id, std::shared_ptr<C2Allocator> *const allocator) {
120 allocator->reset();
Pin-chih Linaa18ea52019-11-19 18:48:50 +0800121 if (id == C2AllocatorStore::DEFAULT_LINEAR) {
122 id = GetPreferredLinearAllocatorId(GetCodec2PoolMask());
123 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800124 switch (id) {
125 // TODO: should we implement a generic registry for all, and use that?
John Stultza7002cb2020-09-04 19:02:30 +0000126 case C2PlatformAllocatorStore::ION: /* also ::DMABUFHEAP */
127 if (using_ion())
128 *allocator = fetchIonAllocator();
129 else
130 *allocator = fetchDmaBufAllocator();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800131 break;
132
133 case C2PlatformAllocatorStore::GRALLOC:
134 case C2AllocatorStore::DEFAULT_GRAPHIC:
135 *allocator = fetchGrallocAllocator();
136 break;
137
138 case C2PlatformAllocatorStore::BUFFERQUEUE:
139 *allocator = fetchBufferQueueAllocator();
140 break;
141
Pin-chih Linaa18ea52019-11-19 18:48:50 +0800142 case C2PlatformAllocatorStore::BLOB:
143 *allocator = fetchBlobAllocator();
144 break;
145
Pawin Vongmasa36653902018-11-15 00:10:25 -0800146 default:
147 // Try to create allocator from platform store plugins.
148 c2_status_t res =
149 C2PlatformStorePluginLoader::GetInstance()->createAllocator(id, allocator);
150 if (res != C2_OK) {
151 return res;
152 }
153 break;
154 }
155 if (*allocator == nullptr) {
156 return C2_NO_MEMORY;
157 }
158 return C2_OK;
159}
160
161namespace {
162
163std::mutex gIonAllocatorMutex;
John Stultza7002cb2020-09-04 19:02:30 +0000164std::mutex gDmaBufAllocatorMutex;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800165std::weak_ptr<C2AllocatorIon> gIonAllocator;
John Stultza7002cb2020-09-04 19:02:30 +0000166std::weak_ptr<C2DmaBufAllocator> gDmaBufAllocator;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800167
168void UseComponentStoreForIonAllocator(
169 const std::shared_ptr<C2AllocatorIon> allocator,
170 std::shared_ptr<C2ComponentStore> store) {
171 C2AllocatorIon::UsageMapperFn mapper;
172 uint64_t minUsage = 0;
173 uint64_t maxUsage = C2MemoryUsage(C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE).expected;
174 size_t blockSize = getpagesize();
175
176 // query min and max usage as well as block size via supported values
177 C2StoreIonUsageInfo usageInfo;
178 std::vector<C2FieldSupportedValuesQuery> query = {
179 C2FieldSupportedValuesQuery::Possible(C2ParamField::Make(usageInfo, usageInfo.usage)),
180 C2FieldSupportedValuesQuery::Possible(C2ParamField::Make(usageInfo, usageInfo.capacity)),
181 };
182 c2_status_t res = store->querySupportedValues_sm(query);
183 if (res == C2_OK) {
184 if (query[0].status == C2_OK) {
185 const C2FieldSupportedValues &fsv = query[0].values;
186 if (fsv.type == C2FieldSupportedValues::FLAGS && !fsv.values.empty()) {
187 minUsage = fsv.values[0].u64;
188 maxUsage = 0;
189 for (C2Value::Primitive v : fsv.values) {
190 maxUsage |= v.u64;
191 }
192 }
193 }
194 if (query[1].status == C2_OK) {
195 const C2FieldSupportedValues &fsv = query[1].values;
196 if (fsv.type == C2FieldSupportedValues::RANGE && fsv.range.step.u32 > 0) {
197 blockSize = fsv.range.step.u32;
198 }
199 }
200
201 mapper = [store](C2MemoryUsage usage, size_t capacity,
202 size_t *align, unsigned *heapMask, unsigned *flags) -> c2_status_t {
203 if (capacity > UINT32_MAX) {
204 return C2_BAD_VALUE;
205 }
206 C2StoreIonUsageInfo usageInfo = { usage.expected, capacity };
207 std::vector<std::unique_ptr<C2SettingResult>> failures; // TODO: remove
208 c2_status_t res = store->config_sm({&usageInfo}, &failures);
209 if (res == C2_OK) {
210 *align = usageInfo.minAlignment;
211 *heapMask = usageInfo.heapMask;
212 *flags = usageInfo.allocFlags;
213 }
214 return res;
215 };
216 }
217
218 allocator->setUsageMapper(mapper, minUsage, maxUsage, blockSize);
219}
220
John Stultza7002cb2020-09-04 19:02:30 +0000221void UseComponentStoreForDmaBufAllocator(const std::shared_ptr<C2DmaBufAllocator> allocator,
222 std::shared_ptr<C2ComponentStore> store) {
223 C2DmaBufAllocator::UsageMapperFn mapper;
224 const size_t maxHeapNameLen = 128;
225 uint64_t minUsage = 0;
226 uint64_t maxUsage = C2MemoryUsage(C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE).expected;
227 size_t blockSize = getpagesize();
228
229 // query min and max usage as well as block size via supported values
230 std::unique_ptr<C2StoreDmaBufUsageInfo> usageInfo;
231 usageInfo = C2StoreDmaBufUsageInfo::AllocUnique(maxHeapNameLen);
232
233 std::vector<C2FieldSupportedValuesQuery> query = {
234 C2FieldSupportedValuesQuery::Possible(C2ParamField::Make(*usageInfo, usageInfo->m.usage)),
235 C2FieldSupportedValuesQuery::Possible(
236 C2ParamField::Make(*usageInfo, usageInfo->m.capacity)),
237 };
238 c2_status_t res = store->querySupportedValues_sm(query);
239 if (res == C2_OK) {
240 if (query[0].status == C2_OK) {
241 const C2FieldSupportedValues& fsv = query[0].values;
242 if (fsv.type == C2FieldSupportedValues::FLAGS && !fsv.values.empty()) {
243 minUsage = fsv.values[0].u64;
244 maxUsage = 0;
245 for (C2Value::Primitive v : fsv.values) {
246 maxUsage |= v.u64;
247 }
248 }
249 }
250 if (query[1].status == C2_OK) {
251 const C2FieldSupportedValues& fsv = query[1].values;
252 if (fsv.type == C2FieldSupportedValues::RANGE && fsv.range.step.u32 > 0) {
253 blockSize = fsv.range.step.u32;
254 }
255 }
256
257 mapper = [store](C2MemoryUsage usage, size_t capacity, C2String* heapName,
258 unsigned* flags) -> c2_status_t {
259 if (capacity > UINT32_MAX) {
260 return C2_BAD_VALUE;
261 }
262
263 std::unique_ptr<C2StoreDmaBufUsageInfo> usageInfo;
264 usageInfo = C2StoreDmaBufUsageInfo::AllocUnique(maxHeapNameLen, usage.expected, capacity);
265 std::vector<std::unique_ptr<C2SettingResult>> failures; // TODO: remove
266
267 c2_status_t res = store->config_sm({&*usageInfo}, &failures);
268 if (res == C2_OK) {
269 *heapName = C2String(usageInfo->m.heapName);
270 *flags = usageInfo->m.allocFlags;
271 }
272
273 return res;
274 };
275 }
276
277 allocator->setUsageMapper(mapper, minUsage, maxUsage, blockSize);
278}
279
Pawin Vongmasa36653902018-11-15 00:10:25 -0800280}
281
282void C2PlatformAllocatorStoreImpl::setComponentStore(std::shared_ptr<C2ComponentStore> store) {
283 // technically this set lock is not needed, but is here for safety in case we add more
284 // getter orders
285 std::lock_guard<std::mutex> lock(_mComponentStoreSetLock);
286 {
287 std::lock_guard<std::mutex> lock(_mComponentStoreReadLock);
288 _mComponentStore = store;
289 }
290 std::shared_ptr<C2AllocatorIon> allocator;
291 {
292 std::lock_guard<std::mutex> lock(gIonAllocatorMutex);
293 allocator = gIonAllocator.lock();
294 }
295 if (allocator) {
296 UseComponentStoreForIonAllocator(allocator, store);
297 }
298}
299
300std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchIonAllocator() {
301 std::lock_guard<std::mutex> lock(gIonAllocatorMutex);
302 std::shared_ptr<C2AllocatorIon> allocator = gIonAllocator.lock();
303 if (allocator == nullptr) {
304 std::shared_ptr<C2ComponentStore> componentStore;
305 {
306 std::lock_guard<std::mutex> lock(_mComponentStoreReadLock);
307 componentStore = _mComponentStore;
308 }
309 allocator = std::make_shared<C2AllocatorIon>(C2PlatformAllocatorStore::ION);
310 UseComponentStoreForIonAllocator(allocator, componentStore);
311 gIonAllocator = allocator;
312 }
313 return allocator;
314}
315
John Stultza7002cb2020-09-04 19:02:30 +0000316std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchDmaBufAllocator() {
317 std::lock_guard<std::mutex> lock(gDmaBufAllocatorMutex);
318 std::shared_ptr<C2DmaBufAllocator> allocator = gDmaBufAllocator.lock();
319 if (allocator == nullptr) {
320 std::shared_ptr<C2ComponentStore> componentStore;
321 {
322 std::lock_guard<std::mutex> lock(_mComponentStoreReadLock);
323 componentStore = _mComponentStore;
324 }
325 allocator = std::make_shared<C2DmaBufAllocator>(C2PlatformAllocatorStore::DMABUFHEAP);
326 UseComponentStoreForDmaBufAllocator(allocator, componentStore);
327 gDmaBufAllocator = allocator;
328 }
329 return allocator;
330}
331
Pin-chih Linaa18ea52019-11-19 18:48:50 +0800332std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchBlobAllocator() {
333 static std::mutex mutex;
334 static std::weak_ptr<C2Allocator> blobAllocator;
335 std::lock_guard<std::mutex> lock(mutex);
336 std::shared_ptr<C2Allocator> allocator = blobAllocator.lock();
337 if (allocator == nullptr) {
338 allocator = std::make_shared<C2AllocatorBlob>(C2PlatformAllocatorStore::BLOB);
339 blobAllocator = allocator;
340 }
341 return allocator;
342}
343
Pawin Vongmasa36653902018-11-15 00:10:25 -0800344std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchGrallocAllocator() {
345 static std::mutex mutex;
346 static std::weak_ptr<C2Allocator> grallocAllocator;
347 std::lock_guard<std::mutex> lock(mutex);
348 std::shared_ptr<C2Allocator> allocator = grallocAllocator.lock();
349 if (allocator == nullptr) {
350 allocator = std::make_shared<C2AllocatorGralloc>(C2PlatformAllocatorStore::GRALLOC);
351 grallocAllocator = allocator;
352 }
353 return allocator;
354}
355
356std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchBufferQueueAllocator() {
357 static std::mutex mutex;
358 static std::weak_ptr<C2Allocator> grallocAllocator;
359 std::lock_guard<std::mutex> lock(mutex);
360 std::shared_ptr<C2Allocator> allocator = grallocAllocator.lock();
361 if (allocator == nullptr) {
362 allocator = std::make_shared<C2AllocatorGralloc>(
363 C2PlatformAllocatorStore::BUFFERQUEUE, true);
364 grallocAllocator = allocator;
365 }
366 return allocator;
367}
368
369namespace {
370 std::mutex gPreferredComponentStoreMutex;
371 std::shared_ptr<C2ComponentStore> gPreferredComponentStore;
372
373 std::mutex gPlatformAllocatorStoreMutex;
374 std::weak_ptr<C2PlatformAllocatorStoreImpl> gPlatformAllocatorStore;
375}
376
377std::shared_ptr<C2AllocatorStore> GetCodec2PlatformAllocatorStore() {
378 std::lock_guard<std::mutex> lock(gPlatformAllocatorStoreMutex);
379 std::shared_ptr<C2PlatformAllocatorStoreImpl> store = gPlatformAllocatorStore.lock();
380 if (store == nullptr) {
381 store = std::make_shared<C2PlatformAllocatorStoreImpl>();
382 store->setComponentStore(GetPreferredCodec2ComponentStore());
383 gPlatformAllocatorStore = store;
384 }
385 return store;
386}
387
388void SetPreferredCodec2ComponentStore(std::shared_ptr<C2ComponentStore> componentStore) {
389 static std::mutex mutex;
390 std::lock_guard<std::mutex> lock(mutex); // don't interleve set-s
391
392 // update preferred store
393 {
394 std::lock_guard<std::mutex> lock(gPreferredComponentStoreMutex);
395 gPreferredComponentStore = componentStore;
396 }
397
398 // update platform allocator's store as well if it is alive
399 std::shared_ptr<C2PlatformAllocatorStoreImpl> allocatorStore;
400 {
401 std::lock_guard<std::mutex> lock(gPlatformAllocatorStoreMutex);
402 allocatorStore = gPlatformAllocatorStore.lock();
403 }
404 if (allocatorStore) {
405 allocatorStore->setComponentStore(componentStore);
406 }
407}
408
409std::shared_ptr<C2ComponentStore> GetPreferredCodec2ComponentStore() {
410 std::lock_guard<std::mutex> lock(gPreferredComponentStoreMutex);
411 return gPreferredComponentStore ? gPreferredComponentStore : GetCodec2PlatformComponentStore();
412}
413
Pin-chih Linaa18ea52019-11-19 18:48:50 +0800414int GetCodec2PoolMask() {
415 return property_get_int32(
416 "debug.stagefright.c2-poolmask",
417 1 << C2PlatformAllocatorStore::ION |
418 1 << C2PlatformAllocatorStore::BUFFERQUEUE);
419}
420
421C2PlatformAllocatorStore::id_t GetPreferredLinearAllocatorId(int poolMask) {
422 return ((poolMask >> C2PlatformAllocatorStore::BLOB) & 1) ? C2PlatformAllocatorStore::BLOB
423 : C2PlatformAllocatorStore::ION;
424}
425
Pawin Vongmasa36653902018-11-15 00:10:25 -0800426namespace {
427
428class _C2BlockPoolCache {
429public:
430 _C2BlockPoolCache() : mBlockPoolSeqId(C2BlockPool::PLATFORM_START + 1) {}
431
432 c2_status_t _createBlockPool(
433 C2PlatformAllocatorStore::id_t allocatorId,
434 std::shared_ptr<const C2Component> component,
435 C2BlockPool::local_id_t poolId,
436 std::shared_ptr<C2BlockPool> *pool) {
437 std::shared_ptr<C2AllocatorStore> allocatorStore =
438 GetCodec2PlatformAllocatorStore();
439 std::shared_ptr<C2Allocator> allocator;
440 c2_status_t res = C2_NOT_FOUND;
441
Pin-chih Linaa18ea52019-11-19 18:48:50 +0800442 if (allocatorId == C2AllocatorStore::DEFAULT_LINEAR) {
443 allocatorId = GetPreferredLinearAllocatorId(GetCodec2PoolMask());
444 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800445 switch(allocatorId) {
John Stultza7002cb2020-09-04 19:02:30 +0000446 case C2PlatformAllocatorStore::ION: /* also ::DMABUFHEAP */
Pawin Vongmasa36653902018-11-15 00:10:25 -0800447 res = allocatorStore->fetchAllocator(
Pin-chih Linaa18ea52019-11-19 18:48:50 +0800448 C2PlatformAllocatorStore::ION, &allocator);
449 if (res == C2_OK) {
450 std::shared_ptr<C2BlockPool> ptr =
451 std::make_shared<C2PooledBlockPool>(
452 allocator, poolId);
453 *pool = ptr;
454 mBlockPools[poolId] = ptr;
455 mComponents[poolId] = component;
456 }
457 break;
458 case C2PlatformAllocatorStore::BLOB:
459 res = allocatorStore->fetchAllocator(
460 C2PlatformAllocatorStore::BLOB, &allocator);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800461 if (res == C2_OK) {
462 std::shared_ptr<C2BlockPool> ptr =
463 std::make_shared<C2PooledBlockPool>(
464 allocator, poolId);
465 *pool = ptr;
466 mBlockPools[poolId] = ptr;
467 mComponents[poolId] = component;
468 }
469 break;
470 case C2PlatformAllocatorStore::GRALLOC:
471 case C2AllocatorStore::DEFAULT_GRAPHIC:
472 res = allocatorStore->fetchAllocator(
473 C2AllocatorStore::DEFAULT_GRAPHIC, &allocator);
474 if (res == C2_OK) {
475 std::shared_ptr<C2BlockPool> ptr =
476 std::make_shared<C2PooledBlockPool>(allocator, poolId);
477 *pool = ptr;
478 mBlockPools[poolId] = ptr;
479 mComponents[poolId] = component;
480 }
481 break;
482 case C2PlatformAllocatorStore::BUFFERQUEUE:
483 res = allocatorStore->fetchAllocator(
484 C2PlatformAllocatorStore::BUFFERQUEUE, &allocator);
485 if (res == C2_OK) {
486 std::shared_ptr<C2BlockPool> ptr =
487 std::make_shared<C2BufferQueueBlockPool>(
488 allocator, poolId);
489 *pool = ptr;
490 mBlockPools[poolId] = ptr;
491 mComponents[poolId] = component;
492 }
493 break;
494 default:
495 // Try to create block pool from platform store plugins.
496 std::shared_ptr<C2BlockPool> ptr;
497 res = C2PlatformStorePluginLoader::GetInstance()->createBlockPool(
498 allocatorId, poolId, &ptr);
499 if (res == C2_OK) {
500 *pool = ptr;
501 mBlockPools[poolId] = ptr;
502 mComponents[poolId] = component;
503 }
504 break;
505 }
506 return res;
507 }
508
509 c2_status_t createBlockPool(
510 C2PlatformAllocatorStore::id_t allocatorId,
511 std::shared_ptr<const C2Component> component,
512 std::shared_ptr<C2BlockPool> *pool) {
513 return _createBlockPool(allocatorId, component, mBlockPoolSeqId++, pool);
514 }
515
516 bool getBlockPool(
517 C2BlockPool::local_id_t blockPoolId,
518 std::shared_ptr<const C2Component> component,
519 std::shared_ptr<C2BlockPool> *pool) {
520 // TODO: use one iterator for multiple blockpool type scalability.
521 std::shared_ptr<C2BlockPool> ptr;
522 auto it = mBlockPools.find(blockPoolId);
523 if (it != mBlockPools.end()) {
524 ptr = it->second.lock();
525 if (!ptr) {
526 mBlockPools.erase(it);
527 mComponents.erase(blockPoolId);
528 } else {
529 auto found = mComponents.find(blockPoolId);
530 if (component == found->second.lock()) {
531 *pool = ptr;
532 return true;
533 }
534 }
535 }
536 return false;
537 }
538
539private:
540 C2BlockPool::local_id_t mBlockPoolSeqId;
541
542 std::map<C2BlockPool::local_id_t, std::weak_ptr<C2BlockPool>> mBlockPools;
543 std::map<C2BlockPool::local_id_t, std::weak_ptr<const C2Component>> mComponents;
544};
545
546static std::unique_ptr<_C2BlockPoolCache> sBlockPoolCache =
547 std::make_unique<_C2BlockPoolCache>();
548static std::mutex sBlockPoolCacheMutex;
549
550} // anynymous namespace
551
552c2_status_t GetCodec2BlockPool(
553 C2BlockPool::local_id_t id, std::shared_ptr<const C2Component> component,
554 std::shared_ptr<C2BlockPool> *pool) {
555 pool->reset();
556 std::lock_guard<std::mutex> lock(sBlockPoolCacheMutex);
557 std::shared_ptr<C2AllocatorStore> allocatorStore = GetCodec2PlatformAllocatorStore();
558 std::shared_ptr<C2Allocator> allocator;
559 c2_status_t res = C2_NOT_FOUND;
560
561 if (id >= C2BlockPool::PLATFORM_START) {
562 if (sBlockPoolCache->getBlockPool(id, component, pool)) {
563 return C2_OK;
564 }
565 }
566
567 switch (id) {
568 case C2BlockPool::BASIC_LINEAR:
569 res = allocatorStore->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &allocator);
570 if (res == C2_OK) {
571 *pool = std::make_shared<C2BasicLinearBlockPool>(allocator);
572 }
573 break;
574 case C2BlockPool::BASIC_GRAPHIC:
575 res = allocatorStore->fetchAllocator(C2AllocatorStore::DEFAULT_GRAPHIC, &allocator);
576 if (res == C2_OK) {
577 *pool = std::make_shared<C2BasicGraphicBlockPool>(allocator);
578 }
579 break;
580 // TODO: remove this. this is temporary
581 case C2BlockPool::PLATFORM_START:
582 res = sBlockPoolCache->_createBlockPool(
583 C2PlatformAllocatorStore::BUFFERQUEUE, component, id, pool);
584 break;
585 default:
586 break;
587 }
588 return res;
589}
590
591c2_status_t CreateCodec2BlockPool(
592 C2PlatformAllocatorStore::id_t allocatorId,
593 std::shared_ptr<const C2Component> component,
594 std::shared_ptr<C2BlockPool> *pool) {
595 pool->reset();
596
597 std::lock_guard<std::mutex> lock(sBlockPoolCacheMutex);
598 return sBlockPoolCache->createBlockPool(allocatorId, component, pool);
599}
600
601class C2PlatformComponentStore : public C2ComponentStore {
602public:
603 virtual std::vector<std::shared_ptr<const C2Component::Traits>> listComponents() override;
604 virtual std::shared_ptr<C2ParamReflector> getParamReflector() const override;
605 virtual C2String getName() const override;
606 virtual c2_status_t querySupportedValues_sm(
607 std::vector<C2FieldSupportedValuesQuery> &fields) const override;
608 virtual c2_status_t querySupportedParams_nb(
609 std::vector<std::shared_ptr<C2ParamDescriptor>> *const params) const override;
610 virtual c2_status_t query_sm(
611 const std::vector<C2Param*> &stackParams,
612 const std::vector<C2Param::Index> &heapParamIndices,
613 std::vector<std::unique_ptr<C2Param>> *const heapParams) const override;
614 virtual c2_status_t createInterface(
615 C2String name, std::shared_ptr<C2ComponentInterface> *const interface) override;
616 virtual c2_status_t createComponent(
617 C2String name, std::shared_ptr<C2Component> *const component) override;
618 virtual c2_status_t copyBuffer(
619 std::shared_ptr<C2GraphicBuffer> src, std::shared_ptr<C2GraphicBuffer> dst) override;
620 virtual c2_status_t config_sm(
621 const std::vector<C2Param*> &params,
622 std::vector<std::unique_ptr<C2SettingResult>> *const failures) override;
623 C2PlatformComponentStore();
624
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530625 // For testing only
626 C2PlatformComponentStore(
627 std::vector<std::tuple<C2String,
628 C2ComponentFactory::CreateCodec2FactoryFunc,
629 C2ComponentFactory::DestroyCodec2FactoryFunc>>);
630
Pawin Vongmasa36653902018-11-15 00:10:25 -0800631 virtual ~C2PlatformComponentStore() override = default;
632
633private:
634
635 /**
636 * An object encapsulating a loaded component module.
637 *
638 * \todo provide a way to add traits to known components here to avoid loading the .so-s
639 * for listComponents
640 */
641 struct ComponentModule : public C2ComponentFactory,
642 public std::enable_shared_from_this<ComponentModule> {
643 virtual c2_status_t createComponent(
644 c2_node_id_t id, std::shared_ptr<C2Component> *component,
645 ComponentDeleter deleter = std::default_delete<C2Component>()) override;
646 virtual c2_status_t createInterface(
647 c2_node_id_t id, std::shared_ptr<C2ComponentInterface> *interface,
648 InterfaceDeleter deleter = std::default_delete<C2ComponentInterface>()) override;
649
650 /**
651 * \returns the traits of the component in this module.
652 */
653 std::shared_ptr<const C2Component::Traits> getTraits();
654
655 /**
656 * Creates an uninitialized component module.
657 *
658 * \param name[in] component name.
659 *
660 * \note Only used by ComponentLoader.
661 */
662 ComponentModule()
663 : mInit(C2_NO_INIT),
664 mLibHandle(nullptr),
665 createFactory(nullptr),
666 destroyFactory(nullptr),
667 mComponentFactory(nullptr) {
668 }
669
670 /**
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530671 * Creates an uninitialized component module.
672 * NOTE: For testing only
673 *
674 * \param name[in] component name.
675 *
676 * \note Only used by ComponentLoader.
677 */
678 ComponentModule(
679 C2ComponentFactory::CreateCodec2FactoryFunc createFactory,
680 C2ComponentFactory::DestroyCodec2FactoryFunc destroyFactory)
681 : mInit(C2_NO_INIT),
682 mLibHandle(nullptr),
683 createFactory(createFactory),
684 destroyFactory(destroyFactory),
685 mComponentFactory(nullptr) {
686 }
687
688 /**
Pawin Vongmasa36653902018-11-15 00:10:25 -0800689 * Initializes a component module with a given library path. Must be called exactly once.
690 *
691 * \note Only used by ComponentLoader.
692 *
Pawin Vongmasa36653902018-11-15 00:10:25 -0800693 * \param libPath[in] library path
694 *
695 * \retval C2_OK the component module has been successfully loaded
696 * \retval C2_NO_MEMORY not enough memory to loading the component module
697 * \retval C2_NOT_FOUND could not locate the component module
698 * \retval C2_CORRUPTED the component module could not be loaded (unexpected)
699 * \retval C2_REFUSED permission denied to load the component module (unexpected)
700 * \retval C2_TIMED_OUT could not load the module within the time limit (unexpected)
701 */
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800702 c2_status_t init(std::string libPath);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800703
704 virtual ~ComponentModule() override;
705
706 protected:
707 std::recursive_mutex mLock; ///< lock protecting mTraits
708 std::shared_ptr<C2Component::Traits> mTraits; ///< cached component traits
709
710 c2_status_t mInit; ///< initialization result
711
712 void *mLibHandle; ///< loaded library handle
713 C2ComponentFactory::CreateCodec2FactoryFunc createFactory; ///< loaded create function
714 C2ComponentFactory::DestroyCodec2FactoryFunc destroyFactory; ///< loaded destroy function
715 C2ComponentFactory *mComponentFactory; ///< loaded/created component factory
716 };
717
718 /**
719 * An object encapsulating a loadable component module.
720 *
721 * \todo make this also work for enumerations
722 */
723 struct ComponentLoader {
724 /**
725 * Load the component module.
726 *
727 * This method simply returns the component module if it is already currently loaded, or
728 * attempts to load it if it is not.
729 *
730 * \param module[out] pointer to the shared pointer where the loaded module shall be stored.
731 * This will be nullptr on error.
732 *
733 * \retval C2_OK the component module has been successfully loaded
734 * \retval C2_NO_MEMORY not enough memory to loading the component module
735 * \retval C2_NOT_FOUND could not locate the component module
736 * \retval C2_CORRUPTED the component module could not be loaded
737 * \retval C2_REFUSED permission denied to load the component module
738 */
739 c2_status_t fetchModule(std::shared_ptr<ComponentModule> *module) {
740 c2_status_t res = C2_OK;
741 std::lock_guard<std::mutex> lock(mMutex);
742 std::shared_ptr<ComponentModule> localModule = mModule.lock();
743 if (localModule == nullptr) {
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530744 if(mCreateFactory) {
745 // For testing only
746 localModule = std::make_shared<ComponentModule>(mCreateFactory,
747 mDestroyFactory);
748 } else {
749 localModule = std::make_shared<ComponentModule>();
750 }
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800751 res = localModule->init(mLibPath);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800752 if (res == C2_OK) {
753 mModule = localModule;
754 }
755 }
756 *module = localModule;
757 return res;
758 }
759
760 /**
761 * Creates a component loader for a specific library path (or name).
762 */
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800763 ComponentLoader(std::string libPath)
764 : mLibPath(libPath) {}
Pawin Vongmasa36653902018-11-15 00:10:25 -0800765
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530766 // For testing only
767 ComponentLoader(std::tuple<C2String,
768 C2ComponentFactory::CreateCodec2FactoryFunc,
769 C2ComponentFactory::DestroyCodec2FactoryFunc> func)
770 : mLibPath(std::get<0>(func)),
771 mCreateFactory(std::get<1>(func)),
772 mDestroyFactory(std::get<2>(func)) {}
773
Pawin Vongmasa36653902018-11-15 00:10:25 -0800774 private:
775 std::mutex mMutex; ///< mutex guarding the module
776 std::weak_ptr<ComponentModule> mModule; ///< weak reference to the loaded module
Pawin Vongmasa36653902018-11-15 00:10:25 -0800777 std::string mLibPath; ///< library path
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530778
779 // For testing only
780 C2ComponentFactory::CreateCodec2FactoryFunc mCreateFactory = nullptr;
781 C2ComponentFactory::DestroyCodec2FactoryFunc mDestroyFactory = nullptr;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800782 };
783
784 struct Interface : public C2InterfaceHelper {
785 std::shared_ptr<C2StoreIonUsageInfo> mIonUsageInfo;
John Stultza7002cb2020-09-04 19:02:30 +0000786 std::shared_ptr<C2StoreDmaBufUsageInfo> mDmaBufUsageInfo;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800787
788 Interface(std::shared_ptr<C2ReflectorHelper> reflector)
789 : C2InterfaceHelper(reflector) {
790 setDerivedInstance(this);
791
792 struct Setter {
793 static C2R setIonUsage(bool /* mayBlock */, C2P<C2StoreIonUsageInfo> &me) {
Wonsik Kimba3db192019-11-22 11:00:48 -0800794#ifdef __ANDROID_APEX__
795 static int32_t defaultHeapMask = [] {
796 int32_t heapmask = base::GetIntProperty(
797 "ro.com.android.media.swcodec.ion.heapmask", int32_t(0xFFFFFFFF));
798 ALOGD("Default ION heapmask = %d", heapmask);
799 return heapmask;
800 }();
801 static int32_t defaultFlags = [] {
802 int32_t flags = base::GetIntProperty(
803 "ro.com.android.media.swcodec.ion.flags", 0);
804 ALOGD("Default ION flags = %d", flags);
805 return flags;
806 }();
807 static uint32_t defaultAlign = [] {
808 uint32_t align = base::GetUintProperty(
809 "ro.com.android.media.swcodec.ion.align", 0u);
810 ALOGD("Default ION align = %d", align);
811 return align;
812 }();
813 me.set().heapMask = defaultHeapMask;
814 me.set().allocFlags = defaultFlags;
815 me.set().minAlignment = defaultAlign;
816#else
Pawin Vongmasa36653902018-11-15 00:10:25 -0800817 me.set().heapMask = ~0;
818 me.set().allocFlags = 0;
819 me.set().minAlignment = 0;
Wonsik Kimba3db192019-11-22 11:00:48 -0800820#endif
Pawin Vongmasa36653902018-11-15 00:10:25 -0800821 return C2R::Ok();
John Stultza7002cb2020-09-04 19:02:30 +0000822 };
823
824 static C2R setDmaBufUsage(bool /* mayBlock */, C2P<C2StoreDmaBufUsageInfo> &me) {
825 strncpy(me.set().m.heapName, "system", me.v.flexCount());
826 me.set().m.allocFlags = 0;
827 return C2R::Ok();
828 };
Pawin Vongmasa36653902018-11-15 00:10:25 -0800829 };
830
831 addParameter(
832 DefineParam(mIonUsageInfo, "ion-usage")
833 .withDefault(new C2StoreIonUsageInfo())
834 .withFields({
835 C2F(mIonUsageInfo, usage).flags({C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE}),
836 C2F(mIonUsageInfo, capacity).inRange(0, UINT32_MAX, 1024),
837 C2F(mIonUsageInfo, heapMask).any(),
838 C2F(mIonUsageInfo, allocFlags).flags({}),
839 C2F(mIonUsageInfo, minAlignment).equalTo(0)
840 })
841 .withSetter(Setter::setIonUsage)
842 .build());
John Stultza7002cb2020-09-04 19:02:30 +0000843
844 addParameter(
845 DefineParam(mDmaBufUsageInfo, "dmabuf-usage")
846 .withDefault(C2StoreDmaBufUsageInfo::AllocShared(0))
847 .withFields({
848 C2F(mDmaBufUsageInfo, m.usage).flags({C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE}),
849 C2F(mDmaBufUsageInfo, m.capacity).inRange(0, UINT32_MAX, 1024),
850 C2F(mDmaBufUsageInfo, m.allocFlags).flags({}),
851 C2F(mDmaBufUsageInfo, m.heapName).any(),
852 })
853 .withSetter(Setter::setDmaBufUsage)
854 .build());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800855 }
856 };
857
858 /**
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800859 * Retrieves the component module for a component.
Pawin Vongmasa36653902018-11-15 00:10:25 -0800860 *
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800861 * \param module pointer to a shared_pointer where the component module will be stored on
862 * success.
Pawin Vongmasa36653902018-11-15 00:10:25 -0800863 *
864 * \retval C2_OK the component loader has been successfully retrieved
865 * \retval C2_NO_MEMORY not enough memory to locate the component loader
866 * \retval C2_NOT_FOUND could not locate the component to be loaded
867 * \retval C2_CORRUPTED the component loader could not be identified due to some modules being
868 * corrupted (this can happen if the name does not refer to an already
869 * identified component but some components could not be loaded due to
870 * bad library)
871 * \retval C2_REFUSED permission denied to find the component loader for the named component
872 * (this can happen if the name does not refer to an already identified
873 * component but some components could not be loaded due to lack of
874 * permissions)
875 */
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800876 c2_status_t findComponent(C2String name, std::shared_ptr<ComponentModule> *module);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800877
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800878 /**
879 * Loads each component module and discover its contents.
880 */
881 void visitComponents();
882
883 std::mutex mMutex; ///< mutex guarding the component lists during construction
884 bool mVisited; ///< component modules visited
885 std::map<C2String, ComponentLoader> mComponents; ///< path -> component module
886 std::map<C2String, C2String> mComponentNameToPath; ///< name -> path
887 std::vector<std::shared_ptr<const C2Component::Traits>> mComponentList;
888
Pawin Vongmasa36653902018-11-15 00:10:25 -0800889 std::shared_ptr<C2ReflectorHelper> mReflector;
890 Interface mInterface;
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530891
892 // For testing only
893 std::vector<std::tuple<C2String,
894 C2ComponentFactory::CreateCodec2FactoryFunc,
895 C2ComponentFactory::DestroyCodec2FactoryFunc>> mCodec2FactoryFuncs;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800896};
897
898c2_status_t C2PlatformComponentStore::ComponentModule::init(
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800899 std::string libPath) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800900 ALOGV("in %s", __func__);
901 ALOGV("loading dll");
Pawin Vongmasa36653902018-11-15 00:10:25 -0800902
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530903 if(!createFactory) {
904 mLibHandle = dlopen(libPath.c_str(), RTLD_NOW|RTLD_NODELETE);
905 LOG_ALWAYS_FATAL_IF(mLibHandle == nullptr,
906 "could not dlopen %s: %s", libPath.c_str(), dlerror());
Chong Zhangf5c7ca82019-04-23 17:06:21 -0700907
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530908 createFactory =
909 (C2ComponentFactory::CreateCodec2FactoryFunc)dlsym(mLibHandle, "CreateCodec2Factory");
910 LOG_ALWAYS_FATAL_IF(createFactory == nullptr,
911 "createFactory is null in %s", libPath.c_str());
912
913 destroyFactory =
914 (C2ComponentFactory::DestroyCodec2FactoryFunc)dlsym(mLibHandle, "DestroyCodec2Factory");
915 LOG_ALWAYS_FATAL_IF(destroyFactory == nullptr,
916 "destroyFactory is null in %s", libPath.c_str());
917 }
Chong Zhangf5c7ca82019-04-23 17:06:21 -0700918
919 mComponentFactory = createFactory();
920 if (mComponentFactory == nullptr) {
921 ALOGD("could not create factory in %s", libPath.c_str());
922 mInit = C2_NO_MEMORY;
Dongwon Kang673236b2019-05-08 09:02:21 -0700923 } else {
924 mInit = C2_OK;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800925 }
926
Dongwon Kang673236b2019-05-08 09:02:21 -0700927 if (mInit != C2_OK) {
928 return mInit;
929 }
Dongwon Kange55d13c2019-04-24 11:01:49 -0700930
Pawin Vongmasa36653902018-11-15 00:10:25 -0800931 std::shared_ptr<C2ComponentInterface> intf;
932 c2_status_t res = createInterface(0, &intf);
933 if (res != C2_OK) {
934 ALOGD("failed to create interface: %d", res);
935 return mInit;
936 }
937
938 std::shared_ptr<C2Component::Traits> traits(new (std::nothrow) C2Component::Traits);
939 if (traits) {
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800940 traits->name = intf->getName();
Lajos Molnar62d62d62019-01-31 16:26:46 -0800941
942 C2ComponentKindSetting kind;
943 C2ComponentDomainSetting domain;
944 res = intf->query_vb({ &kind, &domain }, {}, C2_MAY_BLOCK, nullptr);
945 bool fixDomain = res != C2_OK;
946 if (res == C2_OK) {
947 traits->kind = kind.value;
948 traits->domain = domain.value;
949 } else {
950 // TODO: remove this fall-back
951 ALOGD("failed to query interface for kind and domain: %d", res);
952
953 traits->kind =
954 (traits->name.find("encoder") != std::string::npos) ? C2Component::KIND_ENCODER :
955 (traits->name.find("decoder") != std::string::npos) ? C2Component::KIND_DECODER :
956 C2Component::KIND_OTHER;
957 }
958
959 uint32_t mediaTypeIndex =
Lajos Molnar3bb81cd2019-02-20 15:10:30 -0800960 traits->kind == C2Component::KIND_ENCODER ? C2PortMediaTypeSetting::output::PARAM_TYPE
961 : C2PortMediaTypeSetting::input::PARAM_TYPE;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800962 std::vector<std::unique_ptr<C2Param>> params;
963 res = intf->query_vb({}, { mediaTypeIndex }, C2_MAY_BLOCK, &params);
964 if (res != C2_OK) {
965 ALOGD("failed to query interface: %d", res);
966 return mInit;
967 }
968 if (params.size() != 1u) {
969 ALOGD("failed to query interface: unexpected vector size: %zu", params.size());
970 return mInit;
971 }
Lajos Molnar3bb81cd2019-02-20 15:10:30 -0800972 C2PortMediaTypeSetting *mediaTypeConfig = C2PortMediaTypeSetting::From(params[0].get());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800973 if (mediaTypeConfig == nullptr) {
974 ALOGD("failed to query media type");
975 return mInit;
976 }
Lajos Molnar62d62d62019-01-31 16:26:46 -0800977 traits->mediaType =
978 std::string(mediaTypeConfig->m.value,
979 strnlen(mediaTypeConfig->m.value, mediaTypeConfig->flexCount()));
Pawin Vongmasa36653902018-11-15 00:10:25 -0800980
Lajos Molnar62d62d62019-01-31 16:26:46 -0800981 if (fixDomain) {
982 if (strncmp(traits->mediaType.c_str(), "audio/", 6) == 0) {
983 traits->domain = C2Component::DOMAIN_AUDIO;
984 } else if (strncmp(traits->mediaType.c_str(), "video/", 6) == 0) {
985 traits->domain = C2Component::DOMAIN_VIDEO;
986 } else if (strncmp(traits->mediaType.c_str(), "image/", 6) == 0) {
987 traits->domain = C2Component::DOMAIN_IMAGE;
988 } else {
989 traits->domain = C2Component::DOMAIN_OTHER;
990 }
991 }
992
993 // TODO: get this properly from the store during emplace
994 switch (traits->domain) {
995 case C2Component::DOMAIN_AUDIO:
996 traits->rank = 8;
997 break;
998 default:
999 traits->rank = 512;
1000 }
1001
1002 params.clear();
1003 res = intf->query_vb({}, { C2ComponentAliasesSetting::PARAM_TYPE }, C2_MAY_BLOCK, &params);
1004 if (res == C2_OK && params.size() == 1u) {
1005 C2ComponentAliasesSetting *aliasesSetting =
1006 C2ComponentAliasesSetting::From(params[0].get());
1007 if (aliasesSetting) {
1008 // Split aliases on ','
1009 // This looks simpler in plain C and even std::string would still make a copy.
1010 char *aliases = ::strndup(aliasesSetting->m.value, aliasesSetting->flexCount());
1011 ALOGD("'%s' has aliases: '%s'", intf->getName().c_str(), aliases);
1012
1013 for (char *tok, *ptr, *str = aliases; (tok = ::strtok_r(str, ",", &ptr));
1014 str = nullptr) {
1015 traits->aliases.push_back(tok);
1016 ALOGD("adding alias: '%s'", tok);
1017 }
1018 free(aliases);
1019 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001020 }
1021 }
1022 mTraits = traits;
1023
1024 return mInit;
1025}
1026
1027C2PlatformComponentStore::ComponentModule::~ComponentModule() {
1028 ALOGV("in %s", __func__);
1029 if (destroyFactory && mComponentFactory) {
1030 destroyFactory(mComponentFactory);
1031 }
1032 if (mLibHandle) {
1033 ALOGV("unloading dll");
1034 dlclose(mLibHandle);
1035 }
1036}
1037
1038c2_status_t C2PlatformComponentStore::ComponentModule::createInterface(
1039 c2_node_id_t id, std::shared_ptr<C2ComponentInterface> *interface,
1040 std::function<void(::C2ComponentInterface*)> deleter) {
1041 interface->reset();
1042 if (mInit != C2_OK) {
1043 return mInit;
1044 }
1045 std::shared_ptr<ComponentModule> module = shared_from_this();
1046 c2_status_t res = mComponentFactory->createInterface(
1047 id, interface, [module, deleter](C2ComponentInterface *p) mutable {
1048 // capture module so that we ensure we still have it while deleting interface
1049 deleter(p); // delete interface first
1050 module.reset(); // remove module ref (not technically needed)
1051 });
1052 return res;
1053}
1054
1055c2_status_t C2PlatformComponentStore::ComponentModule::createComponent(
1056 c2_node_id_t id, std::shared_ptr<C2Component> *component,
1057 std::function<void(::C2Component*)> deleter) {
1058 component->reset();
1059 if (mInit != C2_OK) {
1060 return mInit;
1061 }
1062 std::shared_ptr<ComponentModule> module = shared_from_this();
1063 c2_status_t res = mComponentFactory->createComponent(
1064 id, component, [module, deleter](C2Component *p) mutable {
1065 // capture module so that we ensure we still have it while deleting component
1066 deleter(p); // delete component first
1067 module.reset(); // remove module ref (not technically needed)
1068 });
1069 return res;
1070}
1071
1072std::shared_ptr<const C2Component::Traits> C2PlatformComponentStore::ComponentModule::getTraits() {
1073 std::unique_lock<std::recursive_mutex> lock(mLock);
1074 return mTraits;
1075}
1076
1077C2PlatformComponentStore::C2PlatformComponentStore()
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001078 : mVisited(false),
1079 mReflector(std::make_shared<C2ReflectorHelper>()),
Pawin Vongmasa36653902018-11-15 00:10:25 -08001080 mInterface(mReflector) {
1081
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001082 auto emplace = [this](const char *libPath) {
1083 mComponents.emplace(libPath, libPath);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001084 };
Pawin Vongmasa36653902018-11-15 00:10:25 -08001085
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001086 // TODO: move this also into a .so so it can be updated
1087 emplace("libcodec2_soft_aacdec.so");
1088 emplace("libcodec2_soft_aacenc.so");
1089 emplace("libcodec2_soft_amrnbdec.so");
1090 emplace("libcodec2_soft_amrnbenc.so");
1091 emplace("libcodec2_soft_amrwbdec.so");
1092 emplace("libcodec2_soft_amrwbenc.so");
Ray Essickc2cc4372019-08-21 14:02:28 -07001093 //emplace("libcodec2_soft_av1dec_aom.so"); // deprecated for the gav1 implementation
1094 emplace("libcodec2_soft_av1dec_gav1.so");
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001095 emplace("libcodec2_soft_avcdec.so");
1096 emplace("libcodec2_soft_avcenc.so");
1097 emplace("libcodec2_soft_flacdec.so");
1098 emplace("libcodec2_soft_flacenc.so");
1099 emplace("libcodec2_soft_g711alawdec.so");
1100 emplace("libcodec2_soft_g711mlawdec.so");
1101 emplace("libcodec2_soft_gsmdec.so");
1102 emplace("libcodec2_soft_h263dec.so");
1103 emplace("libcodec2_soft_h263enc.so");
1104 emplace("libcodec2_soft_hevcdec.so");
Roma Kauldfe650a2018-08-02 17:48:51 +05301105 emplace("libcodec2_soft_hevcenc.so");
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001106 emplace("libcodec2_soft_mp3dec.so");
1107 emplace("libcodec2_soft_mpeg2dec.so");
1108 emplace("libcodec2_soft_mpeg4dec.so");
1109 emplace("libcodec2_soft_mpeg4enc.so");
1110 emplace("libcodec2_soft_opusdec.so");
1111 emplace("libcodec2_soft_opusenc.so");
1112 emplace("libcodec2_soft_rawdec.so");
1113 emplace("libcodec2_soft_vorbisdec.so");
1114 emplace("libcodec2_soft_vp8dec.so");
1115 emplace("libcodec2_soft_vp8enc.so");
1116 emplace("libcodec2_soft_vp9dec.so");
1117 emplace("libcodec2_soft_vp9enc.so");
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +05301118
1119}
1120
1121// For testing only
1122C2PlatformComponentStore::C2PlatformComponentStore(
1123 std::vector<std::tuple<C2String,
1124 C2ComponentFactory::CreateCodec2FactoryFunc,
1125 C2ComponentFactory::DestroyCodec2FactoryFunc>> funcs)
1126 : mVisited(false),
1127 mReflector(std::make_shared<C2ReflectorHelper>()),
1128 mInterface(mReflector),
1129 mCodec2FactoryFuncs(funcs) {
1130
1131 for(auto const& func: mCodec2FactoryFuncs) {
1132 mComponents.emplace(std::get<0>(func), func);
1133 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001134}
1135
1136c2_status_t C2PlatformComponentStore::copyBuffer(
1137 std::shared_ptr<C2GraphicBuffer> src, std::shared_ptr<C2GraphicBuffer> dst) {
1138 (void)src;
1139 (void)dst;
1140 return C2_OMITTED;
1141}
1142
1143c2_status_t C2PlatformComponentStore::query_sm(
1144 const std::vector<C2Param*> &stackParams,
1145 const std::vector<C2Param::Index> &heapParamIndices,
1146 std::vector<std::unique_ptr<C2Param>> *const heapParams) const {
1147 return mInterface.query(stackParams, heapParamIndices, C2_MAY_BLOCK, heapParams);
1148}
1149
1150c2_status_t C2PlatformComponentStore::config_sm(
1151 const std::vector<C2Param*> &params,
1152 std::vector<std::unique_ptr<C2SettingResult>> *const failures) {
1153 return mInterface.config(params, C2_MAY_BLOCK, failures);
1154}
1155
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001156void C2PlatformComponentStore::visitComponents() {
1157 std::lock_guard<std::mutex> lock(mMutex);
1158 if (mVisited) {
1159 return;
1160 }
1161 for (auto &pathAndLoader : mComponents) {
1162 const C2String &path = pathAndLoader.first;
1163 ComponentLoader &loader = pathAndLoader.second;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001164 std::shared_ptr<ComponentModule> module;
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001165 if (loader.fetchModule(&module) == C2_OK) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001166 std::shared_ptr<const C2Component::Traits> traits = module->getTraits();
1167 if (traits) {
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001168 mComponentList.push_back(traits);
1169 mComponentNameToPath.emplace(traits->name, path);
1170 for (const C2String &alias : traits->aliases) {
1171 mComponentNameToPath.emplace(alias, path);
1172 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001173 }
1174 }
1175 }
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001176 mVisited = true;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001177}
1178
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001179std::vector<std::shared_ptr<const C2Component::Traits>> C2PlatformComponentStore::listComponents() {
1180 // This method SHALL return within 500ms.
1181 visitComponents();
1182 return mComponentList;
1183}
1184
1185c2_status_t C2PlatformComponentStore::findComponent(
1186 C2String name, std::shared_ptr<ComponentModule> *module) {
1187 (*module).reset();
1188 visitComponents();
1189
1190 auto pos = mComponentNameToPath.find(name);
1191 if (pos != mComponentNameToPath.end()) {
1192 return mComponents.at(pos->second).fetchModule(module);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001193 }
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001194 return C2_NOT_FOUND;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001195}
1196
1197c2_status_t C2PlatformComponentStore::createComponent(
1198 C2String name, std::shared_ptr<C2Component> *const component) {
1199 // This method SHALL return within 100ms.
1200 component->reset();
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001201 std::shared_ptr<ComponentModule> module;
1202 c2_status_t res = findComponent(name, &module);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001203 if (res == C2_OK) {
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001204 // TODO: get a unique node ID
1205 res = module->createComponent(0, component);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001206 }
1207 return res;
1208}
1209
1210c2_status_t C2PlatformComponentStore::createInterface(
1211 C2String name, std::shared_ptr<C2ComponentInterface> *const interface) {
1212 // This method SHALL return within 100ms.
1213 interface->reset();
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001214 std::shared_ptr<ComponentModule> module;
1215 c2_status_t res = findComponent(name, &module);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001216 if (res == C2_OK) {
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001217 // TODO: get a unique node ID
1218 res = module->createInterface(0, interface);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001219 }
1220 return res;
1221}
1222
1223c2_status_t C2PlatformComponentStore::querySupportedParams_nb(
1224 std::vector<std::shared_ptr<C2ParamDescriptor>> *const params) const {
1225 return mInterface.querySupportedParams(params);
1226}
1227
1228c2_status_t C2PlatformComponentStore::querySupportedValues_sm(
1229 std::vector<C2FieldSupportedValuesQuery> &fields) const {
1230 return mInterface.querySupportedValues(fields, C2_MAY_BLOCK);
1231}
1232
1233C2String C2PlatformComponentStore::getName() const {
1234 return "android.componentStore.platform";
1235}
1236
1237std::shared_ptr<C2ParamReflector> C2PlatformComponentStore::getParamReflector() const {
1238 return mReflector;
1239}
1240
1241std::shared_ptr<C2ComponentStore> GetCodec2PlatformComponentStore() {
1242 static std::mutex mutex;
1243 static std::weak_ptr<C2ComponentStore> platformStore;
1244 std::lock_guard<std::mutex> lock(mutex);
1245 std::shared_ptr<C2ComponentStore> store = platformStore.lock();
1246 if (store == nullptr) {
1247 store = std::make_shared<C2PlatformComponentStore>();
1248 platformStore = store;
1249 }
1250 return store;
1251}
1252
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +05301253// For testing only
1254std::shared_ptr<C2ComponentStore> GetTestComponentStore(
1255 std::vector<std::tuple<C2String,
1256 C2ComponentFactory::CreateCodec2FactoryFunc,
1257 C2ComponentFactory::DestroyCodec2FactoryFunc>> funcs) {
1258 return std::shared_ptr<C2ComponentStore>(new C2PlatformComponentStore(funcs));
1259}
Pawin Vongmasa36653902018-11-15 00:10:25 -08001260} // namespace android