extern crate byteorder;
mod bitcursor;
mod dec;
pub use dec::{Decoder, Sample};
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct DecoderConfig {
frame_length: u32,
compatible_version: u8,
bit_depth: u8,
pb: u8, mb: u8, kb: u8, num_channels: u8,
max_run: u16,
max_frame_bytes: u32,
avg_bit_rate: u32,
sample_rate: u32,
}
impl DecoderConfig {
pub fn from_cookie(mut cookie: &[u8]) -> Result<DecoderConfig, ()> {
use byteorder::{BigEndian, ReadBytesExt};
use std::io::Cursor;
if cookie.len() < 24 {
return Err(());
};
if &cookie[4..8] == b"frma" {
cookie = &cookie[12..];
}
if &cookie[4..8] == b"alac" {
cookie = &cookie[12..];
}
if cookie.len() < 24 {
return Err(());
}
let mut reader = Cursor::new(cookie);
Ok(DecoderConfig {
frame_length: reader.read_u32::<BigEndian>().unwrap(),
compatible_version: reader.read_u8().unwrap(),
bit_depth: reader.read_u8().unwrap(),
pb: reader.read_u8().unwrap(),
mb: reader.read_u8().unwrap(),
kb: reader.read_u8().unwrap(),
num_channels: reader.read_u8().unwrap(),
max_run: reader.read_u16::<BigEndian>().unwrap(),
max_frame_bytes: reader.read_u32::<BigEndian>().unwrap(),
avg_bit_rate: reader.read_u32::<BigEndian>().unwrap(),
sample_rate: reader.read_u32::<BigEndian>().unwrap(),
})
}
pub fn from_sdp_format_parameters(params: &str) -> Result<DecoderConfig, ()> {
use std::str::FromStr;
fn parse<T: FromStr>(val: Option<&str>) -> Result<T, ()> {
let val = try!(val.ok_or(()));
val.parse().map_err(|_| ())
}
let mut params = params.split_whitespace();
let config = DecoderConfig {
frame_length: try!(parse(params.next())),
compatible_version: try!(parse(params.next())),
bit_depth: try!(parse(params.next())),
pb: try!(parse(params.next())),
mb: try!(parse(params.next())),
kb: try!(parse(params.next())),
num_channels: try!(parse(params.next())),
max_run: try!(parse(params.next())),
max_frame_bytes: try!(parse(params.next())),
avg_bit_rate: try!(parse(params.next())),
sample_rate: try!(parse(params.next())),
};
if params.next().is_some() {
return Err(())
}
Ok(config)
}
pub fn sample_rate(&self) -> u32 {
self.sample_rate
}
pub fn bit_depth(&self) -> u8 {
self.bit_depth
}
pub fn channels(&self) -> u8 {
self.num_channels
}
pub fn max_frames_per_packet(&self) -> u32 {
self.frame_length
}
}
#[cfg(test)]
mod tests {
use super::DecoderConfig;
#[test]
fn test_from_cookie() {
let cookie_bytes = include_bytes!("../tests/data/magic_cookie.bin");
let cookie = DecoderConfig::from_cookie(cookie_bytes).unwrap();
let comparison = DecoderConfig {
frame_length: 4096,
compatible_version: 0,
bit_depth: 16,
pb: 40,
mb: 10,
kb: 14,
num_channels: 2,
max_run: 255,
max_frame_bytes: 0,
avg_bit_rate: 0,
sample_rate: 44100
};
assert_eq!(cookie, comparison);
}
#[test]
fn test_from_sdp_format_parameters() {
let params = "4096 0 16 40 10 14 2 255 0 0 44100";
let cookie = DecoderConfig::from_sdp_format_parameters(params).unwrap();
let comparison = DecoderConfig {
frame_length: 4096,
compatible_version: 0,
bit_depth: 16,
pb: 40,
mb: 10,
kb: 14,
num_channels: 2,
max_run: 255,
max_frame_bytes: 0,
avg_bit_rate: 0,
sample_rate: 44100
};
assert_eq!(cookie, comparison);
}
}