• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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*> &params,
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*> &params,
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