···11+# redlux
22+33+AAC decoder for MPEG-4 (MP4, M4A etc) and AAC files. Supports rodio.
44+55+[](https://crates.io/crates/redlux)
66+[](https://docs.rs/redlux)
77+88+## Caveats
99+1. It only decodes the first AAC track it finds in an MPEG-4 container.
1010+2. Not sure if MPEG files with CRC are supported.
1111+3. According to [this MultimediaWiki page](https://wiki.multimedia.cx/index.php/ADTS), 13 bits of the ADTS header is for specifying the frame length, and this number must include the ADTS header itself. For 8 channel audio, I would assume the frame length could be 8192 bytes, and if we add the header bytes on top of that, it would exceed what 13 bits can carry. Is this a potential issue? No idea.
1212+1313+## Dev instructions
1414+1515+### Get started
1616+1717+Install [Rust](https://www.rust-lang.org).
1818+1919+Run tests:
2020+```
2121+cargo test
2222+```
2323+2424+Build:
2525+```
2626+cargo build
2727+```
2828+2929+### Releasing a new version
3030+3131+1. Update `CHANGELOG.md`
3232+2. Bump the version number in `Cargo.toml`
3333+3. Run `cargo test`
3434+4. Commit and tag in format `v#.#.#`
3535+5. Publish on crates.io:
3636+ 1. Login by running `cargo login` and following the instructions
3737+ 2. Test publish to ensure there are no errors/warnings
3838+ ```
3939+ cargo publish --dry-run
4040+ ```
4141+ 3. Publish
4242+ ```
4343+ cargo publish
4444+ ```
4545+6. Create GitHub release with release notes
+52-57
src/lib.rs
···11+//! AAC decoder for MPEG-4 (MP4, M4A etc) and AAC files. Supports rodio.
12use fdk_aac::dec::{Decoder as AacDecoder, DecoderError, Transport};
22-use std::error;
33-use std::fmt;
43use std::io::{Read, Seek};
54use std::time::Duration;
55+use std::{error, fmt, io};
6677pub mod adts;
8899+/// Redlux error
910#[derive(Debug)]
1011pub enum Error {
1112 /// Error reading header of file
···1920 TrackDecodingError(DecoderError),
2021 /// Error getting samples
2122 SamplesError,
2323+ /// Error from the underlying reader R
2424+ ReaderError(io::Error),
2225}
23262427impl error::Error for Error {}
···2932 }
3033}
31343535+/// File container format
3236pub enum Format {
3337 Mp4,
3438 Aac,
3539}
36404141+/// Underlying reader
3742pub enum Reader<R> {
3843 Mp4Reader(mp4::Mp4Reader<R>),
3944 AacReader(R),
···5156 current_pcm: Vec<i16>,
5257 track_id: u32,
5358 position: u32,
5454- pub decoder_error: Option<Error>,
5959+ /// If there's an error while iterating over the Decoder, that error is added here
6060+ pub iter_error: Option<Error>,
5561}
56625763impl<R> Decoder<R>
5864where
5965 R: Read + Seek,
6066{
6767+ /// Create from an aac buffer
6168 pub fn new_aac(reader: R) -> Self {
6269 let aac_decoder = AacDecoder::new(Transport::Adts);
6370 let aac_decoder = Decoder {
···6976 current_pcm: Vec::new(),
7077 track_id: 0,
7178 position: 1,
7272- decoder_error: None,
7979+ iter_error: None,
7380 };
7481 return aac_decoder;
7582 }
8383+ /// Create from an mpeg buffer
7684 pub fn new_mpeg4(reader: R, size: u64) -> Result<Self, Error> {
7785 let aac_decoder = AacDecoder::new(Transport::Adts);
7886 let mp4 = mp4::Mp4Reader::read_header(reader, size).or(Err(Error::FileHeaderError))?;
···103111 current_pcm: Vec::new(),
104112 track_id: track_id,
105113 position: 1,
106106- decoder_error: None,
114114+ iter_error: None,
107115 });
108116 }
109117 None => {
···126134 pub fn total_duration(&self) -> Option<Duration> {
127135 return None;
128136 }
129129-}
130130-131131-impl<R> Iterator for Decoder<R>
132132-where
133133- R: Read + Seek,
134134-{
135135- type Item = i16;
136136- fn next(&mut self) -> Option<i16> {
137137+ /// Consume and return the next sample, or None when finished
138138+ pub fn decode_next_sample(&mut self) -> Result<Option<i16>, Error> {
137139 if self.current_pcm_index == self.current_pcm.len() {
138140 let mut pcm = vec![0; 8192];
139141 let result = match self.aac_decoder.decode_frame(&mut pcm) {
···142144 // mp4
143145 Reader::Mp4Reader(mp4_reader) => {
144146 let sample_result = mp4_reader.read_sample(self.track_id, self.position);
145145- let sample = match sample_result {
146146- Ok(sample) => sample?, // None if EOF
147147- Err(_) => {
148148- self.decoder_error = Some(Error::SamplesError);
149149- return None;
150150- }
147147+ let sample_opt = sample_result.or(Err(Error::SamplesError))?;
148148+ let sample = match sample_opt {
149149+ Some(sample) => sample,
150150+ None => return Ok(None), // EOF
151151 };
152152 let tracks = mp4_reader.tracks();
153153- let track = match tracks.get(self.track_id as usize - 1) {
154154- Some(track) => track,
155155- None => {
156156- self.decoder_error = Some(Error::TrackNotFound);
157157- return None;
158158- }
159159- };
160160- let object_type = match track.audio_profile() {
161161- Ok(value) => value,
162162- Err(_) => {
163163- self.decoder_error = Some(Error::TrackReadingError);
164164- return None;
165165- }
166166- };
167167- let sample_freq_index = match track.sample_freq_index() {
168168- Ok(value) => value,
169169- Err(_) => {
170170- self.decoder_error = Some(Error::TrackReadingError);
171171- return None;
172172- }
173173- };
174174- let channel_config = match track.channel_config() {
175175- Ok(value) => value,
176176- Err(_) => {
177177- self.decoder_error = Some(Error::TrackReadingError);
178178- return None;
179179- }
180180- };
153153+ let track = tracks
154154+ .get(self.track_id as usize - 1)
155155+ .ok_or(Error::TrackNotFound)?;
156156+ let object_type = track.audio_profile().or(Err(Error::TrackReadingError))?;
157157+ let sample_freq_index = track
158158+ .sample_freq_index()
159159+ .or(Err(Error::TrackReadingError))?;
160160+ let channel_config = track.channel_config().or(Err(Error::TrackReadingError))?;
181161 let adts_header = adts::construct_adts_header(
182162 object_type,
183163 sample_freq_index,
···194174 let mut new_bytes = vec![0; 8192 - old_bytes_len];
195175 let bytes_read = match aac_reader.read(&mut new_bytes) {
196176 Ok(bytes_read) => bytes_read,
197197- Err(_) => return None,
177177+ Err(err) => return Err(Error::ReaderError(err)),
198178 };
199179 if bytes_read == 0 {
200200- return None;
180180+ return Ok(None); // EOF
201181 }
202182 // aac files already have adts headers
203183 self.bytes.extend(new_bytes);
···205185 }
206186 let bytes_filled = match self.aac_decoder.fill(&self.bytes) {
207187 Ok(bytes_filled) => bytes_filled,
208208- Err(_) => return None,
188188+ Err(err) => return Err(Error::TrackDecodingError(err)),
209189 };
210190 self.bytes = self.bytes[bytes_filled..].to_vec();
211191 self.aac_decoder.decode_frame(&mut pcm)
212192 }
213193 val => val,
214194 };
215215- match result {
216216- Ok(_) => {}
217217- Err(err) => {
218218- self.decoder_error = Some(Error::TrackDecodingError(err));
219219- return None;
220220- }
195195+ if let Err(err) = result {
196196+ return Err(Error::TrackDecodingError(err));
221197 }
222198 let decoded_frame_size = self.aac_decoder.decoded_frame_size();
223199 if decoded_frame_size < pcm.len() {
···228204 }
229205 let value = self.current_pcm[self.current_pcm_index];
230206 self.current_pcm_index += 1;
231231- return Some(value);
207207+ return Ok(Some(value));
208208+ }
209209+}
210210+211211+impl<R> Iterator for Decoder<R>
212212+where
213213+ R: Read + Seek,
214214+{
215215+ type Item = i16;
216216+ /// Runs decode_next_sample and returns the sample from that. Once the
217217+ /// iterator is finished, it returns None. If there's an error, it's added
218218+ /// to the iter_error error.
219219+ fn next(&mut self) -> Option<i16> {
220220+ match self.decode_next_sample() {
221221+ Ok(sample) => sample,
222222+ Err(err) => {
223223+ self.iter_error = Some(err);
224224+ return None;
225225+ }
226226+ }
232227 }
233228}
234229