From a92964d593be4ebf96706842c02b428d68325b8d Mon Sep 17 00:00:00 2001 From: Kostya Shishkov Date: Thu, 21 May 2020 10:56:32 +0200 Subject: [PATCH] core: introduce muxers module --- nihav-core/Cargo.toml | 3 +- nihav-core/src/lib.rs | 3 + nihav-core/src/muxers/mod.rs | 131 +++++++++++++++++++++++++++++++++++ 3 files changed, 136 insertions(+), 1 deletion(-) create mode 100644 nihav-core/src/muxers/mod.rs diff --git a/nihav-core/Cargo.toml b/nihav-core/Cargo.toml index f3f46f9..175f7c7 100644 --- a/nihav-core/Cargo.toml +++ b/nihav-core/Cargo.toml @@ -5,10 +5,11 @@ authors = ["Kostya Shishkov "] edition = "2018" [features] -default = ["decoders", "demuxers", "compr"] +default = ["decoders", "demuxers", "muxers", "compr"] decoders = [] demuxers = [] +muxers = [] compr = ["deflate"] deflate = [] \ No newline at end of file diff --git a/nihav-core/src/lib.rs b/nihav-core/src/lib.rs index 99ea57c..c98956d 100644 --- a/nihav-core/src/lib.rs +++ b/nihav-core/src/lib.rs @@ -9,6 +9,9 @@ pub mod codecs; #[cfg(feature="compr")] pub mod compr; +#[cfg(feature="muxers")] +pub mod muxers; + #[cfg(feature="demuxers")] pub mod demuxers; diff --git a/nihav-core/src/muxers/mod.rs b/nihav-core/src/muxers/mod.rs new file mode 100644 index 0000000..ba6f780 --- /dev/null +++ b/nihav-core/src/muxers/mod.rs @@ -0,0 +1,131 @@ +//! Muxer definitions. +pub use crate::frame::*; +pub use crate::io::byteio::*; +pub use crate::demuxers::{StreamManager, StreamIter}; + +/// A list specifying general muxing errors. +#[derive(Debug,Clone,Copy,PartialEq)] +#[allow(dead_code)] +pub enum MuxerError { + /// An invalid argument was provided to the muxer. + InvalidArgument, + /// Trying to mux data without header being written. + NotCreated, + /// Muxer encountered invalid input packet. + InvalidData, + /// Input stream cannot be stored in this container format. + UnsupportedFormat, + /// Data writing error. + IOError, + /// Feature is not implemented. + NotImplemented, + /// Allocation failed. + MemoryError, + /// Operation cannot succeed in principle (e.g. seeking in an output stream not supporting seeking). + NotPossible, +} + +/// A specialised `Result` type for muxing operations. +pub type MuxerResult = Result; + +impl From for MuxerError { + fn from(_: ByteIOError) -> Self { MuxerError::IOError } +} + +/// A trait for muxing operations. +pub trait MuxCore<'a> { + /// Prepares everything for packet muxing. + fn create(&mut self, strmgr: &StreamManager) -> MuxerResult<()>; + /// Queues a packet for muxing. + fn mux_frame(&mut self, strmgr: &StreamManager, pkt: NAPacket) -> MuxerResult<()>; + /// Flushes the current muxing state. + fn flush(&mut self) -> MuxerResult<()>; + /// Finishes muxing and writes necessary header and trailer information if needed. + fn end(&mut self) -> MuxerResult<()>; +} + +/// Muxer structure with auxiliary data. +pub struct Muxer<'a> { + mux: Box + 'a>, + streams: StreamManager, +} + +impl<'a> Muxer<'a> { + /// Constructs a new `Muxer` instance. + fn new(mux: Box + 'a>, str: StreamManager) -> Self { + Muxer { + mux, + streams: str, + } + } + /// 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() + } + + /// Demuxes a new packet from the container. + pub fn mux_frame(&mut self, pkt: NAPacket) -> MuxerResult<()> { + self.mux.mux_frame(&self.streams, pkt) + } + /// Returns internal seek index. + pub fn flush(&mut self) -> MuxerResult<()> { + self.mux.flush() + } + /// Finishes muxing and writes necessary header and trailer information if needed. + pub fn end(mut self) -> MuxerResult<()> { + self.mux.end() + } +} + +/// The trait for creating muxers. +pub trait MuxerCreator { + /// Creates new muxer instance that will use `ByteWriter` for output. + fn new_muxer<'a>(&self, bw: &'a mut ByteWriter<'a>) -> Box + 'a>; + /// Returns the name of current muxer creator (equal to the container name it can create). + fn get_name(&self) -> &'static str; +} + +/// Creates muxer for a provided bytestream writer. +pub fn create_muxer<'a>(mxcr: &MuxerCreator, str: StreamManager, bw: &'a mut ByteWriter<'a>) -> MuxerResult> { + let mut mux = mxcr.new_muxer(bw); + mux.create(&str)?; + Ok(Muxer::new(mux, str)) +} + +/// List of registered muxers. +#[derive(Default)] +pub struct RegisteredMuxers { + muxes: Vec<&'static MuxerCreator>, +} + +impl RegisteredMuxers { + /// Constructs a new `RegisteredMuxers` instance. + pub fn new() -> Self { + Self { muxes: Vec::new() } + } + /// Registers a new muxer. + pub fn add_muxer(&mut self, mux: &'static MuxerCreator) { + self.muxes.push(mux); + } + /// Searches for a muxer that supports requested container format. + pub fn find_muxer(&self, name: &str) -> Option<&MuxerCreator> { + for &mux in self.muxes.iter() { + if mux.get_name() == name { + return Some(mux); + } + } + None + } +} -- 2.30.2