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 
16 #ifndef HISTREAMER_PLUGINS_INTF_PLUGIN_DEFINITION_H
17 #define HISTREAMER_PLUGINS_INTF_PLUGIN_DEFINITION_H
18 
19 #include <functional>
20 #include <string>
21 #include <memory>
22 #include "plugin_caps.h"
23 #include "plugin_base.h"
24 #include "plugin/plugin_buffer.h"
25 
26 namespace OHOS {
27 namespace Media {
28 namespace Plugins {
29 /**
30  * @brief Macro definition, creating the version information.
31  *
32  * @details The versioning is the process of assigning a unique version number to a unique state
33  * of plugin interface. Within a given version number category (major, minor), these numbers are
34  * usually assigned in ascending order and correspond to new developments in the plugin.
35  *
36  * Given a version number MAJOR.MINOR:
37  *  - MAJOR: When you make incompatible API changes.
38  *  - MINOR: When you add features in a backwards-compatible manner or do backwards-compatible bug fixes.
39  */
40 #define MAKE_VERSION(MAJOR, MINOR) ((((MAJOR)&0xFFFF) << 16) | ((MINOR)&0xFFFF))
41 
42 /// Plugin interface major number
43 #define PLUGIN_INTERFACE_VERSION_MAJOR (1)
44 
45 /// Plugin interface minor number
46 #define PLUGIN_INTERFACE_VERSION_MINOR (0)
47 
48 /// Plugin interface version
49 #define PLUGIN_INTERFACE_VERSION MAKE_VERSION(PLUGIN_INTERFACE_VERSION_MAJOR, PLUGIN_INTERFACE_VERSION_MINOR)
50 
51 /**
52  * @enum License Type.
53  * an official permission or permit.
54  *
55  * @since 1.0
56  * @version 1.0
57  */
58 enum struct LicenseType : uint8_t {
59     APACHE_V2, ///< The Apache License 2.0
60     LGPL,      ///< The GNU Lesser General Public License
61     GPL,       ///< The GNU General Public License
62     CC0,       ///< The Creative Commons Zero v1.0 Universal
63     VENDOR,    ///< Offered by Vendor
64     UNKNOWN,   ///< Unknown License
65 };
66 
67 /**
68  * @brief Definition of plugin packaging information.
69  *
70  * @since 1.0
71  * @version 1.0
72  */
73 struct PackageDef {
74     uint32_t pkgVersion;    ///< Package information version, which indicates the latest plug-in interface version
75                             ///< used by the plugin in the package. The default value is PLUGIN_INTERFACE_VERSION.
76 
77     std::string name;   ///< Package name. The plugin framework registers the plugin using this name.
78                         ///< If the plugins are packaged as a dynamic library, the name of library
79                         ///< must be in the format of "libplugin_<name>.so".
80 
81     LicenseType
82         licenseType;    ///< The License information of the plugin in the package.
83                         ///< The different plugins must be the same.
84                         ///< The plugin framework processing in the plugin running state based on different license.
85 };
86 
87 /**
88  * @brief Data source operation interface.
89  *
90  * @since 1.0
91  * @version 1.0
92  */
93 struct DataSource {
94     /// Destructor
95     virtual ~DataSource() = default;
96 
97     /**
98      * @brief Read data from data source.
99      *
100      * @param offset    Offset of read position
101      * @param buffer    Storage of the read data
102      * @param expectedLen   Expected data size to be read
103      * @return  Execution status return
104      *  @retval OK: Plugin ReadAt succeeded.
105      *  @retval ERROR_NOT_ENOUGH_DATA: Data not enough
106      *  @retval END_OF_STREAM: End of stream
107      */
108     virtual Status ReadAt(int64_t offset, std::shared_ptr<Buffer>& buffer, size_t expectedLen) = 0;
109 
110     /**
111      * @brief Get data source size.
112      *
113      * @param size data source size.
114      * @return  Execution status return.
115      *  @retval OK: Plugin GetSize succeeded.
116      */
117     virtual Status GetSize(uint64_t& size) = 0;
118 
119     /**
120      * @brief Indicates that the current data source seekable or not.
121      *
122      * The function is valid only after INITIALIZED state.
123      *
124      * @return  Seekable status
125      */
126     virtual Seekable GetSeekable() = 0;
127 
128     virtual int32_t GetStreamID() = 0;
129 
130     virtual bool IsDash() = 0;
131 };
132 
133 /// Plugin create function. All plugins must implement this function.
134 template <typename T>
135 using PluginCreatorFunc = std::function<std::shared_ptr<T>(const std::string& name)>;
136 
137 /// Sniff function
138 using PluginSnifferFunc = int (*)(const std::string& name, std::shared_ptr<DataSource> dataSource);
139 
140 /**
141  * @brief Describes the basic information about the plugin.
142  *
143  * @since 1.0
144  * @version 1.0
145  */
146 struct PluginDefBase {
147     uint32_t apiVersion{0}; ///< Versions of different plugins. Different types of plugin have their own versions.
148 
149     PluginType pluginType = PluginType::INVALID_TYPE; ///< Describe the plugin type, e.g. 'source', 'codec'.
150 
151     std::string name;   ///< Indicates the name of a plugin. The name of the same type plugins must be unique.
152                         ///< Plugins with the same name may fail to be registered.
153 
154     std::string description; ///< Detailed description of the plugin.
155 
156     uint32_t rank{0};  ///< Plugin score. The plugin with a high score may be preferred. You can evaluate the
157                     ///< plugin score in terms of performance, version support, and license. Range: 0 to 100.
158 
PluginDefBasePluginDefBase159     PluginDefBase()
160     {
161         pluginType = PluginType::INVALID_TYPE;
162     }
163 
~PluginDefBasePluginDefBase164     virtual ~PluginDefBase() {}
165 
AddInCapsPluginDefBase166     virtual void AddInCaps(Capability& capability)
167     {
168         inCaps.emplace_back(capability);
169     }
170 
AddOutCapsPluginDefBase171     virtual void AddOutCaps(Capability& capability)
172     {
173         outCaps.emplace_back(capability);
174     }
175 
AddExtensionsPluginDefBase176     virtual void AddExtensions(std::vector<std::string> ex)
177     {
178         auto iter = ex.begin();
179         while (iter != ex.end()) {
180             extensions.emplace_back(*iter);
181             iter++;
182         }
183     }
184 
GetExtensionsPluginDefBase185     virtual std::vector<std::string> GetExtensions() const
186     {
187         return extensions;
188     }
189 
GetInCapsPluginDefBase190     virtual CapabilitySet GetInCaps() const
191     {
192         return inCaps;
193     }
194 
GetOutCapsPluginDefBase195     virtual CapabilitySet GetOutCaps() const
196     {
197         return outCaps;
198     }
199 
GetCreatorPluginDefBase200     virtual PluginCreatorFunc<PluginBase> GetCreator() const
201     {
202         return creator;
203     }
204 
SetCreatorPluginDefBase205     virtual void SetCreator(PluginCreatorFunc<PluginBase> creatorFunc)
206     {
207         creator = creatorFunc;
208     }
209 
GetSnifferPluginDefBase210     virtual PluginSnifferFunc GetSniffer() const
211     {
212         return sniffer;
213     }
214 
SetSnifferPluginDefBase215     virtual void SetSniffer(PluginSnifferFunc sniffFunc)
216     {
217         sniffer = sniffFunc;
218     }
219 
220 private:
221     std::vector<std::string> extensions;      ///< File extensions
222     CapabilitySet inCaps;                     ///< Plug-in input capability, For details, @see Capability.
223     CapabilitySet outCaps;                    ///< Plug-in output capability, For details, @see Capability.
224     PluginCreatorFunc<PluginBase> creator {nullptr}; ///< plugin create function.
225     PluginSnifferFunc sniffer {nullptr};         ///< plugin sniff function.
226 };
227 
228 /**
229  * @brief The plugin registration interface.
230  * The plugin framework will provide the implementation.
231  * Developers only need to invoke the API to register the plugin.
232  *
233  * @since 1.0
234  * @version 1.0
235  */
236 struct Register {
237     virtual ~Register() = default;
238     /**
239      * @brief Register the plugin.
240      *
241      * @param def   Basic information about the plugin
242      * @return  Registration status return
243      *  @retval OK: The plugin is registered succeed.
244      *  @retval ERROR_PLUGIN_ALREADY_EXISTS: The plugin already exists in plugin registered.
245      *  @retval ERROR_INCOMPATIBLE_VERSION: Incompatible version during plugin registration.
246      */
247     virtual Status AddPlugin(const PluginDefBase& def) = 0;
248 };
249 
250 /**
251  * @brief The package registration interface.
252  * The plugin framework will provide the implementation and auto invoke the API to
253  * finish the package registration when plugin framework first time be initialized.
254  *
255  * @since 1.0
256  * @version 1.0
257  */
258 struct PackageRegister : Register {
259     ~PackageRegister() override = default;
260 
261     /**
262      * @brief Register the package.
263      * During package registration, all plugins in the package are automatically registered.
264      *
265      * @param def   plugin packaging information.
266      * @return  Registration status return
267      *  @retval OK: The package is registered succeed without any errors.
268      *  @retval ERROR_PLUGIN_ALREADY_EXISTS: The package or plugins already exists.
269      *  @retval ERROR_INCOMPATIBLE_VERSION: Incompatible plugin interface version or api version.
270      */
271     virtual Status AddPackage(const PackageDef& def) = 0;
272 };
273 
274 /// Plugin registration function, all plugins must be implemented.
275 using RegisterFunc = Status (*)(const std::shared_ptr<PackageRegister>& reg);
276 
277 /// Plugin deregister function, all plugins must be implemented.
278 using UnregisterFunc = void (*)();
279 
280 #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
281 #define PLUGIN_EXPORT extern "C" __declspec(dllexport)
282 #else
283 #if defined(__GNUC__) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590))
284 #define PLUGIN_EXPORT extern "C" __attribute__((visibility("default")))
285 #else
286 #define PLUGIN_EXPORT
287 #endif
288 #endif
289 
290 /// Macro definition, string concatenation
291 #define PLUGIN_PASTE_ARGS(str1, str2) str1##str2
292 
293 /// Macro definition, string concatenation
294 #define PLUGIN_PASTE(str1, str2) PLUGIN_PASTE_ARGS(str1, str2)
295 
296 /// Macro definition, stringify
297 #define PLUGIN_STRINGIFY_ARG(str) #str
298 
299 /// Macro definition, stringify
300 #define PLUGIN_STRINGIFY(str) PLUGIN_STRINGIFY_ARG(str)
301 
302 /**
303  * @brief Macro definition, Defines basic plugin information.
304  * Which is invoked during plugin package registration. All plugin packages must be implemented.
305  *
306  * @param name              Package name. For details, @see PackageDef::name
307  * @param license           Package License, For details, @see PackageDef::licenseType
308  * @param registerFunc      Plugin registration function, MUST NOT be NULL.
309  * @param unregisterFunc    Plugin deregister function,MUST NOT be NULL.
310  */
311 #define PLUGIN_DEFINITION(name, license, registerFunc, unregisterFunc)                                          \
312     PLUGIN_EXPORT OHOS::Media::Status PLUGIN_PASTE(register_, name)(                                            \
313         const std::shared_ptr<OHOS::Media::Plugins::PackageRegister>& pkgReg)                                   \
314     {                                                                                                           \
315         pkgReg->AddPackage({PLUGIN_INTERFACE_VERSION, PLUGIN_STRINGIFY(name), license});                        \
316         std::shared_ptr<OHOS::Media::Plugins::Register> pluginReg = pkgReg;                                     \
317         return registerFunc(pluginReg);                                                                         \
318     }                                                                                                           \
319     PLUGIN_EXPORT void PLUGIN_PASTE(unregister_, name)()                                                        \
320     {                                                                                                           \
321         unregisterFunc();                                                                                       \
322     }
323 } // namespace Plugins
324 } // namespace Media
325 } // namespace OHOS
326 #endif // HISTREAMER_PLUGINS_INTF_PLUGIN_DEFINITION_H
327