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