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 }