aboutsummaryrefslogtreecommitdiff
path: root/remuxer/src/magic.rs
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2025-09-13 16:08:42 +0200
committermetamuffin <metamuffin@disroot.org>2025-09-13 16:08:42 +0200
commit044c7e1c75145f1ec9d002b4f6fc4433ff7f9540 (patch)
treedb326c8f2327396ed443a1822936927e7c847494 /remuxer/src/magic.rs
parente99bde7a00a161ff5dd91eaf1ce546a9d98cef05 (diff)
downloadjellything-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.rs67
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)
+}