libcamera/
pixel_format.rs

1use std::{ffi::CStr, ptr::NonNull};
2
3use drm_fourcc::{DrmFormat, DrmFourcc, DrmModifier};
4use libcamera_sys::*;
5
6/// Represents `libcamera::PixelFormat`, which itself is a pair of fourcc code and u64 modifier as defined in `libdrm`.
7#[derive(Clone, Copy)]
8pub struct PixelFormat(pub(crate) libcamera_pixel_format_t);
9
10impl PixelFormat {
11    /// Constructs new [PixelFormat] from given fourcc code and modifier.
12    ///
13    /// # Examples
14    ///
15    /// ```rust
16    /// use libcamera::pixel_format::PixelFormat;
17    /// // Constructs MJPEG pixel format
18    /// const PIXEL_FORMAT_MJPEG: PixelFormat =
19    ///     PixelFormat::new(u32::from_le_bytes([b'M', b'J', b'P', b'G']), 0);
20    /// ```
21    pub const fn new(fourcc: u32, modifier: u64) -> Self {
22        Self(libcamera_pixel_format_t { fourcc, modifier })
23    }
24
25    pub fn fourcc(&self) -> u32 {
26        self.0.fourcc
27    }
28
29    pub fn set_fourcc(&mut self, fourcc: u32) {
30        self.0.fourcc = fourcc;
31    }
32
33    pub fn modifier(&self) -> u64 {
34        self.0.modifier
35    }
36
37    pub fn set_modifier(&mut self, modifier: u64) {
38        self.0.modifier = modifier;
39    }
40}
41
42impl PartialEq for PixelFormat {
43    fn eq(&self, other: &Self) -> bool {
44        self.0.fourcc.eq(&other.0.fourcc) && self.0.modifier.eq(&other.0.modifier)
45    }
46}
47
48impl Eq for PixelFormat {}
49
50impl core::fmt::Debug for PixelFormat {
51    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
52        let ptr = unsafe { libcamera_pixel_format_str(&self.0) };
53        let out = unsafe { CStr::from_ptr(ptr) }.to_str().unwrap();
54        f.write_str(out)?;
55        unsafe { libc::free(ptr.cast()) };
56        Ok(())
57    }
58}
59
60impl TryFrom<PixelFormat> for DrmFormat {
61    type Error = drm_fourcc::UnrecognizedFourcc;
62
63    fn try_from(value: PixelFormat) -> Result<Self, Self::Error> {
64        let code = DrmFourcc::try_from(value.0.fourcc)?;
65        let modifier = DrmModifier::from(value.0.modifier);
66        Ok(DrmFormat { code, modifier })
67    }
68}
69
70impl From<DrmFormat> for PixelFormat {
71    fn from(f: DrmFormat) -> Self {
72        PixelFormat::new(f.code as u32, f.modifier.into())
73    }
74}
75
76/// Vector of [PixelFormat]
77pub struct PixelFormats {
78    ptr: NonNull<libcamera_pixel_formats_t>,
79}
80
81impl PixelFormats {
82    pub(crate) unsafe fn from_ptr(ptr: NonNull<libcamera_pixel_formats_t>) -> Self {
83        Self { ptr }
84    }
85
86    /// Number of [PixelFormat]
87    pub fn len(&self) -> usize {
88        unsafe { libcamera_pixel_formats_size(self.ptr.as_ptr()) as _ }
89    }
90
91    /// Returns `true` if there there are no pixel formats
92    pub fn is_empty(&self) -> bool {
93        self.len() == 0
94    }
95
96    /// Returns [PixelFormat] at a given index.
97    ///
98    /// Return None if index is out of range.
99    pub fn get(&self, index: usize) -> Option<PixelFormat> {
100        if index >= self.len() {
101            None
102        } else {
103            Some(unsafe { self.get_unchecked(index) })
104        }
105    }
106
107    /// Returns [PixelFormat] at a given index without checking bounds.
108    ///
109    /// # Safety
110    ///
111    /// `index` must be less than [PixelFormats::len()].
112    pub unsafe fn get_unchecked(&self, index: usize) -> PixelFormat {
113        PixelFormat(unsafe { libcamera_pixel_formats_get(self.ptr.as_ptr(), index as _) })
114    }
115}
116
117impl<'d> IntoIterator for &'d PixelFormats {
118    type Item = PixelFormat;
119
120    type IntoIter = PixelFormatsIterator<'d>;
121
122    fn into_iter(self) -> Self::IntoIter {
123        PixelFormatsIterator {
124            formats: self,
125            index: 0,
126        }
127    }
128}
129
130impl Drop for PixelFormats {
131    fn drop(&mut self) {
132        unsafe { libcamera_pixel_formats_destroy(self.ptr.as_ptr()) }
133    }
134}
135
136pub struct PixelFormatsIterator<'d> {
137    formats: &'d PixelFormats,
138    index: usize,
139}
140
141impl Iterator for PixelFormatsIterator<'_> {
142    type Item = PixelFormat;
143
144    fn next(&mut self) -> Option<Self::Item> {
145        if let Some(next) = self.formats.get(self.index) {
146            self.index += 1;
147            Some(next)
148        } else {
149            None
150        }
151    }
152}