use codec::frame::{PixelFormat, StreamInfo};
pub const MIN_RESOLUTION: u32 = 360;
pub const MIN_FRAME_RATE: f64 = 15.0;
pub const MAX_DURATION_SECS: f64 = 900.0;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ValidationErrorKind {
ResolutionTooSmall,
FrameRateTooSmall,
DurationTooLong,
UnsupportedPixelFormat,
}
#[derive(Debug, Clone)]
pub struct ValidationError {
pub kind: ValidationErrorKind,
pub message: String,
}
impl std::fmt::Display for ValidationError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.message)
}
}
impl std::error::Error for ValidationError {}
pub fn validate_stream(info: &StreamInfo) -> Result<(), ValidationError> {
if info.width < MIN_RESOLUTION || info.height < MIN_RESOLUTION {
return Err(ValidationError {
kind: ValidationErrorKind::ResolutionTooSmall,
message: format!(
"Video resolution {}x{} is below the minimum {}x{}.",
info.width, info.height, MIN_RESOLUTION, MIN_RESOLUTION
),
});
}
if info.frame_rate < MIN_FRAME_RATE {
return Err(ValidationError {
kind: ValidationErrorKind::FrameRateTooSmall,
message: format!(
"Video frame rate {:.1} fps is below the minimum {:.0} fps.",
info.frame_rate, MIN_FRAME_RATE
),
});
}
if info.duration > MAX_DURATION_SECS {
return Err(ValidationError {
kind: ValidationErrorKind::DurationTooLong,
message: format!(
"Video duration {:.0}s exceeds the maximum {}s.",
info.duration, MAX_DURATION_SECS
),
});
}
if !matches!(
info.pixel_format,
PixelFormat::Yuv420p
| PixelFormat::Yuv420p10le
| PixelFormat::Yuv444p10le
| PixelFormat::Yuva444p10le
) {
return Err(ValidationError {
kind: ValidationErrorKind::UnsupportedPixelFormat,
message: format!(
"Pixel format {} is not supported.",
info.pixel_format.as_ffmpeg_str()
),
});
}
Ok(())
}
pub fn needs_chroma_downsample(format: PixelFormat) -> bool {
matches!(
format,
PixelFormat::Yuv444p10le | PixelFormat::Yuva444p10le | PixelFormat::Yuv444p
)
}