use std::error;
use std::fmt;
use std::io::{self, Read, Seek, SeekFrom};
use std::marker::PhantomData;
use {Decoder, InvalidData, Sample, StreamInfo};
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Format {
#[cfg(feature = "caf")]
Caf,
#[cfg(feature = "mp4")]
Mp4,
#[doc(hidden)]
__Nonexhaustive,
}
#[derive(Debug)]
pub enum ReadError {
Io(io::Error),
UnsupportedFormat,
Format(Format, InvalidData),
Decoder(InvalidData),
}
impl error::Error for ReadError {
fn description(&self) -> &str {
match *self {
ReadError::Io(_) => "IO error",
ReadError::UnsupportedFormat => "unsupported format",
ReadError::Format(_, _) => "format error",
ReadError::Decoder(_) => "decoder error",
}
}
fn cause(&self) -> Option<&error::Error> {
match *self {
ReadError::Io(ref err) => Some(err),
ReadError::UnsupportedFormat => return None,
ReadError::Format(_, ref err) => Some(err),
ReadError::Decoder(ref err) => Some(err),
}
}
}
impl fmt::Display for ReadError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
ReadError::Io(ref err) => write!(f, "IO error: {}", err),
ReadError::UnsupportedFormat => write!(f, "unsupported format"),
ReadError::Format(format, ref err) => write!(f, "{:?} error: {}", format, err),
ReadError::Decoder(ref err) => write!(f, "decoder error: {}", err),
}
}
}
impl From<io::Error> for ReadError {
fn from(err: io::Error) -> ReadError {
ReadError::Io(err)
}
}
pub struct Reader<R: Read + Seek> {
packet_buf: Vec<u8>,
packet_reader: PacketReader<R>,
decoder: Decoder,
}
impl<R: Read + Seek> Reader<R> {
pub fn new(reader: R) -> Result<Reader<R>, ReadError> {
let (packet_reader, magic_cookie) = PacketReader::new(reader)?;
let stream_info = StreamInfo::from_cookie(&magic_cookie).map_err(ReadError::Decoder)?;
Ok(Reader {
packet_buf: Vec::new(),
packet_reader,
decoder: Decoder::new(stream_info),
})
}
pub fn format(&self) -> Format {
self.packet_reader.format()
}
pub fn stream_info(&self) -> &StreamInfo {
self.decoder.stream_info()
}
pub fn into_samples<S: Sample>(self) -> Samples<R, S> {
Samples {
reader: self,
samples: Vec::new(),
sample_len: 0,
sample_pos: 0,
}
}
pub fn into_packets<S: Sample>(self) -> Packets<R, S> {
Packets {
reader: self,
phantom: PhantomData,
}
}
fn decode_next_packet_into<'a, S: Sample>(
&mut self,
out: &'a mut [S],
) -> Result<Option<&'a [S]>, ReadError> {
self.packet_reader.next_packet_into(&mut self.packet_buf)?;
if self.packet_buf.is_empty() {
return Ok(None);
}
let samples = self.decoder
.decode_packet(&self.packet_buf, out)
.map_err(|err| ReadError::Decoder(err))?;
if samples.len() == 0 {
Ok(None)
} else {
Ok(Some(samples))
}
}
}
pub struct Samples<R: Read + Seek, S> {
reader: Reader<R>,
samples: Vec<S>,
sample_len: usize,
sample_pos: usize,
}
impl<R: Read + Seek, S: Sample> Samples<R, S> {
pub fn format(&self) -> Format {
self.reader.format()
}
pub fn stream_info(&self) -> &StreamInfo {
self.reader.stream_info()
}
}
impl<R: Read + Seek, S: Sample> Iterator for Samples<R, S> {
type Item = Result<S, ReadError>;
fn next(&mut self) -> Option<Result<S, ReadError>> {
if self.samples.is_empty() {
let max_samples = self.stream_info().max_samples_per_packet() as usize;
self.samples = vec![S::from_decoder(0, 16); max_samples];
}
if self.sample_pos == self.sample_len {
self.sample_len = match self.reader.decode_next_packet_into(&mut self.samples) {
Ok(Some(s)) => s.len(),
Ok(None) => return None,
Err(e) => return Some(Err(e)),
};
self.sample_pos = 0;
}
let sample_pos = self.sample_pos;
self.sample_pos += 1;
Some(Ok(self.samples[sample_pos]))
}
}
pub struct Packets<R: Read + Seek, S> {
reader: Reader<R>,
phantom: PhantomData<[S]>,
}
impl<R: Read + Seek, S: Sample> Packets<R, S> {
pub fn format(&self) -> Format {
self.reader.format()
}
pub fn stream_info(&self) -> &StreamInfo {
self.reader.stream_info()
}
pub fn next_into<'a>(&mut self, out: &'a mut [S]) -> Result<Option<&'a [S]>, ReadError> {
self.reader.decode_next_packet_into(out)
}
}
#[cfg(feature = "caf")]
use caf::CafPacketReader;
#[cfg(feature = "mp4")]
use mp4::Mp4PacketReader;
enum PacketReader<R: Read + Seek> {
#[cfg(feature = "caf")]
Caf(CafPacketReader<R>),
#[cfg(feature = "mp4")]
Mp4(Mp4PacketReader<R>),
}
impl<R: Read + Seek> PacketReader<R> {
fn new(mut reader: R) -> Result<(PacketReader<R>, Vec<u8>), ReadError> {
let mut magic = [0; 8];
reader.read_exact(&mut magic)?;
reader.seek(SeekFrom::Current(-(magic.len() as i64)))?;
match (&magic[0..4], &magic[4..8]) {
#[cfg(feature = "caf")]
(b"caff", _) => {
let (reader, magic_cookie) = CafPacketReader::new(reader)?;
Ok((PacketReader::Caf(reader), magic_cookie))
}
#[cfg(feature = "mp4")]
(_, b"ftyp") => {
let (reader, magic_cookie) = Mp4PacketReader::new(reader)?;
Ok((PacketReader::Mp4(reader), magic_cookie))
}
_ => Err(ReadError::UnsupportedFormat),
}
}
fn format(&self) -> Format {
match *self {
#[cfg(feature = "caf")]
PacketReader::Caf(_) => Format::Caf,
#[cfg(feature = "mp4")]
PacketReader::Mp4(_) => Format::Mp4,
}
}
fn next_packet_into(&mut self, buf: &mut Vec<u8>) -> Result<(), ReadError> {
match *self {
#[cfg(feature = "caf")]
PacketReader::Caf(ref mut r) => r.next_packet_into(buf),
#[cfg(feature = "mp4")]
PacketReader::Mp4(ref mut r) => r.next_packet_into(buf),
}
}
}