use super::ffi::*;
use libloading::Library;
use std::sync::OnceLock;
const ENV_ENABLE: &str = "EDGEFIRST_ENABLE_NVJPEG";
const CANDIDATES: &[&str] = &[
"/usr/local/cuda/targets/aarch64-linux/lib/libnvjpeg.so.12",
"/usr/local/cuda/targets/aarch64-linux/lib/libnvjpeg.so",
"/usr/local/cuda/targets/x86_64-linux/lib/libnvjpeg.so.12",
"/usr/local/cuda/lib64/libnvjpeg.so.12",
"/usr/local/cuda/lib64/libnvjpeg.so",
"libnvjpeg.so.12",
];
pub(crate) struct NvjpegLib {
_lib: &'static Library,
pub create_ex: FnCreateEx,
pub jpeg_state_create: FnJpegStateCreate,
pub get_image_info: FnGetImageInfo,
pub decode: FnDecode,
pub destroy: FnDestroy,
pub jpeg_state_destroy: FnJpegStateDestroy,
}
static LIB: OnceLock<Option<NvjpegLib>> = OnceLock::new();
fn load() -> Option<NvjpegLib> {
if !crate::jpeg::env_flag(ENV_ENABLE) {
log::debug!("nvjpeg off by default; set {ENV_ENABLE}=1 to enable");
return None;
}
for name in CANDIDATES {
let Ok(lib) = (unsafe { Library::new(*name) }) else {
continue;
};
match resolve(&lib) {
Some((
create_ex,
jpeg_state_create,
get_image_info,
decode,
destroy,
jpeg_state_destroy,
)) => {
let lib: &'static Library = Box::leak(Box::new(lib));
log::info!("nvjpeg loaded from {name}");
return Some(NvjpegLib {
_lib: lib,
create_ex,
jpeg_state_create,
get_image_info,
decode,
destroy,
jpeg_state_destroy,
});
}
None => continue,
}
}
log::debug!("nvjpeg unavailable (no libnvjpeg.so.12 with nvjpeg* symbols found)");
None
}
#[allow(clippy::type_complexity)]
fn resolve(
lib: &Library,
) -> Option<(
FnCreateEx,
FnJpegStateCreate,
FnGetImageInfo,
FnDecode,
FnDestroy,
FnJpegStateDestroy,
)> {
macro_rules! sym {
($n:literal) => {
*unsafe { lib.get(concat!($n, "\0").as_bytes()) }.ok()?
};
}
Some((
sym!("nvjpegCreateEx"),
sym!("nvjpegJpegStateCreate"),
sym!("nvjpegGetImageInfo"),
sym!("nvjpegDecode"),
sym!("nvjpegDestroy"),
sym!("nvjpegJpegStateDestroy"),
))
}
pub(crate) fn lib() -> Option<&'static NvjpegLib> {
LIB.get_or_init(load).as_ref()
}
pub fn is_nvjpeg_available() -> bool {
lib().is_some() && edgefirst_tensor::is_cuda_available()
}