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