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}