X-Git-Url: https://git.nihav.org/?a=blobdiff_plain;f=nihav-core%2Fsrc%2Fdemuxers%2Fmod.rs;h=300b6af8f5dbca2b661e4e51dbccb115ddb01de3;hb=405cec9eed5d7f58440ec8495f5cbc1f5c6fee40;hp=dfcd11836e0e7d6dcba1c396ec254ab5a150a5f9;hpb=a480a0de101483d802a11e72d758dae00fa4860a;p=nihav.git diff --git a/nihav-core/src/demuxers/mod.rs b/nihav-core/src/demuxers/mod.rs index dfcd118..300b6af 100644 --- a/nihav-core/src/demuxers/mod.rs +++ b/nihav-core/src/demuxers/mod.rs @@ -45,18 +45,18 @@ pub trait DemuxCore<'a>: NAOptionHandler { /// An auxiliary trait to make bytestream reader read packet data. pub trait NAPacketReader { /// Reads input and constructs a packet containing it. - fn read_packet(&mut self, str: NAStreamRef, ts: NATimeInfo, keyframe: bool, size: usize) -> DemuxerResult; + fn read_packet(&mut self, strm: NAStreamRef, ts: NATimeInfo, keyframe: bool, size: usize) -> DemuxerResult; /// Reads input into already existing packet. fn fill_packet(&mut self, pkt: &mut NAPacket) -> DemuxerResult<()>; } impl<'a> NAPacketReader for ByteReader<'a> { - fn read_packet(&mut self, str: NAStreamRef, ts: NATimeInfo, kf: bool, size: usize) -> DemuxerResult { + fn read_packet(&mut self, strm: NAStreamRef, ts: NATimeInfo, kf: bool, size: usize) -> DemuxerResult { let mut buf: Vec = Vec::with_capacity(size); if buf.capacity() < size { return Err(DemuxerError::MemoryError); } buf.resize(size, 0); self.read_buf(buf.as_mut_slice())?; - let pkt = NAPacket::new(str, ts, kf, buf); + let pkt = NAPacket::new(strm, ts, kf, buf); Ok(pkt) } fn fill_packet(&mut self, pkt: &mut NAPacket) -> DemuxerResult<()> { @@ -90,9 +90,9 @@ impl StreamManager { /// Adds a new stream. pub fn add_stream(&mut self, stream: NAStream) -> Option { let stream_num = self.streams.len(); - let mut str = stream; - str.set_num(stream_num); - self.streams.push(str.into_ref()); + let mut stream = stream; + stream.set_num(stream_num); + self.streams.push(stream.into_ref()); self.ignored.push(false); Some(stream_num) } @@ -291,17 +291,17 @@ impl SeekIndex { pub fn new() -> Self { Self::default() } pub fn add_stream(&mut self, id: u32) -> usize { let ret = self.stream_id_to_index(id); - if ret.is_none() { + if let Some(res) = ret { + res + } else { self.seek_info.push(StreamSeekInfo::new(id)); self.seek_info.len() - 1 - } else { - ret.unwrap() } } /// Adds a new stream to the index. pub fn stream_id_to_index(&self, id: u32) -> Option { - for (idx, str) in self.seek_info.iter().enumerate() { - if str.id == id { + for (idx, strm) in self.seek_info.iter().enumerate() { + if strm.id == id { return Some(idx); } } @@ -309,9 +309,9 @@ impl SeekIndex { } /// Returns stream reference for provided stream ID. pub fn get_stream_index(&mut self, id: u32) -> Option<&mut StreamSeekInfo> { - for str in self.seek_info.iter_mut() { - if str.id == id { - return Some(str); + for stream in self.seek_info.iter_mut() { + if stream.id == id { + return Some(stream); } } None @@ -328,16 +328,16 @@ impl SeekIndex { /// Searches for a seek position before requested time. pub fn find_pos(&self, time: NATimePoint) -> Option { let mut cand = None; - for str in self.seek_info.iter() { - if !str.filled { continue; } - let res = str.find_pos(time); + for stream in self.seek_info.iter() { + if !stream.filled { continue; } + let res = stream.find_pos(time); if res.is_none() { continue; } let res = res.unwrap(); if cand.is_none() { - cand = Some(SeekIndexResult { pts: res.pts, pos: res.pos, str_id: str.id }); + cand = Some(SeekIndexResult { pts: res.pts, pos: res.pos, str_id: stream.id }); } else if let Some(entry) = cand { if res.pos < entry.pos { - cand = Some(SeekIndexResult { pts: res.pts, pos: res.pos, str_id: str.id }); + cand = Some(SeekIndexResult { pts: res.pts, pos: res.pos, str_id: stream.id }); } } } @@ -354,10 +354,10 @@ pub struct Demuxer<'a> { impl<'a> Demuxer<'a> { /// Constructs a new `Demuxer` instance. - fn new(dmx: Box + 'a>, str: StreamManager, seek_idx: SeekIndex) -> Self { + fn new(dmx: Box + 'a>, strmgr: StreamManager, seek_idx: SeekIndex) -> Self { Demuxer { dmx, - streams: str, + streams: strmgr, seek_idx, } } @@ -465,10 +465,20 @@ pub trait DemuxerCreator { /// Creates demuxer for a provided bytestream. pub fn create_demuxer<'a>(dmxcr: &dyn DemuxerCreator, br: &'a mut ByteReader<'a>) -> DemuxerResult> { let mut dmx = dmxcr.new_demuxer(br); - let mut str = StreamManager::new(); + let mut strmgr = StreamManager::new(); + let mut seek_idx = SeekIndex::new(); + dmx.open(&mut strmgr, &mut seek_idx)?; + Ok(Demuxer::new(dmx, strmgr, seek_idx)) +} + +/// Creates demuxer for a provided bytestream with options applied right after its creation. +pub fn create_demuxer_with_options<'a>(dmxcr: &dyn DemuxerCreator, br: &'a mut ByteReader<'a>, opts: &[NAOption]) -> DemuxerResult> { + let mut dmx = dmxcr.new_demuxer(br); + dmx.set_options(opts); + let mut strmgr = StreamManager::new(); let mut seek_idx = SeekIndex::new(); - dmx.open(&mut str, &mut seek_idx)?; - Ok(Demuxer::new(dmx, str, seek_idx)) + dmx.open(&mut strmgr, &mut seek_idx)?; + Ok(Demuxer::new(dmx, strmgr, seek_idx)) } /// List of registered demuxers. @@ -500,3 +510,179 @@ impl RegisteredDemuxers { self.dmxs.iter() } } + +/// A trait for raw data demuxing operations. +pub trait RawDemuxCore<'a>: NAOptionHandler { + /// Opens the input stream, reads required headers and prepares everything for packet demuxing. + fn open(&mut self, strmgr: &mut StreamManager, seek_idx: &mut SeekIndex) -> DemuxerResult<()>; + /// Reads a piece of raw data. + fn get_data(&mut self, strmgr: &mut StreamManager) -> DemuxerResult; + /// Seeks to the requested time. + fn seek(&mut self, time: NATimePoint, seek_idx: &SeekIndex) -> DemuxerResult<()>; + /// Returns container duration in milliseconds (zero if not available). + fn get_duration(&self) -> u64; +} + +/// Demuxer structure with auxiliary data. +pub struct RawDemuxer<'a> { + dmx: Box + 'a>, + streams: StreamManager, + seek_idx: SeekIndex, +} + +impl<'a> RawDemuxer<'a> { + /// Constructs a new `Demuxer` instance. + fn new(dmx: Box + 'a>, strmgr: StreamManager, seek_idx: SeekIndex) -> Self { + Self { + dmx, + streams: strmgr, + seek_idx, + } + } + /// Returns a stream reference by its number. + pub fn get_stream(&self, idx: usize) -> Option { + self.streams.get_stream(idx) + } + /// Returns a stream reference by its ID. + pub fn get_stream_by_id(&self, id: u32) -> Option { + self.streams.get_stream_by_id(id) + } + /// Reports the total number of streams. + pub fn get_num_streams(&self) -> usize { + self.streams.get_num_streams() + } + /// Returns a reference to the internal stream manager. + pub fn get_stream_manager(&self) -> &StreamManager { + &self.streams + } + /// Returns an iterator over streams. + pub fn get_streams(&self) -> StreamIter { + self.streams.iter() + } + /// Returns 'ignored' marker for requested stream. + pub fn is_ignored_stream(&self, idx: usize) -> bool { + self.streams.is_ignored(idx) + } + /// Sets 'ignored' marker for requested stream. + pub fn set_ignored_stream(&mut self, idx: usize) { + self.streams.set_ignored(idx) + } + /// Clears 'ignored' marker for requested stream. + pub fn set_unignored_stream(&mut self, idx: usize) { + self.streams.set_unignored(idx) + } + + /// Demuxes a new piece of data from the container. + pub fn get_data(&mut self) -> DemuxerResult { + loop { + let res = self.dmx.get_data(&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); + } + } + } + /// Seeks to the requested time if possible. + pub fn seek(&mut self, time: NATimePoint) -> DemuxerResult<()> { + if self.seek_idx.skip_index { + return Err(DemuxerError::NotPossible); + } + self.dmx.seek(time, &self.seek_idx) + } + /// Returns internal seek index. + pub fn get_seek_index(&self) -> &SeekIndex { + &self.seek_idx + } + /// Returns media duration reported by container or its streams. + /// + /// Duration is in milliseconds and set to zero when it is not available. + pub fn get_duration(&self) -> u64 { + let duration = self.dmx.get_duration(); + if duration != 0 { + return duration; + } + let mut duration = 0; + for stream in self.streams.iter() { + if stream.duration > 0 { + let dur = NATimeInfo::ts_to_time(stream.duration, 1000, stream.tb_num, stream.tb_den); + if duration < dur { + duration = dur; + } + } + } + duration + } +} + +impl<'a> NAOptionHandler for RawDemuxer<'a> { + fn get_supported_options(&self) -> &[NAOptionDefinition] { + self.dmx.get_supported_options() + } + fn set_options(&mut self, options: &[NAOption]) { + self.dmx.set_options(options); + } + fn query_option_value(&self, name: &str) -> Option { + self.dmx.query_option_value(name) + } +} + +/// The trait for creating raw data demuxers. +pub trait RawDemuxerCreator { + /// Creates new raw demuxer instance that will use `ByteReader` source as an input. + fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box + 'a>; + /// Tries to check whether the input can be demuxed with the demuxer. + fn check_format(&self, br: &mut ByteReader) -> bool; + /// Returns the name of current raw data demuxer creator (equal to the container name it can demux). + fn get_name(&self) -> &'static str; +} + +/// Creates raw data demuxer for a provided bytestream. +pub fn create_raw_demuxer<'a>(dmxcr: &dyn RawDemuxerCreator, br: &'a mut ByteReader<'a>) -> DemuxerResult> { + let mut dmx = dmxcr.new_demuxer(br); + let mut strmgr = StreamManager::new(); + let mut seek_idx = SeekIndex::new(); + dmx.open(&mut strmgr, &mut seek_idx)?; + Ok(RawDemuxer::new(dmx, strmgr, seek_idx)) +} + +/// Creates raw data demuxer for a provided bytestream with options applied right after its creation. +pub fn create_raw_demuxer_with_options<'a>(dmxcr: &dyn RawDemuxerCreator, br: &'a mut ByteReader<'a>, opts: &[NAOption]) -> DemuxerResult> { + let mut dmx = dmxcr.new_demuxer(br); + dmx.set_options(opts); + let mut strmgr = StreamManager::new(); + let mut seek_idx = SeekIndex::new(); + dmx.open(&mut strmgr, &mut seek_idx)?; + Ok(RawDemuxer::new(dmx, strmgr, seek_idx)) +} + +/// List of registered demuxers. +#[derive(Default)] +pub struct RegisteredRawDemuxers { + dmxs: Vec<&'static dyn RawDemuxerCreator>, +} + +impl RegisteredRawDemuxers { + /// Constructs a new `RegisteredDemuxers` instance. + pub fn new() -> Self { + Self { dmxs: Vec::new() } + } + /// Registers a new demuxer. + pub fn add_demuxer(&mut self, dmx: &'static dyn RawDemuxerCreator) { + self.dmxs.push(dmx); + } + /// Searches for a demuxer that supports requested container format. + pub fn find_demuxer(&self, name: &str) -> Option<&dyn RawDemuxerCreator> { + for &dmx in self.dmxs.iter() { + if dmx.get_name() == name { + return Some(dmx); + } + } + None + } + /// Provides an iterator over currently registered demuxers. + pub fn iter(&self) -> std::slice::Iter<&dyn RawDemuxerCreator> { + self.dmxs.iter() + } +}