Skip to main content

ff_encode/shared/
codec.rs

1//! Codec type re-exports and encode-specific extensions.
2//!
3//! `VideoCodec` and `AudioCodec` are the canonical types defined in
4//! `ff-format` and re-exported here so callers can import them from a
5//! single crate.  Encode-specific behaviour (LGPL licensing, default
6//! file extension) is provided via the [`VideoCodecEncodeExt`] trait.
7
8pub use ff_format::{AudioCodec, VideoCodec};
9
10/// Encode-specific methods for [`VideoCodec`].
11///
12/// This trait adds encoding-oriented helpers to the shared `VideoCodec` type.
13/// Import it to call [`is_lgpl_compatible`](Self::is_lgpl_compatible) or
14/// [`default_extension`](Self::default_extension) on a codec value.
15///
16/// # Examples
17///
18/// ```
19/// use ff_encode::{VideoCodec, VideoCodecEncodeExt};
20///
21/// assert!(VideoCodec::Vp9.is_lgpl_compatible());
22/// assert_eq!(VideoCodec::H264.default_extension(), "mp4");
23/// ```
24pub trait VideoCodecEncodeExt {
25    /// Returns `true` if the *software* encoder for this codec is
26    /// LGPL-compatible (i.e. does not require a GPL or proprietary licence).
27    ///
28    /// **Important**: This reflects the codec family's typical software
29    /// encoder licensing, not the actual encoder chosen at runtime.
30    /// H.264 and H.265 return `false` because their software encoders
31    /// (libx264/libx265) are GPL; hardware encoders (NVENC, QSV, etc.)
32    /// are LGPL-compatible regardless.
33    ///
34    /// Use [`VideoEncoder::is_lgpl_compliant`](crate::VideoEncoder) to
35    /// query the actual encoder selected at runtime.
36    fn is_lgpl_compatible(&self) -> bool;
37
38    /// Returns the default output file extension for this codec.
39    fn default_extension(&self) -> &'static str;
40}
41
42impl VideoCodecEncodeExt for VideoCodec {
43    fn is_lgpl_compatible(&self) -> bool {
44        matches!(
45            self,
46            VideoCodec::Vp9
47                | VideoCodec::Av1
48                | VideoCodec::Av1Svt
49                | VideoCodec::Mpeg4
50                | VideoCodec::ProRes
51                | VideoCodec::DnxHd
52                | VideoCodec::Ffv1
53        )
54    }
55
56    fn default_extension(&self) -> &'static str {
57        match self {
58            VideoCodec::Vp9 | VideoCodec::Av1 => "webm",
59            VideoCodec::Ffv1 => "mkv",
60            _ => "mp4",
61        }
62    }
63}
64
65#[cfg(test)]
66mod tests {
67    use super::*;
68
69    #[test]
70    fn video_codec_is_lgpl_compatible_should_return_true_for_open_codecs() {
71        assert!(VideoCodec::Vp9.is_lgpl_compatible());
72        assert!(VideoCodec::Av1.is_lgpl_compatible());
73        assert!(VideoCodec::Mpeg4.is_lgpl_compatible());
74        assert!(VideoCodec::ProRes.is_lgpl_compatible());
75        assert!(VideoCodec::DnxHd.is_lgpl_compatible());
76    }
77
78    #[test]
79    fn video_codec_is_lgpl_compatible_should_return_false_for_gpl_codecs() {
80        assert!(!VideoCodec::H264.is_lgpl_compatible());
81        assert!(!VideoCodec::H265.is_lgpl_compatible());
82    }
83
84    #[test]
85    fn video_codec_default_extension_should_return_webm_for_web_codecs() {
86        assert_eq!(VideoCodec::H264.default_extension(), "mp4");
87        assert_eq!(VideoCodec::Vp9.default_extension(), "webm");
88        assert_eq!(VideoCodec::Av1.default_extension(), "webm");
89    }
90
91    #[test]
92    fn video_and_audio_codec_default_should_be_accessible() {
93        assert_eq!(VideoCodec::default(), VideoCodec::H264);
94        assert_eq!(AudioCodec::default(), AudioCodec::Aac);
95    }
96}