1 // Copyright 2020 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 //#define LOG_NDEBUG 0
6 #define LOG_TAG "V4L2PluginStore"
7
8 #include <inttypes.h>
9
10 #include <map>
11 #include <memory>
12 #include <mutex>
13
14 #include <C2AllocatorGralloc.h>
15 #include <C2BufferPriv.h>
16 #include <log/log.h>
17
18 #include <v4l2_codec2/plugin_store/C2VdaBqBlockPool.h>
19 #include <v4l2_codec2/plugin_store/C2VdaPooledBlockPool.h>
20 #include <v4l2_codec2/plugin_store/V4L2AllocatorId.h>
21 #include <v4l2_codec2/plugin_store/VendorAllocatorLoader.h>
22
23 namespace android {
24
createAllocator(C2Allocator::id_t allocatorId)25 C2Allocator* createAllocator(C2Allocator::id_t allocatorId) {
26 ALOGV("%s(allocatorId=%d)", __func__, allocatorId);
27 static std::unique_ptr<VendorAllocatorLoader> sAllocatorLoader =
28 VendorAllocatorLoader::Create();
29
30 if (sAllocatorLoader != nullptr) {
31 ALOGD("%s(): Create C2Allocator (id=%u) from VendorAllocatorLoader", __func__, allocatorId);
32 return sAllocatorLoader->createAllocator(allocatorId);
33 }
34
35 ALOGI("%s(): Fallback to create C2AllocatorGralloc(id=%u)", __func__, allocatorId);
36 return new C2AllocatorGralloc(allocatorId, true);
37 }
38
fetchAllocator(C2Allocator::id_t allocatorId)39 std::shared_ptr<C2Allocator> fetchAllocator(C2Allocator::id_t allocatorId) {
40 ALOGV("%s(allocatorId=%d)", __func__, allocatorId);
41 static std::mutex sMutex;
42 static std::map<C2Allocator::id_t, std::weak_ptr<C2Allocator>> sCacheAllocators;
43
44 std::lock_guard<std::mutex> lock(sMutex);
45
46 std::shared_ptr<C2Allocator> allocator;
47 auto iter = sCacheAllocators.find(allocatorId);
48 if (iter != sCacheAllocators.end()) {
49 allocator = iter->second.lock();
50 if (allocator != nullptr) {
51 return allocator;
52 }
53 }
54
55 allocator.reset(createAllocator(allocatorId));
56 sCacheAllocators[allocatorId] = allocator;
57 return allocator;
58 }
59
createBlockPool(C2Allocator::id_t allocatorId,C2BlockPool::local_id_t poolId)60 C2BlockPool* createBlockPool(C2Allocator::id_t allocatorId, C2BlockPool::local_id_t poolId) {
61 ALOGV("%s(allocatorId=%d, poolId=%" PRIu64 ")", __func__, allocatorId, poolId);
62
63 std::shared_ptr<C2Allocator> allocator = fetchAllocator(allocatorId);
64 if (allocator == nullptr) {
65 ALOGE("%s(): Failed to create allocator id=%u", __func__, allocatorId);
66 return nullptr;
67 }
68
69 switch (allocatorId) {
70 case V4L2AllocatorId::V4L2_BUFFERPOOL:
71 return new C2VdaPooledBlockPool(allocator, poolId);
72
73 case V4L2AllocatorId::V4L2_BUFFERQUEUE:
74 return new C2VdaBqBlockPool(allocator, poolId);
75
76 case V4L2AllocatorId::SECURE_LINEAR:
77 return new C2PooledBlockPool(allocator, poolId);
78
79 case V4L2AllocatorId::SECURE_GRAPHIC:
80 return new C2VdaBqBlockPool(allocator, poolId);
81
82 default:
83 ALOGE("%s(): Unknown allocator id=%u", __func__, allocatorId);
84 return nullptr;
85 }
86 }
87
88 } // namespace android
89
CreateBlockPool(::C2Allocator::id_t allocatorId,::C2BlockPool::local_id_t poolId)90 extern "C" ::C2BlockPool* CreateBlockPool(::C2Allocator::id_t allocatorId,
91 ::C2BlockPool::local_id_t poolId) {
92 ALOGV("%s(allocatorId=%d, poolId=%" PRIu64 ")", __func__, allocatorId, poolId);
93 return ::android::createBlockPool(allocatorId, poolId);
94 }
95
CreateAllocator(::C2Allocator::id_t allocatorId,::c2_status_t * status)96 extern "C" ::C2Allocator* CreateAllocator(::C2Allocator::id_t allocatorId, ::c2_status_t* status) {
97 ALOGV("%s(allocatorId=%d)", __func__, allocatorId);
98
99 ::C2Allocator* res = ::android::createAllocator(allocatorId);
100 *status = (res != nullptr) ? C2_OK : C2_BAD_INDEX;
101 return res;
102 }
103