diff options
author | metamuffin <metamuffin@disroot.org> | 2023-01-16 12:00:54 +0100 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2023-01-16 12:00:54 +0100 |
commit | 42a81f199793d7d8a07c848d5956436564caf593 (patch) | |
tree | 84bac0b70f6a39a6ef7160d28e00992f95e5c578 | |
parent | 9f9449ddd58eb07d20e14e7a75c7387c9cc17ebe (diff) | |
download | jellything-42a81f199793d7d8a07c848d5956436564caf593.tar jellything-42a81f199793d7d8a07c848d5956436564caf593.tar.bz2 jellything-42a81f199793d7d8a07c848d5956436564caf593.tar.zst |
move importer over to jellyremux
-rw-r--r-- | Cargo.lock | 2 | ||||
-rw-r--r-- | common/src/lib.rs | 1 | ||||
-rw-r--r-- | matroska/src/block.rs | 0 | ||||
-rw-r--r-- | matroska/src/lib.rs | 1 | ||||
-rw-r--r-- | remuxer/Cargo.toml | 3 | ||||
-rw-r--r-- | remuxer/src/import/mod.rs | 176 | ||||
-rw-r--r-- | remuxer/src/lib.rs | 2 | ||||
-rw-r--r-- | tools/Cargo.toml | 1 | ||||
-rw-r--r-- | tools/src/bin/create_item.rs | 1 | ||||
-rw-r--r-- | tools/src/bin/import.rs | 157 |
10 files changed, 190 insertions, 154 deletions
@@ -792,6 +792,7 @@ version = "0.1.0" dependencies = [ "anyhow", "jellycommon", + "jellymatroska", "log", "tokio", ] @@ -825,6 +826,7 @@ dependencies = [ "env_logger", "jellycommon", "jellymatroska", + "jellyremuxer", "log", "serde_json", ] diff --git a/common/src/lib.rs b/common/src/lib.rs index d5fc3fc..a75f599 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -11,6 +11,7 @@ pub struct DirectoryInfo { #[derive(Debug, Clone, Deserialize, Serialize)] pub struct ItemInfo { pub title: String, + pub duration: f64, // in seconds pub tracks: BTreeMap<u64, SourceTrack>, } diff --git a/matroska/src/block.rs b/matroska/src/block.rs new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/matroska/src/block.rs diff --git a/matroska/src/lib.rs b/matroska/src/lib.rs index bcba8fd..d1e0fba 100644 --- a/matroska/src/lib.rs +++ b/matroska/src/lib.rs @@ -3,6 +3,7 @@ pub mod read; pub mod size; pub mod write; pub mod unflatten; +pub mod block; use matroska::MatroskaTag; pub use read::ReadValue; diff --git a/remuxer/Cargo.toml b/remuxer/Cargo.toml index 4327779..82dffd5 100644 --- a/remuxer/Cargo.toml +++ b/remuxer/Cargo.toml @@ -4,9 +4,10 @@ version = "0.1.0" edition = "2021" [dependencies] -tokio = { version = "1.24.1", features = ["io-util"] } jellycommon = { path = "../common" } +jellymatroska = {path = "../matroska"} +tokio = { version = "1.24.1", features = ["io-util"] } anyhow = "1.0.68" log = "0.4.17" diff --git a/remuxer/src/import/mod.rs b/remuxer/src/import/mod.rs new file mode 100644 index 0000000..8a5cd54 --- /dev/null +++ b/remuxer/src/import/mod.rs @@ -0,0 +1,176 @@ +use anyhow::{anyhow, bail, Result}; +use jellycommon::{ItemInfo, SourceTrack, SourceTrackKind}; +use jellymatroska::{ + matroska::MatroskaTag, + read::EbmlReader, + unflatten::{Unflat, Unflatten}, + Master, +}; +use log::{debug, error, info, trace}; + +pub fn import_read(input: &mut EbmlReader, iteminfo: &mut ItemInfo) -> Result<()> { + // TODO dont traverse the entire file, if the tracks are listed at the end + let (mut timestamp_scale, mut duration) = (None, None); + while let Some(item) = input.next() { + let item = item?; + match item { + MatroskaTag::Ebml(_) => { + let mut iter = Unflatten::new_with_end(input, item); + while let Some(Ok(Unflat { children, item })) = iter.next() { + match item { + MatroskaTag::DocType(t) => { + if !matches!(t.as_str(), "matroska" | "webm") { + error!("file is neither matroska nor webm but {:?}", t) + } + } + _ => debug!("(re) tag ignored: {item:?}"), + } + } + } + MatroskaTag::SeekHead(_) => { + Unflatten::new_with_end(input, item); + } + MatroskaTag::Info(_) => { + let mut iter = Unflatten::new_with_end(input, item); + while let Some(Ok(Unflat { children, item })) = iter.next() { + match item { + MatroskaTag::TimestampScale(v) => timestamp_scale = Some(v), + MatroskaTag::Duration(v) => duration = Some(v), + _ => debug!("(ri) tag ignored: {item:?}"), + } + } + } + MatroskaTag::Cluster(_) => { + info!("start of cluster found"); + let mut iter = Unflatten::new_with_end(input, item); + while let Some(Ok(Unflat { children, item })) = iter.next() { + match item { + MatroskaTag::BlockGroup(_) => { + debug!("group"); + let mut iter = children.unwrap(); + while let Some(Ok(Unflat { children, item })) = iter.next() { + match item { + MatroskaTag::Block(_) => (), + _ => trace!("{item:?}"), + } + } + } + MatroskaTag::SimpleBlock(_) => { + // debug!("simple"); + } + _ => debug!("(rc) tag ignored: {item:?}"), + } + } + } + MatroskaTag::Tags(_) => { + Unflatten::new_with_end(input, item); + } + MatroskaTag::Cues(_) => { + let mut iter = Unflatten::new_with_end(input, item); + while let Some(Ok(Unflat { children, item })) = iter.next() { + match item { + MatroskaTag::CuePoint(_) => { + let mut children = children.unwrap(); + while let Some(Ok(Unflat { children, item })) = children.next() { + // error!("{item:?}") + } + } + _ => (), + } + } + } + MatroskaTag::Chapters(_) => { + Unflatten::new_with_end(input, item); + } + MatroskaTag::Tracks(_) => { + let mut iter = Unflatten::new_with_end(input, item); + while let Some(Ok(Unflat { children, item })) = iter.next() { + match item { + MatroskaTag::TrackEntry(_) => { + let mut children = children.unwrap(); + let ( + mut index, + mut language, + mut codec, + mut kind, + mut sample_rate, + mut channels, + mut width, + mut height, + mut name, + mut fps, + mut bit_depth, + ) = ( + None, None, None, None, None, None, None, None, None, None, None, + ); + while let Some(Ok(Unflat { children, item })) = children.next() { + match item { + MatroskaTag::CodecID(b) => codec = Some(b), + MatroskaTag::Language(v) => language = Some(v), + MatroskaTag::TrackNumber(v) => index = Some(v), + MatroskaTag::TrackType(v) => kind = Some(v), + MatroskaTag::Name(v) => name = Some(v), + MatroskaTag::Audio(_) => { + let mut children = children.unwrap(); + while let Some(Ok(Unflat { item, .. })) = children.next() { + match item { + MatroskaTag::Channels(v) => { + channels = Some(v as usize) + } + MatroskaTag::SamplingFrequency(v) => { + sample_rate = Some(v) + } + MatroskaTag::BitDepth(v) => bit_depth = Some(v), + _ => (), + } + } + } + MatroskaTag::Video(_) => { + let mut children = children.unwrap(); + while let Some(Ok(Unflat { item, .. })) = children.next() { + match item { + MatroskaTag::PixelWidth(v) => width = Some(v), + MatroskaTag::PixelHeight(v) => height = Some(v), + MatroskaTag::FrameRate(v) => fps = Some(v), + _ => (), + } + } + } + _ => (), + } + } + let index = index.unwrap(); + let kind = match kind.ok_or(anyhow!("track type required"))? { + 1 => SourceTrackKind::Video { + fps: fps.unwrap_or(f64::NAN), // TODO + width: width.unwrap(), + height: height.unwrap(), + }, + 2 => SourceTrackKind::Audio { + bit_depth: bit_depth.unwrap_or(0) as usize, // TODO + channels: channels.unwrap(), + sample_rate: sample_rate.unwrap(), + }, + 17 => SourceTrackKind::Subtitles, + _ => bail!("invalid track type"), + }; + iteminfo.tracks.insert( + index, + SourceTrack { + name: name.unwrap_or_else(|| "unnamed".to_string()), + codec: codec.unwrap(), + language: language.unwrap_or_else(|| "none".to_string()), + kind, + }, + ); + } + _ => debug!("(rt) tag ignored: {item:?}"), + } + } + } + MatroskaTag::Segment(Master::End) => break, + _ => debug!("(r) tag ignored: {item:?}"), + } + } + Ok(()) +} diff --git a/remuxer/src/lib.rs b/remuxer/src/lib.rs index 749e04f..cc189a3 100644 --- a/remuxer/src/lib.rs +++ b/remuxer/src/lib.rs @@ -1,3 +1,5 @@ +pub mod import; + use jellycommon::ItemInfo; use std::{io::Write, path::PathBuf, sync::Arc}; diff --git a/tools/Cargo.toml b/tools/Cargo.toml index c49dea1..cba6c82 100644 --- a/tools/Cargo.toml +++ b/tools/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" [dependencies] jellycommon = { path = "../common" } jellymatroska = {path = "../matroska"} +jellyremuxer = {path = "../remuxer"} clap = { version = "4.0.32", features = ["derive"] } diff --git a/tools/src/bin/create_item.rs b/tools/src/bin/create_item.rs index 7628f95..4827e74 100644 --- a/tools/src/bin/create_item.rs +++ b/tools/src/bin/create_item.rs @@ -18,6 +18,7 @@ fn main() -> anyhow::Result<()> { let iteminfo = ItemInfo { title: args.title, + duration: 0.0, tracks: Default::default(), }; diff --git a/tools/src/bin/import.rs b/tools/src/bin/import.rs index dfa5267..eeb09e7 100644 --- a/tools/src/bin/import.rs +++ b/tools/src/bin/import.rs @@ -1,13 +1,7 @@ -use anyhow::{anyhow, bail, Result}; use clap::Parser; -use jellycommon::{ItemInfo, SourceTrack, SourceTrackKind}; -use jellymatroska::{ - matroska::MatroskaTag, - read::EbmlReader, - unflatten::{Unflat, Unflatten}, - Master, -}; -use log::{debug, error, info, trace, warn}; +use jellycommon::ItemInfo; +use jellymatroska::read::EbmlReader; +use jellyremuxer::import::import_read; use std::{fs::File, io::Write, path::PathBuf}; #[derive(Parser)] @@ -30,7 +24,7 @@ fn main() -> anyhow::Result<()> { let input = File::open(args.input.clone()).unwrap(); let mut input = EbmlReader::new(input); - read(&mut input, &mut iteminfo)?; + import_read(&mut input, &mut iteminfo)?; let k = serde_json::to_string_pretty(&iteminfo)?; if args.dry { @@ -42,146 +36,3 @@ fn main() -> anyhow::Result<()> { Ok(()) } - -pub fn read(input: &mut EbmlReader, iteminfo: &mut ItemInfo) -> Result<()> { - // TODO dont traverse the entire file, if the tracks are listed at the end - let mut sbc = 0; - while let Some(item) = input.next() { - let item = item?; - match item { - MatroskaTag::Cluster(_) => { - info!("start of cluster found"); - let mut iter = Unflatten::new_with_end(input, item); - while let Some(Ok(Unflat { children, item })) = iter.next() { - match item { - MatroskaTag::BlockGroup(_) => { - debug!("group"); - let mut iter = children.unwrap(); - while let Some(Ok(Unflat { children, item })) = iter.next() { - match item { - MatroskaTag::Block(_) => (), - _ => trace!("{item:?}"), - } - } - } - MatroskaTag::SimpleBlock(_) => { - // debug!("simple"); - } - _ => debug!("(rc) tag ignored: {item:?}"), - } - } - sbc += 1; - } - MatroskaTag::Tags(_) => { - Unflatten::new_with_end(input, item); - } - MatroskaTag::Cues(_) => { - let mut iter = Unflatten::new_with_end(input, item); - while let Some(Ok(Unflat { children, item })) = iter.next() { - match item { - MatroskaTag::CuePoint(_) => { - let mut children = children.unwrap(); - while let Some(Ok(Unflat { children, item })) = children.next() { - // error!("{item:?}") - } - } - _ => (), - } - } - } - MatroskaTag::Chapters(_) => { - Unflatten::new_with_end(input, item); - } - MatroskaTag::Tracks(_) => { - let mut iter = Unflatten::new_with_end(input, item); - while let Some(Ok(Unflat { children, item })) = iter.next() { - match item { - MatroskaTag::TrackEntry(_) => { - let mut children = children.unwrap(); - let ( - mut index, - mut language, - mut codec, - mut kind, - mut sample_rate, - mut channels, - mut width, - mut height, - mut name, - mut fps, - mut bit_depth, - ) = ( - None, None, None, None, None, None, None, None, None, None, None, - ); - while let Some(Ok(Unflat { children, item })) = children.next() { - match item { - MatroskaTag::CodecID(b) => codec = Some(b), - MatroskaTag::Language(v) => language = Some(v), - MatroskaTag::TrackNumber(v) => index = Some(v), - MatroskaTag::TrackType(v) => kind = Some(v), - MatroskaTag::Name(v) => name = Some(v), - MatroskaTag::Audio(_) => { - let mut children = children.unwrap(); - while let Some(Ok(Unflat { item, .. })) = children.next() { - match item { - MatroskaTag::Channels(v) => { - channels = Some(v as usize) - } - MatroskaTag::SamplingFrequency(v) => { - sample_rate = Some(v) - } - MatroskaTag::BitDepth(v) => bit_depth = Some(v), - _ => (), - } - } - } - MatroskaTag::Video(_) => { - let mut children = children.unwrap(); - while let Some(Ok(Unflat { item, .. })) = children.next() { - match item { - MatroskaTag::PixelWidth(v) => width = Some(v), - MatroskaTag::PixelHeight(v) => height = Some(v), - MatroskaTag::FrameRate(v) => fps = Some(v), - _ => (), - } - } - } - _ => (), - } - } - let index = index.unwrap(); - let kind = match kind.ok_or(anyhow!("track type required"))? { - 1 => SourceTrackKind::Video { - fps: fps.unwrap_or(f64::NAN), // TODO - width: width.unwrap(), - height: height.unwrap(), - }, - 2 => SourceTrackKind::Audio { - bit_depth: bit_depth.unwrap_or(0) as usize, // TODO - channels: channels.unwrap(), - sample_rate: sample_rate.unwrap(), - }, - 17 => SourceTrackKind::Subtitles, - _ => bail!("invalid track type"), - }; - iteminfo.tracks.insert( - index, - SourceTrack { - name: name.unwrap_or_else(|| "unnamed".to_string()), - codec: codec.unwrap(), - language: language.unwrap_or_else(|| "none".to_string()), - kind, - }, - ); - } - _ => debug!("(rt) tag ignored: {item:?}"), - } - } - } - MatroskaTag::Segment(Master::End) => break, - _ => debug!("(r) tag ignored: {item:?}"), - } - } - info!("clusters {sbc}"); - Ok(()) -} |