mod cache;
mod encode;
mod path;
mod probe;
pub use cache::*;
pub use encode::*;
pub use path::*;
pub use probe::*;
use serde::{Deserialize, Serialize};
use std::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Codec {
#[serde(rename = "libx264")]
X264,
#[serde(rename = "libx265")]
X265,
#[serde(rename = "libsvtav1")]
SvtAv1,
}
impl Codec {
pub fn as_str(&self) -> &'static str {
match self {
Codec::X264 => "libx264",
Codec::X265 => "libx265",
Codec::SvtAv1 => "libsvtav1",
}
}
}
impl fmt::Display for Codec {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
impl std::str::FromStr for Codec {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"libx264" | "x264" | "h264" => Ok(Codec::X264),
"libx265" | "x265" | "h265" | "hevc" => Ok(Codec::X265),
"libsvtav1" | "svtav1" | "av1" => Ok(Codec::SvtAv1),
_ => Err(anyhow::anyhow!("unknown codec: {s}")),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Resolution {
pub width: i32,
pub height: i32,
}
impl Resolution {
pub const fn new(width: i32, height: i32) -> Self {
Self { width, height }
}
pub fn label(&self) -> String {
match self.height {
h if h >= 2160 => "2160p".into(),
h if h >= 1440 => "1440p".into(),
h if h >= 1080 => "1080p".into(),
h if h >= 720 => "720p".into(),
h if h >= 480 => "480p".into(),
h if h >= 360 => "360p".into(),
h if h >= 240 => "240p".into(),
h => format!("{h}p"),
}
}
}
impl fmt::Display for Resolution {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}x{}", self.width, self.height)
}
}
impl std::str::FromStr for Resolution {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().as_str() {
"2160p" | "4k" => Ok(RES_2160P),
"1440p" => Ok(RES_1440P),
"1080p" => Ok(RES_1080P),
"720p" => Ok(RES_720P),
"480p" => Ok(RES_480P),
"360p" => Ok(RES_360P),
"240p" => Ok(RES_240P),
other => {
if let Some((w, h)) = other.split_once('x') {
Ok(Resolution::new(w.parse()?, h.parse()?))
} else {
Err(anyhow::anyhow!("invalid resolution: {other}"))
}
}
}
}
}
pub const RES_2160P: Resolution = Resolution::new(3840, 2160);
pub const RES_1440P: Resolution = Resolution::new(2560, 1440);
pub const RES_1080P: Resolution = Resolution::new(1920, 1080);
pub const RES_720P: Resolution = Resolution::new(1280, 720);
pub const RES_480P: Resolution = Resolution::new(854, 480);
pub const RES_360P: Resolution = Resolution::new(640, 360);
pub const RES_240P: Resolution = Resolution::new(426, 240);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
#[serde(rename_all = "lowercase")]
pub enum RateControlMode {
#[default]
Crf,
Qp,
Vbr,
}