1use std::{marker::PhantomData, ptr::NonNull};
2
3use libcamera_sys::*;
4use num_enum::{IntoPrimitive, TryFromPrimitive};
5
6use crate::utils::Immutable;
7
8#[derive(Debug, Clone, Copy, Eq, PartialEq, TryFromPrimitive, IntoPrimitive)]
9#[repr(u32)]
10pub enum FrameMetadataStatus {
11 Success = libcamera_frame_metadata_status::LIBCAMERA_FRAME_METADATA_STATUS_SUCCESS,
12 Error = libcamera_frame_metadata_status::LIBCAMERA_FRAME_METADATA_STATUS_ERROR,
13 Cancelled = libcamera_frame_metadata_status::LIBCAMERA_FRAME_METADATA_STATUS_CANCELLED,
14}
15
16pub type FrameMetadataPlane = libcamera_frame_metadata_plane_t;
17
18pub struct FrameMetadataPlanes {
19 pub(crate) ptr: NonNull<libcamera_frame_metadata_planes_t>,
20}
21
22impl FrameMetadataPlanes {
23 pub(crate) unsafe fn from_ptr(ptr: NonNull<libcamera_frame_metadata_planes_t>) -> Self {
24 Self { ptr }
25 }
26
27 pub fn len(&self) -> usize {
31 unsafe { libcamera_frame_metadata_planes_size(self.ptr.as_ptr()) as _ }
32 }
33
34 pub fn is_empty(&self) -> bool {
36 self.len() == 0
37 }
38
39 pub fn get(&self, index: usize) -> Option<FrameMetadataPlane> {
43 if index >= self.len() {
44 None
45 } else {
46 Some(unsafe { libcamera_frame_metadata_planes_at(self.ptr.as_ptr(), index as _).read() })
47 }
48 }
49}
50
51impl core::fmt::Debug for FrameMetadataPlanes {
52 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
53 let mut list = f.debug_list();
54 for plane in self.into_iter() {
55 list.entry(&plane);
56 }
57 list.finish()
58 }
59}
60
61impl Drop for FrameMetadataPlanes {
62 fn drop(&mut self) {
63 unsafe { libcamera_frame_metadata_planes_destroy(self.ptr.as_ptr()) }
64 }
65}
66
67impl<'d> IntoIterator for &'d FrameMetadataPlanes {
68 type Item = FrameMetadataPlane;
69
70 type IntoIter = FrameMetadataPlanesIterator<'d>;
71
72 fn into_iter(self) -> Self::IntoIter {
73 FrameMetadataPlanesIterator { planes: self, index: 0 }
74 }
75}
76
77pub struct FrameMetadataPlanesIterator<'d> {
78 planes: &'d FrameMetadataPlanes,
79 index: usize,
80}
81
82impl Iterator for FrameMetadataPlanesIterator<'_> {
83 type Item = FrameMetadataPlane;
84
85 fn next(&mut self) -> Option<Self::Item> {
86 if let Some(plane) = self.planes.get(self.index) {
87 self.index += 1;
88 Some(plane)
89 } else {
90 None
91 }
92 }
93}
94
95pub struct FrameMetadataRef<'d> {
96 pub(crate) ptr: NonNull<libcamera_frame_metadata_t>,
97 _phantom: PhantomData<&'d ()>,
98}
99
100impl FrameMetadataRef<'_> {
101 pub(crate) unsafe fn from_ptr(ptr: NonNull<libcamera_frame_metadata_t>) -> Self {
102 Self {
103 ptr,
104 _phantom: Default::default(),
105 }
106 }
107
108 pub fn status(&self) -> FrameMetadataStatus {
109 FrameMetadataStatus::try_from(unsafe { libcamera_frame_metadata_status(self.ptr.as_ptr()) }).unwrap()
110 }
111
112 pub fn sequence(&self) -> u32 {
113 unsafe { libcamera_frame_metadata_sequence(self.ptr.as_ptr()) }
114 }
115
116 pub fn timestamp(&self) -> u64 {
117 unsafe { libcamera_frame_metadata_timestamp(self.ptr.as_ptr()) }
118 }
119
120 pub fn planes(&self) -> FrameMetadataPlanes {
121 unsafe {
122 FrameMetadataPlanes::from_ptr(NonNull::new(libcamera_frame_metadata_planes(self.ptr.as_ptr())).unwrap())
123 }
124 }
125}
126
127impl core::fmt::Debug for FrameMetadataRef<'_> {
128 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
129 f.debug_struct("FrameMetadataRef")
130 .field("status", &self.status())
131 .field("sequence", &self.sequence())
132 .field("timestamp", &self.timestamp())
133 .field("planes", &self.planes())
134 .finish()
135 }
136}
137
138pub struct FrameBufferPlaneRef<'d> {
139 pub(crate) ptr: NonNull<libcamera_framebuffer_plane_t>,
140 _phantom: PhantomData<&'d ()>,
141}
142
143impl FrameBufferPlaneRef<'_> {
144 pub(crate) unsafe fn from_ptr(ptr: NonNull<libcamera_framebuffer_plane_t>) -> Self {
145 Self {
146 ptr,
147 _phantom: Default::default(),
148 }
149 }
150
151 pub fn fd(&self) -> i32 {
155 unsafe { libcamera_framebuffer_plane_fd(self.ptr.as_ptr()) }
156 }
157
158 pub fn offset(&self) -> Option<usize> {
160 if unsafe { libcamera_framebuffer_plane_offset_valid(self.ptr.as_ptr()) } {
161 Some(unsafe { libcamera_framebuffer_plane_offset(self.ptr.as_ptr()) as _ })
162 } else {
163 None
164 }
165 }
166
167 pub fn len(&self) -> usize {
169 unsafe { libcamera_framebuffer_plane_length(self.ptr.as_ptr()) as _ }
170 }
171
172 pub fn is_empty(&self) -> bool {
174 self.len() == 0
175 }
176}
177
178impl core::fmt::Debug for FrameBufferPlaneRef<'_> {
179 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
180 f.debug_struct("FrameBufferPlaneRef")
181 .field("fd", &self.fd())
182 .field("offset", &self.offset())
183 .field("len", &self.len())
184 .finish()
185 }
186}
187
188pub struct FrameBufferPlanesRef<'d> {
189 pub(crate) ptr: NonNull<libcamera_framebuffer_planes_t>,
190 _phantom: PhantomData<&'d ()>,
191}
192
193impl FrameBufferPlanesRef<'_> {
194 pub(crate) unsafe fn from_ptr(ptr: NonNull<libcamera_framebuffer_planes_t>) -> Self {
195 Self {
196 ptr,
197 _phantom: Default::default(),
198 }
199 }
200
201 pub fn len(&self) -> usize {
203 unsafe { libcamera_framebuffer_planes_size(self.ptr.as_ptr()) as _ }
204 }
205
206 pub fn is_empty(&self) -> bool {
208 self.len() == 0
209 }
210
211 pub fn get(&self, index: usize) -> Option<Immutable<FrameBufferPlaneRef<'_>>> {
213 if index >= self.len() {
214 None
215 } else {
216 Some(Immutable(unsafe {
217 FrameBufferPlaneRef::from_ptr(
218 NonNull::new(libcamera_framebuffer_planes_at(self.ptr.as_ptr(), index as _)).unwrap(),
219 )
220 }))
221 }
222 }
223}
224
225impl core::fmt::Debug for FrameBufferPlanesRef<'_> {
226 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
227 let mut list = f.debug_list();
228 for plane in self.into_iter() {
229 list.entry(&plane);
230 }
231 list.finish()
232 }
233}
234
235impl<'d> IntoIterator for &'d FrameBufferPlanesRef<'d> {
236 type Item = Immutable<FrameBufferPlaneRef<'d>>;
237
238 type IntoIter = FrameBufferPlanesRefIterator<'d>;
239
240 fn into_iter(self) -> Self::IntoIter {
241 FrameBufferPlanesRefIterator { planes: self, index: 0 }
242 }
243}
244
245pub struct FrameBufferPlanesRefIterator<'d> {
246 planes: &'d FrameBufferPlanesRef<'d>,
247 index: usize,
248}
249
250impl<'d> Iterator for FrameBufferPlanesRefIterator<'d> {
251 type Item = Immutable<FrameBufferPlaneRef<'d>>;
252
253 fn next(&mut self) -> Option<Self::Item> {
254 if let Some(plane) = self.planes.get(self.index) {
255 self.index += 1;
256 Some(plane)
257 } else {
258 None
259 }
260 }
261}
262
263pub trait AsFrameBuffer: Send {
264 unsafe fn ptr(&self) -> NonNull<libcamera_framebuffer_t>;
273
274 fn metadata(&self) -> Option<Immutable<FrameMetadataRef<'_>>> {
278 let ptr = NonNull::new(unsafe { libcamera_framebuffer_metadata(self.ptr().as_ptr()) }.cast_mut()).unwrap();
279 if unsafe { libcamera_frame_metadata_status(ptr.as_ptr()) } != u32::MAX {
280 Some(unsafe { Immutable(FrameMetadataRef::from_ptr(ptr)) })
281 } else {
282 None
283 }
284 }
285
286 fn planes(&self) -> Immutable<FrameBufferPlanesRef<'_>> {
288 unsafe {
289 Immutable(FrameBufferPlanesRef::from_ptr(
290 NonNull::new(libcamera_framebuffer_planes(self.ptr().as_ptr()).cast_mut()).unwrap(),
291 ))
292 }
293 }
294}