mpeg2ts-reader

Rust reader for MPEG2 Transport Stream data

Build Status crates.io version

Example

Dump timestamps attached to any ADTS audio or H264 video streams.

```rust extern crate mpeg2ts_reader;

use std::env; use std::fs::File; use std::io::Read; use std::collections::HashMap; use mpeg2tsreader::demultiplex; use mpeg2tsreader::pes; use mpeg2ts_reader::StreamType;

// Implement the ElementaryStreamConsumer to just dump and PTS/DTS timestamps to stdout struct PtsDumpElementaryStreamConsumer { pid: u16, } impl PtsDumpElementaryStreamConsumer { fn construct(pmtsect: &demultiplex::PmtSection, streaminfo: &demultiplex::StreamInfo) -> Box> { let consumer = pes::PesPacketConsumer::new( PtsDumpElementaryStreamConsumer { pid: streaminfo.elementarypid(), } ); Box::new(std::cell::RefCell::new(consumer)) } } impl pes::ElementaryStreamConsumer for PtsDumpElementaryStreamConsumer { fn startstream(&mut self) { } fn beginpacket(&mut self, header: pes::PesHeader) { match header.contents() { pes::PesContents::Parsed(Some(parsed)) => { match parsed.ptsdts() { pes::PtsDts::PtsOnly(Ok(pts)) => { println!("PID {}: pts {:#x}", self.pid, pts.value()) }, pes::PtsDts::Both{pts:Ok(pts), dts:Ok(dts)} => { println!("PID {}: pts={:#x} dts={:#x}", self.pid, pts.value(), dts.value()) }, _ => (), } }, pes::PesContents::Parsed(None) => (), pes::PesContents::Payload() => { }, } } fn continuepacket(&mut self, data: &[u8]) { } fn endpacket(&mut self) { } fn continuity_error(&mut self) { } }

fn main() { // open input file named on command line, let name = env::args().nth(1).unwrap(); let mut f = File::open(&name).expect(&format!("file not found: {}", &name));

// configure the stream types we will handle,
let mut table: HashMap<StreamType, fn(&demultiplex::PmtSection,&demultiplex::StreamInfo)->Box<std::cell::RefCell<demultiplex::PacketFilter>>>
    = HashMap::new();
table.insert(StreamType::H264, PtsDumpElementaryStreamConsumer::construct);
table.insert(StreamType::Adts, PtsDumpElementaryStreamConsumer::construct);
let stream_constructor = demultiplex::StreamConstructor::new(
    demultiplex::NullPacketFilter::construct,
    table
);

// create the demultiplexer with the above config
let mut demultiplex = demultiplex::Demultiplex::new(stream_constructor);

// consume the input file,
let mut buf = [0u8; 188*1024];
loop {
    match f.read(&mut buf[..]).expect("read failed") {
        0 => break,
        n => demultiplex.push(&buf[0..n]),
    }
}

} ```

Performance

On my i7-7820HQ laptop, a microbenchmark that parses TS structure, but ignores the audio and video contained within, can process at a rate of 6 GiBytes/s (48 Gibits/s). This is when the data is already in memory (no network/disk access), and processing is happening on a single core (no multiprocessing of the stream).

Supported Transport Stream features

Not all Transport Stream features are supported yet. Here's a summary of what's available, and what's yet to come: