1 /*
2 * Copyright (c) 2023-2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "plugin/plugin_register.h"
16
17 #include <algorithm>
18 #include <dirent.h>
19
20 #include "common/log.h"
21 #include "common/status.h"
22 #include "meta/meta_key.h"
23 #include "plugin/plugin_caps.h"
24
25 namespace OHOS {
26 namespace Media {
27 namespace Plugins {
28
~PluginRegister()29 PluginRegister::~PluginRegister()
30 {
31 registerData_->registerNames.clear();
32 registerData_->registerTable.clear();
33 }
34
AddPackage(const PackageDef & def)35 Status PluginRegister::RegisterImpl::AddPackage(const PackageDef& def)
36 {
37 return SetPackageDef(def);
38 }
39
SetPackageDef(const PackageDef & def)40 Status PluginRegister::RegisterImpl::SetPackageDef(const PackageDef& def)
41 {
42 packageDef = std::make_shared<PackageDef>(def);
43 return Status::OK;
44 }
45
AddPlugin(const PluginDefBase & def)46 Status PluginRegister::RegisterImpl::AddPlugin(const PluginDefBase& def)
47 {
48 if (!Verification(def)) {
49 return Status::ERROR_INVALID_DATA;
50 }
51 if (!VersionMatched(def)) {
52 return Status::ERROR_UNKNOWN;
53 }
54 if (registerData->IsPluginExist(def.pluginType, def.name)) {
55 if (MoreAcceptable(registerData->registerTable[def.pluginType][def.name], def)) {
56 registerData->registerTable[def.pluginType].erase(def.name);
57 } else {
58 return Status::ERROR_PLUGIN_ALREADY_EXISTS;
59 }
60 }
61 UpdateRegisterTableAndRegisterNames(def);
62 return Status::OK;
63 }
64
UpdateRegisterTableAndRegisterNames(const PluginDefBase & def)65 void PluginRegister::RegisterImpl::UpdateRegisterTableAndRegisterNames(const PluginDefBase& def)
66 {
67 auto regInfo = std::make_shared<PluginRegInfo>();
68 regInfo->packageDef = packageDef;
69 switch (def.pluginType) {
70 case PluginType::SOURCE:
71 InitSourceInfo(regInfo, def);
72 break;
73 case PluginType::DEMUXER:
74 InitDemuxerInfo(regInfo, def);
75 break;
76 case PluginType::MUXER:
77 InitMuxerInfo(regInfo, def);
78 break;
79 case PluginType::AUDIO_DECODER:
80 case PluginType::VIDEO_DECODER:
81 case PluginType::AUDIO_ENCODER:
82 case PluginType::VIDEO_ENCODER:
83 InitCodecInfo(regInfo, def);
84 break;
85 case PluginType::AUDIO_SINK:
86 InitAudioSinkInfo(regInfo, def);
87 break;
88 case PluginType::VIDEO_SINK:
89 InitVideoSinkInfo(regInfo, def);
90 break;
91 case PluginType::OUTPUT_SINK:
92 InitOutputSinkInfo(regInfo, def);
93 break;
94 case PluginType::GENERIC_PLUGIN:
95 InitGenericPlugin(regInfo, def);
96 break;
97 default:
98 return;
99 }
100 regInfo->loader = std::move(pluginLoader);
101 registerData->registerTable[def.pluginType][def.name] = regInfo;
102 if ((def.pluginType == PluginType::AUDIO_DECODER || def.pluginType == PluginType::VIDEO_DECODER
103 || def.pluginType == PluginType::AUDIO_ENCODER || def.pluginType == PluginType::VIDEO_ENCODER)
104 && AnyCast<CodecMode>(regInfo->info->extra[PLUGIN_INFO_EXTRA_CODEC_MODE]) == CodecMode::HARDWARE) {
105 registerData->registerNames[def.pluginType].insert(registerData->registerNames[def.pluginType].begin(),
106 def.name);
107 } else {
108 registerData->registerNames[def.pluginType].push_back(def.name);
109 }
110 }
111
Verification(const PluginDefBase & definition)112 bool PluginRegister::RegisterImpl::Verification(const PluginDefBase& definition)
113 {
114 if (definition.rank < 0 || definition.rank > 100) { // 100
115 return false;
116 }
117 return (definition.pluginType != PluginType::INVALID_TYPE);
118 }
119
VersionMatched(const PluginDefBase &)120 bool PluginRegister::RegisterImpl::VersionMatched(const PluginDefBase& /* definition */)
121 {
122 return true;
123 }
124
125 // NOLINTNEXTLINE: should be static or anonymous namespace
MoreAcceptable(std::shared_ptr<PluginRegInfo> & regInfo,const PluginDefBase & def)126 bool PluginRegister::RegisterImpl::MoreAcceptable(std::shared_ptr<PluginRegInfo>& regInfo, const PluginDefBase& def)
127 {
128 return false;
129 }
130
SetPluginInfo(std::shared_ptr<PluginInfo> & info,const PluginDefBase & def)131 void PluginRegister::RegisterImpl::SetPluginInfo(std::shared_ptr<PluginInfo>& info, const PluginDefBase& def)
132 {
133 info->apiVersion = def.apiVersion;
134 info->pluginType = def.pluginType;
135 info->name = def.name;
136 info->description = def.description;
137 info->rank = def.rank;
138 }
139
InitSourceInfo(std::shared_ptr<PluginRegInfo> & reg,const PluginDefBase & def)140 Status PluginRegister::RegisterImpl::InitSourceInfo(std::shared_ptr<PluginRegInfo>& reg, const PluginDefBase& def)
141 {
142 reg->creator = def.GetCreator();
143 auto info = std::make_shared<PluginInfo>();
144 SetPluginInfo(info, def);
145
146 auto capSet = def.GetInCaps();
147 FALSE_RETURN_V_MSG_E(capSet.size() == 1, Status::ERROR_INVALID_PARAMETER, "capSet size is not 1");
148
149 Any protocol;
150 capSet[0].GetFixedValue<Any>(Tag::MEDIA_PROTOCOL_TYPE, protocol);
151 FALSE_RETURN_V_MSG_E(Any::IsSameTypeWith<std::vector<ProtocolType>>(protocol),
152 Status::ERROR_INVALID_PARAMETER, "protocol param type error");
153 auto type = AnyCast<std::vector<ProtocolType>>(protocol);
154 info->extra.insert({PLUGIN_INFO_EXTRA_PROTOCOL, type});
155
156 Any input;
157 capSet[0].GetFixedValue<Any>(Tag::SRC_INPUT_TYPE, input);
158 if (Any::IsSameTypeWith<SrcInputType>(input)) {
159 auto inputType = AnyCast<SrcInputType>(input);
160 info->extra.insert({PLUGIN_INFO_EXTRA_INPUT_TYPE, inputType});
161 }
162
163 info->outCaps = def.GetOutCaps();
164 reg->info = info;
165 return Status::OK;
166 }
167
InitDemuxerInfo(std::shared_ptr<PluginRegInfo> & reg,const PluginDefBase & def)168 Status PluginRegister::RegisterImpl::InitDemuxerInfo(std::shared_ptr<PluginRegInfo>& reg, const PluginDefBase& def)
169 {
170 reg->creator = def.GetCreator();
171 reg->sniffer = def.GetSniffer();
172 auto info = std::make_shared<PluginInfo>();
173 SetPluginInfo(info, def);
174 info->extra.insert({PLUGIN_INFO_EXTRA_EXTENSIONS, def.GetExtensions()});
175 info->inCaps = def.GetInCaps();
176 info->outCaps = def.GetOutCaps();
177 reg->info = info;
178 return Status::OK;
179 }
180
InitMuxerInfo(std::shared_ptr<PluginRegInfo> & reg,const PluginDefBase & def)181 Status PluginRegister::RegisterImpl::InitMuxerInfo(std::shared_ptr<PluginRegInfo>& reg, const PluginDefBase& def)
182 {
183 reg->creator = def.GetCreator();
184 auto info = std::make_shared<PluginInfo>();
185 SetPluginInfo(info, def);
186 info->inCaps = def.GetInCaps();
187 info->outCaps = def.GetOutCaps();
188 reg->info = info;
189 return Status::OK;
190 }
191
InitCodecInfo(std::shared_ptr<PluginRegInfo> & reg,const PluginDefBase & def)192 __attribute__((no_sanitize("cfi"))) Status PluginRegister::RegisterImpl::InitCodecInfo(
193 std::shared_ptr<PluginRegInfo>& reg, const PluginDefBase& def)
194 {
195 reg->creator = def.GetCreator();
196 auto info = std::make_shared<PluginInfo>();
197 SetPluginInfo(info, def);
198
199 auto capSet = def.GetInCaps();
200 FALSE_RETURN_V_MSG_E(capSet.size() == 1, Status::ERROR_INVALID_PARAMETER, "capSet size is not 1");
201
202 Any mode;
203 capSet[0].GetFixedValue<Any>(Tag::MEDIA_CODEC_MODE, mode);
204 FALSE_RETURN_V_MSG_E(Any::IsSameTypeWith<CodecMode>(mode),
205 Status::ERROR_INVALID_PARAMETER, "codec mode param type error");
206 auto codecMode = AnyCast<CodecMode>(mode);
207 info->extra.insert({PLUGIN_INFO_EXTRA_CODEC_MODE, codecMode});
208
209 info->inCaps = def.GetInCaps();
210 info->outCaps = def.GetOutCaps();
211 reg->info = info;
212 return Status::OK;
213 }
214
InitAudioSinkInfo(std::shared_ptr<PluginRegInfo> & reg,const PluginDefBase & def)215 Status PluginRegister::RegisterImpl::InitAudioSinkInfo(std::shared_ptr<PluginRegInfo>& reg, const PluginDefBase& def)
216 {
217 reg->creator = def.GetCreator();
218 auto info = std::make_shared<PluginInfo>();
219 SetPluginInfo(info, def);
220 info->inCaps = def.GetInCaps();
221 reg->info = info;
222 return Status::OK;
223 }
224
InitVideoSinkInfo(std::shared_ptr<PluginRegInfo> & reg,const PluginDefBase & def)225 Status PluginRegister::RegisterImpl::InitVideoSinkInfo(std::shared_ptr<PluginRegInfo>& reg, const PluginDefBase& def)
226 {
227 reg->creator = def.GetCreator();
228 auto info = std::make_shared<PluginInfo>();
229 SetPluginInfo(info, def);
230 info->inCaps = def.GetInCaps();
231 reg->info = info;
232 return Status::OK;
233 }
234
InitOutputSinkInfo(std::shared_ptr<PluginRegInfo> & reg,const PluginDefBase & def)235 Status PluginRegister::RegisterImpl::InitOutputSinkInfo(std::shared_ptr<PluginRegInfo>& reg, const PluginDefBase& def)
236 {
237 reg->creator = def.GetCreator();
238 auto info = std::make_shared<PluginInfo>();
239 SetPluginInfo(info, def);
240
241 auto capSet = def.GetInCaps();
242 FALSE_RETURN_V_MSG_E(capSet.size() == 1, Status::ERROR_INVALID_PARAMETER, "capSet size is not 1");
243
244 Any protocol;
245 capSet[0].GetFixedValue<Any>(Tag::MEDIA_PROTOCOL_TYPE, protocol);
246 FALSE_RETURN_V_MSG_E(Any::IsSameTypeWith<ProtocolType>(protocol),
247 Status::ERROR_INVALID_PARAMETER, "protocol type error");
248 auto protocolType = AnyCast<ProtocolType>(protocol);
249 info->extra[PLUGIN_INFO_EXTRA_OUTPUT_TYPE] = protocolType;
250 info->inCaps = def.GetInCaps();
251 reg->info = info;
252 return Status::OK;
253 }
254
InitGenericPlugin(std::shared_ptr<PluginRegInfo> & reg,const PluginDefBase & def)255 Status PluginRegister::RegisterImpl::InitGenericPlugin(std::shared_ptr<PluginRegInfo>& reg, const PluginDefBase& def)
256 {
257 auto& base = (GenericPluginDef&)def;
258 reg->creator = base.creator;
259 auto info = std::make_shared<PluginInfo>();
260 SetPluginInfo(info, def);
261 info->inCaps = base.inCaps;
262 info->outCaps = base.outCaps;
263 reg->info = info;
264 return Status::OK;
265 }
266
ListPlugins(PluginType type,CodecMode preferredCodecMode)267 std::vector<std::string> PluginRegister::ListPlugins(PluginType type, CodecMode preferredCodecMode)
268 {
269 if ((type == PluginType::AUDIO_DECODER || type == PluginType::VIDEO_DECODER
270 || type == PluginType::AUDIO_ENCODER || type == PluginType::VIDEO_ENCODER)
271 && preferredCodecMode != CodecMode::HARDWARE) {
272 std::vector<std::string> pluginNames {registerData_->registerNames[type]};
273 std::reverse(pluginNames.begin(), pluginNames.end());
274 return pluginNames;
275 } else {
276 return registerData_->registerNames[type];
277 }
278 }
279
GetAllRegisteredPluginCount()280 int PluginRegister::GetAllRegisteredPluginCount()
281 {
282 int count = 0;
283 for (auto it : registerData_->registerTable) {
284 count += it.second.size();
285 }
286 return count;
287 }
288
GetPluginRegInfo(PluginType type,const std::string & name)289 std::shared_ptr<PluginRegInfo> PluginRegister::GetPluginRegInfo(PluginType type, const std::string& name)
290 {
291 if (registerData_->IsPluginExist(type, name)) {
292 return registerData_->registerTable[type][name];
293 }
294 return {};
295 }
296
RegisterPlugins()297 void PluginRegister::RegisterPlugins()
298 {
299 RegisterStaticPlugins();
300 RegisterDynamicPlugins();
301 }
302
RegisterGenericPlugin(const GenericPluginDef & pluginDef)303 void PluginRegister::RegisterGenericPlugin(const GenericPluginDef& pluginDef)
304 {
305 (void)staticPluginRegister_->AddPackage({pluginDef.pkgVersion, pluginDef.pkgName, pluginDef.license});
306 FALSE_LOG_MSG(staticPluginRegister_->AddPlugin(pluginDef) == Status::OK,
307 "Plugin " PUBLIC_LOG_S " register fail.", pluginDef.name.c_str());
308 }
309
RegisterGenericPlugins(const std::vector<GenericPluginDef> & vecPluginDef)310 void PluginRegister::RegisterGenericPlugins(const std::vector<GenericPluginDef>& vecPluginDef)
311 {
312 for (auto& pluginDef : vecPluginDef) {
313 (void)staticPluginRegister_->AddPackage({pluginDef.pkgVersion, pluginDef.pkgName, pluginDef.license});
314 FALSE_LOG_MSG(staticPluginRegister_->AddPlugin(pluginDef) == Status::OK,
315 "Plugin " PUBLIC_LOG_S " register fail.", pluginDef.name.c_str());
316 }
317 }
318
RegisterStaticPlugins()319 void PluginRegister::RegisterStaticPlugins()
320 {
321 }
322
RegisterDynamicPlugins()323 void PluginRegister::RegisterDynamicPlugins()
324 {
325 RegisterPluginsFromPath(HST_PLUGIN_PATH);
326 }
327
RegisterPluginsFromPath(const char * libDirPath)328 __attribute__((no_sanitize("cfi"))) void PluginRegister::RegisterPluginsFromPath(const char* libDirPath)
329 {
330 #ifdef DYNAMIC_PLUGINS
331 MEDIA_LOG_D("plugin path %{public}s", libDirPath);
332 DIR* libDir = opendir(libDirPath);
333 if (libDir) {
334 #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
335 static std::string fileSeparator = "\\";
336 #else
337 static std::string fileSeparator = "/";
338 #endif
339 static std::string libFileTail = HST_PLUGIN_FILE_TAIL;
340 struct dirent* lib = nullptr;
341 std::shared_ptr<PluginLoader> loader = nullptr;
342 while ((lib = readdir(libDir))) {
343 if (lib->d_name[0] == '.') {
344 continue;
345 }
346 MEDIA_LOG_D("plugin name %{public}s", lib->d_name);
347 static std::string libFileHead = "libmedia_plugin_";
348 #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
349 static std::string fileSeparator = "\\";
350 #else
351 static std::string fileSeparator = "/";
352 #endif
353 static std::string libFileTail = HST_PLUGIN_FILE_TAIL;
354 std::string libName = lib->d_name;
355 if (libName.find(libFileHead) ||
356 libName.compare(libName.size() - libFileTail.size(), libFileTail.size(), libFileTail)) {
357 continue;
358 }
359 std::string pluginName =
360 libName.substr(libFileHead.size(), libName.size() - libFileHead.size() - libFileTail.size());
361 std::string libPath = libDirPath + fileSeparator + lib->d_name;
362 loader = PluginLoader::Create(pluginName, libPath);
363 if (loader) {
364 loader->FetchRegisterFunction()(std::make_shared<RegisterImpl>(registerData_, loader));
365 registeredLoaders_.push_back(loader);
366 }
367 }
368 closedir(libDir);
369 }
370 #endif
371 }
372
UnregisterAllPlugins()373 void PluginRegister::UnregisterAllPlugins()
374 {
375 #ifdef DYNAMIC_PLUGINS
376 for (auto& loader : registeredLoaders_) {
377 EraseRegisteredPluginsByLoader(loader);
378 loader->FetchUnregisterFunction()();
379 loader.reset();
380 }
381 #endif
382 registeredLoaders_.clear();
383 }
384
DeletePlugin(std::map<std::string,std::shared_ptr<PluginRegInfo>> & plugins,std::map<std::string,std::shared_ptr<PluginRegInfo>>::iterator & info)385 void PluginRegister::DeletePlugin(std::map<std::string, std::shared_ptr<PluginRegInfo>>& plugins,
386 std::map<std::string, std::shared_ptr<PluginRegInfo>>::iterator& info)
387 {
388 auto type = info->second->info->pluginType;
389 for (auto it = registerData_->registerNames[type].begin();
390 it != registerData_->registerNames[type].end();) {
391 if (*it == info->first) {
392 it = registerData_->registerNames[type].erase(it);
393 } else {
394 ++it;
395 }
396 }
397 registerData_->registerTable[type].erase(info->first);
398 info = plugins.erase(info);
399 }
EraseRegisteredPluginsByLoader(const std::shared_ptr<PluginLoader> & loader)400 void PluginRegister::EraseRegisteredPluginsByLoader(const std::shared_ptr<PluginLoader>& loader)
401 {
402 for (auto& it : registerData_->registerTable) {
403 auto plugins = it.second;
404 for (auto info = plugins.begin(); info != plugins.end();) {
405 if (info->second->loader == loader) {
406 DeletePlugin(plugins, info);
407 } else {
408 info++;
409 }
410 }
411 }
412 }
413
IsPluginExist(PluginType type,const std::string & name)414 bool PluginRegister::RegisterData::IsPluginExist(PluginType type, const std::string& name)
415 {
416 return (registerTable.find(type) != registerTable.end() &&
417 registerTable[type].find(name) != registerTable[type].end());
418 }
419 } // namespace Plugins
420 } // namespace Media
421 } // namespace OHOS