Skip to main content

fdk_aac/
enc.rs

1use std::cmp;
2use std::fmt::{self, Display, Debug};
3use std::mem::{self, MaybeUninit};
4use std::os::raw::{c_void, c_uint, c_int};
5use std::ptr;
6
7use fdk_aac_sys as sys;
8
9pub use sys::AACENC_InfoStruct as InfoStruct;
10
11pub struct EncoderError(sys::AACENC_ERROR);
12
13impl EncoderError {
14    fn message(&self) -> &'static str {
15        match self.0 {
16            sys::AACENC_ERROR_AACENC_OK => "Ok",
17            sys::AACENC_ERROR_AACENC_INVALID_HANDLE => "Handle passed to function call was invalid.",
18            sys::AACENC_ERROR_AACENC_MEMORY_ERROR => "Memory allocation failed.",
19            sys::AACENC_ERROR_AACENC_UNSUPPORTED_PARAMETER => "Parameter not available.",
20            sys::AACENC_ERROR_AACENC_INVALID_CONFIG => "Configuration not provided.",
21            sys::AACENC_ERROR_AACENC_INIT_ERROR => "General initialization error.",
22            sys::AACENC_ERROR_AACENC_INIT_AAC_ERROR => "AAC library initialization error.",
23            sys::AACENC_ERROR_AACENC_INIT_SBR_ERROR => "SBR library initialization error.",
24            sys::AACENC_ERROR_AACENC_INIT_TP_ERROR => "Transport library initialization error.",
25            sys::AACENC_ERROR_AACENC_INIT_META_ERROR => "Meta data library initialization error.",
26            sys::AACENC_ERROR_AACENC_INIT_MPS_ERROR => "MPS library initialization error.",
27            sys::AACENC_ERROR_AACENC_ENCODE_ERROR => "The encoding process was interrupted by an unexpected error.",
28            sys::AACENC_ERROR_AACENC_ENCODE_EOF => "End of file reached.",
29            _ => "Unknown error",
30        }
31    }
32}
33
34impl Debug for EncoderError {
35    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
36        write!(f, "EncoderError {{ code: {:?}, message: {:?} }}", self.0 as c_int, self.message())
37    }
38}
39
40impl Display for EncoderError {
41    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
42        write!(f, "{}", self.message())
43    }
44}
45
46fn check(e: sys::AACENC_ERROR) -> Result<(), EncoderError> {
47    if e == sys::AACENC_ERROR_AACENC_OK {
48        Ok(())
49    } else {
50        Err(EncoderError(e))
51    }
52}
53
54struct EncoderHandle {
55    ptr: sys::HANDLE_AACENCODER,
56}
57
58unsafe impl Send for EncoderHandle {}
59unsafe impl Sync for EncoderHandle {}
60
61impl EncoderHandle {
62    pub fn alloc(max_modules: usize, max_channels: usize) -> Result<Self, EncoderError> {
63        let mut ptr: sys::HANDLE_AACENCODER = ptr::null_mut();
64        check(unsafe {
65            sys::aacEncOpen(&mut ptr as *mut _, max_modules as c_uint, max_channels as c_uint)
66        })?;
67        Ok(EncoderHandle { ptr })
68    }
69}
70
71impl Drop for EncoderHandle {
72    fn drop(&mut self) {
73        unsafe { sys::aacEncClose(&mut self.ptr as *mut _); }
74    }
75}
76
77#[derive(Debug, Clone, Copy)]
78pub enum BitRate {
79    Cbr(u32),
80    VbrVeryLow,
81    VbrLow,
82    VbrMedium,
83    VbrHigh,
84    VbrVeryHigh,
85}
86
87#[derive(Debug, Clone, Copy)]
88pub enum ChannelMode {
89    Mono,
90    Stereo,
91}
92
93#[derive(Debug, Clone, Copy)]
94pub enum AudioObjectType {
95    /// MPEG-4 AAC Low Complexity.
96    ///
97    /// Value: 2
98    Mpeg4LowComplexity,
99    /// MPEG-4 AAC Low Complexity with Spectral Band Replication (HE-AAC).
100    ///
101    /// Value: 5
102    Mpeg4HeAac,
103    /// MPEG-4 AAC Low Complexity with Spectral Band Replication and Parametric
104    /// Stereo (HE-AAC v2). This configuration can be used only with stereo
105    /// input audio data.
106    ///
107    /// Value: 29
108    Mpeg4HeAacV2,
109    /// MPEG-4 AAC Low-Delay.
110    ///
111    /// Value: 23
112    Mpeg4LowDelay,
113    /// MPEG-4 AAC Enhanced Low-Delay.
114    ///
115    /// Value: 39
116    Mpeg4EnhancedLowDelay,
117    /// MPEG-2 AAC Low Complexity.
118    ///
119    /// Value: 129
120    Mpeg2Aac,
121    /// MPEG-2 AAC Low Complexity with Spectral Band Replication (HE-AAC)
122    ///
123    /// Value: 132
124    Mpeg2HeAac,
125}
126
127pub struct EncoderParams {
128    pub bit_rate: BitRate,
129    pub sample_rate: u32,
130    pub transport: Transport,
131    pub channels: ChannelMode,
132    pub audio_object_type: AudioObjectType,
133}
134
135pub struct Encoder {
136    handle: EncoderHandle,
137}
138
139#[derive(Debug)]
140pub enum Transport {
141    Adts,
142    Raw,
143}
144
145#[derive(Debug)]
146pub struct EncodeInfo {
147    pub input_consumed: usize,
148    pub output_size: usize,
149}
150
151impl Encoder {
152    pub fn new(params: EncoderParams) -> Result<Self, EncoderError> {
153        let handle = EncoderHandle::alloc(0, 2 /* hardcode stereo */)?;
154
155        unsafe {
156            let aot = match params.audio_object_type {
157                AudioObjectType::Mpeg4LowComplexity => sys::AUDIO_OBJECT_TYPE_AOT_AAC_LC,
158                AudioObjectType::Mpeg4HeAac => sys::AUDIO_OBJECT_TYPE_AOT_SBR,
159                AudioObjectType::Mpeg4HeAacV2 => sys::AUDIO_OBJECT_TYPE_AOT_PS,
160                AudioObjectType::Mpeg4LowDelay => sys::AUDIO_OBJECT_TYPE_AOT_ER_AAC_LD,
161                AudioObjectType::Mpeg4EnhancedLowDelay => sys::AUDIO_OBJECT_TYPE_AOT_ER_AAC_ELD,
162                AudioObjectType::Mpeg2Aac => sys::AUDIO_OBJECT_TYPE_AOT_MP2_AAC_LC,
163                AudioObjectType::Mpeg2HeAac => sys::AUDIO_OBJECT_TYPE_AOT_MP2_SBR,
164            };
165
166            check(sys::aacEncoder_SetParam(handle.ptr, sys::AACENC_PARAM_AACENC_AOT, aot as u32))?;
167
168            let bitrate_mode = match params.bit_rate {
169                BitRate::Cbr(bitrate) => {
170                    check(sys::aacEncoder_SetParam(handle.ptr, sys::AACENC_PARAM_AACENC_BITRATE, bitrate))?;
171                    0
172                }
173                BitRate::VbrVeryLow => 1,
174                BitRate::VbrLow => 2,
175                BitRate::VbrMedium => 3,
176                BitRate::VbrHigh => 4,
177                BitRate::VbrVeryHigh => 5,
178            };
179
180            check(sys::aacEncoder_SetParam(handle.ptr, sys::AACENC_PARAM_AACENC_BITRATEMODE, bitrate_mode))?;
181
182            check(sys::aacEncoder_SetParam(handle.ptr, sys::AACENC_PARAM_AACENC_SAMPLERATE, params.sample_rate))?;
183
184            check(sys::aacEncoder_SetParam(handle.ptr, sys::AACENC_PARAM_AACENC_TRANSMUX, match params.transport {
185                Transport::Adts => 2,
186                Transport::Raw => 0,
187            }))?;
188
189            // hardcode SBR off for now
190            check(sys::aacEncoder_SetParam(handle.ptr, sys::AACENC_PARAM_AACENC_SBR_MODE, 0))?;
191
192            check(sys::aacEncoder_SetParam(
193                handle.ptr,
194                sys::AACENC_PARAM_AACENC_CHANNELMODE,
195                match params.channels {
196                    ChannelMode::Mono => 1,
197                    ChannelMode::Stereo => 2,
198                },
199            ))?;
200
201            // call encode once with all null params according to docs
202            check(sys::aacEncEncode(handle.ptr, ptr::null(), ptr::null(), ptr::null(), ptr::null_mut()))?;
203        }
204
205        Ok(Encoder { handle })
206    }
207
208    pub fn info(&self) -> Result<InfoStruct, EncoderError> {
209        let mut info = MaybeUninit::uninit();
210        check(unsafe { sys::aacEncInfo(self.handle.ptr, info.as_mut_ptr()) })?;
211        Ok(unsafe { info.assume_init() })
212    }
213
214    pub fn encode(&self, input: &[i16], output: &mut [u8]) -> Result<EncodeInfo, EncoderError> {
215        let input_len = cmp::min(i32::max_value() as usize, input.len()) as i32;
216
217        let mut input_buf = input.as_ptr() as *mut i16;
218        let mut input_buf_ident: c_int = sys::AACENC_BufferIdentifier_IN_AUDIO_DATA as c_int;
219        let mut input_buf_size: c_int = input_len as c_int;
220        let mut input_buf_el_size: c_int = mem::size_of::<i16>() as c_int;
221        let input_desc = sys::AACENC_BufDesc {
222            numBufs: 1,
223            bufs: &mut input_buf as *mut _ as *mut *mut c_void,
224            bufferIdentifiers: &mut input_buf_ident as *mut c_int,
225            bufSizes: &mut input_buf_size as *mut c_int,
226            bufElSizes: &mut input_buf_el_size as *mut c_int,
227        };
228
229        let mut output_buf = output.as_mut_ptr();
230        let mut output_buf_ident: c_int = sys::AACENC_BufferIdentifier_OUT_BITSTREAM_DATA as c_int;
231        let mut output_buf_size: c_int = output.len() as c_int;
232        let mut output_buf_el_size: c_int = mem::size_of::<u8>() as c_int;
233        let output_desc = sys::AACENC_BufDesc {
234            numBufs: 1,
235            bufs: &mut output_buf as *mut _ as *mut *mut c_void,
236            bufferIdentifiers: &mut output_buf_ident as *mut _,
237            bufSizes: &mut output_buf_size as *mut _,
238            bufElSizes: &mut output_buf_el_size as *mut _,
239        };
240
241        let in_args = sys::AACENC_InArgs {
242            numInSamples: input_len,
243            numAncBytes: 0,
244        };
245
246        let mut out_args = unsafe { mem::zeroed() };
247
248        check(unsafe { sys::aacEncEncode(self.handle.ptr, &input_desc, &output_desc, &in_args, &mut out_args) })?;
249
250        Ok(EncodeInfo {
251            output_size: out_args.numOutBytes as usize,
252            input_consumed: out_args.numInSamples as usize,
253        })
254    }
255}
256
257impl Debug for Encoder {
258    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
259        write!(f, "Encoder {{ handle: {:?} }}", self.handle.ptr)
260    }
261}