blob: e7fd14f8a44b3df6f3658ec11917fb49c24b6beb [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"
Steven Moreland024a6f12023-04-03 20:02:52 +000018// #define LOG_NDEBUG 0
Pawin Vongmasa36653902018-11-15 00:10:25 -080019#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>
Sungtak Leeaa71b5c2023-11-04 09:21:15 +000029#include <C2IgbaBufferPriv.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080030#include <C2PlatformStorePluginLoader.h>
31#include <C2PlatformSupport.h>
Wonsik Kim0560d602023-11-15 10:08:21 -080032#include <codec2/common/HalSelection.h>
Pin-chih Linaa18ea52019-11-19 18:48:50 +080033#include <cutils/properties.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080034#include <util/C2InterfaceHelper.h>
35
Sungtak Leeaa71b5c2023-11-04 09:21:15 +000036#include <aidl/android/hardware/media/c2/IGraphicBufferAllocator.h>
37
Pawin Vongmasa36653902018-11-15 00:10:25 -080038#include <dlfcn.h>
39#include <unistd.h> // getpagesize
40
41#include <map>
42#include <memory>
43#include <mutex>
44
Wonsik Kimba3db192019-11-22 11:00:48 -080045#ifdef __ANDROID_APEX__
46#include <android-base/properties.h>
47#endif
48
Pawin Vongmasa36653902018-11-15 00:10:25 -080049namespace android {
50
51/**
52 * Returns the preferred component store in this process to access its interface.
53 */
54std::shared_ptr<C2ComponentStore> GetPreferredCodec2ComponentStore();
55
56/**
57 * The platform allocator store provides basic allocator-types for the framework based on ion and
58 * gralloc. Allocators are not meant to be updatable.
59 *
60 * \todo Provide allocator based on ashmem
61 * \todo Move ion allocation into its HIDL or provide some mapping from memory usage to ion flags
62 * \todo Make this allocator store extendable
63 */
64class C2PlatformAllocatorStoreImpl : public C2PlatformAllocatorStore {
65public:
66 C2PlatformAllocatorStoreImpl();
67
68 virtual c2_status_t fetchAllocator(
69 id_t id, std::shared_ptr<C2Allocator> *const allocator) override;
70
71 virtual std::vector<std::shared_ptr<const C2Allocator::Traits>> listAllocators_nb()
72 const override {
73 return std::vector<std::shared_ptr<const C2Allocator::Traits>>(); /// \todo
74 }
75
76 virtual C2String getName() const override {
77 return "android.allocator-store";
78 }
79
80 void setComponentStore(std::shared_ptr<C2ComponentStore> store);
81
82 ~C2PlatformAllocatorStoreImpl() override = default;
83
84private:
Pin-chih Linaa18ea52019-11-19 18:48:50 +080085 /// returns a shared-singleton blob allocator (gralloc-backed)
86 std::shared_ptr<C2Allocator> fetchBlobAllocator();
87
Pawin Vongmasa36653902018-11-15 00:10:25 -080088 /// returns a shared-singleton ion allocator
89 std::shared_ptr<C2Allocator> fetchIonAllocator();
John Stultza7002cb2020-09-04 19:02:30 +000090 std::shared_ptr<C2Allocator> fetchDmaBufAllocator();
Pawin Vongmasa36653902018-11-15 00:10:25 -080091
92 /// returns a shared-singleton gralloc allocator
93 std::shared_ptr<C2Allocator> fetchGrallocAllocator();
94
95 /// returns a shared-singleton bufferqueue supporting gralloc allocator
96 std::shared_ptr<C2Allocator> fetchBufferQueueAllocator();
97
Sungtak Leeaa71b5c2023-11-04 09:21:15 +000098 /// returns a shared-singleton IGBA supporting AHardwareBuffer/gralloc allocator
99 std::shared_ptr<C2Allocator> fetchIgbaAllocator();
100
Pawin Vongmasa36653902018-11-15 00:10:25 -0800101 /// component store to use
102 std::mutex _mComponentStoreSetLock; // protects the entire updating _mComponentStore and its
103 // dependencies
104 std::mutex _mComponentStoreReadLock; // must protect only read/write of _mComponentStore
105 std::shared_ptr<C2ComponentStore> _mComponentStore;
106};
107
108C2PlatformAllocatorStoreImpl::C2PlatformAllocatorStoreImpl() {
109}
110
John Stultza7002cb2020-09-04 19:02:30 +0000111static bool using_ion(void) {
John Stultz3a069352021-01-09 04:11:10 +0000112 static int cached_result = []()->int {
John Stultza7002cb2020-09-04 19:02:30 +0000113 struct stat buffer;
John Stultz3a069352021-01-09 04:11:10 +0000114 int ret = (stat("/dev/ion", &buffer) == 0);
115
116 if (property_get_int32("debug.c2.use_dmabufheaps", 0)) {
117 /*
118 * Double check that the system heap is present so we
119 * can gracefully fail back to ION if we cannot satisfy
120 * the override
121 */
122 ret = (stat("/dev/dma_heap/system", &buffer) != 0);
123 if (ret)
124 ALOGE("debug.c2.use_dmabufheaps set, but no system heap. Ignoring override!");
125 else
126 ALOGD("debug.c2.use_dmabufheaps set, forcing DMABUF Heaps");
127 }
128
129 if (ret)
John Stultza7002cb2020-09-04 19:02:30 +0000130 ALOGD("Using ION\n");
131 else
132 ALOGD("Using DMABUF Heaps\n");
John Stultz3a069352021-01-09 04:11:10 +0000133 return ret;
134 }();
135
John Stultza7002cb2020-09-04 19:02:30 +0000136 return (cached_result == 1);
137}
138
Pawin Vongmasa36653902018-11-15 00:10:25 -0800139c2_status_t C2PlatformAllocatorStoreImpl::fetchAllocator(
140 id_t id, std::shared_ptr<C2Allocator> *const allocator) {
141 allocator->reset();
Pin-chih Linaa18ea52019-11-19 18:48:50 +0800142 if (id == C2AllocatorStore::DEFAULT_LINEAR) {
143 id = GetPreferredLinearAllocatorId(GetCodec2PoolMask());
144 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800145 switch (id) {
146 // TODO: should we implement a generic registry for all, and use that?
John Stultza7002cb2020-09-04 19:02:30 +0000147 case C2PlatformAllocatorStore::ION: /* also ::DMABUFHEAP */
148 if (using_ion())
149 *allocator = fetchIonAllocator();
150 else
151 *allocator = fetchDmaBufAllocator();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800152 break;
153
154 case C2PlatformAllocatorStore::GRALLOC:
155 case C2AllocatorStore::DEFAULT_GRAPHIC:
156 *allocator = fetchGrallocAllocator();
157 break;
158
159 case C2PlatformAllocatorStore::BUFFERQUEUE:
160 *allocator = fetchBufferQueueAllocator();
161 break;
162
Pin-chih Linaa18ea52019-11-19 18:48:50 +0800163 case C2PlatformAllocatorStore::BLOB:
164 *allocator = fetchBlobAllocator();
165 break;
166
Sungtak Leeaa71b5c2023-11-04 09:21:15 +0000167 case C2PlatformAllocatorStore::IGBA:
168 *allocator = fetchIgbaAllocator();
169 break;
170
Pawin Vongmasa36653902018-11-15 00:10:25 -0800171 default:
172 // Try to create allocator from platform store plugins.
173 c2_status_t res =
174 C2PlatformStorePluginLoader::GetInstance()->createAllocator(id, allocator);
175 if (res != C2_OK) {
176 return res;
177 }
178 break;
179 }
180 if (*allocator == nullptr) {
181 return C2_NO_MEMORY;
182 }
183 return C2_OK;
184}
185
186namespace {
187
188std::mutex gIonAllocatorMutex;
John Stultza7002cb2020-09-04 19:02:30 +0000189std::mutex gDmaBufAllocatorMutex;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800190std::weak_ptr<C2AllocatorIon> gIonAllocator;
John Stultza7002cb2020-09-04 19:02:30 +0000191std::weak_ptr<C2DmaBufAllocator> gDmaBufAllocator;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800192
193void UseComponentStoreForIonAllocator(
194 const std::shared_ptr<C2AllocatorIon> allocator,
195 std::shared_ptr<C2ComponentStore> store) {
196 C2AllocatorIon::UsageMapperFn mapper;
197 uint64_t minUsage = 0;
198 uint64_t maxUsage = C2MemoryUsage(C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE).expected;
199 size_t blockSize = getpagesize();
200
201 // query min and max usage as well as block size via supported values
202 C2StoreIonUsageInfo usageInfo;
203 std::vector<C2FieldSupportedValuesQuery> query = {
204 C2FieldSupportedValuesQuery::Possible(C2ParamField::Make(usageInfo, usageInfo.usage)),
205 C2FieldSupportedValuesQuery::Possible(C2ParamField::Make(usageInfo, usageInfo.capacity)),
206 };
207 c2_status_t res = store->querySupportedValues_sm(query);
208 if (res == C2_OK) {
209 if (query[0].status == C2_OK) {
210 const C2FieldSupportedValues &fsv = query[0].values;
211 if (fsv.type == C2FieldSupportedValues::FLAGS && !fsv.values.empty()) {
212 minUsage = fsv.values[0].u64;
213 maxUsage = 0;
214 for (C2Value::Primitive v : fsv.values) {
215 maxUsage |= v.u64;
216 }
217 }
218 }
219 if (query[1].status == C2_OK) {
220 const C2FieldSupportedValues &fsv = query[1].values;
221 if (fsv.type == C2FieldSupportedValues::RANGE && fsv.range.step.u32 > 0) {
222 blockSize = fsv.range.step.u32;
223 }
224 }
225
226 mapper = [store](C2MemoryUsage usage, size_t capacity,
227 size_t *align, unsigned *heapMask, unsigned *flags) -> c2_status_t {
228 if (capacity > UINT32_MAX) {
229 return C2_BAD_VALUE;
230 }
231 C2StoreIonUsageInfo usageInfo = { usage.expected, capacity };
232 std::vector<std::unique_ptr<C2SettingResult>> failures; // TODO: remove
233 c2_status_t res = store->config_sm({&usageInfo}, &failures);
234 if (res == C2_OK) {
235 *align = usageInfo.minAlignment;
236 *heapMask = usageInfo.heapMask;
237 *flags = usageInfo.allocFlags;
238 }
239 return res;
240 };
241 }
242
243 allocator->setUsageMapper(mapper, minUsage, maxUsage, blockSize);
244}
245
John Stultza7002cb2020-09-04 19:02:30 +0000246void UseComponentStoreForDmaBufAllocator(const std::shared_ptr<C2DmaBufAllocator> allocator,
247 std::shared_ptr<C2ComponentStore> store) {
248 C2DmaBufAllocator::UsageMapperFn mapper;
249 const size_t maxHeapNameLen = 128;
250 uint64_t minUsage = 0;
251 uint64_t maxUsage = C2MemoryUsage(C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE).expected;
252 size_t blockSize = getpagesize();
253
254 // query min and max usage as well as block size via supported values
255 std::unique_ptr<C2StoreDmaBufUsageInfo> usageInfo;
256 usageInfo = C2StoreDmaBufUsageInfo::AllocUnique(maxHeapNameLen);
257
258 std::vector<C2FieldSupportedValuesQuery> query = {
259 C2FieldSupportedValuesQuery::Possible(C2ParamField::Make(*usageInfo, usageInfo->m.usage)),
260 C2FieldSupportedValuesQuery::Possible(
261 C2ParamField::Make(*usageInfo, usageInfo->m.capacity)),
262 };
263 c2_status_t res = store->querySupportedValues_sm(query);
264 if (res == C2_OK) {
265 if (query[0].status == C2_OK) {
266 const C2FieldSupportedValues& fsv = query[0].values;
267 if (fsv.type == C2FieldSupportedValues::FLAGS && !fsv.values.empty()) {
268 minUsage = fsv.values[0].u64;
269 maxUsage = 0;
270 for (C2Value::Primitive v : fsv.values) {
271 maxUsage |= v.u64;
272 }
273 }
274 }
275 if (query[1].status == C2_OK) {
276 const C2FieldSupportedValues& fsv = query[1].values;
277 if (fsv.type == C2FieldSupportedValues::RANGE && fsv.range.step.u32 > 0) {
278 blockSize = fsv.range.step.u32;
279 }
280 }
281
282 mapper = [store](C2MemoryUsage usage, size_t capacity, C2String* heapName,
283 unsigned* flags) -> c2_status_t {
284 if (capacity > UINT32_MAX) {
285 return C2_BAD_VALUE;
286 }
287
288 std::unique_ptr<C2StoreDmaBufUsageInfo> usageInfo;
289 usageInfo = C2StoreDmaBufUsageInfo::AllocUnique(maxHeapNameLen, usage.expected, capacity);
290 std::vector<std::unique_ptr<C2SettingResult>> failures; // TODO: remove
291
292 c2_status_t res = store->config_sm({&*usageInfo}, &failures);
293 if (res == C2_OK) {
294 *heapName = C2String(usageInfo->m.heapName);
295 *flags = usageInfo->m.allocFlags;
296 }
297
298 return res;
299 };
300 }
301
302 allocator->setUsageMapper(mapper, minUsage, maxUsage, blockSize);
303}
304
Pawin Vongmasa36653902018-11-15 00:10:25 -0800305}
306
307void C2PlatformAllocatorStoreImpl::setComponentStore(std::shared_ptr<C2ComponentStore> store) {
308 // technically this set lock is not needed, but is here for safety in case we add more
309 // getter orders
310 std::lock_guard<std::mutex> lock(_mComponentStoreSetLock);
311 {
312 std::lock_guard<std::mutex> lock(_mComponentStoreReadLock);
313 _mComponentStore = store;
314 }
Sungtak Lee32429192022-01-07 15:18:51 -0800315 std::shared_ptr<C2AllocatorIon> ionAllocator;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800316 {
317 std::lock_guard<std::mutex> lock(gIonAllocatorMutex);
Sungtak Lee32429192022-01-07 15:18:51 -0800318 ionAllocator = gIonAllocator.lock();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800319 }
Sungtak Lee32429192022-01-07 15:18:51 -0800320 if (ionAllocator) {
321 UseComponentStoreForIonAllocator(ionAllocator, store);
322 }
323 std::shared_ptr<C2DmaBufAllocator> dmaAllocator;
324 {
325 std::lock_guard<std::mutex> lock(gDmaBufAllocatorMutex);
326 dmaAllocator = gDmaBufAllocator.lock();
327 }
328 if (dmaAllocator) {
329 UseComponentStoreForDmaBufAllocator(dmaAllocator, store);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800330 }
331}
332
333std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchIonAllocator() {
334 std::lock_guard<std::mutex> lock(gIonAllocatorMutex);
335 std::shared_ptr<C2AllocatorIon> allocator = gIonAllocator.lock();
336 if (allocator == nullptr) {
337 std::shared_ptr<C2ComponentStore> componentStore;
338 {
339 std::lock_guard<std::mutex> lock(_mComponentStoreReadLock);
340 componentStore = _mComponentStore;
341 }
342 allocator = std::make_shared<C2AllocatorIon>(C2PlatformAllocatorStore::ION);
343 UseComponentStoreForIonAllocator(allocator, componentStore);
344 gIonAllocator = allocator;
345 }
346 return allocator;
347}
348
John Stultza7002cb2020-09-04 19:02:30 +0000349std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchDmaBufAllocator() {
350 std::lock_guard<std::mutex> lock(gDmaBufAllocatorMutex);
351 std::shared_ptr<C2DmaBufAllocator> allocator = gDmaBufAllocator.lock();
352 if (allocator == nullptr) {
353 std::shared_ptr<C2ComponentStore> componentStore;
354 {
355 std::lock_guard<std::mutex> lock(_mComponentStoreReadLock);
356 componentStore = _mComponentStore;
357 }
358 allocator = std::make_shared<C2DmaBufAllocator>(C2PlatformAllocatorStore::DMABUFHEAP);
359 UseComponentStoreForDmaBufAllocator(allocator, componentStore);
360 gDmaBufAllocator = allocator;
361 }
362 return allocator;
363}
364
Pin-chih Linaa18ea52019-11-19 18:48:50 +0800365std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchBlobAllocator() {
366 static std::mutex mutex;
367 static std::weak_ptr<C2Allocator> blobAllocator;
368 std::lock_guard<std::mutex> lock(mutex);
369 std::shared_ptr<C2Allocator> allocator = blobAllocator.lock();
370 if (allocator == nullptr) {
371 allocator = std::make_shared<C2AllocatorBlob>(C2PlatformAllocatorStore::BLOB);
372 blobAllocator = allocator;
373 }
374 return allocator;
375}
376
Pawin Vongmasa36653902018-11-15 00:10:25 -0800377std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchGrallocAllocator() {
378 static std::mutex mutex;
379 static std::weak_ptr<C2Allocator> grallocAllocator;
380 std::lock_guard<std::mutex> lock(mutex);
381 std::shared_ptr<C2Allocator> allocator = grallocAllocator.lock();
382 if (allocator == nullptr) {
383 allocator = std::make_shared<C2AllocatorGralloc>(C2PlatformAllocatorStore::GRALLOC);
384 grallocAllocator = allocator;
385 }
386 return allocator;
387}
388
389std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchBufferQueueAllocator() {
390 static std::mutex mutex;
391 static std::weak_ptr<C2Allocator> grallocAllocator;
392 std::lock_guard<std::mutex> lock(mutex);
393 std::shared_ptr<C2Allocator> allocator = grallocAllocator.lock();
394 if (allocator == nullptr) {
395 allocator = std::make_shared<C2AllocatorGralloc>(
396 C2PlatformAllocatorStore::BUFFERQUEUE, true);
397 grallocAllocator = allocator;
398 }
399 return allocator;
400}
401
Sungtak Leeaa71b5c2023-11-04 09:21:15 +0000402std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchIgbaAllocator() {
403 static std::mutex mutex;
404 static std::weak_ptr<C2Allocator> ahwbAllocator;
405 std::lock_guard<std::mutex> lock(mutex);
406 std::shared_ptr<C2Allocator> allocator = ahwbAllocator.lock();
407 if (allocator == nullptr) {
408 allocator = std::make_shared<C2AllocatorAhwb>(C2PlatformAllocatorStore::IGBA);
409 ahwbAllocator = allocator;
410 }
411 return allocator;
412}
413
Pawin Vongmasa36653902018-11-15 00:10:25 -0800414namespace {
415 std::mutex gPreferredComponentStoreMutex;
416 std::shared_ptr<C2ComponentStore> gPreferredComponentStore;
417
418 std::mutex gPlatformAllocatorStoreMutex;
419 std::weak_ptr<C2PlatformAllocatorStoreImpl> gPlatformAllocatorStore;
420}
421
422std::shared_ptr<C2AllocatorStore> GetCodec2PlatformAllocatorStore() {
423 std::lock_guard<std::mutex> lock(gPlatformAllocatorStoreMutex);
424 std::shared_ptr<C2PlatformAllocatorStoreImpl> store = gPlatformAllocatorStore.lock();
425 if (store == nullptr) {
426 store = std::make_shared<C2PlatformAllocatorStoreImpl>();
427 store->setComponentStore(GetPreferredCodec2ComponentStore());
428 gPlatformAllocatorStore = store;
429 }
430 return store;
431}
432
433void SetPreferredCodec2ComponentStore(std::shared_ptr<C2ComponentStore> componentStore) {
434 static std::mutex mutex;
435 std::lock_guard<std::mutex> lock(mutex); // don't interleve set-s
436
437 // update preferred store
438 {
439 std::lock_guard<std::mutex> lock(gPreferredComponentStoreMutex);
440 gPreferredComponentStore = componentStore;
441 }
442
443 // update platform allocator's store as well if it is alive
444 std::shared_ptr<C2PlatformAllocatorStoreImpl> allocatorStore;
445 {
446 std::lock_guard<std::mutex> lock(gPlatformAllocatorStoreMutex);
447 allocatorStore = gPlatformAllocatorStore.lock();
448 }
449 if (allocatorStore) {
450 allocatorStore->setComponentStore(componentStore);
451 }
452}
453
454std::shared_ptr<C2ComponentStore> GetPreferredCodec2ComponentStore() {
455 std::lock_guard<std::mutex> lock(gPreferredComponentStoreMutex);
456 return gPreferredComponentStore ? gPreferredComponentStore : GetCodec2PlatformComponentStore();
457}
458
Pin-chih Linaa18ea52019-11-19 18:48:50 +0800459int GetCodec2PoolMask() {
460 return property_get_int32(
461 "debug.stagefright.c2-poolmask",
462 1 << C2PlatformAllocatorStore::ION |
463 1 << C2PlatformAllocatorStore::BUFFERQUEUE);
464}
465
466C2PlatformAllocatorStore::id_t GetPreferredLinearAllocatorId(int poolMask) {
467 return ((poolMask >> C2PlatformAllocatorStore::BLOB) & 1) ? C2PlatformAllocatorStore::BLOB
468 : C2PlatformAllocatorStore::ION;
469}
470
Pawin Vongmasa36653902018-11-15 00:10:25 -0800471namespace {
472
Wonsik Kim0560d602023-11-15 10:08:21 -0800473static C2PooledBlockPool::BufferPoolVer GetBufferPoolVer() {
474 static C2PooledBlockPool::BufferPoolVer sVer =
475 IsCodec2AidlHalSelected() ? C2PooledBlockPool::VER_AIDL2 : C2PooledBlockPool::VER_HIDL;
476 return sVer;
477}
478
Pawin Vongmasa36653902018-11-15 00:10:25 -0800479class _C2BlockPoolCache {
480public:
481 _C2BlockPoolCache() : mBlockPoolSeqId(C2BlockPool::PLATFORM_START + 1) {}
482
Wonsik Kim17911e32021-08-26 13:57:02 -0700483private:
Pawin Vongmasa36653902018-11-15 00:10:25 -0800484 c2_status_t _createBlockPool(
Sungtak Leeaa71b5c2023-11-04 09:21:15 +0000485 C2PlatformAllocatorDesc &allocatorParam,
Wonsik Kim2fce07922021-02-11 00:16:11 -0800486 std::vector<std::shared_ptr<const C2Component>> components,
Pawin Vongmasa36653902018-11-15 00:10:25 -0800487 C2BlockPool::local_id_t poolId,
488 std::shared_ptr<C2BlockPool> *pool) {
489 std::shared_ptr<C2AllocatorStore> allocatorStore =
490 GetCodec2PlatformAllocatorStore();
Sungtak Leeaa71b5c2023-11-04 09:21:15 +0000491 C2PlatformAllocatorStore::id_t allocatorId = allocatorParam.allocatorId;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800492 std::shared_ptr<C2Allocator> allocator;
493 c2_status_t res = C2_NOT_FOUND;
494
Pin-chih Linaa18ea52019-11-19 18:48:50 +0800495 if (allocatorId == C2AllocatorStore::DEFAULT_LINEAR) {
496 allocatorId = GetPreferredLinearAllocatorId(GetCodec2PoolMask());
497 }
Wonsik Kim17911e32021-08-26 13:57:02 -0700498 auto deleter = [this, poolId](C2BlockPool *pool) {
499 std::unique_lock lock(mMutex);
500 mBlockPools.erase(poolId);
501 mComponents.erase(poolId);
502 delete pool;
503 };
Pawin Vongmasa36653902018-11-15 00:10:25 -0800504 switch(allocatorId) {
John Stultza7002cb2020-09-04 19:02:30 +0000505 case C2PlatformAllocatorStore::ION: /* also ::DMABUFHEAP */
Pawin Vongmasa36653902018-11-15 00:10:25 -0800506 res = allocatorStore->fetchAllocator(
Pin-chih Linaa18ea52019-11-19 18:48:50 +0800507 C2PlatformAllocatorStore::ION, &allocator);
508 if (res == C2_OK) {
Wonsik Kim17911e32021-08-26 13:57:02 -0700509 std::shared_ptr<C2BlockPool> ptr(
Wonsik Kim0560d602023-11-15 10:08:21 -0800510 new C2PooledBlockPool(allocator, poolId, GetBufferPoolVer()), deleter);
Pin-chih Linaa18ea52019-11-19 18:48:50 +0800511 *pool = ptr;
512 mBlockPools[poolId] = ptr;
Wonsik Kim2fce07922021-02-11 00:16:11 -0800513 mComponents[poolId].insert(
514 mComponents[poolId].end(),
515 components.begin(), components.end());
Pin-chih Linaa18ea52019-11-19 18:48:50 +0800516 }
517 break;
518 case C2PlatformAllocatorStore::BLOB:
519 res = allocatorStore->fetchAllocator(
520 C2PlatformAllocatorStore::BLOB, &allocator);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800521 if (res == C2_OK) {
Wonsik Kim17911e32021-08-26 13:57:02 -0700522 std::shared_ptr<C2BlockPool> ptr(
Wonsik Kim0560d602023-11-15 10:08:21 -0800523 new C2PooledBlockPool(allocator, poolId, GetBufferPoolVer()), deleter);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800524 *pool = ptr;
525 mBlockPools[poolId] = ptr;
Wonsik Kim2fce07922021-02-11 00:16:11 -0800526 mComponents[poolId].insert(
527 mComponents[poolId].end(),
528 components.begin(), components.end());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800529 }
530 break;
531 case C2PlatformAllocatorStore::GRALLOC:
532 case C2AllocatorStore::DEFAULT_GRAPHIC:
533 res = allocatorStore->fetchAllocator(
534 C2AllocatorStore::DEFAULT_GRAPHIC, &allocator);
535 if (res == C2_OK) {
Wonsik Kim17911e32021-08-26 13:57:02 -0700536 std::shared_ptr<C2BlockPool> ptr(
Wonsik Kim0560d602023-11-15 10:08:21 -0800537 new C2PooledBlockPool(allocator, poolId, GetBufferPoolVer()), deleter);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800538 *pool = ptr;
539 mBlockPools[poolId] = ptr;
Wonsik Kim2fce07922021-02-11 00:16:11 -0800540 mComponents[poolId].insert(
541 mComponents[poolId].end(),
542 components.begin(), components.end());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800543 }
544 break;
545 case C2PlatformAllocatorStore::BUFFERQUEUE:
546 res = allocatorStore->fetchAllocator(
547 C2PlatformAllocatorStore::BUFFERQUEUE, &allocator);
548 if (res == C2_OK) {
Wonsik Kim17911e32021-08-26 13:57:02 -0700549 std::shared_ptr<C2BlockPool> ptr(
550 new C2BufferQueueBlockPool(allocator, poolId), deleter);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800551 *pool = ptr;
552 mBlockPools[poolId] = ptr;
Wonsik Kim2fce07922021-02-11 00:16:11 -0800553 mComponents[poolId].insert(
554 mComponents[poolId].end(),
555 components.begin(), components.end());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800556 }
557 break;
Sungtak Leeaa71b5c2023-11-04 09:21:15 +0000558 case C2PlatformAllocatorStore::IGBA:
559 res = allocatorStore->fetchAllocator(
560 C2PlatformAllocatorStore::IGBA, &allocator);
561 if (res == C2_OK) {
562 std::shared_ptr<C2BlockPool> ptr(
563 new C2IgbaBlockPool(allocator,
564 allocatorParam.igba,
565 std::move(allocatorParam.waitableFd),
566 poolId), deleter);
567 *pool = ptr;
568 mBlockPools[poolId] = ptr;
569 mComponents[poolId].insert(
570 mComponents[poolId].end(),
571 components.begin(), components.end());
572 }
573 break;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800574 default:
575 // Try to create block pool from platform store plugins.
576 std::shared_ptr<C2BlockPool> ptr;
577 res = C2PlatformStorePluginLoader::GetInstance()->createBlockPool(
Wonsik Kim17911e32021-08-26 13:57:02 -0700578 allocatorId, poolId, &ptr, deleter);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800579 if (res == C2_OK) {
580 *pool = ptr;
581 mBlockPools[poolId] = ptr;
Wonsik Kim2fce07922021-02-11 00:16:11 -0800582 mComponents[poolId].insert(
583 mComponents[poolId].end(),
584 components.begin(), components.end());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800585 }
586 break;
587 }
588 return res;
589 }
590
Wonsik Kim17911e32021-08-26 13:57:02 -0700591public:
Pawin Vongmasa36653902018-11-15 00:10:25 -0800592 c2_status_t createBlockPool(
593 C2PlatformAllocatorStore::id_t allocatorId,
Wonsik Kim2fce07922021-02-11 00:16:11 -0800594 std::vector<std::shared_ptr<const C2Component>> components,
Pawin Vongmasa36653902018-11-15 00:10:25 -0800595 std::shared_ptr<C2BlockPool> *pool) {
Sungtak Leeaa71b5c2023-11-04 09:21:15 +0000596 C2PlatformAllocatorDesc allocator;
597 allocator.allocatorId = allocatorId;
598 return createBlockPool(allocator, components, pool);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800599 }
600
Sungtak Leeaa71b5c2023-11-04 09:21:15 +0000601 c2_status_t createBlockPool(
602 C2PlatformAllocatorDesc &allocator,
603 std::vector<std::shared_ptr<const C2Component>> components,
604 std::shared_ptr<C2BlockPool> *pool) {
605 std::unique_lock lock(mMutex);
606 return _createBlockPool(allocator, components, mBlockPoolSeqId++, pool);
607 }
608
609
Wonsik Kim17911e32021-08-26 13:57:02 -0700610 c2_status_t getBlockPool(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800611 C2BlockPool::local_id_t blockPoolId,
612 std::shared_ptr<const C2Component> component,
613 std::shared_ptr<C2BlockPool> *pool) {
Wonsik Kim17911e32021-08-26 13:57:02 -0700614 std::unique_lock lock(mMutex);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800615 // TODO: use one iterator for multiple blockpool type scalability.
616 std::shared_ptr<C2BlockPool> ptr;
617 auto it = mBlockPools.find(blockPoolId);
618 if (it != mBlockPools.end()) {
619 ptr = it->second.lock();
620 if (!ptr) {
621 mBlockPools.erase(it);
622 mComponents.erase(blockPoolId);
623 } else {
Wonsik Kim2fce07922021-02-11 00:16:11 -0800624 auto found = std::find_if(
625 mComponents[blockPoolId].begin(),
626 mComponents[blockPoolId].end(),
627 [component](const std::weak_ptr<const C2Component> &ptr) {
628 return component == ptr.lock();
629 });
630 if (found != mComponents[blockPoolId].end()) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800631 *pool = ptr;
Wonsik Kim17911e32021-08-26 13:57:02 -0700632 return C2_OK;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800633 }
634 }
635 }
Wonsik Kim17911e32021-08-26 13:57:02 -0700636 // TODO: remove this. this is temporary
637 if (blockPoolId == C2BlockPool::PLATFORM_START) {
Sungtak Leeaa71b5c2023-11-04 09:21:15 +0000638 C2PlatformAllocatorDesc allocator;
639 allocator.allocatorId = C2PlatformAllocatorStore::BUFFERQUEUE;
Wonsik Kim17911e32021-08-26 13:57:02 -0700640 return _createBlockPool(
Sungtak Leeaa71b5c2023-11-04 09:21:15 +0000641 allocator, {component}, blockPoolId, pool);
Wonsik Kim17911e32021-08-26 13:57:02 -0700642 }
643 return C2_NOT_FOUND;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800644 }
645
646private:
Wonsik Kim17911e32021-08-26 13:57:02 -0700647 // Deleter needs to hold this mutex, and there is a small chance that deleter
648 // is invoked while the mutex is held.
649 std::recursive_mutex mMutex;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800650 C2BlockPool::local_id_t mBlockPoolSeqId;
651
652 std::map<C2BlockPool::local_id_t, std::weak_ptr<C2BlockPool>> mBlockPools;
Wonsik Kim2fce07922021-02-11 00:16:11 -0800653 std::map<C2BlockPool::local_id_t, std::vector<std::weak_ptr<const C2Component>>> mComponents;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800654};
655
656static std::unique_ptr<_C2BlockPoolCache> sBlockPoolCache =
657 std::make_unique<_C2BlockPoolCache>();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800658
659} // anynymous namespace
660
661c2_status_t GetCodec2BlockPool(
662 C2BlockPool::local_id_t id, std::shared_ptr<const C2Component> component,
663 std::shared_ptr<C2BlockPool> *pool) {
664 pool->reset();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800665 std::shared_ptr<C2AllocatorStore> allocatorStore = GetCodec2PlatformAllocatorStore();
666 std::shared_ptr<C2Allocator> allocator;
667 c2_status_t res = C2_NOT_FOUND;
668
669 if (id >= C2BlockPool::PLATFORM_START) {
Wonsik Kim17911e32021-08-26 13:57:02 -0700670 return sBlockPoolCache->getBlockPool(id, component, pool);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800671 }
672
673 switch (id) {
674 case C2BlockPool::BASIC_LINEAR:
675 res = allocatorStore->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &allocator);
676 if (res == C2_OK) {
677 *pool = std::make_shared<C2BasicLinearBlockPool>(allocator);
678 }
679 break;
680 case C2BlockPool::BASIC_GRAPHIC:
681 res = allocatorStore->fetchAllocator(C2AllocatorStore::DEFAULT_GRAPHIC, &allocator);
682 if (res == C2_OK) {
683 *pool = std::make_shared<C2BasicGraphicBlockPool>(allocator);
684 }
685 break;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800686 default:
687 break;
688 }
689 return res;
690}
691
692c2_status_t CreateCodec2BlockPool(
693 C2PlatformAllocatorStore::id_t allocatorId,
Wonsik Kim2fce07922021-02-11 00:16:11 -0800694 const std::vector<std::shared_ptr<const C2Component>> &components,
695 std::shared_ptr<C2BlockPool> *pool) {
696 pool->reset();
697
Sungtak Leeaa71b5c2023-11-04 09:21:15 +0000698 C2PlatformAllocatorDesc allocator;
699 allocator.allocatorId = allocatorId;
700 return sBlockPoolCache->createBlockPool(allocator, components, pool);
Wonsik Kim2fce07922021-02-11 00:16:11 -0800701}
702
703c2_status_t CreateCodec2BlockPool(
704 C2PlatformAllocatorStore::id_t allocatorId,
Pawin Vongmasa36653902018-11-15 00:10:25 -0800705 std::shared_ptr<const C2Component> component,
706 std::shared_ptr<C2BlockPool> *pool) {
707 pool->reset();
708
Sungtak Leeaa71b5c2023-11-04 09:21:15 +0000709 C2PlatformAllocatorDesc allocator;
710 allocator.allocatorId = allocatorId;
711 return sBlockPoolCache->createBlockPool(allocator, {component}, pool);
712}
713
714c2_status_t CreateCodec2BlockPool(
715 C2PlatformAllocatorDesc &allocator,
716 const std::vector<std::shared_ptr<const C2Component>> &components,
717 std::shared_ptr<C2BlockPool> *pool) {
718 pool->reset();
719
720 return sBlockPoolCache->createBlockPool(allocator, components, pool);
721}
722
723c2_status_t CreateCodec2BlockPool(
724 C2PlatformAllocatorDesc &allocator,
725 std::shared_ptr<const C2Component> component,
726 std::shared_ptr<C2BlockPool> *pool) {
727 pool->reset();
728
729 return sBlockPoolCache->createBlockPool(allocator, {component}, pool);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800730}
731
732class C2PlatformComponentStore : public C2ComponentStore {
733public:
734 virtual std::vector<std::shared_ptr<const C2Component::Traits>> listComponents() override;
735 virtual std::shared_ptr<C2ParamReflector> getParamReflector() const override;
736 virtual C2String getName() const override;
737 virtual c2_status_t querySupportedValues_sm(
738 std::vector<C2FieldSupportedValuesQuery> &fields) const override;
739 virtual c2_status_t querySupportedParams_nb(
740 std::vector<std::shared_ptr<C2ParamDescriptor>> *const params) const override;
741 virtual c2_status_t query_sm(
742 const std::vector<C2Param*> &stackParams,
743 const std::vector<C2Param::Index> &heapParamIndices,
744 std::vector<std::unique_ptr<C2Param>> *const heapParams) const override;
745 virtual c2_status_t createInterface(
746 C2String name, std::shared_ptr<C2ComponentInterface> *const interface) override;
747 virtual c2_status_t createComponent(
748 C2String name, std::shared_ptr<C2Component> *const component) override;
749 virtual c2_status_t copyBuffer(
750 std::shared_ptr<C2GraphicBuffer> src, std::shared_ptr<C2GraphicBuffer> dst) override;
751 virtual c2_status_t config_sm(
752 const std::vector<C2Param*> &params,
753 std::vector<std::unique_ptr<C2SettingResult>> *const failures) override;
754 C2PlatformComponentStore();
755
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530756 // For testing only
757 C2PlatformComponentStore(
758 std::vector<std::tuple<C2String,
759 C2ComponentFactory::CreateCodec2FactoryFunc,
760 C2ComponentFactory::DestroyCodec2FactoryFunc>>);
761
Pawin Vongmasa36653902018-11-15 00:10:25 -0800762 virtual ~C2PlatformComponentStore() override = default;
763
764private:
765
766 /**
767 * An object encapsulating a loaded component module.
768 *
769 * \todo provide a way to add traits to known components here to avoid loading the .so-s
770 * for listComponents
771 */
772 struct ComponentModule : public C2ComponentFactory,
773 public std::enable_shared_from_this<ComponentModule> {
774 virtual c2_status_t createComponent(
775 c2_node_id_t id, std::shared_ptr<C2Component> *component,
776 ComponentDeleter deleter = std::default_delete<C2Component>()) override;
777 virtual c2_status_t createInterface(
778 c2_node_id_t id, std::shared_ptr<C2ComponentInterface> *interface,
779 InterfaceDeleter deleter = std::default_delete<C2ComponentInterface>()) override;
780
781 /**
782 * \returns the traits of the component in this module.
783 */
784 std::shared_ptr<const C2Component::Traits> getTraits();
785
786 /**
787 * Creates an uninitialized component module.
788 *
789 * \param name[in] component name.
790 *
791 * \note Only used by ComponentLoader.
792 */
793 ComponentModule()
794 : mInit(C2_NO_INIT),
795 mLibHandle(nullptr),
796 createFactory(nullptr),
797 destroyFactory(nullptr),
798 mComponentFactory(nullptr) {
799 }
800
801 /**
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530802 * Creates an uninitialized component module.
803 * NOTE: For testing only
804 *
805 * \param name[in] component name.
806 *
807 * \note Only used by ComponentLoader.
808 */
809 ComponentModule(
810 C2ComponentFactory::CreateCodec2FactoryFunc createFactory,
811 C2ComponentFactory::DestroyCodec2FactoryFunc destroyFactory)
812 : mInit(C2_NO_INIT),
813 mLibHandle(nullptr),
814 createFactory(createFactory),
815 destroyFactory(destroyFactory),
816 mComponentFactory(nullptr) {
817 }
818
819 /**
Pawin Vongmasa36653902018-11-15 00:10:25 -0800820 * Initializes a component module with a given library path. Must be called exactly once.
821 *
822 * \note Only used by ComponentLoader.
823 *
Pawin Vongmasa36653902018-11-15 00:10:25 -0800824 * \param libPath[in] library path
825 *
826 * \retval C2_OK the component module has been successfully loaded
827 * \retval C2_NO_MEMORY not enough memory to loading the component module
828 * \retval C2_NOT_FOUND could not locate the component module
829 * \retval C2_CORRUPTED the component module could not be loaded (unexpected)
830 * \retval C2_REFUSED permission denied to load the component module (unexpected)
831 * \retval C2_TIMED_OUT could not load the module within the time limit (unexpected)
832 */
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800833 c2_status_t init(std::string libPath);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800834
835 virtual ~ComponentModule() override;
836
837 protected:
838 std::recursive_mutex mLock; ///< lock protecting mTraits
839 std::shared_ptr<C2Component::Traits> mTraits; ///< cached component traits
840
841 c2_status_t mInit; ///< initialization result
842
843 void *mLibHandle; ///< loaded library handle
844 C2ComponentFactory::CreateCodec2FactoryFunc createFactory; ///< loaded create function
845 C2ComponentFactory::DestroyCodec2FactoryFunc destroyFactory; ///< loaded destroy function
846 C2ComponentFactory *mComponentFactory; ///< loaded/created component factory
847 };
848
849 /**
850 * An object encapsulating a loadable component module.
851 *
852 * \todo make this also work for enumerations
853 */
854 struct ComponentLoader {
855 /**
856 * Load the component module.
857 *
858 * This method simply returns the component module if it is already currently loaded, or
859 * attempts to load it if it is not.
860 *
861 * \param module[out] pointer to the shared pointer where the loaded module shall be stored.
862 * This will be nullptr on error.
863 *
864 * \retval C2_OK the component module has been successfully loaded
865 * \retval C2_NO_MEMORY not enough memory to loading the component module
866 * \retval C2_NOT_FOUND could not locate the component module
867 * \retval C2_CORRUPTED the component module could not be loaded
868 * \retval C2_REFUSED permission denied to load the component module
869 */
870 c2_status_t fetchModule(std::shared_ptr<ComponentModule> *module) {
871 c2_status_t res = C2_OK;
872 std::lock_guard<std::mutex> lock(mMutex);
873 std::shared_ptr<ComponentModule> localModule = mModule.lock();
874 if (localModule == nullptr) {
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530875 if(mCreateFactory) {
876 // For testing only
877 localModule = std::make_shared<ComponentModule>(mCreateFactory,
878 mDestroyFactory);
879 } else {
880 localModule = std::make_shared<ComponentModule>();
881 }
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800882 res = localModule->init(mLibPath);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800883 if (res == C2_OK) {
884 mModule = localModule;
885 }
886 }
887 *module = localModule;
888 return res;
889 }
890
891 /**
892 * Creates a component loader for a specific library path (or name).
893 */
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800894 ComponentLoader(std::string libPath)
895 : mLibPath(libPath) {}
Pawin Vongmasa36653902018-11-15 00:10:25 -0800896
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530897 // For testing only
898 ComponentLoader(std::tuple<C2String,
899 C2ComponentFactory::CreateCodec2FactoryFunc,
900 C2ComponentFactory::DestroyCodec2FactoryFunc> func)
901 : mLibPath(std::get<0>(func)),
902 mCreateFactory(std::get<1>(func)),
903 mDestroyFactory(std::get<2>(func)) {}
904
Pawin Vongmasa36653902018-11-15 00:10:25 -0800905 private:
906 std::mutex mMutex; ///< mutex guarding the module
907 std::weak_ptr<ComponentModule> mModule; ///< weak reference to the loaded module
Pawin Vongmasa36653902018-11-15 00:10:25 -0800908 std::string mLibPath; ///< library path
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530909
910 // For testing only
911 C2ComponentFactory::CreateCodec2FactoryFunc mCreateFactory = nullptr;
912 C2ComponentFactory::DestroyCodec2FactoryFunc mDestroyFactory = nullptr;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800913 };
914
915 struct Interface : public C2InterfaceHelper {
916 std::shared_ptr<C2StoreIonUsageInfo> mIonUsageInfo;
John Stultza7002cb2020-09-04 19:02:30 +0000917 std::shared_ptr<C2StoreDmaBufUsageInfo> mDmaBufUsageInfo;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800918
919 Interface(std::shared_ptr<C2ReflectorHelper> reflector)
920 : C2InterfaceHelper(reflector) {
921 setDerivedInstance(this);
922
923 struct Setter {
924 static C2R setIonUsage(bool /* mayBlock */, C2P<C2StoreIonUsageInfo> &me) {
Wonsik Kimba3db192019-11-22 11:00:48 -0800925#ifdef __ANDROID_APEX__
926 static int32_t defaultHeapMask = [] {
927 int32_t heapmask = base::GetIntProperty(
928 "ro.com.android.media.swcodec.ion.heapmask", int32_t(0xFFFFFFFF));
929 ALOGD("Default ION heapmask = %d", heapmask);
930 return heapmask;
931 }();
932 static int32_t defaultFlags = [] {
933 int32_t flags = base::GetIntProperty(
934 "ro.com.android.media.swcodec.ion.flags", 0);
935 ALOGD("Default ION flags = %d", flags);
936 return flags;
937 }();
938 static uint32_t defaultAlign = [] {
939 uint32_t align = base::GetUintProperty(
940 "ro.com.android.media.swcodec.ion.align", 0u);
941 ALOGD("Default ION align = %d", align);
942 return align;
943 }();
944 me.set().heapMask = defaultHeapMask;
945 me.set().allocFlags = defaultFlags;
946 me.set().minAlignment = defaultAlign;
947#else
Pawin Vongmasa36653902018-11-15 00:10:25 -0800948 me.set().heapMask = ~0;
949 me.set().allocFlags = 0;
950 me.set().minAlignment = 0;
Wonsik Kimba3db192019-11-22 11:00:48 -0800951#endif
Pawin Vongmasa36653902018-11-15 00:10:25 -0800952 return C2R::Ok();
John Stultza7002cb2020-09-04 19:02:30 +0000953 };
954
955 static C2R setDmaBufUsage(bool /* mayBlock */, C2P<C2StoreDmaBufUsageInfo> &me) {
John Stultz9eda9bf2021-01-08 00:41:13 +0000956 long long usage = (long long)me.get().m.usage;
957 if (C2DmaBufAllocator::system_uncached_supported() &&
958 !(usage & (C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE))) {
959 strncpy(me.set().m.heapName, "system-uncached", me.v.flexCount());
960 } else {
961 strncpy(me.set().m.heapName, "system", me.v.flexCount());
962 }
John Stultza7002cb2020-09-04 19:02:30 +0000963 me.set().m.allocFlags = 0;
964 return C2R::Ok();
965 };
Pawin Vongmasa36653902018-11-15 00:10:25 -0800966 };
967
968 addParameter(
969 DefineParam(mIonUsageInfo, "ion-usage")
970 .withDefault(new C2StoreIonUsageInfo())
971 .withFields({
972 C2F(mIonUsageInfo, usage).flags({C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE}),
973 C2F(mIonUsageInfo, capacity).inRange(0, UINT32_MAX, 1024),
974 C2F(mIonUsageInfo, heapMask).any(),
975 C2F(mIonUsageInfo, allocFlags).flags({}),
976 C2F(mIonUsageInfo, minAlignment).equalTo(0)
977 })
978 .withSetter(Setter::setIonUsage)
979 .build());
John Stultza7002cb2020-09-04 19:02:30 +0000980
981 addParameter(
982 DefineParam(mDmaBufUsageInfo, "dmabuf-usage")
983 .withDefault(C2StoreDmaBufUsageInfo::AllocShared(0))
984 .withFields({
985 C2F(mDmaBufUsageInfo, m.usage).flags({C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE}),
986 C2F(mDmaBufUsageInfo, m.capacity).inRange(0, UINT32_MAX, 1024),
987 C2F(mDmaBufUsageInfo, m.allocFlags).flags({}),
988 C2F(mDmaBufUsageInfo, m.heapName).any(),
989 })
990 .withSetter(Setter::setDmaBufUsage)
991 .build());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800992 }
993 };
994
995 /**
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800996 * Retrieves the component module for a component.
Pawin Vongmasa36653902018-11-15 00:10:25 -0800997 *
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800998 * \param module pointer to a shared_pointer where the component module will be stored on
999 * success.
Pawin Vongmasa36653902018-11-15 00:10:25 -08001000 *
1001 * \retval C2_OK the component loader has been successfully retrieved
1002 * \retval C2_NO_MEMORY not enough memory to locate the component loader
1003 * \retval C2_NOT_FOUND could not locate the component to be loaded
1004 * \retval C2_CORRUPTED the component loader could not be identified due to some modules being
1005 * corrupted (this can happen if the name does not refer to an already
1006 * identified component but some components could not be loaded due to
1007 * bad library)
1008 * \retval C2_REFUSED permission denied to find the component loader for the named component
1009 * (this can happen if the name does not refer to an already identified
1010 * component but some components could not be loaded due to lack of
1011 * permissions)
1012 */
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001013 c2_status_t findComponent(C2String name, std::shared_ptr<ComponentModule> *module);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001014
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001015 /**
1016 * Loads each component module and discover its contents.
1017 */
1018 void visitComponents();
1019
1020 std::mutex mMutex; ///< mutex guarding the component lists during construction
1021 bool mVisited; ///< component modules visited
1022 std::map<C2String, ComponentLoader> mComponents; ///< path -> component module
1023 std::map<C2String, C2String> mComponentNameToPath; ///< name -> path
1024 std::vector<std::shared_ptr<const C2Component::Traits>> mComponentList;
1025
Pawin Vongmasa36653902018-11-15 00:10:25 -08001026 std::shared_ptr<C2ReflectorHelper> mReflector;
1027 Interface mInterface;
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +05301028
1029 // For testing only
1030 std::vector<std::tuple<C2String,
1031 C2ComponentFactory::CreateCodec2FactoryFunc,
1032 C2ComponentFactory::DestroyCodec2FactoryFunc>> mCodec2FactoryFuncs;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001033};
1034
1035c2_status_t C2PlatformComponentStore::ComponentModule::init(
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001036 std::string libPath) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001037 ALOGV("in %s", __func__);
1038 ALOGV("loading dll");
Pawin Vongmasa36653902018-11-15 00:10:25 -08001039
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +05301040 if(!createFactory) {
1041 mLibHandle = dlopen(libPath.c_str(), RTLD_NOW|RTLD_NODELETE);
1042 LOG_ALWAYS_FATAL_IF(mLibHandle == nullptr,
1043 "could not dlopen %s: %s", libPath.c_str(), dlerror());
Chong Zhangf5c7ca82019-04-23 17:06:21 -07001044
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +05301045 createFactory =
1046 (C2ComponentFactory::CreateCodec2FactoryFunc)dlsym(mLibHandle, "CreateCodec2Factory");
1047 LOG_ALWAYS_FATAL_IF(createFactory == nullptr,
1048 "createFactory is null in %s", libPath.c_str());
1049
1050 destroyFactory =
1051 (C2ComponentFactory::DestroyCodec2FactoryFunc)dlsym(mLibHandle, "DestroyCodec2Factory");
1052 LOG_ALWAYS_FATAL_IF(destroyFactory == nullptr,
1053 "destroyFactory is null in %s", libPath.c_str());
1054 }
Chong Zhangf5c7ca82019-04-23 17:06:21 -07001055
1056 mComponentFactory = createFactory();
1057 if (mComponentFactory == nullptr) {
1058 ALOGD("could not create factory in %s", libPath.c_str());
1059 mInit = C2_NO_MEMORY;
Dongwon Kang673236b2019-05-08 09:02:21 -07001060 } else {
1061 mInit = C2_OK;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001062 }
1063
Dongwon Kang673236b2019-05-08 09:02:21 -07001064 if (mInit != C2_OK) {
1065 return mInit;
1066 }
Dongwon Kange55d13c2019-04-24 11:01:49 -07001067
Pawin Vongmasa36653902018-11-15 00:10:25 -08001068 std::shared_ptr<C2ComponentInterface> intf;
1069 c2_status_t res = createInterface(0, &intf);
1070 if (res != C2_OK) {
1071 ALOGD("failed to create interface: %d", res);
1072 return mInit;
1073 }
1074
1075 std::shared_ptr<C2Component::Traits> traits(new (std::nothrow) C2Component::Traits);
1076 if (traits) {
Wonsik Kimee92b522021-02-07 21:55:31 -08001077 if (!C2InterfaceUtils::FillTraitsFromInterface(traits.get(), intf)) {
1078 ALOGD("Failed to fill traits from interface");
Pawin Vongmasa36653902018-11-15 00:10:25 -08001079 return mInit;
1080 }
Lajos Molnar62d62d62019-01-31 16:26:46 -08001081
1082 // TODO: get this properly from the store during emplace
1083 switch (traits->domain) {
1084 case C2Component::DOMAIN_AUDIO:
1085 traits->rank = 8;
1086 break;
1087 default:
1088 traits->rank = 512;
1089 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001090 }
1091 mTraits = traits;
1092
1093 return mInit;
1094}
1095
1096C2PlatformComponentStore::ComponentModule::~ComponentModule() {
1097 ALOGV("in %s", __func__);
1098 if (destroyFactory && mComponentFactory) {
1099 destroyFactory(mComponentFactory);
1100 }
1101 if (mLibHandle) {
1102 ALOGV("unloading dll");
1103 dlclose(mLibHandle);
1104 }
1105}
1106
1107c2_status_t C2PlatformComponentStore::ComponentModule::createInterface(
1108 c2_node_id_t id, std::shared_ptr<C2ComponentInterface> *interface,
1109 std::function<void(::C2ComponentInterface*)> deleter) {
1110 interface->reset();
1111 if (mInit != C2_OK) {
1112 return mInit;
1113 }
1114 std::shared_ptr<ComponentModule> module = shared_from_this();
1115 c2_status_t res = mComponentFactory->createInterface(
1116 id, interface, [module, deleter](C2ComponentInterface *p) mutable {
1117 // capture module so that we ensure we still have it while deleting interface
1118 deleter(p); // delete interface first
1119 module.reset(); // remove module ref (not technically needed)
1120 });
1121 return res;
1122}
1123
1124c2_status_t C2PlatformComponentStore::ComponentModule::createComponent(
1125 c2_node_id_t id, std::shared_ptr<C2Component> *component,
1126 std::function<void(::C2Component*)> deleter) {
1127 component->reset();
1128 if (mInit != C2_OK) {
1129 return mInit;
1130 }
1131 std::shared_ptr<ComponentModule> module = shared_from_this();
1132 c2_status_t res = mComponentFactory->createComponent(
1133 id, component, [module, deleter](C2Component *p) mutable {
1134 // capture module so that we ensure we still have it while deleting component
1135 deleter(p); // delete component first
1136 module.reset(); // remove module ref (not technically needed)
1137 });
1138 return res;
1139}
1140
1141std::shared_ptr<const C2Component::Traits> C2PlatformComponentStore::ComponentModule::getTraits() {
1142 std::unique_lock<std::recursive_mutex> lock(mLock);
1143 return mTraits;
1144}
1145
1146C2PlatformComponentStore::C2PlatformComponentStore()
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001147 : mVisited(false),
1148 mReflector(std::make_shared<C2ReflectorHelper>()),
Pawin Vongmasa36653902018-11-15 00:10:25 -08001149 mInterface(mReflector) {
1150
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001151 auto emplace = [this](const char *libPath) {
1152 mComponents.emplace(libPath, libPath);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001153 };
Pawin Vongmasa36653902018-11-15 00:10:25 -08001154
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001155 // TODO: move this also into a .so so it can be updated
1156 emplace("libcodec2_soft_aacdec.so");
1157 emplace("libcodec2_soft_aacenc.so");
1158 emplace("libcodec2_soft_amrnbdec.so");
1159 emplace("libcodec2_soft_amrnbenc.so");
1160 emplace("libcodec2_soft_amrwbdec.so");
1161 emplace("libcodec2_soft_amrwbenc.so");
Ray Essickc2cc4372019-08-21 14:02:28 -07001162 //emplace("libcodec2_soft_av1dec_aom.so"); // deprecated for the gav1 implementation
1163 emplace("libcodec2_soft_av1dec_gav1.so");
Harish Mahendrakarf3b4d442023-10-24 17:47:04 +00001164 emplace("libcodec2_soft_av1dec_dav1d.so");
Fyodor Kyslove21a4b72022-09-20 23:25:06 +00001165 emplace("libcodec2_soft_av1enc.so");
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001166 emplace("libcodec2_soft_avcdec.so");
1167 emplace("libcodec2_soft_avcenc.so");
1168 emplace("libcodec2_soft_flacdec.so");
1169 emplace("libcodec2_soft_flacenc.so");
1170 emplace("libcodec2_soft_g711alawdec.so");
1171 emplace("libcodec2_soft_g711mlawdec.so");
1172 emplace("libcodec2_soft_gsmdec.so");
1173 emplace("libcodec2_soft_h263dec.so");
1174 emplace("libcodec2_soft_h263enc.so");
1175 emplace("libcodec2_soft_hevcdec.so");
Roma Kauldfe650a2018-08-02 17:48:51 +05301176 emplace("libcodec2_soft_hevcenc.so");
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001177 emplace("libcodec2_soft_mp3dec.so");
1178 emplace("libcodec2_soft_mpeg2dec.so");
1179 emplace("libcodec2_soft_mpeg4dec.so");
1180 emplace("libcodec2_soft_mpeg4enc.so");
1181 emplace("libcodec2_soft_opusdec.so");
1182 emplace("libcodec2_soft_opusenc.so");
1183 emplace("libcodec2_soft_rawdec.so");
1184 emplace("libcodec2_soft_vorbisdec.so");
1185 emplace("libcodec2_soft_vp8dec.so");
1186 emplace("libcodec2_soft_vp8enc.so");
1187 emplace("libcodec2_soft_vp9dec.so");
1188 emplace("libcodec2_soft_vp9enc.so");
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +05301189
1190}
1191
1192// For testing only
1193C2PlatformComponentStore::C2PlatformComponentStore(
1194 std::vector<std::tuple<C2String,
1195 C2ComponentFactory::CreateCodec2FactoryFunc,
1196 C2ComponentFactory::DestroyCodec2FactoryFunc>> funcs)
1197 : mVisited(false),
1198 mReflector(std::make_shared<C2ReflectorHelper>()),
1199 mInterface(mReflector),
1200 mCodec2FactoryFuncs(funcs) {
1201
1202 for(auto const& func: mCodec2FactoryFuncs) {
1203 mComponents.emplace(std::get<0>(func), func);
1204 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001205}
1206
1207c2_status_t C2PlatformComponentStore::copyBuffer(
1208 std::shared_ptr<C2GraphicBuffer> src, std::shared_ptr<C2GraphicBuffer> dst) {
1209 (void)src;
1210 (void)dst;
1211 return C2_OMITTED;
1212}
1213
1214c2_status_t C2PlatformComponentStore::query_sm(
1215 const std::vector<C2Param*> &stackParams,
1216 const std::vector<C2Param::Index> &heapParamIndices,
1217 std::vector<std::unique_ptr<C2Param>> *const heapParams) const {
1218 return mInterface.query(stackParams, heapParamIndices, C2_MAY_BLOCK, heapParams);
1219}
1220
1221c2_status_t C2PlatformComponentStore::config_sm(
1222 const std::vector<C2Param*> &params,
1223 std::vector<std::unique_ptr<C2SettingResult>> *const failures) {
1224 return mInterface.config(params, C2_MAY_BLOCK, failures);
1225}
1226
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001227void C2PlatformComponentStore::visitComponents() {
1228 std::lock_guard<std::mutex> lock(mMutex);
1229 if (mVisited) {
1230 return;
1231 }
1232 for (auto &pathAndLoader : mComponents) {
1233 const C2String &path = pathAndLoader.first;
1234 ComponentLoader &loader = pathAndLoader.second;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001235 std::shared_ptr<ComponentModule> module;
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001236 if (loader.fetchModule(&module) == C2_OK) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001237 std::shared_ptr<const C2Component::Traits> traits = module->getTraits();
1238 if (traits) {
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001239 mComponentList.push_back(traits);
1240 mComponentNameToPath.emplace(traits->name, path);
1241 for (const C2String &alias : traits->aliases) {
1242 mComponentNameToPath.emplace(alias, path);
1243 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001244 }
1245 }
1246 }
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001247 mVisited = true;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001248}
1249
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001250std::vector<std::shared_ptr<const C2Component::Traits>> C2PlatformComponentStore::listComponents() {
1251 // This method SHALL return within 500ms.
1252 visitComponents();
1253 return mComponentList;
1254}
1255
1256c2_status_t C2PlatformComponentStore::findComponent(
1257 C2String name, std::shared_ptr<ComponentModule> *module) {
1258 (*module).reset();
1259 visitComponents();
1260
1261 auto pos = mComponentNameToPath.find(name);
1262 if (pos != mComponentNameToPath.end()) {
1263 return mComponents.at(pos->second).fetchModule(module);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001264 }
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001265 return C2_NOT_FOUND;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001266}
1267
1268c2_status_t C2PlatformComponentStore::createComponent(
1269 C2String name, std::shared_ptr<C2Component> *const component) {
1270 // This method SHALL return within 100ms.
1271 component->reset();
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001272 std::shared_ptr<ComponentModule> module;
1273 c2_status_t res = findComponent(name, &module);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001274 if (res == C2_OK) {
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001275 // TODO: get a unique node ID
1276 res = module->createComponent(0, component);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001277 }
1278 return res;
1279}
1280
1281c2_status_t C2PlatformComponentStore::createInterface(
1282 C2String name, std::shared_ptr<C2ComponentInterface> *const interface) {
1283 // This method SHALL return within 100ms.
1284 interface->reset();
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001285 std::shared_ptr<ComponentModule> module;
1286 c2_status_t res = findComponent(name, &module);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001287 if (res == C2_OK) {
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001288 // TODO: get a unique node ID
1289 res = module->createInterface(0, interface);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001290 }
1291 return res;
1292}
1293
1294c2_status_t C2PlatformComponentStore::querySupportedParams_nb(
1295 std::vector<std::shared_ptr<C2ParamDescriptor>> *const params) const {
1296 return mInterface.querySupportedParams(params);
1297}
1298
1299c2_status_t C2PlatformComponentStore::querySupportedValues_sm(
1300 std::vector<C2FieldSupportedValuesQuery> &fields) const {
1301 return mInterface.querySupportedValues(fields, C2_MAY_BLOCK);
1302}
1303
1304C2String C2PlatformComponentStore::getName() const {
1305 return "android.componentStore.platform";
1306}
1307
1308std::shared_ptr<C2ParamReflector> C2PlatformComponentStore::getParamReflector() const {
1309 return mReflector;
1310}
1311
1312std::shared_ptr<C2ComponentStore> GetCodec2PlatformComponentStore() {
1313 static std::mutex mutex;
1314 static std::weak_ptr<C2ComponentStore> platformStore;
1315 std::lock_guard<std::mutex> lock(mutex);
1316 std::shared_ptr<C2ComponentStore> store = platformStore.lock();
1317 if (store == nullptr) {
1318 store = std::make_shared<C2PlatformComponentStore>();
1319 platformStore = store;
1320 }
1321 return store;
1322}
1323
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +05301324// For testing only
1325std::shared_ptr<C2ComponentStore> GetTestComponentStore(
1326 std::vector<std::tuple<C2String,
1327 C2ComponentFactory::CreateCodec2FactoryFunc,
1328 C2ComponentFactory::DestroyCodec2FactoryFunc>> funcs) {
1329 return std::shared_ptr<C2ComponentStore>(new C2PlatformComponentStore(funcs));
1330}
Pawin Vongmasa36653902018-11-15 00:10:25 -08001331} // namespace android