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 { APILoader::WelsCreateSVCEncoder(self, ppEncoder) }
61 unsafe fn WelsDestroySVCEncoder(&self, pEncoder: *mut ISVCEncoder) { APILoader::WelsDestroySVCEncoder(self, pEncoder) }
62 unsafe fn WelsGetDecoderCapability(&self, pDecCapability: *mut SDecoderCapability) -> c_int { APILoader::WelsGetDecoderCapability(self, pDecCapability) }
63 unsafe fn WelsCreateDecoder(&self, ppDecoder: *mut *mut ISVCDecoder) -> c_long { APILoader::WelsCreateDecoder(self, ppDecoder) }
64 unsafe fn WelsDestroyDecoder(&self, pDecoder: *mut ISVCDecoder) { APILoader::WelsDestroyDecoder(self, pDecoder) }
65 unsafe fn WelsGetCodecVersion(&self) -> OpenH264Version { APILoader::WelsGetCodecVersion(self) }
66 unsafe fn WelsGetCodecVersionEx(&self, pVersion: *mut OpenH264Version) {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
108pub enum DynamicAPI {
113 #[cfg(feature = "source")]
114 Source(source::APILoader),
115
116 #[cfg(feature = "libloading")]
117 Libloading(libloading::APILoader),
118}
119
120impl DynamicAPI {
121 #[cfg(feature = "source")]
123 pub const fn from_source() -> Self {
124 let api = crate::source::APILoader;
125 Self::Source(api)
126 }
127
128 #[cfg(feature = "libloading")]
142 pub unsafe fn from_blob_path_unchecked(path: impl AsRef<std::ffi::OsStr>) -> Result<Self, Error> {
143 let api = unsafe { libloading::APILoader::new(path)? };
144 Ok(Self::Libloading(api))
145 }
146
147 #[cfg(feature = "libloading")]
160 pub fn from_blob_path(path: impl AsRef<std::ffi::OsStr>) -> Result<Self, Error> {
161 use sha2::Digest;
162 use std::fmt::Write;
163
164 let bytes = std::fs::read(path.as_ref())?;
165
166 let sha256 = sha2::Sha256::digest(bytes).iter().fold(String::new(), |mut acc, byte| {
168 write!(&mut acc, "{:02x}", byte).unwrap(); acc
170 });
171
172 let hash_is_well_known = include_str!("blobs/hashes.txt")
175 .lines()
176 .filter_map(|line| line.split_whitespace().next())
177 .any(|x| x == sha256);
178
179 if !hash_is_well_known {
180 return Err(Error::InvalidHash(sha256));
181 }
182
183 unsafe { Self::from_blob_path_unchecked(path) }
184 }
185}
186
187#[allow(unreachable_patterns)]
188#[allow(unused)]
189impl API for DynamicAPI {
190 unsafe fn WelsCreateSVCEncoder(&self, ppEncoder: *mut *mut ISVCEncoder) -> c_int {
191 unsafe {
192 match self {
193 #[cfg(feature = "source")]
194 DynamicAPI::Source(api) => api.WelsCreateSVCEncoder(ppEncoder),
195 #[cfg(feature = "libloading")]
196 DynamicAPI::Libloading(api) => api.WelsCreateSVCEncoder(ppEncoder),
197 _ => panic!("No API enabled"),
198 }
199 }
200 }
201
202 unsafe fn WelsDestroySVCEncoder(&self, pEncoder: *mut ISVCEncoder) {
203 unsafe {
204 match self {
205 #[cfg(feature = "source")]
206 DynamicAPI::Source(api) => api.WelsDestroySVCEncoder(pEncoder),
207 #[cfg(feature = "libloading")]
208 DynamicAPI::Libloading(api) => api.WelsDestroySVCEncoder(pEncoder),
209 _ => panic!("No API enabled"),
210 }
211 }
212 }
213
214 unsafe fn WelsGetDecoderCapability(&self, pDecCapability: *mut SDecoderCapability) -> c_int {
215 unsafe {
216 match self {
217 #[cfg(feature = "source")]
218 DynamicAPI::Source(api) => api.WelsGetDecoderCapability(pDecCapability),
219 #[cfg(feature = "libloading")]
220 DynamicAPI::Libloading(api) => api.WelsGetDecoderCapability(pDecCapability),
221 _ => panic!("No API enabled"),
222 }
223 }
224 }
225
226 unsafe fn WelsCreateDecoder(&self, ppDecoder: *mut *mut ISVCDecoder) -> c_long {
227 unsafe {
228 match self {
229 #[cfg(feature = "source")]
230 DynamicAPI::Source(api) => api.WelsCreateDecoder(ppDecoder),
231 #[cfg(feature = "libloading")]
232 DynamicAPI::Libloading(api) => api.WelsCreateDecoder(ppDecoder),
233 _ => panic!("No API enabled"),
234 }
235 }
236 }
237
238 unsafe fn WelsDestroyDecoder(&self, pDecoder: *mut ISVCDecoder) {
239 unsafe {
240 match self {
241 #[cfg(feature = "source")]
242 DynamicAPI::Source(api) => api.WelsDestroyDecoder(pDecoder),
243 #[cfg(feature = "libloading")]
244 DynamicAPI::Libloading(api) => api.WelsDestroyDecoder(pDecoder),
245 _ => panic!("No API enabled"),
246 }
247 }
248 }
249
250 unsafe fn WelsGetCodecVersion(&self) -> OpenH264Version {
251 unsafe {
252 match self {
253 #[cfg(feature = "source")]
254 DynamicAPI::Source(api) => api.WelsGetCodecVersion(),
255 #[cfg(feature = "libloading")]
256 DynamicAPI::Libloading(api) => api.WelsGetCodecVersion(),
257 _ => panic!("No API enabled"),
258 }
259 }
260 }
261
262 unsafe fn WelsGetCodecVersionEx(&self, pVersion: *mut OpenH264Version) {
263 unsafe {
264 match self {
265 #[cfg(feature = "source")]
266 DynamicAPI::Source(api) => api.WelsGetCodecVersionEx(pVersion),
267 #[cfg(feature = "libloading")]
268 DynamicAPI::Libloading(api) => api.WelsGetCodecVersionEx(pVersion),
269 _ => panic!("No API enabled"),
270 }
271 }
272 }
273}
274
275#[doc(hidden)]
278#[cfg(all(target_os = "windows", target_arch = "x86_64", feature = "libloading"))]
279pub fn reference_dll_name() -> &'static str {
280 include_str!("../tests/reference/reference.txt")
281}