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
_createBlockPool(C2PlatformAllocatorStore::id_t allocatorId,std::vector<std::shared_ptr<const C2Component>> components,C2BlockPool::local_id_t poolId,std::shared_ptr<C2BlockPool> * pool)446 c2_status_t _createBlockPool(
447 C2PlatformAllocatorStore::id_t allocatorId,
448 std::vector<std::shared_ptr<const C2Component>> components,
449 C2BlockPool::local_id_t poolId,
450 std::shared_ptr<C2BlockPool> *pool) {
451 std::shared_ptr<C2AllocatorStore> allocatorStore =
452 GetCodec2PlatformAllocatorStore();
453 std::shared_ptr<C2Allocator> allocator;
454 c2_status_t res = C2_NOT_FOUND;
455
456 if (allocatorId == C2AllocatorStore::DEFAULT_LINEAR) {
457 allocatorId = GetPreferredLinearAllocatorId(GetCodec2PoolMask());
458 }
459 switch(allocatorId) {
460 case C2PlatformAllocatorStore::ION: /* also ::DMABUFHEAP */
461 res = allocatorStore->fetchAllocator(
462 C2PlatformAllocatorStore::ION, &allocator);
463 if (res == C2_OK) {
464 std::shared_ptr<C2BlockPool> ptr =
465 std::make_shared<C2PooledBlockPool>(
466 allocator, poolId);
467 *pool = ptr;
468 mBlockPools[poolId] = ptr;
469 mComponents[poolId].insert(
470 mComponents[poolId].end(),
471 components.begin(), components.end());
472 }
473 break;
474 case C2PlatformAllocatorStore::BLOB:
475 res = allocatorStore->fetchAllocator(
476 C2PlatformAllocatorStore::BLOB, &allocator);
477 if (res == C2_OK) {
478 std::shared_ptr<C2BlockPool> ptr =
479 std::make_shared<C2PooledBlockPool>(
480 allocator, poolId);
481 *pool = ptr;
482 mBlockPools[poolId] = ptr;
483 mComponents[poolId].insert(
484 mComponents[poolId].end(),
485 components.begin(), components.end());
486 }
487 break;
488 case C2PlatformAllocatorStore::GRALLOC:
489 case C2AllocatorStore::DEFAULT_GRAPHIC:
490 res = allocatorStore->fetchAllocator(
491 C2AllocatorStore::DEFAULT_GRAPHIC, &allocator);
492 if (res == C2_OK) {
493 std::shared_ptr<C2BlockPool> ptr =
494 std::make_shared<C2PooledBlockPool>(allocator, poolId);
495 *pool = ptr;
496 mBlockPools[poolId] = ptr;
497 mComponents[poolId].insert(
498 mComponents[poolId].end(),
499 components.begin(), components.end());
500 }
501 break;
502 case C2PlatformAllocatorStore::BUFFERQUEUE:
503 res = allocatorStore->fetchAllocator(
504 C2PlatformAllocatorStore::BUFFERQUEUE, &allocator);
505 if (res == C2_OK) {
506 std::shared_ptr<C2BlockPool> ptr =
507 std::make_shared<C2BufferQueueBlockPool>(
508 allocator, poolId);
509 *pool = ptr;
510 mBlockPools[poolId] = ptr;
511 mComponents[poolId].insert(
512 mComponents[poolId].end(),
513 components.begin(), components.end());
514 }
515 break;
516 default:
517 // Try to create block pool from platform store plugins.
518 std::shared_ptr<C2BlockPool> ptr;
519 res = C2PlatformStorePluginLoader::GetInstance()->createBlockPool(
520 allocatorId, poolId, &ptr);
521 if (res == C2_OK) {
522 *pool = ptr;
523 mBlockPools[poolId] = ptr;
524 mComponents[poolId].insert(
525 mComponents[poolId].end(),
526 components.begin(), components.end());
527 }
528 break;
529 }
530 return res;
531 }
532
createBlockPool(C2PlatformAllocatorStore::id_t allocatorId,std::vector<std::shared_ptr<const C2Component>> components,std::shared_ptr<C2BlockPool> * pool)533 c2_status_t createBlockPool(
534 C2PlatformAllocatorStore::id_t allocatorId,
535 std::vector<std::shared_ptr<const C2Component>> components,
536 std::shared_ptr<C2BlockPool> *pool) {
537 return _createBlockPool(allocatorId, components, mBlockPoolSeqId++, pool);
538 }
539
getBlockPool(C2BlockPool::local_id_t blockPoolId,std::shared_ptr<const C2Component> component,std::shared_ptr<C2BlockPool> * pool)540 bool getBlockPool(
541 C2BlockPool::local_id_t blockPoolId,
542 std::shared_ptr<const C2Component> component,
543 std::shared_ptr<C2BlockPool> *pool) {
544 // TODO: use one iterator for multiple blockpool type scalability.
545 std::shared_ptr<C2BlockPool> ptr;
546 auto it = mBlockPools.find(blockPoolId);
547 if (it != mBlockPools.end()) {
548 ptr = it->second.lock();
549 if (!ptr) {
550 mBlockPools.erase(it);
551 mComponents.erase(blockPoolId);
552 } else {
553 auto found = std::find_if(
554 mComponents[blockPoolId].begin(),
555 mComponents[blockPoolId].end(),
556 [component](const std::weak_ptr<const C2Component> &ptr) {
557 return component == ptr.lock();
558 });
559 if (found != mComponents[blockPoolId].end()) {
560 *pool = ptr;
561 return true;
562 }
563 }
564 }
565 return false;
566 }
567
568 private:
569 C2BlockPool::local_id_t mBlockPoolSeqId;
570
571 std::map<C2BlockPool::local_id_t, std::weak_ptr<C2BlockPool>> mBlockPools;
572 std::map<C2BlockPool::local_id_t, std::vector<std::weak_ptr<const C2Component>>> mComponents;
573 };
574
575 static std::unique_ptr<_C2BlockPoolCache> sBlockPoolCache =
576 std::make_unique<_C2BlockPoolCache>();
577 static std::mutex sBlockPoolCacheMutex;
578
579 } // anynymous namespace
580
GetCodec2BlockPool(C2BlockPool::local_id_t id,std::shared_ptr<const C2Component> component,std::shared_ptr<C2BlockPool> * pool)581 c2_status_t GetCodec2BlockPool(
582 C2BlockPool::local_id_t id, std::shared_ptr<const C2Component> component,
583 std::shared_ptr<C2BlockPool> *pool) {
584 pool->reset();
585 std::lock_guard<std::mutex> lock(sBlockPoolCacheMutex);
586 std::shared_ptr<C2AllocatorStore> allocatorStore = GetCodec2PlatformAllocatorStore();
587 std::shared_ptr<C2Allocator> allocator;
588 c2_status_t res = C2_NOT_FOUND;
589
590 if (id >= C2BlockPool::PLATFORM_START) {
591 if (sBlockPoolCache->getBlockPool(id, component, pool)) {
592 return C2_OK;
593 }
594 }
595
596 switch (id) {
597 case C2BlockPool::BASIC_LINEAR:
598 res = allocatorStore->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &allocator);
599 if (res == C2_OK) {
600 *pool = std::make_shared<C2BasicLinearBlockPool>(allocator);
601 }
602 break;
603 case C2BlockPool::BASIC_GRAPHIC:
604 res = allocatorStore->fetchAllocator(C2AllocatorStore::DEFAULT_GRAPHIC, &allocator);
605 if (res == C2_OK) {
606 *pool = std::make_shared<C2BasicGraphicBlockPool>(allocator);
607 }
608 break;
609 // TODO: remove this. this is temporary
610 case C2BlockPool::PLATFORM_START:
611 res = sBlockPoolCache->_createBlockPool(
612 C2PlatformAllocatorStore::BUFFERQUEUE, {component}, id, pool);
613 break;
614 default:
615 break;
616 }
617 return res;
618 }
619
CreateCodec2BlockPool(C2PlatformAllocatorStore::id_t allocatorId,const std::vector<std::shared_ptr<const C2Component>> & components,std::shared_ptr<C2BlockPool> * pool)620 c2_status_t CreateCodec2BlockPool(
621 C2PlatformAllocatorStore::id_t allocatorId,
622 const std::vector<std::shared_ptr<const C2Component>> &components,
623 std::shared_ptr<C2BlockPool> *pool) {
624 pool->reset();
625
626 std::lock_guard<std::mutex> lock(sBlockPoolCacheMutex);
627 return sBlockPoolCache->createBlockPool(allocatorId, components, pool);
628 }
629
CreateCodec2BlockPool(C2PlatformAllocatorStore::id_t allocatorId,std::shared_ptr<const C2Component> component,std::shared_ptr<C2BlockPool> * pool)630 c2_status_t CreateCodec2BlockPool(
631 C2PlatformAllocatorStore::id_t allocatorId,
632 std::shared_ptr<const C2Component> component,
633 std::shared_ptr<C2BlockPool> *pool) {
634 pool->reset();
635
636 std::lock_guard<std::mutex> lock(sBlockPoolCacheMutex);
637 return sBlockPoolCache->createBlockPool(allocatorId, {component}, pool);
638 }
639
640 class C2PlatformComponentStore : public C2ComponentStore {
641 public:
642 virtual std::vector<std::shared_ptr<const C2Component::Traits>> listComponents() override;
643 virtual std::shared_ptr<C2ParamReflector> getParamReflector() const override;
644 virtual C2String getName() const override;
645 virtual c2_status_t querySupportedValues_sm(
646 std::vector<C2FieldSupportedValuesQuery> &fields) const override;
647 virtual c2_status_t querySupportedParams_nb(
648 std::vector<std::shared_ptr<C2ParamDescriptor>> *const params) const override;
649 virtual c2_status_t query_sm(
650 const std::vector<C2Param*> &stackParams,
651 const std::vector<C2Param::Index> &heapParamIndices,
652 std::vector<std::unique_ptr<C2Param>> *const heapParams) const override;
653 virtual c2_status_t createInterface(
654 C2String name, std::shared_ptr<C2ComponentInterface> *const interface) override;
655 virtual c2_status_t createComponent(
656 C2String name, std::shared_ptr<C2Component> *const component) override;
657 virtual c2_status_t copyBuffer(
658 std::shared_ptr<C2GraphicBuffer> src, std::shared_ptr<C2GraphicBuffer> dst) override;
659 virtual c2_status_t config_sm(
660 const std::vector<C2Param*> ¶ms,
661 std::vector<std::unique_ptr<C2SettingResult>> *const failures) override;
662 C2PlatformComponentStore();
663
664 // For testing only
665 C2PlatformComponentStore(
666 std::vector<std::tuple<C2String,
667 C2ComponentFactory::CreateCodec2FactoryFunc,
668 C2ComponentFactory::DestroyCodec2FactoryFunc>>);
669
670 virtual ~C2PlatformComponentStore() override = default;
671
672 private:
673
674 /**
675 * An object encapsulating a loaded component module.
676 *
677 * \todo provide a way to add traits to known components here to avoid loading the .so-s
678 * for listComponents
679 */
680 struct ComponentModule : public C2ComponentFactory,
681 public std::enable_shared_from_this<ComponentModule> {
682 virtual c2_status_t createComponent(
683 c2_node_id_t id, std::shared_ptr<C2Component> *component,
684 ComponentDeleter deleter = std::default_delete<C2Component>()) override;
685 virtual c2_status_t createInterface(
686 c2_node_id_t id, std::shared_ptr<C2ComponentInterface> *interface,
687 InterfaceDeleter deleter = std::default_delete<C2ComponentInterface>()) override;
688
689 /**
690 * \returns the traits of the component in this module.
691 */
692 std::shared_ptr<const C2Component::Traits> getTraits();
693
694 /**
695 * Creates an uninitialized component module.
696 *
697 * \param name[in] component name.
698 *
699 * \note Only used by ComponentLoader.
700 */
ComponentModuleandroid::C2PlatformComponentStore::ComponentModule701 ComponentModule()
702 : mInit(C2_NO_INIT),
703 mLibHandle(nullptr),
704 createFactory(nullptr),
705 destroyFactory(nullptr),
706 mComponentFactory(nullptr) {
707 }
708
709 /**
710 * Creates an uninitialized component module.
711 * NOTE: For testing only
712 *
713 * \param name[in] component name.
714 *
715 * \note Only used by ComponentLoader.
716 */
ComponentModuleandroid::C2PlatformComponentStore::ComponentModule717 ComponentModule(
718 C2ComponentFactory::CreateCodec2FactoryFunc createFactory,
719 C2ComponentFactory::DestroyCodec2FactoryFunc destroyFactory)
720 : mInit(C2_NO_INIT),
721 mLibHandle(nullptr),
722 createFactory(createFactory),
723 destroyFactory(destroyFactory),
724 mComponentFactory(nullptr) {
725 }
726
727 /**
728 * Initializes a component module with a given library path. Must be called exactly once.
729 *
730 * \note Only used by ComponentLoader.
731 *
732 * \param libPath[in] library path
733 *
734 * \retval C2_OK the component module has been successfully loaded
735 * \retval C2_NO_MEMORY not enough memory to loading the component module
736 * \retval C2_NOT_FOUND could not locate the component module
737 * \retval C2_CORRUPTED the component module could not be loaded (unexpected)
738 * \retval C2_REFUSED permission denied to load the component module (unexpected)
739 * \retval C2_TIMED_OUT could not load the module within the time limit (unexpected)
740 */
741 c2_status_t init(std::string libPath);
742
743 virtual ~ComponentModule() override;
744
745 protected:
746 std::recursive_mutex mLock; ///< lock protecting mTraits
747 std::shared_ptr<C2Component::Traits> mTraits; ///< cached component traits
748
749 c2_status_t mInit; ///< initialization result
750
751 void *mLibHandle; ///< loaded library handle
752 C2ComponentFactory::CreateCodec2FactoryFunc createFactory; ///< loaded create function
753 C2ComponentFactory::DestroyCodec2FactoryFunc destroyFactory; ///< loaded destroy function
754 C2ComponentFactory *mComponentFactory; ///< loaded/created component factory
755 };
756
757 /**
758 * An object encapsulating a loadable component module.
759 *
760 * \todo make this also work for enumerations
761 */
762 struct ComponentLoader {
763 /**
764 * Load the component module.
765 *
766 * This method simply returns the component module if it is already currently loaded, or
767 * attempts to load it if it is not.
768 *
769 * \param module[out] pointer to the shared pointer where the loaded module shall be stored.
770 * This will be nullptr on error.
771 *
772 * \retval C2_OK the component module has been successfully loaded
773 * \retval C2_NO_MEMORY not enough memory to loading the component module
774 * \retval C2_NOT_FOUND could not locate the component module
775 * \retval C2_CORRUPTED the component module could not be loaded
776 * \retval C2_REFUSED permission denied to load the component module
777 */
fetchModuleandroid::C2PlatformComponentStore::ComponentLoader778 c2_status_t fetchModule(std::shared_ptr<ComponentModule> *module) {
779 c2_status_t res = C2_OK;
780 std::lock_guard<std::mutex> lock(mMutex);
781 std::shared_ptr<ComponentModule> localModule = mModule.lock();
782 if (localModule == nullptr) {
783 if(mCreateFactory) {
784 // For testing only
785 localModule = std::make_shared<ComponentModule>(mCreateFactory,
786 mDestroyFactory);
787 } else {
788 localModule = std::make_shared<ComponentModule>();
789 }
790 res = localModule->init(mLibPath);
791 if (res == C2_OK) {
792 mModule = localModule;
793 }
794 }
795 *module = localModule;
796 return res;
797 }
798
799 /**
800 * Creates a component loader for a specific library path (or name).
801 */
ComponentLoaderandroid::C2PlatformComponentStore::ComponentLoader802 ComponentLoader(std::string libPath)
803 : mLibPath(libPath) {}
804
805 // For testing only
ComponentLoaderandroid::C2PlatformComponentStore::ComponentLoader806 ComponentLoader(std::tuple<C2String,
807 C2ComponentFactory::CreateCodec2FactoryFunc,
808 C2ComponentFactory::DestroyCodec2FactoryFunc> func)
809 : mLibPath(std::get<0>(func)),
810 mCreateFactory(std::get<1>(func)),
811 mDestroyFactory(std::get<2>(func)) {}
812
813 private:
814 std::mutex mMutex; ///< mutex guarding the module
815 std::weak_ptr<ComponentModule> mModule; ///< weak reference to the loaded module
816 std::string mLibPath; ///< library path
817
818 // For testing only
819 C2ComponentFactory::CreateCodec2FactoryFunc mCreateFactory = nullptr;
820 C2ComponentFactory::DestroyCodec2FactoryFunc mDestroyFactory = nullptr;
821 };
822
823 struct Interface : public C2InterfaceHelper {
824 std::shared_ptr<C2StoreIonUsageInfo> mIonUsageInfo;
825 std::shared_ptr<C2StoreDmaBufUsageInfo> mDmaBufUsageInfo;
826
Interfaceandroid::C2PlatformComponentStore::Interface827 Interface(std::shared_ptr<C2ReflectorHelper> reflector)
828 : C2InterfaceHelper(reflector) {
829 setDerivedInstance(this);
830
831 struct Setter {
832 static C2R setIonUsage(bool /* mayBlock */, C2P<C2StoreIonUsageInfo> &me) {
833 #ifdef __ANDROID_APEX__
834 static int32_t defaultHeapMask = [] {
835 int32_t heapmask = base::GetIntProperty(
836 "ro.com.android.media.swcodec.ion.heapmask", int32_t(0xFFFFFFFF));
837 ALOGD("Default ION heapmask = %d", heapmask);
838 return heapmask;
839 }();
840 static int32_t defaultFlags = [] {
841 int32_t flags = base::GetIntProperty(
842 "ro.com.android.media.swcodec.ion.flags", 0);
843 ALOGD("Default ION flags = %d", flags);
844 return flags;
845 }();
846 static uint32_t defaultAlign = [] {
847 uint32_t align = base::GetUintProperty(
848 "ro.com.android.media.swcodec.ion.align", 0u);
849 ALOGD("Default ION align = %d", align);
850 return align;
851 }();
852 me.set().heapMask = defaultHeapMask;
853 me.set().allocFlags = defaultFlags;
854 me.set().minAlignment = defaultAlign;
855 #else
856 me.set().heapMask = ~0;
857 me.set().allocFlags = 0;
858 me.set().minAlignment = 0;
859 #endif
860 return C2R::Ok();
861 };
862
863 static C2R setDmaBufUsage(bool /* mayBlock */, C2P<C2StoreDmaBufUsageInfo> &me) {
864 long long usage = (long long)me.get().m.usage;
865 if (C2DmaBufAllocator::system_uncached_supported() &&
866 !(usage & (C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE))) {
867 strncpy(me.set().m.heapName, "system-uncached", me.v.flexCount());
868 } else {
869 strncpy(me.set().m.heapName, "system", me.v.flexCount());
870 }
871 me.set().m.allocFlags = 0;
872 return C2R::Ok();
873 };
874 };
875
876 addParameter(
877 DefineParam(mIonUsageInfo, "ion-usage")
878 .withDefault(new C2StoreIonUsageInfo())
879 .withFields({
880 C2F(mIonUsageInfo, usage).flags({C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE}),
881 C2F(mIonUsageInfo, capacity).inRange(0, UINT32_MAX, 1024),
882 C2F(mIonUsageInfo, heapMask).any(),
883 C2F(mIonUsageInfo, allocFlags).flags({}),
884 C2F(mIonUsageInfo, minAlignment).equalTo(0)
885 })
886 .withSetter(Setter::setIonUsage)
887 .build());
888
889 addParameter(
890 DefineParam(mDmaBufUsageInfo, "dmabuf-usage")
891 .withDefault(C2StoreDmaBufUsageInfo::AllocShared(0))
892 .withFields({
893 C2F(mDmaBufUsageInfo, m.usage).flags({C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE}),
894 C2F(mDmaBufUsageInfo, m.capacity).inRange(0, UINT32_MAX, 1024),
895 C2F(mDmaBufUsageInfo, m.allocFlags).flags({}),
896 C2F(mDmaBufUsageInfo, m.heapName).any(),
897 })
898 .withSetter(Setter::setDmaBufUsage)
899 .build());
900 }
901 };
902
903 /**
904 * Retrieves the component module for a component.
905 *
906 * \param module pointer to a shared_pointer where the component module will be stored on
907 * success.
908 *
909 * \retval C2_OK the component loader has been successfully retrieved
910 * \retval C2_NO_MEMORY not enough memory to locate the component loader
911 * \retval C2_NOT_FOUND could not locate the component to be loaded
912 * \retval C2_CORRUPTED the component loader could not be identified due to some modules being
913 * corrupted (this can happen if the name does not refer to an already
914 * identified component but some components could not be loaded due to
915 * bad library)
916 * \retval C2_REFUSED permission denied to find the component loader for the named component
917 * (this can happen if the name does not refer to an already identified
918 * component but some components could not be loaded due to lack of
919 * permissions)
920 */
921 c2_status_t findComponent(C2String name, std::shared_ptr<ComponentModule> *module);
922
923 /**
924 * Loads each component module and discover its contents.
925 */
926 void visitComponents();
927
928 std::mutex mMutex; ///< mutex guarding the component lists during construction
929 bool mVisited; ///< component modules visited
930 std::map<C2String, ComponentLoader> mComponents; ///< path -> component module
931 std::map<C2String, C2String> mComponentNameToPath; ///< name -> path
932 std::vector<std::shared_ptr<const C2Component::Traits>> mComponentList;
933
934 std::shared_ptr<C2ReflectorHelper> mReflector;
935 Interface mInterface;
936
937 // For testing only
938 std::vector<std::tuple<C2String,
939 C2ComponentFactory::CreateCodec2FactoryFunc,
940 C2ComponentFactory::DestroyCodec2FactoryFunc>> mCodec2FactoryFuncs;
941 };
942
init(std::string libPath)943 c2_status_t C2PlatformComponentStore::ComponentModule::init(
944 std::string libPath) {
945 ALOGV("in %s", __func__);
946 ALOGV("loading dll");
947
948 if(!createFactory) {
949 mLibHandle = dlopen(libPath.c_str(), RTLD_NOW|RTLD_NODELETE);
950 LOG_ALWAYS_FATAL_IF(mLibHandle == nullptr,
951 "could not dlopen %s: %s", libPath.c_str(), dlerror());
952
953 createFactory =
954 (C2ComponentFactory::CreateCodec2FactoryFunc)dlsym(mLibHandle, "CreateCodec2Factory");
955 LOG_ALWAYS_FATAL_IF(createFactory == nullptr,
956 "createFactory is null in %s", libPath.c_str());
957
958 destroyFactory =
959 (C2ComponentFactory::DestroyCodec2FactoryFunc)dlsym(mLibHandle, "DestroyCodec2Factory");
960 LOG_ALWAYS_FATAL_IF(destroyFactory == nullptr,
961 "destroyFactory is null in %s", libPath.c_str());
962 }
963
964 mComponentFactory = createFactory();
965 if (mComponentFactory == nullptr) {
966 ALOGD("could not create factory in %s", libPath.c_str());
967 mInit = C2_NO_MEMORY;
968 } else {
969 mInit = C2_OK;
970 }
971
972 if (mInit != C2_OK) {
973 return mInit;
974 }
975
976 std::shared_ptr<C2ComponentInterface> intf;
977 c2_status_t res = createInterface(0, &intf);
978 if (res != C2_OK) {
979 ALOGD("failed to create interface: %d", res);
980 return mInit;
981 }
982
983 std::shared_ptr<C2Component::Traits> traits(new (std::nothrow) C2Component::Traits);
984 if (traits) {
985 if (!C2InterfaceUtils::FillTraitsFromInterface(traits.get(), intf)) {
986 ALOGD("Failed to fill traits from interface");
987 return mInit;
988 }
989
990 // TODO: get this properly from the store during emplace
991 switch (traits->domain) {
992 case C2Component::DOMAIN_AUDIO:
993 traits->rank = 8;
994 break;
995 default:
996 traits->rank = 512;
997 }
998 }
999 mTraits = traits;
1000
1001 return mInit;
1002 }
1003
~ComponentModule()1004 C2PlatformComponentStore::ComponentModule::~ComponentModule() {
1005 ALOGV("in %s", __func__);
1006 if (destroyFactory && mComponentFactory) {
1007 destroyFactory(mComponentFactory);
1008 }
1009 if (mLibHandle) {
1010 ALOGV("unloading dll");
1011 dlclose(mLibHandle);
1012 }
1013 }
1014
createInterface(c2_node_id_t id,std::shared_ptr<C2ComponentInterface> * interface,std::function<void (::C2ComponentInterface *)> deleter)1015 c2_status_t C2PlatformComponentStore::ComponentModule::createInterface(
1016 c2_node_id_t id, std::shared_ptr<C2ComponentInterface> *interface,
1017 std::function<void(::C2ComponentInterface*)> deleter) {
1018 interface->reset();
1019 if (mInit != C2_OK) {
1020 return mInit;
1021 }
1022 std::shared_ptr<ComponentModule> module = shared_from_this();
1023 c2_status_t res = mComponentFactory->createInterface(
1024 id, interface, [module, deleter](C2ComponentInterface *p) mutable {
1025 // capture module so that we ensure we still have it while deleting interface
1026 deleter(p); // delete interface first
1027 module.reset(); // remove module ref (not technically needed)
1028 });
1029 return res;
1030 }
1031
createComponent(c2_node_id_t id,std::shared_ptr<C2Component> * component,std::function<void (::C2Component *)> deleter)1032 c2_status_t C2PlatformComponentStore::ComponentModule::createComponent(
1033 c2_node_id_t id, std::shared_ptr<C2Component> *component,
1034 std::function<void(::C2Component*)> deleter) {
1035 component->reset();
1036 if (mInit != C2_OK) {
1037 return mInit;
1038 }
1039 std::shared_ptr<ComponentModule> module = shared_from_this();
1040 c2_status_t res = mComponentFactory->createComponent(
1041 id, component, [module, deleter](C2Component *p) mutable {
1042 // capture module so that we ensure we still have it while deleting component
1043 deleter(p); // delete component first
1044 module.reset(); // remove module ref (not technically needed)
1045 });
1046 return res;
1047 }
1048
getTraits()1049 std::shared_ptr<const C2Component::Traits> C2PlatformComponentStore::ComponentModule::getTraits() {
1050 std::unique_lock<std::recursive_mutex> lock(mLock);
1051 return mTraits;
1052 }
1053
C2PlatformComponentStore()1054 C2PlatformComponentStore::C2PlatformComponentStore()
1055 : mVisited(false),
1056 mReflector(std::make_shared<C2ReflectorHelper>()),
1057 mInterface(mReflector) {
1058
1059 auto emplace = [this](const char *libPath) {
1060 mComponents.emplace(libPath, libPath);
1061 };
1062
1063 // TODO: move this also into a .so so it can be updated
1064 emplace("libcodec2_soft_aacdec.so");
1065 emplace("libcodec2_soft_aacenc.so");
1066 emplace("libcodec2_soft_amrnbdec.so");
1067 emplace("libcodec2_soft_amrnbenc.so");
1068 emplace("libcodec2_soft_amrwbdec.so");
1069 emplace("libcodec2_soft_amrwbenc.so");
1070 //emplace("libcodec2_soft_av1dec_aom.so"); // deprecated for the gav1 implementation
1071 emplace("libcodec2_soft_av1dec_gav1.so");
1072 emplace("libcodec2_soft_avcdec.so");
1073 emplace("libcodec2_soft_avcenc.so");
1074 emplace("libcodec2_soft_flacdec.so");
1075 emplace("libcodec2_soft_flacenc.so");
1076 emplace("libcodec2_soft_g711alawdec.so");
1077 emplace("libcodec2_soft_g711mlawdec.so");
1078 emplace("libcodec2_soft_gsmdec.so");
1079 emplace("libcodec2_soft_h263dec.so");
1080 emplace("libcodec2_soft_h263enc.so");
1081 emplace("libcodec2_soft_hevcdec.so");
1082 emplace("libcodec2_soft_hevcenc.so");
1083 emplace("libcodec2_soft_mp3dec.so");
1084 emplace("libcodec2_soft_mpeg2dec.so");
1085 emplace("libcodec2_soft_mpeg4dec.so");
1086 emplace("libcodec2_soft_mpeg4enc.so");
1087 emplace("libcodec2_soft_opusdec.so");
1088 emplace("libcodec2_soft_opusenc.so");
1089 emplace("libcodec2_soft_rawdec.so");
1090 emplace("libcodec2_soft_vorbisdec.so");
1091 emplace("libcodec2_soft_vp8dec.so");
1092 emplace("libcodec2_soft_vp8enc.so");
1093 emplace("libcodec2_soft_vp9dec.so");
1094 emplace("libcodec2_soft_vp9enc.so");
1095
1096 }
1097
1098 // For testing only
C2PlatformComponentStore(std::vector<std::tuple<C2String,C2ComponentFactory::CreateCodec2FactoryFunc,C2ComponentFactory::DestroyCodec2FactoryFunc>> funcs)1099 C2PlatformComponentStore::C2PlatformComponentStore(
1100 std::vector<std::tuple<C2String,
1101 C2ComponentFactory::CreateCodec2FactoryFunc,
1102 C2ComponentFactory::DestroyCodec2FactoryFunc>> funcs)
1103 : mVisited(false),
1104 mReflector(std::make_shared<C2ReflectorHelper>()),
1105 mInterface(mReflector),
1106 mCodec2FactoryFuncs(funcs) {
1107
1108 for(auto const& func: mCodec2FactoryFuncs) {
1109 mComponents.emplace(std::get<0>(func), func);
1110 }
1111 }
1112
copyBuffer(std::shared_ptr<C2GraphicBuffer> src,std::shared_ptr<C2GraphicBuffer> dst)1113 c2_status_t C2PlatformComponentStore::copyBuffer(
1114 std::shared_ptr<C2GraphicBuffer> src, std::shared_ptr<C2GraphicBuffer> dst) {
1115 (void)src;
1116 (void)dst;
1117 return C2_OMITTED;
1118 }
1119
query_sm(const std::vector<C2Param * > & stackParams,const std::vector<C2Param::Index> & heapParamIndices,std::vector<std::unique_ptr<C2Param>> * const heapParams) const1120 c2_status_t C2PlatformComponentStore::query_sm(
1121 const std::vector<C2Param*> &stackParams,
1122 const std::vector<C2Param::Index> &heapParamIndices,
1123 std::vector<std::unique_ptr<C2Param>> *const heapParams) const {
1124 return mInterface.query(stackParams, heapParamIndices, C2_MAY_BLOCK, heapParams);
1125 }
1126
config_sm(const std::vector<C2Param * > & params,std::vector<std::unique_ptr<C2SettingResult>> * const failures)1127 c2_status_t C2PlatformComponentStore::config_sm(
1128 const std::vector<C2Param*> ¶ms,
1129 std::vector<std::unique_ptr<C2SettingResult>> *const failures) {
1130 return mInterface.config(params, C2_MAY_BLOCK, failures);
1131 }
1132
visitComponents()1133 void C2PlatformComponentStore::visitComponents() {
1134 std::lock_guard<std::mutex> lock(mMutex);
1135 if (mVisited) {
1136 return;
1137 }
1138 for (auto &pathAndLoader : mComponents) {
1139 const C2String &path = pathAndLoader.first;
1140 ComponentLoader &loader = pathAndLoader.second;
1141 std::shared_ptr<ComponentModule> module;
1142 if (loader.fetchModule(&module) == C2_OK) {
1143 std::shared_ptr<const C2Component::Traits> traits = module->getTraits();
1144 if (traits) {
1145 mComponentList.push_back(traits);
1146 mComponentNameToPath.emplace(traits->name, path);
1147 for (const C2String &alias : traits->aliases) {
1148 mComponentNameToPath.emplace(alias, path);
1149 }
1150 }
1151 }
1152 }
1153 mVisited = true;
1154 }
1155
listComponents()1156 std::vector<std::shared_ptr<const C2Component::Traits>> C2PlatformComponentStore::listComponents() {
1157 // This method SHALL return within 500ms.
1158 visitComponents();
1159 return mComponentList;
1160 }
1161
findComponent(C2String name,std::shared_ptr<ComponentModule> * module)1162 c2_status_t C2PlatformComponentStore::findComponent(
1163 C2String name, std::shared_ptr<ComponentModule> *module) {
1164 (*module).reset();
1165 visitComponents();
1166
1167 auto pos = mComponentNameToPath.find(name);
1168 if (pos != mComponentNameToPath.end()) {
1169 return mComponents.at(pos->second).fetchModule(module);
1170 }
1171 return C2_NOT_FOUND;
1172 }
1173
createComponent(C2String name,std::shared_ptr<C2Component> * const component)1174 c2_status_t C2PlatformComponentStore::createComponent(
1175 C2String name, std::shared_ptr<C2Component> *const component) {
1176 // This method SHALL return within 100ms.
1177 component->reset();
1178 std::shared_ptr<ComponentModule> module;
1179 c2_status_t res = findComponent(name, &module);
1180 if (res == C2_OK) {
1181 // TODO: get a unique node ID
1182 res = module->createComponent(0, component);
1183 }
1184 return res;
1185 }
1186
createInterface(C2String name,std::shared_ptr<C2ComponentInterface> * const interface)1187 c2_status_t C2PlatformComponentStore::createInterface(
1188 C2String name, std::shared_ptr<C2ComponentInterface> *const interface) {
1189 // This method SHALL return within 100ms.
1190 interface->reset();
1191 std::shared_ptr<ComponentModule> module;
1192 c2_status_t res = findComponent(name, &module);
1193 if (res == C2_OK) {
1194 // TODO: get a unique node ID
1195 res = module->createInterface(0, interface);
1196 }
1197 return res;
1198 }
1199
querySupportedParams_nb(std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const1200 c2_status_t C2PlatformComponentStore::querySupportedParams_nb(
1201 std::vector<std::shared_ptr<C2ParamDescriptor>> *const params) const {
1202 return mInterface.querySupportedParams(params);
1203 }
1204
querySupportedValues_sm(std::vector<C2FieldSupportedValuesQuery> & fields) const1205 c2_status_t C2PlatformComponentStore::querySupportedValues_sm(
1206 std::vector<C2FieldSupportedValuesQuery> &fields) const {
1207 return mInterface.querySupportedValues(fields, C2_MAY_BLOCK);
1208 }
1209
getName() const1210 C2String C2PlatformComponentStore::getName() const {
1211 return "android.componentStore.platform";
1212 }
1213
getParamReflector() const1214 std::shared_ptr<C2ParamReflector> C2PlatformComponentStore::getParamReflector() const {
1215 return mReflector;
1216 }
1217
GetCodec2PlatformComponentStore()1218 std::shared_ptr<C2ComponentStore> GetCodec2PlatformComponentStore() {
1219 static std::mutex mutex;
1220 static std::weak_ptr<C2ComponentStore> platformStore;
1221 std::lock_guard<std::mutex> lock(mutex);
1222 std::shared_ptr<C2ComponentStore> store = platformStore.lock();
1223 if (store == nullptr) {
1224 store = std::make_shared<C2PlatformComponentStore>();
1225 platformStore = store;
1226 }
1227 return store;
1228 }
1229
1230 // For testing only
GetTestComponentStore(std::vector<std::tuple<C2String,C2ComponentFactory::CreateCodec2FactoryFunc,C2ComponentFactory::DestroyCodec2FactoryFunc>> funcs)1231 std::shared_ptr<C2ComponentStore> GetTestComponentStore(
1232 std::vector<std::tuple<C2String,
1233 C2ComponentFactory::CreateCodec2FactoryFunc,
1234 C2ComponentFactory::DestroyCodec2FactoryFunc>> funcs) {
1235 return std::shared_ptr<C2ComponentStore>(new C2PlatformComponentStore(funcs));
1236 }
1237 } // namespace android
1238