diff options
author | metamuffin <metamuffin@disroot.org> | 2025-09-13 16:08:42 +0200 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2025-09-13 16:08:42 +0200 |
commit | 044c7e1c75145f1ec9d002b4f6fc4433ff7f9540 (patch) | |
tree | db326c8f2327396ed443a1822936927e7c847494 /remuxer/src/magic.rs | |
parent | e99bde7a00a161ff5dd91eaf1ce546a9d98cef05 (diff) | |
download | jellything-044c7e1c75145f1ec9d002b4f6fc4433ff7f9540.tar jellything-044c7e1c75145f1ec9d002b4f6fc4433ff7f9540.tar.bz2 jellything-044c7e1c75145f1ec9d002b4f6fc4433ff7f9540.tar.zst |
start remuxer crate rewrite; added matroska demuxer and format detection
Diffstat (limited to 'remuxer/src/magic.rs')
-rw-r--r-- | remuxer/src/magic.rs | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/remuxer/src/magic.rs b/remuxer/src/magic.rs new file mode 100644 index 0000000..65ab4de --- /dev/null +++ b/remuxer/src/magic.rs @@ -0,0 +1,67 @@ +/* + This file is part of jellything (https://codeberg.org/metamuffin/jellything) + which is licensed under the GNU Affero General Public License (version 3); see /COPYING. + Copyright (C) 2025 metamuffin <metamuffin.org> +*/ + +use crate::ContainerFormat; +use anyhow::Result; +use std::io::Read; +use winter_ebml::{Ebml, EbmlHeader, read_vint_slice}; +use winter_matroska::MatroskaFile; + +pub fn detect_container_format(reader: &mut dyn Read) -> Result<Option<ContainerFormat>> { + let mut data = Vec::new(); + reader.take(128).read_to_end(&mut data)?; + Ok(test_matroska(&data)) +} + +fn test_matroska(mut data: &[u8]) -> Option<ContainerFormat> { + let tag = read_vint_slice(&mut data)?; + if tag != MatroskaFile::TAG_EBML_HEADER { + return None; + }; + let size = read_vint_slice(&mut data)? as usize; + if size > data.len() { + return None; + } + let header = EbmlHeader::read(&data[..size]).ok()?; + match header.doc_type.as_str() { + "matroska" => Some(ContainerFormat::Matroska), + "webm" => Some(ContainerFormat::Webm), + _ => None, + } +} + +#[test] +fn verify_matroska() { + // WebM + let sample = "\ +1a45dfa39f4286810142f7810142f2810442f381084282847765626d4287\ +8104428581021853806701000000088a9c1a114d9b74bc4dbb8b53ab8415\ +49a96653ac81a14dbb8b53ab841654ae6b53ac81d64dbb8c53ab841254c3\ +6753ac8201a04dbb8e53ab841c53bb6b53ac84088a9accec010000000000\ +0057000000000000"; + let sample = hex::decode(sample).unwrap(); + assert_eq!(test_matroska(&sample), Some(ContainerFormat::Webm)); + + // Matroska + let sample = "\ +1a45dfa3a34286810142f7810142f2810442f381084282886d6174726f73\ +6b61428781044285810218538067010000005d66b4a2114d9b74c2bf8492\ +1ae3e14dbb8b53ab841549a96653ac81a14dbb8b53ab841654ae6b53ac81\ +ef4dbb8c53ab841254c36753ac82019b4dbb8e53ab841c53bb6b53ac845d\ +66a14aec01000000"; + let sample = hex::decode(sample).unwrap(); + assert_eq!(test_matroska(&sample), Some(ContainerFormat::Matroska)); + + // GIF + let sample = "\ +47494638396100010001f71f000000002400004800006c0000900000b400\ +00d80000fc00000024002424004824006c2400902400b42400d82400fc24\ +000048002448004848006c4800904800b44800d84800fc4800006c00246c\ +00486c006c6c00906c00b46c00d86c00fc6c000090002490004890006c90\ +00909000b49000d8"; + let sample = hex::decode(sample).unwrap(); + assert_eq!(test_matroska(&sample), None) +} |