mirror of
https://git.asonix.dog/asonix/pict-rs
synced 2024-12-22 19:31:35 +00:00
Fix tests, add animated_webp test
This commit is contained in:
parent
3d0857ff65
commit
27451971a6
31 changed files with 3991 additions and 265 deletions
|
@ -9,6 +9,7 @@ use crate::{
|
||||||
store::Store,
|
store::Store,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub(crate) struct Discovery {
|
pub(crate) struct Discovery {
|
||||||
pub(crate) input: InputFile,
|
pub(crate) input: InputFile,
|
||||||
pub(crate) width: u16,
|
pub(crate) width: u16,
|
||||||
|
@ -16,6 +17,7 @@ pub(crate) struct Discovery {
|
||||||
pub(crate) frames: Option<u32>,
|
pub(crate) frames: Option<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub(crate) struct DiscoveryLite {
|
pub(crate) struct DiscoveryLite {
|
||||||
pub(crate) format: InternalFormat,
|
pub(crate) format: InternalFormat,
|
||||||
pub(crate) width: u16,
|
pub(crate) width: u16,
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests;
|
||||||
|
|
||||||
use std::{collections::HashSet, sync::OnceLock};
|
use std::{collections::HashSet, sync::OnceLock};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -14,13 +17,16 @@ use tokio::io::AsyncReadExt;
|
||||||
|
|
||||||
use super::{Discovery, DiscoveryLite};
|
use super::{Discovery, DiscoveryLite};
|
||||||
|
|
||||||
|
const MP4: &str = "mp4";
|
||||||
|
const WEBP: &str = "webp_pipe";
|
||||||
|
|
||||||
const FFMPEG_FORMAT_MAPPINGS: &[(&str, InternalFormat)] = &[
|
const FFMPEG_FORMAT_MAPPINGS: &[(&str, InternalFormat)] = &[
|
||||||
("apng", InternalFormat::Animation(AnimationFormat::Apng)),
|
("apng", InternalFormat::Animation(AnimationFormat::Apng)),
|
||||||
("gif", InternalFormat::Animation(AnimationFormat::Gif)),
|
("gif", InternalFormat::Animation(AnimationFormat::Gif)),
|
||||||
("mp4", InternalFormat::Video(InternalVideoFormat::Mp4)),
|
(MP4, InternalFormat::Video(InternalVideoFormat::Mp4)),
|
||||||
("png_pipe", InternalFormat::Image(ImageFormat::Png)),
|
("png_pipe", InternalFormat::Image(ImageFormat::Png)),
|
||||||
("webm", InternalFormat::Video(InternalVideoFormat::Webm)),
|
("webm", InternalFormat::Video(InternalVideoFormat::Webm)),
|
||||||
("webp_pipe", InternalFormat::Image(ImageFormat::Webp)),
|
(WEBP, InternalFormat::Image(ImageFormat::Webp)),
|
||||||
];
|
];
|
||||||
|
|
||||||
#[derive(Debug, serde::Deserialize)]
|
#[derive(Debug, serde::Deserialize)]
|
||||||
|
@ -229,7 +235,7 @@ where
|
||||||
|
|
||||||
let output: FfMpegDiscovery = serde_json::from_slice(&output).map_err(FfMpegError::Json)?;
|
let output: FfMpegDiscovery = serde_json::from_slice(&output).map_err(FfMpegError::Json)?;
|
||||||
|
|
||||||
parse_discovery_ffmpeg(output)
|
parse_discovery(output)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn pixel_format<F, Fut>(f: F) -> Result<String, FfMpegError>
|
async fn pixel_format<F, Fut>(f: F) -> Result<String, FfMpegError>
|
||||||
|
@ -321,9 +327,7 @@ fn parse_pixel_formats(formats: PixelFormatOutput) -> HashSet<String> {
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_discovery_ffmpeg(
|
fn parse_discovery(discovery: FfMpegDiscovery) -> Result<Option<DiscoveryLite>, FfMpegError> {
|
||||||
discovery: FfMpegDiscovery,
|
|
||||||
) -> Result<Option<DiscoveryLite>, FfMpegError> {
|
|
||||||
let FfMpegDiscovery {
|
let FfMpegDiscovery {
|
||||||
streams:
|
streams:
|
||||||
[FfMpegStream {
|
[FfMpegStream {
|
||||||
|
@ -340,7 +344,7 @@ fn parse_discovery_ffmpeg(
|
||||||
{
|
{
|
||||||
let frames = nb_read_frames.and_then(|frames| frames.parse().ok());
|
let frames = nb_read_frames.and_then(|frames| frames.parse().ok());
|
||||||
|
|
||||||
if *name == "mp4" && frames.map(|nb| nb == 1).unwrap_or(false) {
|
if *name == MP4 && frames.map(|nb| nb == 1).unwrap_or(false) {
|
||||||
// Might be AVIF, ffmpeg incorrectly detects AVIF as single-framed mp4 even when
|
// Might be AVIF, ffmpeg incorrectly detects AVIF as single-framed mp4 even when
|
||||||
// animated
|
// animated
|
||||||
|
|
||||||
|
@ -348,11 +352,11 @@ fn parse_discovery_ffmpeg(
|
||||||
format: InternalFormat::Animation(AnimationFormat::Avif),
|
format: InternalFormat::Animation(AnimationFormat::Avif),
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
frames,
|
frames: None,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
if *name == "webp" && (frames.is_none() || width == 0 || height == 0) {
|
if *name == WEBP && (frames.is_none() || width == 0 || height == 0) {
|
||||||
// Might be Animated Webp, ffmpeg incorrectly detects animated webp as having no frames
|
// Might be Animated Webp, ffmpeg incorrectly detects animated webp as having no frames
|
||||||
// and 0 dimensions
|
// and 0 dimensions
|
||||||
|
|
||||||
|
@ -368,7 +372,7 @@ fn parse_discovery_ffmpeg(
|
||||||
format: *value,
|
format: *value,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
frames,
|
frames: frames.and_then(|frames| if frames > 1 { Some(frames) } else { None }),
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
14
src/discover/ffmpeg/ffprobe_6_0_animated_webp_details.json
Normal file
14
src/discover/ffmpeg/ffprobe_6_0_animated_webp_details.json
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"programs": [
|
||||||
|
|
||||||
|
],
|
||||||
|
"streams": [
|
||||||
|
{
|
||||||
|
"width": 0,
|
||||||
|
"height": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"format": {
|
||||||
|
"format_name": "webp_pipe"
|
||||||
|
}
|
||||||
|
}
|
177
src/discover/ffmpeg/tests.rs
Normal file
177
src/discover/ffmpeg/tests.rs
Normal file
|
@ -0,0 +1,177 @@
|
||||||
|
use crate::formats::{AnimationFormat, ImageFormat, InternalFormat, InternalVideoFormat};
|
||||||
|
|
||||||
|
use super::{DiscoveryLite, FfMpegDiscovery, PixelFormatOutput};
|
||||||
|
|
||||||
|
fn details_tests() -> [(&'static str, Option<DiscoveryLite>); 11] {
|
||||||
|
[
|
||||||
|
(
|
||||||
|
"animated_webp",
|
||||||
|
Some(DiscoveryLite {
|
||||||
|
format: InternalFormat::Animation(AnimationFormat::Webp),
|
||||||
|
width: 0,
|
||||||
|
height: 0,
|
||||||
|
frames: None,
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"apng",
|
||||||
|
Some(DiscoveryLite {
|
||||||
|
format: InternalFormat::Animation(AnimationFormat::Apng),
|
||||||
|
width: 112,
|
||||||
|
height: 112,
|
||||||
|
frames: Some(27),
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"avif",
|
||||||
|
Some(DiscoveryLite {
|
||||||
|
format: InternalFormat::Animation(AnimationFormat::Avif),
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
frames: None,
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"gif",
|
||||||
|
Some(DiscoveryLite {
|
||||||
|
format: InternalFormat::Animation(AnimationFormat::Gif),
|
||||||
|
width: 160,
|
||||||
|
height: 227,
|
||||||
|
frames: Some(28),
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
("jpeg", None),
|
||||||
|
("jxl", None),
|
||||||
|
(
|
||||||
|
"mp4",
|
||||||
|
Some(DiscoveryLite {
|
||||||
|
format: InternalFormat::Video(InternalVideoFormat::Mp4),
|
||||||
|
width: 852,
|
||||||
|
height: 480,
|
||||||
|
frames: Some(35364),
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"png",
|
||||||
|
Some(DiscoveryLite {
|
||||||
|
format: InternalFormat::Image(ImageFormat::Png),
|
||||||
|
width: 450,
|
||||||
|
height: 401,
|
||||||
|
frames: None,
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"webm",
|
||||||
|
Some(DiscoveryLite {
|
||||||
|
format: InternalFormat::Video(InternalVideoFormat::Webm),
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
frames: Some(34650),
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"webm_av1",
|
||||||
|
Some(DiscoveryLite {
|
||||||
|
format: InternalFormat::Video(InternalVideoFormat::Webm),
|
||||||
|
width: 112,
|
||||||
|
height: 112,
|
||||||
|
frames: Some(27),
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"webp",
|
||||||
|
Some(DiscoveryLite {
|
||||||
|
format: InternalFormat::Image(ImageFormat::Webp),
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
frames: None,
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_discovery() {
|
||||||
|
for (case, expected) in details_tests() {
|
||||||
|
let string = std::fs::read_to_string(format!(
|
||||||
|
"./src/discover/ffmpeg/ffprobe_6_0_{case}_details.json"
|
||||||
|
))
|
||||||
|
.expect("Read file");
|
||||||
|
|
||||||
|
let json: FfMpegDiscovery = serde_json::from_str(&string).expect("Valid json");
|
||||||
|
|
||||||
|
let output = super::parse_discovery(json).expect("Parsed details");
|
||||||
|
|
||||||
|
assert_eq!(output, expected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const ALPHA_PIXEL_FORMATS: &[&str] = &[
|
||||||
|
"pal8",
|
||||||
|
"argb",
|
||||||
|
"rgba",
|
||||||
|
"abgr",
|
||||||
|
"bgra",
|
||||||
|
"yuva420p",
|
||||||
|
"ya8",
|
||||||
|
"yuva422p",
|
||||||
|
"yuva444p",
|
||||||
|
"yuva420p9be",
|
||||||
|
"yuva420p9le",
|
||||||
|
"yuva422p9be",
|
||||||
|
"yuva422p9le",
|
||||||
|
"yuva444p9be",
|
||||||
|
"yuva444p9le",
|
||||||
|
"yuva420p10be",
|
||||||
|
"yuva420p10le",
|
||||||
|
"yuva422p10be",
|
||||||
|
"yuva422p10le",
|
||||||
|
"yuva444p10be",
|
||||||
|
"yuva444p10le",
|
||||||
|
"yuva420p16be",
|
||||||
|
"yuva420p16le",
|
||||||
|
"yuva422p16be",
|
||||||
|
"yuva422p16le",
|
||||||
|
"yuva444p16be",
|
||||||
|
"yuva444p16le",
|
||||||
|
"rgba64be",
|
||||||
|
"rgba64le",
|
||||||
|
"bgra64be",
|
||||||
|
"bgra64le",
|
||||||
|
"ya16be",
|
||||||
|
"ya16le",
|
||||||
|
"gbrap",
|
||||||
|
"gbrap16be",
|
||||||
|
"gbrap16le",
|
||||||
|
"ayuv64le",
|
||||||
|
"ayuv64be",
|
||||||
|
"gbrap12be",
|
||||||
|
"gbrap12le",
|
||||||
|
"gbrap10be",
|
||||||
|
"gbrap10le",
|
||||||
|
"gbrapf32be",
|
||||||
|
"gbrapf32le",
|
||||||
|
"yuva422p12be",
|
||||||
|
"yuva422p12le",
|
||||||
|
"yuva444p12be",
|
||||||
|
"yuva444p12le",
|
||||||
|
"vuya",
|
||||||
|
"rgbaf16be",
|
||||||
|
"rgbaf16le",
|
||||||
|
"rgbaf32be",
|
||||||
|
"rgbaf32le",
|
||||||
|
];
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_pixel_formats() {
|
||||||
|
let formats = std::fs::read_to_string("./src/discover/ffmpeg/ffprobe_6_0_pixel_formats.json")
|
||||||
|
.expect("Read file");
|
||||||
|
|
||||||
|
let json: PixelFormatOutput = serde_json::from_str(&formats).expect("Valid json");
|
||||||
|
|
||||||
|
let output = super::parse_pixel_formats(json);
|
||||||
|
|
||||||
|
for format in ALPHA_PIXEL_FORMATS {
|
||||||
|
assert!(output.contains(*format), "Doesn't contain {format}");
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,3 +1,6 @@
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests;
|
||||||
|
|
||||||
use actix_web::web::Bytes;
|
use actix_web::web::Bytes;
|
||||||
use futures_util::Stream;
|
use futures_util::Stream;
|
||||||
use tokio::io::AsyncReadExt;
|
use tokio::io::AsyncReadExt;
|
||||||
|
@ -27,6 +30,24 @@ struct Geometry {
|
||||||
height: u16,
|
height: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Discovery {
|
||||||
|
fn lite(self) -> DiscoveryLite {
|
||||||
|
let Discovery {
|
||||||
|
input,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
frames,
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
DiscoveryLite {
|
||||||
|
format: input.internal_format(),
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
frames,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(super) async fn discover_bytes_lite(bytes: Bytes) -> Result<DiscoveryLite, MagickError> {
|
pub(super) async fn discover_bytes_lite(bytes: Bytes) -> Result<DiscoveryLite, MagickError> {
|
||||||
discover_file_lite(move |mut file| async move {
|
discover_file_lite(move |mut file| async move {
|
||||||
file.write_from_bytes(bytes)
|
file.write_from_bytes(bytes)
|
||||||
|
@ -154,19 +175,7 @@ where
|
||||||
F: FnOnce(crate::file::File) -> Fut,
|
F: FnOnce(crate::file::File) -> Fut,
|
||||||
Fut: std::future::Future<Output = Result<crate::file::File, MagickError>>,
|
Fut: std::future::Future<Output = Result<crate::file::File, MagickError>>,
|
||||||
{
|
{
|
||||||
let Discovery {
|
discover_file(f).await.map(Discovery::lite)
|
||||||
input,
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
frames,
|
|
||||||
} = discover_file(f).await?;
|
|
||||||
|
|
||||||
Ok(DiscoveryLite {
|
|
||||||
format: input.internal_format(),
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
frames,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn discover_file<F, Fut>(f: F) -> Result<Discovery, MagickError>
|
async fn discover_file<F, Fut>(f: F) -> Result<Discovery, MagickError>
|
||||||
|
@ -346,6 +355,12 @@ fn parse_discovery(output: Vec<MagickDiscovery>) -> Result<Discovery, MagickErro
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
"WEBM" => Ok(Discovery {
|
||||||
|
input: InputFile::Video(VideoFormat::Webm { alpha: true }),
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
frames: Some(frames),
|
||||||
|
}),
|
||||||
otherwise => todo!("Error {otherwise}"),
|
otherwise => todo!("Error {otherwise}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
3649
src/discover/magick/magick_7_1_1_animated_webp_details.json
Normal file
3649
src/discover/magick/magick_7_1_1_animated_webp_details.json
Normal file
File diff suppressed because it is too large
Load diff
105
src/discover/magick/tests.rs
Normal file
105
src/discover/magick/tests.rs
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
use crate::formats::{AnimationFormat, ImageFormat, InternalFormat, InternalVideoFormat};
|
||||||
|
|
||||||
|
use super::{DiscoveryLite, MagickDiscovery};
|
||||||
|
|
||||||
|
fn details_tests() -> [(&'static str, DiscoveryLite); 9] {
|
||||||
|
[
|
||||||
|
(
|
||||||
|
"animated_webp",
|
||||||
|
DiscoveryLite {
|
||||||
|
format: InternalFormat::Animation(AnimationFormat::Webp),
|
||||||
|
width: 112,
|
||||||
|
height: 112,
|
||||||
|
frames: Some(27),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"avif",
|
||||||
|
DiscoveryLite {
|
||||||
|
format: InternalFormat::Image(ImageFormat::Avif),
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
frames: None,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"gif",
|
||||||
|
DiscoveryLite {
|
||||||
|
format: InternalFormat::Animation(AnimationFormat::Gif),
|
||||||
|
width: 414,
|
||||||
|
height: 261,
|
||||||
|
frames: Some(17),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"jpeg",
|
||||||
|
DiscoveryLite {
|
||||||
|
format: InternalFormat::Image(ImageFormat::Jpeg),
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
frames: None,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"jxl",
|
||||||
|
DiscoveryLite {
|
||||||
|
format: InternalFormat::Image(ImageFormat::Jxl),
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
frames: None,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"mp4",
|
||||||
|
DiscoveryLite {
|
||||||
|
format: InternalFormat::Video(InternalVideoFormat::Mp4),
|
||||||
|
width: 414,
|
||||||
|
height: 261,
|
||||||
|
frames: Some(17),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"png",
|
||||||
|
DiscoveryLite {
|
||||||
|
format: InternalFormat::Image(ImageFormat::Png),
|
||||||
|
width: 497,
|
||||||
|
height: 694,
|
||||||
|
frames: None,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"webm",
|
||||||
|
DiscoveryLite {
|
||||||
|
format: InternalFormat::Video(InternalVideoFormat::Webm),
|
||||||
|
width: 112,
|
||||||
|
height: 112,
|
||||||
|
frames: Some(27),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"webp",
|
||||||
|
DiscoveryLite {
|
||||||
|
format: InternalFormat::Image(ImageFormat::Webp),
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
frames: None,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_discovery() {
|
||||||
|
for (case, expected) in details_tests() {
|
||||||
|
let string = std::fs::read_to_string(format!(
|
||||||
|
"./src/discover/magick/magick_7_1_1_{case}_details.json"
|
||||||
|
))
|
||||||
|
.expect("Read file");
|
||||||
|
|
||||||
|
let json: Vec<MagickDiscovery> = serde_json::from_str(&string).expect("Valid json");
|
||||||
|
|
||||||
|
let output = super::parse_discovery(json).expect("Parsed details").lite();
|
||||||
|
|
||||||
|
assert_eq!(output, expected);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,3 @@
|
||||||
#[cfg(test)]
|
|
||||||
mod tests;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
formats::InternalVideoFormat,
|
formats::InternalVideoFormat,
|
||||||
process::{Process, ProcessError},
|
process::{Process, ProcessError},
|
||||||
|
|
|
@ -1,141 +0,0 @@
|
||||||
use super::{Details, DetailsOutput, PixelFormatOutput};
|
|
||||||
|
|
||||||
fn details_tests() -> [(&'static str, Option<Details>); 10] {
|
|
||||||
[
|
|
||||||
(
|
|
||||||
"apng",
|
|
||||||
Some(Details {
|
|
||||||
mime_type: crate::formats::mimes::image_apng(),
|
|
||||||
width: 112,
|
|
||||||
height: 112,
|
|
||||||
frames: Some(27),
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
("avif", None),
|
|
||||||
(
|
|
||||||
"gif",
|
|
||||||
Some(Details {
|
|
||||||
mime_type: mime::IMAGE_GIF,
|
|
||||||
width: 160,
|
|
||||||
height: 227,
|
|
||||||
frames: Some(28),
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
("jpeg", None),
|
|
||||||
("jxl", None),
|
|
||||||
(
|
|
||||||
"mp4",
|
|
||||||
Some(Details {
|
|
||||||
mime_type: crate::formats::mimes::video_mp4(),
|
|
||||||
width: 852,
|
|
||||||
height: 480,
|
|
||||||
frames: Some(35364),
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
("png", None),
|
|
||||||
(
|
|
||||||
"webm",
|
|
||||||
Some(Details {
|
|
||||||
mime_type: crate::formats::mimes::video_webm(),
|
|
||||||
width: 640,
|
|
||||||
height: 480,
|
|
||||||
frames: Some(34650),
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"webm_av1",
|
|
||||||
Some(Details {
|
|
||||||
mime_type: crate::formats::mimes::video_webm(),
|
|
||||||
width: 112,
|
|
||||||
height: 112,
|
|
||||||
frames: Some(27),
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
("webp", None),
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn parse_details() {
|
|
||||||
for (case, expected) in details_tests() {
|
|
||||||
let string =
|
|
||||||
std::fs::read_to_string(format!("./src/ffmpeg/ffprobe_6_0_{case}_details.json"))
|
|
||||||
.expect("Read file");
|
|
||||||
|
|
||||||
let json: DetailsOutput = serde_json::from_str(&string).expect("Valid json");
|
|
||||||
|
|
||||||
let output = super::parse_details(json).expect("Parsed details");
|
|
||||||
|
|
||||||
assert_eq!(output, expected);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const ALPHA_PIXEL_FORMATS: &[&str] = &[
|
|
||||||
"pal8",
|
|
||||||
"argb",
|
|
||||||
"rgba",
|
|
||||||
"abgr",
|
|
||||||
"bgra",
|
|
||||||
"yuva420p",
|
|
||||||
"ya8",
|
|
||||||
"yuva422p",
|
|
||||||
"yuva444p",
|
|
||||||
"yuva420p9be",
|
|
||||||
"yuva420p9le",
|
|
||||||
"yuva422p9be",
|
|
||||||
"yuva422p9le",
|
|
||||||
"yuva444p9be",
|
|
||||||
"yuva444p9le",
|
|
||||||
"yuva420p10be",
|
|
||||||
"yuva420p10le",
|
|
||||||
"yuva422p10be",
|
|
||||||
"yuva422p10le",
|
|
||||||
"yuva444p10be",
|
|
||||||
"yuva444p10le",
|
|
||||||
"yuva420p16be",
|
|
||||||
"yuva420p16le",
|
|
||||||
"yuva422p16be",
|
|
||||||
"yuva422p16le",
|
|
||||||
"yuva444p16be",
|
|
||||||
"yuva444p16le",
|
|
||||||
"rgba64be",
|
|
||||||
"rgba64le",
|
|
||||||
"bgra64be",
|
|
||||||
"bgra64le",
|
|
||||||
"ya16be",
|
|
||||||
"ya16le",
|
|
||||||
"gbrap",
|
|
||||||
"gbrap16be",
|
|
||||||
"gbrap16le",
|
|
||||||
"ayuv64le",
|
|
||||||
"ayuv64be",
|
|
||||||
"gbrap12be",
|
|
||||||
"gbrap12le",
|
|
||||||
"gbrap10be",
|
|
||||||
"gbrap10le",
|
|
||||||
"gbrapf32be",
|
|
||||||
"gbrapf32le",
|
|
||||||
"yuva422p12be",
|
|
||||||
"yuva422p12le",
|
|
||||||
"yuva444p12be",
|
|
||||||
"yuva444p12le",
|
|
||||||
"vuya",
|
|
||||||
"rgbaf16be",
|
|
||||||
"rgbaf16le",
|
|
||||||
"rgbaf32be",
|
|
||||||
"rgbaf32le",
|
|
||||||
];
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn parse_pixel_formats() {
|
|
||||||
let formats =
|
|
||||||
std::fs::read_to_string("./src/ffmpeg/ffprobe_6_0_pixel_formats.json").expect("Read file");
|
|
||||||
|
|
||||||
let json: PixelFormatOutput = serde_json::from_str(&formats).expect("Valid json");
|
|
||||||
|
|
||||||
let output = super::parse_pixel_formats(json);
|
|
||||||
|
|
||||||
for format in ALPHA_PIXEL_FORMATS {
|
|
||||||
assert!(output.contains(*format), "Doesn't contain {format}");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -17,14 +17,14 @@ pub(crate) struct PrescribedFormats {
|
||||||
pub(crate) allow_audio: bool,
|
pub(crate) allow_audio: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub(crate) enum InputFile {
|
pub(crate) enum InputFile {
|
||||||
Image(ImageInput),
|
Image(ImageInput),
|
||||||
Animation(AnimationInput),
|
Animation(AnimationInput),
|
||||||
Video(VideoFormat),
|
Video(VideoFormat),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, serde::Serialize, serde::Deserialize)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
|
||||||
pub(crate) enum InternalFormat {
|
pub(crate) enum InternalFormat {
|
||||||
Image(ImageFormat),
|
Image(ImageFormat),
|
||||||
Animation(AnimationFormat),
|
Animation(AnimationFormat),
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
#[cfg(test)]
|
|
||||||
mod tests;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
formats::ProcessableFormat,
|
formats::ProcessableFormat,
|
||||||
process::{Process, ProcessError},
|
process::{Process, ProcessError},
|
||||||
|
|
|
@ -1,93 +0,0 @@
|
||||||
use super::{Details, DetailsOutput};
|
|
||||||
|
|
||||||
fn details_tests() -> [(&'static str, Details); 8] {
|
|
||||||
[
|
|
||||||
(
|
|
||||||
"avif",
|
|
||||||
Details {
|
|
||||||
mime_type: super::image_avif(),
|
|
||||||
width: 1920,
|
|
||||||
height: 1080,
|
|
||||||
frames: None,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"gif",
|
|
||||||
Details {
|
|
||||||
mime_type: mime::IMAGE_GIF,
|
|
||||||
width: 414,
|
|
||||||
height: 261,
|
|
||||||
frames: Some(17),
|
|
||||||
},
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"jpeg",
|
|
||||||
Details {
|
|
||||||
mime_type: mime::IMAGE_JPEG,
|
|
||||||
width: 1920,
|
|
||||||
height: 1080,
|
|
||||||
frames: None,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"jxl",
|
|
||||||
Details {
|
|
||||||
mime_type: super::image_jxl(),
|
|
||||||
width: 1920,
|
|
||||||
height: 1080,
|
|
||||||
frames: None,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"mp4",
|
|
||||||
Details {
|
|
||||||
mime_type: super::video_mp4(),
|
|
||||||
width: 414,
|
|
||||||
height: 261,
|
|
||||||
frames: Some(17),
|
|
||||||
},
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"png",
|
|
||||||
Details {
|
|
||||||
mime_type: mime::IMAGE_PNG,
|
|
||||||
width: 497,
|
|
||||||
height: 694,
|
|
||||||
frames: None,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"webm",
|
|
||||||
Details {
|
|
||||||
mime_type: super::video_webm(),
|
|
||||||
width: 112,
|
|
||||||
height: 112,
|
|
||||||
frames: Some(27),
|
|
||||||
},
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"webp",
|
|
||||||
Details {
|
|
||||||
mime_type: super::image_webp(),
|
|
||||||
width: 1920,
|
|
||||||
height: 1080,
|
|
||||||
frames: None,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn parse_details() {
|
|
||||||
for (case, expected) in details_tests() {
|
|
||||||
let string =
|
|
||||||
std::fs::read_to_string(format!("./src/magick/magick_7_1_1_{case}_details.json"))
|
|
||||||
.expect("Read file");
|
|
||||||
|
|
||||||
let json: Vec<DetailsOutput> = serde_json::from_str(&string).expect("Valid json");
|
|
||||||
|
|
||||||
let output = super::parse_details(json).expect("Parsed details");
|
|
||||||
|
|
||||||
assert_eq!(output, expected);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue