Skip to main content

oxideav_core/
format.rs

1//! Media-type and sample/pixel format enumerations.
2
3#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
4pub enum MediaType {
5    Audio,
6    Video,
7    Subtitle,
8    Data,
9    Unknown,
10}
11
12/// Audio sample format.
13#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
14pub enum SampleFormat {
15    /// Unsigned 8-bit, interleaved.
16    U8,
17    /// Signed 8-bit, interleaved. Native format of Amiga 8SVX and MOD samples.
18    S8,
19    /// Signed 16-bit little-endian, interleaved.
20    S16,
21    /// Signed 24-bit packed (3 bytes/sample) little-endian, interleaved.
22    S24,
23    /// Signed 32-bit little-endian, interleaved.
24    S32,
25    /// 32-bit IEEE float, interleaved.
26    F32,
27    /// 64-bit IEEE float, interleaved.
28    F64,
29    /// Planar variants — one plane per channel.
30    U8P,
31    S16P,
32    S32P,
33    F32P,
34    F64P,
35}
36
37impl SampleFormat {
38    pub fn is_planar(&self) -> bool {
39        matches!(
40            self,
41            Self::U8P | Self::S16P | Self::S32P | Self::F32P | Self::F64P
42        )
43    }
44
45    /// Bytes per sample *per channel*.
46    pub fn bytes_per_sample(&self) -> usize {
47        match self {
48            Self::U8 | Self::U8P | Self::S8 => 1,
49            Self::S16 | Self::S16P => 2,
50            Self::S24 => 3,
51            Self::S32 | Self::S32P | Self::F32 | Self::F32P => 4,
52            Self::F64 | Self::F64P => 8,
53        }
54    }
55
56    pub fn is_float(&self) -> bool {
57        matches!(self, Self::F32 | Self::F64 | Self::F32P | Self::F64P)
58    }
59}
60
61/// Video pixel format.
62///
63/// The first six variants (`Yuv420P` through `Gray8`) are the original
64/// formats produced by the early codec crates. Everything beyond that is
65/// additional surface handled by `oxideav-pixfmt` and the still-image
66/// codecs (PNG, GIF, still-JPEG). The enum is `#[non_exhaustive]` so new
67/// variants can land without breaking downstream crates — consumers that
68/// match must include a wildcard arm.
69#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
70#[non_exhaustive]
71pub enum PixelFormat {
72    /// 8-bit YUV 4:2:0, planar (Y, U, V).
73    Yuv420P,
74    /// 8-bit YUV 4:2:2, planar.
75    Yuv422P,
76    /// 8-bit YUV 4:4:4, planar.
77    Yuv444P,
78    /// Packed 8-bit RGB, 3 bytes/pixel.
79    Rgb24,
80    /// Packed 8-bit RGBA, 4 bytes/pixel.
81    Rgba,
82    /// Packed 8-bit grayscale.
83    Gray8,
84
85    // --- Palette ---
86    /// 8-bit palette indices — companion palette carried out of band.
87    Pal8,
88
89    // --- Packed RGB/BGR swizzles ---
90    /// Packed 8-bit BGR, 3 bytes/pixel.
91    Bgr24,
92    /// Packed 8-bit BGRA, 4 bytes/pixel.
93    Bgra,
94    /// Packed 8-bit ARGB, 4 bytes/pixel (alpha first).
95    Argb,
96    /// Packed 8-bit ABGR, 4 bytes/pixel.
97    Abgr,
98
99    // --- Deeper packed RGB ---
100    /// Packed 16-bit-per-channel RGB, little-endian, 6 bytes/pixel.
101    Rgb48Le,
102    /// Packed 16-bit-per-channel RGBA, little-endian, 8 bytes/pixel.
103    Rgba64Le,
104
105    // --- Grayscale deeper / partial bit depths ---
106    /// 16-bit little-endian grayscale.
107    Gray16Le,
108    /// 10-bit grayscale in a 16-bit little-endian word.
109    Gray10Le,
110    /// 12-bit grayscale in a 16-bit little-endian word.
111    Gray12Le,
112
113    // --- Higher-precision YUV ---
114    /// 10-bit YUV 4:2:0 planar, little-endian 16-bit storage.
115    Yuv420P10Le,
116    /// 10-bit YUV 4:2:2 planar, little-endian 16-bit storage.
117    Yuv422P10Le,
118    /// 10-bit YUV 4:4:4 planar, little-endian 16-bit storage.
119    Yuv444P10Le,
120    /// 12-bit YUV 4:2:0 planar, little-endian 16-bit storage.
121    Yuv420P12Le,
122
123    // --- Full-range ("J") YUV ---
124    /// JPEG/full-range YUV 4:2:0 planar.
125    YuvJ420P,
126    /// JPEG/full-range YUV 4:2:2 planar.
127    YuvJ422P,
128    /// JPEG/full-range YUV 4:4:4 planar.
129    YuvJ444P,
130
131    // --- Semi-planar YUV ---
132    /// YUV 4:2:0, planar Y + interleaved UV (NV12).
133    Nv12,
134    /// YUV 4:2:0, planar Y + interleaved VU (NV21).
135    Nv21,
136
137    // --- Gray + alpha / YUV + alpha ---
138    /// Packed grayscale + alpha, 2 bytes/pixel (Y, A).
139    Ya8,
140    /// Yuv420P with an additional full-resolution alpha plane.
141    Yuva420P,
142
143    // --- Mono (1 bit per pixel) ---
144    /// 1 bit per pixel, packed MSB-first, 0 = black.
145    MonoBlack,
146    /// 1 bit per pixel, packed MSB-first, 0 = white.
147    MonoWhite,
148
149    // --- Interleaved YUV 4:2:2 ---
150    /// Packed 4:2:2, byte order Y0 U0 Y1 V0.
151    Yuyv422,
152    /// Packed 4:2:2, byte order U0 Y0 V0 Y1.
153    Uyvy422,
154}
155
156impl PixelFormat {
157    /// True if this format stores its components in separate planes.
158    pub fn is_planar(&self) -> bool {
159        matches!(
160            self,
161            Self::Yuv420P
162                | Self::Yuv422P
163                | Self::Yuv444P
164                | Self::Yuv420P10Le
165                | Self::Yuv422P10Le
166                | Self::Yuv444P10Le
167                | Self::Yuv420P12Le
168                | Self::YuvJ420P
169                | Self::YuvJ422P
170                | Self::YuvJ444P
171                | Self::Nv12
172                | Self::Nv21
173                | Self::Yuva420P
174        )
175    }
176
177    /// True if the format is a palette index format (`Pal8`).
178    pub fn is_palette(&self) -> bool {
179        matches!(self, Self::Pal8)
180    }
181
182    /// True if this format carries an alpha channel.
183    pub fn has_alpha(&self) -> bool {
184        matches!(
185            self,
186            Self::Rgba
187                | Self::Bgra
188                | Self::Argb
189                | Self::Abgr
190                | Self::Rgba64Le
191                | Self::Ya8
192                | Self::Yuva420P
193        )
194    }
195
196    /// Number of planes in the stored layout. Packed and palette formats
197    /// return 1; NV12/NV21 return 2; planar YUV without alpha returns 3;
198    /// YuvA variants return 4.
199    pub fn plane_count(&self) -> usize {
200        match self {
201            Self::Nv12 | Self::Nv21 => 2,
202            Self::Yuv420P
203            | Self::Yuv422P
204            | Self::Yuv444P
205            | Self::Yuv420P10Le
206            | Self::Yuv422P10Le
207            | Self::Yuv444P10Le
208            | Self::Yuv420P12Le
209            | Self::YuvJ420P
210            | Self::YuvJ422P
211            | Self::YuvJ444P => 3,
212            Self::Yuva420P => 4,
213            _ => 1,
214        }
215    }
216
217    /// Rough bits-per-pixel estimate, useful for buffer sizing. Not exact
218    /// for chroma-subsampled YUV — intended for worst-case preallocation
219    /// rather than wire-accurate accounting.
220    pub fn bits_per_pixel_approx(&self) -> u32 {
221        match self {
222            Self::MonoBlack | Self::MonoWhite => 1,
223            Self::Gray8 | Self::Pal8 => 8,
224            Self::Ya8 => 16,
225            Self::Gray16Le | Self::Gray10Le | Self::Gray12Le => 16,
226            Self::Rgb24 | Self::Bgr24 => 24,
227            Self::Rgba | Self::Bgra | Self::Argb | Self::Abgr => 32,
228            Self::Rgb48Le => 48,
229            Self::Rgba64Le => 64,
230            Self::Yuyv422 | Self::Uyvy422 => 16,
231            // Planar YUV: 4:2:0 ≈ 12, 4:2:2 ≈ 16, 4:4:4 ≈ 24
232            // 10/12-bit variants double the byte count but we report the
233            // packed-bits-per-pixel estimate for a uniform heuristic.
234            Self::Yuv420P | Self::YuvJ420P | Self::Nv12 | Self::Nv21 => 12,
235            Self::Yuv422P | Self::YuvJ422P => 16,
236            Self::Yuv444P | Self::YuvJ444P => 24,
237            Self::Yuv420P10Le | Self::Yuv420P12Le => 24,
238            Self::Yuv422P10Le => 32,
239            Self::Yuv444P10Le => 48,
240            Self::Yuva420P => 20,
241        }
242    }
243}