aboutsummaryrefslogtreecommitdiff
path: root/remuxer/src/import/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'remuxer/src/import/mod.rs')
-rw-r--r--remuxer/src/import/mod.rs176
1 files changed, 176 insertions, 0 deletions
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(())
+}