blob: 1e907c14bdb56ebdb282c79d8f99b83047623757 [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
625 virtual ~C2PlatformComponentStore() override = default;
626
627private:
628
629 /**
630 * An object encapsulating a loaded component module.
631 *
632 * \todo provide a way to add traits to known components here to avoid loading the .so-s
633 * for listComponents
634 */
635 struct ComponentModule : public C2ComponentFactory,
636 public std::enable_shared_from_this<ComponentModule> {
637 virtual c2_status_t createComponent(
638 c2_node_id_t id, std::shared_ptr<C2Component> *component,
639 ComponentDeleter deleter = std::default_delete<C2Component>()) override;
640 virtual c2_status_t createInterface(
641 c2_node_id_t id, std::shared_ptr<C2ComponentInterface> *interface,
642 InterfaceDeleter deleter = std::default_delete<C2ComponentInterface>()) override;
643
644 /**
645 * \returns the traits of the component in this module.
646 */
647 std::shared_ptr<const C2Component::Traits> getTraits();
648
649 /**
650 * Creates an uninitialized component module.
651 *
652 * \param name[in] component name.
653 *
654 * \note Only used by ComponentLoader.
655 */
656 ComponentModule()
657 : mInit(C2_NO_INIT),
658 mLibHandle(nullptr),
659 createFactory(nullptr),
660 destroyFactory(nullptr),
661 mComponentFactory(nullptr) {
662 }
663
664 /**
665 * Initializes a component module with a given library path. Must be called exactly once.
666 *
667 * \note Only used by ComponentLoader.
668 *
Pawin Vongmasa36653902018-11-15 00:10:25 -0800669 * \param libPath[in] library path
670 *
671 * \retval C2_OK the component module has been successfully loaded
672 * \retval C2_NO_MEMORY not enough memory to loading the component module
673 * \retval C2_NOT_FOUND could not locate the component module
674 * \retval C2_CORRUPTED the component module could not be loaded (unexpected)
675 * \retval C2_REFUSED permission denied to load the component module (unexpected)
676 * \retval C2_TIMED_OUT could not load the module within the time limit (unexpected)
677 */
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800678 c2_status_t init(std::string libPath);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800679
680 virtual ~ComponentModule() override;
681
682 protected:
683 std::recursive_mutex mLock; ///< lock protecting mTraits
684 std::shared_ptr<C2Component::Traits> mTraits; ///< cached component traits
685
686 c2_status_t mInit; ///< initialization result
687
688 void *mLibHandle; ///< loaded library handle
689 C2ComponentFactory::CreateCodec2FactoryFunc createFactory; ///< loaded create function
690 C2ComponentFactory::DestroyCodec2FactoryFunc destroyFactory; ///< loaded destroy function
691 C2ComponentFactory *mComponentFactory; ///< loaded/created component factory
692 };
693
694 /**
695 * An object encapsulating a loadable component module.
696 *
697 * \todo make this also work for enumerations
698 */
699 struct ComponentLoader {
700 /**
701 * Load the component module.
702 *
703 * This method simply returns the component module if it is already currently loaded, or
704 * attempts to load it if it is not.
705 *
706 * \param module[out] pointer to the shared pointer where the loaded module shall be stored.
707 * This will be nullptr on error.
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
713 * \retval C2_REFUSED permission denied to load the component module
714 */
715 c2_status_t fetchModule(std::shared_ptr<ComponentModule> *module) {
716 c2_status_t res = C2_OK;
717 std::lock_guard<std::mutex> lock(mMutex);
718 std::shared_ptr<ComponentModule> localModule = mModule.lock();
719 if (localModule == nullptr) {
720 localModule = std::make_shared<ComponentModule>();
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800721 res = localModule->init(mLibPath);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800722 if (res == C2_OK) {
723 mModule = localModule;
724 }
725 }
726 *module = localModule;
727 return res;
728 }
729
730 /**
731 * Creates a component loader for a specific library path (or name).
732 */
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800733 ComponentLoader(std::string libPath)
734 : mLibPath(libPath) {}
Pawin Vongmasa36653902018-11-15 00:10:25 -0800735
736 private:
737 std::mutex mMutex; ///< mutex guarding the module
738 std::weak_ptr<ComponentModule> mModule; ///< weak reference to the loaded module
Pawin Vongmasa36653902018-11-15 00:10:25 -0800739 std::string mLibPath; ///< library path
740 };
741
742 struct Interface : public C2InterfaceHelper {
743 std::shared_ptr<C2StoreIonUsageInfo> mIonUsageInfo;
John Stultza7002cb2020-09-04 19:02:30 +0000744 std::shared_ptr<C2StoreDmaBufUsageInfo> mDmaBufUsageInfo;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800745
746 Interface(std::shared_ptr<C2ReflectorHelper> reflector)
747 : C2InterfaceHelper(reflector) {
748 setDerivedInstance(this);
749
750 struct Setter {
751 static C2R setIonUsage(bool /* mayBlock */, C2P<C2StoreIonUsageInfo> &me) {
Wonsik Kimba3db192019-11-22 11:00:48 -0800752#ifdef __ANDROID_APEX__
753 static int32_t defaultHeapMask = [] {
754 int32_t heapmask = base::GetIntProperty(
755 "ro.com.android.media.swcodec.ion.heapmask", int32_t(0xFFFFFFFF));
756 ALOGD("Default ION heapmask = %d", heapmask);
757 return heapmask;
758 }();
759 static int32_t defaultFlags = [] {
760 int32_t flags = base::GetIntProperty(
761 "ro.com.android.media.swcodec.ion.flags", 0);
762 ALOGD("Default ION flags = %d", flags);
763 return flags;
764 }();
765 static uint32_t defaultAlign = [] {
766 uint32_t align = base::GetUintProperty(
767 "ro.com.android.media.swcodec.ion.align", 0u);
768 ALOGD("Default ION align = %d", align);
769 return align;
770 }();
771 me.set().heapMask = defaultHeapMask;
772 me.set().allocFlags = defaultFlags;
773 me.set().minAlignment = defaultAlign;
774#else
Pawin Vongmasa36653902018-11-15 00:10:25 -0800775 me.set().heapMask = ~0;
776 me.set().allocFlags = 0;
777 me.set().minAlignment = 0;
Wonsik Kimba3db192019-11-22 11:00:48 -0800778#endif
Pawin Vongmasa36653902018-11-15 00:10:25 -0800779 return C2R::Ok();
John Stultza7002cb2020-09-04 19:02:30 +0000780 };
781
782 static C2R setDmaBufUsage(bool /* mayBlock */, C2P<C2StoreDmaBufUsageInfo> &me) {
783 strncpy(me.set().m.heapName, "system", me.v.flexCount());
784 me.set().m.allocFlags = 0;
785 return C2R::Ok();
786 };
Pawin Vongmasa36653902018-11-15 00:10:25 -0800787 };
788
789 addParameter(
790 DefineParam(mIonUsageInfo, "ion-usage")
791 .withDefault(new C2StoreIonUsageInfo())
792 .withFields({
793 C2F(mIonUsageInfo, usage).flags({C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE}),
794 C2F(mIonUsageInfo, capacity).inRange(0, UINT32_MAX, 1024),
795 C2F(mIonUsageInfo, heapMask).any(),
796 C2F(mIonUsageInfo, allocFlags).flags({}),
797 C2F(mIonUsageInfo, minAlignment).equalTo(0)
798 })
799 .withSetter(Setter::setIonUsage)
800 .build());
John Stultza7002cb2020-09-04 19:02:30 +0000801
802 addParameter(
803 DefineParam(mDmaBufUsageInfo, "dmabuf-usage")
804 .withDefault(C2StoreDmaBufUsageInfo::AllocShared(0))
805 .withFields({
806 C2F(mDmaBufUsageInfo, m.usage).flags({C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE}),
807 C2F(mDmaBufUsageInfo, m.capacity).inRange(0, UINT32_MAX, 1024),
808 C2F(mDmaBufUsageInfo, m.allocFlags).flags({}),
809 C2F(mDmaBufUsageInfo, m.heapName).any(),
810 })
811 .withSetter(Setter::setDmaBufUsage)
812 .build());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800813 }
814 };
815
816 /**
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800817 * Retrieves the component module for a component.
Pawin Vongmasa36653902018-11-15 00:10:25 -0800818 *
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800819 * \param module pointer to a shared_pointer where the component module will be stored on
820 * success.
Pawin Vongmasa36653902018-11-15 00:10:25 -0800821 *
822 * \retval C2_OK the component loader has been successfully retrieved
823 * \retval C2_NO_MEMORY not enough memory to locate the component loader
824 * \retval C2_NOT_FOUND could not locate the component to be loaded
825 * \retval C2_CORRUPTED the component loader could not be identified due to some modules being
826 * corrupted (this can happen if the name does not refer to an already
827 * identified component but some components could not be loaded due to
828 * bad library)
829 * \retval C2_REFUSED permission denied to find the component loader for the named component
830 * (this can happen if the name does not refer to an already identified
831 * component but some components could not be loaded due to lack of
832 * permissions)
833 */
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800834 c2_status_t findComponent(C2String name, std::shared_ptr<ComponentModule> *module);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800835
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800836 /**
837 * Loads each component module and discover its contents.
838 */
839 void visitComponents();
840
841 std::mutex mMutex; ///< mutex guarding the component lists during construction
842 bool mVisited; ///< component modules visited
843 std::map<C2String, ComponentLoader> mComponents; ///< path -> component module
844 std::map<C2String, C2String> mComponentNameToPath; ///< name -> path
845 std::vector<std::shared_ptr<const C2Component::Traits>> mComponentList;
846
Pawin Vongmasa36653902018-11-15 00:10:25 -0800847 std::shared_ptr<C2ReflectorHelper> mReflector;
848 Interface mInterface;
849};
850
851c2_status_t C2PlatformComponentStore::ComponentModule::init(
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800852 std::string libPath) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800853 ALOGV("in %s", __func__);
854 ALOGV("loading dll");
855 mLibHandle = dlopen(libPath.c_str(), RTLD_NOW|RTLD_NODELETE);
Dongwon Kang673236b2019-05-08 09:02:21 -0700856 LOG_ALWAYS_FATAL_IF(mLibHandle == nullptr,
857 "could not dlopen %s: %s", libPath.c_str(), dlerror());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800858
Chong Zhangf5c7ca82019-04-23 17:06:21 -0700859 createFactory =
860 (C2ComponentFactory::CreateCodec2FactoryFunc)dlsym(mLibHandle, "CreateCodec2Factory");
Dongwon Kang673236b2019-05-08 09:02:21 -0700861 LOG_ALWAYS_FATAL_IF(createFactory == nullptr,
862 "createFactory is null in %s", libPath.c_str());
Chong Zhangf5c7ca82019-04-23 17:06:21 -0700863
864 destroyFactory =
865 (C2ComponentFactory::DestroyCodec2FactoryFunc)dlsym(mLibHandle, "DestroyCodec2Factory");
Dongwon Kang673236b2019-05-08 09:02:21 -0700866 LOG_ALWAYS_FATAL_IF(destroyFactory == nullptr,
867 "destroyFactory is null in %s", libPath.c_str());
Chong Zhangf5c7ca82019-04-23 17:06:21 -0700868
869 mComponentFactory = createFactory();
870 if (mComponentFactory == nullptr) {
871 ALOGD("could not create factory in %s", libPath.c_str());
872 mInit = C2_NO_MEMORY;
Dongwon Kang673236b2019-05-08 09:02:21 -0700873 } else {
874 mInit = C2_OK;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800875 }
876
Dongwon Kang673236b2019-05-08 09:02:21 -0700877 if (mInit != C2_OK) {
878 return mInit;
879 }
Dongwon Kange55d13c2019-04-24 11:01:49 -0700880
Pawin Vongmasa36653902018-11-15 00:10:25 -0800881 std::shared_ptr<C2ComponentInterface> intf;
882 c2_status_t res = createInterface(0, &intf);
883 if (res != C2_OK) {
884 ALOGD("failed to create interface: %d", res);
885 return mInit;
886 }
887
888 std::shared_ptr<C2Component::Traits> traits(new (std::nothrow) C2Component::Traits);
889 if (traits) {
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800890 traits->name = intf->getName();
Lajos Molnar62d62d62019-01-31 16:26:46 -0800891
892 C2ComponentKindSetting kind;
893 C2ComponentDomainSetting domain;
894 res = intf->query_vb({ &kind, &domain }, {}, C2_MAY_BLOCK, nullptr);
895 bool fixDomain = res != C2_OK;
896 if (res == C2_OK) {
897 traits->kind = kind.value;
898 traits->domain = domain.value;
899 } else {
900 // TODO: remove this fall-back
901 ALOGD("failed to query interface for kind and domain: %d", res);
902
903 traits->kind =
904 (traits->name.find("encoder") != std::string::npos) ? C2Component::KIND_ENCODER :
905 (traits->name.find("decoder") != std::string::npos) ? C2Component::KIND_DECODER :
906 C2Component::KIND_OTHER;
907 }
908
909 uint32_t mediaTypeIndex =
Lajos Molnar3bb81cd2019-02-20 15:10:30 -0800910 traits->kind == C2Component::KIND_ENCODER ? C2PortMediaTypeSetting::output::PARAM_TYPE
911 : C2PortMediaTypeSetting::input::PARAM_TYPE;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800912 std::vector<std::unique_ptr<C2Param>> params;
913 res = intf->query_vb({}, { mediaTypeIndex }, C2_MAY_BLOCK, &params);
914 if (res != C2_OK) {
915 ALOGD("failed to query interface: %d", res);
916 return mInit;
917 }
918 if (params.size() != 1u) {
919 ALOGD("failed to query interface: unexpected vector size: %zu", params.size());
920 return mInit;
921 }
Lajos Molnar3bb81cd2019-02-20 15:10:30 -0800922 C2PortMediaTypeSetting *mediaTypeConfig = C2PortMediaTypeSetting::From(params[0].get());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800923 if (mediaTypeConfig == nullptr) {
924 ALOGD("failed to query media type");
925 return mInit;
926 }
Lajos Molnar62d62d62019-01-31 16:26:46 -0800927 traits->mediaType =
928 std::string(mediaTypeConfig->m.value,
929 strnlen(mediaTypeConfig->m.value, mediaTypeConfig->flexCount()));
Pawin Vongmasa36653902018-11-15 00:10:25 -0800930
Lajos Molnar62d62d62019-01-31 16:26:46 -0800931 if (fixDomain) {
932 if (strncmp(traits->mediaType.c_str(), "audio/", 6) == 0) {
933 traits->domain = C2Component::DOMAIN_AUDIO;
934 } else if (strncmp(traits->mediaType.c_str(), "video/", 6) == 0) {
935 traits->domain = C2Component::DOMAIN_VIDEO;
936 } else if (strncmp(traits->mediaType.c_str(), "image/", 6) == 0) {
937 traits->domain = C2Component::DOMAIN_IMAGE;
938 } else {
939 traits->domain = C2Component::DOMAIN_OTHER;
940 }
941 }
942
943 // TODO: get this properly from the store during emplace
944 switch (traits->domain) {
945 case C2Component::DOMAIN_AUDIO:
946 traits->rank = 8;
947 break;
948 default:
949 traits->rank = 512;
950 }
951
952 params.clear();
953 res = intf->query_vb({}, { C2ComponentAliasesSetting::PARAM_TYPE }, C2_MAY_BLOCK, &params);
954 if (res == C2_OK && params.size() == 1u) {
955 C2ComponentAliasesSetting *aliasesSetting =
956 C2ComponentAliasesSetting::From(params[0].get());
957 if (aliasesSetting) {
958 // Split aliases on ','
959 // This looks simpler in plain C and even std::string would still make a copy.
960 char *aliases = ::strndup(aliasesSetting->m.value, aliasesSetting->flexCount());
961 ALOGD("'%s' has aliases: '%s'", intf->getName().c_str(), aliases);
962
963 for (char *tok, *ptr, *str = aliases; (tok = ::strtok_r(str, ",", &ptr));
964 str = nullptr) {
965 traits->aliases.push_back(tok);
966 ALOGD("adding alias: '%s'", tok);
967 }
968 free(aliases);
969 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800970 }
971 }
972 mTraits = traits;
973
974 return mInit;
975}
976
977C2PlatformComponentStore::ComponentModule::~ComponentModule() {
978 ALOGV("in %s", __func__);
979 if (destroyFactory && mComponentFactory) {
980 destroyFactory(mComponentFactory);
981 }
982 if (mLibHandle) {
983 ALOGV("unloading dll");
984 dlclose(mLibHandle);
985 }
986}
987
988c2_status_t C2PlatformComponentStore::ComponentModule::createInterface(
989 c2_node_id_t id, std::shared_ptr<C2ComponentInterface> *interface,
990 std::function<void(::C2ComponentInterface*)> deleter) {
991 interface->reset();
992 if (mInit != C2_OK) {
993 return mInit;
994 }
995 std::shared_ptr<ComponentModule> module = shared_from_this();
996 c2_status_t res = mComponentFactory->createInterface(
997 id, interface, [module, deleter](C2ComponentInterface *p) mutable {
998 // capture module so that we ensure we still have it while deleting interface
999 deleter(p); // delete interface first
1000 module.reset(); // remove module ref (not technically needed)
1001 });
1002 return res;
1003}
1004
1005c2_status_t C2PlatformComponentStore::ComponentModule::createComponent(
1006 c2_node_id_t id, std::shared_ptr<C2Component> *component,
1007 std::function<void(::C2Component*)> deleter) {
1008 component->reset();
1009 if (mInit != C2_OK) {
1010 return mInit;
1011 }
1012 std::shared_ptr<ComponentModule> module = shared_from_this();
1013 c2_status_t res = mComponentFactory->createComponent(
1014 id, component, [module, deleter](C2Component *p) mutable {
1015 // capture module so that we ensure we still have it while deleting component
1016 deleter(p); // delete component first
1017 module.reset(); // remove module ref (not technically needed)
1018 });
1019 return res;
1020}
1021
1022std::shared_ptr<const C2Component::Traits> C2PlatformComponentStore::ComponentModule::getTraits() {
1023 std::unique_lock<std::recursive_mutex> lock(mLock);
1024 return mTraits;
1025}
1026
1027C2PlatformComponentStore::C2PlatformComponentStore()
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001028 : mVisited(false),
1029 mReflector(std::make_shared<C2ReflectorHelper>()),
Pawin Vongmasa36653902018-11-15 00:10:25 -08001030 mInterface(mReflector) {
1031
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001032 auto emplace = [this](const char *libPath) {
1033 mComponents.emplace(libPath, libPath);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001034 };
Pawin Vongmasa36653902018-11-15 00:10:25 -08001035
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001036 // TODO: move this also into a .so so it can be updated
1037 emplace("libcodec2_soft_aacdec.so");
1038 emplace("libcodec2_soft_aacenc.so");
1039 emplace("libcodec2_soft_amrnbdec.so");
1040 emplace("libcodec2_soft_amrnbenc.so");
1041 emplace("libcodec2_soft_amrwbdec.so");
1042 emplace("libcodec2_soft_amrwbenc.so");
Ray Essickc2cc4372019-08-21 14:02:28 -07001043 //emplace("libcodec2_soft_av1dec_aom.so"); // deprecated for the gav1 implementation
1044 emplace("libcodec2_soft_av1dec_gav1.so");
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001045 emplace("libcodec2_soft_avcdec.so");
1046 emplace("libcodec2_soft_avcenc.so");
1047 emplace("libcodec2_soft_flacdec.so");
1048 emplace("libcodec2_soft_flacenc.so");
1049 emplace("libcodec2_soft_g711alawdec.so");
1050 emplace("libcodec2_soft_g711mlawdec.so");
1051 emplace("libcodec2_soft_gsmdec.so");
1052 emplace("libcodec2_soft_h263dec.so");
1053 emplace("libcodec2_soft_h263enc.so");
1054 emplace("libcodec2_soft_hevcdec.so");
Roma Kauldfe650a2018-08-02 17:48:51 +05301055 emplace("libcodec2_soft_hevcenc.so");
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001056 emplace("libcodec2_soft_mp3dec.so");
1057 emplace("libcodec2_soft_mpeg2dec.so");
1058 emplace("libcodec2_soft_mpeg4dec.so");
1059 emplace("libcodec2_soft_mpeg4enc.so");
1060 emplace("libcodec2_soft_opusdec.so");
1061 emplace("libcodec2_soft_opusenc.so");
1062 emplace("libcodec2_soft_rawdec.so");
1063 emplace("libcodec2_soft_vorbisdec.so");
1064 emplace("libcodec2_soft_vp8dec.so");
1065 emplace("libcodec2_soft_vp8enc.so");
1066 emplace("libcodec2_soft_vp9dec.so");
1067 emplace("libcodec2_soft_vp9enc.so");
Pawin Vongmasa36653902018-11-15 00:10:25 -08001068}
1069
1070c2_status_t C2PlatformComponentStore::copyBuffer(
1071 std::shared_ptr<C2GraphicBuffer> src, std::shared_ptr<C2GraphicBuffer> dst) {
1072 (void)src;
1073 (void)dst;
1074 return C2_OMITTED;
1075}
1076
1077c2_status_t C2PlatformComponentStore::query_sm(
1078 const std::vector<C2Param*> &stackParams,
1079 const std::vector<C2Param::Index> &heapParamIndices,
1080 std::vector<std::unique_ptr<C2Param>> *const heapParams) const {
1081 return mInterface.query(stackParams, heapParamIndices, C2_MAY_BLOCK, heapParams);
1082}
1083
1084c2_status_t C2PlatformComponentStore::config_sm(
1085 const std::vector<C2Param*> &params,
1086 std::vector<std::unique_ptr<C2SettingResult>> *const failures) {
1087 return mInterface.config(params, C2_MAY_BLOCK, failures);
1088}
1089
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001090void C2PlatformComponentStore::visitComponents() {
1091 std::lock_guard<std::mutex> lock(mMutex);
1092 if (mVisited) {
1093 return;
1094 }
1095 for (auto &pathAndLoader : mComponents) {
1096 const C2String &path = pathAndLoader.first;
1097 ComponentLoader &loader = pathAndLoader.second;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001098 std::shared_ptr<ComponentModule> module;
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001099 if (loader.fetchModule(&module) == C2_OK) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001100 std::shared_ptr<const C2Component::Traits> traits = module->getTraits();
1101 if (traits) {
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001102 mComponentList.push_back(traits);
1103 mComponentNameToPath.emplace(traits->name, path);
1104 for (const C2String &alias : traits->aliases) {
1105 mComponentNameToPath.emplace(alias, path);
1106 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001107 }
1108 }
1109 }
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001110 mVisited = true;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001111}
1112
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001113std::vector<std::shared_ptr<const C2Component::Traits>> C2PlatformComponentStore::listComponents() {
1114 // This method SHALL return within 500ms.
1115 visitComponents();
1116 return mComponentList;
1117}
1118
1119c2_status_t C2PlatformComponentStore::findComponent(
1120 C2String name, std::shared_ptr<ComponentModule> *module) {
1121 (*module).reset();
1122 visitComponents();
1123
1124 auto pos = mComponentNameToPath.find(name);
1125 if (pos != mComponentNameToPath.end()) {
1126 return mComponents.at(pos->second).fetchModule(module);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001127 }
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001128 return C2_NOT_FOUND;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001129}
1130
1131c2_status_t C2PlatformComponentStore::createComponent(
1132 C2String name, std::shared_ptr<C2Component> *const component) {
1133 // This method SHALL return within 100ms.
1134 component->reset();
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001135 std::shared_ptr<ComponentModule> module;
1136 c2_status_t res = findComponent(name, &module);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001137 if (res == C2_OK) {
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001138 // TODO: get a unique node ID
1139 res = module->createComponent(0, component);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001140 }
1141 return res;
1142}
1143
1144c2_status_t C2PlatformComponentStore::createInterface(
1145 C2String name, std::shared_ptr<C2ComponentInterface> *const interface) {
1146 // This method SHALL return within 100ms.
1147 interface->reset();
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001148 std::shared_ptr<ComponentModule> module;
1149 c2_status_t res = findComponent(name, &module);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001150 if (res == C2_OK) {
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001151 // TODO: get a unique node ID
1152 res = module->createInterface(0, interface);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001153 }
1154 return res;
1155}
1156
1157c2_status_t C2PlatformComponentStore::querySupportedParams_nb(
1158 std::vector<std::shared_ptr<C2ParamDescriptor>> *const params) const {
1159 return mInterface.querySupportedParams(params);
1160}
1161
1162c2_status_t C2PlatformComponentStore::querySupportedValues_sm(
1163 std::vector<C2FieldSupportedValuesQuery> &fields) const {
1164 return mInterface.querySupportedValues(fields, C2_MAY_BLOCK);
1165}
1166
1167C2String C2PlatformComponentStore::getName() const {
1168 return "android.componentStore.platform";
1169}
1170
1171std::shared_ptr<C2ParamReflector> C2PlatformComponentStore::getParamReflector() const {
1172 return mReflector;
1173}
1174
1175std::shared_ptr<C2ComponentStore> GetCodec2PlatformComponentStore() {
1176 static std::mutex mutex;
1177 static std::weak_ptr<C2ComponentStore> platformStore;
1178 std::lock_guard<std::mutex> lock(mutex);
1179 std::shared_ptr<C2ComponentStore> store = platformStore.lock();
1180 if (store == nullptr) {
1181 store = std::make_shared<C2PlatformComponentStore>();
1182 platformStore = store;
1183 }
1184 return store;
1185}
1186
1187} // namespace android