1#![allow(non_snake_case)]
2#![allow(unpredictable_function_pointer_comparisons)]
3#![allow(non_camel_case_types)]
4#![allow(non_upper_case_globals)]
5#![allow(clippy::missing_safety_doc)]
6#![doc = include_str!("../README.md")]
7
8mod error;
9
10mod generated {
12 pub mod consts;
13 #[cfg(feature = "libloading")]
14 pub mod fns_libloading;
15 #[cfg(feature = "source")]
16 pub mod fns_source;
17 pub mod types;
18}
19
20pub use self::generated::consts::*;
21pub use self::generated::types::*;
22pub use error::Error;
23use std::os::raw::{c_int, c_long};
24
25#[rustfmt::skip]
27#[allow(clippy::missing_safety_doc)]
28pub trait API {
29 unsafe fn WelsCreateSVCEncoder(&self, ppEncoder: *mut *mut ISVCEncoder) -> ::std::os::raw::c_int;
30 unsafe fn WelsDestroySVCEncoder(&self, pEncoder: *mut ISVCEncoder);
31 unsafe fn WelsGetDecoderCapability(&self, pDecCapability: *mut SDecoderCapability) -> ::std::os::raw::c_int;
32 unsafe fn WelsCreateDecoder(&self, ppDecoder: *mut *mut ISVCDecoder) -> ::std::os::raw::c_long;
33 unsafe fn WelsDestroyDecoder(&self, pDecoder: *mut ISVCDecoder);
34 unsafe fn WelsGetCodecVersion(&self) -> OpenH264Version;
35 unsafe fn WelsGetCodecVersionEx(&self, pVersion: *mut OpenH264Version);
36}
37
38#[cfg(feature = "libloading")]
53pub mod libloading {
54 pub use crate::generated::fns_libloading::*;
55 use crate::{ISVCDecoder, ISVCEncoder, OpenH264Version, SDecoderCapability};
56 use std::os::raw::{c_int, c_long};
57
58 #[rustfmt::skip]
59 impl super::API for APILoader {
60 unsafe fn WelsCreateSVCEncoder(&self, ppEncoder: *mut *mut ISVCEncoder) -> c_int { unsafe { APILoader::WelsCreateSVCEncoder(self, ppEncoder) } }
61 unsafe fn WelsDestroySVCEncoder(&self, pEncoder: *mut ISVCEncoder) { unsafe { APILoader::WelsDestroySVCEncoder(self, pEncoder) } }
62 unsafe fn WelsGetDecoderCapability(&self, pDecCapability: *mut SDecoderCapability) -> c_int { unsafe { APILoader::WelsGetDecoderCapability(self, pDecCapability) } }
63 unsafe fn WelsCreateDecoder(&self, ppDecoder: *mut *mut ISVCDecoder) -> c_long { unsafe { APILoader::WelsCreateDecoder(self, ppDecoder) } }
64 unsafe fn WelsDestroyDecoder(&self, pDecoder: *mut ISVCDecoder) { unsafe { APILoader::WelsDestroyDecoder(self, pDecoder) } }
65 unsafe fn WelsGetCodecVersion(&self) -> OpenH264Version { unsafe { APILoader::WelsGetCodecVersion(self) } }
66 unsafe fn WelsGetCodecVersionEx(&self, pVersion: *mut OpenH264Version) { unsafe { APILoader::WelsGetCodecVersionEx(self, pVersion) } }
67 }
68}
69
70#[cfg(feature = "source")]
75pub mod source {
76 use crate::{ISVCDecoder, ISVCEncoder, OpenH264Version, SDecoderCapability};
77 use std::os::raw::{c_int, c_long};
78
79 #[derive(Debug, Default)]
80 pub struct APILoader;
81
82 #[rustfmt::skip]
83 #[allow(clippy::missing_safety_doc)]
84 impl APILoader {
85 pub const fn new() -> Self { Self }
86 pub unsafe fn WelsCreateSVCEncoder(ppEncoder: *mut *mut ISVCEncoder) -> ::std::os::raw::c_int { unsafe { crate::generated::fns_source::WelsCreateSVCEncoder(ppEncoder) }}
87 pub unsafe fn WelsDestroySVCEncoder(pEncoder: *mut ISVCEncoder) { unsafe { crate::generated::fns_source::WelsDestroySVCEncoder(pEncoder) }}
88 pub unsafe fn WelsGetDecoderCapability(pDecCapability: *mut SDecoderCapability) -> ::std::os::raw::c_int { unsafe { crate::generated::fns_source::WelsGetDecoderCapability(pDecCapability) }}
89 pub unsafe fn WelsCreateDecoder(ppDecoder: *mut *mut ISVCDecoder) -> ::std::os::raw::c_long { unsafe { crate::generated::fns_source::WelsCreateDecoder(ppDecoder) }}
90 pub unsafe fn WelsDestroyDecoder(pDecoder: *mut ISVCDecoder) { unsafe { crate::generated::fns_source::WelsDestroyDecoder(pDecoder) }}
91 pub unsafe fn WelsGetCodecVersion() -> OpenH264Version { unsafe { crate::generated::fns_source::WelsGetCodecVersion() }}
92 pub unsafe fn WelsGetCodecVersionEx(pVersion: *mut OpenH264Version) { unsafe { crate::generated::fns_source::WelsGetCodecVersionEx(pVersion) }}
93 }
94
95 #[rustfmt::skip]
96 #[allow(clippy::missing_safety_doc)]
97 impl super::API for APILoader {
98 unsafe fn WelsCreateSVCEncoder(&self, ppEncoder: *mut *mut ISVCEncoder) -> c_int { unsafe { APILoader::WelsCreateSVCEncoder(ppEncoder) }}
99 unsafe fn WelsDestroySVCEncoder(&self, pEncoder: *mut ISVCEncoder) { unsafe { APILoader::WelsDestroySVCEncoder(pEncoder) }}
100 unsafe fn WelsGetDecoderCapability(&self, pDecCapability: *mut SDecoderCapability) -> c_int { unsafe { APILoader::WelsGetDecoderCapability(pDecCapability) }}
101 unsafe fn WelsCreateDecoder(&self, ppDecoder: *mut *mut ISVCDecoder) -> c_long { unsafe { APILoader::WelsCreateDecoder(ppDecoder) }}
102 unsafe fn WelsDestroyDecoder(&self, pDecoder: *mut ISVCDecoder) { unsafe { APILoader::WelsDestroyDecoder(pDecoder) }}
103 unsafe fn WelsGetCodecVersion(&self) -> OpenH264Version { unsafe { APILoader::WelsGetCodecVersion() }}
104 unsafe fn WelsGetCodecVersionEx(&self, pVersion: *mut OpenH264Version) { unsafe { APILoader::WelsGetCodecVersionEx(pVersion) }}
105 }
106}
107
108#[allow(clippy::large_enum_variant)]
113pub enum DynamicAPI {
114 #[cfg(feature = "source")]
115 Source(source::APILoader),
116
117 #[cfg(feature = "libloading")]
118 Libloading(libloading::APILoader),
119}
120
121impl DynamicAPI {
122 #[cfg(feature = "source")]
124 pub const fn from_source() -> Self {
125 let api = crate::source::APILoader;
126 Self::Source(api)
127 }
128
129 #[cfg(feature = "libloading")]
143 pub unsafe fn from_blob_path_unchecked(path: impl AsRef<std::ffi::OsStr>) -> Result<Self, Error> {
144 let api = unsafe { libloading::APILoader::new(path)? };
145 Ok(Self::Libloading(api))
146 }
147
148 #[cfg(feature = "libloading")]
161 pub fn from_blob_path(path: impl AsRef<std::ffi::OsStr>) -> Result<Self, Error> {
162 use sha2::Digest;
163 use std::fmt::Write;
164
165 let bytes = std::fs::read(path.as_ref())?;
166
167 let sha256 = sha2::Sha256::digest(bytes).iter().fold(String::new(), |mut acc, byte| {
169 write!(&mut acc, "{:02x}", byte).unwrap(); acc
171 });
172
173 let hash_is_well_known = include_str!("blobs/hashes.txt")
176 .lines()
177 .filter_map(|line| line.split_whitespace().next())
178 .any(|x| x == sha256);
179
180 if !hash_is_well_known {
181 return Err(Error::InvalidHash(sha256));
182 }
183
184 unsafe { Self::from_blob_path_unchecked(path) }
185 }
186}
187
188#[allow(unreachable_patterns)]
189#[allow(unused)]
190impl API for DynamicAPI {
191 unsafe fn WelsCreateSVCEncoder(&self, ppEncoder: *mut *mut ISVCEncoder) -> c_int {
192 unsafe {
193 match self {
194 #[cfg(feature = "source")]
195 DynamicAPI::Source(api) => api.WelsCreateSVCEncoder(ppEncoder),
196 #[cfg(feature = "libloading")]
197 DynamicAPI::Libloading(api) => api.WelsCreateSVCEncoder(ppEncoder),
198 _ => panic!("No API enabled"),
199 }
200 }
201 }
202
203 unsafe fn WelsDestroySVCEncoder(&self, pEncoder: *mut ISVCEncoder) {
204 unsafe {
205 match self {
206 #[cfg(feature = "source")]
207 DynamicAPI::Source(api) => api.WelsDestroySVCEncoder(pEncoder),
208 #[cfg(feature = "libloading")]
209 DynamicAPI::Libloading(api) => api.WelsDestroySVCEncoder(pEncoder),
210 _ => panic!("No API enabled"),
211 }
212 }
213 }
214
215 unsafe fn WelsGetDecoderCapability(&self, pDecCapability: *mut SDecoderCapability) -> c_int {
216 unsafe {
217 match self {
218 #[cfg(feature = "source")]
219 DynamicAPI::Source(api) => api.WelsGetDecoderCapability(pDecCapability),
220 #[cfg(feature = "libloading")]
221 DynamicAPI::Libloading(api) => api.WelsGetDecoderCapability(pDecCapability),
222 _ => panic!("No API enabled"),
223 }
224 }
225 }
226
227 unsafe fn WelsCreateDecoder(&self, ppDecoder: *mut *mut ISVCDecoder) -> c_long {
228 unsafe {
229 match self {
230 #[cfg(feature = "source")]
231 DynamicAPI::Source(api) => api.WelsCreateDecoder(ppDecoder),
232 #[cfg(feature = "libloading")]
233 DynamicAPI::Libloading(api) => api.WelsCreateDecoder(ppDecoder),
234 _ => panic!("No API enabled"),
235 }
236 }
237 }
238
239 unsafe fn WelsDestroyDecoder(&self, pDecoder: *mut ISVCDecoder) {
240 unsafe {
241 match self {
242 #[cfg(feature = "source")]
243 DynamicAPI::Source(api) => api.WelsDestroyDecoder(pDecoder),
244 #[cfg(feature = "libloading")]
245 DynamicAPI::Libloading(api) => api.WelsDestroyDecoder(pDecoder),
246 _ => panic!("No API enabled"),
247 }
248 }
249 }
250
251 unsafe fn WelsGetCodecVersion(&self) -> OpenH264Version {
252 unsafe {
253 match self {
254 #[cfg(feature = "source")]
255 DynamicAPI::Source(api) => api.WelsGetCodecVersion(),
256 #[cfg(feature = "libloading")]
257 DynamicAPI::Libloading(api) => api.WelsGetCodecVersion(),
258 _ => panic!("No API enabled"),
259 }
260 }
261 }
262
263 unsafe fn WelsGetCodecVersionEx(&self, pVersion: *mut OpenH264Version) {
264 unsafe {
265 match self {
266 #[cfg(feature = "source")]
267 DynamicAPI::Source(api) => api.WelsGetCodecVersionEx(pVersion),
268 #[cfg(feature = "libloading")]
269 DynamicAPI::Libloading(api) => api.WelsGetCodecVersionEx(pVersion),
270 _ => panic!("No API enabled"),
271 }
272 }
273 }
274}
275
276#[doc(hidden)]
279#[cfg(all(target_os = "windows", target_arch = "x86_64", feature = "libloading"))]
280pub fn reference_dll_name() -> &'static str {
281 include_str!("../tests/reference/reference.txt")
282}