Skip to main content

ff_encode/video/codec_options/
h265.rs

1//! H.265 (HEVC) per-codec encoding options.
2
3/// H.265 (HEVC) per-codec options.
4#[derive(Debug, Clone)]
5pub struct H265Options {
6    /// Encoding profile.
7    pub profile: H265Profile,
8    /// Encoding tier.
9    pub tier: H265Tier,
10    /// Encoding level as an integer (e.g. `31` = 3.1, `51` = 5.1).
11    ///
12    /// `None` leaves the encoder default.
13    pub level: Option<u32>,
14    /// libx265 encoding speed/quality preset (e.g. `"ultrafast"`, `"medium"`, `"slow"`).
15    ///
16    /// `None` leaves the encoder default. Invalid or unsupported values are logged as a
17    /// warning and skipped — `build()` never fails due to an unsupported preset.
18    /// Hardware HEVC encoders (hevc_nvenc, etc.) ignore this option.
19    pub preset: Option<String>,
20    /// Raw x265-params string passed verbatim to libx265 (e.g. `"ctu=32:ref=4"`).
21    ///
22    /// **Note**: H.265 encoding requires an FFmpeg build with `--enable-libx265`.
23    ///
24    /// An invalid parameter string is logged as a warning and skipped. It never causes
25    /// `build()` to return an error.
26    pub x265_params: Option<String>,
27}
28
29impl Default for H265Options {
30    fn default() -> Self {
31        Self {
32            profile: H265Profile::Main,
33            tier: H265Tier::Main,
34            level: None,
35            preset: None,
36            x265_params: None,
37        }
38    }
39}
40
41/// H.265 encoding profile.
42#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
43pub enum H265Profile {
44    /// Main profile (8-bit, 4:2:0).
45    #[default]
46    Main,
47    /// Main 10-bit profile (HDR-capable).
48    Main10,
49}
50
51impl H265Profile {
52    pub(in crate::video) fn as_str(self) -> &'static str {
53        match self {
54            Self::Main => "main",
55            Self::Main10 => "main10",
56        }
57    }
58}
59
60/// H.265 encoding tier.
61#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
62pub enum H265Tier {
63    /// Main tier — lower bitrate ceiling (consumer content).
64    #[default]
65    Main,
66    /// High tier — higher bitrate ceiling (broadcast / professional).
67    High,
68}
69
70impl H265Tier {
71    pub(in crate::video) fn as_str(self) -> &'static str {
72        match self {
73            Self::Main => "main",
74            Self::High => "high",
75        }
76    }
77}
78
79#[cfg(test)]
80mod tests {
81    use super::*;
82
83    #[test]
84    fn h265_profile_should_return_correct_str() {
85        assert_eq!(H265Profile::Main.as_str(), "main");
86        assert_eq!(H265Profile::Main10.as_str(), "main10");
87    }
88
89    #[test]
90    fn h265_tier_should_return_correct_str() {
91        assert_eq!(H265Tier::Main.as_str(), "main");
92        assert_eq!(H265Tier::High.as_str(), "high");
93    }
94
95    #[test]
96    fn h265_options_default_should_have_main_profile() {
97        let opts = H265Options::default();
98        assert_eq!(opts.profile, H265Profile::Main);
99        assert_eq!(opts.tier, H265Tier::Main);
100        assert_eq!(opts.level, None);
101        assert!(opts.preset.is_none());
102        assert!(opts.x265_params.is_none());
103    }
104}