• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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