faad2/
lib.rs

1use std::ffi::CStr;
2use std::fmt::{self, Debug, Display};
3use std::marker::Send;
4use std::mem::MaybeUninit;
5use std::ptr;
6use std::slice;
7use std::str;
8
9use faad2_sys::{self, NeAACDecHandle, c_char, c_uchar, c_ulong};
10
11unsafe fn static_cstr(ptr: *const c_char) -> &'static str {
12    str::from_utf8_unchecked(CStr::from_ptr(ptr).to_bytes())
13}
14
15pub fn version() -> (&'static str, &'static str) {
16    unsafe {
17        let mut id: *const c_char = ptr::null();
18        let mut copyright: *const c_char = ptr::null();
19
20        faad2_sys::NeAACDecGetVersion(&mut id as *mut _, &mut copyright as *mut _);
21
22        (static_cstr(id), static_cstr(copyright))
23    }
24}
25
26pub struct Error(c_uchar);
27
28impl Error {
29    pub fn message(&self) -> &'static str {
30        unsafe {
31            static_cstr(faad2_sys::NeAACDecGetErrorMessage(self.0))
32        }
33    }
34}
35
36impl Display for Error {
37    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
38        write!(f, "{}", self.message())
39    }
40}
41
42impl Debug for Error {
43    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
44        write!(f, "Error {{ code: {:?}, message: {:?} }}", self.0, self.message())
45    }
46}
47
48struct DecoderHandle {
49    handle: NeAACDecHandle,
50}
51
52unsafe impl Send for DecoderHandle {}
53
54impl DecoderHandle {
55    fn alloc() -> Self {
56        let handle = unsafe { faad2_sys::NeAACDecOpen() };
57
58        if handle == ptr::null_mut() {
59            panic!("NeAACDecOpen failed")
60        } else {
61            DecoderHandle { handle }
62        }
63    }
64}
65
66impl Drop for DecoderHandle {
67    fn drop(&mut self) {
68        unsafe {
69            faad2_sys::NeAACDecClose(self.handle);
70        }
71    }
72}
73
74pub struct Decoder {
75    decoder: DecoderHandle,
76    sample_rate: usize,
77    channels: usize,
78}
79
80#[derive(Debug)]
81pub struct DecodeResult<'a> {
82    pub samples: &'a [f32],
83    pub bytes_consumed: usize,
84    pub channels: usize,
85    pub sample_rate: usize,
86}
87
88impl Decoder {
89    pub fn new(audio_specific_config: &[u8]) -> Result<Self, ()> {
90        unsafe {
91            let decoder = DecoderHandle::alloc();
92
93            let mut config = faad2_sys::NeAACDecGetCurrentConfiguration(decoder.handle);
94            (*config).outputFormat = faad2_sys::FAAD_FMT_FLOAT;
95            if faad2_sys::NeAACDecSetConfiguration(decoder.handle, config) != 1 {
96                return Err(());
97            }
98
99            let mut sample_rate: c_ulong = 0;
100            let mut channels: c_uchar = 0;
101
102            let err = faad2_sys::NeAACDecInit2(
103                decoder.handle,
104                audio_specific_config.as_ptr(),
105                audio_specific_config.len() as c_ulong,
106                &mut sample_rate as *mut _,
107                &mut channels as *mut _,
108            );
109
110            if err != 0 {
111                return Err(());
112            }
113
114            Ok(Decoder {
115                decoder,
116                sample_rate: sample_rate as usize,
117                channels: channels as usize,
118            })
119        }
120    }
121
122    pub fn sample_rate(&self) -> usize {
123        self.sample_rate
124    }
125
126    pub fn channels(&self) -> usize {
127        self.channels
128    }
129
130    pub fn decode(&mut self, data: &[u8]) -> Result<DecodeResult<'_>, Error> {
131        unsafe {
132            let mut frame_info = MaybeUninit::zeroed();
133
134            let samples = faad2_sys::NeAACDecDecode(
135                self.decoder.handle,
136                frame_info.as_mut_ptr(),
137                data.as_ptr(),
138                data.len() as c_ulong,
139            );
140
141            let frame_info = frame_info.assume_init();
142
143            if samples == ptr::null_mut() {
144                return Err(Error(frame_info.error));
145            }
146
147            let info = DecodeResult {
148                samples: slice::from_raw_parts::<f32>(samples as *const f32, frame_info.samples as usize),
149                bytes_consumed: frame_info.bytesconsumed as usize,
150                channels: frame_info.channels as usize,
151                sample_rate: frame_info.samplerate as usize,
152            };
153
154            self.channels = info.channels;
155            self.sample_rate = info.sample_rate;
156
157            Ok(info)
158        }
159    }
160}