diff options
author | metamuffin <metamuffin@disroot.org> | 2023-01-16 10:57:40 +0100 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2023-01-16 10:57:40 +0100 |
commit | 9f9449ddd58eb07d20e14e7a75c7387c9cc17ebe (patch) | |
tree | 52e39085589303d3d2e386a3575152fb6594bb61 /tools/src/bin/import.rs | |
parent | e3f1a8ac9f4c9a015e9eac769fb3262e3bd16bad (diff) | |
download | jellything-9f9449ddd58eb07d20e14e7a75c7387c9cc17ebe.tar jellything-9f9449ddd58eb07d20e14e7a75c7387c9cc17ebe.tar.bz2 jellything-9f9449ddd58eb07d20e14e7a75c7387c9cc17ebe.tar.zst |
write more code
Diffstat (limited to 'tools/src/bin/import.rs')
-rw-r--r-- | tools/src/bin/import.rs | 187 |
1 files changed, 187 insertions, 0 deletions
diff --git a/tools/src/bin/import.rs b/tools/src/bin/import.rs new file mode 100644 index 0000000..dfa5267 --- /dev/null +++ b/tools/src/bin/import.rs @@ -0,0 +1,187 @@ +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 std::{fs::File, io::Write, path::PathBuf}; + +#[derive(Parser)] +struct Args { + #[clap(short = 'I', long)] + item: PathBuf, + #[clap(short = 'd', long)] + dry: bool, + #[clap(short = 'i', long)] + input: PathBuf, +} + +fn main() -> anyhow::Result<()> { + env_logger::init_from_env("LOG"); + let args = Args::parse(); + + let mut iteminfo: ItemInfo = serde_json::from_reader(File::open(&args.item)?)?; + // let iteminfo_orig = iteminfo.clone(); + + let input = File::open(args.input.clone()).unwrap(); + let mut input = EbmlReader::new(input); + + read(&mut input, &mut iteminfo)?; + + let k = serde_json::to_string_pretty(&iteminfo)?; + if args.dry { + println!("{k}") + } else { + let mut f = File::create(args.item)?; + f.write_all(k.as_bytes())?; + } + + 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(()) +} |