src: &'a mut ByteReader<'a>,
cur_frame: Vec<u64>,
num_streams: u8,
- dmx: Demuxer,
size: usize,
movi_size: usize,
sstate: StreamState,
struct RIFFParser {
tag: RIFFTag,
- parse: fn(&mut AVIDemuxer, size: usize) -> DemuxerResult<usize>,
+ parse: fn(&mut AVIDemuxer, strmgr: &mut StreamManager, size: usize) -> DemuxerResult<usize>,
}
-impl<'a> Demux<'a> for AVIDemuxer<'a> {
+impl<'a> DemuxCore<'a> for AVIDemuxer<'a> {
#[allow(unused_variables)]
- fn open(&mut self) -> DemuxerResult<()> {
- self.read_header()?;
+ fn open(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<()> {
+ self.read_header(strmgr)?;
self.opened = true;
Ok(())
}
- fn get_num_streams(&self) -> usize { self.dmx.get_num_streams() }
- fn get_stream(&self, idx: usize) -> Option<Rc<NAStream>> { self.dmx.get_stream(idx) }
-
- fn get_frame(&mut self) -> DemuxerResult<NAPacket> {
+ fn get_frame(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<NAPacket> {
if !self.opened { return Err(NoSuchInput); }
if self.movi_size == 0 { return Err(EOF); }
let mut tag: [u8; 4] = [0; 4];
return Err(InvalidData);
}
let stream_no = (tag[0] - b'0') * 10 + (tag[1] - b'0');
- let str = self.dmx.get_stream(stream_no as usize);
+ let str = strmgr.get_stream(stream_no as usize);
if let None = str { return Err(InvalidData); }
let stream = str.unwrap();
if size == 0 {
sstate: StreamState::new(),
tb_num: 0,
tb_den: 0,
- dmx: Demuxer::new()
}
}
- fn parse_chunk(&mut self, end_tag: RIFFTag, csize: usize, depth: u16) -> DemuxerResult<(usize, bool)> {
+ fn parse_chunk(&mut self, strmgr: &mut StreamManager, end_tag: RIFFTag, csize: usize, depth: u16) -> DemuxerResult<(usize, bool)> {
if csize < 8 { return Err(InvalidData); }
if depth > 42 { return Err(InvalidData); }
for i in 0..CHUNKS.len() {
if RIFFTag::Chunk(tag) == CHUNKS[i].tag {
- let psize = (CHUNKS[i].parse)(self, size)?;
+ let psize = (CHUNKS[i].parse)(self, strmgr, size)?;
if psize != size { return Err(InvalidData); }
if (psize & 1) == 1 { self.src.read_skip(1)?; }
return Ok((size + 8, false));
}
if RIFFTag::List(tag, ltag) == CHUNKS[i].tag {
let mut rest_size = size - 4;
- let psize = (CHUNKS[i].parse)(self, rest_size)?;
+ let psize = (CHUNKS[i].parse)(self, strmgr, rest_size)?;
if psize > rest_size { return Err(InvalidData); }
rest_size -= psize;
while rest_size > 0 {
- let (psize, _) = self.parse_chunk(end_tag, rest_size, depth+1)?;
+ let (psize, _) = self.parse_chunk(strmgr, end_tag, rest_size, depth+1)?;
if psize > rest_size { return Err(InvalidData); }
rest_size -= psize;
if (psize & 1) == 1 {
return Ok((size + 8, false));
}
- fn read_header(&mut self) -> DemuxerResult<()> {
+ fn read_header(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<()> {
let riff_tag = self.src.read_u32be()?;
let size = self.src.read_u32le()? as usize;
let avi_tag = self.src.read_u32be()?;
self.size = size;
let mut rest_size = size;
loop {
- let (csz, end) = self.parse_chunk(RIFFTag::List(mktag!(b"LIST"), mktag!(b"movi")), rest_size,0)?;
+ let (csz, end) = self.parse_chunk(strmgr, RIFFTag::List(mktag!(b"LIST"), mktag!(b"movi")), rest_size,0)?;
if end { self.movi_size = csz - 4; break; }
rest_size -= csz;
}
}
#[allow(unused_variables)]
-fn parse_hdrl(dmx: &mut AVIDemuxer, size: usize) -> DemuxerResult<usize> {
+fn parse_hdrl(dmx: &mut AVIDemuxer, strmgr: &mut StreamManager, size: usize) -> DemuxerResult<usize> {
Ok(0)
}
#[allow(unused_variables)]
-fn parse_strl(dmx: &mut AVIDemuxer, size: usize) -> DemuxerResult<usize> {
+fn parse_strl(dmx: &mut AVIDemuxer, strmgr: &mut StreamManager, size: usize) -> DemuxerResult<usize> {
Ok(0)
}
#[allow(unused_variables)]
-fn parse_strh(dmx: &mut AVIDemuxer, size: usize) -> DemuxerResult<usize> {
+fn parse_strh(dmx: &mut AVIDemuxer, strmgr: &mut StreamManager, size: usize) -> DemuxerResult<usize> {
if size < 0x38 { return Err(InvalidData); }
let tag = dmx.src.read_u32be()?; //stream type
let fcc = dmx.src.read_u32be()?; //handler(fourcc)
Ok(size)
}
-fn parse_strf(dmx: &mut AVIDemuxer, size: usize) -> DemuxerResult<usize> {
+fn parse_strf(dmx: &mut AVIDemuxer, strmgr: &mut StreamManager, size: usize) -> DemuxerResult<usize> {
if let None = dmx.sstate.strm_type { return Err(InvalidData); }
match dmx.sstate.strm_type.unwrap() {
- StreamType::Video => parse_strf_vids(dmx, size),
- StreamType::Audio => parse_strf_auds(dmx, size),
- _ => parse_strf_xxxx(dmx, size),
+ StreamType::Video => parse_strf_vids(dmx, strmgr, size),
+ StreamType::Audio => parse_strf_auds(dmx, strmgr, size),
+ _ => parse_strf_xxxx(dmx, strmgr, size),
}
}
#[allow(unused_variables)]
-fn parse_strf_vids(dmx: &mut AVIDemuxer, size: usize) -> DemuxerResult<usize> {
+fn parse_strf_vids(dmx: &mut AVIDemuxer, strmgr: &mut StreamManager, size: usize) -> DemuxerResult<usize> {
if size < 40 { return Err(InvalidData); }
let bi_size = dmx.src.read_u32le()?;
if (bi_size as usize) > size { return Err(InvalidData); }
Some(name) => name,
};
let vinfo = NACodecInfo::new(cname, vci, edata);
- let res = dmx.dmx.add_stream(NAStream::new(StreamType::Video, dmx.sstate.strm_no as u32, vinfo, dmx.tb_num, dmx.tb_den));
+ let res = strmgr.add_stream(NAStream::new(StreamType::Video, dmx.sstate.strm_no as u32, vinfo, dmx.tb_num, dmx.tb_den));
if let None = res { return Err(MemoryError); }
dmx.sstate.reset();
Ok(size)
}
#[allow(unused_variables)]
-fn parse_strf_auds(dmx: &mut AVIDemuxer, size: usize) -> DemuxerResult<usize> {
+fn parse_strf_auds(dmx: &mut AVIDemuxer, strmgr: &mut StreamManager, size: usize) -> DemuxerResult<usize> {
if size < 16 { return Err(InvalidData); }
let w_format_tag = dmx.src.read_u16le()?;
let channels = dmx.src.read_u16le()?;
Some(name) => name,
};
let ainfo = NACodecInfo::new(cname, NACodecTypeInfo::Audio(ahdr), edata);
- let res = dmx.dmx.add_stream(NAStream::new(StreamType::Audio, dmx.sstate.strm_no as u32, ainfo, dmx.tb_num, dmx.tb_den));
+ let res = strmgr.add_stream(NAStream::new(StreamType::Audio, dmx.sstate.strm_no as u32, ainfo, dmx.tb_num, dmx.tb_den));
if let None = res { return Err(MemoryError); }
dmx.sstate.reset();
Ok(size)
}
-fn parse_strf_xxxx(dmx: &mut AVIDemuxer, size: usize) -> DemuxerResult<usize> {
+fn parse_strf_xxxx(dmx: &mut AVIDemuxer, strmgr: &mut StreamManager, size: usize) -> DemuxerResult<usize> {
let edata = dmx.read_extradata(size)?;
let info = NACodecInfo::new("unknown", NACodecTypeInfo::None, edata);
- let res = dmx.dmx.add_stream(NAStream::new(StreamType::Data, dmx.sstate.strm_no as u32, info, dmx.tb_num, dmx.tb_den));
+ let res = strmgr.add_stream(NAStream::new(StreamType::Data, dmx.sstate.strm_no as u32, info, dmx.tb_num, dmx.tb_den));
if let None = res { return Err(MemoryError); }
dmx.sstate.reset();
Ok(size)
}
#[allow(unused_variables)]
-fn parse_avih(dmx: &mut AVIDemuxer, size: usize) -> DemuxerResult<usize> {
+fn parse_avih(dmx: &mut AVIDemuxer, strmgr: &mut StreamManager, size: usize) -> DemuxerResult<usize> {
if size < 0x38 { return Err(InvalidData); }
let timebase = dmx.src.read_u32le()?; //microsec per frame
dmx.src.read_skip(4)?; //max frame size
Ok(size)
}
-fn parse_junk(dmx: &mut AVIDemuxer, size: usize) -> DemuxerResult<usize> {
+#[allow(unused_variables)]
+fn parse_junk(dmx: &mut AVIDemuxer, strmgr: &mut StreamManager, size: usize) -> DemuxerResult<usize> {
dmx.src.read_skip(size)?;
Ok(size)
}
pub struct AVIDemuxerCreator { }
impl DemuxerCreator for AVIDemuxerCreator {
- fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box<Demux<'a> + 'a> {
+ fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box<DemuxCore<'a> + 'a> {
Box::new(AVIDemuxer::new(br))
}
fn get_name(&self) -> &'static str { "avi" }
let mut fr = FileReader::new_read(&mut file);
let mut br = ByteReader::new(&mut fr);
let mut dmx = AVIDemuxer::new(&mut br);
- dmx.open().unwrap();
+ let mut sm = StreamManager::new();
+ dmx.open(&mut sm).unwrap();
loop {
- let pktres = dmx.get_frame();
+ let pktres = dmx.get_frame(&mut sm);
if let Err(e) = pktres {
if e == DemuxerError::EOF { break; }
panic!("error");
apacked: bool,
state: GDVState,
pktdta: Vec<u8>,
- dmx: Demuxer,
a_id: Option<usize>,
v_id: Option<usize>,
}
GDVFixedSizes { id: 21, width: 320, height: 240 },
];
-impl<'a> Demux<'a> for GremlinVideoDemuxer<'a> {
+impl<'a> DemuxCore<'a> for GremlinVideoDemuxer<'a> {
#[allow(unused_variables)]
- fn open(&mut self) -> DemuxerResult<()> {
+ fn open(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<()> {
let src = &mut self.src;
let magic = src.read_u32le()?;
if magic != 0x29111994 { return Err(DemuxerError::InvalidData); }
let vhdr = NAVideoInfo::new(width as usize, height as usize, false, PAL8_FORMAT);
let vci = NACodecTypeInfo::Video(vhdr);
let vinfo = NACodecInfo::new("gdv-video", vci, if edata.len() == 0 { None } else { Some(edata) });
- self.v_id = self.dmx.add_stream(NAStream::new(StreamType::Video, 0, vinfo, 1, fps as u32));
+ self.v_id = strmgr.add_stream(NAStream::new(StreamType::Video, 0, vinfo, 1, fps as u32));
}
if (aflags & 1) != 0 {
let channels = if (aflags & 2) != 0 { 2 } else { 1 };
let ahdr = NAAudioInfo::new(rate as u32, channels as u8, if depth == 16 { SND_S16_FORMAT } else { SND_U8_FORMAT }, 2);
let ainfo = NACodecInfo::new(if packed != 0 { "gdv-audio" } else { "pcm" },
NACodecTypeInfo::Audio(ahdr), None);
- self.a_id = self.dmx.add_stream(NAStream::new(StreamType::Audio, 1, ainfo, 1, rate as u32));
+ self.a_id = strmgr.add_stream(NAStream::new(StreamType::Audio, 1, ainfo, 1, rate as u32));
self.asize = (((rate / fps) * channels * (depth / 8)) >> packed) as usize;
self.apacked = (aflags & 8) != 0;
}
#[allow(unused_variables)]
- fn get_frame(&mut self) -> DemuxerResult<NAPacket> {
+ fn get_frame(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<NAPacket> {
if !self.opened { return Err(DemuxerError::NoSuchInput); }
if self.cur_frame >= self.frames { return Err(DemuxerError::EOF); }
match self.state {
- GDVState::NewFrame if self.asize > 0 => { self.read_achunk() }
- _ => { self.read_vchunk() }
+ GDVState::NewFrame if self.asize > 0 => { self.read_achunk(strmgr) }
+ _ => { self.read_vchunk(strmgr) }
}
}
- fn get_num_streams(&self) -> usize { self.dmx.get_num_streams() }
- fn get_stream(&self, idx: usize) -> Option<Rc<NAStream>> { self.dmx.get_stream(idx) }
-
#[allow(unused_variables)]
fn seek(&mut self, time: u64) -> DemuxerResult<()> {
if !self.opened { return Err(DemuxerError::NoSuchInput); }
src: io,
a_id: None,
v_id: None,
- dmx: Demuxer::new()
}
}
- fn read_achunk(&mut self) -> DemuxerResult<NAPacket> {
+ fn read_achunk(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<NAPacket> {
self.state = GDVState::AudioRead;
- let str = self.dmx.get_stream(self.a_id.unwrap()).unwrap();
+ let str = strmgr.get_stream(self.a_id.unwrap()).unwrap();
let (tb_num, tb_den) = str.get_timebase();
let ts = NATimeInfo::new(Some(self.cur_frame as u64), None, None, tb_num, tb_den);
self.src.read_packet(str, ts, true, self.asize)
}
- fn read_vchunk(&mut self) -> DemuxerResult<NAPacket> {
- let str = self.dmx.get_stream(self.v_id.unwrap()).unwrap();
+ fn read_vchunk(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<NAPacket> {
+ let str = strmgr.get_stream(self.v_id.unwrap()).unwrap();
let mut src = &mut self.src;
let magic = src.read_u16be()?;
if magic != 0x0513 { return Err(DemuxerError::InvalidData); }
pub struct GDVDemuxerCreator { }
impl DemuxerCreator for GDVDemuxerCreator {
- fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box<Demux<'a> + 'a> {
+ fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box<DemuxCore<'a> + 'a> {
Box::new(GremlinVideoDemuxer::new(br))
}
fn get_name(&self) -> &'static str { "gdv" }
let mut fr = FileReader::new_read(&mut file);
let mut br = ByteReader::new(&mut fr);
let mut dmx = GremlinVideoDemuxer::new(&mut br);
- dmx.open().unwrap();
+ let mut sm = StreamManager::new();
+ dmx.open(&mut sm).unwrap();
loop {
- let pktres = dmx.get_frame();
+ let pktres = dmx.get_frame(&mut sm);
if let Err(e) = pktres {
if (e as i32) == (DemuxerError::EOF as i32) { break; }
panic!("error");
#[cfg(feature="demuxer_gdv")]
-pub mod gdv;
+mod gdv;
#[cfg(feature="demuxer_avi")]
-pub mod avi;
+mod avi;
use std::rc::Rc;
use frame::*;
type DemuxerResult<T> = Result<T, DemuxerError>;
-pub trait Demux<'a> {
- fn open(&mut self) -> DemuxerResult<()>;
- fn get_num_streams(&self) -> usize;
- fn get_stream(&self, idx: usize) -> Option<Rc<NAStream>>;
- fn get_frame(&mut self) -> DemuxerResult<NAPacket>;
+pub trait DemuxCore<'a> {
+ fn open(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<()>;
+ fn get_frame(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<NAPacket>;
fn seek(&mut self, time: u64) -> DemuxerResult<()>;
}
}
}
-struct Demuxer {
+pub struct StreamManager {
streams: Vec<Rc<NAStream>>,
+ ignored: Vec<bool>,
+ no_ign: bool,
}
-impl Demuxer {
- pub fn new() -> Self { Demuxer { streams: Vec::new() } }
+impl StreamManager {
+ pub fn new() -> Self {
+ StreamManager {
+ streams: Vec::new(),
+ ignored: Vec::new(),
+ no_ign: true,
+ }
+ }
+ pub fn iter(&self) -> StreamIter { StreamIter::new(&self.streams) }
+
pub fn add_stream(&mut self, stream: NAStream) -> Option<usize> {
let stream_num = self.streams.len();
let mut str = stream.clone();
str.set_num(stream_num);
self.streams.push(Rc::new(str));
+ self.ignored.push(false);
Some(stream_num)
}
pub fn get_stream(&self, idx: usize) -> Option<Rc<NAStream>> {
None
}
}
- #[allow(dead_code)]
pub fn get_stream_by_id(&self, id: u32) -> Option<Rc<NAStream>> {
for i in 0..self.streams.len() {
if self.streams[i].get_id() == id {
None
}
pub fn get_num_streams(&self) -> usize { self.streams.len() }
+ pub fn is_ignored(&self, idx: usize) -> bool {
+ if self.no_ign {
+ true
+ } else if idx < self.ignored.len() {
+ self.ignored[idx]
+ } else {
+ false
+ }
+ }
+ pub fn set_ignored(&mut self, idx: usize) {
+ if idx < self.ignored.len() {
+ self.ignored[idx] = true;
+ self.no_ign = false;
+ }
+ }
+ pub fn set_unignored(&mut self, idx: usize) {
+ if idx < self.ignored.len() {
+ self.ignored[idx] = false;
+ }
+ }
+}
+
+pub struct StreamIter<'a> {
+ streams: &'a Vec<Rc<NAStream>>,
+ pos: usize,
+}
+
+impl<'a> StreamIter<'a> {
+ pub fn new(streams: &'a Vec<Rc<NAStream>>) -> Self {
+ StreamIter { streams: streams, pos: 0 }
+ }
+}
+
+impl<'a> Iterator for StreamIter<'a> {
+ type Item = Rc<NAStream>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ if self.pos >= self.streams.len() { return None; }
+ let ret = self.streams[self.pos].clone();
+ self.pos += 1;
+ Some(ret)
+ }
+}
+
+pub struct Demuxer<'a> {
+ dmx: Box<DemuxCore<'a> + 'a>,
+ streams: StreamManager,
+}
+
+impl<'a> Demuxer<'a> {
+ fn new(dmx: Box<DemuxCore<'a> + 'a>, str: StreamManager) -> Self {
+ Demuxer {
+ dmx: dmx,
+ streams: str,
+ }
+ }
+ pub fn get_stream(&self, idx: usize) -> Option<Rc<NAStream>> {
+ self.streams.get_stream(idx)
+ }
+ pub fn get_stream_by_id(&self, id: u32) -> Option<Rc<NAStream>> {
+ self.streams.get_stream_by_id(id)
+ }
+ pub fn get_num_streams(&self) -> usize {
+ self.streams.get_num_streams()
+ }
+ pub fn get_streams(&self) -> StreamIter {
+ self.streams.iter()
+ }
+ pub fn is_ignored_stream(&self, idx: usize) -> bool {
+ self.streams.is_ignored(idx)
+ }
+ pub fn set_ignored_stream(&mut self, idx: usize) {
+ self.streams.set_ignored(idx)
+ }
+ pub fn set_unignored_stream(&mut self, idx: usize) {
+ self.streams.set_unignored(idx)
+ }
+
+ pub fn get_frame(&mut self) -> DemuxerResult<NAPacket> {
+ loop {
+ let res = self.dmx.get_frame(&mut self.streams);
+ if self.streams.no_ign || res.is_err() { return res; }
+ let res = res.unwrap();
+ let idx = res.get_stream().get_num();
+ if !self.is_ignored_stream(idx) {
+ return Ok(res);
+ }
+ }
+ }
+ pub fn seek(&mut self, time: u64) -> DemuxerResult<()> {
+ self.dmx.seek(time)
+ }
}
impl From<ByteIOError> for DemuxerError {
///The structure used to create demuxers.
pub trait DemuxerCreator {
/// Create new demuxer instance that will use `ByteReader` source as an input.
- fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box<Demux<'a> + 'a>;
+ fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box<DemuxCore<'a> + 'a>;
/// Get the name of current demuxer creator.
fn get_name(&self) -> &'static str;
}
}
None
}
+
+pub fn create_demuxer<'a>(dmxcr: &DemuxerCreator, br: &'a mut ByteReader<'a>) -> DemuxerResult<Demuxer<'a>> {
+ let mut dmx = dmxcr.new_demuxer(br);
+ let mut str = StreamManager::new();
+ dmx.open(&mut str)?;
+ Ok(Demuxer::new(dmx, str))
+}
let mut file = File::open(name).unwrap();
let mut fr = FileReader::new_read(&mut file);
let mut br = ByteReader::new(&mut fr);
- let mut dmx = dmx_f.new_demuxer(&mut br);
- dmx.open().unwrap();
+ let mut dmx = create_demuxer(dmx_f, &mut br).unwrap();
let mut decs: Vec<Option<Box<NADecoder>>> = Vec::new();
for i in 0..dmx.get_num_streams() {
let mut file = File::open(name).unwrap();
let mut fr = FileReader::new_read(&mut file);
let mut br = ByteReader::new(&mut fr);
- let mut dmx = dmx_f.new_demuxer(&mut br);
- dmx.open().unwrap();
+ let mut dmx = create_demuxer(dmx_f, &mut br).unwrap();
let mut decs: Vec<Option<Box<NADecoder>>> = Vec::new();
for i in 0..dmx.get_num_streams() {