aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKostya Shishkov <kostya.shishkov@gmail.com>2020-05-21 10:56:32 +0200
committerKostya Shishkov <kostya.shishkov@gmail.com>2020-05-21 10:56:32 +0200
commita92964d593be4ebf96706842c02b428d68325b8d (patch)
tree30057ebf0c370e0eaaf502cc3dad08085e00efbd
parent5d7c05420cbb5ba6ca051defd85b996e037c3fe1 (diff)
downloadnihav-a92964d593be4ebf96706842c02b428d68325b8d.tar.gz
core: introduce muxers module
-rw-r--r--nihav-core/Cargo.toml3
-rw-r--r--nihav-core/src/lib.rs3
-rw-r--r--nihav-core/src/muxers/mod.rs131
3 files changed, 136 insertions, 1 deletions
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 <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
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<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
+ }
+}