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