Files
pile/crates/pile-audio/src/flac/mod.rs
2026-01-06 23:04:28 -08:00

943 lines
29 KiB
Rust

//! Parse FLAC metadata.
pub mod blockread;
pub mod blocks;
pub mod errors;
pub mod proc;
#[cfg(test)]
mod tests {
use std::str::FromStr;
use itertools::Itertools;
use mime::Mime;
use super::errors::FlacDecodeError;
use crate::common::{picturetype::PictureType, vorbiscomment::VorbisCommentDecodeError};
/// The value of a vorbis comment.
///
/// Some files have VERY large comments, and providing them
/// explicitly here doesn't make sense.
#[derive(Clone)]
pub enum VorbisCommentTestValue {
/// The comments, in order
Raw {
tags: &'static [(&'static str, &'static str)],
},
/// The hash of all comments concatenated together,
/// stringified as `{key}={value};`
Hash {
n_comments: usize,
hash: &'static str,
},
}
#[derive(Clone)]
pub enum FlacBlockOutput {
Application {
application_id: u32,
hash: &'static str,
},
Streaminfo {
min_block_size: u32,
max_block_size: u32,
min_frame_size: u32,
max_frame_size: u32,
sample_rate: u32,
channels: u8,
bits_per_sample: u8,
total_samples: u128,
md5_signature: &'static str,
},
CueSheet {
// Hash of this block's data, without the header.
// This is easy to get with
//
// ```notrust
// metaflac \
// --list \
// --block-number=<n> \
// --data-format=binary-headerless \
// <file> \
// | sha256sum
//```
hash: &'static str,
},
Seektable {
hash: &'static str,
},
Padding {
size: u32,
},
Picture {
picture_type: PictureType,
mime: Mime,
description: &'static str,
width: u32,
height: u32,
bit_depth: u32,
color_count: u32,
img_data: &'static str,
},
VorbisComment {
vendor: &'static str,
comments: VorbisCommentTestValue,
pictures: &'static [FlacBlockOutput],
},
}
pub enum FlacTestCase {
Success {
/// This test's name
test_name: &'static str,
/// The file to use for this test
file_path: &'static str,
/// The hash of the input files
in_hash: &'static str,
/// The flac metablocks we expect to find in this file, in order.
blocks: Vec<FlacBlockOutput>,
/// The hash of the audio frames in this file
///
/// Get this hash by running `metaflac --remove-all --dont-use-padding`,
/// then by manually deleting remaining headers in a hex editor
/// (Remember that the sync sequence is 0xFF 0xF8)
audio_hash: &'static str,
/// The hash we should get when we strip this file's tags.
///
/// A stripped flac file has unmodified STREAMINFO, SEEKTABLE,
/// CUESHEET, and audio data blocks; and nothing else (not even padding).
///
/// Reference implementation:
/// ```notrust
/// metaflac \
/// --remove \
/// --block-type=PADDING,APPLICATION,VORBIS_COMMENT,PICTURE \
/// --dont-use-padding \
/// <file>
/// ```
stripped_hash: &'static str,
},
Error {
/// This test's name
test_name: &'static str,
/// The file to use for this test
file_path: &'static str,
/// The hash of the input files
in_hash: &'static str,
/// The error we should encounter while reading this file
check_error: &'static dyn Fn(&FlacDecodeError) -> bool,
/// If some, stripping this file's metadata should produce the given hash.
/// If none, trying to strip metadata should produce `check_error`
stripped_hash: Option<&'static str>,
/// If some, the following images should be extracted from this file
/// If none, trying to strip images should produce `check_error`
pictures: Option<Vec<FlacBlockOutput>>,
},
}
impl FlacTestCase {
pub fn get_name(&self) -> &str {
match self {
Self::Error { test_name, .. } | Self::Success { test_name, .. } => test_name,
}
}
pub fn get_path(&self) -> &str {
match self {
Self::Success { file_path, .. } | Self::Error { file_path, .. } => file_path,
}
}
pub fn get_in_hash(&self) -> &str {
match self {
Self::Success { in_hash, .. } | Self::Error { in_hash, .. } => in_hash,
}
}
pub fn get_stripped_hash(&self) -> Option<&str> {
match self {
Self::Success { stripped_hash, .. } => Some(stripped_hash),
Self::Error { stripped_hash, .. } => *stripped_hash,
}
}
pub fn get_audio_hash(&self) -> Option<&str> {
match self {
Self::Success { audio_hash, .. } => Some(audio_hash),
_ => None,
}
}
pub fn get_blocks(&self) -> Option<&[FlacBlockOutput]> {
match self {
Self::Success { blocks, .. } => Some(blocks),
_ => None,
}
}
pub fn get_pictures(&self) -> Option<Vec<FlacBlockOutput>> {
match self {
Self::Success { blocks, .. } => {
let mut out = Vec::new();
for b in blocks {
match b {
FlacBlockOutput::Picture { .. } => out.push(b.clone()),
FlacBlockOutput::VorbisComment { pictures, .. } => {
for p in *pictures {
out.push(p.clone())
}
}
_ => {}
}
}
return Some(out);
}
Self::Error { pictures, .. } => {
pictures.as_ref().map(|x| x.iter().cloned().collect())
}
}
}
}
/// A list of test files and their expected output
pub fn manifest() -> [FlacTestCase; 23] {
[
FlacTestCase::Error {
test_name: "uncommon_10",
file_path: concat!(
env!("CARGO_MANIFEST_DIR"),
"/tests/files/flac_uncommon/10 - file starting at frame header.flac"
),
in_hash: "d95f63e8101320f5ac7ffe249bc429a209eb0e10996a987301eaa63386a8faa1",
check_error: &|x| matches!(x, FlacDecodeError::BadMagicBytes),
stripped_hash: None,
pictures: None,
},
FlacTestCase::Error {
test_name: "faulty_06",
file_path: concat!(
env!("CARGO_MANIFEST_DIR"),
"/tests/files/flac_faulty/06 - missing streaminfo metadata block.flac"
),
in_hash: "53aed5e7fde7a652b82ba06a8382b2612b02ebbde7b0d2016276644d17cc76cd",
check_error: &|x| matches!(x, FlacDecodeError::BadFirstBlock),
stripped_hash: None,
pictures: None,
},
FlacTestCase::Error {
test_name: "faulty_07",
file_path: concat!(
env!("CARGO_MANIFEST_DIR"),
"/tests/files/flac_faulty/07 - other metadata blocks preceding streaminfo metadata block.flac"
),
in_hash: "6d46725991ba5da477187fde7709ea201c399d00027257c365d7301226d851ea",
check_error: &|x| matches!(x, FlacDecodeError::BadFirstBlock),
stripped_hash: None,
pictures: None,
},
FlacTestCase::Error {
test_name: "faulty_10",
file_path: concat!(
env!("CARGO_MANIFEST_DIR"),
"/tests/files/flac_faulty/10 - invalid vorbis comment metadata block.flac"
),
in_hash: "c79b0514a61634035a5653c5493797bbd1fcc78982116e4d429630e9e462d29b",
check_error: &|x| {
matches!(
x,
FlacDecodeError::VorbisComment(VorbisCommentDecodeError::MalformedData)
)
},
// This file's vorbis comment is invalid, but that shouldn't stop us from removing it.
// As a general rule, we should NOT encounter an error when stripping invalid blocks.
//
// We should, however, get errors when we try to strip flac files with invalid *structure*
// (For example, the out-of-order streaminfo test in faulty_07).
stripped_hash: Some(
"4b994f82dc1699a58e2b127058b37374220ee41dc294d4887ac14f056291a1b0",
),
pictures: None,
},
FlacTestCase::Error {
test_name: "faulty_11",
file_path: concat!(
env!("CARGO_MANIFEST_DIR"),
"/tests/files/flac_faulty/11 - incorrect metadata block length.flac"
),
in_hash: "3732151ba8c4e66a785165aa75a444aad814c16807ddc97b793811376acacfd6",
check_error: &|x| matches!(x, FlacDecodeError::BadMetablockType(127)),
stripped_hash: None,
pictures: None,
},
FlacTestCase::Success {
test_name: "subset_45",
file_path: concat!(
env!("CARGO_MANIFEST_DIR"),
"/tests/files/flac_subset/45 - no total number of samples set.flac"
),
in_hash: "336a18eb7a78f7fc0ab34980348e2895bc3f82db440a2430d9f92e996f889f9a",
blocks: vec![
FlacBlockOutput::Streaminfo {
min_block_size: 4096,
max_block_size: 4096,
min_frame_size: 907,
max_frame_size: 8053,
sample_rate: 48000,
channels: 2,
bits_per_sample: 16,
total_samples: 0,
md5_signature: "c41ae3b82c35d8f5c3dab1729f948fde",
},
FlacBlockOutput::VorbisComment {
vendor: "reference libFLAC 1.3.2 20170101",
comments: VorbisCommentTestValue::Raw { tags: &[] },
pictures: &[],
},
],
audio_hash: "3fb3482ebc1724559bdd57f34de472458563d78a676029614e76e32b5d2b8816",
stripped_hash: "31631ac227ebe2689bac7caa1fa964b47e71a9f1c9c583a04ea8ebd9371508d0",
},
FlacTestCase::Success {
test_name: "subset_46",
file_path: concat!(
env!("CARGO_MANIFEST_DIR"),
"/tests/files/flac_subset/46 - no min-max framesize set.flac"
),
in_hash: "9dc39732ce17815832790901b768bb50cd5ff0cd21b28a123c1cabc16ed776cc",
blocks: vec![
FlacBlockOutput::Streaminfo {
min_block_size: 4096,
max_block_size: 4096,
min_frame_size: 0,
max_frame_size: 0,
sample_rate: 48000,
channels: 2,
bits_per_sample: 16,
total_samples: 282866,
md5_signature: "fd131e6ebc75251ed83f8f4c07df36a4",
},
FlacBlockOutput::VorbisComment {
vendor: "reference libFLAC 1.3.2 20170101",
comments: VorbisCommentTestValue::Raw { tags: &[] },
pictures: &[],
},
],
audio_hash: "a1eed422462b386a932b9eb3dff3aea3687b41eca919624fb574aadb7eb50040",
stripped_hash: "9e57cd77f285fc31f87fa4e3a31ab8395d68d5482e174c8e0d0bba9a0c20ba27",
},
FlacTestCase::Success {
test_name: "subset_47",
file_path: concat!(
env!("CARGO_MANIFEST_DIR"),
"/tests/files/flac_subset/47 - only STREAMINFO.flac"
),
in_hash: "9a62c79f634849e74cb2183f9e3a9bd284f51e2591c553008d3e6449967eef85",
blocks: vec![FlacBlockOutput::Streaminfo {
min_block_size: 4096,
max_block_size: 4096,
min_frame_size: 4747,
max_frame_size: 7034,
sample_rate: 48000,
channels: 2,
bits_per_sample: 16,
total_samples: 232608,
md5_signature: "bba30c5f70789910e404b7ac727c3853",
}],
audio_hash: "5ee1450058254087f58c91baf0f70d14bde8782cf2dc23c741272177fe0fce6e",
stripped_hash: "9a62c79f634849e74cb2183f9e3a9bd284f51e2591c553008d3e6449967eef85",
},
FlacTestCase::Success {
test_name: "subset_48",
file_path: concat!(
env!("CARGO_MANIFEST_DIR"),
"/tests/files/flac_subset/48 - Extremely large SEEKTABLE.flac"
),
in_hash: "4417aca6b5f90971c50c28766d2f32b3acaa7f9f9667bd313336242dae8b2531",
blocks: vec![
FlacBlockOutput::Streaminfo {
min_block_size: 4096,
max_block_size: 4096,
min_frame_size: 2445,
max_frame_size: 7364,
sample_rate: 48000,
channels: 2,
bits_per_sample: 16,
total_samples: 259884,
md5_signature: "97a0574290237563fbaa788ad77d2cdf",
},
FlacBlockOutput::Seektable {
hash: "21ca2184ae22fe26b690fd7cbd8d25fcde1d830ff6e5796ced4107bab219d7c0",
},
FlacBlockOutput::VorbisComment {
vendor: "reference libFLAC 1.3.2 20170101",
comments: VorbisCommentTestValue::Raw { tags: &[] },
pictures: &[],
},
],
audio_hash: "c2d691f2c4c986fe3cd5fd7864d9ba9ce6dd68a4ffc670447f008434b13102c2",
stripped_hash: "abc9a0c40a29c896bc6e1cc0b374db1c8e157af716a5a3c43b7db1591a74c4e8",
},
FlacTestCase::Success {
test_name: "subset_49",
file_path: concat!(
env!("CARGO_MANIFEST_DIR"),
"/tests/files/flac_subset/49 - Extremely large PADDING.flac",
),
in_hash: "7bc44fa2754536279fde4f8fb31d824f43b8d0b3f93d27d055d209682914f20e",
blocks: vec![
FlacBlockOutput::Streaminfo {
min_block_size: 4096,
max_block_size: 4096,
min_frame_size: 1353,
max_frame_size: 7117,
sample_rate: 48000,
channels: 2,
bits_per_sample: 16,
total_samples: 258939,
md5_signature: "6e78f221caaaa5d570a53f1714d84ded",
},
FlacBlockOutput::VorbisComment {
vendor: "reference libFLAC 1.3.2 20170101",
comments: VorbisCommentTestValue::Raw { tags: &[] },
pictures: &[],
},
FlacBlockOutput::Padding { size: 16777215 },
],
audio_hash: "5007be7109b28b0149d1b929d2a0e93a087381bd3e68cf2a3ef78ea265ea20c3",
stripped_hash: "a2283bbacbc4905ad3df1bf9f43a0ea7aa65cf69523d84a7dd8eb54553cc437e",
},
FlacTestCase::Success {
test_name: "subset_50",
file_path: concat!(
env!("CARGO_MANIFEST_DIR"),
"/tests/files/flac_subset/50 - Extremely large PICTURE.flac"
),
in_hash: "1f04f237d74836104993a8072d4223e84a5d3bd76fbc44555c221c7e69a23594",
blocks: vec![
FlacBlockOutput::Streaminfo {
min_block_size: 4096,
max_block_size: 4096,
min_frame_size: 5099,
max_frame_size: 7126,
sample_rate: 48000,
channels: 2,
bits_per_sample: 16,
total_samples: 265617,
md5_signature: "82164e4da30ed43b47e6027cef050648",
},
FlacBlockOutput::VorbisComment {
vendor: "reference libFLAC 1.3.2 20170101",
comments: VorbisCommentTestValue::Raw { tags: &[] },
pictures: &[],
},
FlacBlockOutput::Picture {
picture_type: PictureType::FrontCover,
mime: mime::IMAGE_JPEG,
description: "",
width: 3200,
height: 2252,
bit_depth: 24,
color_count: 0,
img_data: "b78c3a48fde4ebbe8e4090e544caeb8f81ed10020d57cc50b3265f9b338d8563",
},
],
audio_hash: "9778b25c5d1f56cfcd418e550baed14f9d6a4baf29489a83ed450fbebb28de8c",
stripped_hash: "20df129287d94f9ae5951b296d7f65fcbed92db423ba7db4f0d765f1f0a7e18c",
},
FlacTestCase::Success {
test_name: "subset_51",
file_path: concat!(
env!("CARGO_MANIFEST_DIR"),
"/tests/files/flac_subset/51 - Extremely large VORBISCOMMENT.flac"
),
in_hash: "033160e8124ed287b0b5d615c94ac4139477e47d6e4059b1c19b7141566f5ef9",
blocks: vec![
FlacBlockOutput::Streaminfo {
min_block_size: 4096,
max_block_size: 4096,
min_frame_size: 4531,
max_frame_size: 7528,
sample_rate: 48000,
channels: 2,
bits_per_sample: 16,
total_samples: 289972,
md5_signature: "5ff622c88f8dd9bc201a6a541f3890d3",
},
FlacBlockOutput::VorbisComment {
vendor: "reference libFLAC 1.3.2 20170101",
comments: VorbisCommentTestValue::Hash {
n_comments: 39,
hash: "01984e9ec0cfad41f27b3b4e84184966f6725ead84b7815bd0b3313549ee4229",
},
pictures: &[],
},
],
audio_hash: "76419865d10eb22a74f020423a4e515e800f0177441676afd0418557c2d76c36",
stripped_hash: "c0ca6c6099b5d9ec53d6bb370f339b2b1570055813a6cd3616fac2db83a2185e",
},
FlacTestCase::Success {
test_name: "subset_52",
file_path: concat!(
env!("CARGO_MANIFEST_DIR"),
"/tests/files/flac_subset/52 - Extremely large APPLICATION.flac"
),
in_hash: "0e45a4f8dbef15cbebdd8dfe690d8ae60e0c6abb596db1270a9161b62a7a3f1c",
blocks: vec![
FlacBlockOutput::Streaminfo {
min_block_size: 4096,
max_block_size: 4096,
min_frame_size: 3711,
max_frame_size: 7056,
sample_rate: 48000,
channels: 2,
bits_per_sample: 16,
total_samples: 317876,
md5_signature: "eb7140266bc194527488c21ab49bc47b",
},
FlacBlockOutput::VorbisComment {
vendor: "reference libFLAC 1.3.2 20170101",
comments: VorbisCommentTestValue::Raw { tags: &[] },
pictures: &[],
},
FlacBlockOutput::Application {
application_id: 0x74657374,
hash: "cfc0b8969e4ba6bd507999ba89dea2d274df69d94749d6ae3cf117a7780bba09",
},
],
audio_hash: "89ad1a5c86a9ef35d33189c81c8a90285a23964a13f8325bf2c02043e8c83d63",
stripped_hash: "cc4a0afb95ec9bcde8ee33f13951e494dc4126a9a3a668d79c80ce3c14a3acd9",
},
FlacTestCase::Success {
test_name: "subset_53",
file_path: concat!(
env!("CARGO_MANIFEST_DIR"),
"/tests/files/flac_subset/53 - CUESHEET with very many indexes.flac"
),
in_hash: "513fad18578f3225fae5de1bda8f700415be6fd8aa1e7af533b5eb796ed2d461",
blocks: vec![
FlacBlockOutput::Streaminfo {
min_block_size: 4096,
max_block_size: 4096,
min_frame_size: 2798,
max_frame_size: 7408,
sample_rate: 48000,
channels: 2,
bits_per_sample: 16,
total_samples: 2910025,
md5_signature: "d11f3717d628cfe6a90a10facc478340",
},
FlacBlockOutput::Seektable {
hash: "18629e1b874cb27e4364da72fb3fec2141eb0618baae4a1cee6ed09562aa00a8",
},
FlacBlockOutput::VorbisComment {
vendor: "reference libFLAC 1.3.2 20170101",
comments: VorbisCommentTestValue::Raw { tags: &[] },
pictures: &[],
},
FlacBlockOutput::CueSheet {
hash: "70638a241ca06881a52c0a18258ea2d8946a830137a70479c49746d2a1344bdd",
},
],
audio_hash: "e993070f2080f2c598be1d61d208e9187a55ddea4be1d2ed1f8043e7c03e97a5",
stripped_hash: "57c5b945e14c6fcd06916d6a57e5b036d67ff35757893c24ed872007aabbcf4b",
},
FlacTestCase::Success {
test_name: "subset_54",
file_path: concat!(
env!("CARGO_MANIFEST_DIR"),
"/tests/files/flac_subset/54 - 1000x repeating VORBISCOMMENT.flac"
),
in_hash: "b68dc6644784fac35aa07581be8603a360d1697e07a2265d7eb24001936fd247",
blocks: vec![
FlacBlockOutput::Streaminfo {
min_block_size: 4096,
max_block_size: 4096,
min_frame_size: 1694,
max_frame_size: 7145,
sample_rate: 48000,
channels: 2,
bits_per_sample: 16,
total_samples: 433151,
md5_signature: "1d950e92b357dedbc5290a7f2210a2ef",
},
FlacBlockOutput::VorbisComment {
vendor: "reference libFLAC 1.3.2 20170101",
comments: VorbisCommentTestValue::Hash {
n_comments: 20000,
hash: "433f34ae532d265835153139b1db79352a26ad0d3b03e2f1a1b88ada34abfc77",
},
pictures: &[],
},
],
audio_hash: "4721b784058410c6263f73680079e9a71aee914c499afcf5580c121fce00e874",
stripped_hash: "5c8b92b83c0fa17821add38263fa323d1c66cfd2ee57aca054b50bd05b9df5c2",
},
FlacTestCase::Success {
test_name: "subset_55",
file_path: concat!(
env!("CARGO_MANIFEST_DIR"),
"/tests/files/flac_subset/55 - file 48-53 combined.flac"
),
in_hash: "a756b460df79b7cc492223f80cda570e4511f2024e5fa0c4d505ba51b86191f6",
blocks: vec![
FlacBlockOutput::Streaminfo {
min_block_size: 4096,
max_block_size: 4096,
min_frame_size: 3103,
max_frame_size: 11306,
sample_rate: 44100,
channels: 2,
bits_per_sample: 16,
total_samples: 2646000,
md5_signature: "2c78978cbbff11daac296fee97c3e061",
},
FlacBlockOutput::Seektable {
hash: "58dfa7bac4974edf1956b068f5aa72d1fbd9301c36a3085a8a57b9db11a2dbf0",
},
FlacBlockOutput::VorbisComment {
vendor: "reference libFLAC 1.3.3 20190804",
comments: VorbisCommentTestValue::Hash {
n_comments: 40036,
hash: "66cac9f9c42f48128e9fc24e1e96b46a06e885d233155556da16d9b05a23486e",
},
pictures: &[],
},
FlacBlockOutput::CueSheet {
hash: "db11916c8f5f39648256f93f202e00ff8d73d7d96b62f749b4c77cf3ea744f90",
},
FlacBlockOutput::Application {
application_id: 0x74657374,
hash: "6088a557a1bad7bfa5ebf79a324669fbf4fa2f8e708f5487305dfc5b2ff2249a",
},
FlacBlockOutput::Picture {
picture_type: PictureType::FrontCover,
mime: mime::IMAGE_JPEG,
description: "",
width: 3200,
height: 2252,
bit_depth: 24,
color_count: 0,
img_data: "b78c3a48fde4ebbe8e4090e544caeb8f81ed10020d57cc50b3265f9b338d8563",
},
FlacBlockOutput::Padding { size: 16777215 },
],
audio_hash: "f1285b77cec7fa9a0979033244489a9d06b8515b2158e9270087a65a4007084d",
stripped_hash: "401038fce06aff5ebdc7a5f2fc01fa491cbf32d5da9ec99086e414b2da3f8449",
},
FlacTestCase::Success {
test_name: "subset_56",
file_path: concat!(
env!("CARGO_MANIFEST_DIR"),
"/tests/files/flac_subset/56 - JPG PICTURE.flac"
),
in_hash: "5cebe7a3710cf8924bd2913854e9ca60b4cd53cfee5a3af0c3c73fddc1888963",
blocks: vec![
FlacBlockOutput::Streaminfo {
min_block_size: 4096,
max_block_size: 4096,
min_frame_size: 3014,
max_frame_size: 7219,
sample_rate: 44100,
channels: 2,
bits_per_sample: 16,
total_samples: 220026,
md5_signature: "5b0e898d9c2626d0c28684f5a586813f",
},
FlacBlockOutput::VorbisComment {
vendor: "reference libFLAC 1.3.2 20170101",
comments: VorbisCommentTestValue::Raw { tags: &[] },
pictures: &[],
},
FlacBlockOutput::Picture {
picture_type: PictureType::FrontCover,
mime: mime::IMAGE_JPEG,
description: "",
width: 1920,
height: 1080,
bit_depth: 24,
color_count: 0,
img_data: "7a3ed658f80f433eee3914fff451ea0312807de0af709e37cc6a4f3f6e8a47c6",
},
],
audio_hash: "ccfe90b0f15cd9662f7a18f40cd4c347538cf8897a08228e75351206f7804573",
stripped_hash: "31a38d59db2010790b7abf65ec0cc03f2bbe1fed5952bc72bee4ca4d0c92e79f",
},
FlacTestCase::Success {
test_name: "subset_57",
file_path: concat!(
env!("CARGO_MANIFEST_DIR"),
"/tests/files/flac_subset/57 - PNG PICTURE.flac"
),
in_hash: "c6abff7f8bb63c2821bd21dd9052c543f10ba0be878e83cb419c248f14f72697",
blocks: vec![
FlacBlockOutput::Streaminfo {
min_block_size: 4096,
max_block_size: 4096,
min_frame_size: 463,
max_frame_size: 6770,
sample_rate: 44100,
channels: 2,
bits_per_sample: 16,
total_samples: 221623,
md5_signature: "ad16957bcf8d5a3ec8caf261e43d5ff7",
},
FlacBlockOutput::VorbisComment {
vendor: "reference libFLAC 1.3.2 20170101",
comments: VorbisCommentTestValue::Raw { tags: &[] },
pictures: &[],
},
FlacBlockOutput::Picture {
picture_type: PictureType::FrontCover,
mime: mime::IMAGE_PNG,
description: "",
width: 960,
height: 540,
bit_depth: 24,
color_count: 0,
img_data: "d804e5c7b9ee5af694b5e301c6cdf64508ff85997deda49d2250a06a964f10b2",
},
],
audio_hash: "39bf9981613ac2f35d253c0c21b76a48abba7792c27da5dbf23e6021e2e6673f",
stripped_hash: "3328201dd56289b6c81fa90ff26cb57fa9385cb0db197e89eaaa83efd79a58b1",
},
FlacTestCase::Success {
test_name: "subset_58",
file_path: concat!(
env!("CARGO_MANIFEST_DIR"),
"/tests/files/flac_subset/58 - GIF PICTURE.flac"
),
in_hash: "7c2b1a963a665847167a7275f9924f65baeb85c21726c218f61bf3f803f301c8",
blocks: vec![
FlacBlockOutput::Streaminfo {
min_block_size: 4096,
max_block_size: 4096,
min_frame_size: 2853,
max_frame_size: 6683,
sample_rate: 44100,
channels: 2,
bits_per_sample: 16,
total_samples: 219826,
md5_signature: "7c1810602a7db96d7a48022ac4aa495c",
},
FlacBlockOutput::VorbisComment {
vendor: "reference libFLAC 1.3.2 20170101",
comments: VorbisCommentTestValue::Raw { tags: &[] },
pictures: &[],
},
FlacBlockOutput::Picture {
picture_type: PictureType::FrontCover,
mime: mime::IMAGE_GIF,
description: "",
width: 1920,
height: 1080,
bit_depth: 24,
color_count: 32,
img_data: "e33cccc1d799eb2bb618f47be7099cf02796df5519f3f0e1cc258606cf6e8bb1",
},
],
audio_hash: "30e3292e9f56cf88658eeadfdec8ad3a440690ce6d813e1b3374f60518c8e0ae",
stripped_hash: "4cd771e27870e2a586000f5b369e0426183a521b61212302a2f5802b046910b2",
},
FlacTestCase::Success {
test_name: "subset_59",
file_path: concat!(
env!("CARGO_MANIFEST_DIR"),
"/tests/files/flac_subset/59 - AVIF PICTURE.flac"
),
in_hash: "7395d02bf8d9533dc554cce02dee9de98c77f8731a45f62d0a243bd0d6f9a45c",
blocks: vec![
FlacBlockOutput::Streaminfo {
min_block_size: 4096,
max_block_size: 4096,
min_frame_size: 153,
max_frame_size: 7041,
sample_rate: 44100,
channels: 2,
bits_per_sample: 16,
total_samples: 221423,
md5_signature: "d354246011ca204159c06f52cad5f634",
},
FlacBlockOutput::VorbisComment {
vendor: "reference libFLAC 1.3.2 20170101",
comments: VorbisCommentTestValue::Raw { tags: &[] },
pictures: &[],
},
FlacBlockOutput::Picture {
picture_type: PictureType::FrontCover,
mime: Mime::from_str("image/avif").unwrap(),
description: "",
width: 1920,
height: 1080,
bit_depth: 24,
color_count: 0,
img_data: "a431123040c74f75096237f20544a7fb56b4eb71ddea62efa700b0a016f5b2fc",
},
],
audio_hash: "b208c73d274e65b27232bfffbfcbcf4805ee3cbc9cfbf7d2104db8f53370273b",
stripped_hash: "d5215e16c6b978fc2c3e6809e1e78981497cb8514df297c5169f3b4a28fd875c",
},
FlacTestCase::Success {
test_name: "custom_01",
file_path: concat!(
env!("CARGO_MANIFEST_DIR"),
"/tests/files/flac_custom/01 - many images.flac"
),
in_hash: "8a5df37488866cd91ac16773e549ef4e3a85d9f88a0d9d345f174807bb536b96",
blocks: vec![
FlacBlockOutput::Streaminfo {
min_block_size: 4096,
max_block_size: 4096,
min_frame_size: 5099,
max_frame_size: 7126,
sample_rate: 48000,
channels: 2,
bits_per_sample: 16,
total_samples: 265617,
md5_signature: "82164e4da30ed43b47e6027cef050648",
},
FlacBlockOutput::VorbisComment {
vendor: "reference libFLAC 1.3.2 20170101",
comments: VorbisCommentTestValue::Raw { tags: &[] },
pictures: &[FlacBlockOutput::Picture {
picture_type: PictureType::FrontCover,
mime: mime::IMAGE_PNG,
description: "",
width: 960,
height: 540,
bit_depth: 24,
color_count: 0,
img_data: "d804e5c7b9ee5af694b5e301c6cdf64508ff85997deda49d2250a06a964f10b2",
}],
},
FlacBlockOutput::Picture {
picture_type: PictureType::FrontCover,
mime: mime::IMAGE_JPEG,
description: "",
width: 3200,
height: 2252,
bit_depth: 24,
color_count: 0,
img_data: "b78c3a48fde4ebbe8e4090e544caeb8f81ed10020d57cc50b3265f9b338d8563",
},
FlacBlockOutput::Picture {
picture_type: PictureType::ABrightColoredFish,
mime: mime::IMAGE_JPEG,
description: "lorem",
width: 1920,
height: 1080,
bit_depth: 24,
color_count: 0,
img_data: "7a3ed658f80f433eee3914fff451ea0312807de0af709e37cc6a4f3f6e8a47c6",
},
FlacBlockOutput::Picture {
picture_type: PictureType::OtherFileIcon,
mime: mime::IMAGE_PNG,
description: "ipsum",
width: 960,
height: 540,
bit_depth: 24,
color_count: 0,
img_data: "d804e5c7b9ee5af694b5e301c6cdf64508ff85997deda49d2250a06a964f10b2",
},
FlacBlockOutput::Picture {
picture_type: PictureType::Lyricist,
mime: mime::IMAGE_GIF,
description: "dolor",
width: 1920,
height: 1080,
bit_depth: 24,
color_count: 32,
img_data: "e33cccc1d799eb2bb618f47be7099cf02796df5519f3f0e1cc258606cf6e8bb1",
},
FlacBlockOutput::Picture {
picture_type: PictureType::BackCover,
mime: Mime::from_str("image/avif").unwrap(),
description: "est",
width: 1920,
height: 1080,
bit_depth: 24,
color_count: 0,
img_data: "a431123040c74f75096237f20544a7fb56b4eb71ddea62efa700b0a016f5b2fc",
},
],
audio_hash: "9778b25c5d1f56cfcd418e550baed14f9d6a4baf29489a83ed450fbebb28de8c",
stripped_hash: "20df129287d94f9ae5951b296d7f65fcbed92db423ba7db4f0d765f1f0a7e18c",
},
FlacTestCase::Success {
test_name: "custom_02",
file_path: concat!(
env!("CARGO_MANIFEST_DIR"),
"/tests/files/flac_custom/02 - picture in vorbis comment.flac"
),
in_hash: "f6bb1a726fe6a3e25a4337d36e29fdced8ff01a46d627b7c2e1988c88f461f8c",
blocks: vec![
FlacBlockOutput::Streaminfo {
min_block_size: 4096,
max_block_size: 4096,
min_frame_size: 463,
max_frame_size: 6770,
sample_rate: 44100,
channels: 2,
bits_per_sample: 16,
total_samples: 221623,
md5_signature: "ad16957bcf8d5a3ec8caf261e43d5ff7",
},
FlacBlockOutput::VorbisComment {
vendor: "reference libFLAC 1.3.2 20170101",
comments: VorbisCommentTestValue::Raw { tags: &[] },
pictures: &[FlacBlockOutput::Picture {
picture_type: PictureType::FrontCover,
mime: mime::IMAGE_PNG,
description: "",
width: 960,
height: 540,
bit_depth: 24,
color_count: 0,
img_data: "d804e5c7b9ee5af694b5e301c6cdf64508ff85997deda49d2250a06a964f10b2",
}],
},
],
audio_hash: "39bf9981613ac2f35d253c0c21b76a48abba7792c27da5dbf23e6021e2e6673f",
stripped_hash: "3328201dd56289b6c81fa90ff26cb57fa9385cb0db197e89eaaa83efd79a58b1",
},
FlacTestCase::Error {
test_name: "custom_03",
file_path: concat!(
env!("CARGO_MANIFEST_DIR"),
"/tests/files/flac_custom/03 - faulty picture in vorbis comment.flac"
),
in_hash: "7177f0ae4f04a563292be286ec05967f81ab16eb0a28b70fc07a1e47da9cafd0",
check_error: &|x| {
matches!(
x,
FlacDecodeError::VorbisComment(VorbisCommentDecodeError::MalformedPicture)
)
},
stripped_hash: Some(
"3328201dd56289b6c81fa90ff26cb57fa9385cb0db197e89eaaa83efd79a58b1",
),
pictures: None,
},
]
}
#[test]
fn manifest_sanity_check() {
assert!(manifest().iter().map(|x| x.get_name()).all_unique());
assert!(manifest().iter().map(|x| x.get_path()).all_unique());
}
}