• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-2023 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/plugin_register.h"
16 
17 #include <algorithm>
18 #include <dirent.h>
19 
20 #include "common/log.h"
21 #include "common/status.h"
22 #include "meta/meta_key.h"
23 #include "plugin/plugin_caps.h"
24 
25 namespace OHOS {
26 namespace Media {
27 namespace Plugins {
28 
~PluginRegister()29 PluginRegister::~PluginRegister()
30 {
31     registerData_->registerNames.clear();
32     registerData_->registerTable.clear();
33 }
34 
AddPackage(const PackageDef & def)35 Status PluginRegister::RegisterImpl::AddPackage(const PackageDef& def)
36 {
37     return SetPackageDef(def);
38 }
39 
SetPackageDef(const PackageDef & def)40 Status PluginRegister::RegisterImpl::SetPackageDef(const PackageDef& def)
41 {
42     packageDef = std::make_shared<PackageDef>(def);
43     return Status::OK;
44 }
45 
AddPlugin(const PluginDefBase & def)46 Status PluginRegister::RegisterImpl::AddPlugin(const PluginDefBase& def)
47 {
48     if (!Verification(def)) {
49         return Status::ERROR_INVALID_DATA;
50     }
51     if (!VersionMatched(def)) {
52         return Status::ERROR_UNKNOWN;
53     }
54     if (registerData->IsPluginExist(def.pluginType, def.name)) {
55         if (MoreAcceptable(registerData->registerTable[def.pluginType][def.name], def)) {
56             registerData->registerTable[def.pluginType].erase(def.name);
57         } else {
58             return Status::ERROR_PLUGIN_ALREADY_EXISTS;
59         }
60     }
61     UpdateRegisterTableAndRegisterNames(def);
62     return Status::OK;
63 }
64 
UpdateRegisterTableAndRegisterNames(const PluginDefBase & def)65 void PluginRegister::RegisterImpl::UpdateRegisterTableAndRegisterNames(const PluginDefBase& def)
66 {
67     auto regInfo = std::make_shared<PluginRegInfo>();
68     regInfo->packageDef = packageDef;
69     switch (def.pluginType) {
70         case PluginType::SOURCE:
71             InitSourceInfo(regInfo, def);
72             break;
73         case PluginType::DEMUXER:
74             InitDemuxerInfo(regInfo, def);
75             break;
76         case PluginType::MUXER:
77             InitMuxerInfo(regInfo, def);
78             break;
79         case PluginType::AUDIO_DECODER:
80         case PluginType::VIDEO_DECODER:
81         case PluginType::AUDIO_ENCODER:
82         case PluginType::VIDEO_ENCODER:
83             InitCodecInfo(regInfo, def);
84             break;
85         case PluginType::AUDIO_SINK:
86             InitAudioSinkInfo(regInfo, def);
87             break;
88         case PluginType::VIDEO_SINK:
89             InitVideoSinkInfo(regInfo, def);
90             break;
91         case PluginType::OUTPUT_SINK:
92             InitOutputSinkInfo(regInfo, def);
93             break;
94         case PluginType::GENERIC_PLUGIN:
95             InitGenericPlugin(regInfo, def);
96             break;
97         default:
98             return;
99     }
100     regInfo->loader = std::move(pluginLoader);
101     registerData->registerTable[def.pluginType][def.name] = regInfo;
102     if ((def.pluginType == PluginType::AUDIO_DECODER || def.pluginType == PluginType::VIDEO_DECODER
103         || def.pluginType == PluginType::AUDIO_ENCODER || def.pluginType == PluginType::VIDEO_ENCODER)
104         && AnyCast<CodecMode>(regInfo->info->extra[PLUGIN_INFO_EXTRA_CODEC_MODE]) == CodecMode::HARDWARE) {
105         registerData->registerNames[def.pluginType].insert(registerData->registerNames[def.pluginType].begin(),
106             def.name);
107     } else {
108         registerData->registerNames[def.pluginType].push_back(def.name);
109     }
110 }
111 
Verification(const PluginDefBase & definition)112 bool PluginRegister::RegisterImpl::Verification(const PluginDefBase& definition)
113 {
114     if (definition.rank < 0 || definition.rank > 100) { // 100
115         return false;
116     }
117     return (definition.pluginType != PluginType::INVALID_TYPE);
118 }
119 
VersionMatched(const PluginDefBase &)120 bool PluginRegister::RegisterImpl::VersionMatched(const PluginDefBase& /* definition */)
121 {
122     return true;
123 }
124 
125 // NOLINTNEXTLINE: should be static or anonymous namespace
MoreAcceptable(std::shared_ptr<PluginRegInfo> & regInfo,const PluginDefBase & def)126 bool PluginRegister::RegisterImpl::MoreAcceptable(std::shared_ptr<PluginRegInfo>& regInfo, const PluginDefBase& def)
127 {
128     return false;
129 }
130 
SetPluginInfo(std::shared_ptr<PluginInfo> & info,const PluginDefBase & def)131 void PluginRegister::RegisterImpl::SetPluginInfo(std::shared_ptr<PluginInfo>& info, const PluginDefBase& def)
132 {
133     info->apiVersion = def.apiVersion;
134     info->pluginType = def.pluginType;
135     info->name = def.name;
136     info->description = def.description;
137     info->rank = def.rank;
138 }
139 
InitSourceInfo(std::shared_ptr<PluginRegInfo> & reg,const PluginDefBase & def)140 Status PluginRegister::RegisterImpl::InitSourceInfo(std::shared_ptr<PluginRegInfo>& reg, const PluginDefBase& def)
141 {
142     reg->creator = def.GetCreator();
143     auto info = std::make_shared<PluginInfo>();
144     SetPluginInfo(info, def);
145 
146     auto capSet = def.GetInCaps();
147     FALSE_RETURN_V_MSG_E(capSet.size() == 1, Status::ERROR_INVALID_PARAMETER, "capSet size is not 1");
148 
149     Any protocol;
150     capSet[0].GetFixedValue<Any>(Tag::MEDIA_PROTOCOL_TYPE, protocol);
151     FALSE_RETURN_V_MSG_E(Any::IsSameTypeWith<std::vector<ProtocolType>>(protocol),
152                          Status::ERROR_INVALID_PARAMETER, "protocol param type error");
153     auto type = AnyCast<std::vector<ProtocolType>>(protocol);
154     info->extra.insert({PLUGIN_INFO_EXTRA_PROTOCOL, type});
155 
156     Any input;
157     capSet[0].GetFixedValue<Any>(Tag::SRC_INPUT_TYPE, input);
158     if (Any::IsSameTypeWith<SrcInputType>(input)) {
159         auto inputType = AnyCast<SrcInputType>(input);
160         info->extra.insert({PLUGIN_INFO_EXTRA_INPUT_TYPE, inputType});
161     }
162 
163     info->outCaps = def.GetOutCaps();
164     reg->info = info;
165     return Status::OK;
166 }
167 
InitDemuxerInfo(std::shared_ptr<PluginRegInfo> & reg,const PluginDefBase & def)168 Status PluginRegister::RegisterImpl::InitDemuxerInfo(std::shared_ptr<PluginRegInfo>& reg, const PluginDefBase& def)
169 {
170     reg->creator = def.GetCreator();
171     reg->sniffer = def.GetSniffer();
172     auto info = std::make_shared<PluginInfo>();
173     SetPluginInfo(info, def);
174     info->extra.insert({PLUGIN_INFO_EXTRA_EXTENSIONS, def.GetExtensions()});
175     info->inCaps = def.GetInCaps();
176     info->outCaps = def.GetOutCaps();
177     reg->info = info;
178     return Status::OK;
179 }
180 
InitMuxerInfo(std::shared_ptr<PluginRegInfo> & reg,const PluginDefBase & def)181 Status PluginRegister::RegisterImpl::InitMuxerInfo(std::shared_ptr<PluginRegInfo>& reg, const PluginDefBase& def)
182 {
183     reg->creator = def.GetCreator();
184     auto info = std::make_shared<PluginInfo>();
185     SetPluginInfo(info, def);
186     info->inCaps = def.GetInCaps();
187     info->outCaps = def.GetOutCaps();
188     reg->info = info;
189     return Status::OK;
190 }
191 
InitCodecInfo(std::shared_ptr<PluginRegInfo> & reg,const PluginDefBase & def)192 __attribute__((no_sanitize("cfi"))) Status PluginRegister::RegisterImpl::InitCodecInfo(
193     std::shared_ptr<PluginRegInfo>& reg, const PluginDefBase& def)
194 {
195     reg->creator = def.GetCreator();
196     auto info = std::make_shared<PluginInfo>();
197     SetPluginInfo(info, def);
198 
199     auto capSet = def.GetInCaps();
200     FALSE_RETURN_V_MSG_E(capSet.size() == 1, Status::ERROR_INVALID_PARAMETER, "capSet size is not 1");
201 
202     Any mode;
203     capSet[0].GetFixedValue<Any>(Tag::MEDIA_CODEC_MODE, mode);
204     FALSE_RETURN_V_MSG_E(Any::IsSameTypeWith<CodecMode>(mode),
205                          Status::ERROR_INVALID_PARAMETER, "codec mode param type error");
206     auto codecMode = AnyCast<CodecMode>(mode);
207     info->extra.insert({PLUGIN_INFO_EXTRA_CODEC_MODE, codecMode});
208 
209     info->inCaps = def.GetInCaps();
210     info->outCaps = def.GetOutCaps();
211     reg->info = info;
212     return Status::OK;
213 }
214 
InitAudioSinkInfo(std::shared_ptr<PluginRegInfo> & reg,const PluginDefBase & def)215 Status PluginRegister::RegisterImpl::InitAudioSinkInfo(std::shared_ptr<PluginRegInfo>& reg, const PluginDefBase& def)
216 {
217     reg->creator = def.GetCreator();
218     auto info = std::make_shared<PluginInfo>();
219     SetPluginInfo(info, def);
220     info->inCaps = def.GetInCaps();
221     reg->info = info;
222     return Status::OK;
223 }
224 
InitVideoSinkInfo(std::shared_ptr<PluginRegInfo> & reg,const PluginDefBase & def)225 Status PluginRegister::RegisterImpl::InitVideoSinkInfo(std::shared_ptr<PluginRegInfo>& reg, const PluginDefBase& def)
226 {
227     reg->creator = def.GetCreator();
228     auto info = std::make_shared<PluginInfo>();
229     SetPluginInfo(info, def);
230     info->inCaps = def.GetInCaps();
231     reg->info = info;
232     return Status::OK;
233 }
234 
InitOutputSinkInfo(std::shared_ptr<PluginRegInfo> & reg,const PluginDefBase & def)235 Status PluginRegister::RegisterImpl::InitOutputSinkInfo(std::shared_ptr<PluginRegInfo>& reg, const PluginDefBase& def)
236 {
237     reg->creator = def.GetCreator();
238     auto info = std::make_shared<PluginInfo>();
239     SetPluginInfo(info, def);
240 
241     auto capSet = def.GetInCaps();
242     FALSE_RETURN_V_MSG_E(capSet.size() == 1, Status::ERROR_INVALID_PARAMETER, "capSet size is not 1");
243 
244     Any protocol;
245     capSet[0].GetFixedValue<Any>(Tag::MEDIA_PROTOCOL_TYPE, protocol);
246     FALSE_RETURN_V_MSG_E(Any::IsSameTypeWith<ProtocolType>(protocol),
247                          Status::ERROR_INVALID_PARAMETER, "protocol type error");
248     auto protocolType = AnyCast<ProtocolType>(protocol);
249     info->extra[PLUGIN_INFO_EXTRA_OUTPUT_TYPE] = protocolType;
250     info->inCaps = def.GetInCaps();
251     reg->info = info;
252     return Status::OK;
253 }
254 
InitGenericPlugin(std::shared_ptr<PluginRegInfo> & reg,const PluginDefBase & def)255 Status PluginRegister::RegisterImpl::InitGenericPlugin(std::shared_ptr<PluginRegInfo>& reg, const PluginDefBase& def)
256 {
257     auto& base = (GenericPluginDef&)def;
258     reg->creator = base.creator;
259     auto info = std::make_shared<PluginInfo>();
260     SetPluginInfo(info, def);
261     info->inCaps = base.inCaps;
262     info->outCaps = base.outCaps;
263     reg->info = info;
264     return Status::OK;
265 }
266 
ListPlugins(PluginType type,CodecMode preferredCodecMode)267 std::vector<std::string> PluginRegister::ListPlugins(PluginType type, CodecMode preferredCodecMode)
268 {
269     if ((type == PluginType::AUDIO_DECODER || type == PluginType::VIDEO_DECODER
270         || type == PluginType::AUDIO_ENCODER || type == PluginType::VIDEO_ENCODER)
271         && preferredCodecMode != CodecMode::HARDWARE) {
272         std::vector<std::string> pluginNames {registerData_->registerNames[type]};
273         std::reverse(pluginNames.begin(), pluginNames.end());
274         return pluginNames;
275     } else {
276         return registerData_->registerNames[type];
277     }
278 }
279 
GetAllRegisteredPluginCount()280 int PluginRegister::GetAllRegisteredPluginCount()
281 {
282     int count = 0;
283     for (auto it : registerData_->registerTable) {
284         count += it.second.size();
285     }
286     return count;
287 }
288 
GetPluginRegInfo(PluginType type,const std::string & name)289 std::shared_ptr<PluginRegInfo> PluginRegister::GetPluginRegInfo(PluginType type, const std::string& name)
290 {
291     if (registerData_->IsPluginExist(type, name)) {
292         return registerData_->registerTable[type][name];
293     }
294     return {};
295 }
296 
RegisterPlugins()297 void PluginRegister::RegisterPlugins()
298 {
299     RegisterStaticPlugins();
300     RegisterDynamicPlugins();
301 }
302 
RegisterGenericPlugin(const GenericPluginDef & pluginDef)303 void PluginRegister::RegisterGenericPlugin(const GenericPluginDef& pluginDef)
304 {
305     (void)staticPluginRegister_->AddPackage({pluginDef.pkgVersion, pluginDef.pkgName, pluginDef.license});
306     FALSE_LOG_MSG(staticPluginRegister_->AddPlugin(pluginDef) == Status::OK,
307         "Plugin " PUBLIC_LOG_S  " register fail.", pluginDef.name.c_str());
308 }
309 
RegisterGenericPlugins(const std::vector<GenericPluginDef> & vecPluginDef)310 void PluginRegister::RegisterGenericPlugins(const std::vector<GenericPluginDef>& vecPluginDef)
311 {
312     for (auto& pluginDef : vecPluginDef) {
313         (void)staticPluginRegister_->AddPackage({pluginDef.pkgVersion, pluginDef.pkgName, pluginDef.license});
314         FALSE_LOG_MSG(staticPluginRegister_->AddPlugin(pluginDef) == Status::OK,
315             "Plugin " PUBLIC_LOG_S  " register fail.", pluginDef.name.c_str());
316     }
317 }
318 
RegisterStaticPlugins()319 void PluginRegister::RegisterStaticPlugins()
320 {
321 }
322 
RegisterDynamicPlugins()323 void PluginRegister::RegisterDynamicPlugins()
324 {
325     RegisterPluginsFromPath(HST_PLUGIN_PATH);
326 }
327 
RegisterPluginsFromPath(const char * libDirPath)328 __attribute__((no_sanitize("cfi"))) void PluginRegister::RegisterPluginsFromPath(const char* libDirPath)
329 {
330 #ifdef DYNAMIC_PLUGINS
331     MEDIA_LOG_D("plugin path %{public}s", libDirPath);
332     DIR* libDir = opendir(libDirPath);
333     if (libDir) {
334         #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
335         static std::string fileSeparator = "\\";
336         #else
337         static std::string fileSeparator = "/";
338         #endif
339         static std::string libFileTail = HST_PLUGIN_FILE_TAIL;
340         struct dirent* lib = nullptr;
341         std::shared_ptr<PluginLoader> loader = nullptr;
342         while ((lib = readdir(libDir))) {
343             if (lib->d_name[0] == '.') {
344                 continue;
345             }
346             MEDIA_LOG_D("plugin name %{public}s", lib->d_name);
347             static std::string libFileHead = "libmedia_plugin_";
348             #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
349             static std::string fileSeparator = "\\";
350             #else
351             static std::string fileSeparator = "/";
352             #endif
353             static std::string libFileTail = HST_PLUGIN_FILE_TAIL;
354             std::string libName = lib->d_name;
355             if (libName.find(libFileHead) ||
356                 libName.compare(libName.size() - libFileTail.size(), libFileTail.size(), libFileTail)) {
357                 continue;
358             }
359             std::string pluginName =
360                 libName.substr(libFileHead.size(), libName.size() - libFileHead.size() - libFileTail.size());
361             std::string libPath = libDirPath + fileSeparator + lib->d_name;
362             loader = PluginLoader::Create(pluginName, libPath);
363             if (loader) {
364                 loader->FetchRegisterFunction()(std::make_shared<RegisterImpl>(registerData_, loader));
365                 registeredLoaders_.push_back(loader);
366             }
367         }
368         closedir(libDir);
369     }
370 #endif
371 }
372 
UnregisterAllPlugins()373 void PluginRegister::UnregisterAllPlugins()
374 {
375 #ifdef DYNAMIC_PLUGINS
376     for (auto& loader : registeredLoaders_) {
377         EraseRegisteredPluginsByLoader(loader);
378         loader->FetchUnregisterFunction()();
379         loader.reset();
380     }
381 #endif
382     registeredLoaders_.clear();
383 }
384 
DeletePlugin(std::map<std::string,std::shared_ptr<PluginRegInfo>> & plugins,std::map<std::string,std::shared_ptr<PluginRegInfo>>::iterator & info)385 void PluginRegister::DeletePlugin(std::map<std::string, std::shared_ptr<PluginRegInfo>>& plugins,
386     std::map<std::string, std::shared_ptr<PluginRegInfo>>::iterator& info)
387 {
388     auto type = info->second->info->pluginType;
389     for (auto it = registerData_->registerNames[type].begin();
390          it != registerData_->registerNames[type].end();) {
391         if (*it == info->first) {
392             it = registerData_->registerNames[type].erase(it);
393         } else {
394             ++it;
395         }
396     }
397     registerData_->registerTable[type].erase(info->first);
398     info = plugins.erase(info);
399 }
EraseRegisteredPluginsByLoader(const std::shared_ptr<PluginLoader> & loader)400 void PluginRegister::EraseRegisteredPluginsByLoader(const std::shared_ptr<PluginLoader>& loader)
401 {
402     for (auto& it : registerData_->registerTable) {
403         auto plugins = it.second;
404         for (auto info = plugins.begin(); info != plugins.end();) {
405             if (info->second->loader == loader) {
406                 DeletePlugin(plugins, info);
407             } else {
408                 info++;
409             }
410         }
411     }
412 }
413 
IsPluginExist(PluginType type,const std::string & name)414 bool PluginRegister::RegisterData::IsPluginExist(PluginType type, const std::string& name)
415 {
416     return (registerTable.find(type) != registerTable.end() &&
417             registerTable[type].find(name) != registerTable[type].end());
418 }
419 } // namespace Plugins
420 } // namespace Media
421 } // namespace OHOS