Skip to main content

ff_encode/
container.rs

1//! Container format definitions.
2
3/// Container format for output file.
4///
5/// The container format is usually auto-detected from the file extension,
6/// but can be explicitly specified if needed.
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8#[non_exhaustive]
9pub enum Container {
10    /// MP4 / `QuickTime`
11    Mp4,
12
13    /// Fragmented MP4 — CMAF-compatible streaming container.
14    ///
15    /// Uses the same `mp4` `FFmpeg` muxer as [`Container::Mp4`] but with
16    /// `movflags=+frag_keyframe+empty_moov+default_base_moof` applied before
17    /// writing the header. Required for HTTP Live Streaming fMP4 segments
18    /// (CMAF) and MPEG-DASH.
19    FMp4,
20
21    /// `WebM`
22    WebM,
23
24    /// Matroska
25    Mkv,
26
27    /// AVI
28    Avi,
29
30    /// MOV
31    Mov,
32
33    /// FLAC (lossless audio container)
34    Flac,
35
36    /// OGG (audio container for Vorbis/Opus)
37    Ogg,
38}
39
40impl Container {
41    /// Get `FFmpeg` format name.
42    #[must_use]
43    pub const fn as_str(self) -> &'static str {
44        match self {
45            Self::Mp4 | Self::FMp4 => "mp4",
46            Self::WebM => "webm",
47            Self::Mkv => "matroska",
48            Self::Avi => "avi",
49            Self::Mov => "mov",
50            Self::Flac => "flac",
51            Self::Ogg => "ogg",
52        }
53    }
54
55    /// Get default file extension.
56    #[must_use]
57    pub const fn default_extension(self) -> &'static str {
58        match self {
59            Self::Mp4 | Self::FMp4 => "mp4",
60            Self::WebM => "webm",
61            Self::Mkv => "mkv",
62            Self::Avi => "avi",
63            Self::Mov => "mov",
64            Self::Flac => "flac",
65            Self::Ogg => "ogg",
66        }
67    }
68
69    /// Returns `true` if this container is fragmented MP4.
70    ///
71    /// When `true`, the encoder applies
72    /// `movflags=+frag_keyframe+empty_moov+default_base_moof` before writing
73    /// the file header, enabling CMAF-compatible streaming output.
74    #[must_use]
75    pub const fn is_fragmented(self) -> bool {
76        matches!(self, Self::FMp4)
77    }
78}
79
80#[cfg(test)]
81mod tests {
82    use super::*;
83
84    #[test]
85    fn test_container_as_str() {
86        assert_eq!(Container::Mp4.as_str(), "mp4");
87        assert_eq!(Container::WebM.as_str(), "webm");
88        assert_eq!(Container::Mkv.as_str(), "matroska");
89    }
90
91    #[test]
92    fn test_container_extension() {
93        assert_eq!(Container::Mp4.default_extension(), "mp4");
94        assert_eq!(Container::WebM.default_extension(), "webm");
95        assert_eq!(Container::Mkv.default_extension(), "mkv");
96        assert_eq!(Container::Flac.default_extension(), "flac");
97        assert_eq!(Container::Ogg.default_extension(), "ogg");
98    }
99
100    #[test]
101    fn flac_as_str_should_return_flac() {
102        assert_eq!(Container::Flac.as_str(), "flac");
103    }
104
105    #[test]
106    fn ogg_as_str_should_return_ogg() {
107        assert_eq!(Container::Ogg.as_str(), "ogg");
108    }
109
110    #[test]
111    fn fmp4_as_str_should_return_mp4() {
112        assert_eq!(Container::FMp4.as_str(), "mp4");
113    }
114
115    #[test]
116    fn fmp4_extension_should_return_mp4() {
117        assert_eq!(Container::FMp4.default_extension(), "mp4");
118    }
119
120    #[test]
121    fn fmp4_is_fragmented_should_return_true() {
122        assert!(Container::FMp4.is_fragmented());
123        assert!(!Container::Mp4.is_fragmented());
124        assert!(!Container::Mkv.is_fragmented());
125    }
126}