blob: dfdd84d48417a0ff05124bf5209c069768b7af9a [file] [log] [blame]
Pawin Vongmasa36653902018-11-15 00:10:25 -08001/*
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
Pin-chih Linaa18ea52019-11-19 18:48:50 +080021#include <C2AllocatorBlob.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080022#include <C2AllocatorGralloc.h>
23#include <C2AllocatorIon.h>
John Stultza7002cb2020-09-04 19:02:30 +000024#include <C2DmaBufAllocator.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080025#include <C2BufferPriv.h>
26#include <C2BqBufferPriv.h>
27#include <C2Component.h>
28#include <C2Config.h>
29#include <C2PlatformStorePluginLoader.h>
30#include <C2PlatformSupport.h>
Pin-chih Linaa18ea52019-11-19 18:48:50 +080031#include <cutils/properties.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080032#include <util/C2InterfaceHelper.h>
33
34#include <dlfcn.h>
35#include <unistd.h> // getpagesize
36
37#include <map>
38#include <memory>
39#include <mutex>
40
Wonsik Kimba3db192019-11-22 11:00:48 -080041#ifdef __ANDROID_APEX__
42#include <android-base/properties.h>
43#endif
44
Pawin Vongmasa36653902018-11-15 00:10:25 -080045namespace android {
46
47/**
48 * Returns the preferred component store in this process to access its interface.
49 */
50std::shared_ptr<C2ComponentStore> GetPreferredCodec2ComponentStore();
51
52/**
53 * The platform allocator store provides basic allocator-types for the framework based on ion and
54 * gralloc. Allocators are not meant to be updatable.
55 *
56 * \todo Provide allocator based on ashmem
57 * \todo Move ion allocation into its HIDL or provide some mapping from memory usage to ion flags
58 * \todo Make this allocator store extendable
59 */
60class C2PlatformAllocatorStoreImpl : public C2PlatformAllocatorStore {
61public:
62 C2PlatformAllocatorStoreImpl();
63
64 virtual c2_status_t fetchAllocator(
65 id_t id, std::shared_ptr<C2Allocator> *const allocator) override;
66
67 virtual std::vector<std::shared_ptr<const C2Allocator::Traits>> listAllocators_nb()
68 const override {
69 return std::vector<std::shared_ptr<const C2Allocator::Traits>>(); /// \todo
70 }
71
72 virtual C2String getName() const override {
73 return "android.allocator-store";
74 }
75
76 void setComponentStore(std::shared_ptr<C2ComponentStore> store);
77
78 ~C2PlatformAllocatorStoreImpl() override = default;
79
80private:
Pin-chih Linaa18ea52019-11-19 18:48:50 +080081 /// returns a shared-singleton blob allocator (gralloc-backed)
82 std::shared_ptr<C2Allocator> fetchBlobAllocator();
83
Pawin Vongmasa36653902018-11-15 00:10:25 -080084 /// returns a shared-singleton ion allocator
85 std::shared_ptr<C2Allocator> fetchIonAllocator();
John Stultza7002cb2020-09-04 19:02:30 +000086 std::shared_ptr<C2Allocator> fetchDmaBufAllocator();
Pawin Vongmasa36653902018-11-15 00:10:25 -080087
88 /// returns a shared-singleton gralloc allocator
89 std::shared_ptr<C2Allocator> fetchGrallocAllocator();
90
91 /// returns a shared-singleton bufferqueue supporting gralloc allocator
92 std::shared_ptr<C2Allocator> fetchBufferQueueAllocator();
93
94 /// component store to use
95 std::mutex _mComponentStoreSetLock; // protects the entire updating _mComponentStore and its
96 // dependencies
97 std::mutex _mComponentStoreReadLock; // must protect only read/write of _mComponentStore
98 std::shared_ptr<C2ComponentStore> _mComponentStore;
99};
100
101C2PlatformAllocatorStoreImpl::C2PlatformAllocatorStoreImpl() {
102}
103
John Stultza7002cb2020-09-04 19:02:30 +0000104static bool using_ion(void) {
John Stultz3a069352021-01-09 04:11:10 +0000105 static int cached_result = []()->int {
John Stultza7002cb2020-09-04 19:02:30 +0000106 struct stat buffer;
John Stultz3a069352021-01-09 04:11:10 +0000107 int ret = (stat("/dev/ion", &buffer) == 0);
108
109 if (property_get_int32("debug.c2.use_dmabufheaps", 0)) {
110 /*
111 * Double check that the system heap is present so we
112 * can gracefully fail back to ION if we cannot satisfy
113 * the override
114 */
115 ret = (stat("/dev/dma_heap/system", &buffer) != 0);
116 if (ret)
117 ALOGE("debug.c2.use_dmabufheaps set, but no system heap. Ignoring override!");
118 else
119 ALOGD("debug.c2.use_dmabufheaps set, forcing DMABUF Heaps");
120 }
121
122 if (ret)
John Stultza7002cb2020-09-04 19:02:30 +0000123 ALOGD("Using ION\n");
124 else
125 ALOGD("Using DMABUF Heaps\n");
John Stultz3a069352021-01-09 04:11:10 +0000126 return ret;
127 }();
128
John Stultza7002cb2020-09-04 19:02:30 +0000129 return (cached_result == 1);
130}
131
Pawin Vongmasa36653902018-11-15 00:10:25 -0800132c2_status_t C2PlatformAllocatorStoreImpl::fetchAllocator(
133 id_t id, std::shared_ptr<C2Allocator> *const allocator) {
134 allocator->reset();
Pin-chih Linaa18ea52019-11-19 18:48:50 +0800135 if (id == C2AllocatorStore::DEFAULT_LINEAR) {
136 id = GetPreferredLinearAllocatorId(GetCodec2PoolMask());
137 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800138 switch (id) {
139 // TODO: should we implement a generic registry for all, and use that?
John Stultza7002cb2020-09-04 19:02:30 +0000140 case C2PlatformAllocatorStore::ION: /* also ::DMABUFHEAP */
141 if (using_ion())
142 *allocator = fetchIonAllocator();
143 else
144 *allocator = fetchDmaBufAllocator();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800145 break;
146
147 case C2PlatformAllocatorStore::GRALLOC:
148 case C2AllocatorStore::DEFAULT_GRAPHIC:
149 *allocator = fetchGrallocAllocator();
150 break;
151
152 case C2PlatformAllocatorStore::BUFFERQUEUE:
153 *allocator = fetchBufferQueueAllocator();
154 break;
155
Pin-chih Linaa18ea52019-11-19 18:48:50 +0800156 case C2PlatformAllocatorStore::BLOB:
157 *allocator = fetchBlobAllocator();
158 break;
159
Pawin Vongmasa36653902018-11-15 00:10:25 -0800160 default:
161 // Try to create allocator from platform store plugins.
162 c2_status_t res =
163 C2PlatformStorePluginLoader::GetInstance()->createAllocator(id, allocator);
164 if (res != C2_OK) {
165 return res;
166 }
167 break;
168 }
169 if (*allocator == nullptr) {
170 return C2_NO_MEMORY;
171 }
172 return C2_OK;
173}
174
175namespace {
176
177std::mutex gIonAllocatorMutex;
John Stultza7002cb2020-09-04 19:02:30 +0000178std::mutex gDmaBufAllocatorMutex;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800179std::weak_ptr<C2AllocatorIon> gIonAllocator;
John Stultza7002cb2020-09-04 19:02:30 +0000180std::weak_ptr<C2DmaBufAllocator> gDmaBufAllocator;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800181
182void UseComponentStoreForIonAllocator(
183 const std::shared_ptr<C2AllocatorIon> allocator,
184 std::shared_ptr<C2ComponentStore> store) {
185 C2AllocatorIon::UsageMapperFn mapper;
186 uint64_t minUsage = 0;
187 uint64_t maxUsage = C2MemoryUsage(C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE).expected;
188 size_t blockSize = getpagesize();
189
190 // query min and max usage as well as block size via supported values
191 C2StoreIonUsageInfo usageInfo;
192 std::vector<C2FieldSupportedValuesQuery> query = {
193 C2FieldSupportedValuesQuery::Possible(C2ParamField::Make(usageInfo, usageInfo.usage)),
194 C2FieldSupportedValuesQuery::Possible(C2ParamField::Make(usageInfo, usageInfo.capacity)),
195 };
196 c2_status_t res = store->querySupportedValues_sm(query);
197 if (res == C2_OK) {
198 if (query[0].status == C2_OK) {
199 const C2FieldSupportedValues &fsv = query[0].values;
200 if (fsv.type == C2FieldSupportedValues::FLAGS && !fsv.values.empty()) {
201 minUsage = fsv.values[0].u64;
202 maxUsage = 0;
203 for (C2Value::Primitive v : fsv.values) {
204 maxUsage |= v.u64;
205 }
206 }
207 }
208 if (query[1].status == C2_OK) {
209 const C2FieldSupportedValues &fsv = query[1].values;
210 if (fsv.type == C2FieldSupportedValues::RANGE && fsv.range.step.u32 > 0) {
211 blockSize = fsv.range.step.u32;
212 }
213 }
214
215 mapper = [store](C2MemoryUsage usage, size_t capacity,
216 size_t *align, unsigned *heapMask, unsigned *flags) -> c2_status_t {
217 if (capacity > UINT32_MAX) {
218 return C2_BAD_VALUE;
219 }
220 C2StoreIonUsageInfo usageInfo = { usage.expected, capacity };
221 std::vector<std::unique_ptr<C2SettingResult>> failures; // TODO: remove
222 c2_status_t res = store->config_sm({&usageInfo}, &failures);
223 if (res == C2_OK) {
224 *align = usageInfo.minAlignment;
225 *heapMask = usageInfo.heapMask;
226 *flags = usageInfo.allocFlags;
227 }
228 return res;
229 };
230 }
231
232 allocator->setUsageMapper(mapper, minUsage, maxUsage, blockSize);
233}
234
John Stultza7002cb2020-09-04 19:02:30 +0000235void UseComponentStoreForDmaBufAllocator(const std::shared_ptr<C2DmaBufAllocator> allocator,
236 std::shared_ptr<C2ComponentStore> store) {
237 C2DmaBufAllocator::UsageMapperFn mapper;
238 const size_t maxHeapNameLen = 128;
239 uint64_t minUsage = 0;
240 uint64_t maxUsage = C2MemoryUsage(C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE).expected;
241 size_t blockSize = getpagesize();
242
243 // query min and max usage as well as block size via supported values
244 std::unique_ptr<C2StoreDmaBufUsageInfo> usageInfo;
245 usageInfo = C2StoreDmaBufUsageInfo::AllocUnique(maxHeapNameLen);
246
247 std::vector<C2FieldSupportedValuesQuery> query = {
248 C2FieldSupportedValuesQuery::Possible(C2ParamField::Make(*usageInfo, usageInfo->m.usage)),
249 C2FieldSupportedValuesQuery::Possible(
250 C2ParamField::Make(*usageInfo, usageInfo->m.capacity)),
251 };
252 c2_status_t res = store->querySupportedValues_sm(query);
253 if (res == C2_OK) {
254 if (query[0].status == C2_OK) {
255 const C2FieldSupportedValues& fsv = query[0].values;
256 if (fsv.type == C2FieldSupportedValues::FLAGS && !fsv.values.empty()) {
257 minUsage = fsv.values[0].u64;
258 maxUsage = 0;
259 for (C2Value::Primitive v : fsv.values) {
260 maxUsage |= v.u64;
261 }
262 }
263 }
264 if (query[1].status == C2_OK) {
265 const C2FieldSupportedValues& fsv = query[1].values;
266 if (fsv.type == C2FieldSupportedValues::RANGE && fsv.range.step.u32 > 0) {
267 blockSize = fsv.range.step.u32;
268 }
269 }
270
271 mapper = [store](C2MemoryUsage usage, size_t capacity, C2String* heapName,
272 unsigned* flags) -> c2_status_t {
273 if (capacity > UINT32_MAX) {
274 return C2_BAD_VALUE;
275 }
276
277 std::unique_ptr<C2StoreDmaBufUsageInfo> usageInfo;
278 usageInfo = C2StoreDmaBufUsageInfo::AllocUnique(maxHeapNameLen, usage.expected, capacity);
279 std::vector<std::unique_ptr<C2SettingResult>> failures; // TODO: remove
280
281 c2_status_t res = store->config_sm({&*usageInfo}, &failures);
282 if (res == C2_OK) {
283 *heapName = C2String(usageInfo->m.heapName);
284 *flags = usageInfo->m.allocFlags;
285 }
286
287 return res;
288 };
289 }
290
291 allocator->setUsageMapper(mapper, minUsage, maxUsage, blockSize);
292}
293
Pawin Vongmasa36653902018-11-15 00:10:25 -0800294}
295
296void C2PlatformAllocatorStoreImpl::setComponentStore(std::shared_ptr<C2ComponentStore> store) {
297 // technically this set lock is not needed, but is here for safety in case we add more
298 // getter orders
299 std::lock_guard<std::mutex> lock(_mComponentStoreSetLock);
300 {
301 std::lock_guard<std::mutex> lock(_mComponentStoreReadLock);
302 _mComponentStore = store;
303 }
Sungtak Lee32429192022-01-07 15:18:51 -0800304 std::shared_ptr<C2AllocatorIon> ionAllocator;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800305 {
306 std::lock_guard<std::mutex> lock(gIonAllocatorMutex);
Sungtak Lee32429192022-01-07 15:18:51 -0800307 ionAllocator = gIonAllocator.lock();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800308 }
Sungtak Lee32429192022-01-07 15:18:51 -0800309 if (ionAllocator) {
310 UseComponentStoreForIonAllocator(ionAllocator, store);
311 }
312 std::shared_ptr<C2DmaBufAllocator> dmaAllocator;
313 {
314 std::lock_guard<std::mutex> lock(gDmaBufAllocatorMutex);
315 dmaAllocator = gDmaBufAllocator.lock();
316 }
317 if (dmaAllocator) {
318 UseComponentStoreForDmaBufAllocator(dmaAllocator, store);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800319 }
320}
321
322std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchIonAllocator() {
323 std::lock_guard<std::mutex> lock(gIonAllocatorMutex);
324 std::shared_ptr<C2AllocatorIon> allocator = gIonAllocator.lock();
325 if (allocator == nullptr) {
326 std::shared_ptr<C2ComponentStore> componentStore;
327 {
328 std::lock_guard<std::mutex> lock(_mComponentStoreReadLock);
329 componentStore = _mComponentStore;
330 }
331 allocator = std::make_shared<C2AllocatorIon>(C2PlatformAllocatorStore::ION);
332 UseComponentStoreForIonAllocator(allocator, componentStore);
333 gIonAllocator = allocator;
334 }
335 return allocator;
336}
337
John Stultza7002cb2020-09-04 19:02:30 +0000338std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchDmaBufAllocator() {
339 std::lock_guard<std::mutex> lock(gDmaBufAllocatorMutex);
340 std::shared_ptr<C2DmaBufAllocator> allocator = gDmaBufAllocator.lock();
341 if (allocator == nullptr) {
342 std::shared_ptr<C2ComponentStore> componentStore;
343 {
344 std::lock_guard<std::mutex> lock(_mComponentStoreReadLock);
345 componentStore = _mComponentStore;
346 }
347 allocator = std::make_shared<C2DmaBufAllocator>(C2PlatformAllocatorStore::DMABUFHEAP);
348 UseComponentStoreForDmaBufAllocator(allocator, componentStore);
349 gDmaBufAllocator = allocator;
350 }
351 return allocator;
352}
353
Pin-chih Linaa18ea52019-11-19 18:48:50 +0800354std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchBlobAllocator() {
355 static std::mutex mutex;
356 static std::weak_ptr<C2Allocator> blobAllocator;
357 std::lock_guard<std::mutex> lock(mutex);
358 std::shared_ptr<C2Allocator> allocator = blobAllocator.lock();
359 if (allocator == nullptr) {
360 allocator = std::make_shared<C2AllocatorBlob>(C2PlatformAllocatorStore::BLOB);
361 blobAllocator = allocator;
362 }
363 return allocator;
364}
365
Pawin Vongmasa36653902018-11-15 00:10:25 -0800366std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchGrallocAllocator() {
367 static std::mutex mutex;
368 static std::weak_ptr<C2Allocator> grallocAllocator;
369 std::lock_guard<std::mutex> lock(mutex);
370 std::shared_ptr<C2Allocator> allocator = grallocAllocator.lock();
371 if (allocator == nullptr) {
372 allocator = std::make_shared<C2AllocatorGralloc>(C2PlatformAllocatorStore::GRALLOC);
373 grallocAllocator = allocator;
374 }
375 return allocator;
376}
377
378std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchBufferQueueAllocator() {
379 static std::mutex mutex;
380 static std::weak_ptr<C2Allocator> grallocAllocator;
381 std::lock_guard<std::mutex> lock(mutex);
382 std::shared_ptr<C2Allocator> allocator = grallocAllocator.lock();
383 if (allocator == nullptr) {
384 allocator = std::make_shared<C2AllocatorGralloc>(
385 C2PlatformAllocatorStore::BUFFERQUEUE, true);
386 grallocAllocator = allocator;
387 }
388 return allocator;
389}
390
391namespace {
392 std::mutex gPreferredComponentStoreMutex;
393 std::shared_ptr<C2ComponentStore> gPreferredComponentStore;
394
395 std::mutex gPlatformAllocatorStoreMutex;
396 std::weak_ptr<C2PlatformAllocatorStoreImpl> gPlatformAllocatorStore;
397}
398
399std::shared_ptr<C2AllocatorStore> GetCodec2PlatformAllocatorStore() {
400 std::lock_guard<std::mutex> lock(gPlatformAllocatorStoreMutex);
401 std::shared_ptr<C2PlatformAllocatorStoreImpl> store = gPlatformAllocatorStore.lock();
402 if (store == nullptr) {
403 store = std::make_shared<C2PlatformAllocatorStoreImpl>();
404 store->setComponentStore(GetPreferredCodec2ComponentStore());
405 gPlatformAllocatorStore = store;
406 }
407 return store;
408}
409
410void SetPreferredCodec2ComponentStore(std::shared_ptr<C2ComponentStore> componentStore) {
411 static std::mutex mutex;
412 std::lock_guard<std::mutex> lock(mutex); // don't interleve set-s
413
414 // update preferred store
415 {
416 std::lock_guard<std::mutex> lock(gPreferredComponentStoreMutex);
417 gPreferredComponentStore = componentStore;
418 }
419
420 // update platform allocator's store as well if it is alive
421 std::shared_ptr<C2PlatformAllocatorStoreImpl> allocatorStore;
422 {
423 std::lock_guard<std::mutex> lock(gPlatformAllocatorStoreMutex);
424 allocatorStore = gPlatformAllocatorStore.lock();
425 }
426 if (allocatorStore) {
427 allocatorStore->setComponentStore(componentStore);
428 }
429}
430
431std::shared_ptr<C2ComponentStore> GetPreferredCodec2ComponentStore() {
432 std::lock_guard<std::mutex> lock(gPreferredComponentStoreMutex);
433 return gPreferredComponentStore ? gPreferredComponentStore : GetCodec2PlatformComponentStore();
434}
435
Pin-chih Linaa18ea52019-11-19 18:48:50 +0800436int GetCodec2PoolMask() {
437 return property_get_int32(
438 "debug.stagefright.c2-poolmask",
439 1 << C2PlatformAllocatorStore::ION |
440 1 << C2PlatformAllocatorStore::BUFFERQUEUE);
441}
442
443C2PlatformAllocatorStore::id_t GetPreferredLinearAllocatorId(int poolMask) {
444 return ((poolMask >> C2PlatformAllocatorStore::BLOB) & 1) ? C2PlatformAllocatorStore::BLOB
445 : C2PlatformAllocatorStore::ION;
446}
447
Pawin Vongmasa36653902018-11-15 00:10:25 -0800448namespace {
449
450class _C2BlockPoolCache {
451public:
452 _C2BlockPoolCache() : mBlockPoolSeqId(C2BlockPool::PLATFORM_START + 1) {}
453
Wonsik Kim17911e32021-08-26 13:57:02 -0700454private:
Pawin Vongmasa36653902018-11-15 00:10:25 -0800455 c2_status_t _createBlockPool(
456 C2PlatformAllocatorStore::id_t allocatorId,
Wonsik Kim2fce07922021-02-11 00:16:11 -0800457 std::vector<std::shared_ptr<const C2Component>> components,
Pawin Vongmasa36653902018-11-15 00:10:25 -0800458 C2BlockPool::local_id_t poolId,
459 std::shared_ptr<C2BlockPool> *pool) {
460 std::shared_ptr<C2AllocatorStore> allocatorStore =
461 GetCodec2PlatformAllocatorStore();
462 std::shared_ptr<C2Allocator> allocator;
463 c2_status_t res = C2_NOT_FOUND;
464
Pin-chih Linaa18ea52019-11-19 18:48:50 +0800465 if (allocatorId == C2AllocatorStore::DEFAULT_LINEAR) {
466 allocatorId = GetPreferredLinearAllocatorId(GetCodec2PoolMask());
467 }
Wonsik Kim17911e32021-08-26 13:57:02 -0700468 auto deleter = [this, poolId](C2BlockPool *pool) {
469 std::unique_lock lock(mMutex);
470 mBlockPools.erase(poolId);
471 mComponents.erase(poolId);
472 delete pool;
473 };
Pawin Vongmasa36653902018-11-15 00:10:25 -0800474 switch(allocatorId) {
John Stultza7002cb2020-09-04 19:02:30 +0000475 case C2PlatformAllocatorStore::ION: /* also ::DMABUFHEAP */
Pawin Vongmasa36653902018-11-15 00:10:25 -0800476 res = allocatorStore->fetchAllocator(
Pin-chih Linaa18ea52019-11-19 18:48:50 +0800477 C2PlatformAllocatorStore::ION, &allocator);
478 if (res == C2_OK) {
Wonsik Kim17911e32021-08-26 13:57:02 -0700479 std::shared_ptr<C2BlockPool> ptr(
480 new C2PooledBlockPool(allocator, poolId), deleter);
Pin-chih Linaa18ea52019-11-19 18:48:50 +0800481 *pool = ptr;
482 mBlockPools[poolId] = ptr;
Wonsik Kim2fce07922021-02-11 00:16:11 -0800483 mComponents[poolId].insert(
484 mComponents[poolId].end(),
485 components.begin(), components.end());
Pin-chih Linaa18ea52019-11-19 18:48:50 +0800486 }
487 break;
488 case C2PlatformAllocatorStore::BLOB:
489 res = allocatorStore->fetchAllocator(
490 C2PlatformAllocatorStore::BLOB, &allocator);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800491 if (res == C2_OK) {
Wonsik Kim17911e32021-08-26 13:57:02 -0700492 std::shared_ptr<C2BlockPool> ptr(
493 new C2PooledBlockPool(allocator, poolId), deleter);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800494 *pool = ptr;
495 mBlockPools[poolId] = ptr;
Wonsik Kim2fce07922021-02-11 00:16:11 -0800496 mComponents[poolId].insert(
497 mComponents[poolId].end(),
498 components.begin(), components.end());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800499 }
500 break;
501 case C2PlatformAllocatorStore::GRALLOC:
502 case C2AllocatorStore::DEFAULT_GRAPHIC:
503 res = allocatorStore->fetchAllocator(
504 C2AllocatorStore::DEFAULT_GRAPHIC, &allocator);
505 if (res == C2_OK) {
Wonsik Kim17911e32021-08-26 13:57:02 -0700506 std::shared_ptr<C2BlockPool> ptr(
507 new C2PooledBlockPool(allocator, poolId), deleter);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800508 *pool = ptr;
509 mBlockPools[poolId] = ptr;
Wonsik Kim2fce07922021-02-11 00:16:11 -0800510 mComponents[poolId].insert(
511 mComponents[poolId].end(),
512 components.begin(), components.end());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800513 }
514 break;
515 case C2PlatformAllocatorStore::BUFFERQUEUE:
516 res = allocatorStore->fetchAllocator(
517 C2PlatformAllocatorStore::BUFFERQUEUE, &allocator);
518 if (res == C2_OK) {
Wonsik Kim17911e32021-08-26 13:57:02 -0700519 std::shared_ptr<C2BlockPool> ptr(
520 new C2BufferQueueBlockPool(allocator, poolId), deleter);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800521 *pool = ptr;
522 mBlockPools[poolId] = ptr;
Wonsik Kim2fce07922021-02-11 00:16:11 -0800523 mComponents[poolId].insert(
524 mComponents[poolId].end(),
525 components.begin(), components.end());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800526 }
527 break;
528 default:
529 // Try to create block pool from platform store plugins.
530 std::shared_ptr<C2BlockPool> ptr;
531 res = C2PlatformStorePluginLoader::GetInstance()->createBlockPool(
Wonsik Kim17911e32021-08-26 13:57:02 -0700532 allocatorId, poolId, &ptr, deleter);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800533 if (res == C2_OK) {
534 *pool = ptr;
535 mBlockPools[poolId] = ptr;
Wonsik Kim2fce07922021-02-11 00:16:11 -0800536 mComponents[poolId].insert(
537 mComponents[poolId].end(),
538 components.begin(), components.end());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800539 }
540 break;
541 }
542 return res;
543 }
544
Wonsik Kim17911e32021-08-26 13:57:02 -0700545public:
Pawin Vongmasa36653902018-11-15 00:10:25 -0800546 c2_status_t createBlockPool(
547 C2PlatformAllocatorStore::id_t allocatorId,
Wonsik Kim2fce07922021-02-11 00:16:11 -0800548 std::vector<std::shared_ptr<const C2Component>> components,
Pawin Vongmasa36653902018-11-15 00:10:25 -0800549 std::shared_ptr<C2BlockPool> *pool) {
Wonsik Kim17911e32021-08-26 13:57:02 -0700550 std::unique_lock lock(mMutex);
Wonsik Kim2fce07922021-02-11 00:16:11 -0800551 return _createBlockPool(allocatorId, components, mBlockPoolSeqId++, pool);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800552 }
553
Wonsik Kim17911e32021-08-26 13:57:02 -0700554 c2_status_t getBlockPool(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800555 C2BlockPool::local_id_t blockPoolId,
556 std::shared_ptr<const C2Component> component,
557 std::shared_ptr<C2BlockPool> *pool) {
Wonsik Kim17911e32021-08-26 13:57:02 -0700558 std::unique_lock lock(mMutex);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800559 // TODO: use one iterator for multiple blockpool type scalability.
560 std::shared_ptr<C2BlockPool> ptr;
561 auto it = mBlockPools.find(blockPoolId);
562 if (it != mBlockPools.end()) {
563 ptr = it->second.lock();
564 if (!ptr) {
565 mBlockPools.erase(it);
566 mComponents.erase(blockPoolId);
567 } else {
Wonsik Kim2fce07922021-02-11 00:16:11 -0800568 auto found = std::find_if(
569 mComponents[blockPoolId].begin(),
570 mComponents[blockPoolId].end(),
571 [component](const std::weak_ptr<const C2Component> &ptr) {
572 return component == ptr.lock();
573 });
574 if (found != mComponents[blockPoolId].end()) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800575 *pool = ptr;
Wonsik Kim17911e32021-08-26 13:57:02 -0700576 return C2_OK;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800577 }
578 }
579 }
Wonsik Kim17911e32021-08-26 13:57:02 -0700580 // TODO: remove this. this is temporary
581 if (blockPoolId == C2BlockPool::PLATFORM_START) {
582 return _createBlockPool(
583 C2PlatformAllocatorStore::BUFFERQUEUE, {component}, blockPoolId, pool);
584 }
585 return C2_NOT_FOUND;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800586 }
587
588private:
Wonsik Kim17911e32021-08-26 13:57:02 -0700589 // Deleter needs to hold this mutex, and there is a small chance that deleter
590 // is invoked while the mutex is held.
591 std::recursive_mutex mMutex;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800592 C2BlockPool::local_id_t mBlockPoolSeqId;
593
594 std::map<C2BlockPool::local_id_t, std::weak_ptr<C2BlockPool>> mBlockPools;
Wonsik Kim2fce07922021-02-11 00:16:11 -0800595 std::map<C2BlockPool::local_id_t, std::vector<std::weak_ptr<const C2Component>>> mComponents;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800596};
597
598static std::unique_ptr<_C2BlockPoolCache> sBlockPoolCache =
599 std::make_unique<_C2BlockPoolCache>();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800600
601} // anynymous namespace
602
603c2_status_t GetCodec2BlockPool(
604 C2BlockPool::local_id_t id, std::shared_ptr<const C2Component> component,
605 std::shared_ptr<C2BlockPool> *pool) {
606 pool->reset();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800607 std::shared_ptr<C2AllocatorStore> allocatorStore = GetCodec2PlatformAllocatorStore();
608 std::shared_ptr<C2Allocator> allocator;
609 c2_status_t res = C2_NOT_FOUND;
610
611 if (id >= C2BlockPool::PLATFORM_START) {
Wonsik Kim17911e32021-08-26 13:57:02 -0700612 return sBlockPoolCache->getBlockPool(id, component, pool);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800613 }
614
615 switch (id) {
616 case C2BlockPool::BASIC_LINEAR:
617 res = allocatorStore->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &allocator);
618 if (res == C2_OK) {
619 *pool = std::make_shared<C2BasicLinearBlockPool>(allocator);
620 }
621 break;
622 case C2BlockPool::BASIC_GRAPHIC:
623 res = allocatorStore->fetchAllocator(C2AllocatorStore::DEFAULT_GRAPHIC, &allocator);
624 if (res == C2_OK) {
625 *pool = std::make_shared<C2BasicGraphicBlockPool>(allocator);
626 }
627 break;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800628 default:
629 break;
630 }
631 return res;
632}
633
634c2_status_t CreateCodec2BlockPool(
635 C2PlatformAllocatorStore::id_t allocatorId,
Wonsik Kim2fce07922021-02-11 00:16:11 -0800636 const std::vector<std::shared_ptr<const C2Component>> &components,
637 std::shared_ptr<C2BlockPool> *pool) {
638 pool->reset();
639
Wonsik Kim2fce07922021-02-11 00:16:11 -0800640 return sBlockPoolCache->createBlockPool(allocatorId, components, pool);
641}
642
643c2_status_t CreateCodec2BlockPool(
644 C2PlatformAllocatorStore::id_t allocatorId,
Pawin Vongmasa36653902018-11-15 00:10:25 -0800645 std::shared_ptr<const C2Component> component,
646 std::shared_ptr<C2BlockPool> *pool) {
647 pool->reset();
648
Wonsik Kim2fce07922021-02-11 00:16:11 -0800649 return sBlockPoolCache->createBlockPool(allocatorId, {component}, pool);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800650}
651
652class C2PlatformComponentStore : public C2ComponentStore {
653public:
654 virtual std::vector<std::shared_ptr<const C2Component::Traits>> listComponents() override;
655 virtual std::shared_ptr<C2ParamReflector> getParamReflector() const override;
656 virtual C2String getName() const override;
657 virtual c2_status_t querySupportedValues_sm(
658 std::vector<C2FieldSupportedValuesQuery> &fields) const override;
659 virtual c2_status_t querySupportedParams_nb(
660 std::vector<std::shared_ptr<C2ParamDescriptor>> *const params) const override;
661 virtual c2_status_t query_sm(
662 const std::vector<C2Param*> &stackParams,
663 const std::vector<C2Param::Index> &heapParamIndices,
664 std::vector<std::unique_ptr<C2Param>> *const heapParams) const override;
665 virtual c2_status_t createInterface(
666 C2String name, std::shared_ptr<C2ComponentInterface> *const interface) override;
667 virtual c2_status_t createComponent(
668 C2String name, std::shared_ptr<C2Component> *const component) override;
669 virtual c2_status_t copyBuffer(
670 std::shared_ptr<C2GraphicBuffer> src, std::shared_ptr<C2GraphicBuffer> dst) override;
671 virtual c2_status_t config_sm(
672 const std::vector<C2Param*> &params,
673 std::vector<std::unique_ptr<C2SettingResult>> *const failures) override;
674 C2PlatformComponentStore();
675
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530676 // For testing only
677 C2PlatformComponentStore(
678 std::vector<std::tuple<C2String,
679 C2ComponentFactory::CreateCodec2FactoryFunc,
680 C2ComponentFactory::DestroyCodec2FactoryFunc>>);
681
Pawin Vongmasa36653902018-11-15 00:10:25 -0800682 virtual ~C2PlatformComponentStore() override = default;
683
684private:
685
686 /**
687 * An object encapsulating a loaded component module.
688 *
689 * \todo provide a way to add traits to known components here to avoid loading the .so-s
690 * for listComponents
691 */
692 struct ComponentModule : public C2ComponentFactory,
693 public std::enable_shared_from_this<ComponentModule> {
694 virtual c2_status_t createComponent(
695 c2_node_id_t id, std::shared_ptr<C2Component> *component,
696 ComponentDeleter deleter = std::default_delete<C2Component>()) override;
697 virtual c2_status_t createInterface(
698 c2_node_id_t id, std::shared_ptr<C2ComponentInterface> *interface,
699 InterfaceDeleter deleter = std::default_delete<C2ComponentInterface>()) override;
700
701 /**
702 * \returns the traits of the component in this module.
703 */
704 std::shared_ptr<const C2Component::Traits> getTraits();
705
706 /**
707 * Creates an uninitialized component module.
708 *
709 * \param name[in] component name.
710 *
711 * \note Only used by ComponentLoader.
712 */
713 ComponentModule()
714 : mInit(C2_NO_INIT),
715 mLibHandle(nullptr),
716 createFactory(nullptr),
717 destroyFactory(nullptr),
718 mComponentFactory(nullptr) {
719 }
720
721 /**
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530722 * Creates an uninitialized component module.
723 * NOTE: For testing only
724 *
725 * \param name[in] component name.
726 *
727 * \note Only used by ComponentLoader.
728 */
729 ComponentModule(
730 C2ComponentFactory::CreateCodec2FactoryFunc createFactory,
731 C2ComponentFactory::DestroyCodec2FactoryFunc destroyFactory)
732 : mInit(C2_NO_INIT),
733 mLibHandle(nullptr),
734 createFactory(createFactory),
735 destroyFactory(destroyFactory),
736 mComponentFactory(nullptr) {
737 }
738
739 /**
Pawin Vongmasa36653902018-11-15 00:10:25 -0800740 * Initializes a component module with a given library path. Must be called exactly once.
741 *
742 * \note Only used by ComponentLoader.
743 *
Pawin Vongmasa36653902018-11-15 00:10:25 -0800744 * \param libPath[in] library path
745 *
746 * \retval C2_OK the component module has been successfully loaded
747 * \retval C2_NO_MEMORY not enough memory to loading the component module
748 * \retval C2_NOT_FOUND could not locate the component module
749 * \retval C2_CORRUPTED the component module could not be loaded (unexpected)
750 * \retval C2_REFUSED permission denied to load the component module (unexpected)
751 * \retval C2_TIMED_OUT could not load the module within the time limit (unexpected)
752 */
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800753 c2_status_t init(std::string libPath);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800754
755 virtual ~ComponentModule() override;
756
757 protected:
758 std::recursive_mutex mLock; ///< lock protecting mTraits
759 std::shared_ptr<C2Component::Traits> mTraits; ///< cached component traits
760
761 c2_status_t mInit; ///< initialization result
762
763 void *mLibHandle; ///< loaded library handle
764 C2ComponentFactory::CreateCodec2FactoryFunc createFactory; ///< loaded create function
765 C2ComponentFactory::DestroyCodec2FactoryFunc destroyFactory; ///< loaded destroy function
766 C2ComponentFactory *mComponentFactory; ///< loaded/created component factory
767 };
768
769 /**
770 * An object encapsulating a loadable component module.
771 *
772 * \todo make this also work for enumerations
773 */
774 struct ComponentLoader {
775 /**
776 * Load the component module.
777 *
778 * This method simply returns the component module if it is already currently loaded, or
779 * attempts to load it if it is not.
780 *
781 * \param module[out] pointer to the shared pointer where the loaded module shall be stored.
782 * This will be nullptr on error.
783 *
784 * \retval C2_OK the component module has been successfully loaded
785 * \retval C2_NO_MEMORY not enough memory to loading the component module
786 * \retval C2_NOT_FOUND could not locate the component module
787 * \retval C2_CORRUPTED the component module could not be loaded
788 * \retval C2_REFUSED permission denied to load the component module
789 */
790 c2_status_t fetchModule(std::shared_ptr<ComponentModule> *module) {
791 c2_status_t res = C2_OK;
792 std::lock_guard<std::mutex> lock(mMutex);
793 std::shared_ptr<ComponentModule> localModule = mModule.lock();
794 if (localModule == nullptr) {
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530795 if(mCreateFactory) {
796 // For testing only
797 localModule = std::make_shared<ComponentModule>(mCreateFactory,
798 mDestroyFactory);
799 } else {
800 localModule = std::make_shared<ComponentModule>();
801 }
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800802 res = localModule->init(mLibPath);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800803 if (res == C2_OK) {
804 mModule = localModule;
805 }
806 }
807 *module = localModule;
808 return res;
809 }
810
811 /**
812 * Creates a component loader for a specific library path (or name).
813 */
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800814 ComponentLoader(std::string libPath)
815 : mLibPath(libPath) {}
Pawin Vongmasa36653902018-11-15 00:10:25 -0800816
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530817 // For testing only
818 ComponentLoader(std::tuple<C2String,
819 C2ComponentFactory::CreateCodec2FactoryFunc,
820 C2ComponentFactory::DestroyCodec2FactoryFunc> func)
821 : mLibPath(std::get<0>(func)),
822 mCreateFactory(std::get<1>(func)),
823 mDestroyFactory(std::get<2>(func)) {}
824
Pawin Vongmasa36653902018-11-15 00:10:25 -0800825 private:
826 std::mutex mMutex; ///< mutex guarding the module
827 std::weak_ptr<ComponentModule> mModule; ///< weak reference to the loaded module
Pawin Vongmasa36653902018-11-15 00:10:25 -0800828 std::string mLibPath; ///< library path
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530829
830 // For testing only
831 C2ComponentFactory::CreateCodec2FactoryFunc mCreateFactory = nullptr;
832 C2ComponentFactory::DestroyCodec2FactoryFunc mDestroyFactory = nullptr;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800833 };
834
835 struct Interface : public C2InterfaceHelper {
836 std::shared_ptr<C2StoreIonUsageInfo> mIonUsageInfo;
John Stultza7002cb2020-09-04 19:02:30 +0000837 std::shared_ptr<C2StoreDmaBufUsageInfo> mDmaBufUsageInfo;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800838
839 Interface(std::shared_ptr<C2ReflectorHelper> reflector)
840 : C2InterfaceHelper(reflector) {
841 setDerivedInstance(this);
842
843 struct Setter {
844 static C2R setIonUsage(bool /* mayBlock */, C2P<C2StoreIonUsageInfo> &me) {
Wonsik Kimba3db192019-11-22 11:00:48 -0800845#ifdef __ANDROID_APEX__
846 static int32_t defaultHeapMask = [] {
847 int32_t heapmask = base::GetIntProperty(
848 "ro.com.android.media.swcodec.ion.heapmask", int32_t(0xFFFFFFFF));
849 ALOGD("Default ION heapmask = %d", heapmask);
850 return heapmask;
851 }();
852 static int32_t defaultFlags = [] {
853 int32_t flags = base::GetIntProperty(
854 "ro.com.android.media.swcodec.ion.flags", 0);
855 ALOGD("Default ION flags = %d", flags);
856 return flags;
857 }();
858 static uint32_t defaultAlign = [] {
859 uint32_t align = base::GetUintProperty(
860 "ro.com.android.media.swcodec.ion.align", 0u);
861 ALOGD("Default ION align = %d", align);
862 return align;
863 }();
864 me.set().heapMask = defaultHeapMask;
865 me.set().allocFlags = defaultFlags;
866 me.set().minAlignment = defaultAlign;
867#else
Pawin Vongmasa36653902018-11-15 00:10:25 -0800868 me.set().heapMask = ~0;
869 me.set().allocFlags = 0;
870 me.set().minAlignment = 0;
Wonsik Kimba3db192019-11-22 11:00:48 -0800871#endif
Pawin Vongmasa36653902018-11-15 00:10:25 -0800872 return C2R::Ok();
John Stultza7002cb2020-09-04 19:02:30 +0000873 };
874
875 static C2R setDmaBufUsage(bool /* mayBlock */, C2P<C2StoreDmaBufUsageInfo> &me) {
John Stultz9eda9bf2021-01-08 00:41:13 +0000876 long long usage = (long long)me.get().m.usage;
877 if (C2DmaBufAllocator::system_uncached_supported() &&
878 !(usage & (C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE))) {
879 strncpy(me.set().m.heapName, "system-uncached", me.v.flexCount());
880 } else {
881 strncpy(me.set().m.heapName, "system", me.v.flexCount());
882 }
John Stultza7002cb2020-09-04 19:02:30 +0000883 me.set().m.allocFlags = 0;
884 return C2R::Ok();
885 };
Pawin Vongmasa36653902018-11-15 00:10:25 -0800886 };
887
888 addParameter(
889 DefineParam(mIonUsageInfo, "ion-usage")
890 .withDefault(new C2StoreIonUsageInfo())
891 .withFields({
892 C2F(mIonUsageInfo, usage).flags({C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE}),
893 C2F(mIonUsageInfo, capacity).inRange(0, UINT32_MAX, 1024),
894 C2F(mIonUsageInfo, heapMask).any(),
895 C2F(mIonUsageInfo, allocFlags).flags({}),
896 C2F(mIonUsageInfo, minAlignment).equalTo(0)
897 })
898 .withSetter(Setter::setIonUsage)
899 .build());
John Stultza7002cb2020-09-04 19:02:30 +0000900
901 addParameter(
902 DefineParam(mDmaBufUsageInfo, "dmabuf-usage")
903 .withDefault(C2StoreDmaBufUsageInfo::AllocShared(0))
904 .withFields({
905 C2F(mDmaBufUsageInfo, m.usage).flags({C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE}),
906 C2F(mDmaBufUsageInfo, m.capacity).inRange(0, UINT32_MAX, 1024),
907 C2F(mDmaBufUsageInfo, m.allocFlags).flags({}),
908 C2F(mDmaBufUsageInfo, m.heapName).any(),
909 })
910 .withSetter(Setter::setDmaBufUsage)
911 .build());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800912 }
913 };
914
915 /**
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800916 * Retrieves the component module for a component.
Pawin Vongmasa36653902018-11-15 00:10:25 -0800917 *
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800918 * \param module pointer to a shared_pointer where the component module will be stored on
919 * success.
Pawin Vongmasa36653902018-11-15 00:10:25 -0800920 *
921 * \retval C2_OK the component loader has been successfully retrieved
922 * \retval C2_NO_MEMORY not enough memory to locate the component loader
923 * \retval C2_NOT_FOUND could not locate the component to be loaded
924 * \retval C2_CORRUPTED the component loader could not be identified due to some modules being
925 * corrupted (this can happen if the name does not refer to an already
926 * identified component but some components could not be loaded due to
927 * bad library)
928 * \retval C2_REFUSED permission denied to find the component loader for the named component
929 * (this can happen if the name does not refer to an already identified
930 * component but some components could not be loaded due to lack of
931 * permissions)
932 */
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800933 c2_status_t findComponent(C2String name, std::shared_ptr<ComponentModule> *module);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800934
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800935 /**
936 * Loads each component module and discover its contents.
937 */
938 void visitComponents();
939
940 std::mutex mMutex; ///< mutex guarding the component lists during construction
941 bool mVisited; ///< component modules visited
942 std::map<C2String, ComponentLoader> mComponents; ///< path -> component module
943 std::map<C2String, C2String> mComponentNameToPath; ///< name -> path
944 std::vector<std::shared_ptr<const C2Component::Traits>> mComponentList;
945
Pawin Vongmasa36653902018-11-15 00:10:25 -0800946 std::shared_ptr<C2ReflectorHelper> mReflector;
947 Interface mInterface;
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530948
949 // For testing only
950 std::vector<std::tuple<C2String,
951 C2ComponentFactory::CreateCodec2FactoryFunc,
952 C2ComponentFactory::DestroyCodec2FactoryFunc>> mCodec2FactoryFuncs;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800953};
954
955c2_status_t C2PlatformComponentStore::ComponentModule::init(
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800956 std::string libPath) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800957 ALOGV("in %s", __func__);
958 ALOGV("loading dll");
Pawin Vongmasa36653902018-11-15 00:10:25 -0800959
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530960 if(!createFactory) {
961 mLibHandle = dlopen(libPath.c_str(), RTLD_NOW|RTLD_NODELETE);
962 LOG_ALWAYS_FATAL_IF(mLibHandle == nullptr,
963 "could not dlopen %s: %s", libPath.c_str(), dlerror());
Chong Zhangf5c7ca82019-04-23 17:06:21 -0700964
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530965 createFactory =
966 (C2ComponentFactory::CreateCodec2FactoryFunc)dlsym(mLibHandle, "CreateCodec2Factory");
967 LOG_ALWAYS_FATAL_IF(createFactory == nullptr,
968 "createFactory is null in %s", libPath.c_str());
969
970 destroyFactory =
971 (C2ComponentFactory::DestroyCodec2FactoryFunc)dlsym(mLibHandle, "DestroyCodec2Factory");
972 LOG_ALWAYS_FATAL_IF(destroyFactory == nullptr,
973 "destroyFactory is null in %s", libPath.c_str());
974 }
Chong Zhangf5c7ca82019-04-23 17:06:21 -0700975
976 mComponentFactory = createFactory();
977 if (mComponentFactory == nullptr) {
978 ALOGD("could not create factory in %s", libPath.c_str());
979 mInit = C2_NO_MEMORY;
Dongwon Kang673236b2019-05-08 09:02:21 -0700980 } else {
981 mInit = C2_OK;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800982 }
983
Dongwon Kang673236b2019-05-08 09:02:21 -0700984 if (mInit != C2_OK) {
985 return mInit;
986 }
Dongwon Kange55d13c2019-04-24 11:01:49 -0700987
Pawin Vongmasa36653902018-11-15 00:10:25 -0800988 std::shared_ptr<C2ComponentInterface> intf;
989 c2_status_t res = createInterface(0, &intf);
990 if (res != C2_OK) {
991 ALOGD("failed to create interface: %d", res);
992 return mInit;
993 }
994
995 std::shared_ptr<C2Component::Traits> traits(new (std::nothrow) C2Component::Traits);
996 if (traits) {
Wonsik Kimee92b522021-02-07 21:55:31 -0800997 if (!C2InterfaceUtils::FillTraitsFromInterface(traits.get(), intf)) {
998 ALOGD("Failed to fill traits from interface");
Pawin Vongmasa36653902018-11-15 00:10:25 -0800999 return mInit;
1000 }
Lajos Molnar62d62d62019-01-31 16:26:46 -08001001
1002 // TODO: get this properly from the store during emplace
1003 switch (traits->domain) {
1004 case C2Component::DOMAIN_AUDIO:
1005 traits->rank = 8;
1006 break;
1007 default:
1008 traits->rank = 512;
1009 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001010 }
1011 mTraits = traits;
1012
1013 return mInit;
1014}
1015
1016C2PlatformComponentStore::ComponentModule::~ComponentModule() {
1017 ALOGV("in %s", __func__);
1018 if (destroyFactory && mComponentFactory) {
1019 destroyFactory(mComponentFactory);
1020 }
1021 if (mLibHandle) {
1022 ALOGV("unloading dll");
1023 dlclose(mLibHandle);
1024 }
1025}
1026
1027c2_status_t C2PlatformComponentStore::ComponentModule::createInterface(
1028 c2_node_id_t id, std::shared_ptr<C2ComponentInterface> *interface,
1029 std::function<void(::C2ComponentInterface*)> deleter) {
1030 interface->reset();
1031 if (mInit != C2_OK) {
1032 return mInit;
1033 }
1034 std::shared_ptr<ComponentModule> module = shared_from_this();
1035 c2_status_t res = mComponentFactory->createInterface(
1036 id, interface, [module, deleter](C2ComponentInterface *p) mutable {
1037 // capture module so that we ensure we still have it while deleting interface
1038 deleter(p); // delete interface first
1039 module.reset(); // remove module ref (not technically needed)
1040 });
1041 return res;
1042}
1043
1044c2_status_t C2PlatformComponentStore::ComponentModule::createComponent(
1045 c2_node_id_t id, std::shared_ptr<C2Component> *component,
1046 std::function<void(::C2Component*)> deleter) {
1047 component->reset();
1048 if (mInit != C2_OK) {
1049 return mInit;
1050 }
1051 std::shared_ptr<ComponentModule> module = shared_from_this();
1052 c2_status_t res = mComponentFactory->createComponent(
1053 id, component, [module, deleter](C2Component *p) mutable {
1054 // capture module so that we ensure we still have it while deleting component
1055 deleter(p); // delete component first
1056 module.reset(); // remove module ref (not technically needed)
1057 });
1058 return res;
1059}
1060
1061std::shared_ptr<const C2Component::Traits> C2PlatformComponentStore::ComponentModule::getTraits() {
1062 std::unique_lock<std::recursive_mutex> lock(mLock);
1063 return mTraits;
1064}
1065
1066C2PlatformComponentStore::C2PlatformComponentStore()
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001067 : mVisited(false),
1068 mReflector(std::make_shared<C2ReflectorHelper>()),
Pawin Vongmasa36653902018-11-15 00:10:25 -08001069 mInterface(mReflector) {
1070
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001071 auto emplace = [this](const char *libPath) {
1072 mComponents.emplace(libPath, libPath);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001073 };
Pawin Vongmasa36653902018-11-15 00:10:25 -08001074
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001075 // TODO: move this also into a .so so it can be updated
1076 emplace("libcodec2_soft_aacdec.so");
1077 emplace("libcodec2_soft_aacenc.so");
1078 emplace("libcodec2_soft_amrnbdec.so");
1079 emplace("libcodec2_soft_amrnbenc.so");
1080 emplace("libcodec2_soft_amrwbdec.so");
1081 emplace("libcodec2_soft_amrwbenc.so");
Ray Essickc2cc4372019-08-21 14:02:28 -07001082 //emplace("libcodec2_soft_av1dec_aom.so"); // deprecated for the gav1 implementation
1083 emplace("libcodec2_soft_av1dec_gav1.so");
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001084 emplace("libcodec2_soft_avcdec.so");
1085 emplace("libcodec2_soft_avcenc.so");
1086 emplace("libcodec2_soft_flacdec.so");
1087 emplace("libcodec2_soft_flacenc.so");
1088 emplace("libcodec2_soft_g711alawdec.so");
1089 emplace("libcodec2_soft_g711mlawdec.so");
1090 emplace("libcodec2_soft_gsmdec.so");
1091 emplace("libcodec2_soft_h263dec.so");
1092 emplace("libcodec2_soft_h263enc.so");
1093 emplace("libcodec2_soft_hevcdec.so");
Roma Kauldfe650a2018-08-02 17:48:51 +05301094 emplace("libcodec2_soft_hevcenc.so");
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001095 emplace("libcodec2_soft_mp3dec.so");
1096 emplace("libcodec2_soft_mpeg2dec.so");
1097 emplace("libcodec2_soft_mpeg4dec.so");
1098 emplace("libcodec2_soft_mpeg4enc.so");
1099 emplace("libcodec2_soft_opusdec.so");
1100 emplace("libcodec2_soft_opusenc.so");
1101 emplace("libcodec2_soft_rawdec.so");
1102 emplace("libcodec2_soft_vorbisdec.so");
1103 emplace("libcodec2_soft_vp8dec.so");
1104 emplace("libcodec2_soft_vp8enc.so");
1105 emplace("libcodec2_soft_vp9dec.so");
1106 emplace("libcodec2_soft_vp9enc.so");
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +05301107
1108}
1109
1110// For testing only
1111C2PlatformComponentStore::C2PlatformComponentStore(
1112 std::vector<std::tuple<C2String,
1113 C2ComponentFactory::CreateCodec2FactoryFunc,
1114 C2ComponentFactory::DestroyCodec2FactoryFunc>> funcs)
1115 : mVisited(false),
1116 mReflector(std::make_shared<C2ReflectorHelper>()),
1117 mInterface(mReflector),
1118 mCodec2FactoryFuncs(funcs) {
1119
1120 for(auto const& func: mCodec2FactoryFuncs) {
1121 mComponents.emplace(std::get<0>(func), func);
1122 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001123}
1124
1125c2_status_t C2PlatformComponentStore::copyBuffer(
1126 std::shared_ptr<C2GraphicBuffer> src, std::shared_ptr<C2GraphicBuffer> dst) {
1127 (void)src;
1128 (void)dst;
1129 return C2_OMITTED;
1130}
1131
1132c2_status_t C2PlatformComponentStore::query_sm(
1133 const std::vector<C2Param*> &stackParams,
1134 const std::vector<C2Param::Index> &heapParamIndices,
1135 std::vector<std::unique_ptr<C2Param>> *const heapParams) const {
1136 return mInterface.query(stackParams, heapParamIndices, C2_MAY_BLOCK, heapParams);
1137}
1138
1139c2_status_t C2PlatformComponentStore::config_sm(
1140 const std::vector<C2Param*> &params,
1141 std::vector<std::unique_ptr<C2SettingResult>> *const failures) {
1142 return mInterface.config(params, C2_MAY_BLOCK, failures);
1143}
1144
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001145void C2PlatformComponentStore::visitComponents() {
1146 std::lock_guard<std::mutex> lock(mMutex);
1147 if (mVisited) {
1148 return;
1149 }
1150 for (auto &pathAndLoader : mComponents) {
1151 const C2String &path = pathAndLoader.first;
1152 ComponentLoader &loader = pathAndLoader.second;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001153 std::shared_ptr<ComponentModule> module;
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001154 if (loader.fetchModule(&module) == C2_OK) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001155 std::shared_ptr<const C2Component::Traits> traits = module->getTraits();
1156 if (traits) {
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001157 mComponentList.push_back(traits);
1158 mComponentNameToPath.emplace(traits->name, path);
1159 for (const C2String &alias : traits->aliases) {
1160 mComponentNameToPath.emplace(alias, path);
1161 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001162 }
1163 }
1164 }
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001165 mVisited = true;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001166}
1167
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001168std::vector<std::shared_ptr<const C2Component::Traits>> C2PlatformComponentStore::listComponents() {
1169 // This method SHALL return within 500ms.
1170 visitComponents();
1171 return mComponentList;
1172}
1173
1174c2_status_t C2PlatformComponentStore::findComponent(
1175 C2String name, std::shared_ptr<ComponentModule> *module) {
1176 (*module).reset();
1177 visitComponents();
1178
1179 auto pos = mComponentNameToPath.find(name);
1180 if (pos != mComponentNameToPath.end()) {
1181 return mComponents.at(pos->second).fetchModule(module);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001182 }
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001183 return C2_NOT_FOUND;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001184}
1185
1186c2_status_t C2PlatformComponentStore::createComponent(
1187 C2String name, std::shared_ptr<C2Component> *const component) {
1188 // This method SHALL return within 100ms.
1189 component->reset();
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001190 std::shared_ptr<ComponentModule> module;
1191 c2_status_t res = findComponent(name, &module);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001192 if (res == C2_OK) {
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001193 // TODO: get a unique node ID
1194 res = module->createComponent(0, component);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001195 }
1196 return res;
1197}
1198
1199c2_status_t C2PlatformComponentStore::createInterface(
1200 C2String name, std::shared_ptr<C2ComponentInterface> *const interface) {
1201 // This method SHALL return within 100ms.
1202 interface->reset();
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001203 std::shared_ptr<ComponentModule> module;
1204 c2_status_t res = findComponent(name, &module);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001205 if (res == C2_OK) {
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001206 // TODO: get a unique node ID
1207 res = module->createInterface(0, interface);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001208 }
1209 return res;
1210}
1211
1212c2_status_t C2PlatformComponentStore::querySupportedParams_nb(
1213 std::vector<std::shared_ptr<C2ParamDescriptor>> *const params) const {
1214 return mInterface.querySupportedParams(params);
1215}
1216
1217c2_status_t C2PlatformComponentStore::querySupportedValues_sm(
1218 std::vector<C2FieldSupportedValuesQuery> &fields) const {
1219 return mInterface.querySupportedValues(fields, C2_MAY_BLOCK);
1220}
1221
1222C2String C2PlatformComponentStore::getName() const {
1223 return "android.componentStore.platform";
1224}
1225
1226std::shared_ptr<C2ParamReflector> C2PlatformComponentStore::getParamReflector() const {
1227 return mReflector;
1228}
1229
1230std::shared_ptr<C2ComponentStore> GetCodec2PlatformComponentStore() {
1231 static std::mutex mutex;
1232 static std::weak_ptr<C2ComponentStore> platformStore;
1233 std::lock_guard<std::mutex> lock(mutex);
1234 std::shared_ptr<C2ComponentStore> store = platformStore.lock();
1235 if (store == nullptr) {
1236 store = std::make_shared<C2PlatformComponentStore>();
1237 platformStore = store;
1238 }
1239 return store;
1240}
1241
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +05301242// For testing only
1243std::shared_ptr<C2ComponentStore> GetTestComponentStore(
1244 std::vector<std::tuple<C2String,
1245 C2ComponentFactory::CreateCodec2FactoryFunc,
1246 C2ComponentFactory::DestroyCodec2FactoryFunc>> funcs) {
1247 return std::shared_ptr<C2ComponentStore>(new C2PlatformComponentStore(funcs));
1248}
Pawin Vongmasa36653902018-11-15 00:10:25 -08001249} // namespace android