• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "V4L2ComponentStore"
7 
8 #include <v4l2_codec2/store/V4L2ComponentStore.h>
9 
10 #include <dlfcn.h>
11 #include <stdint.h>
12 
13 #include <memory>
14 #include <mutex>
15 
16 #include <C2.h>
17 #include <C2Config.h>
18 #include <log/log.h>
19 
20 #include <v4l2_codec2/common/V4L2ComponentCommon.h>
21 
22 namespace android {
23 namespace {
24 const char* kLibPath = "libv4l2_codec2_components.so";
25 const char* kCreateFactoryFuncName = "CreateCodec2Factory";
26 const char* kDestroyFactoryFuncName = "DestroyCodec2Factory";
27 
28 const uint32_t kComponentRank = 0x80;
29 }  // namespace
30 
31 // static
Create()32 std::shared_ptr<C2ComponentStore> V4L2ComponentStore::Create() {
33     ALOGV("%s()", __func__);
34 
35     static std::mutex mutex;
36     static std::weak_ptr<C2ComponentStore> platformStore;
37 
38     std::lock_guard<std::mutex> lock(mutex);
39     std::shared_ptr<C2ComponentStore> store = platformStore.lock();
40     if (store != nullptr) return store;
41 
42     void* libHandle = dlopen(kLibPath, RTLD_NOW | RTLD_NODELETE);
43     if (!libHandle) {
44         ALOGE("Failed to load library: %s", kLibPath);
45         return nullptr;
46     }
47 
48     auto createFactoryFunc = (CreateV4L2FactoryFunc)dlsym(libHandle, kCreateFactoryFuncName);
49     auto destroyFactoryFunc = (DestroyV4L2FactoryFunc)dlsym(libHandle, kDestroyFactoryFuncName);
50     if (!createFactoryFunc || !destroyFactoryFunc) {
51         ALOGE("Failed to load functions: %s, %s", kCreateFactoryFuncName, kDestroyFactoryFuncName);
52         dlclose(libHandle);
53         return nullptr;
54     }
55 
56     store = std::shared_ptr<C2ComponentStore>(
57             new V4L2ComponentStore(libHandle, createFactoryFunc, destroyFactoryFunc));
58     platformStore = store;
59     return store;
60 }
61 
V4L2ComponentStore(void * libHandle,CreateV4L2FactoryFunc createFactoryFunc,DestroyV4L2FactoryFunc destroyFactoryFunc)62 V4L2ComponentStore::V4L2ComponentStore(void* libHandle, CreateV4L2FactoryFunc createFactoryFunc,
63                                        DestroyV4L2FactoryFunc destroyFactoryFunc)
64       : mLibHandle(libHandle),
65         mCreateFactoryFunc(createFactoryFunc),
66         mDestroyFactoryFunc(destroyFactoryFunc),
67         mReflector(std::make_shared<C2ReflectorHelper>()) {
68     ALOGV("%s()", __func__);
69 }
70 
~V4L2ComponentStore()71 V4L2ComponentStore::~V4L2ComponentStore() {
72     ALOGV("%s()", __func__);
73 
74     std::lock_guard<std::mutex> lock(mCachedFactoriesLock);
75     for (const auto& kv : mCachedFactories) mDestroyFactoryFunc(kv.second);
76     mCachedFactories.clear();
77 
78     dlclose(mLibHandle);
79 }
80 
getName() const81 C2String V4L2ComponentStore::getName() const {
82     return "android.componentStore.v4l2";
83 }
84 
createComponent(C2String name,std::shared_ptr<C2Component> * const component)85 c2_status_t V4L2ComponentStore::createComponent(C2String name,
86                                                 std::shared_ptr<C2Component>* const component) {
87     ALOGV("%s(%s)", __func__, name.c_str());
88 
89     auto factory = GetFactory(name);
90     if (factory == nullptr) return C2_CORRUPTED;
91 
92     component->reset();
93     return factory->createComponent(0, component);
94 }
95 
createInterface(C2String name,std::shared_ptr<C2ComponentInterface> * const interface)96 c2_status_t V4L2ComponentStore::createInterface(
97         C2String name, std::shared_ptr<C2ComponentInterface>* const interface) {
98     ALOGV("%s(%s)", __func__, name.c_str());
99 
100     auto factory = GetFactory(name);
101     if (factory == nullptr) return C2_CORRUPTED;
102 
103     interface->reset();
104     return factory->createInterface(0, interface);
105 }
106 
listComponents()107 std::vector<std::shared_ptr<const C2Component::Traits>> V4L2ComponentStore::listComponents() {
108     ALOGV("%s()", __func__);
109 
110     std::vector<std::shared_ptr<const C2Component::Traits>> ret;
111     ret.push_back(GetTraits(V4L2ComponentName::kH264Encoder));
112     ret.push_back(GetTraits(V4L2ComponentName::kH264Decoder));
113     ret.push_back(GetTraits(V4L2ComponentName::kH264SecureDecoder));
114     ret.push_back(GetTraits(V4L2ComponentName::kVP8Decoder));
115     ret.push_back(GetTraits(V4L2ComponentName::kVP8SecureDecoder));
116     ret.push_back(GetTraits(V4L2ComponentName::kVP9Decoder));
117     ret.push_back(GetTraits(V4L2ComponentName::kVP9SecureDecoder));
118     return ret;
119 }
120 
getParamReflector() const121 std::shared_ptr<C2ParamReflector> V4L2ComponentStore::getParamReflector() const {
122     return mReflector;
123 }
124 
copyBuffer(std::shared_ptr<C2GraphicBuffer>,std::shared_ptr<C2GraphicBuffer>)125 c2_status_t V4L2ComponentStore::copyBuffer(std::shared_ptr<C2GraphicBuffer> /* src */,
126                                            std::shared_ptr<C2GraphicBuffer> /* dst */) {
127     return C2_OMITTED;
128 }
129 
querySupportedParams_nb(std::vector<std::shared_ptr<C2ParamDescriptor>> * const) const130 c2_status_t V4L2ComponentStore::querySupportedParams_nb(
131         std::vector<std::shared_ptr<C2ParamDescriptor>>* const /* params */) const {
132     return C2_OK;
133 }
134 
query_sm(const std::vector<C2Param * > & stackParams,const std::vector<C2Param::Index> & heapParamIndices,std::vector<std::unique_ptr<C2Param>> * const) const135 c2_status_t V4L2ComponentStore::query_sm(
136         const std::vector<C2Param*>& stackParams,
137         const std::vector<C2Param::Index>& heapParamIndices,
138         std::vector<std::unique_ptr<C2Param>>* const /* heapParams */) const {
139     // There are no supported config params.
140     return stackParams.empty() && heapParamIndices.empty() ? C2_OK : C2_BAD_INDEX;
141 }
142 
config_sm(const std::vector<C2Param * > & params,std::vector<std::unique_ptr<C2SettingResult>> * const)143 c2_status_t V4L2ComponentStore::config_sm(
144         const std::vector<C2Param*>& params,
145         std::vector<std::unique_ptr<C2SettingResult>>* const /* failures */) {
146     // There are no supported config params.
147     return params.empty() ? C2_OK : C2_BAD_INDEX;
148 }
149 
querySupportedValues_sm(std::vector<C2FieldSupportedValuesQuery> & fields) const150 c2_status_t V4L2ComponentStore::querySupportedValues_sm(
151         std::vector<C2FieldSupportedValuesQuery>& fields) const {
152     // There are no supported config params.
153     return fields.empty() ? C2_OK : C2_BAD_INDEX;
154 }
155 
GetFactory(const C2String & name)156 ::C2ComponentFactory* V4L2ComponentStore::GetFactory(const C2String& name) {
157     ALOGV("%s(%s)", __func__, name.c_str());
158 
159     if (!V4L2ComponentName::isValid(name.c_str())) {
160         ALOGE("Invalid component name: %s", name.c_str());
161         return nullptr;
162     }
163 
164     std::lock_guard<std::mutex> lock(mCachedFactoriesLock);
165     const auto it = mCachedFactories.find(name);
166     if (it != mCachedFactories.end()) return it->second;
167 
168     ::C2ComponentFactory* factory = mCreateFactoryFunc(name.c_str());
169     if (factory == nullptr) {
170         ALOGE("Failed to create factory for %s", name.c_str());
171         return nullptr;
172     }
173 
174     mCachedFactories.emplace(name, factory);
175     return factory;
176 }
177 
GetTraits(const C2String & name)178 std::shared_ptr<const C2Component::Traits> V4L2ComponentStore::GetTraits(const C2String& name) {
179     ALOGV("%s(%s)", __func__, name.c_str());
180 
181     if (!V4L2ComponentName::isValid(name.c_str())) {
182         ALOGE("Invalid component name: %s", name.c_str());
183         return nullptr;
184     }
185 
186     std::lock_guard<std::mutex> lock(mCachedTraitsLock);
187     auto it = mCachedTraits.find(name);
188     if (it != mCachedTraits.end()) return it->second;
189 
190     std::shared_ptr<C2ComponentInterface> intf;
191     auto res = createInterface(name, &intf);
192     if (res != C2_OK) {
193         ALOGE("failed to create interface for %s: %d", name.c_str(), res);
194         return nullptr;
195     }
196 
197     bool isEncoder = V4L2ComponentName::isEncoder(name.c_str());
198     uint32_t mediaTypeIndex = isEncoder ? C2PortMediaTypeSetting::output::PARAM_TYPE
199                                         : C2PortMediaTypeSetting::input::PARAM_TYPE;
200     std::vector<std::unique_ptr<C2Param>> params;
201     res = intf->query_vb({}, {mediaTypeIndex}, C2_MAY_BLOCK, &params);
202     if (res != C2_OK) {
203         ALOGE("failed to query interface: %d", res);
204         return nullptr;
205     }
206     if (params.size() != 1u) {
207         ALOGE("failed to query interface: unexpected vector size: %zu", params.size());
208         return nullptr;
209     }
210 
211     C2PortMediaTypeSetting* mediaTypeConfig = (C2PortMediaTypeSetting*)(params[0].get());
212     if (mediaTypeConfig == nullptr) {
213         ALOGE("failed to query media type");
214         return nullptr;
215     }
216 
217     auto traits = std::make_shared<C2Component::Traits>();
218     traits->name = intf->getName();
219     traits->domain = C2Component::DOMAIN_VIDEO;
220     traits->kind = isEncoder ? C2Component::KIND_ENCODER : C2Component::KIND_DECODER;
221     traits->mediaType = mediaTypeConfig->m.value;
222     traits->rank = kComponentRank;
223 
224     mCachedTraits.emplace(name, traits);
225     return traits;
226 }
227 
228 }  // namespace android
229