• 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 #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