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 <C2BqBufferPriv.h>
16 #include <C2BufferPriv.h>
17 #include <log/log.h>
18
19 #include <v4l2_codec2/plugin_store/V4L2AllocatorId.h>
20 #include <v4l2_codec2/plugin_store/VendorAllocatorLoader.h>
21
22 namespace android {
23
24 static std::mutex sAllocatorLoaderMutex;
25
26 // Using optional because in the case of library being no availiable, we do not want to retry its search.
27 static std::optional<std::unique_ptr<VendorAllocatorLoader>> sAllocatorLoader = std::nullopt;
28
getAllocatorLoader()29 const std::unique_ptr<VendorAllocatorLoader>& getAllocatorLoader() {
30 {
31 std::lock_guard<std::mutex> lock(sAllocatorLoaderMutex);
32
33 if (sAllocatorLoader == std::nullopt) {
34 sAllocatorLoader = VendorAllocatorLoader::Create();
35 }
36 }
37
38 return *sAllocatorLoader;
39 }
40
createAllocator(C2Allocator::id_t allocatorId)41 C2Allocator* createAllocator(C2Allocator::id_t allocatorId) {
42 ALOGV("%s(allocatorId=%d)", __func__, allocatorId);
43
44 auto& allocatorLoader = getAllocatorLoader();
45 if (allocatorLoader != nullptr) {
46 ALOGD("%s(): Create C2Allocator (id=%u) from VendorAllocatorLoader", __func__, allocatorId);
47 return allocatorLoader->createAllocator(allocatorId);
48 }
49
50 ALOGI("%s(): Fallback to create C2AllocatorGralloc(id=%u)", __func__, allocatorId);
51 return new C2AllocatorGralloc(allocatorId, true);
52 }
53
fetchAllocator(C2Allocator::id_t allocatorId)54 std::shared_ptr<C2Allocator> fetchAllocator(C2Allocator::id_t allocatorId) {
55 ALOGV("%s(allocatorId=%d)", __func__, allocatorId);
56 static std::mutex sMutex;
57 static std::map<C2Allocator::id_t, std::weak_ptr<C2Allocator>> sCacheAllocators;
58
59 std::lock_guard<std::mutex> lock(sMutex);
60
61 std::shared_ptr<C2Allocator> allocator;
62 auto iter = sCacheAllocators.find(allocatorId);
63 if (iter != sCacheAllocators.end()) {
64 allocator = iter->second.lock();
65 if (allocator != nullptr) {
66 return allocator;
67 }
68 }
69
70 allocator.reset(createAllocator(allocatorId));
71 sCacheAllocators[allocatorId] = allocator;
72 return allocator;
73 }
74
createBlockPool(C2Allocator::id_t allocatorId,C2BlockPool::local_id_t poolId)75 C2BlockPool* createBlockPool(C2Allocator::id_t allocatorId, C2BlockPool::local_id_t poolId) {
76 ALOGV("%s(allocatorId=%d, poolId=%" PRIu64 ")", __func__, allocatorId, poolId);
77
78 auto& allocatorLoader = getAllocatorLoader();
79 if (allocatorLoader != nullptr) {
80 ALOGD("%s(): Create C2BlockPool (id=%u) from VendorAllocatorLoader", __func__, allocatorId);
81 C2BlockPool* pool = allocatorLoader->createBlockPool(allocatorId, poolId);
82 ;
83 if (pool != nullptr) {
84 return pool;
85 }
86 }
87
88 std::shared_ptr<C2Allocator> allocator = fetchAllocator(allocatorId);
89 if (allocator == nullptr) {
90 ALOGE("%s(): Failed to create allocator id=%u", __func__, allocatorId);
91 return nullptr;
92 }
93
94 switch (allocatorId) {
95 case V4L2AllocatorId::SECURE_LINEAR:
96 return new C2PooledBlockPool(allocator, poolId);
97
98 case V4L2AllocatorId::SECURE_GRAPHIC:
99 return new C2BufferQueueBlockPool(allocator, poolId);
100
101 default:
102 ALOGE("%s(): Unknown allocator id=%u", __func__, allocatorId);
103 return nullptr;
104 }
105 }
106
107 } // namespace android
108
CreateBlockPool(::C2Allocator::id_t allocatorId,::C2BlockPool::local_id_t poolId)109 extern "C" ::C2BlockPool* CreateBlockPool(::C2Allocator::id_t allocatorId,
110 ::C2BlockPool::local_id_t poolId) {
111 ALOGV("%s(allocatorId=%d, poolId=%" PRIu64 ")", __func__, allocatorId, poolId);
112 return ::android::createBlockPool(allocatorId, poolId);
113 }
114
CreateAllocator(::C2Allocator::id_t allocatorId,::c2_status_t * status)115 extern "C" ::C2Allocator* CreateAllocator(::C2Allocator::id_t allocatorId, ::c2_status_t* status) {
116 ALOGV("%s(allocatorId=%d)", __func__, allocatorId);
117
118 ::C2Allocator* res = ::android::createAllocator(allocatorId);
119 *status = (res != nullptr) ? C2_OK : C2_BAD_INDEX;
120 return res;
121 }
122