1 /*
2 * Copyright (c) 2021-2021 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/core/plugin_register.h"
16
17 #include <algorithm>
18 #include <dirent.h>
19
20 #include "all_plugin_static.h"
21 #include "foundation/log.h"
22 #include "plugin/interface/audio_sink_plugin.h"
23 #include "plugin/interface/codec_plugin.h"
24 #include "plugin/interface/demuxer_plugin.h"
25 #include "plugin/interface/generic_plugin.h"
26 #include "plugin/interface/muxer_plugin.h"
27 #include "plugin/interface/source_plugin.h"
28 #include "plugin/interface/video_sink_plugin.h"
29 #include "plugin/interface/output_sink_plugin.h"
30
31 using namespace OHOS::Media::Plugin;
32
~PluginRegister()33 PluginRegister::~PluginRegister()
34 {
35 UnregisterAllPlugins();
36 registerData_->registerNames.clear();
37 registerData_->registerTable.clear();
38 }
39
AddPackage(const PackageDef & def)40 Status PluginRegister::RegisterImpl::AddPackage(const PackageDef& def)
41 {
42 return SetPackageDef(def);
43 }
44
SetPackageDef(const PackageDef & def)45 Status PluginRegister::RegisterImpl::SetPackageDef(const PackageDef& def)
46 {
47 packageDef = std::make_shared<PackageDef>(def);
48 return Status::OK;
49 }
50
AddPlugin(const PluginDefBase & def)51 Status PluginRegister::RegisterImpl::AddPlugin(const PluginDefBase& def)
52 {
53 if (!Verification(def)) {
54 // 插件定义参数校验不合法
55 return Status::ERROR_INVALID_DATA;
56 }
57 if (!VersionMatched(def)) {
58 // 版本不匹配,不给注册
59 return Status::ERROR_UNKNOWN;
60 }
61 if (registerData->IsPluginExist(def.pluginType, def.name)) {
62 if (MoreAcceptable(registerData->registerTable[def.pluginType][def.name], def)) {
63 registerData->registerTable[def.pluginType].erase(def.name);
64 } else {
65 // 重复注册,且有更合适的版本存在
66 return Status::ERROR_PLUGIN_ALREADY_EXISTS;
67 }
68 }
69 UpdateRegisterTableAndRegisterNames(def);
70 return Status::OK;
71 }
72
UpdateRegisterTableAndRegisterNames(const PluginDefBase & def)73 void PluginRegister::RegisterImpl::UpdateRegisterTableAndRegisterNames(const PluginDefBase& def)
74 {
75 auto regInfo = std::make_shared<PluginRegInfo>();
76 regInfo->packageDef = packageDef;
77 switch (def.pluginType) {
78 case PluginType::SOURCE:
79 InitSourceInfo(regInfo, def);
80 break;
81 case PluginType::DEMUXER:
82 InitDemuxerInfo(regInfo, def);
83 break;
84 case PluginType::MUXER:
85 InitMuxerInfo(regInfo, def);
86 break;
87 case PluginType::AUDIO_DECODER:
88 case PluginType::VIDEO_DECODER:
89 case PluginType::AUDIO_ENCODER:
90 case PluginType::VIDEO_ENCODER:
91 InitCodecInfo(regInfo, def);
92 break;
93 case PluginType::AUDIO_SINK:
94 InitAudioSinkInfo(regInfo, def);
95 break;
96 case PluginType::VIDEO_SINK:
97 InitVideoSinkInfo(regInfo, def);
98 break;
99 case PluginType::OUTPUT_SINK:
100 InitOutputSinkInfo(regInfo, def);
101 break;
102 case PluginType::GENERIC_PLUGIN:
103 InitGenericPlugin(regInfo, def);
104 break;
105 default:
106 return;
107 }
108 regInfo->loader = std::move(pluginLoader);
109 registerData->registerTable[def.pluginType][def.name] = regInfo;
110 auto extra = regInfo->info->extra[PLUGIN_INFO_EXTRA_CODEC_MODE];
111 if ((def.pluginType == PluginType::AUDIO_DECODER || def.pluginType == PluginType::VIDEO_DECODER
112 || def.pluginType == PluginType::AUDIO_ENCODER || def.pluginType == PluginType::VIDEO_ENCODER)
113 && regInfo->info->extra.count(PLUGIN_INFO_EXTRA_CODEC_MODE) != 0
114 && (Plugin::Any::IsSameTypeWith<CodecMode>(extra) && AnyCast<CodecMode>(extra) == CodecMode::HARDWARE)) {
115 registerData->registerNames[def.pluginType].insert(registerData->registerNames[def.pluginType].begin(),
116 def.name);
117 } else {
118 registerData->registerNames[def.pluginType].push_back(def.name);
119 }
120 }
121
Verification(const PluginDefBase & definition)122 bool PluginRegister::RegisterImpl::Verification(const PluginDefBase& definition)
123 {
124 if (definition.rank < 0 || definition.rank > 100) { // 100
125 return false;
126 }
127 return (definition.pluginType != PluginType::INVALID_TYPE);
128 }
129
VersionMatched(const PluginDefBase & definition)130 bool PluginRegister::RegisterImpl::VersionMatched(const PluginDefBase& definition)
131 {
132 static std::map<PluginType, int> g_apiVersionMap = {
133 {PluginType::SOURCE, SOURCE_API_VERSION},
134 {PluginType::DEMUXER, DEMUXER_API_VERSION},
135 {PluginType::AUDIO_DECODER, CODEC_API_VERSION},
136 {PluginType::VIDEO_DECODER, CODEC_API_VERSION},
137 {PluginType::AUDIO_ENCODER, CODEC_API_VERSION},
138 {PluginType::VIDEO_ENCODER, CODEC_API_VERSION},
139 {PluginType::AUDIO_SINK, AUDIO_SINK_API_VERSION},
140 {PluginType::VIDEO_SINK, VIDEO_SINK_API_VERSION},
141 {PluginType::MUXER, MUXER_API_VERSION},
142 {PluginType::OUTPUT_SINK, OUTPUT_SINK_API_VERSION},
143 };
144 if (definition.pluginType == PluginType::GENERIC_PLUGIN) {
145 return true;
146 }
147 int major = (definition.apiVersion >> 16) & 0xFFFF; // 16
148 int minor = definition.apiVersion & 0xFFFF;
149 uint32_t version = g_apiVersionMap[definition.pluginType];
150 int coreMajor = (version >> 16) & 0xFFFF; // 16
151 int coreMinor = version & 0xFFFF;
152 return (major == coreMajor) && (minor <= coreMinor);
153 }
154
155 // NOLINTNEXTLINE: should be static or anonymous namespace
MoreAcceptable(std::shared_ptr<PluginRegInfo> & regInfo,const PluginDefBase & def)156 bool PluginRegister::RegisterImpl::MoreAcceptable(std::shared_ptr<PluginRegInfo>& regInfo, const PluginDefBase& def)
157 {
158 return false;
159 }
160
SetPluginInfo(std::shared_ptr<PluginInfo> & info,const PluginDefBase & def)161 void PluginRegister::RegisterImpl::SetPluginInfo(std::shared_ptr<PluginInfo>& info, const PluginDefBase& def)
162 {
163 info->apiVersion = def.apiVersion;
164 info->pluginType = def.pluginType;
165 info->name = def.name;
166 info->description = def.description;
167 info->rank = def.rank;
168 }
169
InitSourceInfo(std::shared_ptr<PluginRegInfo> & reg,const PluginDefBase & def)170 Status PluginRegister::RegisterImpl::InitSourceInfo(std::shared_ptr<PluginRegInfo>& reg, const PluginDefBase& def)
171 {
172 auto& base = (SourcePluginDef&)def;
173 reg->creator = base.creator;
174 auto info = std::make_shared<PluginInfo>();
175 SetPluginInfo(info, def);
176 info->extra.insert({PLUGIN_INFO_EXTRA_PROTOCOL, base.protocol});
177 info->extra.insert({PLUGIN_INFO_EXTRA_INPUT_TYPE, base.inputType});
178 SourceCapabilityConvert(info, def);
179 reg->info = info;
180 return Status::OK;
181 }
182
InitDemuxerInfo(std::shared_ptr<PluginRegInfo> & reg,const PluginDefBase & def)183 Status PluginRegister::RegisterImpl::InitDemuxerInfo(std::shared_ptr<PluginRegInfo>& reg, const PluginDefBase& def)
184 {
185 auto& base = (DemuxerPluginDef&)def;
186 reg->creator = base.creator;
187 reg->sniffer = base.sniffer;
188 auto info = std::make_shared<PluginInfo>();
189 SetPluginInfo(info, def);
190 info->extra.insert({PLUGIN_INFO_EXTRA_EXTENSIONS, base.extensions});
191 DemuxerCapabilityConvert(info, def);
192 reg->info = info;
193 return Status::OK;
194 }
195
InitMuxerInfo(std::shared_ptr<PluginRegInfo> & reg,const PluginDefBase & def)196 Status PluginRegister::RegisterImpl::InitMuxerInfo(std::shared_ptr<PluginRegInfo>& reg, const PluginDefBase& def)
197 {
198 auto& base = (MuxerPluginDef&)def;
199 reg->creator = base.creator;
200 auto info = std::make_shared<PluginInfo>();
201 SetPluginInfo(info, def);
202 info->inCaps = base.inCaps;
203 info->outCaps = base.outCaps;
204 reg->info = info;
205 return Status::OK;
206 }
207
InitCodecInfo(std::shared_ptr<PluginRegInfo> & reg,const PluginDefBase & def)208 Status PluginRegister::RegisterImpl::InitCodecInfo(std::shared_ptr<PluginRegInfo>& reg, const PluginDefBase& def)
209 {
210 auto& base = (CodecPluginDef&)def;
211 reg->creator = base.creator;
212 auto info = std::make_shared<PluginInfo>();
213 SetPluginInfo(info, def);
214 info->extra.insert({PLUGIN_INFO_EXTRA_CODEC_MODE, base.codecMode});
215 CodecCapabilityConvert(info, def);
216 reg->info = info;
217 return Status::OK;
218 }
219
InitAudioSinkInfo(std::shared_ptr<PluginRegInfo> & reg,const PluginDefBase & def)220 Status PluginRegister::RegisterImpl::InitAudioSinkInfo(std::shared_ptr<PluginRegInfo>& reg, const PluginDefBase& def)
221 {
222 reg->creator = ((AudioSinkPluginDef&)def).creator;
223 auto info = std::make_shared<PluginInfo>();
224 SetPluginInfo(info, def);
225 AudioSinkCapabilityConvert(info, def);
226 reg->info = info;
227 return Status::OK;
228 }
229
InitVideoSinkInfo(std::shared_ptr<PluginRegInfo> & reg,const PluginDefBase & def)230 Status PluginRegister::RegisterImpl::InitVideoSinkInfo(std::shared_ptr<PluginRegInfo>& reg, const PluginDefBase& def)
231 {
232 reg->creator = ((VideoSinkPluginDef&)def).creator;
233 auto info = std::make_shared<PluginInfo>();
234 SetPluginInfo(info, def);
235 VideoSinkCapabilityConvert(info, def);
236 reg->info = info;
237 return Status::OK;
238 }
239
InitOutputSinkInfo(std::shared_ptr<PluginRegInfo> & reg,const PluginDefBase & def)240 Status PluginRegister::RegisterImpl::InitOutputSinkInfo(std::shared_ptr<PluginRegInfo>& reg, const PluginDefBase& def)
241 {
242 auto& base = (OutputSinkPluginDef&)def;
243 reg->creator = base.creator;
244 auto info = std::make_shared<PluginInfo>();
245 SetPluginInfo(info, def);
246 info->extra[PLUGIN_INFO_EXTRA_OUTPUT_TYPE] = base.protocolType;
247 info->inCaps = base.inCaps;
248 reg->info = info;
249 return Status::OK;
250 }
251
InitGenericPlugin(std::shared_ptr<PluginRegInfo> & reg,const PluginDefBase & def)252 Status PluginRegister::RegisterImpl::InitGenericPlugin(std::shared_ptr<PluginRegInfo>& reg, const PluginDefBase& def)
253 {
254 auto& base = (GenericPluginDef&)def;
255 reg->creator = base.creator;
256 auto info = std::make_shared<PluginInfo>();
257 SetPluginInfo(info, def);
258 info->inCaps = base.inCaps;
259 info->outCaps = base.outCaps;
260 reg->info = info;
261 return Status::OK;
262 }
263
SourceCapabilityConvert(std::shared_ptr<PluginInfo> & info,const PluginDefBase & def)264 Status PluginRegister::RegisterImpl::SourceCapabilityConvert(std::shared_ptr<PluginInfo>& info,
265 const PluginDefBase& def)
266 {
267 auto& base = (SourcePluginDef&)def;
268 info->outCaps = base.outCaps;
269 return Status::OK;
270 }
271
DemuxerCapabilityConvert(std::shared_ptr<PluginInfo> & info,const PluginDefBase & def)272 Status PluginRegister::RegisterImpl::DemuxerCapabilityConvert(std::shared_ptr<PluginInfo>& info,
273 const PluginDefBase& def)
274 {
275 auto& base = (DemuxerPluginDef&)def;
276 info->inCaps = base.inCaps;
277 info->outCaps = base.outCaps;
278 return Status::OK;
279 }
280
CodecCapabilityConvert(std::shared_ptr<PluginInfo> & info,const PluginDefBase & def)281 Status PluginRegister::RegisterImpl::CodecCapabilityConvert(std::shared_ptr<PluginInfo>& info, const PluginDefBase& def)
282 {
283 auto& base = (CodecPluginDef&)def;
284 info->inCaps = base.inCaps;
285 info->outCaps = base.outCaps;
286 return Status::OK;
287 }
288
AudioSinkCapabilityConvert(std::shared_ptr<PluginInfo> & info,const PluginDefBase & def)289 Status PluginRegister::RegisterImpl::AudioSinkCapabilityConvert(std::shared_ptr<PluginInfo>& info,
290 const PluginDefBase& def)
291 {
292 auto& base = (AudioSinkPluginDef&)def;
293 info->inCaps = base.inCaps;
294 return Status::OK;
295 }
296
VideoSinkCapabilityConvert(std::shared_ptr<PluginInfo> & info,const PluginDefBase & def)297 Status PluginRegister::RegisterImpl::VideoSinkCapabilityConvert(std::shared_ptr<PluginInfo>& info,
298 const PluginDefBase& def)
299 {
300 auto& base = (VideoSinkPluginDef&)def;
301 info->inCaps = base.inCaps;
302 return Status::OK;
303 }
304
ListPlugins(PluginType type,CodecMode preferredCodecMode)305 std::vector<std::string> PluginRegister::ListPlugins(PluginType type, CodecMode preferredCodecMode)
306 {
307 if ((type == PluginType::AUDIO_DECODER || type == PluginType::VIDEO_DECODER
308 || type == PluginType::AUDIO_ENCODER || type == PluginType::VIDEO_ENCODER)
309 && preferredCodecMode != CodecMode::HARDWARE) {
310 std::vector<std::string> pluginNames {registerData_->registerNames[type]};
311 std::reverse(pluginNames.begin(), pluginNames.end());
312 return pluginNames;
313 } else {
314 return registerData_->registerNames[type];
315 }
316 }
317
GetAllRegisteredPluginCount()318 int PluginRegister::GetAllRegisteredPluginCount()
319 {
320 int count = 0;
321 for (auto it : registerData_->registerTable) {
322 count += it.second.size();
323 }
324 return count;
325 }
326
GetPluginRegInfo(PluginType type,const std::string & name)327 std::shared_ptr<PluginRegInfo> PluginRegister::GetPluginRegInfo(PluginType type, const std::string& name)
328 {
329 if (registerData_->IsPluginExist(type, name)) {
330 return registerData_->registerTable[type][name];
331 }
332 return {};
333 }
334
RegisterPlugins()335 void PluginRegister::RegisterPlugins()
336 {
337 RegisterStaticPlugins();
338 RegisterDynamicPlugins();
339 }
340
RegisterGenericPlugin(const GenericPluginDef & pluginDef)341 void PluginRegister::RegisterGenericPlugin(const GenericPluginDef& pluginDef)
342 {
343 (void)staticPluginRegister_->AddPackage({pluginDef.pkgVersion, pluginDef.pkgName, pluginDef.license});
344 FALSE_LOG_MSG(staticPluginRegister_->AddPlugin(pluginDef) == Status::OK,
345 "Plugin " PUBLIC_LOG_S " register fail.", pluginDef.name.c_str());
346 }
347
RegisterGenericPlugins(const std::vector<GenericPluginDef> & vecPluginDef)348 void PluginRegister::RegisterGenericPlugins(const std::vector<GenericPluginDef>& vecPluginDef)
349 {
350 for (auto& pluginDef : vecPluginDef) {
351 (void)staticPluginRegister_->AddPackage({pluginDef.pkgVersion, pluginDef.pkgName, pluginDef.license});
352 FALSE_LOG_MSG(staticPluginRegister_->AddPlugin(pluginDef) == Status::OK,
353 "Plugin " PUBLIC_LOG_S " register fail.", pluginDef.name.c_str());
354 }
355 }
356
RegisterStaticPlugins()357 void PluginRegister::RegisterStaticPlugins()
358 {
359 RegisterPluginStatic(staticPluginRegister_);
360 }
361
RegisterDynamicPlugins()362 void PluginRegister::RegisterDynamicPlugins()
363 {
364 RegisterPluginsFromPath(HST_PLUGIN_PATH);
365 }
366
RegisterPluginsFromPath(const char * libDirPath)367 void PluginRegister::RegisterPluginsFromPath(const char* libDirPath)
368 {
369 #ifdef DYNAMIC_PLUGINS
370 static std::string libFileHead = "libhistreamer_plugin_";
371 #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
372 static std::string fileSeparator = "\\";
373 #else
374 static std::string fileSeparator = "/";
375 #endif
376 static std::string libFileTail = HST_PLUGIN_FILE_TAIL;
377 DIR* libDir = opendir(libDirPath);
378 if (libDir) {
379 struct dirent* lib = nullptr;
380 std::shared_ptr<PluginLoader> loader = nullptr;
381 while ((lib = readdir(libDir))) {
382 if (lib->d_name[0] == '.') {
383 continue;
384 }
385 std::string libName = lib->d_name;
386 if (libName.find(libFileHead) ||
387 libName.compare(libName.size() - libFileTail.size(), libFileTail.size(), libFileTail)) {
388 continue;
389 }
390 std::string pluginName =
391 libName.substr(libFileHead.size(), libName.size() - libFileHead.size() - libFileTail.size());
392 std::string libPath = libDirPath + fileSeparator + lib->d_name;
393 loader = PluginLoader::Create(pluginName, libPath);
394 if (loader) {
395 loader->FetchRegisterFunction()(std::make_shared<RegisterImpl>(registerData_, loader));
396 registeredLoaders_.push_back(loader);
397 }
398 }
399 closedir(libDir);
400 }
401 #endif
402 }
403
UnregisterAllPlugins()404 void PluginRegister::UnregisterAllPlugins()
405 {
406 UnregisterPluginStatic();
407 #ifdef DYNAMIC_PLUGINS
408 for (auto& loader : registeredLoaders_) {
409 EraseRegisteredPluginsByLoader(loader);
410 loader->FetchUnregisterFunction()();
411 loader.reset();
412 }
413 #endif
414 registeredLoaders_.clear();
415 }
416
DeletePlugin(std::map<std::string,std::shared_ptr<PluginRegInfo>> & plugins,std::map<std::string,std::shared_ptr<PluginRegInfo>>::iterator & info)417 void PluginRegister::DeletePlugin(std::map<std::string, std::shared_ptr<PluginRegInfo>>& plugins,
418 std::map<std::string, std::shared_ptr<PluginRegInfo>>::iterator& info)
419 {
420 auto type = info->second->info->pluginType;
421 for (auto it = registerData_->registerNames[type].begin();
422 it != registerData_->registerNames[type].end();) {
423 if (*it == info->first) {
424 it = registerData_->registerNames[type].erase(it);
425 } else {
426 ++it;
427 }
428 }
429 registerData_->registerTable[type].erase(info->first);
430 info = plugins.erase(info);
431 }
EraseRegisteredPluginsByLoader(const std::shared_ptr<PluginLoader> & loader)432 void PluginRegister::EraseRegisteredPluginsByLoader(const std::shared_ptr<PluginLoader>& loader)
433 {
434 for (auto& it : registerData_->registerTable) {
435 auto plugins = it.second;
436 for (auto info = plugins.begin(); info != plugins.end();) {
437 if (info->second->loader == loader) {
438 DeletePlugin(plugins, info);
439 } else {
440 info++;
441 }
442 }
443 }
444 }
445
IsPluginExist(PluginType type,const std::string & name)446 bool PluginRegister::RegisterData::IsPluginExist(PluginType type, const std::string& name)
447 {
448 return (registerTable.find(type) != registerTable.end() &&
449 registerTable[type].find(name) != registerTable[type].end());
450 }