use nom::IResult;
use std::fmt;
use errors::*;
use super::clock::{Clock, clock_and_ext};
use super::pes;
#[derive(Debug, PartialEq, Eq)]
pub struct Header {
pub scr: Clock,
pub bit_rate: u32,
}
impl fmt::Display for Header {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "[PS packet @ {}, {} kbps]", self.scr, (self.bit_rate*50*8)/1024)
}
}
named!(pub header<Header>,
do_parse!(
tag!(&[0x00, 0x00, 0x01, 0xba]) >>
header: bits!(
do_parse!(
tag_bits!(u8, 2, 0b01) >>
scr: call!(clock_and_ext) >>
bit_rate: take_bits!(u32, 22) >>
tag_bits!(u8, 2, 0b11) >>
take_bits!(u8, 5) >>
stuffing_length: take_bits!(usize, 3) >>
take_bits!(u64, stuffing_length * 8) >>
(Header {
scr: scr,
bit_rate: bit_rate,
})
)
) >>
(header)
)
);
#[derive(Debug, PartialEq, Eq)]
pub struct PesPacket<'a> {
pub ps_header: Header,
pub pes_packet: pes::Packet<'a>,
}
named!(pub pes_packet<PesPacket>,
do_parse!(
ps_header: call!(header) >>
pes_packet: call!(pes::packet) >>
(PesPacket {
ps_header: ps_header,
pes_packet: pes_packet,
})
)
);
pub struct PesPackets<'a> {
remaining: &'a [u8],
}
impl<'a> Iterator for PesPackets<'a> {
type Item = Result<PesPacket<'a>>;
fn next(&mut self) -> Option<Self::Item> {
loop {
let needle = &[0x00, 0x00, 0x01, 0xba];
let start = self.remaining.windows(needle.len())
.position(|window| needle == window);
if let Some(start) = start {
self.remaining = &self.remaining[start..];
match pes_packet(self.remaining) {
IResult::Done(remaining, packet) => {
self.remaining = remaining;
trace!("Decoded packet {:?}", &packet);
return Some(Ok(packet));
}
IResult::Incomplete(needed) => {
self.remaining = &[];
warn!("Incomplete packet, need: {:?}", needed);
return Some(Err("Incomplete PES packet".into()));
}
IResult::Error(err) => {
self.remaining = &self.remaining[needle.len()..];
debug!("Skipping packet {:?}", &err);
}
}
} else {
self.remaining = &[];
trace!("Reached end of data");
return None;
}
}
}
}
pub fn pes_packets(input: &[u8]) -> PesPackets {
PesPackets { remaining: input }
}