1pub mod bitstream_utils;
24pub mod codec;
25
26#[cfg(feature = "backend")]
27pub mod backend;
28#[cfg(feature = "backend")]
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 H265,
274 VP8,
275 VP9,
276 AV1,
277}
278
279impl FromStr for EncodedFormat {
280 type Err = &'static str;
281
282 fn from_str(s: &str) -> Result<Self, Self::Err> {
283 match s {
284 "h264" | "H264" => Ok(EncodedFormat::H264),
285 "h265" | "H265" => Ok(EncodedFormat::H265),
286 "vp8" | "VP8" => Ok(EncodedFormat::VP8),
287 "vp9" | "VP9" => Ok(EncodedFormat::VP9),
288 "av1" | "AV1" => Ok(EncodedFormat::AV1),
289 _ => Err("unrecognized input format. Valid values: h264, h265, vp8, vp9, av1"),
290 }
291 }
292}
293
294impl From<Fourcc> for EncodedFormat {
295 fn from(fourcc: Fourcc) -> EncodedFormat {
296 match fourcc.to_string().as_str() {
297 "H264" => EncodedFormat::H264,
298 "HEVC" => EncodedFormat::H265,
299 "VP80" => EncodedFormat::VP8,
300 "VP90" => EncodedFormat::VP9,
301 "AV1F" => EncodedFormat::AV1,
302 _ => todo!("Fourcc {} not yet supported", fourcc),
303 }
304 }
305}
306
307impl From<EncodedFormat> for Fourcc {
308 fn from(format: EncodedFormat) -> Fourcc {
309 match format {
310 EncodedFormat::H264 => Fourcc::from(b"H264"),
311 EncodedFormat::H265 => Fourcc::from(b"HEVC"),
312 EncodedFormat::VP8 => Fourcc::from(b"VP80"),
313 EncodedFormat::VP9 => Fourcc::from(b"VP90"),
314 EncodedFormat::AV1 => Fourcc::from(b"AV1F"),
315 }
316 }
317}
318
319#[derive(Debug, Default, Clone, PartialEq)]
321pub struct PlaneLayout {
322 pub buffer_index: usize,
324 pub offset: usize,
326 pub stride: usize,
328}
329
330#[derive(Debug, Default, Clone, PartialEq)]
335pub struct FrameLayout {
336 pub format: (Fourcc, u64),
341 pub size: Resolution,
343 pub planes: Vec<PlaneLayout>,
345}
346
347#[macro_export]
368macro_rules! multiple_desc_type {
369 (enum $s:ident { $($v:ident($t:ty),)* } ) => {
370 pub enum $s {
371 $($v($t),)*
372 }
373
374 #[cfg(feature = "vaapi")]
375 impl libva::SurfaceMemoryDescriptor for $s {
376 fn add_attrs(&mut self, attrs: &mut Vec<libva::VASurfaceAttrib>) -> Option<Box<dyn std::any::Any>> {
377 match self {
378 $($s::$v(desc) => desc.add_attrs(attrs),)*
379 }
380 }
381 }
382 }
383}
384
385pub fn decoded_frame_size(format: DecodedFormat, width: usize, height: usize) -> usize {
389 match format {
390 DecodedFormat::I420 | DecodedFormat::NV12 => {
391 let u_size = width * height;
392 let uv_size = ((width + 1) / 2) * ((height + 1) / 2) * 2;
394
395 u_size + uv_size
396 }
397 DecodedFormat::I422 => {
398 let u_size = width * height;
399 let uv_size = ((width + 1) / 2) * ((height + 1) / 2) * 2 * 2;
401
402 u_size + uv_size
403 }
404 DecodedFormat::I444 => (width * height) * 3,
405 DecodedFormat::I010 | DecodedFormat::I012 => {
406 decoded_frame_size(DecodedFormat::I420, width, height) * 2
407 }
408 DecodedFormat::I210 | DecodedFormat::I212 => {
409 let u_size = width * height * 2;
410 let uv_size = ((width + 1) / 2) * ((height + 1) / 2) * 2 * 2;
412
413 u_size + uv_size
414 }
415 DecodedFormat::I410 | DecodedFormat::I412 => (width * height * 2) * 3,
416 DecodedFormat::MM21 => panic!("Unable to convert to MM21"),
417 }
418}
419
420#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
422pub enum BlockingMode {
423 Blocking,
424 #[default]
425 NonBlocking,
426}
427
428#[cfg(test)]
429mod tests {
430 use super::Fourcc;
431
432 const NV12_FOURCC: u32 = 0x3231564E;
433
434 #[test]
435 fn fourcc_u32() {
436 let fourcc = Fourcc::from(NV12_FOURCC);
437 let value: u32 = fourcc.into();
438 assert_eq!(value, NV12_FOURCC);
439 }
440
441 #[test]
442 fn fourcc_u8_4() {
443 let fourcc = Fourcc::from(NV12_FOURCC);
444 let value: [u8; 4] = fourcc.into();
445 assert_eq!(value, *b"NV12");
446 }
447
448 #[test]
449 fn fourcc_display() {
450 let fourcc = Fourcc::from(NV12_FOURCC);
451 assert_eq!(fourcc.to_string(), "NV12");
452 }
453
454 #[test]
455 fn fourcc_debug() {
456 let fourcc = Fourcc::from(NV12_FOURCC);
457 assert_eq!(format!("{:?}", fourcc), "0x3231564e (NV12)");
458 }
459}