//! A check of the first bytes of a file against the audio containers voice //! memos come in, before anything decodes it. //! //! The audio comes from matrix rooms with outside people, so the decoder only //! ever sees files that start like an audio container. A file that claims to //! be anything else (a playlist, an image, a script) stops here, which keeps //! most of `ffmpeg`'s demuxers out of reach. /// `true` when `bytes` start like Ogg (Opus, Vorbis), WAV, FLAC, MP3 (with or /// without an `ID3` tag), AMR, `MP4` or `M4A`, Matroska or `WebM`. #[must_use] pub fn is_audio(bytes: &[u8]) -> bool { let starts = |magic: &[u8]| bytes.starts_with(magic); starts(b"OggS") || (starts(b"RIFF") && bytes.get(8..12) == Some(b"WAVE")) || starts(b"fLaC") || starts(b"ID3") || starts(b"#!AMR") // An MPEG audio frame: eleven set bits of sync. || matches!(bytes, [0xFF, second, ..] if second & 0xE0 == 0xE0) // The `ftyp` box of an ISO base media file (MP4, M4A, 3GP). || bytes.get(4..8) == Some(b"ftyp") // The EBML header of Matroska and WebM. || starts(&[0x1A, 0x45, 0xDF, 0xA3]) } #[cfg(test)] mod tests { use super::is_audio; #[test] fn the_containers_voice_memos_come_in_pass() { for (name, head) in [ ("ogg", &b"OggS\0\x02"[..]), ("wav", b"RIFF\x24\0\0\0WAVEfmt "), ("flac", b"fLaC\0"), ("mp3 with a tag", b"ID3\x04\0"), ("mp3 frame", &[0xFF, 0xFB, 0x90, 0x00]), ("amr", b"#!AMR\n"), ("m4a", b"\0\0\0\x20ftypM4A "), ("webm", &[0x1A, 0x45, 0xDF, 0xA3, 0x9F]), ] { assert!(is_audio(head), "{name} was refused"); } } #[test] fn files_that_are_not_audio_containers_are_refused() { for (name, head) in [ ("an HLS playlist", &b"#EXTM3U\n#EXT-X-VERSION:3\n"[..]), ("a png", b"\x89PNG\r\n\x1a\n"), ("a script", b"#!/bin/sh\nid\n"), ( "a concat list", b"ffconcat version 1.0\nfile '/etc/passwd'\n", ), ("a wave-less riff (avi)", b"RIFF\x24\0\0\0AVI LIST"), ("empty", b""), ("one byte", &[0xFF]), ] { assert!(!is_audio(head), "{name} was accepted"); } } }