1pub mod bitstream_utils;
24pub mod codec;
25
26#[cfg(feature = "backend")]
27pub mod backend;
28#[cfg(feature = "c2-wrapper")]
29pub mod c2_wrapper;
30#[cfg(feature = "backend")]
31pub mod decoder;
32#[cfg(feature = "v4l2")]
33pub mod device;
34#[cfg(feature = "backend")]
35pub mod encoder;
36#[cfg(feature = "backend")]
37pub mod image_processing;
38#[cfg(feature = "backend")]
39pub mod utils;
40#[cfg(feature = "backend")]
41pub mod video_frame;
42
43use std::str::FromStr;
44
45#[cfg(feature = "vaapi")]
46pub use libva;
47#[cfg(feature = "v4l2")]
48pub use v4l2r;
49
50#[derive(Debug, PartialEq, Eq, Copy, Clone)]
51pub enum FrameMemoryType {
52 Managed,
53 Prime,
54 User,
55}
56
57impl FromStr for FrameMemoryType {
58 type Err = &'static str;
59
60 fn from_str(s: &str) -> Result<Self, Self::Err> {
61 match s {
62 "managed" => Ok(FrameMemoryType::Managed),
63 "prime" => Ok(FrameMemoryType::Prime),
64 "user" => Ok(FrameMemoryType::User),
65 _ => Err("unrecognized memory type. Valid values: managed, prime, user"),
66 }
67 }
68}
69
70#[derive(Copy, Clone, Debug, PartialEq, Eq)]
72pub enum ResolutionRoundMode {
73 Even,
75}
76
77#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
79pub struct Resolution {
80 pub width: u32,
81 pub height: u32,
82}
83
84impl Resolution {
85 pub fn can_contain(&self, other: Self) -> bool {
87 self.width >= other.width && self.height >= other.height
88 }
89
90 pub fn round(mut self, rnd_mode: ResolutionRoundMode) -> Self {
92 match rnd_mode {
93 ResolutionRoundMode::Even => {
94 if self.width % 2 != 0 {
95 self.width += 1;
96 }
97
98 if self.height % 2 != 0 {
99 self.height += 1;
100 }
101 }
102 }
103
104 self
105 }
106
107 pub fn get_area(&self) -> usize {
108 (self.width as usize) * (self.height as usize)
109 }
110}
111
112impl From<(u32, u32)> for Resolution {
113 fn from(value: (u32, u32)) -> Self {
114 Self { width: value.0, height: value.1 }
115 }
116}
117
118impl From<Resolution> for (u32, u32) {
119 fn from(value: Resolution) -> Self {
120 (value.width, value.height)
121 }
122}
123
124#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
125pub struct Rect {
126 pub x: u32,
127 pub y: u32,
128 pub width: u32,
129 pub height: u32,
130}
131
132impl From<Rect> for Resolution {
133 fn from(value: Rect) -> Self {
134 Self { width: value.width - value.x, height: value.height - value.y }
135 }
136}
137
138impl From<Resolution> for Rect {
139 fn from(value: Resolution) -> Self {
140 Self { x: 0, y: 0, width: value.width, height: value.height }
141 }
142}
143
144impl From<((u32, u32), (u32, u32))> for Rect {
145 fn from(value: ((u32, u32), (u32, u32))) -> Self {
146 Self { x: value.0 .0, y: value.0 .1, width: value.1 .0, height: value.1 .1 }
147 }
148}
149#[derive(Clone, Copy, Default, PartialEq)]
153pub struct Fourcc(u32);
154
155impl From<u32> for Fourcc {
156 fn from(fourcc: u32) -> Self {
157 Self(fourcc)
158 }
159}
160
161impl From<Fourcc> for u32 {
162 fn from(fourcc: Fourcc) -> Self {
163 fourcc.0
164 }
165}
166
167impl From<&[u8; 4]> for Fourcc {
168 fn from(n: &[u8; 4]) -> Self {
169 Self(n[0] as u32 | (n[1] as u32) << 8 | (n[2] as u32) << 16 | (n[3] as u32) << 24)
170 }
171}
172
173impl From<Fourcc> for [u8; 4] {
174 fn from(n: Fourcc) -> Self {
175 [n.0 as u8, (n.0 >> 8) as u8, (n.0 >> 16) as u8, (n.0 >> 24) as u8]
176 }
177}
178
179impl std::fmt::Display for Fourcc {
180 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
181 let c: [u8; 4] = (*self).into();
182
183 f.write_fmt(format_args!(
184 "{}{}{}{}",
185 c[0] as char, c[1] as char, c[2] as char, c[3] as char
186 ))
187 }
188}
189
190impl std::fmt::Debug for Fourcc {
191 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
192 f.write_fmt(format_args!("0x{:08x} ({})", self.0, self))
193 }
194}
195
196#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
200pub enum DecodedFormat {
201 I420,
203 NV12,
205 I422,
207 I444,
209 I010,
211 I012,
213 I210,
215 I212,
217 I410,
219 I412,
221 MM21,
224}
225
226impl FromStr for DecodedFormat {
227 type Err = &'static str;
228
229 fn from_str(s: &str) -> Result<Self, Self::Err> {
230 match s {
231 "i420" | "I420" => Ok(DecodedFormat::I420),
232 "i422" | "I422" => Ok(DecodedFormat::I422),
233 "i444" | "I444" => Ok(DecodedFormat::I444),
234 "nv12" | "NV12" => Ok(DecodedFormat::NV12),
235 "i010" | "I010" => Ok(DecodedFormat::I010),
236 "i012" | "I012" => Ok(DecodedFormat::I012),
237 "i210" | "I210" => Ok(DecodedFormat::I210),
238 "i212" | "I212" => Ok(DecodedFormat::I212),
239 "i410" | "I410" => Ok(DecodedFormat::I410),
240 "i412" | "I412" => Ok(DecodedFormat::I412),
241 "mm21" | "MM21" => Ok(DecodedFormat::MM21),
242 _ => Err("unrecognized output format. \
243 Valid values: i420, nv12, i422, i444, i010, i012, i210, i212, i410, i412, mm21"),
244 }
245 }
246}
247
248impl From<Fourcc> for DecodedFormat {
249 fn from(fourcc: Fourcc) -> DecodedFormat {
250 match fourcc.to_string().as_str() {
251 "I420" => DecodedFormat::I420,
252 "NV12" | "NM12" => DecodedFormat::NV12,
253 "MM21" => DecodedFormat::MM21,
254 _ => todo!("Fourcc {} not yet supported", fourcc),
255 }
256 }
257}
258
259impl From<DecodedFormat> for Fourcc {
260 fn from(format: DecodedFormat) -> Fourcc {
261 match format {
262 DecodedFormat::I420 => Fourcc::from(b"I420"),
263 DecodedFormat::NV12 => Fourcc::from(b"NV12"),
264 DecodedFormat::MM21 => Fourcc::from(b"MM21"),
265 _ => todo!(),
266 }
267 }
268}
269
270#[derive(Debug, PartialEq, Eq, Copy, Clone)]
271pub enum EncodedFormat {
272 H264,
273 #[cfg(feature = "h265")]
274 H265,
275 VP8,
276 VP9,
277 #[cfg(feature = "av1")]
278 AV1,
279}
280
281impl FromStr for EncodedFormat {
282 type Err = &'static str;
283
284 fn from_str(s: &str) -> Result<Self, Self::Err> {
285 match s {
286 "h264" | "H264" => Ok(EncodedFormat::H264),
287 #[cfg(feature = "h265")]
288 "h265" | "H265" => Ok(EncodedFormat::H265),
289 "vp8" | "VP8" => Ok(EncodedFormat::VP8),
290 "vp9" | "VP9" => Ok(EncodedFormat::VP9),
291 #[cfg(feature = "av1")]
292 "av1" | "AV1" => Ok(EncodedFormat::AV1),
293 _ => Err("unrecognized input format. Valid values: h264, h265, vp8, vp9, av1"),
294 }
295 }
296}
297
298impl From<Fourcc> for EncodedFormat {
299 fn from(fourcc: Fourcc) -> EncodedFormat {
300 match fourcc.to_string().as_str() {
301 "H264" => EncodedFormat::H264,
302 #[cfg(feature = "h265")]
303 "HEVC" => EncodedFormat::H265,
304 "VP80" => EncodedFormat::VP8,
305 "VP90" => EncodedFormat::VP9,
306 #[cfg(feature = "av1")]
307 "AV1F" => EncodedFormat::AV1,
308 _ => todo!("Fourcc {} not yet supported", fourcc),
309 }
310 }
311}
312
313impl From<EncodedFormat> for Fourcc {
314 fn from(format: EncodedFormat) -> Fourcc {
315 match format {
316 EncodedFormat::H264 => Fourcc::from(b"H264"),
317 #[cfg(feature = "h265")]
318 EncodedFormat::H265 => Fourcc::from(b"HEVC"),
319 EncodedFormat::VP8 => Fourcc::from(b"VP80"),
320 EncodedFormat::VP9 => Fourcc::from(b"VP90"),
321 #[cfg(feature = "av1")]
322 EncodedFormat::AV1 => Fourcc::from(b"AV1F"),
323 }
324 }
325}
326
327#[derive(Debug, Default, Clone, PartialEq)]
329pub struct PlaneLayout {
330 pub buffer_index: usize,
332 pub offset: usize,
334 pub stride: usize,
336}
337
338#[derive(Debug, Default, Clone, PartialEq)]
343pub struct FrameLayout {
344 pub format: (Fourcc, u64),
349 pub size: Resolution,
351 pub planes: Vec<PlaneLayout>,
353}
354
355#[macro_export]
376macro_rules! multiple_desc_type {
377 (enum $s:ident { $($v:ident($t:ty),)* } ) => {
378 pub enum $s {
379 $($v($t),)*
380 }
381
382 #[cfg(feature = "vaapi")]
383 impl libva::SurfaceMemoryDescriptor for $s {
384 fn add_attrs(&mut self, attrs: &mut Vec<libva::VASurfaceAttrib>) -> Option<Box<dyn std::any::Any>> {
385 match self {
386 $($s::$v(desc) => desc.add_attrs(attrs),)*
387 }
388 }
389 }
390 }
391}
392
393pub fn decoded_frame_size(format: DecodedFormat, width: usize, height: usize) -> usize {
397 match format {
398 DecodedFormat::I420 | DecodedFormat::NV12 => {
399 let u_size = width * height;
400 let uv_size = ((width + 1) / 2) * ((height + 1) / 2) * 2;
402
403 u_size + uv_size
404 }
405 DecodedFormat::I422 => {
406 let u_size = width * height;
407 let uv_size = ((width + 1) / 2) * ((height + 1) / 2) * 2 * 2;
409
410 u_size + uv_size
411 }
412 DecodedFormat::I444 => (width * height) * 3,
413 DecodedFormat::I010 | DecodedFormat::I012 => {
414 decoded_frame_size(DecodedFormat::I420, width, height) * 2
415 }
416 DecodedFormat::I210 | DecodedFormat::I212 => {
417 let u_size = width * height * 2;
418 let uv_size = ((width + 1) / 2) * ((height + 1) / 2) * 2 * 2;
420
421 u_size + uv_size
422 }
423 DecodedFormat::I410 | DecodedFormat::I412 => (width * height * 2) * 3,
424 DecodedFormat::MM21 => panic!("Unable to convert to MM21"),
425 }
426}
427
428#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
430pub enum BlockingMode {
431 Blocking,
432 #[default]
433 NonBlocking,
434}
435
436#[cfg(test)]
437mod tests {
438 use super::Fourcc;
439
440 const NV12_FOURCC: u32 = 0x3231564E;
441
442 #[test]
443 fn fourcc_u32() {
444 let fourcc = Fourcc::from(NV12_FOURCC);
445 let value: u32 = fourcc.into();
446 assert_eq!(value, NV12_FOURCC);
447 }
448
449 #[test]
450 fn fourcc_u8_4() {
451 let fourcc = Fourcc::from(NV12_FOURCC);
452 let value: [u8; 4] = fourcc.into();
453 assert_eq!(value, *b"NV12");
454 }
455
456 #[test]
457 fn fourcc_display() {
458 let fourcc = Fourcc::from(NV12_FOURCC);
459 assert_eq!(fourcc.to_string(), "NV12");
460 }
461
462 #[test]
463 fn fourcc_debug() {
464 let fourcc = Fourcc::from(NV12_FOURCC);
465 assert_eq!(format!("{:?}", fourcc), "0x3231564e (NV12)");
466 }
467}