1 /*
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
21 #include <C2AllocatorBlob.h>
22 #include <C2AllocatorGralloc.h>
23 #include <C2AllocatorIon.h>
24 #include <C2DmaBufAllocator.h>
25 #include <C2BufferPriv.h>
26 #include <C2BqBufferPriv.h>
27 #include <C2Component.h>
28 #include <C2Config.h>
29 #include <C2PlatformStorePluginLoader.h>
30 #include <C2PlatformSupport.h>
31 #include <cutils/properties.h>
32 #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
41 #ifdef __ANDROID_APEX__
42 #include <android-base/properties.h>
43 #endif
44
45 namespace android {
46
47 /**
48 * Returns the preferred component store in this process to access its interface.
49 */
50 std::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 */
60 class C2PlatformAllocatorStoreImpl : public C2PlatformAllocatorStore {
61 public:
62 C2PlatformAllocatorStoreImpl();
63
64 virtual c2_status_t fetchAllocator(
65 id_t id, std::shared_ptr<C2Allocator> *const allocator) override;
66
listAllocators_nb() const67 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
getName() const72 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
80 private:
81 /// returns a shared-singleton blob allocator (gralloc-backed)
82 std::shared_ptr<C2Allocator> fetchBlobAllocator();
83
84 /// returns a shared-singleton ion allocator
85 std::shared_ptr<C2Allocator> fetchIonAllocator();
86 std::shared_ptr<C2Allocator> fetchDmaBufAllocator();
87
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
C2PlatformAllocatorStoreImpl()101 C2PlatformAllocatorStoreImpl::C2PlatformAllocatorStoreImpl() {
102 }
103
using_ion(void)104 static bool using_ion(void) {
105 static int cached_result = []()->int {
106 struct stat buffer;
107 int ret = (stat("/dev/ion", &buffer) == 0);
108
109 if (property_get_int32("debug.c2.use_dmabufheaps", 0)) {
110 /*
111 * Double check that the system heap is present so we
112 * can gracefully fail back to ION if we cannot satisfy
113 * the override
114 */
115 ret = (stat("/dev/dma_heap/system", &buffer) != 0);
116 if (ret)
117 ALOGE("debug.c2.use_dmabufheaps set, but no system heap. Ignoring override!");
118 else
119 ALOGD("debug.c2.use_dmabufheaps set, forcing DMABUF Heaps");
120 }
121
122 if (ret)
123 ALOGD("Using ION\n");
124 else
125 ALOGD("Using DMABUF Heaps\n");
126 return ret;
127 }();
128
129 return (cached_result == 1);
130 }
131
fetchAllocator(id_t id,std::shared_ptr<C2Allocator> * const allocator)132 c2_status_t C2PlatformAllocatorStoreImpl::fetchAllocator(
133 id_t id, std::shared_ptr<C2Allocator> *const allocator) {
134 allocator->reset();
135 if (id == C2AllocatorStore::DEFAULT_LINEAR) {
136 id = GetPreferredLinearAllocatorId(GetCodec2PoolMask());
137 }
138 switch (id) {
139 // TODO: should we implement a generic registry for all, and use that?
140 case C2PlatformAllocatorStore::ION: /* also ::DMABUFHEAP */
141 if (using_ion())
142 *allocator = fetchIonAllocator();
143 else
144 *allocator = fetchDmaBufAllocator();
145 break;
146
147 case C2PlatformAllocatorStore::GRALLOC:
148 case C2AllocatorStore::DEFAULT_GRAPHIC:
149 *allocator = fetchGrallocAllocator();
150 break;
151
152 case C2PlatformAllocatorStore::BUFFERQUEUE:
153 *allocator = fetchBufferQueueAllocator();
154 break;
155
156 case C2PlatformAllocatorStore::BLOB:
157 *allocator = fetchBlobAllocator();
158 break;
159
160 default:
161 // Try to create allocator from platform store plugins.
162 c2_status_t res =
163 C2PlatformStorePluginLoader::GetInstance()->createAllocator(id, allocator);
164 if (res != C2_OK) {
165 return res;
166 }
167 break;
168 }
169 if (*allocator == nullptr) {
170 return C2_NO_MEMORY;
171 }
172 return C2_OK;
173 }
174
175 namespace {
176
177 std::mutex gIonAllocatorMutex;
178 std::mutex gDmaBufAllocatorMutex;
179 std::weak_ptr<C2AllocatorIon> gIonAllocator;
180 std::weak_ptr<C2DmaBufAllocator> gDmaBufAllocator;
181
UseComponentStoreForIonAllocator(const std::shared_ptr<C2AllocatorIon> allocator,std::shared_ptr<C2ComponentStore> store)182 void UseComponentStoreForIonAllocator(
183 const std::shared_ptr<C2AllocatorIon> allocator,
184 std::shared_ptr<C2ComponentStore> store) {
185 C2AllocatorIon::UsageMapperFn mapper;
186 uint64_t minUsage = 0;
187 uint64_t maxUsage = C2MemoryUsage(C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE).expected;
188 size_t blockSize = getpagesize();
189
190 // query min and max usage as well as block size via supported values
191 C2StoreIonUsageInfo usageInfo;
192 std::vector<C2FieldSupportedValuesQuery> query = {
193 C2FieldSupportedValuesQuery::Possible(C2ParamField::Make(usageInfo, usageInfo.usage)),
194 C2FieldSupportedValuesQuery::Possible(C2ParamField::Make(usageInfo, usageInfo.capacity)),
195 };
196 c2_status_t res = store->querySupportedValues_sm(query);
197 if (res == C2_OK) {
198 if (query[0].status == C2_OK) {
199 const C2FieldSupportedValues &fsv = query[0].values;
200 if (fsv.type == C2FieldSupportedValues::FLAGS && !fsv.values.empty()) {
201 minUsage = fsv.values[0].u64;
202 maxUsage = 0;
203 for (C2Value::Primitive v : fsv.values) {
204 maxUsage |= v.u64;
205 }
206 }
207 }
208 if (query[1].status == C2_OK) {
209 const C2FieldSupportedValues &fsv = query[1].values;
210 if (fsv.type == C2FieldSupportedValues::RANGE && fsv.range.step.u32 > 0) {
211 blockSize = fsv.range.step.u32;
212 }
213 }
214
215 mapper = [store](C2MemoryUsage usage, size_t capacity,
216 size_t *align, unsigned *heapMask, unsigned *flags) -> c2_status_t {
217 if (capacity > UINT32_MAX) {
218 return C2_BAD_VALUE;
219 }
220 C2StoreIonUsageInfo usageInfo = { usage.expected, capacity };
221 std::vector<std::unique_ptr<C2SettingResult>> failures; // TODO: remove
222 c2_status_t res = store->config_sm({&usageInfo}, &failures);
223 if (res == C2_OK) {
224 *align = usageInfo.minAlignment;
225 *heapMask = usageInfo.heapMask;
226 *flags = usageInfo.allocFlags;
227 }
228 return res;
229 };
230 }
231
232 allocator->setUsageMapper(mapper, minUsage, maxUsage, blockSize);
233 }
234
UseComponentStoreForDmaBufAllocator(const std::shared_ptr<C2DmaBufAllocator> allocator,std::shared_ptr<C2ComponentStore> store)235 void UseComponentStoreForDmaBufAllocator(const std::shared_ptr<C2DmaBufAllocator> allocator,
236 std::shared_ptr<C2ComponentStore> store) {
237 C2DmaBufAllocator::UsageMapperFn mapper;
238 const size_t maxHeapNameLen = 128;
239 uint64_t minUsage = 0;
240 uint64_t maxUsage = C2MemoryUsage(C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE).expected;
241 size_t blockSize = getpagesize();
242
243 // query min and max usage as well as block size via supported values
244 std::unique_ptr<C2StoreDmaBufUsageInfo> usageInfo;
245 usageInfo = C2StoreDmaBufUsageInfo::AllocUnique(maxHeapNameLen);
246
247 std::vector<C2FieldSupportedValuesQuery> query = {
248 C2FieldSupportedValuesQuery::Possible(C2ParamField::Make(*usageInfo, usageInfo->m.usage)),
249 C2FieldSupportedValuesQuery::Possible(
250 C2ParamField::Make(*usageInfo, usageInfo->m.capacity)),
251 };
252 c2_status_t res = store->querySupportedValues_sm(query);
253 if (res == C2_OK) {
254 if (query[0].status == C2_OK) {
255 const C2FieldSupportedValues& fsv = query[0].values;
256 if (fsv.type == C2FieldSupportedValues::FLAGS && !fsv.values.empty()) {
257 minUsage = fsv.values[0].u64;
258 maxUsage = 0;
259 for (C2Value::Primitive v : fsv.values) {
260 maxUsage |= v.u64;
261 }
262 }
263 }
264 if (query[1].status == C2_OK) {
265 const C2FieldSupportedValues& fsv = query[1].values;
266 if (fsv.type == C2FieldSupportedValues::RANGE && fsv.range.step.u32 > 0) {
267 blockSize = fsv.range.step.u32;
268 }
269 }
270
271 mapper = [store](C2MemoryUsage usage, size_t capacity, C2String* heapName,
272 unsigned* flags) -> c2_status_t {
273 if (capacity > UINT32_MAX) {
274 return C2_BAD_VALUE;
275 }
276
277 std::unique_ptr<C2StoreDmaBufUsageInfo> usageInfo;
278 usageInfo = C2StoreDmaBufUsageInfo::AllocUnique(maxHeapNameLen, usage.expected, capacity);
279 std::vector<std::unique_ptr<C2SettingResult>> failures; // TODO: remove
280
281 c2_status_t res = store->config_sm({&*usageInfo}, &failures);
282 if (res == C2_OK) {
283 *heapName = C2String(usageInfo->m.heapName);
284 *flags = usageInfo->m.allocFlags;
285 }
286
287 return res;
288 };
289 }
290
291 allocator->setUsageMapper(mapper, minUsage, maxUsage, blockSize);
292 }
293
294 }
295
setComponentStore(std::shared_ptr<C2ComponentStore> store)296 void C2PlatformAllocatorStoreImpl::setComponentStore(std::shared_ptr<C2ComponentStore> store) {
297 // technically this set lock is not needed, but is here for safety in case we add more
298 // getter orders
299 std::lock_guard<std::mutex> lock(_mComponentStoreSetLock);
300 {
301 std::lock_guard<std::mutex> lock(_mComponentStoreReadLock);
302 _mComponentStore = store;
303 }
304 std::shared_ptr<C2AllocatorIon> allocator;
305 {
306 std::lock_guard<std::mutex> lock(gIonAllocatorMutex);
307 allocator = gIonAllocator.lock();
308 }
309 if (allocator) {
310 UseComponentStoreForIonAllocator(allocator, store);
311 }
312 }
313
fetchIonAllocator()314 std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchIonAllocator() {
315 std::lock_guard<std::mutex> lock(gIonAllocatorMutex);
316 std::shared_ptr<C2AllocatorIon> allocator = gIonAllocator.lock();
317 if (allocator == nullptr) {
318 std::shared_ptr<C2ComponentStore> componentStore;
319 {
320 std::lock_guard<std::mutex> lock(_mComponentStoreReadLock);
321 componentStore = _mComponentStore;
322 }
323 allocator = std::make_shared<C2AllocatorIon>(C2PlatformAllocatorStore::ION);
324 UseComponentStoreForIonAllocator(allocator, componentStore);
325 gIonAllocator = allocator;
326 }
327 return allocator;
328 }
329
fetchDmaBufAllocator()330 std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchDmaBufAllocator() {
331 std::lock_guard<std::mutex> lock(gDmaBufAllocatorMutex);
332 std::shared_ptr<C2DmaBufAllocator> allocator = gDmaBufAllocator.lock();
333 if (allocator == nullptr) {
334 std::shared_ptr<C2ComponentStore> componentStore;
335 {
336 std::lock_guard<std::mutex> lock(_mComponentStoreReadLock);
337 componentStore = _mComponentStore;
338 }
339 allocator = std::make_shared<C2DmaBufAllocator>(C2PlatformAllocatorStore::DMABUFHEAP);
340 UseComponentStoreForDmaBufAllocator(allocator, componentStore);
341 gDmaBufAllocator = allocator;
342 }
343 return allocator;
344 }
345
fetchBlobAllocator()346 std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchBlobAllocator() {
347 static std::mutex mutex;
348 static std::weak_ptr<C2Allocator> blobAllocator;
349 std::lock_guard<std::mutex> lock(mutex);
350 std::shared_ptr<C2Allocator> allocator = blobAllocator.lock();
351 if (allocator == nullptr) {
352 allocator = std::make_shared<C2AllocatorBlob>(C2PlatformAllocatorStore::BLOB);
353 blobAllocator = allocator;
354 }
355 return allocator;
356 }
357
fetchGrallocAllocator()358 std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchGrallocAllocator() {
359 static std::mutex mutex;
360 static std::weak_ptr<C2Allocator> grallocAllocator;
361 std::lock_guard<std::mutex> lock(mutex);
362 std::shared_ptr<C2Allocator> allocator = grallocAllocator.lock();
363 if (allocator == nullptr) {
364 allocator = std::make_shared<C2AllocatorGralloc>(C2PlatformAllocatorStore::GRALLOC);
365 grallocAllocator = allocator;
366 }
367 return allocator;
368 }
369
fetchBufferQueueAllocator()370 std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchBufferQueueAllocator() {
371 static std::mutex mutex;
372 static std::weak_ptr<C2Allocator> grallocAllocator;
373 std::lock_guard<std::mutex> lock(mutex);
374 std::shared_ptr<C2Allocator> allocator = grallocAllocator.lock();
375 if (allocator == nullptr) {
376 allocator = std::make_shared<C2AllocatorGralloc>(
377 C2PlatformAllocatorStore::BUFFERQUEUE, true);
378 grallocAllocator = allocator;
379 }
380 return allocator;
381 }
382
383 namespace {
384 std::mutex gPreferredComponentStoreMutex;
385 std::shared_ptr<C2ComponentStore> gPreferredComponentStore;
386
387 std::mutex gPlatformAllocatorStoreMutex;
388 std::weak_ptr<C2PlatformAllocatorStoreImpl> gPlatformAllocatorStore;
389 }
390
GetCodec2PlatformAllocatorStore()391 std::shared_ptr<C2AllocatorStore> GetCodec2PlatformAllocatorStore() {
392 std::lock_guard<std::mutex> lock(gPlatformAllocatorStoreMutex);
393 std::shared_ptr<C2PlatformAllocatorStoreImpl> store = gPlatformAllocatorStore.lock();
394 if (store == nullptr) {
395 store = std::make_shared<C2PlatformAllocatorStoreImpl>();
396 store->setComponentStore(GetPreferredCodec2ComponentStore());
397 gPlatformAllocatorStore = store;
398 }
399 return store;
400 }
401
SetPreferredCodec2ComponentStore(std::shared_ptr<C2ComponentStore> componentStore)402 void SetPreferredCodec2ComponentStore(std::shared_ptr<C2ComponentStore> componentStore) {
403 static std::mutex mutex;
404 std::lock_guard<std::mutex> lock(mutex); // don't interleve set-s
405
406 // update preferred store
407 {
408 std::lock_guard<std::mutex> lock(gPreferredComponentStoreMutex);
409 gPreferredComponentStore = componentStore;
410 }
411
412 // update platform allocator's store as well if it is alive
413 std::shared_ptr<C2PlatformAllocatorStoreImpl> allocatorStore;
414 {
415 std::lock_guard<std::mutex> lock(gPlatformAllocatorStoreMutex);
416 allocatorStore = gPlatformAllocatorStore.lock();
417 }
418 if (allocatorStore) {
419 allocatorStore->setComponentStore(componentStore);
420 }
421 }
422
GetPreferredCodec2ComponentStore()423 std::shared_ptr<C2ComponentStore> GetPreferredCodec2ComponentStore() {
424 std::lock_guard<std::mutex> lock(gPreferredComponentStoreMutex);
425 return gPreferredComponentStore ? gPreferredComponentStore : GetCodec2PlatformComponentStore();
426 }
427
GetCodec2PoolMask()428 int GetCodec2PoolMask() {
429 return property_get_int32(
430 "debug.stagefright.c2-poolmask",
431 1 << C2PlatformAllocatorStore::ION |
432 1 << C2PlatformAllocatorStore::BUFFERQUEUE);
433 }
434
GetPreferredLinearAllocatorId(int poolMask)435 C2PlatformAllocatorStore::id_t GetPreferredLinearAllocatorId(int poolMask) {
436 return ((poolMask >> C2PlatformAllocatorStore::BLOB) & 1) ? C2PlatformAllocatorStore::BLOB
437 : C2PlatformAllocatorStore::ION;
438 }
439
440 namespace {
441
442 class _C2BlockPoolCache {
443 public:
_C2BlockPoolCache()444 _C2BlockPoolCache() : mBlockPoolSeqId(C2BlockPool::PLATFORM_START + 1) {}
445
446 private:
_createBlockPool(C2PlatformAllocatorStore::id_t allocatorId,std::vector<std::shared_ptr<const C2Component>> components,C2BlockPool::local_id_t poolId,std::shared_ptr<C2BlockPool> * pool)447 c2_status_t _createBlockPool(
448 C2PlatformAllocatorStore::id_t allocatorId,
449 std::vector<std::shared_ptr<const C2Component>> components,
450 C2BlockPool::local_id_t poolId,
451 std::shared_ptr<C2BlockPool> *pool) {
452 std::shared_ptr<C2AllocatorStore> allocatorStore =
453 GetCodec2PlatformAllocatorStore();
454 std::shared_ptr<C2Allocator> allocator;
455 c2_status_t res = C2_NOT_FOUND;
456
457 if (allocatorId == C2AllocatorStore::DEFAULT_LINEAR) {
458 allocatorId = GetPreferredLinearAllocatorId(GetCodec2PoolMask());
459 }
460 auto deleter = [this, poolId](C2BlockPool *pool) {
461 std::unique_lock lock(mMutex);
462 mBlockPools.erase(poolId);
463 mComponents.erase(poolId);
464 delete pool;
465 };
466 switch(allocatorId) {
467 case C2PlatformAllocatorStore::ION: /* also ::DMABUFHEAP */
468 res = allocatorStore->fetchAllocator(
469 C2PlatformAllocatorStore::ION, &allocator);
470 if (res == C2_OK) {
471 std::shared_ptr<C2BlockPool> ptr(
472 new C2PooledBlockPool(allocator, poolId), deleter);
473 *pool = ptr;
474 mBlockPools[poolId] = ptr;
475 mComponents[poolId].insert(
476 mComponents[poolId].end(),
477 components.begin(), components.end());
478 }
479 break;
480 case C2PlatformAllocatorStore::BLOB:
481 res = allocatorStore->fetchAllocator(
482 C2PlatformAllocatorStore::BLOB, &allocator);
483 if (res == C2_OK) {
484 std::shared_ptr<C2BlockPool> ptr(
485 new C2PooledBlockPool(allocator, poolId), deleter);
486 *pool = ptr;
487 mBlockPools[poolId] = ptr;
488 mComponents[poolId].insert(
489 mComponents[poolId].end(),
490 components.begin(), components.end());
491 }
492 break;
493 case C2PlatformAllocatorStore::GRALLOC:
494 case C2AllocatorStore::DEFAULT_GRAPHIC:
495 res = allocatorStore->fetchAllocator(
496 C2AllocatorStore::DEFAULT_GRAPHIC, &allocator);
497 if (res == C2_OK) {
498 std::shared_ptr<C2BlockPool> ptr(
499 new C2PooledBlockPool(allocator, poolId), deleter);
500 *pool = ptr;
501 mBlockPools[poolId] = ptr;
502 mComponents[poolId].insert(
503 mComponents[poolId].end(),
504 components.begin(), components.end());
505 }
506 break;
507 case C2PlatformAllocatorStore::BUFFERQUEUE:
508 res = allocatorStore->fetchAllocator(
509 C2PlatformAllocatorStore::BUFFERQUEUE, &allocator);
510 if (res == C2_OK) {
511 std::shared_ptr<C2BlockPool> ptr(
512 new C2BufferQueueBlockPool(allocator, poolId), deleter);
513 *pool = ptr;
514 mBlockPools[poolId] = ptr;
515 mComponents[poolId].insert(
516 mComponents[poolId].end(),
517 components.begin(), components.end());
518 }
519 break;
520 default:
521 // Try to create block pool from platform store plugins.
522 std::shared_ptr<C2BlockPool> ptr;
523 res = C2PlatformStorePluginLoader::GetInstance()->createBlockPool(
524 allocatorId, poolId, &ptr, deleter);
525 if (res == C2_OK) {
526 *pool = ptr;
527 mBlockPools[poolId] = ptr;
528 mComponents[poolId].insert(
529 mComponents[poolId].end(),
530 components.begin(), components.end());
531 }
532 break;
533 }
534 return res;
535 }
536
537 public:
createBlockPool(C2PlatformAllocatorStore::id_t allocatorId,std::vector<std::shared_ptr<const C2Component>> components,std::shared_ptr<C2BlockPool> * pool)538 c2_status_t createBlockPool(
539 C2PlatformAllocatorStore::id_t allocatorId,
540 std::vector<std::shared_ptr<const C2Component>> components,
541 std::shared_ptr<C2BlockPool> *pool) {
542 std::unique_lock lock(mMutex);
543 return _createBlockPool(allocatorId, components, mBlockPoolSeqId++, pool);
544 }
545
getBlockPool(C2BlockPool::local_id_t blockPoolId,std::shared_ptr<const C2Component> component,std::shared_ptr<C2BlockPool> * pool)546 c2_status_t getBlockPool(
547 C2BlockPool::local_id_t blockPoolId,
548 std::shared_ptr<const C2Component> component,
549 std::shared_ptr<C2BlockPool> *pool) {
550 std::unique_lock lock(mMutex);
551 // TODO: use one iterator for multiple blockpool type scalability.
552 std::shared_ptr<C2BlockPool> ptr;
553 auto it = mBlockPools.find(blockPoolId);
554 if (it != mBlockPools.end()) {
555 ptr = it->second.lock();
556 if (!ptr) {
557 mBlockPools.erase(it);
558 mComponents.erase(blockPoolId);
559 } else {
560 auto found = std::find_if(
561 mComponents[blockPoolId].begin(),
562 mComponents[blockPoolId].end(),
563 [component](const std::weak_ptr<const C2Component> &ptr) {
564 return component == ptr.lock();
565 });
566 if (found != mComponents[blockPoolId].end()) {
567 *pool = ptr;
568 return C2_OK;
569 }
570 }
571 }
572 // TODO: remove this. this is temporary
573 if (blockPoolId == C2BlockPool::PLATFORM_START) {
574 return _createBlockPool(
575 C2PlatformAllocatorStore::BUFFERQUEUE, {component}, blockPoolId, pool);
576 }
577 return C2_NOT_FOUND;
578 }
579
580 private:
581 // Deleter needs to hold this mutex, and there is a small chance that deleter
582 // is invoked while the mutex is held.
583 std::recursive_mutex mMutex;
584 C2BlockPool::local_id_t mBlockPoolSeqId;
585
586 std::map<C2BlockPool::local_id_t, std::weak_ptr<C2BlockPool>> mBlockPools;
587 std::map<C2BlockPool::local_id_t, std::vector<std::weak_ptr<const C2Component>>> mComponents;
588 };
589
590 static std::unique_ptr<_C2BlockPoolCache> sBlockPoolCache =
591 std::make_unique<_C2BlockPoolCache>();
592
593 } // anynymous namespace
594
GetCodec2BlockPool(C2BlockPool::local_id_t id,std::shared_ptr<const C2Component> component,std::shared_ptr<C2BlockPool> * pool)595 c2_status_t GetCodec2BlockPool(
596 C2BlockPool::local_id_t id, std::shared_ptr<const C2Component> component,
597 std::shared_ptr<C2BlockPool> *pool) {
598 pool->reset();
599 std::shared_ptr<C2AllocatorStore> allocatorStore = GetCodec2PlatformAllocatorStore();
600 std::shared_ptr<C2Allocator> allocator;
601 c2_status_t res = C2_NOT_FOUND;
602
603 if (id >= C2BlockPool::PLATFORM_START) {
604 return sBlockPoolCache->getBlockPool(id, component, pool);
605 }
606
607 switch (id) {
608 case C2BlockPool::BASIC_LINEAR:
609 res = allocatorStore->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &allocator);
610 if (res == C2_OK) {
611 *pool = std::make_shared<C2BasicLinearBlockPool>(allocator);
612 }
613 break;
614 case C2BlockPool::BASIC_GRAPHIC:
615 res = allocatorStore->fetchAllocator(C2AllocatorStore::DEFAULT_GRAPHIC, &allocator);
616 if (res == C2_OK) {
617 *pool = std::make_shared<C2BasicGraphicBlockPool>(allocator);
618 }
619 break;
620 default:
621 break;
622 }
623 return res;
624 }
625
CreateCodec2BlockPool(C2PlatformAllocatorStore::id_t allocatorId,const std::vector<std::shared_ptr<const C2Component>> & components,std::shared_ptr<C2BlockPool> * pool)626 c2_status_t CreateCodec2BlockPool(
627 C2PlatformAllocatorStore::id_t allocatorId,
628 const std::vector<std::shared_ptr<const C2Component>> &components,
629 std::shared_ptr<C2BlockPool> *pool) {
630 pool->reset();
631
632 return sBlockPoolCache->createBlockPool(allocatorId, components, pool);
633 }
634
CreateCodec2BlockPool(C2PlatformAllocatorStore::id_t allocatorId,std::shared_ptr<const C2Component> component,std::shared_ptr<C2BlockPool> * pool)635 c2_status_t CreateCodec2BlockPool(
636 C2PlatformAllocatorStore::id_t allocatorId,
637 std::shared_ptr<const C2Component> component,
638 std::shared_ptr<C2BlockPool> *pool) {
639 pool->reset();
640
641 return sBlockPoolCache->createBlockPool(allocatorId, {component}, pool);
642 }
643
644 class C2PlatformComponentStore : public C2ComponentStore {
645 public:
646 virtual std::vector<std::shared_ptr<const C2Component::Traits>> listComponents() override;
647 virtual std::shared_ptr<C2ParamReflector> getParamReflector() const override;
648 virtual C2String getName() const override;
649 virtual c2_status_t querySupportedValues_sm(
650 std::vector<C2FieldSupportedValuesQuery> &fields) const override;
651 virtual c2_status_t querySupportedParams_nb(
652 std::vector<std::shared_ptr<C2ParamDescriptor>> *const params) const override;
653 virtual c2_status_t query_sm(
654 const std::vector<C2Param*> &stackParams,
655 const std::vector<C2Param::Index> &heapParamIndices,
656 std::vector<std::unique_ptr<C2Param>> *const heapParams) const override;
657 virtual c2_status_t createInterface(
658 C2String name, std::shared_ptr<C2ComponentInterface> *const interface) override;
659 virtual c2_status_t createComponent(
660 C2String name, std::shared_ptr<C2Component> *const component) override;
661 virtual c2_status_t copyBuffer(
662 std::shared_ptr<C2GraphicBuffer> src, std::shared_ptr<C2GraphicBuffer> dst) override;
663 virtual c2_status_t config_sm(
664 const std::vector<C2Param*> ¶ms,
665 std::vector<std::unique_ptr<C2SettingResult>> *const failures) override;
666 C2PlatformComponentStore();
667
668 // For testing only
669 C2PlatformComponentStore(
670 std::vector<std::tuple<C2String,
671 C2ComponentFactory::CreateCodec2FactoryFunc,
672 C2ComponentFactory::DestroyCodec2FactoryFunc>>);
673
674 virtual ~C2PlatformComponentStore() override = default;
675
676 private:
677
678 /**
679 * An object encapsulating a loaded component module.
680 *
681 * \todo provide a way to add traits to known components here to avoid loading the .so-s
682 * for listComponents
683 */
684 struct ComponentModule : public C2ComponentFactory,
685 public std::enable_shared_from_this<ComponentModule> {
686 virtual c2_status_t createComponent(
687 c2_node_id_t id, std::shared_ptr<C2Component> *component,
688 ComponentDeleter deleter = std::default_delete<C2Component>()) override;
689 virtual c2_status_t createInterface(
690 c2_node_id_t id, std::shared_ptr<C2ComponentInterface> *interface,
691 InterfaceDeleter deleter = std::default_delete<C2ComponentInterface>()) override;
692
693 /**
694 * \returns the traits of the component in this module.
695 */
696 std::shared_ptr<const C2Component::Traits> getTraits();
697
698 /**
699 * Creates an uninitialized component module.
700 *
701 * \param name[in] component name.
702 *
703 * \note Only used by ComponentLoader.
704 */
ComponentModuleandroid::C2PlatformComponentStore::ComponentModule705 ComponentModule()
706 : mInit(C2_NO_INIT),
707 mLibHandle(nullptr),
708 createFactory(nullptr),
709 destroyFactory(nullptr),
710 mComponentFactory(nullptr) {
711 }
712
713 /**
714 * Creates an uninitialized component module.
715 * NOTE: For testing only
716 *
717 * \param name[in] component name.
718 *
719 * \note Only used by ComponentLoader.
720 */
ComponentModuleandroid::C2PlatformComponentStore::ComponentModule721 ComponentModule(
722 C2ComponentFactory::CreateCodec2FactoryFunc createFactory,
723 C2ComponentFactory::DestroyCodec2FactoryFunc destroyFactory)
724 : mInit(C2_NO_INIT),
725 mLibHandle(nullptr),
726 createFactory(createFactory),
727 destroyFactory(destroyFactory),
728 mComponentFactory(nullptr) {
729 }
730
731 /**
732 * Initializes a component module with a given library path. Must be called exactly once.
733 *
734 * \note Only used by ComponentLoader.
735 *
736 * \param libPath[in] library path
737 *
738 * \retval C2_OK the component module has been successfully loaded
739 * \retval C2_NO_MEMORY not enough memory to loading the component module
740 * \retval C2_NOT_FOUND could not locate the component module
741 * \retval C2_CORRUPTED the component module could not be loaded (unexpected)
742 * \retval C2_REFUSED permission denied to load the component module (unexpected)
743 * \retval C2_TIMED_OUT could not load the module within the time limit (unexpected)
744 */
745 c2_status_t init(std::string libPath);
746
747 virtual ~ComponentModule() override;
748
749 protected:
750 std::recursive_mutex mLock; ///< lock protecting mTraits
751 std::shared_ptr<C2Component::Traits> mTraits; ///< cached component traits
752
753 c2_status_t mInit; ///< initialization result
754
755 void *mLibHandle; ///< loaded library handle
756 C2ComponentFactory::CreateCodec2FactoryFunc createFactory; ///< loaded create function
757 C2ComponentFactory::DestroyCodec2FactoryFunc destroyFactory; ///< loaded destroy function
758 C2ComponentFactory *mComponentFactory; ///< loaded/created component factory
759 };
760
761 /**
762 * An object encapsulating a loadable component module.
763 *
764 * \todo make this also work for enumerations
765 */
766 struct ComponentLoader {
767 /**
768 * Load the component module.
769 *
770 * This method simply returns the component module if it is already currently loaded, or
771 * attempts to load it if it is not.
772 *
773 * \param module[out] pointer to the shared pointer where the loaded module shall be stored.
774 * This will be nullptr on error.
775 *
776 * \retval C2_OK the component module has been successfully loaded
777 * \retval C2_NO_MEMORY not enough memory to loading the component module
778 * \retval C2_NOT_FOUND could not locate the component module
779 * \retval C2_CORRUPTED the component module could not be loaded
780 * \retval C2_REFUSED permission denied to load the component module
781 */
fetchModuleandroid::C2PlatformComponentStore::ComponentLoader782 c2_status_t fetchModule(std::shared_ptr<ComponentModule> *module) {
783 c2_status_t res = C2_OK;
784 std::lock_guard<std::mutex> lock(mMutex);
785 std::shared_ptr<ComponentModule> localModule = mModule.lock();
786 if (localModule == nullptr) {
787 if(mCreateFactory) {
788 // For testing only
789 localModule = std::make_shared<ComponentModule>(mCreateFactory,
790 mDestroyFactory);
791 } else {
792 localModule = std::make_shared<ComponentModule>();
793 }
794 res = localModule->init(mLibPath);
795 if (res == C2_OK) {
796 mModule = localModule;
797 }
798 }
799 *module = localModule;
800 return res;
801 }
802
803 /**
804 * Creates a component loader for a specific library path (or name).
805 */
ComponentLoaderandroid::C2PlatformComponentStore::ComponentLoader806 ComponentLoader(std::string libPath)
807 : mLibPath(libPath) {}
808
809 // For testing only
ComponentLoaderandroid::C2PlatformComponentStore::ComponentLoader810 ComponentLoader(std::tuple<C2String,
811 C2ComponentFactory::CreateCodec2FactoryFunc,
812 C2ComponentFactory::DestroyCodec2FactoryFunc> func)
813 : mLibPath(std::get<0>(func)),
814 mCreateFactory(std::get<1>(func)),
815 mDestroyFactory(std::get<2>(func)) {}
816
817 private:
818 std::mutex mMutex; ///< mutex guarding the module
819 std::weak_ptr<ComponentModule> mModule; ///< weak reference to the loaded module
820 std::string mLibPath; ///< library path
821
822 // For testing only
823 C2ComponentFactory::CreateCodec2FactoryFunc mCreateFactory = nullptr;
824 C2ComponentFactory::DestroyCodec2FactoryFunc mDestroyFactory = nullptr;
825 };
826
827 struct Interface : public C2InterfaceHelper {
828 std::shared_ptr<C2StoreIonUsageInfo> mIonUsageInfo;
829 std::shared_ptr<C2StoreDmaBufUsageInfo> mDmaBufUsageInfo;
830
Interfaceandroid::C2PlatformComponentStore::Interface831 Interface(std::shared_ptr<C2ReflectorHelper> reflector)
832 : C2InterfaceHelper(reflector) {
833 setDerivedInstance(this);
834
835 struct Setter {
836 static C2R setIonUsage(bool /* mayBlock */, C2P<C2StoreIonUsageInfo> &me) {
837 #ifdef __ANDROID_APEX__
838 static int32_t defaultHeapMask = [] {
839 int32_t heapmask = base::GetIntProperty(
840 "ro.com.android.media.swcodec.ion.heapmask", int32_t(0xFFFFFFFF));
841 ALOGD("Default ION heapmask = %d", heapmask);
842 return heapmask;
843 }();
844 static int32_t defaultFlags = [] {
845 int32_t flags = base::GetIntProperty(
846 "ro.com.android.media.swcodec.ion.flags", 0);
847 ALOGD("Default ION flags = %d", flags);
848 return flags;
849 }();
850 static uint32_t defaultAlign = [] {
851 uint32_t align = base::GetUintProperty(
852 "ro.com.android.media.swcodec.ion.align", 0u);
853 ALOGD("Default ION align = %d", align);
854 return align;
855 }();
856 me.set().heapMask = defaultHeapMask;
857 me.set().allocFlags = defaultFlags;
858 me.set().minAlignment = defaultAlign;
859 #else
860 me.set().heapMask = ~0;
861 me.set().allocFlags = 0;
862 me.set().minAlignment = 0;
863 #endif
864 return C2R::Ok();
865 };
866
867 static C2R setDmaBufUsage(bool /* mayBlock */, C2P<C2StoreDmaBufUsageInfo> &me) {
868 long long usage = (long long)me.get().m.usage;
869 if (C2DmaBufAllocator::system_uncached_supported() &&
870 !(usage & (C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE))) {
871 strncpy(me.set().m.heapName, "system-uncached", me.v.flexCount());
872 } else {
873 strncpy(me.set().m.heapName, "system", me.v.flexCount());
874 }
875 me.set().m.allocFlags = 0;
876 return C2R::Ok();
877 };
878 };
879
880 addParameter(
881 DefineParam(mIonUsageInfo, "ion-usage")
882 .withDefault(new C2StoreIonUsageInfo())
883 .withFields({
884 C2F(mIonUsageInfo, usage).flags({C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE}),
885 C2F(mIonUsageInfo, capacity).inRange(0, UINT32_MAX, 1024),
886 C2F(mIonUsageInfo, heapMask).any(),
887 C2F(mIonUsageInfo, allocFlags).flags({}),
888 C2F(mIonUsageInfo, minAlignment).equalTo(0)
889 })
890 .withSetter(Setter::setIonUsage)
891 .build());
892
893 addParameter(
894 DefineParam(mDmaBufUsageInfo, "dmabuf-usage")
895 .withDefault(C2StoreDmaBufUsageInfo::AllocShared(0))
896 .withFields({
897 C2F(mDmaBufUsageInfo, m.usage).flags({C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE}),
898 C2F(mDmaBufUsageInfo, m.capacity).inRange(0, UINT32_MAX, 1024),
899 C2F(mDmaBufUsageInfo, m.allocFlags).flags({}),
900 C2F(mDmaBufUsageInfo, m.heapName).any(),
901 })
902 .withSetter(Setter::setDmaBufUsage)
903 .build());
904 }
905 };
906
907 /**
908 * Retrieves the component module for a component.
909 *
910 * \param module pointer to a shared_pointer where the component module will be stored on
911 * success.
912 *
913 * \retval C2_OK the component loader has been successfully retrieved
914 * \retval C2_NO_MEMORY not enough memory to locate the component loader
915 * \retval C2_NOT_FOUND could not locate the component to be loaded
916 * \retval C2_CORRUPTED the component loader could not be identified due to some modules being
917 * corrupted (this can happen if the name does not refer to an already
918 * identified component but some components could not be loaded due to
919 * bad library)
920 * \retval C2_REFUSED permission denied to find the component loader for the named component
921 * (this can happen if the name does not refer to an already identified
922 * component but some components could not be loaded due to lack of
923 * permissions)
924 */
925 c2_status_t findComponent(C2String name, std::shared_ptr<ComponentModule> *module);
926
927 /**
928 * Loads each component module and discover its contents.
929 */
930 void visitComponents();
931
932 std::mutex mMutex; ///< mutex guarding the component lists during construction
933 bool mVisited; ///< component modules visited
934 std::map<C2String, ComponentLoader> mComponents; ///< path -> component module
935 std::map<C2String, C2String> mComponentNameToPath; ///< name -> path
936 std::vector<std::shared_ptr<const C2Component::Traits>> mComponentList;
937
938 std::shared_ptr<C2ReflectorHelper> mReflector;
939 Interface mInterface;
940
941 // For testing only
942 std::vector<std::tuple<C2String,
943 C2ComponentFactory::CreateCodec2FactoryFunc,
944 C2ComponentFactory::DestroyCodec2FactoryFunc>> mCodec2FactoryFuncs;
945 };
946
init(std::string libPath)947 c2_status_t C2PlatformComponentStore::ComponentModule::init(
948 std::string libPath) {
949 ALOGV("in %s", __func__);
950 ALOGV("loading dll");
951
952 if(!createFactory) {
953 mLibHandle = dlopen(libPath.c_str(), RTLD_NOW|RTLD_NODELETE);
954 LOG_ALWAYS_FATAL_IF(mLibHandle == nullptr,
955 "could not dlopen %s: %s", libPath.c_str(), dlerror());
956
957 createFactory =
958 (C2ComponentFactory::CreateCodec2FactoryFunc)dlsym(mLibHandle, "CreateCodec2Factory");
959 LOG_ALWAYS_FATAL_IF(createFactory == nullptr,
960 "createFactory is null in %s", libPath.c_str());
961
962 destroyFactory =
963 (C2ComponentFactory::DestroyCodec2FactoryFunc)dlsym(mLibHandle, "DestroyCodec2Factory");
964 LOG_ALWAYS_FATAL_IF(destroyFactory == nullptr,
965 "destroyFactory is null in %s", libPath.c_str());
966 }
967
968 mComponentFactory = createFactory();
969 if (mComponentFactory == nullptr) {
970 ALOGD("could not create factory in %s", libPath.c_str());
971 mInit = C2_NO_MEMORY;
972 } else {
973 mInit = C2_OK;
974 }
975
976 if (mInit != C2_OK) {
977 return mInit;
978 }
979
980 std::shared_ptr<C2ComponentInterface> intf;
981 c2_status_t res = createInterface(0, &intf);
982 if (res != C2_OK) {
983 ALOGD("failed to create interface: %d", res);
984 return mInit;
985 }
986
987 std::shared_ptr<C2Component::Traits> traits(new (std::nothrow) C2Component::Traits);
988 if (traits) {
989 if (!C2InterfaceUtils::FillTraitsFromInterface(traits.get(), intf)) {
990 ALOGD("Failed to fill traits from interface");
991 return mInit;
992 }
993
994 // TODO: get this properly from the store during emplace
995 switch (traits->domain) {
996 case C2Component::DOMAIN_AUDIO:
997 traits->rank = 8;
998 break;
999 default:
1000 traits->rank = 512;
1001 }
1002 }
1003 mTraits = traits;
1004
1005 return mInit;
1006 }
1007
~ComponentModule()1008 C2PlatformComponentStore::ComponentModule::~ComponentModule() {
1009 ALOGV("in %s", __func__);
1010 if (destroyFactory && mComponentFactory) {
1011 destroyFactory(mComponentFactory);
1012 }
1013 if (mLibHandle) {
1014 ALOGV("unloading dll");
1015 dlclose(mLibHandle);
1016 }
1017 }
1018
createInterface(c2_node_id_t id,std::shared_ptr<C2ComponentInterface> * interface,std::function<void (::C2ComponentInterface *)> deleter)1019 c2_status_t C2PlatformComponentStore::ComponentModule::createInterface(
1020 c2_node_id_t id, std::shared_ptr<C2ComponentInterface> *interface,
1021 std::function<void(::C2ComponentInterface*)> deleter) {
1022 interface->reset();
1023 if (mInit != C2_OK) {
1024 return mInit;
1025 }
1026 std::shared_ptr<ComponentModule> module = shared_from_this();
1027 c2_status_t res = mComponentFactory->createInterface(
1028 id, interface, [module, deleter](C2ComponentInterface *p) mutable {
1029 // capture module so that we ensure we still have it while deleting interface
1030 deleter(p); // delete interface first
1031 module.reset(); // remove module ref (not technically needed)
1032 });
1033 return res;
1034 }
1035
createComponent(c2_node_id_t id,std::shared_ptr<C2Component> * component,std::function<void (::C2Component *)> deleter)1036 c2_status_t C2PlatformComponentStore::ComponentModule::createComponent(
1037 c2_node_id_t id, std::shared_ptr<C2Component> *component,
1038 std::function<void(::C2Component*)> deleter) {
1039 component->reset();
1040 if (mInit != C2_OK) {
1041 return mInit;
1042 }
1043 std::shared_ptr<ComponentModule> module = shared_from_this();
1044 c2_status_t res = mComponentFactory->createComponent(
1045 id, component, [module, deleter](C2Component *p) mutable {
1046 // capture module so that we ensure we still have it while deleting component
1047 deleter(p); // delete component first
1048 module.reset(); // remove module ref (not technically needed)
1049 });
1050 return res;
1051 }
1052
getTraits()1053 std::shared_ptr<const C2Component::Traits> C2PlatformComponentStore::ComponentModule::getTraits() {
1054 std::unique_lock<std::recursive_mutex> lock(mLock);
1055 return mTraits;
1056 }
1057
C2PlatformComponentStore()1058 C2PlatformComponentStore::C2PlatformComponentStore()
1059 : mVisited(false),
1060 mReflector(std::make_shared<C2ReflectorHelper>()),
1061 mInterface(mReflector) {
1062
1063 auto emplace = [this](const char *libPath) {
1064 mComponents.emplace(libPath, libPath);
1065 };
1066
1067 // TODO: move this also into a .so so it can be updated
1068 emplace("libcodec2_soft_aacdec.so");
1069 emplace("libcodec2_soft_aacenc.so");
1070 emplace("libcodec2_soft_amrnbdec.so");
1071 emplace("libcodec2_soft_amrnbenc.so");
1072 emplace("libcodec2_soft_amrwbdec.so");
1073 emplace("libcodec2_soft_amrwbenc.so");
1074 //emplace("libcodec2_soft_av1dec_aom.so"); // deprecated for the gav1 implementation
1075 emplace("libcodec2_soft_av1dec_gav1.so");
1076 emplace("libcodec2_soft_avcdec.so");
1077 emplace("libcodec2_soft_avcenc.so");
1078 emplace("libcodec2_soft_flacdec.so");
1079 emplace("libcodec2_soft_flacenc.so");
1080 emplace("libcodec2_soft_g711alawdec.so");
1081 emplace("libcodec2_soft_g711mlawdec.so");
1082 emplace("libcodec2_soft_gsmdec.so");
1083 emplace("libcodec2_soft_h263dec.so");
1084 emplace("libcodec2_soft_h263enc.so");
1085 emplace("libcodec2_soft_hevcdec.so");
1086 emplace("libcodec2_soft_hevcenc.so");
1087 emplace("libcodec2_soft_mp3dec.so");
1088 emplace("libcodec2_soft_mpeg2dec.so");
1089 emplace("libcodec2_soft_mpeg4dec.so");
1090 emplace("libcodec2_soft_mpeg4enc.so");
1091 emplace("libcodec2_soft_opusdec.so");
1092 emplace("libcodec2_soft_opusenc.so");
1093 emplace("libcodec2_soft_rawdec.so");
1094 emplace("libcodec2_soft_vorbisdec.so");
1095 emplace("libcodec2_soft_vp8dec.so");
1096 emplace("libcodec2_soft_vp8enc.so");
1097 emplace("libcodec2_soft_vp9dec.so");
1098 emplace("libcodec2_soft_vp9enc.so");
1099
1100 }
1101
1102 // For testing only
C2PlatformComponentStore(std::vector<std::tuple<C2String,C2ComponentFactory::CreateCodec2FactoryFunc,C2ComponentFactory::DestroyCodec2FactoryFunc>> funcs)1103 C2PlatformComponentStore::C2PlatformComponentStore(
1104 std::vector<std::tuple<C2String,
1105 C2ComponentFactory::CreateCodec2FactoryFunc,
1106 C2ComponentFactory::DestroyCodec2FactoryFunc>> funcs)
1107 : mVisited(false),
1108 mReflector(std::make_shared<C2ReflectorHelper>()),
1109 mInterface(mReflector),
1110 mCodec2FactoryFuncs(funcs) {
1111
1112 for(auto const& func: mCodec2FactoryFuncs) {
1113 mComponents.emplace(std::get<0>(func), func);
1114 }
1115 }
1116
copyBuffer(std::shared_ptr<C2GraphicBuffer> src,std::shared_ptr<C2GraphicBuffer> dst)1117 c2_status_t C2PlatformComponentStore::copyBuffer(
1118 std::shared_ptr<C2GraphicBuffer> src, std::shared_ptr<C2GraphicBuffer> dst) {
1119 (void)src;
1120 (void)dst;
1121 return C2_OMITTED;
1122 }
1123
query_sm(const std::vector<C2Param * > & stackParams,const std::vector<C2Param::Index> & heapParamIndices,std::vector<std::unique_ptr<C2Param>> * const heapParams) const1124 c2_status_t C2PlatformComponentStore::query_sm(
1125 const std::vector<C2Param*> &stackParams,
1126 const std::vector<C2Param::Index> &heapParamIndices,
1127 std::vector<std::unique_ptr<C2Param>> *const heapParams) const {
1128 return mInterface.query(stackParams, heapParamIndices, C2_MAY_BLOCK, heapParams);
1129 }
1130
config_sm(const std::vector<C2Param * > & params,std::vector<std::unique_ptr<C2SettingResult>> * const failures)1131 c2_status_t C2PlatformComponentStore::config_sm(
1132 const std::vector<C2Param*> ¶ms,
1133 std::vector<std::unique_ptr<C2SettingResult>> *const failures) {
1134 return mInterface.config(params, C2_MAY_BLOCK, failures);
1135 }
1136
visitComponents()1137 void C2PlatformComponentStore::visitComponents() {
1138 std::lock_guard<std::mutex> lock(mMutex);
1139 if (mVisited) {
1140 return;
1141 }
1142 for (auto &pathAndLoader : mComponents) {
1143 const C2String &path = pathAndLoader.first;
1144 ComponentLoader &loader = pathAndLoader.second;
1145 std::shared_ptr<ComponentModule> module;
1146 if (loader.fetchModule(&module) == C2_OK) {
1147 std::shared_ptr<const C2Component::Traits> traits = module->getTraits();
1148 if (traits) {
1149 mComponentList.push_back(traits);
1150 mComponentNameToPath.emplace(traits->name, path);
1151 for (const C2String &alias : traits->aliases) {
1152 mComponentNameToPath.emplace(alias, path);
1153 }
1154 }
1155 }
1156 }
1157 mVisited = true;
1158 }
1159
listComponents()1160 std::vector<std::shared_ptr<const C2Component::Traits>> C2PlatformComponentStore::listComponents() {
1161 // This method SHALL return within 500ms.
1162 visitComponents();
1163 return mComponentList;
1164 }
1165
findComponent(C2String name,std::shared_ptr<ComponentModule> * module)1166 c2_status_t C2PlatformComponentStore::findComponent(
1167 C2String name, std::shared_ptr<ComponentModule> *module) {
1168 (*module).reset();
1169 visitComponents();
1170
1171 auto pos = mComponentNameToPath.find(name);
1172 if (pos != mComponentNameToPath.end()) {
1173 return mComponents.at(pos->second).fetchModule(module);
1174 }
1175 return C2_NOT_FOUND;
1176 }
1177
createComponent(C2String name,std::shared_ptr<C2Component> * const component)1178 c2_status_t C2PlatformComponentStore::createComponent(
1179 C2String name, std::shared_ptr<C2Component> *const component) {
1180 // This method SHALL return within 100ms.
1181 component->reset();
1182 std::shared_ptr<ComponentModule> module;
1183 c2_status_t res = findComponent(name, &module);
1184 if (res == C2_OK) {
1185 // TODO: get a unique node ID
1186 res = module->createComponent(0, component);
1187 }
1188 return res;
1189 }
1190
createInterface(C2String name,std::shared_ptr<C2ComponentInterface> * const interface)1191 c2_status_t C2PlatformComponentStore::createInterface(
1192 C2String name, std::shared_ptr<C2ComponentInterface> *const interface) {
1193 // This method SHALL return within 100ms.
1194 interface->reset();
1195 std::shared_ptr<ComponentModule> module;
1196 c2_status_t res = findComponent(name, &module);
1197 if (res == C2_OK) {
1198 // TODO: get a unique node ID
1199 res = module->createInterface(0, interface);
1200 }
1201 return res;
1202 }
1203
querySupportedParams_nb(std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const1204 c2_status_t C2PlatformComponentStore::querySupportedParams_nb(
1205 std::vector<std::shared_ptr<C2ParamDescriptor>> *const params) const {
1206 return mInterface.querySupportedParams(params);
1207 }
1208
querySupportedValues_sm(std::vector<C2FieldSupportedValuesQuery> & fields) const1209 c2_status_t C2PlatformComponentStore::querySupportedValues_sm(
1210 std::vector<C2FieldSupportedValuesQuery> &fields) const {
1211 return mInterface.querySupportedValues(fields, C2_MAY_BLOCK);
1212 }
1213
getName() const1214 C2String C2PlatformComponentStore::getName() const {
1215 return "android.componentStore.platform";
1216 }
1217
getParamReflector() const1218 std::shared_ptr<C2ParamReflector> C2PlatformComponentStore::getParamReflector() const {
1219 return mReflector;
1220 }
1221
GetCodec2PlatformComponentStore()1222 std::shared_ptr<C2ComponentStore> GetCodec2PlatformComponentStore() {
1223 static std::mutex mutex;
1224 static std::weak_ptr<C2ComponentStore> platformStore;
1225 std::lock_guard<std::mutex> lock(mutex);
1226 std::shared_ptr<C2ComponentStore> store = platformStore.lock();
1227 if (store == nullptr) {
1228 store = std::make_shared<C2PlatformComponentStore>();
1229 platformStore = store;
1230 }
1231 return store;
1232 }
1233
1234 // For testing only
GetTestComponentStore(std::vector<std::tuple<C2String,C2ComponentFactory::CreateCodec2FactoryFunc,C2ComponentFactory::DestroyCodec2FactoryFunc>> funcs)1235 std::shared_ptr<C2ComponentStore> GetTestComponentStore(
1236 std::vector<std::tuple<C2String,
1237 C2ComponentFactory::CreateCodec2FactoryFunc,
1238 C2ComponentFactory::DestroyCodec2FactoryFunc>> funcs) {
1239 return std::shared_ptr<C2ComponentStore>(new C2PlatformComponentStore(funcs));
1240 }
1241 } // namespace android
1242