blob: 6ec9d6b873da794db62b8d08b65e7617b835b66c [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:
Sungtak Lee2e979ed2024-05-08 08:21:21 +0000481 _C2BlockPoolCache() : mBlockPoolSeqId(C2BlockPool::PLATFORM_START + 1) {
482 mBqPoolDeferDeallocAfterStop = false;
483#ifdef __ANDROID_APEX__
484 bool stopHalBeforeSurface = ::android::base::GetBoolProperty(
485 "debug.codec2.stop_hal_before_surface", false);
486 if (!stopHalBeforeSurface) {
487 mBqPoolDeferDeallocAfterStop =
488 ::android::base::GetIntProperty(
489 "debug.codec2.bqpool_dealloc_after_stop", 0) != 0;
490 }
491#endif
492 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800493
Wonsik Kim17911e32021-08-26 13:57:02 -0700494private:
Pawin Vongmasa36653902018-11-15 00:10:25 -0800495 c2_status_t _createBlockPool(
Sungtak Leeaa71b5c2023-11-04 09:21:15 +0000496 C2PlatformAllocatorDesc &allocatorParam,
Wonsik Kim2fce07922021-02-11 00:16:11 -0800497 std::vector<std::shared_ptr<const C2Component>> components,
Pawin Vongmasa36653902018-11-15 00:10:25 -0800498 C2BlockPool::local_id_t poolId,
Sungtak Lee2e979ed2024-05-08 08:21:21 +0000499 bool deferDeallocAfterStop,
Pawin Vongmasa36653902018-11-15 00:10:25 -0800500 std::shared_ptr<C2BlockPool> *pool) {
501 std::shared_ptr<C2AllocatorStore> allocatorStore =
502 GetCodec2PlatformAllocatorStore();
Sungtak Leeaa71b5c2023-11-04 09:21:15 +0000503 C2PlatformAllocatorStore::id_t allocatorId = allocatorParam.allocatorId;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800504 std::shared_ptr<C2Allocator> allocator;
505 c2_status_t res = C2_NOT_FOUND;
506
Pin-chih Linaa18ea52019-11-19 18:48:50 +0800507 if (allocatorId == C2AllocatorStore::DEFAULT_LINEAR) {
508 allocatorId = GetPreferredLinearAllocatorId(GetCodec2PoolMask());
509 }
Wonsik Kim17911e32021-08-26 13:57:02 -0700510 auto deleter = [this, poolId](C2BlockPool *pool) {
511 std::unique_lock lock(mMutex);
512 mBlockPools.erase(poolId);
513 mComponents.erase(poolId);
514 delete pool;
515 };
Pawin Vongmasa36653902018-11-15 00:10:25 -0800516 switch(allocatorId) {
John Stultza7002cb2020-09-04 19:02:30 +0000517 case C2PlatformAllocatorStore::ION: /* also ::DMABUFHEAP */
Pawin Vongmasa36653902018-11-15 00:10:25 -0800518 res = allocatorStore->fetchAllocator(
Pin-chih Linaa18ea52019-11-19 18:48:50 +0800519 C2PlatformAllocatorStore::ION, &allocator);
520 if (res == C2_OK) {
Wonsik Kim17911e32021-08-26 13:57:02 -0700521 std::shared_ptr<C2BlockPool> ptr(
Wonsik Kim0560d602023-11-15 10:08:21 -0800522 new C2PooledBlockPool(allocator, poolId, GetBufferPoolVer()), deleter);
Pin-chih Linaa18ea52019-11-19 18:48:50 +0800523 *pool = ptr;
524 mBlockPools[poolId] = ptr;
Wonsik Kim2fce07922021-02-11 00:16:11 -0800525 mComponents[poolId].insert(
526 mComponents[poolId].end(),
527 components.begin(), components.end());
Pin-chih Linaa18ea52019-11-19 18:48:50 +0800528 }
529 break;
530 case C2PlatformAllocatorStore::BLOB:
531 res = allocatorStore->fetchAllocator(
532 C2PlatformAllocatorStore::BLOB, &allocator);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800533 if (res == C2_OK) {
Wonsik Kim17911e32021-08-26 13:57:02 -0700534 std::shared_ptr<C2BlockPool> ptr(
Wonsik Kim0560d602023-11-15 10:08:21 -0800535 new C2PooledBlockPool(allocator, poolId, GetBufferPoolVer()), deleter);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800536 *pool = ptr;
537 mBlockPools[poolId] = ptr;
Wonsik Kim2fce07922021-02-11 00:16:11 -0800538 mComponents[poolId].insert(
539 mComponents[poolId].end(),
540 components.begin(), components.end());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800541 }
542 break;
543 case C2PlatformAllocatorStore::GRALLOC:
544 case C2AllocatorStore::DEFAULT_GRAPHIC:
545 res = allocatorStore->fetchAllocator(
546 C2AllocatorStore::DEFAULT_GRAPHIC, &allocator);
547 if (res == C2_OK) {
Wonsik Kim17911e32021-08-26 13:57:02 -0700548 std::shared_ptr<C2BlockPool> ptr(
Wonsik Kim0560d602023-11-15 10:08:21 -0800549 new C2PooledBlockPool(allocator, poolId, GetBufferPoolVer()), deleter);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800550 *pool = ptr;
551 mBlockPools[poolId] = ptr;
Wonsik Kim2fce07922021-02-11 00:16:11 -0800552 mComponents[poolId].insert(
553 mComponents[poolId].end(),
554 components.begin(), components.end());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800555 }
556 break;
557 case C2PlatformAllocatorStore::BUFFERQUEUE:
558 res = allocatorStore->fetchAllocator(
559 C2PlatformAllocatorStore::BUFFERQUEUE, &allocator);
560 if (res == C2_OK) {
Wonsik Kim17911e32021-08-26 13:57:02 -0700561 std::shared_ptr<C2BlockPool> ptr(
562 new C2BufferQueueBlockPool(allocator, poolId), deleter);
Sungtak Lee2e979ed2024-05-08 08:21:21 +0000563 if (deferDeallocAfterStop) {
564 std::shared_ptr<C2BufferQueueBlockPool> bqPool =
565 std::static_pointer_cast<C2BufferQueueBlockPool>(ptr);
566 bqPool->setDeferDeallocationAfterStop();
567 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800568 *pool = ptr;
569 mBlockPools[poolId] = ptr;
Wonsik Kim2fce07922021-02-11 00:16:11 -0800570 mComponents[poolId].insert(
571 mComponents[poolId].end(),
572 components.begin(), components.end());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800573 }
574 break;
Sungtak Leeaa71b5c2023-11-04 09:21:15 +0000575 case C2PlatformAllocatorStore::IGBA:
576 res = allocatorStore->fetchAllocator(
577 C2PlatformAllocatorStore::IGBA, &allocator);
578 if (res == C2_OK) {
579 std::shared_ptr<C2BlockPool> ptr(
580 new C2IgbaBlockPool(allocator,
581 allocatorParam.igba,
582 std::move(allocatorParam.waitableFd),
583 poolId), deleter);
584 *pool = ptr;
585 mBlockPools[poolId] = ptr;
586 mComponents[poolId].insert(
587 mComponents[poolId].end(),
588 components.begin(), components.end());
589 }
590 break;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800591 default:
592 // Try to create block pool from platform store plugins.
593 std::shared_ptr<C2BlockPool> ptr;
594 res = C2PlatformStorePluginLoader::GetInstance()->createBlockPool(
Wonsik Kim17911e32021-08-26 13:57:02 -0700595 allocatorId, poolId, &ptr, deleter);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800596 if (res == C2_OK) {
597 *pool = ptr;
598 mBlockPools[poolId] = ptr;
Wonsik Kim2fce07922021-02-11 00:16:11 -0800599 mComponents[poolId].insert(
600 mComponents[poolId].end(),
601 components.begin(), components.end());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800602 }
603 break;
604 }
605 return res;
606 }
607
Wonsik Kim17911e32021-08-26 13:57:02 -0700608public:
Pawin Vongmasa36653902018-11-15 00:10:25 -0800609 c2_status_t createBlockPool(
610 C2PlatformAllocatorStore::id_t allocatorId,
Wonsik Kim2fce07922021-02-11 00:16:11 -0800611 std::vector<std::shared_ptr<const C2Component>> components,
Pawin Vongmasa36653902018-11-15 00:10:25 -0800612 std::shared_ptr<C2BlockPool> *pool) {
Sungtak Leeaa71b5c2023-11-04 09:21:15 +0000613 C2PlatformAllocatorDesc allocator;
614 allocator.allocatorId = allocatorId;
615 return createBlockPool(allocator, components, pool);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800616 }
617
Sungtak Leeaa71b5c2023-11-04 09:21:15 +0000618 c2_status_t createBlockPool(
619 C2PlatformAllocatorDesc &allocator,
620 std::vector<std::shared_ptr<const C2Component>> components,
621 std::shared_ptr<C2BlockPool> *pool) {
622 std::unique_lock lock(mMutex);
Sungtak Lee2e979ed2024-05-08 08:21:21 +0000623 return _createBlockPool(allocator, components, mBlockPoolSeqId++,
624 mBqPoolDeferDeallocAfterStop, pool);
Sungtak Leeaa71b5c2023-11-04 09:21:15 +0000625 }
626
627
Wonsik Kim17911e32021-08-26 13:57:02 -0700628 c2_status_t getBlockPool(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800629 C2BlockPool::local_id_t blockPoolId,
630 std::shared_ptr<const C2Component> component,
631 std::shared_ptr<C2BlockPool> *pool) {
Wonsik Kim17911e32021-08-26 13:57:02 -0700632 std::unique_lock lock(mMutex);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800633 // TODO: use one iterator for multiple blockpool type scalability.
634 std::shared_ptr<C2BlockPool> ptr;
635 auto it = mBlockPools.find(blockPoolId);
636 if (it != mBlockPools.end()) {
637 ptr = it->second.lock();
638 if (!ptr) {
639 mBlockPools.erase(it);
640 mComponents.erase(blockPoolId);
641 } else {
Wonsik Kim2fce07922021-02-11 00:16:11 -0800642 auto found = std::find_if(
643 mComponents[blockPoolId].begin(),
644 mComponents[blockPoolId].end(),
645 [component](const std::weak_ptr<const C2Component> &ptr) {
646 return component == ptr.lock();
647 });
648 if (found != mComponents[blockPoolId].end()) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800649 *pool = ptr;
Wonsik Kim17911e32021-08-26 13:57:02 -0700650 return C2_OK;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800651 }
652 }
653 }
Wonsik Kim17911e32021-08-26 13:57:02 -0700654 // TODO: remove this. this is temporary
655 if (blockPoolId == C2BlockPool::PLATFORM_START) {
Sungtak Leeaa71b5c2023-11-04 09:21:15 +0000656 C2PlatformAllocatorDesc allocator;
657 allocator.allocatorId = C2PlatformAllocatorStore::BUFFERQUEUE;
Wonsik Kim17911e32021-08-26 13:57:02 -0700658 return _createBlockPool(
Sungtak Lee2e979ed2024-05-08 08:21:21 +0000659 allocator, {component}, blockPoolId, mBqPoolDeferDeallocAfterStop, pool);
Wonsik Kim17911e32021-08-26 13:57:02 -0700660 }
661 return C2_NOT_FOUND;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800662 }
663
664private:
Wonsik Kim17911e32021-08-26 13:57:02 -0700665 // Deleter needs to hold this mutex, and there is a small chance that deleter
666 // is invoked while the mutex is held.
667 std::recursive_mutex mMutex;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800668 C2BlockPool::local_id_t mBlockPoolSeqId;
669
670 std::map<C2BlockPool::local_id_t, std::weak_ptr<C2BlockPool>> mBlockPools;
Wonsik Kim2fce07922021-02-11 00:16:11 -0800671 std::map<C2BlockPool::local_id_t, std::vector<std::weak_ptr<const C2Component>>> mComponents;
Sungtak Lee2e979ed2024-05-08 08:21:21 +0000672
673 bool mBqPoolDeferDeallocAfterStop;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800674};
675
676static std::unique_ptr<_C2BlockPoolCache> sBlockPoolCache =
677 std::make_unique<_C2BlockPoolCache>();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800678
679} // anynymous namespace
680
681c2_status_t GetCodec2BlockPool(
682 C2BlockPool::local_id_t id, std::shared_ptr<const C2Component> component,
683 std::shared_ptr<C2BlockPool> *pool) {
684 pool->reset();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800685 std::shared_ptr<C2AllocatorStore> allocatorStore = GetCodec2PlatformAllocatorStore();
686 std::shared_ptr<C2Allocator> allocator;
687 c2_status_t res = C2_NOT_FOUND;
688
689 if (id >= C2BlockPool::PLATFORM_START) {
Wonsik Kim17911e32021-08-26 13:57:02 -0700690 return sBlockPoolCache->getBlockPool(id, component, pool);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800691 }
692
693 switch (id) {
694 case C2BlockPool::BASIC_LINEAR:
695 res = allocatorStore->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &allocator);
696 if (res == C2_OK) {
697 *pool = std::make_shared<C2BasicLinearBlockPool>(allocator);
698 }
699 break;
700 case C2BlockPool::BASIC_GRAPHIC:
701 res = allocatorStore->fetchAllocator(C2AllocatorStore::DEFAULT_GRAPHIC, &allocator);
702 if (res == C2_OK) {
703 *pool = std::make_shared<C2BasicGraphicBlockPool>(allocator);
704 }
705 break;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800706 default:
707 break;
708 }
709 return res;
710}
711
712c2_status_t CreateCodec2BlockPool(
713 C2PlatformAllocatorStore::id_t allocatorId,
Wonsik Kim2fce07922021-02-11 00:16:11 -0800714 const std::vector<std::shared_ptr<const C2Component>> &components,
715 std::shared_ptr<C2BlockPool> *pool) {
716 pool->reset();
717
Sungtak Leeaa71b5c2023-11-04 09:21:15 +0000718 C2PlatformAllocatorDesc allocator;
719 allocator.allocatorId = allocatorId;
720 return sBlockPoolCache->createBlockPool(allocator, components, pool);
Wonsik Kim2fce07922021-02-11 00:16:11 -0800721}
722
723c2_status_t CreateCodec2BlockPool(
724 C2PlatformAllocatorStore::id_t allocatorId,
Pawin Vongmasa36653902018-11-15 00:10:25 -0800725 std::shared_ptr<const C2Component> component,
726 std::shared_ptr<C2BlockPool> *pool) {
727 pool->reset();
728
Sungtak Leeaa71b5c2023-11-04 09:21:15 +0000729 C2PlatformAllocatorDesc allocator;
730 allocator.allocatorId = allocatorId;
731 return sBlockPoolCache->createBlockPool(allocator, {component}, pool);
732}
733
734c2_status_t CreateCodec2BlockPool(
735 C2PlatformAllocatorDesc &allocator,
736 const std::vector<std::shared_ptr<const C2Component>> &components,
737 std::shared_ptr<C2BlockPool> *pool) {
738 pool->reset();
739
740 return sBlockPoolCache->createBlockPool(allocator, components, pool);
741}
742
743c2_status_t CreateCodec2BlockPool(
744 C2PlatformAllocatorDesc &allocator,
745 std::shared_ptr<const C2Component> component,
746 std::shared_ptr<C2BlockPool> *pool) {
747 pool->reset();
748
749 return sBlockPoolCache->createBlockPool(allocator, {component}, pool);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800750}
751
752class C2PlatformComponentStore : public C2ComponentStore {
753public:
754 virtual std::vector<std::shared_ptr<const C2Component::Traits>> listComponents() override;
755 virtual std::shared_ptr<C2ParamReflector> getParamReflector() const override;
756 virtual C2String getName() const override;
757 virtual c2_status_t querySupportedValues_sm(
758 std::vector<C2FieldSupportedValuesQuery> &fields) const override;
759 virtual c2_status_t querySupportedParams_nb(
760 std::vector<std::shared_ptr<C2ParamDescriptor>> *const params) const override;
761 virtual c2_status_t query_sm(
762 const std::vector<C2Param*> &stackParams,
763 const std::vector<C2Param::Index> &heapParamIndices,
764 std::vector<std::unique_ptr<C2Param>> *const heapParams) const override;
765 virtual c2_status_t createInterface(
766 C2String name, std::shared_ptr<C2ComponentInterface> *const interface) override;
767 virtual c2_status_t createComponent(
768 C2String name, std::shared_ptr<C2Component> *const component) override;
769 virtual c2_status_t copyBuffer(
770 std::shared_ptr<C2GraphicBuffer> src, std::shared_ptr<C2GraphicBuffer> dst) override;
771 virtual c2_status_t config_sm(
772 const std::vector<C2Param*> &params,
773 std::vector<std::unique_ptr<C2SettingResult>> *const failures) override;
774 C2PlatformComponentStore();
775
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530776 // For testing only
777 C2PlatformComponentStore(
778 std::vector<std::tuple<C2String,
779 C2ComponentFactory::CreateCodec2FactoryFunc,
780 C2ComponentFactory::DestroyCodec2FactoryFunc>>);
781
Pawin Vongmasa36653902018-11-15 00:10:25 -0800782 virtual ~C2PlatformComponentStore() override = default;
783
784private:
785
786 /**
787 * An object encapsulating a loaded component module.
788 *
789 * \todo provide a way to add traits to known components here to avoid loading the .so-s
790 * for listComponents
791 */
792 struct ComponentModule : public C2ComponentFactory,
793 public std::enable_shared_from_this<ComponentModule> {
794 virtual c2_status_t createComponent(
795 c2_node_id_t id, std::shared_ptr<C2Component> *component,
796 ComponentDeleter deleter = std::default_delete<C2Component>()) override;
797 virtual c2_status_t createInterface(
798 c2_node_id_t id, std::shared_ptr<C2ComponentInterface> *interface,
799 InterfaceDeleter deleter = std::default_delete<C2ComponentInterface>()) override;
800
801 /**
802 * \returns the traits of the component in this module.
803 */
804 std::shared_ptr<const C2Component::Traits> getTraits();
805
806 /**
807 * Creates an uninitialized component module.
808 *
809 * \param name[in] component name.
810 *
811 * \note Only used by ComponentLoader.
812 */
813 ComponentModule()
814 : mInit(C2_NO_INIT),
815 mLibHandle(nullptr),
816 createFactory(nullptr),
817 destroyFactory(nullptr),
818 mComponentFactory(nullptr) {
819 }
820
821 /**
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530822 * Creates an uninitialized component module.
823 * NOTE: For testing only
824 *
825 * \param name[in] component name.
826 *
827 * \note Only used by ComponentLoader.
828 */
829 ComponentModule(
830 C2ComponentFactory::CreateCodec2FactoryFunc createFactory,
831 C2ComponentFactory::DestroyCodec2FactoryFunc destroyFactory)
832 : mInit(C2_NO_INIT),
833 mLibHandle(nullptr),
834 createFactory(createFactory),
835 destroyFactory(destroyFactory),
836 mComponentFactory(nullptr) {
837 }
838
839 /**
Pawin Vongmasa36653902018-11-15 00:10:25 -0800840 * Initializes a component module with a given library path. Must be called exactly once.
841 *
842 * \note Only used by ComponentLoader.
843 *
Pawin Vongmasa36653902018-11-15 00:10:25 -0800844 * \param libPath[in] library path
845 *
846 * \retval C2_OK the component module has been successfully loaded
847 * \retval C2_NO_MEMORY not enough memory to loading the component module
848 * \retval C2_NOT_FOUND could not locate the component module
849 * \retval C2_CORRUPTED the component module could not be loaded (unexpected)
850 * \retval C2_REFUSED permission denied to load the component module (unexpected)
851 * \retval C2_TIMED_OUT could not load the module within the time limit (unexpected)
852 */
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800853 c2_status_t init(std::string libPath);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800854
855 virtual ~ComponentModule() override;
856
857 protected:
858 std::recursive_mutex mLock; ///< lock protecting mTraits
859 std::shared_ptr<C2Component::Traits> mTraits; ///< cached component traits
860
861 c2_status_t mInit; ///< initialization result
862
863 void *mLibHandle; ///< loaded library handle
864 C2ComponentFactory::CreateCodec2FactoryFunc createFactory; ///< loaded create function
865 C2ComponentFactory::DestroyCodec2FactoryFunc destroyFactory; ///< loaded destroy function
866 C2ComponentFactory *mComponentFactory; ///< loaded/created component factory
867 };
868
869 /**
870 * An object encapsulating a loadable component module.
871 *
872 * \todo make this also work for enumerations
873 */
874 struct ComponentLoader {
875 /**
876 * Load the component module.
877 *
878 * This method simply returns the component module if it is already currently loaded, or
879 * attempts to load it if it is not.
880 *
881 * \param module[out] pointer to the shared pointer where the loaded module shall be stored.
882 * This will be nullptr on error.
883 *
884 * \retval C2_OK the component module has been successfully loaded
885 * \retval C2_NO_MEMORY not enough memory to loading the component module
886 * \retval C2_NOT_FOUND could not locate the component module
887 * \retval C2_CORRUPTED the component module could not be loaded
888 * \retval C2_REFUSED permission denied to load the component module
889 */
890 c2_status_t fetchModule(std::shared_ptr<ComponentModule> *module) {
891 c2_status_t res = C2_OK;
892 std::lock_guard<std::mutex> lock(mMutex);
893 std::shared_ptr<ComponentModule> localModule = mModule.lock();
894 if (localModule == nullptr) {
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530895 if(mCreateFactory) {
896 // For testing only
897 localModule = std::make_shared<ComponentModule>(mCreateFactory,
898 mDestroyFactory);
899 } else {
900 localModule = std::make_shared<ComponentModule>();
901 }
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800902 res = localModule->init(mLibPath);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800903 if (res == C2_OK) {
904 mModule = localModule;
905 }
906 }
907 *module = localModule;
908 return res;
909 }
910
911 /**
912 * Creates a component loader for a specific library path (or name).
913 */
Lajos Molnarc9b4ca02019-01-31 16:24:45 -0800914 ComponentLoader(std::string libPath)
915 : mLibPath(libPath) {}
Pawin Vongmasa36653902018-11-15 00:10:25 -0800916
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530917 // For testing only
918 ComponentLoader(std::tuple<C2String,
919 C2ComponentFactory::CreateCodec2FactoryFunc,
920 C2ComponentFactory::DestroyCodec2FactoryFunc> func)
921 : mLibPath(std::get<0>(func)),
922 mCreateFactory(std::get<1>(func)),
923 mDestroyFactory(std::get<2>(func)) {}
924
Pawin Vongmasa36653902018-11-15 00:10:25 -0800925 private:
926 std::mutex mMutex; ///< mutex guarding the module
927 std::weak_ptr<ComponentModule> mModule; ///< weak reference to the loaded module
Pawin Vongmasa36653902018-11-15 00:10:25 -0800928 std::string mLibPath; ///< library path
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +0530929
930 // For testing only
931 C2ComponentFactory::CreateCodec2FactoryFunc mCreateFactory = nullptr;
932 C2ComponentFactory::DestroyCodec2FactoryFunc mDestroyFactory = nullptr;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800933 };
934
935 struct Interface : public C2InterfaceHelper {
936 std::shared_ptr<C2StoreIonUsageInfo> mIonUsageInfo;
John Stultza7002cb2020-09-04 19:02:30 +0000937 std::shared_ptr<C2StoreDmaBufUsageInfo> mDmaBufUsageInfo;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800938
939 Interface(std::shared_ptr<C2ReflectorHelper> reflector)
940 : C2InterfaceHelper(reflector) {
941 setDerivedInstance(this);
942
943 struct Setter {
944 static C2R setIonUsage(bool /* mayBlock */, C2P<C2StoreIonUsageInfo> &me) {
Wonsik Kimba3db192019-11-22 11:00:48 -0800945#ifdef __ANDROID_APEX__
946 static int32_t defaultHeapMask = [] {
947 int32_t heapmask = base::GetIntProperty(
948 "ro.com.android.media.swcodec.ion.heapmask", int32_t(0xFFFFFFFF));
949 ALOGD("Default ION heapmask = %d", heapmask);
950 return heapmask;
951 }();
952 static int32_t defaultFlags = [] {
953 int32_t flags = base::GetIntProperty(
954 "ro.com.android.media.swcodec.ion.flags", 0);
955 ALOGD("Default ION flags = %d", flags);
956 return flags;
957 }();
958 static uint32_t defaultAlign = [] {
959 uint32_t align = base::GetUintProperty(
960 "ro.com.android.media.swcodec.ion.align", 0u);
961 ALOGD("Default ION align = %d", align);
962 return align;
963 }();
964 me.set().heapMask = defaultHeapMask;
965 me.set().allocFlags = defaultFlags;
966 me.set().minAlignment = defaultAlign;
967#else
Pawin Vongmasa36653902018-11-15 00:10:25 -0800968 me.set().heapMask = ~0;
969 me.set().allocFlags = 0;
970 me.set().minAlignment = 0;
Wonsik Kimba3db192019-11-22 11:00:48 -0800971#endif
Pawin Vongmasa36653902018-11-15 00:10:25 -0800972 return C2R::Ok();
John Stultza7002cb2020-09-04 19:02:30 +0000973 };
974
975 static C2R setDmaBufUsage(bool /* mayBlock */, C2P<C2StoreDmaBufUsageInfo> &me) {
John Stultz9eda9bf2021-01-08 00:41:13 +0000976 long long usage = (long long)me.get().m.usage;
977 if (C2DmaBufAllocator::system_uncached_supported() &&
978 !(usage & (C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE))) {
979 strncpy(me.set().m.heapName, "system-uncached", me.v.flexCount());
980 } else {
981 strncpy(me.set().m.heapName, "system", me.v.flexCount());
982 }
John Stultza7002cb2020-09-04 19:02:30 +0000983 me.set().m.allocFlags = 0;
984 return C2R::Ok();
985 };
Pawin Vongmasa36653902018-11-15 00:10:25 -0800986 };
987
988 addParameter(
989 DefineParam(mIonUsageInfo, "ion-usage")
990 .withDefault(new C2StoreIonUsageInfo())
991 .withFields({
992 C2F(mIonUsageInfo, usage).flags({C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE}),
993 C2F(mIonUsageInfo, capacity).inRange(0, UINT32_MAX, 1024),
994 C2F(mIonUsageInfo, heapMask).any(),
995 C2F(mIonUsageInfo, allocFlags).flags({}),
996 C2F(mIonUsageInfo, minAlignment).equalTo(0)
997 })
998 .withSetter(Setter::setIonUsage)
999 .build());
John Stultza7002cb2020-09-04 19:02:30 +00001000
1001 addParameter(
1002 DefineParam(mDmaBufUsageInfo, "dmabuf-usage")
1003 .withDefault(C2StoreDmaBufUsageInfo::AllocShared(0))
1004 .withFields({
1005 C2F(mDmaBufUsageInfo, m.usage).flags({C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE}),
1006 C2F(mDmaBufUsageInfo, m.capacity).inRange(0, UINT32_MAX, 1024),
1007 C2F(mDmaBufUsageInfo, m.allocFlags).flags({}),
1008 C2F(mDmaBufUsageInfo, m.heapName).any(),
1009 })
1010 .withSetter(Setter::setDmaBufUsage)
1011 .build());
Pawin Vongmasa36653902018-11-15 00:10:25 -08001012 }
1013 };
1014
1015 /**
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001016 * Retrieves the component module for a component.
Pawin Vongmasa36653902018-11-15 00:10:25 -08001017 *
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001018 * \param module pointer to a shared_pointer where the component module will be stored on
1019 * success.
Pawin Vongmasa36653902018-11-15 00:10:25 -08001020 *
1021 * \retval C2_OK the component loader has been successfully retrieved
1022 * \retval C2_NO_MEMORY not enough memory to locate the component loader
1023 * \retval C2_NOT_FOUND could not locate the component to be loaded
1024 * \retval C2_CORRUPTED the component loader could not be identified due to some modules being
1025 * corrupted (this can happen if the name does not refer to an already
1026 * identified component but some components could not be loaded due to
1027 * bad library)
1028 * \retval C2_REFUSED permission denied to find the component loader for the named component
1029 * (this can happen if the name does not refer to an already identified
1030 * component but some components could not be loaded due to lack of
1031 * permissions)
1032 */
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001033 c2_status_t findComponent(C2String name, std::shared_ptr<ComponentModule> *module);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001034
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001035 /**
1036 * Loads each component module and discover its contents.
1037 */
1038 void visitComponents();
1039
1040 std::mutex mMutex; ///< mutex guarding the component lists during construction
1041 bool mVisited; ///< component modules visited
1042 std::map<C2String, ComponentLoader> mComponents; ///< path -> component module
1043 std::map<C2String, C2String> mComponentNameToPath; ///< name -> path
1044 std::vector<std::shared_ptr<const C2Component::Traits>> mComponentList;
1045
Pawin Vongmasa36653902018-11-15 00:10:25 -08001046 std::shared_ptr<C2ReflectorHelper> mReflector;
1047 Interface mInterface;
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +05301048
1049 // For testing only
1050 std::vector<std::tuple<C2String,
1051 C2ComponentFactory::CreateCodec2FactoryFunc,
1052 C2ComponentFactory::DestroyCodec2FactoryFunc>> mCodec2FactoryFuncs;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001053};
1054
1055c2_status_t C2PlatformComponentStore::ComponentModule::init(
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001056 std::string libPath) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001057 ALOGV("in %s", __func__);
1058 ALOGV("loading dll");
Pawin Vongmasa36653902018-11-15 00:10:25 -08001059
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +05301060 if(!createFactory) {
1061 mLibHandle = dlopen(libPath.c_str(), RTLD_NOW|RTLD_NODELETE);
1062 LOG_ALWAYS_FATAL_IF(mLibHandle == nullptr,
1063 "could not dlopen %s: %s", libPath.c_str(), dlerror());
Chong Zhangf5c7ca82019-04-23 17:06:21 -07001064
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +05301065 createFactory =
1066 (C2ComponentFactory::CreateCodec2FactoryFunc)dlsym(mLibHandle, "CreateCodec2Factory");
1067 LOG_ALWAYS_FATAL_IF(createFactory == nullptr,
1068 "createFactory is null in %s", libPath.c_str());
1069
1070 destroyFactory =
1071 (C2ComponentFactory::DestroyCodec2FactoryFunc)dlsym(mLibHandle, "DestroyCodec2Factory");
1072 LOG_ALWAYS_FATAL_IF(destroyFactory == nullptr,
1073 "destroyFactory is null in %s", libPath.c_str());
1074 }
Chong Zhangf5c7ca82019-04-23 17:06:21 -07001075
1076 mComponentFactory = createFactory();
1077 if (mComponentFactory == nullptr) {
1078 ALOGD("could not create factory in %s", libPath.c_str());
1079 mInit = C2_NO_MEMORY;
Dongwon Kang673236b2019-05-08 09:02:21 -07001080 } else {
1081 mInit = C2_OK;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001082 }
1083
Dongwon Kang673236b2019-05-08 09:02:21 -07001084 if (mInit != C2_OK) {
1085 return mInit;
1086 }
Dongwon Kange55d13c2019-04-24 11:01:49 -07001087
Pawin Vongmasa36653902018-11-15 00:10:25 -08001088 std::shared_ptr<C2ComponentInterface> intf;
1089 c2_status_t res = createInterface(0, &intf);
1090 if (res != C2_OK) {
1091 ALOGD("failed to create interface: %d", res);
1092 return mInit;
1093 }
1094
1095 std::shared_ptr<C2Component::Traits> traits(new (std::nothrow) C2Component::Traits);
1096 if (traits) {
Wonsik Kimee92b522021-02-07 21:55:31 -08001097 if (!C2InterfaceUtils::FillTraitsFromInterface(traits.get(), intf)) {
1098 ALOGD("Failed to fill traits from interface");
Pawin Vongmasa36653902018-11-15 00:10:25 -08001099 return mInit;
1100 }
Lajos Molnar62d62d62019-01-31 16:26:46 -08001101
1102 // TODO: get this properly from the store during emplace
1103 switch (traits->domain) {
1104 case C2Component::DOMAIN_AUDIO:
1105 traits->rank = 8;
1106 break;
1107 default:
1108 traits->rank = 512;
1109 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001110 }
1111 mTraits = traits;
1112
1113 return mInit;
1114}
1115
1116C2PlatformComponentStore::ComponentModule::~ComponentModule() {
1117 ALOGV("in %s", __func__);
1118 if (destroyFactory && mComponentFactory) {
1119 destroyFactory(mComponentFactory);
1120 }
1121 if (mLibHandle) {
1122 ALOGV("unloading dll");
1123 dlclose(mLibHandle);
1124 }
1125}
1126
1127c2_status_t C2PlatformComponentStore::ComponentModule::createInterface(
1128 c2_node_id_t id, std::shared_ptr<C2ComponentInterface> *interface,
1129 std::function<void(::C2ComponentInterface*)> deleter) {
1130 interface->reset();
1131 if (mInit != C2_OK) {
1132 return mInit;
1133 }
1134 std::shared_ptr<ComponentModule> module = shared_from_this();
1135 c2_status_t res = mComponentFactory->createInterface(
1136 id, interface, [module, deleter](C2ComponentInterface *p) mutable {
1137 // capture module so that we ensure we still have it while deleting interface
1138 deleter(p); // delete interface first
1139 module.reset(); // remove module ref (not technically needed)
1140 });
1141 return res;
1142}
1143
1144c2_status_t C2PlatformComponentStore::ComponentModule::createComponent(
1145 c2_node_id_t id, std::shared_ptr<C2Component> *component,
1146 std::function<void(::C2Component*)> deleter) {
1147 component->reset();
1148 if (mInit != C2_OK) {
1149 return mInit;
1150 }
1151 std::shared_ptr<ComponentModule> module = shared_from_this();
1152 c2_status_t res = mComponentFactory->createComponent(
1153 id, component, [module, deleter](C2Component *p) mutable {
1154 // capture module so that we ensure we still have it while deleting component
1155 deleter(p); // delete component first
1156 module.reset(); // remove module ref (not technically needed)
1157 });
1158 return res;
1159}
1160
1161std::shared_ptr<const C2Component::Traits> C2PlatformComponentStore::ComponentModule::getTraits() {
1162 std::unique_lock<std::recursive_mutex> lock(mLock);
1163 return mTraits;
1164}
1165
1166C2PlatformComponentStore::C2PlatformComponentStore()
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001167 : mVisited(false),
1168 mReflector(std::make_shared<C2ReflectorHelper>()),
Pawin Vongmasa36653902018-11-15 00:10:25 -08001169 mInterface(mReflector) {
1170
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001171 auto emplace = [this](const char *libPath) {
1172 mComponents.emplace(libPath, libPath);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001173 };
Pawin Vongmasa36653902018-11-15 00:10:25 -08001174
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001175 // TODO: move this also into a .so so it can be updated
1176 emplace("libcodec2_soft_aacdec.so");
1177 emplace("libcodec2_soft_aacenc.so");
1178 emplace("libcodec2_soft_amrnbdec.so");
1179 emplace("libcodec2_soft_amrnbenc.so");
1180 emplace("libcodec2_soft_amrwbdec.so");
1181 emplace("libcodec2_soft_amrwbenc.so");
Ray Essickc2cc4372019-08-21 14:02:28 -07001182 //emplace("libcodec2_soft_av1dec_aom.so"); // deprecated for the gav1 implementation
1183 emplace("libcodec2_soft_av1dec_gav1.so");
Harish Mahendrakarf3b4d442023-10-24 17:47:04 +00001184 emplace("libcodec2_soft_av1dec_dav1d.so");
Fyodor Kyslove21a4b72022-09-20 23:25:06 +00001185 emplace("libcodec2_soft_av1enc.so");
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001186 emplace("libcodec2_soft_avcdec.so");
1187 emplace("libcodec2_soft_avcenc.so");
1188 emplace("libcodec2_soft_flacdec.so");
1189 emplace("libcodec2_soft_flacenc.so");
1190 emplace("libcodec2_soft_g711alawdec.so");
1191 emplace("libcodec2_soft_g711mlawdec.so");
1192 emplace("libcodec2_soft_gsmdec.so");
1193 emplace("libcodec2_soft_h263dec.so");
1194 emplace("libcodec2_soft_h263enc.so");
1195 emplace("libcodec2_soft_hevcdec.so");
Roma Kauldfe650a2018-08-02 17:48:51 +05301196 emplace("libcodec2_soft_hevcenc.so");
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001197 emplace("libcodec2_soft_mp3dec.so");
1198 emplace("libcodec2_soft_mpeg2dec.so");
1199 emplace("libcodec2_soft_mpeg4dec.so");
1200 emplace("libcodec2_soft_mpeg4enc.so");
1201 emplace("libcodec2_soft_opusdec.so");
1202 emplace("libcodec2_soft_opusenc.so");
1203 emplace("libcodec2_soft_rawdec.so");
1204 emplace("libcodec2_soft_vorbisdec.so");
1205 emplace("libcodec2_soft_vp8dec.so");
1206 emplace("libcodec2_soft_vp8enc.so");
1207 emplace("libcodec2_soft_vp9dec.so");
1208 emplace("libcodec2_soft_vp9enc.so");
Fyodor Kyslovdd7d5992024-11-05 21:40:16 +00001209 emplace("libcodec2_soft_apvenc.so");
1210 emplace("libcodec2_soft_apvdec.so");
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +05301211}
1212
1213// For testing only
1214C2PlatformComponentStore::C2PlatformComponentStore(
1215 std::vector<std::tuple<C2String,
1216 C2ComponentFactory::CreateCodec2FactoryFunc,
1217 C2ComponentFactory::DestroyCodec2FactoryFunc>> funcs)
1218 : mVisited(false),
1219 mReflector(std::make_shared<C2ReflectorHelper>()),
1220 mInterface(mReflector),
1221 mCodec2FactoryFuncs(funcs) {
1222
1223 for(auto const& func: mCodec2FactoryFuncs) {
1224 mComponents.emplace(std::get<0>(func), func);
1225 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001226}
1227
1228c2_status_t C2PlatformComponentStore::copyBuffer(
1229 std::shared_ptr<C2GraphicBuffer> src, std::shared_ptr<C2GraphicBuffer> dst) {
1230 (void)src;
1231 (void)dst;
1232 return C2_OMITTED;
1233}
1234
1235c2_status_t C2PlatformComponentStore::query_sm(
1236 const std::vector<C2Param*> &stackParams,
1237 const std::vector<C2Param::Index> &heapParamIndices,
1238 std::vector<std::unique_ptr<C2Param>> *const heapParams) const {
1239 return mInterface.query(stackParams, heapParamIndices, C2_MAY_BLOCK, heapParams);
1240}
1241
1242c2_status_t C2PlatformComponentStore::config_sm(
1243 const std::vector<C2Param*> &params,
1244 std::vector<std::unique_ptr<C2SettingResult>> *const failures) {
1245 return mInterface.config(params, C2_MAY_BLOCK, failures);
1246}
1247
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001248void C2PlatformComponentStore::visitComponents() {
1249 std::lock_guard<std::mutex> lock(mMutex);
1250 if (mVisited) {
1251 return;
1252 }
1253 for (auto &pathAndLoader : mComponents) {
1254 const C2String &path = pathAndLoader.first;
1255 ComponentLoader &loader = pathAndLoader.second;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001256 std::shared_ptr<ComponentModule> module;
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001257 if (loader.fetchModule(&module) == C2_OK) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001258 std::shared_ptr<const C2Component::Traits> traits = module->getTraits();
1259 if (traits) {
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001260 mComponentList.push_back(traits);
1261 mComponentNameToPath.emplace(traits->name, path);
1262 for (const C2String &alias : traits->aliases) {
1263 mComponentNameToPath.emplace(alias, path);
1264 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001265 }
1266 }
1267 }
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001268 mVisited = true;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001269}
1270
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001271std::vector<std::shared_ptr<const C2Component::Traits>> C2PlatformComponentStore::listComponents() {
1272 // This method SHALL return within 500ms.
1273 visitComponents();
1274 return mComponentList;
1275}
1276
1277c2_status_t C2PlatformComponentStore::findComponent(
1278 C2String name, std::shared_ptr<ComponentModule> *module) {
1279 (*module).reset();
1280 visitComponents();
1281
1282 auto pos = mComponentNameToPath.find(name);
1283 if (pos != mComponentNameToPath.end()) {
1284 return mComponents.at(pos->second).fetchModule(module);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001285 }
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001286 return C2_NOT_FOUND;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001287}
1288
1289c2_status_t C2PlatformComponentStore::createComponent(
1290 C2String name, std::shared_ptr<C2Component> *const component) {
1291 // This method SHALL return within 100ms.
1292 component->reset();
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001293 std::shared_ptr<ComponentModule> module;
1294 c2_status_t res = findComponent(name, &module);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001295 if (res == C2_OK) {
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001296 // TODO: get a unique node ID
1297 res = module->createComponent(0, component);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001298 }
1299 return res;
1300}
1301
1302c2_status_t C2PlatformComponentStore::createInterface(
1303 C2String name, std::shared_ptr<C2ComponentInterface> *const interface) {
1304 // This method SHALL return within 100ms.
1305 interface->reset();
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001306 std::shared_ptr<ComponentModule> module;
1307 c2_status_t res = findComponent(name, &module);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001308 if (res == C2_OK) {
Lajos Molnarc9b4ca02019-01-31 16:24:45 -08001309 // TODO: get a unique node ID
1310 res = module->createInterface(0, interface);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001311 }
1312 return res;
1313}
1314
1315c2_status_t C2PlatformComponentStore::querySupportedParams_nb(
1316 std::vector<std::shared_ptr<C2ParamDescriptor>> *const params) const {
1317 return mInterface.querySupportedParams(params);
1318}
1319
1320c2_status_t C2PlatformComponentStore::querySupportedValues_sm(
1321 std::vector<C2FieldSupportedValuesQuery> &fields) const {
1322 return mInterface.querySupportedValues(fields, C2_MAY_BLOCK);
1323}
1324
1325C2String C2PlatformComponentStore::getName() const {
1326 return "android.componentStore.platform";
1327}
1328
1329std::shared_ptr<C2ParamReflector> C2PlatformComponentStore::getParamReflector() const {
1330 return mReflector;
1331}
1332
1333std::shared_ptr<C2ComponentStore> GetCodec2PlatformComponentStore() {
1334 static std::mutex mutex;
1335 static std::weak_ptr<C2ComponentStore> platformStore;
1336 std::lock_guard<std::mutex> lock(mutex);
1337 std::shared_ptr<C2ComponentStore> store = platformStore.lock();
1338 if (store == nullptr) {
1339 store = std::make_shared<C2PlatformComponentStore>();
1340 platformStore = store;
1341 }
1342 return store;
1343}
1344
S Vasudev Prasad2daf0ca2020-05-11 16:57:14 +05301345// For testing only
1346std::shared_ptr<C2ComponentStore> GetTestComponentStore(
1347 std::vector<std::tuple<C2String,
1348 C2ComponentFactory::CreateCodec2FactoryFunc,
1349 C2ComponentFactory::DestroyCodec2FactoryFunc>> funcs) {
1350 return std::shared_ptr<C2ComponentStore>(new C2PlatformComponentStore(funcs));
1351}
Pawin Vongmasa36653902018-11-15 00:10:25 -08001352} // namespace android