Skip to main content

ff_encode/
codec.rs

1//! Codec definitions for encoding.
2
3/// Video codec for encoding.
4#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
5#[non_exhaustive]
6pub enum VideoCodec {
7    /// H.264 / AVC (most compatible)
8    #[default]
9    H264,
10
11    /// H.265 / HEVC (high compression)
12    H265,
13
14    /// VP9 (`WebM`, royalty-free)
15    Vp9,
16
17    /// AV1 (latest, high compression, LGPL compatible)
18    Av1,
19
20    /// `ProRes` (Apple, editing)
21    ProRes,
22
23    /// `DNxHD`/`DNxHR` (Avid, editing)
24    DnxHd,
25
26    /// MPEG-4
27    Mpeg4,
28}
29
30impl VideoCodec {
31    /// Check if this codec specification is LGPL compatible.
32    ///
33    /// Returns `true` for codecs that can be used without GPL licensing.
34    ///
35    /// **Important**: This indicates the codec family's licensing, not the actual encoder used.
36    /// H.264 and H.265 return `false` because their software encoders (libx264/libx265) are GPL,
37    /// but hardware encoders (NVENC, QSV, etc.) are LGPL-compatible.
38    ///
39    /// Use [`VideoEncoder::is_lgpl_compliant()`](crate::VideoEncoder::is_lgpl_compliant) to check
40    /// the actual encoder selected at runtime.
41    ///
42    /// # LGPL-Compatible Codecs
43    ///
44    /// - `VP9` - Google's royalty-free codec (libvpx-vp9)
45    /// - `AV1` - Next-gen royalty-free codec (libaom-av1)
46    /// - `ProRes` - Apple's professional codec
47    /// - `DNxHD` - Avid's professional codec
48    /// - `MPEG4` - ISO MPEG-4 Part 2
49    ///
50    /// # GPL Codecs (require licensing for commercial use)
51    ///
52    /// - `H264` - Requires MPEG LA license (when using libx264)
53    /// - `H265` - Requires MPEG LA license (when using libx265)
54    ///
55    /// Note: Hardware H.264/H.265 encoders are LGPL-compatible and don't require licensing fees.
56    #[must_use]
57    pub const fn is_lgpl_compatible(self) -> bool {
58        match self {
59            Self::Vp9 | Self::Av1 | Self::Mpeg4 | Self::ProRes | Self::DnxHd => true,
60            Self::H264 | Self::H265 => false, // libx264/libx265 are GPL
61        }
62    }
63
64    /// Get default file extension for this codec.
65    #[must_use]
66    pub const fn default_extension(self) -> &'static str {
67        match self {
68            Self::Vp9 | Self::Av1 => "webm",
69            _ => "mp4",
70        }
71    }
72}
73
74/// Audio codec for encoding.
75#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
76#[non_exhaustive]
77pub enum AudioCodec {
78    /// AAC (most compatible)
79    #[default]
80    Aac,
81
82    /// Opus (high quality, low latency)
83    Opus,
84
85    /// MP3
86    Mp3,
87
88    /// FLAC (lossless)
89    Flac,
90
91    /// PCM (uncompressed)
92    Pcm,
93
94    /// Vorbis (OGG)
95    Vorbis,
96}
97
98#[cfg(test)]
99mod tests {
100    use super::*;
101
102    #[test]
103    fn test_video_codec_lgpl() {
104        assert!(VideoCodec::Vp9.is_lgpl_compatible());
105        assert!(VideoCodec::Av1.is_lgpl_compatible());
106        assert!(VideoCodec::Mpeg4.is_lgpl_compatible());
107        assert!(!VideoCodec::H264.is_lgpl_compatible());
108        assert!(!VideoCodec::H265.is_lgpl_compatible());
109    }
110
111    #[test]
112    fn test_video_codec_extension() {
113        assert_eq!(VideoCodec::H264.default_extension(), "mp4");
114        assert_eq!(VideoCodec::Vp9.default_extension(), "webm");
115        assert_eq!(VideoCodec::Av1.default_extension(), "webm");
116    }
117
118    #[test]
119    fn test_default_codecs() {
120        assert_eq!(VideoCodec::default(), VideoCodec::H264);
121        assert_eq!(AudioCodec::default(), AudioCodec::Aac);
122    }
123}