basis_universal/transcoding/mod.rs
1use basis_universal_sys as sys;
2use std::sync::atomic::{AtomicBool, Ordering};
3use std::sync::Mutex;
4
5mod enums;
6pub use enums::*;
7
8mod transcoder;
9pub use transcoder::*;
10
11#[cfg(test)]
12mod transcoding_tests;
13
14static TRANSCODER_INIT_CALLED: AtomicBool = AtomicBool::new(false);
15lazy_static::lazy_static! {
16 static ref TRANSCODER_INIT_LOCK: Mutex<()> = Mutex::default();
17}
18
19/// The underlying C++ library requires that transcoder_init() has been called before a .basis file
20/// can be encoded. This function allows a user to do this early in the application explicitly. It
21/// is protected by a lock and AtomicBool flag so it is safe and cheap to call multiple times, and
22/// correctly handles multiple threads trying to initialize at the same time.
23pub fn transcoder_init() {
24 unsafe {
25 // Early out if it has been initialized
26 if !TRANSCODER_INIT_CALLED.load(Ordering::Acquire) {
27 // Lock and check again to ensure that exactly one thread runs the init code and that
28 // all other threads wait for it to complete and don't re-run it.
29 let lock = TRANSCODER_INIT_LOCK.lock().unwrap();
30 if !TRANSCODER_INIT_CALLED.load(Ordering::Acquire) {
31 // Run the init code
32 sys::basisu_encoder_init();
33 TRANSCODER_INIT_CALLED.store(true, Ordering::Release);
34 }
35 std::mem::drop(lock);
36 }
37 }
38}