diff options
Diffstat (limited to 'remuxer/src/import')
| -rw-r--r-- | remuxer/src/import/mod.rs | 176 | 
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(()) +} | 
