core: introduce muxers module
authorKostya Shishkov <kostya.shishkov@gmail.com>
Thu, 21 May 2020 08:56:32 +0000 (10:56 +0200)
committerKostya Shishkov <kostya.shishkov@gmail.com>
Thu, 21 May 2020 08:56:32 +0000 (10:56 +0200)
nihav-core/Cargo.toml
nihav-core/src/lib.rs
nihav-core/src/muxers/mod.rs [new file with mode: 0644]

index f3f46f9a20d998ff159420302ef811d986a86442..175f7c7f6cd5b31043172801097abd3fb391c3fe 100644 (file)
@@ -5,10 +5,11 @@ authors = ["Kostya Shishkov <kostya.shishkov@gmail.com>"]
 edition = "2018"
 
 [features]
-default = ["decoders", "demuxers", "compr"]
+default = ["decoders", "demuxers", "muxers", "compr"]
 
 decoders = []
 demuxers = []
+muxers = []
 
 compr = ["deflate"]
 deflate = []
\ No newline at end of file
index 99ea57c9802ab795f555debe50fd9781620896c5..c98956d85a3957ecc92ab3685d1dfabc5c2fb61b 100644 (file)
@@ -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 (file)
index 0000000..ba6f780
--- /dev/null
@@ -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<T> = Result<T, MuxerError>;
+
+impl From<ByteIOError> 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<dyn MuxCore<'a> + 'a>,
+    streams:    StreamManager,
+}
+
+impl<'a> Muxer<'a> {
+    /// Constructs a new `Muxer` instance.
+    fn new(mux: Box<dyn MuxCore<'a> + 'a>, str: StreamManager) -> Self {
+        Muxer {
+            mux,
+            streams:    str,
+        }
+    }
+    /// Returns a stream reference by its number.
+    pub fn get_stream(&self, idx: usize) -> Option<NAStreamRef> {
+        self.streams.get_stream(idx)
+    }
+    /// Returns a stream reference by its ID.
+    pub fn get_stream_by_id(&self, id: u32) -> Option<NAStreamRef> {
+        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<dyn MuxCore<'a> + '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<Muxer<'a>> {
+    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
+    }
+}