/* 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 */ 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> { let mut data = Vec::new(); reader.take(128).read_to_end(&mut data)?; Ok(test_matroska(&data)) } fn test_matroska(mut data: &[u8]) -> Option { 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) }