#[macro_use]
extern crate mpeg2ts_reader;
extern crate hex_slice;
use std::env;
use std::fs::File;
use std::io::Read;
use mpeg2ts_reader::demultiplex;
use mpeg2ts_reader::pes;
use mpeg2ts_reader::StreamType;
use hex_slice::AsHex;
use std::cmp;
use mpeg2ts_reader::psi;
packet_filter_switch!{
DumpFilterSwitch<DumpDemuxContext> {
Pes: pes::PesPacketFilter<DumpDemuxContext,PtsDumpElementaryStreamConsumer>,
Pat: demultiplex::PatPacketFilter<DumpDemuxContext>,
Pmt: demultiplex::PmtPacketFilter<DumpDemuxContext>,
Null: demultiplex::NullPacketFilter<DumpDemuxContext>,
}
}
demux_context!(DumpDemuxContext, DumpStreamConstructor);
pub struct DumpStreamConstructor;
impl demultiplex::StreamConstructor for DumpStreamConstructor {
type F = DumpFilterSwitch;
fn construct(&mut self, req: demultiplex::FilterRequest) -> Self::F {
match req {
demultiplex::FilterRequest::ByPid(0) =>
DumpFilterSwitch::Pat(demultiplex::PatPacketFilter::default()),
demultiplex::FilterRequest::ByPid(_) =>
DumpFilterSwitch::Null(demultiplex::NullPacketFilter::default()),
demultiplex::FilterRequest::ByStream(StreamType::H264, pmt_section, stream_info) =>
PtsDumpElementaryStreamConsumer::construct(pmt_section, stream_info),
demultiplex::FilterRequest::ByStream(_stype, _pmt_section, _stream_info) =>
DumpFilterSwitch::Null(demultiplex::NullPacketFilter::default()),
demultiplex::FilterRequest::Pmt{pid, program_number} =>
DumpFilterSwitch::Pmt(demultiplex::PmtPacketFilter::new(pid, program_number)),
demultiplex::FilterRequest::Nit{..} =>
DumpFilterSwitch::Null(demultiplex::NullPacketFilter::default()),
}
}
}
pub struct PtsDumpElementaryStreamConsumer {
pid: u16,
len: Option<usize>,
}
impl PtsDumpElementaryStreamConsumer {
fn construct(_pmt_sect: &psi::pmt::PmtSection, stream_info: &psi::pmt::StreamInfo)
-> DumpFilterSwitch
{
let filter = pes::PesPacketFilter::new(
PtsDumpElementaryStreamConsumer {
pid: stream_info.elementary_pid(),
len: None
}
);
DumpFilterSwitch::Pes(filter)
}
}
impl pes::ElementaryStreamConsumer for PtsDumpElementaryStreamConsumer {
fn start_stream(&mut self) { }
fn begin_packet(&mut self, header: pes::PesHeader) {
match header.contents() {
pes::PesContents::Parsed(Some(parsed)) => {
match parsed.pts_dts() {
Ok(pes::PtsDts::PtsOnly(Ok(pts))) => {
print!("PID {}: pts {:#08x} ",
self.pid,
pts.value())
},
Ok(pes::PtsDts::Both{pts:Ok(pts), dts:Ok(dts)}) => {
print!("PID {}: pts {:#08x} dts {:#08x} ",
self.pid,
pts.value(),
dts.value())
},
_ => (),
}
let payload = parsed.payload();
self.len = Some(payload.len());
println!("{:02x}", payload[..cmp::min(payload.len(),16)].plain_hex(false))
},
pes::PesContents::Parsed(None) => (),
pes::PesContents::Payload(payload) => {
self.len = Some(payload.len());
println!("PID {}: {:02x}",
self.pid,
payload[..cmp::min(payload.len(),16)].plain_hex(false))
},
}
}
fn continue_packet(&mut self, data: &[u8]) {
println!("PID {}: continues {:02x}",
self.pid,
data[..cmp::min(data.len(),16)].plain_hex(false));
self.len = self.len.map(|l| l+data.len() );
}
fn end_packet(&mut self) {
println!("PID {}: end of packet length={:?}",
self.pid,
self.len);
}
fn continuity_error(&mut self) { }
}
fn main() {
let name = env::args().nth(1).unwrap();
let mut f = File::open(&name).expect(&format!("file not found: {}", &name));
let mut ctx = DumpDemuxContext::new(DumpStreamConstructor);
let mut demux = demultiplex::Demultiplex::new(&mut ctx);
let mut buf = [0u8; 188*1024];
loop {
match f.read(&mut buf[..]).expect("read failed") {
0 => break ,
n => demux.push(&mut ctx, &buf[0..n]),
}
}
}