1mod cache;
2mod encode;
3mod path;
4mod probe;
5
6pub use cache::*;
7pub use encode::*;
8pub use path::*;
9pub use probe::*;
10
11use serde::{Deserialize, Serialize};
12use std::fmt;
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
16pub enum Codec {
17 #[serde(rename = "libx264")]
18 X264,
19 #[serde(rename = "libx265")]
20 X265,
21 #[serde(rename = "libsvtav1")]
22 SvtAv1,
23}
24
25impl Codec {
26 pub fn as_str(&self) -> &'static str {
27 match self {
28 Codec::X264 => "libx264",
29 Codec::X265 => "libx265",
30 Codec::SvtAv1 => "libsvtav1",
31 }
32 }
33}
34
35impl fmt::Display for Codec {
36 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37 f.write_str(self.as_str())
38 }
39}
40
41impl std::str::FromStr for Codec {
42 type Err = anyhow::Error;
43
44 fn from_str(s: &str) -> Result<Self, Self::Err> {
45 match s {
46 "libx264" | "x264" | "h264" => Ok(Codec::X264),
47 "libx265" | "x265" | "h265" | "hevc" => Ok(Codec::X265),
48 "libsvtav1" | "svtav1" | "av1" => Ok(Codec::SvtAv1),
49 _ => Err(anyhow::anyhow!("unknown codec: {s}")),
50 }
51 }
52}
53
54#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
56pub struct Resolution {
57 pub width: i32,
58 pub height: i32,
59}
60
61impl Resolution {
62 pub const fn new(width: i32, height: i32) -> Self {
63 Self { width, height }
64 }
65
66 pub fn label(&self) -> String {
68 match self.height {
69 h if h >= 2160 => "2160p".into(),
70 h if h >= 1440 => "1440p".into(),
71 h if h >= 1080 => "1080p".into(),
72 h if h >= 720 => "720p".into(),
73 h if h >= 480 => "480p".into(),
74 h if h >= 360 => "360p".into(),
75 h if h >= 240 => "240p".into(),
76 h => format!("{h}p"),
77 }
78 }
79}
80
81impl fmt::Display for Resolution {
82 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83 write!(f, "{}x{}", self.width, self.height)
84 }
85}
86
87impl std::str::FromStr for Resolution {
88 type Err = anyhow::Error;
89
90 fn from_str(s: &str) -> Result<Self, Self::Err> {
91 match s.to_lowercase().as_str() {
92 "2160p" | "4k" => Ok(RES_2160P),
93 "1440p" => Ok(RES_1440P),
94 "1080p" => Ok(RES_1080P),
95 "720p" => Ok(RES_720P),
96 "480p" => Ok(RES_480P),
97 "360p" => Ok(RES_360P),
98 "240p" => Ok(RES_240P),
99 other => {
100 if let Some((w, h)) = other.split_once('x') {
101 Ok(Resolution::new(w.parse()?, h.parse()?))
102 } else {
103 Err(anyhow::anyhow!("invalid resolution: {other}"))
104 }
105 }
106 }
107 }
108}
109
110pub const RES_2160P: Resolution = Resolution::new(3840, 2160);
112pub const RES_1440P: Resolution = Resolution::new(2560, 1440);
113pub const RES_1080P: Resolution = Resolution::new(1920, 1080);
114pub const RES_720P: Resolution = Resolution::new(1280, 720);
115pub const RES_480P: Resolution = Resolution::new(854, 480);
116pub const RES_360P: Resolution = Resolution::new(640, 360);
117pub const RES_240P: Resolution = Resolution::new(426, 240);
118
119#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
121#[serde(rename_all = "lowercase")]
122pub enum RateControlMode {
123 #[default]
125 Crf,
126 Qp,
128 Vbr,
130}