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