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 bool blockFence =
580 (components.size() == 1 && allocatorParam.blockFenceSupport);
581 std::shared_ptr<C2BlockPool> ptr(
582 new C2IgbaBlockPool(allocator,
583 allocatorParam.igba,
584 std::move(allocatorParam.waitableFd),
585 blockFence, poolId), deleter);
586 *pool = ptr;
587 mBlockPools[poolId] = ptr;
588 mComponents[poolId].insert(
589 mComponents[poolId].end(),
590 components.begin(), components.end());
591 }
592 break;
593 default:
594 // Try to create block pool from platform store plugins.
595 std::shared_ptr<C2BlockPool> ptr;
596 res = C2PlatformStorePluginLoader::GetInstance()->createBlockPool(
597 allocatorId, poolId, &ptr, deleter);
598 if (res == C2_OK) {
599 *pool = ptr;
600 mBlockPools[poolId] = ptr;
601 mComponents[poolId].insert(
602 mComponents[poolId].end(),
603 components.begin(), components.end());
604 }
605 break;
606 }
607 return res;
608 }
609
610 public:
createBlockPool(C2PlatformAllocatorStore::id_t allocatorId,std::vector<std::shared_ptr<const C2Component>> components,std::shared_ptr<C2BlockPool> * pool)611 c2_status_t createBlockPool(
612 C2PlatformAllocatorStore::id_t allocatorId,
613 std::vector<std::shared_ptr<const C2Component>> components,
614 std::shared_ptr<C2BlockPool> *pool) {
615 C2PlatformAllocatorDesc allocator;
616 allocator.allocatorId = allocatorId;
617 return createBlockPool(allocator, components, pool);
618 }
619
createBlockPool(C2PlatformAllocatorDesc & allocator,std::vector<std::shared_ptr<const C2Component>> components,std::shared_ptr<C2BlockPool> * pool)620 c2_status_t createBlockPool(
621 C2PlatformAllocatorDesc &allocator,
622 std::vector<std::shared_ptr<const C2Component>> components,
623 std::shared_ptr<C2BlockPool> *pool) {
624 std::unique_lock lock(mMutex);
625 return _createBlockPool(allocator, components, mBlockPoolSeqId++,
626 mBqPoolDeferDeallocAfterStop, pool);
627 }
628
629
getBlockPool(C2BlockPool::local_id_t blockPoolId,std::shared_ptr<const C2Component> component,std::shared_ptr<C2BlockPool> * pool)630 c2_status_t getBlockPool(
631 C2BlockPool::local_id_t blockPoolId,
632 std::shared_ptr<const C2Component> component,
633 std::shared_ptr<C2BlockPool> *pool) {
634 std::unique_lock lock(mMutex);
635 // TODO: use one iterator for multiple blockpool type scalability.
636 std::shared_ptr<C2BlockPool> ptr;
637 auto it = mBlockPools.find(blockPoolId);
638 if (it != mBlockPools.end()) {
639 ptr = it->second.lock();
640 if (!ptr) {
641 mBlockPools.erase(it);
642 mComponents.erase(blockPoolId);
643 } else {
644 auto found = std::find_if(
645 mComponents[blockPoolId].begin(),
646 mComponents[blockPoolId].end(),
647 [component](const std::weak_ptr<const C2Component> &ptr) {
648 return component == ptr.lock();
649 });
650 if (found != mComponents[blockPoolId].end()) {
651 *pool = ptr;
652 return C2_OK;
653 }
654 }
655 }
656 // TODO: remove this. this is temporary
657 if (blockPoolId == C2BlockPool::PLATFORM_START) {
658 C2PlatformAllocatorDesc allocator;
659 allocator.allocatorId = C2PlatformAllocatorStore::BUFFERQUEUE;
660 return _createBlockPool(
661 allocator, {component}, blockPoolId, mBqPoolDeferDeallocAfterStop, pool);
662 }
663 return C2_NOT_FOUND;
664 }
665
666 private:
667 // Deleter needs to hold this mutex, and there is a small chance that deleter
668 // is invoked while the mutex is held.
669 std::recursive_mutex mMutex;
670 C2BlockPool::local_id_t mBlockPoolSeqId;
671
672 std::map<C2BlockPool::local_id_t, std::weak_ptr<C2BlockPool>> mBlockPools;
673 std::map<C2BlockPool::local_id_t, std::vector<std::weak_ptr<const C2Component>>> mComponents;
674
675 bool mBqPoolDeferDeallocAfterStop;
676 };
677
678 static std::unique_ptr<_C2BlockPoolCache> sBlockPoolCache =
679 std::make_unique<_C2BlockPoolCache>();
680
681 } // anynymous namespace
682
GetCodec2BlockPool(C2BlockPool::local_id_t id,std::shared_ptr<const C2Component> component,std::shared_ptr<C2BlockPool> * pool)683 c2_status_t GetCodec2BlockPool(
684 C2BlockPool::local_id_t id, std::shared_ptr<const C2Component> component,
685 std::shared_ptr<C2BlockPool> *pool) {
686 pool->reset();
687 std::shared_ptr<C2AllocatorStore> allocatorStore = GetCodec2PlatformAllocatorStore();
688 std::shared_ptr<C2Allocator> allocator;
689 c2_status_t res = C2_NOT_FOUND;
690
691 if (id >= C2BlockPool::PLATFORM_START) {
692 return sBlockPoolCache->getBlockPool(id, component, pool);
693 }
694
695 switch (id) {
696 case C2BlockPool::BASIC_LINEAR:
697 res = allocatorStore->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &allocator);
698 if (res == C2_OK) {
699 *pool = std::make_shared<C2BasicLinearBlockPool>(allocator);
700 }
701 break;
702 case C2BlockPool::BASIC_GRAPHIC:
703 res = allocatorStore->fetchAllocator(C2AllocatorStore::DEFAULT_GRAPHIC, &allocator);
704 if (res == C2_OK) {
705 *pool = std::make_shared<C2BasicGraphicBlockPool>(allocator);
706 }
707 break;
708 default:
709 break;
710 }
711 return res;
712 }
713
CreateCodec2BlockPool(C2PlatformAllocatorStore::id_t allocatorId,const std::vector<std::shared_ptr<const C2Component>> & components,std::shared_ptr<C2BlockPool> * pool)714 c2_status_t CreateCodec2BlockPool(
715 C2PlatformAllocatorStore::id_t allocatorId,
716 const std::vector<std::shared_ptr<const C2Component>> &components,
717 std::shared_ptr<C2BlockPool> *pool) {
718 pool->reset();
719
720 C2PlatformAllocatorDesc allocator;
721 allocator.allocatorId = allocatorId;
722 return sBlockPoolCache->createBlockPool(allocator, components, pool);
723 }
724
CreateCodec2BlockPool(C2PlatformAllocatorStore::id_t allocatorId,std::shared_ptr<const C2Component> component,std::shared_ptr<C2BlockPool> * pool)725 c2_status_t CreateCodec2BlockPool(
726 C2PlatformAllocatorStore::id_t allocatorId,
727 std::shared_ptr<const C2Component> component,
728 std::shared_ptr<C2BlockPool> *pool) {
729 pool->reset();
730
731 C2PlatformAllocatorDesc allocator;
732 allocator.allocatorId = allocatorId;
733 return sBlockPoolCache->createBlockPool(allocator, {component}, pool);
734 }
735
CreateCodec2BlockPool(C2PlatformAllocatorDesc & allocator,const std::vector<std::shared_ptr<const C2Component>> & components,std::shared_ptr<C2BlockPool> * pool)736 c2_status_t CreateCodec2BlockPool(
737 C2PlatformAllocatorDesc &allocator,
738 const std::vector<std::shared_ptr<const C2Component>> &components,
739 std::shared_ptr<C2BlockPool> *pool) {
740 pool->reset();
741
742 return sBlockPoolCache->createBlockPool(allocator, components, pool);
743 }
744
CreateCodec2BlockPool(C2PlatformAllocatorDesc & allocator,std::shared_ptr<const C2Component> component,std::shared_ptr<C2BlockPool> * pool)745 c2_status_t CreateCodec2BlockPool(
746 C2PlatformAllocatorDesc &allocator,
747 std::shared_ptr<const C2Component> component,
748 std::shared_ptr<C2BlockPool> *pool) {
749 pool->reset();
750
751 return sBlockPoolCache->createBlockPool(allocator, {component}, pool);
752 }
753
754 class C2PlatformComponentStore : public C2ComponentStore {
755 public:
756 virtual std::vector<std::shared_ptr<const C2Component::Traits>> listComponents() override;
757 virtual std::shared_ptr<C2ParamReflector> getParamReflector() const override;
758 virtual C2String getName() const override;
759 virtual c2_status_t querySupportedValues_sm(
760 std::vector<C2FieldSupportedValuesQuery> &fields) const override;
761 virtual c2_status_t querySupportedParams_nb(
762 std::vector<std::shared_ptr<C2ParamDescriptor>> *const params) const override;
763 virtual c2_status_t query_sm(
764 const std::vector<C2Param*> &stackParams,
765 const std::vector<C2Param::Index> &heapParamIndices,
766 std::vector<std::unique_ptr<C2Param>> *const heapParams) const override;
767 virtual c2_status_t createInterface(
768 C2String name, std::shared_ptr<C2ComponentInterface> *const interface) override;
769 virtual c2_status_t createComponent(
770 C2String name, std::shared_ptr<C2Component> *const component) override;
771 virtual c2_status_t copyBuffer(
772 std::shared_ptr<C2GraphicBuffer> src, std::shared_ptr<C2GraphicBuffer> dst) override;
773 virtual c2_status_t config_sm(
774 const std::vector<C2Param*> ¶ms,
775 std::vector<std::unique_ptr<C2SettingResult>> *const failures) override;
776 C2PlatformComponentStore();
777
778 // For testing only
779 C2PlatformComponentStore(
780 std::vector<std::tuple<C2String,
781 C2ComponentFactory::CreateCodec2FactoryFunc,
782 C2ComponentFactory::DestroyCodec2FactoryFunc>>);
783
784 virtual ~C2PlatformComponentStore() override = default;
785
786 private:
787
788 /**
789 * An object encapsulating a loaded component module.
790 *
791 * \todo provide a way to add traits to known components here to avoid loading the .so-s
792 * for listComponents
793 */
794 struct ComponentModule : public C2ComponentFactory,
795 public std::enable_shared_from_this<ComponentModule> {
796 virtual c2_status_t createComponent(
797 c2_node_id_t id, std::shared_ptr<C2Component> *component,
798 ComponentDeleter deleter = std::default_delete<C2Component>()) override;
799 virtual c2_status_t createInterface(
800 c2_node_id_t id, std::shared_ptr<C2ComponentInterface> *interface,
801 InterfaceDeleter deleter = std::default_delete<C2ComponentInterface>()) override;
802
803 /**
804 * \returns the traits of the component in this module.
805 */
806 std::shared_ptr<const C2Component::Traits> getTraits();
807
808 /**
809 * Creates an uninitialized component module.
810 *
811 * \param name[in] component name.
812 *
813 * \note Only used by ComponentLoader.
814 */
ComponentModuleandroid::C2PlatformComponentStore::ComponentModule815 ComponentModule()
816 : mInit(C2_NO_INIT),
817 mLibHandle(nullptr),
818 createFactory(nullptr),
819 destroyFactory(nullptr),
820 mComponentFactory(nullptr) {
821 }
822
823 /**
824 * Creates an uninitialized component module.
825 * NOTE: For testing only
826 *
827 * \param name[in] component name.
828 *
829 * \note Only used by ComponentLoader.
830 */
ComponentModuleandroid::C2PlatformComponentStore::ComponentModule831 ComponentModule(
832 C2ComponentFactory::CreateCodec2FactoryFunc createFactory,
833 C2ComponentFactory::DestroyCodec2FactoryFunc destroyFactory)
834 : mInit(C2_NO_INIT),
835 mLibHandle(nullptr),
836 createFactory(createFactory),
837 destroyFactory(destroyFactory),
838 mComponentFactory(nullptr) {
839 }
840
841 /**
842 * Initializes a component module with a given library path. Must be called exactly once.
843 *
844 * \note Only used by ComponentLoader.
845 *
846 * \param libPath[in] library path
847 *
848 * \retval C2_OK the component module has been successfully loaded
849 * \retval C2_NO_MEMORY not enough memory to loading the component module
850 * \retval C2_NOT_FOUND could not locate the component module
851 * \retval C2_CORRUPTED the component module could not be loaded (unexpected)
852 * \retval C2_REFUSED permission denied to load the component module (unexpected)
853 * \retval C2_TIMED_OUT could not load the module within the time limit (unexpected)
854 */
855 c2_status_t init(std::string libPath);
856
857 virtual ~ComponentModule() override;
858
859 protected:
860 std::recursive_mutex mLock; ///< lock protecting mTraits
861 std::shared_ptr<C2Component::Traits> mTraits; ///< cached component traits
862
863 c2_status_t mInit; ///< initialization result
864
865 void *mLibHandle; ///< loaded library handle
866 C2ComponentFactory::CreateCodec2FactoryFunc createFactory; ///< loaded create function
867 C2ComponentFactory::DestroyCodec2FactoryFunc destroyFactory; ///< loaded destroy function
868 C2ComponentFactory *mComponentFactory; ///< loaded/created component factory
869 };
870
871 /**
872 * An object encapsulating a loadable component module.
873 *
874 * \todo make this also work for enumerations
875 */
876 struct ComponentLoader {
877 /**
878 * Load the component module.
879 *
880 * This method simply returns the component module if it is already currently loaded, or
881 * attempts to load it if it is not.
882 *
883 * \param module[out] pointer to the shared pointer where the loaded module shall be stored.
884 * This will be nullptr on error.
885 *
886 * \retval C2_OK the component module has been successfully loaded
887 * \retval C2_NO_MEMORY not enough memory to loading the component module
888 * \retval C2_NOT_FOUND could not locate the component module
889 * \retval C2_CORRUPTED the component module could not be loaded
890 * \retval C2_REFUSED permission denied to load the component module
891 */
fetchModuleandroid::C2PlatformComponentStore::ComponentLoader892 c2_status_t fetchModule(std::shared_ptr<ComponentModule> *module) {
893 c2_status_t res = C2_OK;
894 std::lock_guard<std::mutex> lock(mMutex);
895 std::shared_ptr<ComponentModule> localModule = mModule.lock();
896 if (localModule == nullptr) {
897 if(mCreateFactory) {
898 // For testing only
899 localModule = std::make_shared<ComponentModule>(mCreateFactory,
900 mDestroyFactory);
901 } else {
902 localModule = std::make_shared<ComponentModule>();
903 }
904 res = localModule->init(mLibPath);
905 if (res == C2_OK) {
906 mModule = localModule;
907 }
908 }
909 *module = localModule;
910 return res;
911 }
912
913 /**
914 * Creates a component loader for a specific library path (or name).
915 */
ComponentLoaderandroid::C2PlatformComponentStore::ComponentLoader916 ComponentLoader(std::string libPath)
917 : mLibPath(libPath) {}
918
919 // For testing only
ComponentLoaderandroid::C2PlatformComponentStore::ComponentLoader920 ComponentLoader(std::tuple<C2String,
921 C2ComponentFactory::CreateCodec2FactoryFunc,
922 C2ComponentFactory::DestroyCodec2FactoryFunc> func)
923 : mLibPath(std::get<0>(func)),
924 mCreateFactory(std::get<1>(func)),
925 mDestroyFactory(std::get<2>(func)) {}
926
927 private:
928 std::mutex mMutex; ///< mutex guarding the module
929 std::weak_ptr<ComponentModule> mModule; ///< weak reference to the loaded module
930 std::string mLibPath; ///< library path
931
932 // For testing only
933 C2ComponentFactory::CreateCodec2FactoryFunc mCreateFactory = nullptr;
934 C2ComponentFactory::DestroyCodec2FactoryFunc mDestroyFactory = nullptr;
935 };
936
937 struct Interface : public C2InterfaceHelper {
938 std::shared_ptr<C2StoreIonUsageInfo> mIonUsageInfo;
939 std::shared_ptr<C2StoreDmaBufUsageInfo> mDmaBufUsageInfo;
940
Interfaceandroid::C2PlatformComponentStore::Interface941 Interface(std::shared_ptr<C2ReflectorHelper> reflector)
942 : C2InterfaceHelper(reflector) {
943 setDerivedInstance(this);
944
945 struct Setter {
946 static C2R setIonUsage(bool /* mayBlock */, C2P<C2StoreIonUsageInfo> &me) {
947 #ifdef __ANDROID_APEX__
948 static int32_t defaultHeapMask = [] {
949 int32_t heapmask = base::GetIntProperty(
950 "ro.com.android.media.swcodec.ion.heapmask", int32_t(0xFFFFFFFF));
951 ALOGD("Default ION heapmask = %d", heapmask);
952 return heapmask;
953 }();
954 static int32_t defaultFlags = [] {
955 int32_t flags = base::GetIntProperty(
956 "ro.com.android.media.swcodec.ion.flags", 0);
957 ALOGD("Default ION flags = %d", flags);
958 return flags;
959 }();
960 static uint32_t defaultAlign = [] {
961 uint32_t align = base::GetUintProperty(
962 "ro.com.android.media.swcodec.ion.align", 0u);
963 ALOGD("Default ION align = %d", align);
964 return align;
965 }();
966 me.set().heapMask = defaultHeapMask;
967 me.set().allocFlags = defaultFlags;
968 me.set().minAlignment = defaultAlign;
969 #else
970 me.set().heapMask = ~0;
971 me.set().allocFlags = 0;
972 me.set().minAlignment = 0;
973 #endif
974 return C2R::Ok();
975 };
976
977 static C2R setDmaBufUsage(bool /* mayBlock */, C2P<C2StoreDmaBufUsageInfo> &me) {
978 long long usage = (long long)me.get().m.usage;
979 if (C2DmaBufAllocator::system_uncached_supported() &&
980 !(usage & (C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE))) {
981 strncpy(me.set().m.heapName, "system-uncached", me.v.flexCount());
982 } else {
983 strncpy(me.set().m.heapName, "system", me.v.flexCount());
984 }
985 me.set().m.allocFlags = 0;
986 return C2R::Ok();
987 };
988 };
989
990 addParameter(
991 DefineParam(mIonUsageInfo, "ion-usage")
992 .withDefault(new C2StoreIonUsageInfo())
993 .withFields({
994 C2F(mIonUsageInfo, usage).flags({C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE}),
995 C2F(mIonUsageInfo, capacity).inRange(0, UINT32_MAX, 1024),
996 C2F(mIonUsageInfo, heapMask).any(),
997 C2F(mIonUsageInfo, allocFlags).flags({}),
998 C2F(mIonUsageInfo, minAlignment).equalTo(0)
999 })
1000 .withSetter(Setter::setIonUsage)
1001 .build());
1002
1003 addParameter(
1004 DefineParam(mDmaBufUsageInfo, "dmabuf-usage")
1005 .withDefault(C2StoreDmaBufUsageInfo::AllocShared(0))
1006 .withFields({
1007 C2F(mDmaBufUsageInfo, m.usage).flags({C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE}),
1008 C2F(mDmaBufUsageInfo, m.capacity).inRange(0, UINT32_MAX, 1024),
1009 C2F(mDmaBufUsageInfo, m.allocFlags).flags({}),
1010 C2F(mDmaBufUsageInfo, m.heapName).any(),
1011 })
1012 .withSetter(Setter::setDmaBufUsage)
1013 .build());
1014 }
1015 };
1016
1017 /**
1018 * Retrieves the component module for a component.
1019 *
1020 * \param module pointer to a shared_pointer where the component module will be stored on
1021 * success.
1022 *
1023 * \retval C2_OK the component loader has been successfully retrieved
1024 * \retval C2_NO_MEMORY not enough memory to locate the component loader
1025 * \retval C2_NOT_FOUND could not locate the component to be loaded
1026 * \retval C2_CORRUPTED the component loader could not be identified due to some modules being
1027 * corrupted (this can happen if the name does not refer to an already
1028 * identified component but some components could not be loaded due to
1029 * bad library)
1030 * \retval C2_REFUSED permission denied to find the component loader for the named component
1031 * (this can happen if the name does not refer to an already identified
1032 * component but some components could not be loaded due to lack of
1033 * permissions)
1034 */
1035 c2_status_t findComponent(C2String name, std::shared_ptr<ComponentModule> *module);
1036
1037 /**
1038 * Loads each component module and discover its contents.
1039 */
1040 void visitComponents();
1041
1042 std::mutex mMutex; ///< mutex guarding the component lists during construction
1043 bool mVisited; ///< component modules visited
1044 std::map<C2String, ComponentLoader> mComponents; ///< path -> component module
1045 std::map<C2String, C2String> mComponentNameToPath; ///< name -> path
1046 std::vector<std::shared_ptr<const C2Component::Traits>> mComponentList;
1047
1048 std::shared_ptr<C2ReflectorHelper> mReflector;
1049 Interface mInterface;
1050
1051 // For testing only
1052 std::vector<std::tuple<C2String,
1053 C2ComponentFactory::CreateCodec2FactoryFunc,
1054 C2ComponentFactory::DestroyCodec2FactoryFunc>> mCodec2FactoryFuncs;
1055 };
1056
init(std::string libPath)1057 c2_status_t C2PlatformComponentStore::ComponentModule::init(
1058 std::string libPath) {
1059 ALOGV("in %s", __func__);
1060 ALOGV("loading dll");
1061
1062 if(!createFactory) {
1063 mLibHandle = dlopen(libPath.c_str(), RTLD_NOW|RTLD_NODELETE);
1064 LOG_ALWAYS_FATAL_IF(mLibHandle == nullptr,
1065 "could not dlopen %s: %s", libPath.c_str(), dlerror());
1066
1067 createFactory =
1068 (C2ComponentFactory::CreateCodec2FactoryFunc)dlsym(mLibHandle, "CreateCodec2Factory");
1069 LOG_ALWAYS_FATAL_IF(createFactory == nullptr,
1070 "createFactory is null in %s", libPath.c_str());
1071
1072 destroyFactory =
1073 (C2ComponentFactory::DestroyCodec2FactoryFunc)dlsym(mLibHandle, "DestroyCodec2Factory");
1074 LOG_ALWAYS_FATAL_IF(destroyFactory == nullptr,
1075 "destroyFactory is null in %s", libPath.c_str());
1076 }
1077
1078 mComponentFactory = createFactory();
1079 if (mComponentFactory == nullptr) {
1080 ALOGD("could not create factory in %s", libPath.c_str());
1081 mInit = C2_NO_MEMORY;
1082 } else {
1083 mInit = C2_OK;
1084 }
1085
1086 if (mInit != C2_OK) {
1087 return mInit;
1088 }
1089
1090 std::shared_ptr<C2ComponentInterface> intf;
1091 c2_status_t res = createInterface(0, &intf);
1092 if (res != C2_OK) {
1093 ALOGD("failed to create interface: %d", res);
1094 return mInit;
1095 }
1096
1097 std::shared_ptr<C2Component::Traits> traits(new (std::nothrow) C2Component::Traits);
1098 if (traits) {
1099 if (!C2InterfaceUtils::FillTraitsFromInterface(traits.get(), intf)) {
1100 ALOGD("Failed to fill traits from interface");
1101 return mInit;
1102 }
1103
1104 // TODO: get this properly from the store during emplace
1105 switch (traits->domain) {
1106 case C2Component::DOMAIN_AUDIO:
1107 traits->rank = 8;
1108 break;
1109 default:
1110 traits->rank = 512;
1111 }
1112 }
1113 mTraits = traits;
1114
1115 return mInit;
1116 }
1117
~ComponentModule()1118 C2PlatformComponentStore::ComponentModule::~ComponentModule() {
1119 ALOGV("in %s", __func__);
1120 if (destroyFactory && mComponentFactory) {
1121 destroyFactory(mComponentFactory);
1122 }
1123 if (mLibHandle) {
1124 ALOGV("unloading dll");
1125 dlclose(mLibHandle);
1126 }
1127 }
1128
createInterface(c2_node_id_t id,std::shared_ptr<C2ComponentInterface> * interface,std::function<void (::C2ComponentInterface *)> deleter)1129 c2_status_t C2PlatformComponentStore::ComponentModule::createInterface(
1130 c2_node_id_t id, std::shared_ptr<C2ComponentInterface> *interface,
1131 std::function<void(::C2ComponentInterface*)> deleter) {
1132 interface->reset();
1133 if (mInit != C2_OK) {
1134 return mInit;
1135 }
1136 std::shared_ptr<ComponentModule> module = shared_from_this();
1137 c2_status_t res = mComponentFactory->createInterface(
1138 id, interface, [module, deleter](C2ComponentInterface *p) mutable {
1139 // capture module so that we ensure we still have it while deleting interface
1140 deleter(p); // delete interface first
1141 module.reset(); // remove module ref (not technically needed)
1142 });
1143 return res;
1144 }
1145
createComponent(c2_node_id_t id,std::shared_ptr<C2Component> * component,std::function<void (::C2Component *)> deleter)1146 c2_status_t C2PlatformComponentStore::ComponentModule::createComponent(
1147 c2_node_id_t id, std::shared_ptr<C2Component> *component,
1148 std::function<void(::C2Component*)> deleter) {
1149 component->reset();
1150 if (mInit != C2_OK) {
1151 return mInit;
1152 }
1153 std::shared_ptr<ComponentModule> module = shared_from_this();
1154 c2_status_t res = mComponentFactory->createComponent(
1155 id, component, [module, deleter](C2Component *p) mutable {
1156 // capture module so that we ensure we still have it while deleting component
1157 deleter(p); // delete component first
1158 module.reset(); // remove module ref (not technically needed)
1159 });
1160 return res;
1161 }
1162
getTraits()1163 std::shared_ptr<const C2Component::Traits> C2PlatformComponentStore::ComponentModule::getTraits() {
1164 std::unique_lock<std::recursive_mutex> lock(mLock);
1165 return mTraits;
1166 }
1167
C2PlatformComponentStore()1168 C2PlatformComponentStore::C2PlatformComponentStore()
1169 : mVisited(false),
1170 mReflector(std::make_shared<C2ReflectorHelper>()),
1171 mInterface(mReflector) {
1172
1173 auto emplace = [this](const char *libPath) {
1174 mComponents.emplace(libPath, libPath);
1175 };
1176
1177 // TODO: move this also into a .so so it can be updated
1178 emplace("libcodec2_soft_aacdec.so");
1179 emplace("libcodec2_soft_aacenc.so");
1180 emplace("libcodec2_soft_amrnbdec.so");
1181 emplace("libcodec2_soft_amrnbenc.so");
1182 emplace("libcodec2_soft_amrwbdec.so");
1183 emplace("libcodec2_soft_amrwbenc.so");
1184 //emplace("libcodec2_soft_av1dec_aom.so"); // deprecated for the gav1 implementation
1185 emplace("libcodec2_soft_av1dec_gav1.so");
1186 emplace("libcodec2_soft_av1dec_dav1d.so");
1187 emplace("libcodec2_soft_av1enc.so");
1188 emplace("libcodec2_soft_avcdec.so");
1189 emplace("libcodec2_soft_avcenc.so");
1190 emplace("libcodec2_soft_flacdec.so");
1191 emplace("libcodec2_soft_flacenc.so");
1192 emplace("libcodec2_soft_g711alawdec.so");
1193 emplace("libcodec2_soft_g711mlawdec.so");
1194 emplace("libcodec2_soft_gsmdec.so");
1195 emplace("libcodec2_soft_h263dec.so");
1196 emplace("libcodec2_soft_h263enc.so");
1197 emplace("libcodec2_soft_hevcdec.so");
1198 emplace("libcodec2_soft_hevcenc.so");
1199 emplace("libcodec2_soft_mp3dec.so");
1200 emplace("libcodec2_soft_mpeg2dec.so");
1201 emplace("libcodec2_soft_mpeg4dec.so");
1202 emplace("libcodec2_soft_mpeg4enc.so");
1203 emplace("libcodec2_soft_opusdec.so");
1204 emplace("libcodec2_soft_opusenc.so");
1205 emplace("libcodec2_soft_rawdec.so");
1206 emplace("libcodec2_soft_vorbisdec.so");
1207 emplace("libcodec2_soft_vp8dec.so");
1208 emplace("libcodec2_soft_vp8enc.so");
1209 emplace("libcodec2_soft_vp9dec.so");
1210 emplace("libcodec2_soft_vp9enc.so");
1211 emplace("libcodec2_soft_apvenc.so");
1212 emplace("libcodec2_soft_apvdec.so");
1213 }
1214
1215 // For testing only
C2PlatformComponentStore(std::vector<std::tuple<C2String,C2ComponentFactory::CreateCodec2FactoryFunc,C2ComponentFactory::DestroyCodec2FactoryFunc>> funcs)1216 C2PlatformComponentStore::C2PlatformComponentStore(
1217 std::vector<std::tuple<C2String,
1218 C2ComponentFactory::CreateCodec2FactoryFunc,
1219 C2ComponentFactory::DestroyCodec2FactoryFunc>> funcs)
1220 : mVisited(false),
1221 mReflector(std::make_shared<C2ReflectorHelper>()),
1222 mInterface(mReflector),
1223 mCodec2FactoryFuncs(funcs) {
1224
1225 for(auto const& func: mCodec2FactoryFuncs) {
1226 mComponents.emplace(std::get<0>(func), func);
1227 }
1228 }
1229
copyBuffer(std::shared_ptr<C2GraphicBuffer> src,std::shared_ptr<C2GraphicBuffer> dst)1230 c2_status_t C2PlatformComponentStore::copyBuffer(
1231 std::shared_ptr<C2GraphicBuffer> src, std::shared_ptr<C2GraphicBuffer> dst) {
1232 (void)src;
1233 (void)dst;
1234 return C2_OMITTED;
1235 }
1236
query_sm(const std::vector<C2Param * > & stackParams,const std::vector<C2Param::Index> & heapParamIndices,std::vector<std::unique_ptr<C2Param>> * const heapParams) const1237 c2_status_t C2PlatformComponentStore::query_sm(
1238 const std::vector<C2Param*> &stackParams,
1239 const std::vector<C2Param::Index> &heapParamIndices,
1240 std::vector<std::unique_ptr<C2Param>> *const heapParams) const {
1241 return mInterface.query(stackParams, heapParamIndices, C2_MAY_BLOCK, heapParams);
1242 }
1243
config_sm(const std::vector<C2Param * > & params,std::vector<std::unique_ptr<C2SettingResult>> * const failures)1244 c2_status_t C2PlatformComponentStore::config_sm(
1245 const std::vector<C2Param*> ¶ms,
1246 std::vector<std::unique_ptr<C2SettingResult>> *const failures) {
1247 return mInterface.config(params, C2_MAY_BLOCK, failures);
1248 }
1249
visitComponents()1250 void C2PlatformComponentStore::visitComponents() {
1251 std::lock_guard<std::mutex> lock(mMutex);
1252 if (mVisited) {
1253 return;
1254 }
1255 for (auto &pathAndLoader : mComponents) {
1256 const C2String &path = pathAndLoader.first;
1257 ComponentLoader &loader = pathAndLoader.second;
1258 std::shared_ptr<ComponentModule> module;
1259 if (loader.fetchModule(&module) == C2_OK) {
1260 std::shared_ptr<const C2Component::Traits> traits = module->getTraits();
1261 if (traits) {
1262 mComponentList.push_back(traits);
1263 mComponentNameToPath.emplace(traits->name, path);
1264 for (const C2String &alias : traits->aliases) {
1265 mComponentNameToPath.emplace(alias, path);
1266 }
1267 }
1268 }
1269 }
1270 mVisited = true;
1271 }
1272
listComponents()1273 std::vector<std::shared_ptr<const C2Component::Traits>> C2PlatformComponentStore::listComponents() {
1274 // This method SHALL return within 500ms.
1275 visitComponents();
1276 return mComponentList;
1277 }
1278
findComponent(C2String name,std::shared_ptr<ComponentModule> * module)1279 c2_status_t C2PlatformComponentStore::findComponent(
1280 C2String name, std::shared_ptr<ComponentModule> *module) {
1281 (*module).reset();
1282 visitComponents();
1283
1284 auto pos = mComponentNameToPath.find(name);
1285 if (pos != mComponentNameToPath.end()) {
1286 return mComponents.at(pos->second).fetchModule(module);
1287 }
1288 return C2_NOT_FOUND;
1289 }
1290
createComponent(C2String name,std::shared_ptr<C2Component> * const component)1291 c2_status_t C2PlatformComponentStore::createComponent(
1292 C2String name, std::shared_ptr<C2Component> *const component) {
1293 // This method SHALL return within 100ms.
1294 component->reset();
1295 std::shared_ptr<ComponentModule> module;
1296 c2_status_t res = findComponent(name, &module);
1297 if (res == C2_OK) {
1298 // TODO: get a unique node ID
1299 res = module->createComponent(0, component);
1300 }
1301 return res;
1302 }
1303
createInterface(C2String name,std::shared_ptr<C2ComponentInterface> * const interface)1304 c2_status_t C2PlatformComponentStore::createInterface(
1305 C2String name, std::shared_ptr<C2ComponentInterface> *const interface) {
1306 // This method SHALL return within 100ms.
1307 interface->reset();
1308 std::shared_ptr<ComponentModule> module;
1309 c2_status_t res = findComponent(name, &module);
1310 if (res == C2_OK) {
1311 // TODO: get a unique node ID
1312 res = module->createInterface(0, interface);
1313 }
1314 return res;
1315 }
1316
querySupportedParams_nb(std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const1317 c2_status_t C2PlatformComponentStore::querySupportedParams_nb(
1318 std::vector<std::shared_ptr<C2ParamDescriptor>> *const params) const {
1319 return mInterface.querySupportedParams(params);
1320 }
1321
querySupportedValues_sm(std::vector<C2FieldSupportedValuesQuery> & fields) const1322 c2_status_t C2PlatformComponentStore::querySupportedValues_sm(
1323 std::vector<C2FieldSupportedValuesQuery> &fields) const {
1324 return mInterface.querySupportedValues(fields, C2_MAY_BLOCK);
1325 }
1326
getName() const1327 C2String C2PlatformComponentStore::getName() const {
1328 return "android.componentStore.platform";
1329 }
1330
getParamReflector() const1331 std::shared_ptr<C2ParamReflector> C2PlatformComponentStore::getParamReflector() const {
1332 return mReflector;
1333 }
1334
GetCodec2PlatformComponentStore()1335 std::shared_ptr<C2ComponentStore> GetCodec2PlatformComponentStore() {
1336 static std::mutex mutex;
1337 static std::weak_ptr<C2ComponentStore> platformStore;
1338 std::lock_guard<std::mutex> lock(mutex);
1339 std::shared_ptr<C2ComponentStore> store = platformStore.lock();
1340 if (store == nullptr) {
1341 store = std::make_shared<C2PlatformComponentStore>();
1342 platformStore = store;
1343 }
1344 return store;
1345 }
1346
1347 // For testing only
GetTestComponentStore(std::vector<std::tuple<C2String,C2ComponentFactory::CreateCodec2FactoryFunc,C2ComponentFactory::DestroyCodec2FactoryFunc>> funcs)1348 std::shared_ptr<C2ComponentStore> GetTestComponentStore(
1349 std::vector<std::tuple<C2String,
1350 C2ComponentFactory::CreateCodec2FactoryFunc,
1351 C2ComponentFactory::DestroyCodec2FactoryFunc>> funcs) {
1352 return std::shared_ptr<C2ComponentStore>(new C2PlatformComponentStore(funcs));
1353 }
1354 } // namespace android
1355