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}