From ab683361f34521567eb54daaa75d6e8a4450a60c Mon Sep 17 00:00:00 2001 From: Kostya Shishkov Date: Tue, 18 Feb 2020 18:50:39 +0100 Subject: [PATCH] core/demuxers: document module --- nihav-core/src/demuxers/mod.rs | 85 ++++++++++++++++++++++++++++++++-- 1 file changed, 81 insertions(+), 4 deletions(-) diff --git a/nihav-core/src/demuxers/mod.rs b/nihav-core/src/demuxers/mod.rs index ee2fe58..8857cee 100644 --- a/nihav-core/src/demuxers/mod.rs +++ b/nihav-core/src/demuxers/mod.rs @@ -1,30 +1,49 @@ +//! Demuxer definitions. pub use crate::frame::*; pub use crate::io::byteio::*; +/// A list specifying general demuxing errors. #[derive(Debug,Clone,Copy,PartialEq)] #[allow(dead_code)] pub enum DemuxerError { + /// Reader got to end of stream. EOF, + /// Demuxer encountered empty container. NoSuchInput, + /// Demuxer encountered invalid input data. InvalidData, + /// Data reading error. IOError, + /// Feature is not implemented. NotImplemented, + /// Allocation failed. MemoryError, + /// The operation should be repeated. TryAgain, + /// Seeking failed. SeekError, + /// Operation cannot succeed in principle (e.g. seeking in a format not supporting seeking). NotPossible, } +/// A specialised `Result` type for demuxing operations. pub type DemuxerResult = Result; +/// A trait for demuxing operations. pub trait DemuxCore<'a> { + /// 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<()>; + /// Demuxes a packet. fn get_frame(&mut self, strmgr: &mut StreamManager) -> DemuxerResult; + /// Seeks to the requested time. fn seek(&mut self, time: u64, seek_idx: &SeekIndex) -> DemuxerResult<()>; } +/// 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; + /// Reads input into already existing packet. fn fill_packet(&mut self, pkt: &mut NAPacket) -> DemuxerResult<()>; } @@ -45,6 +64,7 @@ impl<'a> NAPacketReader for ByteReader<'a> { } } +/// An auxiliary structure for operations with individual streams inside the container. #[derive(Default)] pub struct StreamManager { streams: Vec, @@ -53,6 +73,7 @@ pub struct StreamManager { } impl StreamManager { + /// Constructs a new instance of `StreamManager`. pub fn new() -> Self { StreamManager { streams: Vec::new(), @@ -60,8 +81,10 @@ impl StreamManager { no_ign: true, } } + /// Returns stream iterator. pub fn iter(&self) -> StreamIter { StreamIter::new(&self.streams) } + /// Adds a new stream. pub fn add_stream(&mut self, stream: NAStream) -> Option { let stream_num = self.streams.len(); let mut str = stream.clone(); @@ -70,6 +93,7 @@ impl StreamManager { self.ignored.push(false); Some(stream_num) } + /// Returns stream with the requested index. pub fn get_stream(&self, idx: usize) -> Option { if idx < self.streams.len() { Some(self.streams[idx].clone()) @@ -77,6 +101,7 @@ impl StreamManager { None } } + /// Returns stream with the requested stream ID. pub fn get_stream_by_id(&self, id: u32) -> Option { for i in 0..self.streams.len() { if self.streams[i].get_id() == id { @@ -85,7 +110,9 @@ impl StreamManager { } None } + /// Returns the number of known streams. pub fn get_num_streams(&self) -> usize { self.streams.len() } + /// Reports whether the stream is marked as ignored. pub fn is_ignored(&self, idx: usize) -> bool { if self.no_ign { true @@ -95,6 +122,7 @@ impl StreamManager { false } } + /// Reports whether the stream with certain ID is marked as ignored. pub fn is_ignored_id(&self, id: u32) -> bool { for i in 0..self.streams.len() { if self.streams[i].get_id() == id { @@ -103,12 +131,14 @@ impl StreamManager { } false } + /// Marks requested stream as ignored. pub fn set_ignored(&mut self, idx: usize) { if idx < self.ignored.len() { self.ignored[idx] = true; self.no_ign = false; } } + /// Clears the ignored mark for the requested stream. pub fn set_unignored(&mut self, idx: usize) { if idx < self.ignored.len() { self.ignored[idx] = false; @@ -116,12 +146,14 @@ impl StreamManager { } } +/// Stream iterator. pub struct StreamIter<'a> { streams: &'a [NAStreamRef], pos: usize, } impl<'a> StreamIter<'a> { + /// Constructs a new instance of `StreamIter`. pub fn new(streams: &'a [NAStreamRef]) -> Self { StreamIter { streams, pos: 0 } } @@ -138,10 +170,14 @@ impl<'a> Iterator for StreamIter<'a> { } } +/// Seeking modes. #[derive(Clone,Copy,PartialEq)] pub enum SeekIndexMode { + /// No seeking index present. None, + /// Seeking index is present. Present, + /// Seeking index should be constructed by the demuxer if possible. Automatic, } @@ -149,21 +185,30 @@ impl Default for SeekIndexMode { fn default() -> Self { SeekIndexMode::None } } +/// A structure holding seeking information. #[derive(Clone,Copy,Default)] pub struct SeekEntry { - pub time: u64, // in milliseconds + /// Time in milliseconds. + pub time: u64, + /// PTS pub pts: u64, + /// Position in file. pub pos: u64, } +/// Seeking information for individual streams. #[derive(Clone)] pub struct StreamSeekInfo { + /// Stream ID. pub id: u32, + /// Index is present. pub filled: bool, + /// Packet seeking information. pub entries: Vec, } impl StreamSeekInfo { + /// Constructs a new `StreamSeekInfo` instance. pub fn new(id: u32) -> Self { Self { id, @@ -171,9 +216,11 @@ impl StreamSeekInfo { entries: Vec::new(), } } + /// Adds new seeking point. pub fn add_entry(&mut self, entry: SeekEntry) { self.entries.push(entry); } + /// Searches for an appropriate seek position before requested time. pub fn find_pos(&self, time: u64) -> Option { if !self.entries.is_empty() { // todo something faster like binary search @@ -192,21 +239,30 @@ impl StreamSeekInfo { } } +/// Structure for holding seeking point search results. #[derive(Clone,Copy,Default)] pub struct SeekIndexResult { + /// Packet PTS. pub pts: u64, + /// Position in file. pub pos: u64, + /// Stream ID. pub str_id: u32, } +/// Seek information for the whole container. #[derive(Default)] pub struct SeekIndex { + /// Seek information for individual streams. pub seek_info: Vec, + /// Seeking index mode. pub mode: SeekIndexMode, + /// Ignore index flag. pub skip_index: bool, } impl SeekIndex { + /// Constructs a new `SeekIndex` instance. pub fn new() -> Self { Self::default() } pub fn add_stream(&mut self, id: u32) -> usize { let ret = self.stream_id_to_index(id); @@ -217,6 +273,7 @@ impl SeekIndex { 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 { @@ -225,6 +282,7 @@ impl SeekIndex { } None } + /// 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 { @@ -233,6 +291,7 @@ impl SeekIndex { } None } + /// Adds seeking information to the index. pub fn add_entry(&mut self, id: u32, entry: SeekEntry) { let mut idx = self.stream_id_to_index(id); if idx.is_none() { @@ -241,6 +300,7 @@ impl SeekIndex { self.seek_info[idx.unwrap()].add_entry(entry); self.seek_info[idx.unwrap()].filled = true; } + /// Searches for a seek position before requested time. pub fn find_pos(&self, time: u64) -> Option { let mut cand = None; for str in self.seek_info.iter() { @@ -260,6 +320,7 @@ impl SeekIndex { } } +/// Demuxer structure with auxiliary data. pub struct Demuxer<'a> { dmx: Box + 'a>, streams: StreamManager, @@ -267,6 +328,7 @@ pub struct Demuxer<'a> { } impl<'a> Demuxer<'a> { + /// Constructs a new `Demuxer` instance. fn new(dmx: Box + 'a>, str: StreamManager, seek_idx: SeekIndex) -> Self { Demuxer { dmx, @@ -274,28 +336,36 @@ impl<'a> Demuxer<'a> { 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 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 packet from the container. pub fn get_frame(&mut self) -> DemuxerResult { loop { let res = self.dmx.get_frame(&mut self.streams); @@ -307,12 +377,14 @@ impl<'a> Demuxer<'a> { } } } + /// Seeks to the requested time (in milliseconds) if possible. pub fn seek(&mut self, time: u64) -> 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 } @@ -322,14 +394,15 @@ impl From for DemuxerError { fn from(_: ByteIOError) -> Self { DemuxerError::IOError } } -///The structure used to create demuxers. +/// The trait for creating demuxers. pub trait DemuxerCreator { - /// Create new demuxer instance that will use `ByteReader` source as an input. + /// Creates new demuxer instance that will use `ByteReader` source as an input. fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box + 'a>; - /// Get the name of current demuxer creator. + /// Returns the name of current demuxer creator (equal to the container name it can demux). fn get_name(&self) -> &'static str; } +/// Creates demuxer for a provided bytestream. pub fn create_demuxer<'a>(dmxcr: &DemuxerCreator, br: &'a mut ByteReader<'a>) -> DemuxerResult> { let mut dmx = dmxcr.new_demuxer(br); let mut str = StreamManager::new(); @@ -338,18 +411,22 @@ pub fn create_demuxer<'a>(dmxcr: &DemuxerCreator, br: &'a mut ByteReader<'a>) -> Ok(Demuxer::new(dmx, str, seek_idx)) } +/// List of registered demuxers. #[derive(Default)] pub struct RegisteredDemuxers { dmxs: Vec<&'static DemuxerCreator>, } impl RegisteredDemuxers { + /// 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 DemuxerCreator) { self.dmxs.push(dmx); } + /// Searches for a demuxer that supports requested container format. pub fn find_demuxer(&self, name: &str) -> Option<&DemuxerCreator> { for &dmx in self.dmxs.iter() { if dmx.get_name() == name { -- 2.30.2