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