blob: 13c90f240c6b2eaa060613e0fa0cb7604d34b79b [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 }
304 std::shared_ptr<C2AllocatorIon> allocator;
305 {
306 std::lock_guard<std::mutex> lock(gIonAllocatorMutex);
307 allocator = gIonAllocator.lock();
308 }
309 if (allocator) {
310 UseComponentStoreForIonAllocator(allocator, store);
311 }
312}
313
314std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchIonAllocator() {
315 std::lock_guard<std::mutex> lock(gIonAllocatorMutex);
316 std::shared_ptr<C2AllocatorIon> allocator = gIonAllocator.lock();
317 if (allocator == nullptr) {
318 std::shared_ptr<C2ComponentStore> componentStore;
319 {
320 std::lock_guard<std::mutex> lock(_mComponentStoreReadLock);
321 componentStore = _mComponentStore;
322 }
323 allocator = std::make_shared<C2AllocatorIon>(C2PlatformAllocatorStore::ION);
324 UseComponentStoreForIonAllocator(allocator, componentStore);
325 gIonAllocator = allocator;
326 }
327 return allocator;
328}
329
John Stultza7002cb2020-09-04 19:02:30 +0000330std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchDmaBufAllocator() {
331 std::lock_guard<std::mutex> lock(gDmaBufAllocatorMutex);
332 std::shared_ptr<C2DmaBufAllocator> allocator = gDmaBufAllocator.lock();
333 if (allocator == nullptr) {
334 std::shared_ptr<C2ComponentStore> componentStore;
335 {
336 std::lock_guard<std::mutex> lock(_mComponentStoreReadLock);
337 componentStore = _mComponentStore;
338 }
339 allocator = std::make_shared<C2DmaBufAllocator>(C2PlatformAllocatorStore::DMABUFHEAP);
340 UseComponentStoreForDmaBufAllocator(allocator, componentStore);
341 gDmaBufAllocator = allocator;
342 }
343 return allocator;
344}
345
Pin-chih Linaa18ea52019-11-19 18:48:50 +0800346std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchBlobAllocator() {
347 static std::mutex mutex;
348 static std::weak_ptr<C2Allocator> blobAllocator;
349 std::lock_guard<std::mutex> lock(mutex);
350 std::shared_ptr<C2Allocator> allocator = blobAllocator.lock();
351 if (allocator == nullptr) {
352 allocator = std::make_shared<C2AllocatorBlob>(C2PlatformAllocatorStore::BLOB);
353 blobAllocator = allocator;
354 }
355 return allocator;
356}
357
Pawin Vongmasa36653902018-11-15 00:10:25 -0800358std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchGrallocAllocator() {
359 static std::mutex mutex;
360 static std::weak_ptr<C2Allocator> grallocAllocator;
361 std::lock_guard<std::mutex> lock(mutex);
362 std::shared_ptr<C2Allocator> allocator = grallocAllocator.lock();
363 if (allocator == nullptr) {
364 allocator = std::make_shared<C2AllocatorGralloc>(C2PlatformAllocatorStore::GRALLOC);
365 grallocAllocator = allocator;
366 }
367 return allocator;
368}
369
370std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchBufferQueueAllocator() {
371 static std::mutex mutex;
372 static std::weak_ptr<C2Allocator> grallocAllocator;
373 std::lock_guard<std::mutex> lock(mutex);
374 std::shared_ptr<C2Allocator> allocator = grallocAllocator.lock();
375 if (allocator == nullptr) {
376 allocator = std::make_shared<C2AllocatorGralloc>(
377 C2PlatformAllocatorStore::BUFFERQUEUE, true);
378 grallocAllocator = allocator;
379 }
380 return allocator;
381}
382
383namespace {
384 std::mutex gPreferredComponentStoreMutex;
385 std::shared_ptr<C2ComponentStore> gPreferredComponentStore;
386
387 std::mutex gPlatformAllocatorStoreMutex;
388 std::weak_ptr<C2PlatformAllocatorStoreImpl> gPlatformAllocatorStore;
389}
390
391std::shared_ptr<C2AllocatorStore> GetCodec2PlatformAllocatorStore() {
392 std::lock_guard<std::mutex> lock(gPlatformAllocatorStoreMutex);
393 std::shared_ptr<C2PlatformAllocatorStoreImpl> store = gPlatformAllocatorStore.lock();
394 if (store == nullptr) {
395 store = std::make_shared<C2PlatformAllocatorStoreImpl>();
396 store->setComponentStore(GetPreferredCodec2ComponentStore());
397 gPlatformAllocatorStore = store;
398 }
399 return store;
400}
401
402void SetPreferredCodec2ComponentStore(std::shared_ptr<C2ComponentStore> componentStore) {
403 static std::mutex mutex;
404 std::lock_guard<std::mutex> lock(mutex); // don't interleve set-s
405
406 // update preferred store
407 {
408 std::lock_guard<std::mutex> lock(gPreferredComponentStoreMutex);
409 gPreferredComponentStore = componentStore;
410 }
411
412 // update platform allocator's store as well if it is alive
413 std::shared_ptr<C2PlatformAllocatorStoreImpl> allocatorStore;
414 {
415 std::lock_guard<std::mutex> lock(gPlatformAllocatorStoreMutex);
416 allocatorStore = gPlatformAllocatorStore.lock();
417 }
418 if (allocatorStore) {
419 allocatorStore->setComponentStore(componentStore);
420 }
421}
422
423std::shared_ptr<C2ComponentStore> GetPreferredCodec2ComponentStore() {
424 std::lock_guard<std::mutex> lock(gPreferredComponentStoreMutex);
425 return gPreferredComponentStore ? gPreferredComponentStore : GetCodec2PlatformComponentStore();
426}
427
Pin-chih Linaa18ea52019-11-19 18:48:50 +0800428int GetCodec2PoolMask() {
429 return property_get_int32(
430 "debug.stagefright.c2-poolmask",
431 1 << C2PlatformAllocatorStore::ION |
432 1 << C2PlatformAllocatorStore::BUFFERQUEUE);
433}
434
435C2PlatformAllocatorStore::id_t GetPreferredLinearAllocatorId(int poolMask) {
436 return ((poolMask >> C2PlatformAllocatorStore::BLOB) & 1) ? C2PlatformAllocatorStore::BLOB
437 : C2PlatformAllocatorStore::ION;
438}
439
Pawin Vongmasa36653902018-11-15 00:10:25 -0800440namespace {
441
442class _C2BlockPoolCache {
443public:
444 _C2BlockPoolCache() : mBlockPoolSeqId(C2BlockPool::PLATFORM_START + 1) {}
445
446 c2_status_t _createBlockPool(
447 C2PlatformAllocatorStore::id_t allocatorId,
Wonsik Kim2fce07922021-02-11 00:16:11 -0800448 std::vector<std::shared_ptr<const C2Component>> components,
Pawin Vongmasa36653902018-11-15 00:10:25 -0800449 C2BlockPool::local_id_t poolId,
450 std::shared_ptr<C2BlockPool> *pool) {
451 std::shared_ptr<C2AllocatorStore> allocatorStore =
452 GetCodec2PlatformAllocatorStore();
453 std::shared_ptr<C2Allocator> allocator;
454 c2_status_t res = C2_NOT_FOUND;
455
Pin-chih Linaa18ea52019-11-19 18:48:50 +0800456 if (allocatorId == C2AllocatorStore::DEFAULT_LINEAR) {
457 allocatorId = GetPreferredLinearAllocatorId(GetCodec2PoolMask());
458 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800459 switch(allocatorId) {
John Stultza7002cb2020-09-04 19:02:30 +0000460 case C2PlatformAllocatorStore::ION: /* also ::DMABUFHEAP */
Pawin Vongmasa36653902018-11-15 00:10:25 -0800461 res = allocatorStore->fetchAllocator(
Pin-chih Linaa18ea52019-11-19 18:48:50 +0800462 C2PlatformAllocatorStore::ION, &allocator);
463 if (res == C2_OK) {
464 std::shared_ptr<C2BlockPool> ptr =
465 std::make_shared<C2PooledBlockPool>(
466 allocator, poolId);
467 *pool = ptr;
468 mBlockPools[poolId] = ptr;
Wonsik Kim2fce07922021-02-11 00:16:11 -0800469 mComponents[poolId].insert(
470 mComponents[poolId].end(),
471 components.begin(), components.end());
Pin-chih Linaa18ea52019-11-19 18:48:50 +0800472 }
473 break;
474 case C2PlatformAllocatorStore::BLOB:
475 res = allocatorStore->fetchAllocator(
476 C2PlatformAllocatorStore::BLOB, &allocator);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800477 if (res == C2_OK) {
478 std::shared_ptr<C2BlockPool> ptr =
479 std::make_shared<C2PooledBlockPool>(
480 allocator, poolId);
481 *pool = ptr;
482 mBlockPools[poolId] = ptr;
Wonsik Kim2fce07922021-02-11 00:16:11 -0800483 mComponents[poolId].insert(
484 mComponents[poolId].end(),
485 components.begin(), components.end());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800486 }
487 break;
488 case C2PlatformAllocatorStore::GRALLOC:
489 case C2AllocatorStore::DEFAULT_GRAPHIC:
490 res = allocatorStore->fetchAllocator(
491 C2AllocatorStore::DEFAULT_GRAPHIC, &allocator);
492 if (res == C2_OK) {
493 std::shared_ptr<C2BlockPool> ptr =
494 std::make_shared<C2PooledBlockPool>(allocator, poolId);
495 *pool = ptr;
496 mBlockPools[poolId] = ptr;
Wonsik Kim2fce07922021-02-11 00:16:11 -0800497 mComponents[poolId].insert(
498 mComponents[poolId].end(),
499 components.begin(), components.end());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800500 }
501 break;
502 case C2PlatformAllocatorStore::BUFFERQUEUE:
503 res = allocatorStore->fetchAllocator(
504 C2PlatformAllocatorStore::BUFFERQUEUE, &allocator);
505 if (res == C2_OK) {
506 std::shared_ptr<C2BlockPool> ptr =
507 std::make_shared<C2BufferQueueBlockPool>(
508 allocator, poolId);
509 *pool = ptr;
510 mBlockPools[poolId] = ptr;
Wonsik Kim2fce07922021-02-11 00:16:11 -0800511 mComponents[poolId].insert(
512 mComponents[poolId].end(),
513 components.begin(), components.end());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800514 }
515 break;
516 default:
517 // Try to create block pool from platform store plugins.
518 std::shared_ptr<C2BlockPool> ptr;
519 res = C2PlatformStorePluginLoader::GetInstance()->createBlockPool(
520 allocatorId, poolId, &ptr);
521 if (res == C2_OK) {
522 *pool = ptr;
523 mBlockPools[poolId] = ptr;
Wonsik Kim2fce07922021-02-11 00:16:11 -0800524 mComponents[poolId].insert(
525 mComponents[poolId].end(),
526 components.begin(), components.end());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800527 }
528 break;
529 }
530 return res;
531 }
532
533 c2_status_t createBlockPool(
534 C2PlatformAllocatorStore::id_t allocatorId,
Wonsik Kim2fce07922021-02-11 00:16:11 -0800535 std::vector<std::shared_ptr<const C2Component>> components,
Pawin Vongmasa36653902018-11-15 00:10:25 -0800536 std::shared_ptr<C2BlockPool> *pool) {
Wonsik Kim2fce07922021-02-11 00:16:11 -0800537 return _createBlockPool(allocatorId, components, mBlockPoolSeqId++, pool);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800538 }
539
540 bool getBlockPool(
541 C2BlockPool::local_id_t blockPoolId,
542 std::shared_ptr<const C2Component> component,
543 std::shared_ptr<C2BlockPool> *pool) {
544 // TODO: use one iterator for multiple blockpool type scalability.
545 std::shared_ptr<C2BlockPool> ptr;
546 auto it = mBlockPools.find(blockPoolId);
547 if (it != mBlockPools.end()) {
548 ptr = it->second.lock();
549 if (!ptr) {
550 mBlockPools.erase(it);
551 mComponents.erase(blockPoolId);
552 } else {
Wonsik Kim2fce07922021-02-11 00:16:11 -0800553 auto found = std::find_if(
554 mComponents[blockPoolId].begin(),
555 mComponents[blockPoolId].end(),
556 [component](const std::weak_ptr<const C2Component> &ptr) {
557 return component == ptr.lock();
558 });
559 if (found != mComponents[blockPoolId].end()) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800560 *pool = ptr;
561 return true;
562 }
563 }
564 }
565 return false;
566 }
567
568private:
569 C2BlockPool::local_id_t mBlockPoolSeqId;
570
571 std::map<C2BlockPool::local_id_t, std::weak_ptr<C2BlockPool>> mBlockPools;
Wonsik Kim2fce07922021-02-11 00:16:11 -0800572 std::map<C2BlockPool::local_id_t, std::vector<std::weak_ptr<const C2Component>>> mComponents;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800573};
574
575static std::unique_ptr<_C2BlockPoolCache> sBlockPoolCache =
576 std::make_unique<_C2BlockPoolCache>();
577static std::mutex sBlockPoolCacheMutex;
578
579} // anynymous namespace
580
581c2_status_t GetCodec2BlockPool(
582 C2BlockPool::local_id_t id, std::shared_ptr<const C2Component> component,
583 std::shared_ptr<C2BlockPool> *pool) {
584 pool->reset();
585 std::lock_guard<std::mutex> lock(sBlockPoolCacheMutex);
586 std::shared_ptr<C2AllocatorStore> allocatorStore = GetCodec2PlatformAllocatorStore();
587 std::shared_ptr<C2Allocator> allocator;
588 c2_status_t res = C2_NOT_FOUND;
589
590 if (id >= C2BlockPool::PLATFORM_START) {
591 if (sBlockPoolCache->getBlockPool(id, component, pool)) {
592 return C2_OK;
593 }
594 }
595
596 switch (id) {
597 case C2BlockPool::BASIC_LINEAR:
598 res = allocatorStore->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &allocator);
599 if (res == C2_OK) {
600 *pool = std::make_shared<C2BasicLinearBlockPool>(allocator);
601 }
602 break;
603 case C2BlockPool::BASIC_GRAPHIC:
604 res = allocatorStore->fetchAllocator(C2AllocatorStore::DEFAULT_GRAPHIC, &allocator);
605 if (res == C2_OK) {
606 *pool = std::make_shared<C2BasicGraphicBlockPool>(allocator);
607 }
608 break;
609 // TODO: remove this. this is temporary
610 case C2BlockPool::PLATFORM_START:
611 res = sBlockPoolCache->_createBlockPool(
Wonsik Kim2fce07922021-02-11 00:16:11 -0800612 C2PlatformAllocatorStore::BUFFERQUEUE, {component}, id, pool);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800613 break;
614 default:
615 break;
616 }
617 return res;
618}
619
620c2_status_t CreateCodec2BlockPool(
621 C2PlatformAllocatorStore::id_t allocatorId,
Wonsik Kim2fce07922021-02-11 00:16:11 -0800622 const std::vector<std::shared_ptr<const C2Component>> &components,
623 std::shared_ptr<C2BlockPool> *pool) {
624 pool->reset();
625
626 std::lock_guard<std::mutex> lock(sBlockPoolCacheMutex);
627 return sBlockPoolCache->createBlockPool(allocatorId, components, pool);
628}
629
630c2_status_t CreateCodec2BlockPool(
631 C2PlatformAllocatorStore::id_t allocatorId,
Pawin Vongmasa36653902018-11-15 00:10:25 -0800632 std::shared_ptr<const C2Component> component,
633 std::shared_ptr<C2BlockPool> *pool) {
634 pool->reset();
635
636 std::lock_guard<std::mutex> lock(sBlockPoolCacheMutex);
Wonsik Kim2fce07922021-02-11 00:16:11 -0800637 return sBlockPoolCache->createBlockPool(allocatorId, {component}, pool);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800638}
639
640class C2PlatformComponentStore : public C2ComponentStore {
641public:
642 virtual std::vector<std::shared_ptr<const C2Component::Traits>> listComponents() override;
643 virtual std::shared_ptr<C2ParamReflector> getParamReflector() const override;
644 virtual C2String getName() const override;
645 virtual c2_status_t querySupportedValues_sm(
646 std::vector<C2FieldSupportedValuesQuery> &fields) const override;
647 virtual c2_status_t querySupportedParams_nb(
648 std::vector<std::shared_ptr<C2ParamDescriptor>> *const params) const override;
649 virtual c2_status_t query_sm(
650 const std::vector<C2Param*> &stackParams,
651 const std::vector<C2Param::Index> &heapParamIndices,
652 std::vector<std::unique_ptr<C2Param>> *const heapParams) const override;
653 virtual c2_status_t createInterface(
654 C2String name, std::shared_ptr<C2ComponentInterface> *const interface) override;
655 virtual c2_status_t createComponent(
656 C2String name, std::shared_ptr<C2Component> *const component) override;
657 virtual c2_status_t copyBuffer(
658 std::shared_ptr<C2GraphicBuffer> src, std::shared_ptr<C2GraphicBuffer> dst) override;
659 virtual c2_status_t config_sm(
660 const std::vector<C2Param*> &params,
661 std::vector<std::unique_ptr<C2SettingResult>> *const failures) override;
662 C2PlatformComponentStore();
663
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530664 // For testing only
665 C2PlatformComponentStore(
666 std::vector<std::tuple<C2String,
667 C2ComponentFactory::CreateCodec2FactoryFunc,
668 C2ComponentFactory::DestroyCodec2FactoryFunc>>);
669
Pawin Vongmasa36653902018-11-15 00:10:25 -0800670 virtual ~C2PlatformComponentStore() override = default;
671
672private:
673
674 /**
675 * An object encapsulating a loaded component module.
676 *
677 * \todo provide a way to add traits to known components here to avoid loading the .so-s
678 * for listComponents
679 */
680 struct ComponentModule : public C2ComponentFactory,
681 public std::enable_shared_from_this<ComponentModule> {
682 virtual c2_status_t createComponent(
683 c2_node_id_t id, std::shared_ptr<C2Component> *component,
684 ComponentDeleter deleter = std::default_delete<C2Component>()) override;
685 virtual c2_status_t createInterface(
686 c2_node_id_t id, std::shared_ptr<C2ComponentInterface> *interface,
687 InterfaceDeleter deleter = std::default_delete<C2ComponentInterface>()) override;
688
689 /**
690 * \returns the traits of the component in this module.
691 */
692 std::shared_ptr<const C2Component::Traits> getTraits();
693
694 /**
695 * Creates an uninitialized component module.
696 *
697 * \param name[in] component name.
698 *
699 * \note Only used by ComponentLoader.
700 */
701 ComponentModule()
702 : mInit(C2_NO_INIT),
703 mLibHandle(nullptr),
704 createFactory(nullptr),
705 destroyFactory(nullptr),
706 mComponentFactory(nullptr) {
707 }
708
709 /**
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530710 * Creates an uninitialized component module.
711 * NOTE: For testing only
712 *
713 * \param name[in] component name.
714 *
715 * \note Only used by ComponentLoader.
716 */
717 ComponentModule(
718 C2ComponentFactory::CreateCodec2FactoryFunc createFactory,
719 C2ComponentFactory::DestroyCodec2FactoryFunc destroyFactory)
720 : mInit(C2_NO_INIT),
721 mLibHandle(nullptr),
722 createFactory(createFactory),
723 destroyFactory(destroyFactory),
724 mComponentFactory(nullptr) {
725 }
726
727 /**
Pawin Vongmasa36653902018-11-15 00:10:25 -0800728 * Initializes a component module with a given library path. Must be called exactly once.
729 *
730 * \note Only used by ComponentLoader.
731 *
Pawin Vongmasa36653902018-11-15 00:10:25 -0800732 * \param libPath[in] library path
733 *
734 * \retval C2_OK the component module has been successfully loaded
735 * \retval C2_NO_MEMORY not enough memory to loading the component module
736 * \retval C2_NOT_FOUND could not locate the component module
737 * \retval C2_CORRUPTED the component module could not be loaded (unexpected)
738 * \retval C2_REFUSED permission denied to load the component module (unexpected)
739 * \retval C2_TIMED_OUT could not load the module within the time limit (unexpected)
740 */
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800741 c2_status_t init(std::string libPath);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800742
743 virtual ~ComponentModule() override;
744
745 protected:
746 std::recursive_mutex mLock; ///< lock protecting mTraits
747 std::shared_ptr<C2Component::Traits> mTraits; ///< cached component traits
748
749 c2_status_t mInit; ///< initialization result
750
751 void *mLibHandle; ///< loaded library handle
752 C2ComponentFactory::CreateCodec2FactoryFunc createFactory; ///< loaded create function
753 C2ComponentFactory::DestroyCodec2FactoryFunc destroyFactory; ///< loaded destroy function
754 C2ComponentFactory *mComponentFactory; ///< loaded/created component factory
755 };
756
757 /**
758 * An object encapsulating a loadable component module.
759 *
760 * \todo make this also work for enumerations
761 */
762 struct ComponentLoader {
763 /**
764 * Load the component module.
765 *
766 * This method simply returns the component module if it is already currently loaded, or
767 * attempts to load it if it is not.
768 *
769 * \param module[out] pointer to the shared pointer where the loaded module shall be stored.
770 * This will be nullptr on error.
771 *
772 * \retval C2_OK the component module has been successfully loaded
773 * \retval C2_NO_MEMORY not enough memory to loading the component module
774 * \retval C2_NOT_FOUND could not locate the component module
775 * \retval C2_CORRUPTED the component module could not be loaded
776 * \retval C2_REFUSED permission denied to load the component module
777 */
778 c2_status_t fetchModule(std::shared_ptr<ComponentModule> *module) {
779 c2_status_t res = C2_OK;
780 std::lock_guard<std::mutex> lock(mMutex);
781 std::shared_ptr<ComponentModule> localModule = mModule.lock();
782 if (localModule == nullptr) {
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530783 if(mCreateFactory) {
784 // For testing only
785 localModule = std::make_shared<ComponentModule>(mCreateFactory,
786 mDestroyFactory);
787 } else {
788 localModule = std::make_shared<ComponentModule>();
789 }
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800790 res = localModule->init(mLibPath);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800791 if (res == C2_OK) {
792 mModule = localModule;
793 }
794 }
795 *module = localModule;
796 return res;
797 }
798
799 /**
800 * Creates a component loader for a specific library path (or name).
801 */
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800802 ComponentLoader(std::string libPath)
803 : mLibPath(libPath) {}
Pawin Vongmasa36653902018-11-15 00:10:25 -0800804
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530805 // For testing only
806 ComponentLoader(std::tuple<C2String,
807 C2ComponentFactory::CreateCodec2FactoryFunc,
808 C2ComponentFactory::DestroyCodec2FactoryFunc> func)
809 : mLibPath(std::get<0>(func)),
810 mCreateFactory(std::get<1>(func)),
811 mDestroyFactory(std::get<2>(func)) {}
812
Pawin Vongmasa36653902018-11-15 00:10:25 -0800813 private:
814 std::mutex mMutex; ///< mutex guarding the module
815 std::weak_ptr<ComponentModule> mModule; ///< weak reference to the loaded module
Pawin Vongmasa36653902018-11-15 00:10:25 -0800816 std::string mLibPath; ///< library path
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530817
818 // For testing only
819 C2ComponentFactory::CreateCodec2FactoryFunc mCreateFactory = nullptr;
820 C2ComponentFactory::DestroyCodec2FactoryFunc mDestroyFactory = nullptr;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800821 };
822
823 struct Interface : public C2InterfaceHelper {
824 std::shared_ptr<C2StoreIonUsageInfo> mIonUsageInfo;
John Stultza7002cb2020-09-04 19:02:30 +0000825 std::shared_ptr<C2StoreDmaBufUsageInfo> mDmaBufUsageInfo;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800826
827 Interface(std::shared_ptr<C2ReflectorHelper> reflector)
828 : C2InterfaceHelper(reflector) {
829 setDerivedInstance(this);
830
831 struct Setter {
832 static C2R setIonUsage(bool /* mayBlock */, C2P<C2StoreIonUsageInfo> &me) {
Wonsik Kimba3db192019-11-22 11:00:48 -0800833#ifdef __ANDROID_APEX__
834 static int32_t defaultHeapMask = [] {
835 int32_t heapmask = base::GetIntProperty(
836 "ro.com.android.media.swcodec.ion.heapmask", int32_t(0xFFFFFFFF));
837 ALOGD("Default ION heapmask = %d", heapmask);
838 return heapmask;
839 }();
840 static int32_t defaultFlags = [] {
841 int32_t flags = base::GetIntProperty(
842 "ro.com.android.media.swcodec.ion.flags", 0);
843 ALOGD("Default ION flags = %d", flags);
844 return flags;
845 }();
846 static uint32_t defaultAlign = [] {
847 uint32_t align = base::GetUintProperty(
848 "ro.com.android.media.swcodec.ion.align", 0u);
849 ALOGD("Default ION align = %d", align);
850 return align;
851 }();
852 me.set().heapMask = defaultHeapMask;
853 me.set().allocFlags = defaultFlags;
854 me.set().minAlignment = defaultAlign;
855#else
Pawin Vongmasa36653902018-11-15 00:10:25 -0800856 me.set().heapMask = ~0;
857 me.set().allocFlags = 0;
858 me.set().minAlignment = 0;
Wonsik Kimba3db192019-11-22 11:00:48 -0800859#endif
Pawin Vongmasa36653902018-11-15 00:10:25 -0800860 return C2R::Ok();
John Stultza7002cb2020-09-04 19:02:30 +0000861 };
862
863 static C2R setDmaBufUsage(bool /* mayBlock */, C2P<C2StoreDmaBufUsageInfo> &me) {
John Stultz9eda9bf2021-01-08 00:41:13 +0000864 long long usage = (long long)me.get().m.usage;
865 if (C2DmaBufAllocator::system_uncached_supported() &&
866 !(usage & (C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE))) {
867 strncpy(me.set().m.heapName, "system-uncached", me.v.flexCount());
868 } else {
869 strncpy(me.set().m.heapName, "system", me.v.flexCount());
870 }
John Stultza7002cb2020-09-04 19:02:30 +0000871 me.set().m.allocFlags = 0;
872 return C2R::Ok();
873 };
Pawin Vongmasa36653902018-11-15 00:10:25 -0800874 };
875
876 addParameter(
877 DefineParam(mIonUsageInfo, "ion-usage")
878 .withDefault(new C2StoreIonUsageInfo())
879 .withFields({
880 C2F(mIonUsageInfo, usage).flags({C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE}),
881 C2F(mIonUsageInfo, capacity).inRange(0, UINT32_MAX, 1024),
882 C2F(mIonUsageInfo, heapMask).any(),
883 C2F(mIonUsageInfo, allocFlags).flags({}),
884 C2F(mIonUsageInfo, minAlignment).equalTo(0)
885 })
886 .withSetter(Setter::setIonUsage)
887 .build());
John Stultza7002cb2020-09-04 19:02:30 +0000888
889 addParameter(
890 DefineParam(mDmaBufUsageInfo, "dmabuf-usage")
891 .withDefault(C2StoreDmaBufUsageInfo::AllocShared(0))
892 .withFields({
893 C2F(mDmaBufUsageInfo, m.usage).flags({C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE}),
894 C2F(mDmaBufUsageInfo, m.capacity).inRange(0, UINT32_MAX, 1024),
895 C2F(mDmaBufUsageInfo, m.allocFlags).flags({}),
896 C2F(mDmaBufUsageInfo, m.heapName).any(),
897 })
898 .withSetter(Setter::setDmaBufUsage)
899 .build());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800900 }
901 };
902
903 /**
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800904 * Retrieves the component module for a component.
Pawin Vongmasa36653902018-11-15 00:10:25 -0800905 *
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800906 * \param module pointer to a shared_pointer where the component module will be stored on
907 * success.
Pawin Vongmasa36653902018-11-15 00:10:25 -0800908 *
909 * \retval C2_OK the component loader has been successfully retrieved
910 * \retval C2_NO_MEMORY not enough memory to locate the component loader
911 * \retval C2_NOT_FOUND could not locate the component to be loaded
912 * \retval C2_CORRUPTED the component loader could not be identified due to some modules being
913 * corrupted (this can happen if the name does not refer to an already
914 * identified component but some components could not be loaded due to
915 * bad library)
916 * \retval C2_REFUSED permission denied to find the component loader for the named component
917 * (this can happen if the name does not refer to an already identified
918 * component but some components could not be loaded due to lack of
919 * permissions)
920 */
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800921 c2_status_t findComponent(C2String name, std::shared_ptr<ComponentModule> *module);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800922
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800923 /**
924 * Loads each component module and discover its contents.
925 */
926 void visitComponents();
927
928 std::mutex mMutex; ///< mutex guarding the component lists during construction
929 bool mVisited; ///< component modules visited
930 std::map<C2String, ComponentLoader> mComponents; ///< path -> component module
931 std::map<C2String, C2String> mComponentNameToPath; ///< name -> path
932 std::vector<std::shared_ptr<const C2Component::Traits>> mComponentList;
933
Pawin Vongmasa36653902018-11-15 00:10:25 -0800934 std::shared_ptr<C2ReflectorHelper> mReflector;
935 Interface mInterface;
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530936
937 // For testing only
938 std::vector<std::tuple<C2String,
939 C2ComponentFactory::CreateCodec2FactoryFunc,
940 C2ComponentFactory::DestroyCodec2FactoryFunc>> mCodec2FactoryFuncs;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800941};
942
943c2_status_t C2PlatformComponentStore::ComponentModule::init(
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800944 std::string libPath) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800945 ALOGV("in %s", __func__);
946 ALOGV("loading dll");
Pawin Vongmasa36653902018-11-15 00:10:25 -0800947
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530948 if(!createFactory) {
949 mLibHandle = dlopen(libPath.c_str(), RTLD_NOW|RTLD_NODELETE);
950 LOG_ALWAYS_FATAL_IF(mLibHandle == nullptr,
951 "could not dlopen %s: %s", libPath.c_str(), dlerror());
Chong Zhangf5c7ca82019-04-23 17:06:21 -0700952
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530953 createFactory =
954 (C2ComponentFactory::CreateCodec2FactoryFunc)dlsym(mLibHandle, "CreateCodec2Factory");
955 LOG_ALWAYS_FATAL_IF(createFactory == nullptr,
956 "createFactory is null in %s", libPath.c_str());
957
958 destroyFactory =
959 (C2ComponentFactory::DestroyCodec2FactoryFunc)dlsym(mLibHandle, "DestroyCodec2Factory");
960 LOG_ALWAYS_FATAL_IF(destroyFactory == nullptr,
961 "destroyFactory is null in %s", libPath.c_str());
962 }
Chong Zhangf5c7ca82019-04-23 17:06:21 -0700963
964 mComponentFactory = createFactory();
965 if (mComponentFactory == nullptr) {
966 ALOGD("could not create factory in %s", libPath.c_str());
967 mInit = C2_NO_MEMORY;
Dongwon Kang673236b2019-05-08 09:02:21 -0700968 } else {
969 mInit = C2_OK;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800970 }
971
Dongwon Kang673236b2019-05-08 09:02:21 -0700972 if (mInit != C2_OK) {
973 return mInit;
974 }
Dongwon Kange55d13c2019-04-24 11:01:49 -0700975
Pawin Vongmasa36653902018-11-15 00:10:25 -0800976 std::shared_ptr<C2ComponentInterface> intf;
977 c2_status_t res = createInterface(0, &intf);
978 if (res != C2_OK) {
979 ALOGD("failed to create interface: %d", res);
980 return mInit;
981 }
982
983 std::shared_ptr<C2Component::Traits> traits(new (std::nothrow) C2Component::Traits);
984 if (traits) {
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800985 traits->name = intf->getName();
Lajos Molnar62d62d62019-01-31 16:26:46 -0800986
987 C2ComponentKindSetting kind;
988 C2ComponentDomainSetting domain;
989 res = intf->query_vb({ &kind, &domain }, {}, C2_MAY_BLOCK, nullptr);
990 bool fixDomain = res != C2_OK;
991 if (res == C2_OK) {
992 traits->kind = kind.value;
993 traits->domain = domain.value;
994 } else {
995 // TODO: remove this fall-back
996 ALOGD("failed to query interface for kind and domain: %d", res);
997
998 traits->kind =
999 (traits->name.find("encoder") != std::string::npos) ? C2Component::KIND_ENCODER :
1000 (traits->name.find("decoder") != std::string::npos) ? C2Component::KIND_DECODER :
1001 C2Component::KIND_OTHER;
1002 }
1003
1004 uint32_t mediaTypeIndex =
Lajos Molnar3bb81cd2019-02-20 15:10:30 -08001005 traits->kind == C2Component::KIND_ENCODER ? C2PortMediaTypeSetting::output::PARAM_TYPE
1006 : C2PortMediaTypeSetting::input::PARAM_TYPE;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001007 std::vector<std::unique_ptr<C2Param>> params;
1008 res = intf->query_vb({}, { mediaTypeIndex }, C2_MAY_BLOCK, &params);
1009 if (res != C2_OK) {
1010 ALOGD("failed to query interface: %d", res);
1011 return mInit;
1012 }
1013 if (params.size() != 1u) {
1014 ALOGD("failed to query interface: unexpected vector size: %zu", params.size());
1015 return mInit;
1016 }
Lajos Molnar3bb81cd2019-02-20 15:10:30 -08001017 C2PortMediaTypeSetting *mediaTypeConfig = C2PortMediaTypeSetting::From(params[0].get());
Pawin Vongmasa36653902018-11-15 00:10:25 -08001018 if (mediaTypeConfig == nullptr) {
1019 ALOGD("failed to query media type");
1020 return mInit;
1021 }
Lajos Molnar62d62d62019-01-31 16:26:46 -08001022 traits->mediaType =
1023 std::string(mediaTypeConfig->m.value,
1024 strnlen(mediaTypeConfig->m.value, mediaTypeConfig->flexCount()));
Pawin Vongmasa36653902018-11-15 00:10:25 -08001025
Lajos Molnar62d62d62019-01-31 16:26:46 -08001026 if (fixDomain) {
1027 if (strncmp(traits->mediaType.c_str(), "audio/", 6) == 0) {
1028 traits->domain = C2Component::DOMAIN_AUDIO;
1029 } else if (strncmp(traits->mediaType.c_str(), "video/", 6) == 0) {
1030 traits->domain = C2Component::DOMAIN_VIDEO;
1031 } else if (strncmp(traits->mediaType.c_str(), "image/", 6) == 0) {
1032 traits->domain = C2Component::DOMAIN_IMAGE;
1033 } else {
1034 traits->domain = C2Component::DOMAIN_OTHER;
1035 }
1036 }
1037
1038 // TODO: get this properly from the store during emplace
1039 switch (traits->domain) {
1040 case C2Component::DOMAIN_AUDIO:
1041 traits->rank = 8;
1042 break;
1043 default:
1044 traits->rank = 512;
1045 }
1046
1047 params.clear();
1048 res = intf->query_vb({}, { C2ComponentAliasesSetting::PARAM_TYPE }, C2_MAY_BLOCK, &params);
1049 if (res == C2_OK && params.size() == 1u) {
1050 C2ComponentAliasesSetting *aliasesSetting =
1051 C2ComponentAliasesSetting::From(params[0].get());
1052 if (aliasesSetting) {
1053 // Split aliases on ','
1054 // This looks simpler in plain C and even std::string would still make a copy.
1055 char *aliases = ::strndup(aliasesSetting->m.value, aliasesSetting->flexCount());
1056 ALOGD("'%s' has aliases: '%s'", intf->getName().c_str(), aliases);
1057
1058 for (char *tok, *ptr, *str = aliases; (tok = ::strtok_r(str, ",", &ptr));
1059 str = nullptr) {
1060 traits->aliases.push_back(tok);
1061 ALOGD("adding alias: '%s'", tok);
1062 }
1063 free(aliases);
1064 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001065 }
1066 }
1067 mTraits = traits;
1068
1069 return mInit;
1070}
1071
1072C2PlatformComponentStore::ComponentModule::~ComponentModule() {
1073 ALOGV("in %s", __func__);
1074 if (destroyFactory && mComponentFactory) {
1075 destroyFactory(mComponentFactory);
1076 }
1077 if (mLibHandle) {
1078 ALOGV("unloading dll");
1079 dlclose(mLibHandle);
1080 }
1081}
1082
1083c2_status_t C2PlatformComponentStore::ComponentModule::createInterface(
1084 c2_node_id_t id, std::shared_ptr<C2ComponentInterface> *interface,
1085 std::function<void(::C2ComponentInterface*)> deleter) {
1086 interface->reset();
1087 if (mInit != C2_OK) {
1088 return mInit;
1089 }
1090 std::shared_ptr<ComponentModule> module = shared_from_this();
1091 c2_status_t res = mComponentFactory->createInterface(
1092 id, interface, [module, deleter](C2ComponentInterface *p) mutable {
1093 // capture module so that we ensure we still have it while deleting interface
1094 deleter(p); // delete interface first
1095 module.reset(); // remove module ref (not technically needed)
1096 });
1097 return res;
1098}
1099
1100c2_status_t C2PlatformComponentStore::ComponentModule::createComponent(
1101 c2_node_id_t id, std::shared_ptr<C2Component> *component,
1102 std::function<void(::C2Component*)> deleter) {
1103 component->reset();
1104 if (mInit != C2_OK) {
1105 return mInit;
1106 }
1107 std::shared_ptr<ComponentModule> module = shared_from_this();
1108 c2_status_t res = mComponentFactory->createComponent(
1109 id, component, [module, deleter](C2Component *p) mutable {
1110 // capture module so that we ensure we still have it while deleting component
1111 deleter(p); // delete component first
1112 module.reset(); // remove module ref (not technically needed)
1113 });
1114 return res;
1115}
1116
1117std::shared_ptr<const C2Component::Traits> C2PlatformComponentStore::ComponentModule::getTraits() {
1118 std::unique_lock<std::recursive_mutex> lock(mLock);
1119 return mTraits;
1120}
1121
1122C2PlatformComponentStore::C2PlatformComponentStore()
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001123 : mVisited(false),
1124 mReflector(std::make_shared<C2ReflectorHelper>()),
Pawin Vongmasa36653902018-11-15 00:10:25 -08001125 mInterface(mReflector) {
1126
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001127 auto emplace = [this](const char *libPath) {
1128 mComponents.emplace(libPath, libPath);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001129 };
Pawin Vongmasa36653902018-11-15 00:10:25 -08001130
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001131 // TODO: move this also into a .so so it can be updated
1132 emplace("libcodec2_soft_aacdec.so");
1133 emplace("libcodec2_soft_aacenc.so");
1134 emplace("libcodec2_soft_amrnbdec.so");
1135 emplace("libcodec2_soft_amrnbenc.so");
1136 emplace("libcodec2_soft_amrwbdec.so");
1137 emplace("libcodec2_soft_amrwbenc.so");
Ray Essickc2cc4372019-08-21 14:02:28 -07001138 //emplace("libcodec2_soft_av1dec_aom.so"); // deprecated for the gav1 implementation
1139 emplace("libcodec2_soft_av1dec_gav1.so");
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001140 emplace("libcodec2_soft_avcdec.so");
1141 emplace("libcodec2_soft_avcenc.so");
1142 emplace("libcodec2_soft_flacdec.so");
1143 emplace("libcodec2_soft_flacenc.so");
1144 emplace("libcodec2_soft_g711alawdec.so");
1145 emplace("libcodec2_soft_g711mlawdec.so");
1146 emplace("libcodec2_soft_gsmdec.so");
1147 emplace("libcodec2_soft_h263dec.so");
1148 emplace("libcodec2_soft_h263enc.so");
1149 emplace("libcodec2_soft_hevcdec.so");
Roma Kauldfe650a2018-08-02 17:48:51 +05301150 emplace("libcodec2_soft_hevcenc.so");
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001151 emplace("libcodec2_soft_mp3dec.so");
1152 emplace("libcodec2_soft_mpeg2dec.so");
1153 emplace("libcodec2_soft_mpeg4dec.so");
1154 emplace("libcodec2_soft_mpeg4enc.so");
1155 emplace("libcodec2_soft_opusdec.so");
1156 emplace("libcodec2_soft_opusenc.so");
1157 emplace("libcodec2_soft_rawdec.so");
1158 emplace("libcodec2_soft_vorbisdec.so");
1159 emplace("libcodec2_soft_vp8dec.so");
1160 emplace("libcodec2_soft_vp8enc.so");
1161 emplace("libcodec2_soft_vp9dec.so");
1162 emplace("libcodec2_soft_vp9enc.so");
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +05301163
1164}
1165
1166// For testing only
1167C2PlatformComponentStore::C2PlatformComponentStore(
1168 std::vector<std::tuple<C2String,
1169 C2ComponentFactory::CreateCodec2FactoryFunc,
1170 C2ComponentFactory::DestroyCodec2FactoryFunc>> funcs)
1171 : mVisited(false),
1172 mReflector(std::make_shared<C2ReflectorHelper>()),
1173 mInterface(mReflector),
1174 mCodec2FactoryFuncs(funcs) {
1175
1176 for(auto const& func: mCodec2FactoryFuncs) {
1177 mComponents.emplace(std::get<0>(func), func);
1178 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001179}
1180
1181c2_status_t C2PlatformComponentStore::copyBuffer(
1182 std::shared_ptr<C2GraphicBuffer> src, std::shared_ptr<C2GraphicBuffer> dst) {
1183 (void)src;
1184 (void)dst;
1185 return C2_OMITTED;
1186}
1187
1188c2_status_t C2PlatformComponentStore::query_sm(
1189 const std::vector<C2Param*> &stackParams,
1190 const std::vector<C2Param::Index> &heapParamIndices,
1191 std::vector<std::unique_ptr<C2Param>> *const heapParams) const {
1192 return mInterface.query(stackParams, heapParamIndices, C2_MAY_BLOCK, heapParams);
1193}
1194
1195c2_status_t C2PlatformComponentStore::config_sm(
1196 const std::vector<C2Param*> &params,
1197 std::vector<std::unique_ptr<C2SettingResult>> *const failures) {
1198 return mInterface.config(params, C2_MAY_BLOCK, failures);
1199}
1200
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001201void C2PlatformComponentStore::visitComponents() {
1202 std::lock_guard<std::mutex> lock(mMutex);
1203 if (mVisited) {
1204 return;
1205 }
1206 for (auto &pathAndLoader : mComponents) {
1207 const C2String &path = pathAndLoader.first;
1208 ComponentLoader &loader = pathAndLoader.second;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001209 std::shared_ptr<ComponentModule> module;
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001210 if (loader.fetchModule(&module) == C2_OK) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001211 std::shared_ptr<const C2Component::Traits> traits = module->getTraits();
1212 if (traits) {
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001213 mComponentList.push_back(traits);
1214 mComponentNameToPath.emplace(traits->name, path);
1215 for (const C2String &alias : traits->aliases) {
1216 mComponentNameToPath.emplace(alias, path);
1217 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001218 }
1219 }
1220 }
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001221 mVisited = true;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001222}
1223
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001224std::vector<std::shared_ptr<const C2Component::Traits>> C2PlatformComponentStore::listComponents() {
1225 // This method SHALL return within 500ms.
1226 visitComponents();
1227 return mComponentList;
1228}
1229
1230c2_status_t C2PlatformComponentStore::findComponent(
1231 C2String name, std::shared_ptr<ComponentModule> *module) {
1232 (*module).reset();
1233 visitComponents();
1234
1235 auto pos = mComponentNameToPath.find(name);
1236 if (pos != mComponentNameToPath.end()) {
1237 return mComponents.at(pos->second).fetchModule(module);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001238 }
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001239 return C2_NOT_FOUND;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001240}
1241
1242c2_status_t C2PlatformComponentStore::createComponent(
1243 C2String name, std::shared_ptr<C2Component> *const component) {
1244 // This method SHALL return within 100ms.
1245 component->reset();
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001246 std::shared_ptr<ComponentModule> module;
1247 c2_status_t res = findComponent(name, &module);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001248 if (res == C2_OK) {
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001249 // TODO: get a unique node ID
1250 res = module->createComponent(0, component);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001251 }
1252 return res;
1253}
1254
1255c2_status_t C2PlatformComponentStore::createInterface(
1256 C2String name, std::shared_ptr<C2ComponentInterface> *const interface) {
1257 // This method SHALL return within 100ms.
1258 interface->reset();
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001259 std::shared_ptr<ComponentModule> module;
1260 c2_status_t res = findComponent(name, &module);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001261 if (res == C2_OK) {
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001262 // TODO: get a unique node ID
1263 res = module->createInterface(0, interface);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001264 }
1265 return res;
1266}
1267
1268c2_status_t C2PlatformComponentStore::querySupportedParams_nb(
1269 std::vector<std::shared_ptr<C2ParamDescriptor>> *const params) const {
1270 return mInterface.querySupportedParams(params);
1271}
1272
1273c2_status_t C2PlatformComponentStore::querySupportedValues_sm(
1274 std::vector<C2FieldSupportedValuesQuery> &fields) const {
1275 return mInterface.querySupportedValues(fields, C2_MAY_BLOCK);
1276}
1277
1278C2String C2PlatformComponentStore::getName() const {
1279 return "android.componentStore.platform";
1280}
1281
1282std::shared_ptr<C2ParamReflector> C2PlatformComponentStore::getParamReflector() const {
1283 return mReflector;
1284}
1285
1286std::shared_ptr<C2ComponentStore> GetCodec2PlatformComponentStore() {
1287 static std::mutex mutex;
1288 static std::weak_ptr<C2ComponentStore> platformStore;
1289 std::lock_guard<std::mutex> lock(mutex);
1290 std::shared_ptr<C2ComponentStore> store = platformStore.lock();
1291 if (store == nullptr) {
1292 store = std::make_shared<C2PlatformComponentStore>();
1293 platformStore = store;
1294 }
1295 return store;
1296}
1297
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +05301298// For testing only
1299std::shared_ptr<C2ComponentStore> GetTestComponentStore(
1300 std::vector<std::tuple<C2String,
1301 C2ComponentFactory::CreateCodec2FactoryFunc,
1302 C2ComponentFactory::DestroyCodec2FactoryFunc>> funcs) {
1303 return std::shared_ptr<C2ComponentStore>(new C2PlatformComponentStore(funcs));
1304}
Pawin Vongmasa36653902018-11-15 00:10:25 -08001305} // namespace android