1#![allow(non_snake_case)]
23#![allow(non_camel_case_types)]
24#![allow(non_upper_case_globals)]
25#![allow(clippy::missing_safety_doc)]
26
27mod error;
28
29mod generated {
31 pub mod consts;
32 #[cfg(feature = "libloading")]
33 pub mod fns_libloading;
34 #[cfg(feature = "source")]
35 pub mod fns_source;
36 pub mod types;
37}
38
39pub use self::generated::consts::*;
40pub use self::generated::types::*;
41pub use error::Error;
42use std::os::raw::{c_int, c_long};
43
44#[rustfmt::skip]
46#[allow(clippy::missing_safety_doc)]
47pub trait API {
48 unsafe fn WelsCreateSVCEncoder(&self, ppEncoder: *mut *mut ISVCEncoder) -> ::std::os::raw::c_int;
49 unsafe fn WelsDestroySVCEncoder(&self, pEncoder: *mut ISVCEncoder);
50 unsafe fn WelsGetDecoderCapability(&self, pDecCapability: *mut SDecoderCapability) -> ::std::os::raw::c_int;
51 unsafe fn WelsCreateDecoder(&self, ppDecoder: *mut *mut ISVCDecoder) -> ::std::os::raw::c_long;
52 unsafe fn WelsDestroyDecoder(&self, pDecoder: *mut ISVCDecoder);
53 unsafe fn WelsGetCodecVersion(&self) -> OpenH264Version;
54 unsafe fn WelsGetCodecVersionEx(&self, pVersion: *mut OpenH264Version);
55}
56
57#[cfg(feature = "libloading")]
72pub mod libloading {
73 pub use crate::generated::fns_libloading::*;
74 use crate::{ISVCDecoder, ISVCEncoder, OpenH264Version, SDecoderCapability};
75 use std::os::raw::{c_int, c_long};
76
77 #[rustfmt::skip]
78 impl super::API for APILoader {
79 unsafe fn WelsCreateSVCEncoder(&self, ppEncoder: *mut *mut ISVCEncoder) -> c_int { APILoader::WelsCreateSVCEncoder(self, ppEncoder) }
80 unsafe fn WelsDestroySVCEncoder(&self, pEncoder: *mut ISVCEncoder) { APILoader::WelsDestroySVCEncoder(self, pEncoder) }
81 unsafe fn WelsGetDecoderCapability(&self, pDecCapability: *mut SDecoderCapability) -> c_int { APILoader::WelsGetDecoderCapability(self, pDecCapability) }
82 unsafe fn WelsCreateDecoder(&self, ppDecoder: *mut *mut ISVCDecoder) -> c_long { APILoader::WelsCreateDecoder(self, ppDecoder) }
83 unsafe fn WelsDestroyDecoder(&self, pDecoder: *mut ISVCDecoder) { APILoader::WelsDestroyDecoder(self, pDecoder) }
84 unsafe fn WelsGetCodecVersion(&self) -> OpenH264Version { APILoader::WelsGetCodecVersion(self) }
85 unsafe fn WelsGetCodecVersionEx(&self, pVersion: *mut OpenH264Version) {APILoader::WelsGetCodecVersionEx(self, pVersion) }
86 }
87}
88
89#[cfg(feature = "source")]
94pub mod source {
95 use crate::{ISVCDecoder, ISVCEncoder, OpenH264Version, SDecoderCapability};
96 use std::os::raw::{c_int, c_long};
97
98 #[derive(Debug, Default)]
99 pub struct APILoader {}
100
101 #[rustfmt::skip]
102 #[allow(clippy::missing_safety_doc)]
103 impl APILoader {
104 pub fn new() -> Self { Self {} }
105 pub unsafe fn WelsCreateSVCEncoder(&self, ppEncoder: *mut *mut ISVCEncoder) -> ::std::os::raw::c_int { crate::generated::fns_source::WelsCreateSVCEncoder(ppEncoder) }
106 pub unsafe fn WelsDestroySVCEncoder(&self, pEncoder: *mut ISVCEncoder) { crate::generated::fns_source::WelsDestroySVCEncoder(pEncoder) }
107 pub unsafe fn WelsGetDecoderCapability(&self, pDecCapability: *mut SDecoderCapability) -> ::std::os::raw::c_int { crate::generated::fns_source::WelsGetDecoderCapability(pDecCapability) }
108 pub unsafe fn WelsCreateDecoder(&self, ppDecoder: *mut *mut ISVCDecoder) -> ::std::os::raw::c_long { crate::generated::fns_source::WelsCreateDecoder(ppDecoder) }
109 pub unsafe fn WelsDestroyDecoder(&self, pDecoder: *mut ISVCDecoder) { crate::generated::fns_source::WelsDestroyDecoder(pDecoder) }
110 pub unsafe fn WelsGetCodecVersion(&self) -> OpenH264Version { crate::generated::fns_source::WelsGetCodecVersion() }
111 pub unsafe fn WelsGetCodecVersionEx(&self, pVersion: *mut OpenH264Version) { crate::generated::fns_source::WelsGetCodecVersionEx(pVersion) }
112 }
113
114 #[rustfmt::skip]
115 #[allow(clippy::missing_safety_doc)]
116 impl super::API for APILoader {
117 unsafe fn WelsCreateSVCEncoder(&self, ppEncoder: *mut *mut ISVCEncoder) -> c_int { APILoader::WelsCreateSVCEncoder(self, ppEncoder) }
118 unsafe fn WelsDestroySVCEncoder(&self, pEncoder: *mut ISVCEncoder) { APILoader::WelsDestroySVCEncoder(self, pEncoder) }
119 unsafe fn WelsGetDecoderCapability(&self, pDecCapability: *mut SDecoderCapability) -> c_int { APILoader::WelsGetDecoderCapability(self, pDecCapability) }
120 unsafe fn WelsCreateDecoder(&self, ppDecoder: *mut *mut ISVCDecoder) -> c_long { APILoader::WelsCreateDecoder(self, ppDecoder) }
121 unsafe fn WelsDestroyDecoder(&self, pDecoder: *mut ISVCDecoder) { APILoader::WelsDestroyDecoder(self, pDecoder) }
122 unsafe fn WelsGetCodecVersion(&self) -> OpenH264Version { APILoader::WelsGetCodecVersion(self) }
123 unsafe fn WelsGetCodecVersionEx(&self, pVersion: *mut OpenH264Version) { APILoader::WelsGetCodecVersionEx(self, pVersion) }
124 }
125}
126
127pub enum DynamicAPI {
132 #[cfg(feature = "source")]
133 Source(source::APILoader),
134
135 #[cfg(feature = "libloading")]
136 Libloading(libloading::APILoader),
137}
138
139impl DynamicAPI {
140 #[cfg(feature = "source")]
142 pub fn from_source() -> Self {
143 let api = crate::source::APILoader::new();
144 Self::Source(api)
145 }
146
147 #[cfg(feature = "libloading")]
161 pub unsafe fn from_blob_path_unchecked(path: impl AsRef<std::ffi::OsStr>) -> Result<Self, Error> {
162 let api = unsafe { libloading::APILoader::new(path)? };
163 Ok(Self::Libloading(api))
164 }
165
166 #[cfg(feature = "libloading")]
179 pub fn from_blob_path(path: impl AsRef<std::ffi::OsStr>) -> Result<Self, Error> {
180 use sha2::Digest;
181 use std::fmt::Write;
182
183 let bytes = std::fs::read(path.as_ref())?;
184
185 let sha256 = sha2::Sha256::digest(bytes).iter().fold(String::new(), |mut acc, byte| {
187 write!(&mut acc, "{:02x}", byte).unwrap(); acc
189 });
190
191 let hash_is_well_known = include_str!("blobs/hashes.txt")
194 .lines()
195 .filter_map(|line| line.split_whitespace().next())
196 .any(|x| x == sha256);
197
198 if !hash_is_well_known {
199 return Err(Error::InvalidHash(sha256));
200 }
201
202 unsafe { Self::from_blob_path_unchecked(path) }
203 }
204}
205
206#[allow(unreachable_patterns)]
207#[allow(unused)]
208impl API for DynamicAPI {
209 unsafe fn WelsCreateSVCEncoder(&self, ppEncoder: *mut *mut ISVCEncoder) -> c_int {
210 match self {
211 #[cfg(feature = "source")]
212 DynamicAPI::Source(api) => api.WelsCreateSVCEncoder(ppEncoder),
213 #[cfg(feature = "libloading")]
214 DynamicAPI::Libloading(api) => api.WelsCreateSVCEncoder(ppEncoder),
215 _ => panic!("No API enabled"),
216 }
217 }
218
219 unsafe fn WelsDestroySVCEncoder(&self, pEncoder: *mut ISVCEncoder) {
220 match self {
221 #[cfg(feature = "source")]
222 DynamicAPI::Source(api) => api.WelsDestroySVCEncoder(pEncoder),
223 #[cfg(feature = "libloading")]
224 DynamicAPI::Libloading(api) => api.WelsDestroySVCEncoder(pEncoder),
225 _ => panic!("No API enabled"),
226 }
227 }
228
229 unsafe fn WelsGetDecoderCapability(&self, pDecCapability: *mut SDecoderCapability) -> c_int {
230 match self {
231 #[cfg(feature = "source")]
232 DynamicAPI::Source(api) => api.WelsGetDecoderCapability(pDecCapability),
233 #[cfg(feature = "libloading")]
234 DynamicAPI::Libloading(api) => api.WelsGetDecoderCapability(pDecCapability),
235 _ => panic!("No API enabled"),
236 }
237 }
238
239 unsafe fn WelsCreateDecoder(&self, ppDecoder: *mut *mut ISVCDecoder) -> c_long {
240 match self {
241 #[cfg(feature = "source")]
242 DynamicAPI::Source(api) => api.WelsCreateDecoder(ppDecoder),
243 #[cfg(feature = "libloading")]
244 DynamicAPI::Libloading(api) => api.WelsCreateDecoder(ppDecoder),
245 _ => panic!("No API enabled"),
246 }
247 }
248
249 unsafe fn WelsDestroyDecoder(&self, pDecoder: *mut ISVCDecoder) {
250 match self {
251 #[cfg(feature = "source")]
252 DynamicAPI::Source(api) => api.WelsDestroyDecoder(pDecoder),
253 #[cfg(feature = "libloading")]
254 DynamicAPI::Libloading(api) => api.WelsDestroyDecoder(pDecoder),
255 _ => panic!("No API enabled"),
256 }
257 }
258
259 unsafe fn WelsGetCodecVersion(&self) -> OpenH264Version {
260 match self {
261 #[cfg(feature = "source")]
262 DynamicAPI::Source(api) => api.WelsGetCodecVersion(),
263 #[cfg(feature = "libloading")]
264 DynamicAPI::Libloading(api) => api.WelsGetCodecVersion(),
265 _ => panic!("No API enabled"),
266 }
267 }
268
269 unsafe fn WelsGetCodecVersionEx(&self, pVersion: *mut OpenH264Version) {
270 match self {
271 #[cfg(feature = "source")]
272 DynamicAPI::Source(api) => api.WelsGetCodecVersionEx(pVersion),
273 #[cfg(feature = "libloading")]
274 DynamicAPI::Libloading(api) => api.WelsGetCodecVersionEx(pVersion),
275 _ => panic!("No API enabled"),
276 }
277 }
278}
279
280#[doc(hidden)]
283#[cfg(all(target_os = "windows", target_arch = "x86_64", feature = "libloading"))]
284pub fn reference_dll_name() -> &'static str {
285 include_str!("../tests/reference/reference.txt")
286}