diff options
author | metamuffin <metamuffin@disroot.org> | 2023-01-12 22:05:32 +0100 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2023-01-12 22:05:32 +0100 |
commit | 7ca91b6f33bb260bc966e853c832b4339c1c2ae0 (patch) | |
tree | 573eea3ea72a55fff4d43f42de4ae6fe0af4b2d9 | |
parent | 047cb61bcf0ca61c58566ef5ca5d236234e46b21 (diff) | |
download | jellything-7ca91b6f33bb260bc966e853c832b4339c1c2ae0.tar jellything-7ca91b6f33bb260bc966e853c832b4339c1c2ae0.tar.bz2 jellything-7ca91b6f33bb260bc966e853c832b4339c1c2ae0.tar.zst |
implementing my own ebml library
-rw-r--r-- | remuxer/src/format/ebml/matroska.rs | 39 | ||||
-rw-r--r-- | remuxer/src/format/ebml/mod.rs | 3 | ||||
-rw-r--r-- | remuxer/src/format/ebml/read.rs | 44 | ||||
-rw-r--r-- | remuxer/src/format/ebml/write.rs | 38 | ||||
-rw-r--r-- | remuxer/src/format/mod.rs | 1 | ||||
-rw-r--r-- | remuxer/src/lib.rs | 59 | ||||
-rw-r--r-- | server/src/main.rs | 32 | ||||
-rw-r--r-- | tools/src/bin/gen_meta.rs | 2 |
8 files changed, 183 insertions, 35 deletions
diff --git a/remuxer/src/format/ebml/matroska.rs b/remuxer/src/format/ebml/matroska.rs new file mode 100644 index 0000000..50aa783 --- /dev/null +++ b/remuxer/src/format/ebml/matroska.rs @@ -0,0 +1,39 @@ +pub enum TagType { + Master, + UnsignedInt, + Integer, + Utf8, + Binary, + Float, +} + +macro_rules! define_ebml { + ($master:ident { $($name:ident: $kind:ty = $id:literal),* }) => { + pub enum $master { + $($name($kind)),* + } + impl $master { + + } + }; +} + +// 0x1a45dfa3 +define_ebml! { + Ebml { + EbmlVersion: u64 = 0x4286, + EbmlReadVersion: u64 = 0x42f7, + EbmlMaxIdLength: u64 = 0x42f2, + EbmlMaxSizeLength: u64 = 0x42f3, + DocType: String = 0x4282, + DocTypeVersion: u64 = 0x4287, + DocTypeReadVersion: u64 = 0x4285, + DocTypeExtension: DocTypeExtension = 0x4281 + } +} +define_ebml! { + DocTypeExtension { + Name: String = 0x4283, + Version: u64 = 0x4284 + } +} diff --git a/remuxer/src/format/ebml/mod.rs b/remuxer/src/format/ebml/mod.rs new file mode 100644 index 0000000..d8a703a --- /dev/null +++ b/remuxer/src/format/ebml/mod.rs @@ -0,0 +1,3 @@ +pub mod read; +pub mod write; +pub mod matroska; diff --git a/remuxer/src/format/ebml/read.rs b/remuxer/src/format/ebml/read.rs new file mode 100644 index 0000000..06ccf2f --- /dev/null +++ b/remuxer/src/format/ebml/read.rs @@ -0,0 +1,44 @@ +use std::io::{Read, Seek}; + +use anyhow::Result; + +pub struct EbmlReader<T> { + inner: T, + position: usize, +} + +impl<T: Read + Seek> EbmlReader<T> { + pub fn new(inner: T) -> Self { + Self { inner, position: 0 } + } + + pub fn read_byte(&mut self) -> Result<u8> { + let mut b = [0u8]; + self.inner.read_exact(&mut b)?; + Ok(b[0]) + } + pub fn read_vint(&mut self) -> Result<(u64, u64)> { + let s = self.read_byte()? as u64; + let len = s.leading_zeros() + 1; + let mut value = s; + value -= 1 << (8 - len); + for _ in 0..(len - 1) { + value <<= 8; + value += self.read_byte()? as u64; + } + Ok((value, len.into())) + } + + pub fn read_tag_id(&mut self) -> Result<u64> { + let (value, len) = self.read_vint()?; + Ok(value + (1 << (7 * len))) + } + + pub fn read_tag(&mut self) -> Result<()> { + let id = self.read_tag_id()?; + + Ok(()) + + } +} + diff --git a/remuxer/src/format/ebml/write.rs b/remuxer/src/format/ebml/write.rs new file mode 100644 index 0000000..1dee225 --- /dev/null +++ b/remuxer/src/format/ebml/write.rs @@ -0,0 +1,38 @@ +use anyhow::{bail, Result}; +use std::io::Write; + +pub struct EbmlWriter<T> { + inner: T, + position: usize, +} + +impl<T: Write> EbmlWriter<T> { + pub fn new(inner: T, position: usize) -> Self { + Self { inner, position } + } + + pub fn write(&mut self, data: &[u8]) -> Result<()> { + self.inner.write_all(data)?; + self.position += data.len(); + Ok(()) + } + + pub fn write_vint(&mut self, i: u64) -> Result<()> { + if i > (1 << 56) - 1 { + bail!("vint does not fit"); + } + let mut len = 1; + while len <= 8 { + if i < (1 << ((7 * len) - 1)) { + break; + } + len += 1; + } + let mut bytes = i.to_be_bytes(); + bytes[0] |= 1 << (8 - len); + self.write(&bytes) + } + +} + + diff --git a/remuxer/src/format/mod.rs b/remuxer/src/format/mod.rs new file mode 100644 index 0000000..faec908 --- /dev/null +++ b/remuxer/src/format/mod.rs @@ -0,0 +1 @@ +pub mod ebml; diff --git a/remuxer/src/lib.rs b/remuxer/src/lib.rs index 95bd1ff..95e6e8b 100644 --- a/remuxer/src/lib.rs +++ b/remuxer/src/lib.rs @@ -1,9 +1,10 @@ +pub mod format; + use jellycommon::ItemInfo; use log::{debug, info}; use std::{fs::File, io::Write, path::PathBuf, sync::Arc}; -use tokio::sync::mpsc::Sender; use webm_iterable::{ - matroska_spec::{Master, MatroskaSpec, Block}, + matroska_spec::{Block, Master, MatroskaSpec}, WebmIterator, WebmWriter, }; @@ -17,6 +18,7 @@ impl RemuxerContext { pub fn generate_into( &self, writer: impl Write, + offset: usize, path_base: PathBuf, item: ItemInfo, selection: Vec<u64>, @@ -28,9 +30,19 @@ impl RemuxerContext { let tags = WebmIterator::new(&mut input, &[MatroskaSpec::TrackEntry(Master::Start)]); let mut output = WebmWriter::new(writer); + let mut tscale = None; + let mut duration = None; + let mut ignore = false; + for tag in tags { let tag = tag.unwrap(); match tag { + MatroskaSpec::SeekHead(Master::Start) | MatroskaSpec::Cues(Master::Start) => { + ignore = true + } + MatroskaSpec::SeekHead(Master::End) | MatroskaSpec::Cues(Master::End) => { + ignore = false + } MatroskaSpec::TrackEntry(master) => { let children = master.get_children(); let mut number = None; @@ -50,17 +62,31 @@ impl RemuxerContext { if selection.contains(&block.track) { output.write(&tag)?; } - }, + } MatroskaSpec::SimpleBlock(ref data) => { let data: &[u8] = &data; let block: Block = data.try_into()?; if selection.contains(&block.track) { output.write(&tag)?; } - }, + } + MatroskaSpec::Info(Master::Start) => (), + MatroskaSpec::TimestampScale(n) => tscale = Some(n), + MatroskaSpec::Duration(n) => duration = Some(n), + MatroskaSpec::Info(Master::End) => { + output.write(&MatroskaSpec::Info(Master::Full(vec![ + MatroskaSpec::TimestampScale(tscale.unwrap()), + MatroskaSpec::Title(item.title.clone()), + MatroskaSpec::Duration(duration.unwrap()), + MatroskaSpec::MuxingApp("jellyremux".to_string()), + MatroskaSpec::WritingApp("jellything".to_string()), + ])))?; + } x => { - // debug!("tag"); - output.write(&x)?; + if !ignore { + debug!("{x:?}"); + output.write(&x)?; + } } } } @@ -68,16 +94,15 @@ impl RemuxerContext { } } -pub struct SendWriter(pub Sender<Vec<u8>>); +// pub struct SendWriter(pub Sender<Vec<u8>>); -impl Write for SendWriter { - fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> { - debug!("write {buf:?}"); - self.0.blocking_send(buf.to_owned()).unwrap(); - Ok(buf.len()) - } +// impl Write for SendWriter { +// fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> { +// self.0.blocking_send(buf.to_owned()).unwrap(); +// Ok(buf.len()) +// } - fn flush(&mut self) -> std::io::Result<()> { - Ok(()) // TODO should we actually do something here? - } -} +// fn flush(&mut self) -> std::io::Result<()> { +// Ok(()) // TODO should we actually do something here? +// } +// } diff --git a/server/src/main.rs b/server/src/main.rs index 2fc6406..6243b3f 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -1,24 +1,15 @@ #![feature(box_syntax)] use crate::frontend::{pages::MyError, style::CSS_BUNDLE}; -use anyhow::anyhow; +use anyhow::{anyhow, Context}; use database::Database; use frontend::pages::{home::page_home, node::page_library_node}; -use jellyremuxer::{RemuxerContext, SendWriter}; +use jellyremuxer::RemuxerContext; use library::Library; use log::{debug, warn}; -use rocket::{ - get, - http::ContentType, - launch, - response::stream::{ByteStream, ReaderStream}, - routes, State, -}; -use std::{fs::read_to_string, sync::Arc}; -use tokio::{ - io::{duplex, DuplexStream}, - sync::mpsc, -}; +use rocket::{get, http::ContentType, launch, response::stream::ReaderStream, routes, State}; +use std::{fs::read_to_string, path::PathBuf, sync::Arc}; +use tokio::io::{duplex, DuplexStream}; use tokio_util::io::SyncIoBridge; pub mod database; @@ -37,13 +28,19 @@ async fn assets_style() -> (ContentType, String) { ) } -#[get("/stream?<selection>")] +#[get("/stream/<path..>?<selection>")] fn stream( + path: PathBuf, selection: String, state: &State<AppState>, ) -> Result<(ContentType, ReaderStream![DuplexStream]), MyError> { - let (a, b) = duplex(8196); - let item = state.library.nested("mili-bento-box-bivouac")?.get_item()?; + let (a, b) = duplex(1024); + let path = path.to_str().unwrap().to_string(); + let item = state + .library + .nested(&path) + .context("retrieving library node")? + .get_item()?; let remuxer = state.remuxer.clone(); let selection = selection .split(",") @@ -55,6 +52,7 @@ fn stream( tokio::task::spawn_blocking(move || { if let Err(e) = remuxer.generate_into( b, + offset, item.fs_path.parent().unwrap().to_path_buf(), item.data.clone(), selection, diff --git a/tools/src/bin/gen_meta.rs b/tools/src/bin/gen_meta.rs index e7aa559..871836b 100644 --- a/tools/src/bin/gen_meta.rs +++ b/tools/src/bin/gen_meta.rs @@ -83,7 +83,7 @@ fn main() -> anyhow::Result<()> { language: language.unwrap(), }, 17 => SourceTrack::Subtitles { - language: name.unwrap(), + language: name.unwrap_or("unknown".to_string()), codec: codec.unwrap(), }, _ => bail!("invalid track type"), |