1use std::{marker::PhantomData, ptr::NonNull};
2
3use libcamera_sys::*;
4
5use crate::{
6 color_space::ColorSpace,
7 geometry::{Size, SizeRange},
8 pixel_format::{PixelFormat, PixelFormats},
9 utils::Immutable,
10};
11
12#[derive(Debug, Clone, Copy)]
16pub enum StreamRole {
17 Raw,
18 StillCapture,
19 VideoRecording,
20 ViewFinder,
21}
22
23impl TryFrom<libcamera_stream_role::Type> for StreamRole {
24 type Error = ();
25
26 fn try_from(value: libcamera_stream_role::Type) -> Result<Self, Self::Error> {
27 match value {
28 libcamera_stream_role::LIBCAMERA_STREAM_ROLE_RAW => Ok(StreamRole::Raw),
29 libcamera_stream_role::LIBCAMERA_STREAM_ROLE_STILL_CAPTURE => Ok(StreamRole::StillCapture),
30 libcamera_stream_role::LIBCAMERA_STREAM_ROLE_VIDEO_RECORDING => Ok(StreamRole::VideoRecording),
31 libcamera_stream_role::LIBCAMERA_STREAM_ROLE_VIEW_FINDER => Ok(StreamRole::ViewFinder),
32 _ => Err(()),
33 }
34 }
35}
36
37impl From<StreamRole> for libcamera_stream_role::Type {
38 fn from(role: StreamRole) -> Self {
39 match role {
40 StreamRole::Raw => libcamera_stream_role::LIBCAMERA_STREAM_ROLE_RAW,
41 StreamRole::StillCapture => libcamera_stream_role::LIBCAMERA_STREAM_ROLE_STILL_CAPTURE,
42 StreamRole::VideoRecording => libcamera_stream_role::LIBCAMERA_STREAM_ROLE_VIDEO_RECORDING,
43 StreamRole::ViewFinder => libcamera_stream_role::LIBCAMERA_STREAM_ROLE_VIEW_FINDER,
44 }
45 }
46}
47
48pub struct StreamFormatsRef<'d> {
50 ptr: NonNull<libcamera_stream_formats_t>,
51 _phantom: PhantomData<&'d ()>,
52}
53
54impl StreamFormatsRef<'_> {
55 pub(crate) unsafe fn from_ptr(ptr: NonNull<libcamera_stream_formats_t>) -> Self {
56 Self {
57 ptr,
58 _phantom: Default::default(),
59 }
60 }
61
62 pub fn pixel_formats(&self) -> Immutable<PixelFormats> {
64 Immutable(unsafe {
65 PixelFormats::from_ptr(NonNull::new(libcamera_stream_formats_pixel_formats(self.ptr.as_ptr())).unwrap())
66 })
67 }
68
69 pub fn sizes(&self, pixel_format: PixelFormat) -> Vec<Size> {
71 let sizes = unsafe { libcamera_stream_formats_sizes(self.ptr.as_ptr(), &pixel_format.0) };
72 let len = unsafe { libcamera_sizes_size(sizes) };
73
74 let out = (0..len)
75 .map(|i| Size::from(unsafe { *libcamera_sizes_at(sizes, i as _) }))
76 .collect();
77
78 unsafe { libcamera_sizes_destroy(sizes) };
79
80 out
81 }
82
83 pub fn range(&self, pixel_format: PixelFormat) -> SizeRange {
85 SizeRange::from(unsafe { libcamera_stream_formats_range(self.ptr.as_ptr(), &pixel_format.0) })
86 }
87}
88
89impl core::fmt::Debug for StreamFormatsRef<'_> {
90 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
91 let mut map = f.debug_map();
92 for pixel_format in self.pixel_formats().into_iter() {
93 map.entry(&pixel_format, &self.sizes(pixel_format));
94 }
95 map.finish()
96 }
97}
98
99pub struct StreamConfigurationRef<'d> {
100 ptr: NonNull<libcamera_stream_configuration_t>,
101 _phantom: PhantomData<&'d ()>,
102}
103
104impl StreamConfigurationRef<'_> {
105 pub(crate) unsafe fn from_ptr(ptr: NonNull<libcamera_stream_configuration_t>) -> Self {
106 Self {
107 ptr,
108 _phantom: Default::default(),
109 }
110 }
111
112 pub(crate) fn as_ptr(&self) -> *const libcamera_stream_configuration_t {
113 self.ptr.as_ptr()
114 }
115
116 pub fn get_pixel_format(&self) -> PixelFormat {
117 PixelFormat(unsafe { self.ptr.as_ref() }.pixel_format)
118 }
119
120 pub fn set_pixel_format(&mut self, pixel_format: PixelFormat) {
121 unsafe { self.ptr.as_mut() }.pixel_format = pixel_format.0;
122 }
123
124 pub fn get_size(&self) -> Size {
125 unsafe { self.ptr.as_ref() }.size.into()
126 }
127
128 pub fn set_size(&mut self, size: Size) {
129 unsafe { self.ptr.as_mut() }.size = size.into()
130 }
131
132 pub fn get_stride(&self) -> u32 {
133 unsafe { self.ptr.as_ref() }.stride
134 }
135
136 pub fn set_stride(&mut self, stride: u32) {
138 unsafe { self.ptr.as_mut() }.stride = stride
139 }
140
141 pub fn get_frame_size(&self) -> u32 {
142 unsafe { self.ptr.as_ref() }.frame_size
143 }
144
145 pub fn set_frame_size(&mut self, frame_size: u32) {
147 unsafe { self.ptr.as_mut() }.frame_size = frame_size
148 }
149
150 pub fn get_buffer_count(&self) -> u32 {
151 unsafe { self.ptr.as_ref() }.buffer_count
152 }
153
154 pub fn set_buffer_count(&mut self, buffer_count: u32) {
155 unsafe { self.ptr.as_mut() }.buffer_count = buffer_count;
156 }
157
158 pub fn get_color_space(&self) -> Option<ColorSpace> {
160 if unsafe { libcamera_stream_configuration_has_color_space(self.ptr.as_ptr()) } {
161 Some(ColorSpace::from(unsafe {
162 libcamera_stream_configuration_get_color_space(self.ptr.as_ptr())
163 }))
164 } else {
165 None
166 }
167 }
168
169 pub fn set_color_space(&mut self, color_space: Option<ColorSpace>) {
171 unsafe {
172 match color_space {
173 Some(cs) => libcamera_stream_configuration_set_color_space(self.ptr.as_ptr(), &cs.into()),
174 None => libcamera_stream_configuration_set_color_space(self.ptr.as_ptr(), core::ptr::null()),
175 }
176 }
177 }
178
179 pub fn stream(&self) -> Option<Stream> {
185 let stream = unsafe { libcamera_stream_configuration_stream(self.ptr.as_ptr()) };
186 NonNull::new(stream).map(|p| unsafe { Stream::from_ptr(p) })
189 }
190
191 pub fn formats(&self) -> StreamFormatsRef<'_> {
193 unsafe {
194 StreamFormatsRef::from_ptr(
195 NonNull::new(libcamera_stream_configuration_formats(self.ptr.as_ptr()).cast_mut()).unwrap(),
196 )
197 }
198 }
199
200 pub fn to_string_repr(&self) -> String {
202 unsafe {
203 let ptr = libcamera_stream_configuration_to_string(self.ptr.as_ptr());
204 if ptr.is_null() {
205 return String::new();
206 }
207 let s = std::ffi::CStr::from_ptr(ptr).to_string_lossy().into_owned();
208 libc::free(ptr.cast());
209 s
210 }
211 }
212}
213
214impl core::fmt::Debug for StreamConfigurationRef<'_> {
215 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
216 f.debug_struct("StreamConfigurationRef")
217 .field("pixel_format", &self.get_pixel_format())
218 .field("size", &self.get_size())
219 .field("stride", &self.get_stride())
220 .field("frame_size", &self.get_frame_size())
221 .field("buffer_count", &self.get_buffer_count())
222 .field("color_space", &self.get_color_space())
223 .finish()
224 }
225}
226
227#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)]
231pub struct Stream {
232 pub(crate) ptr: NonNull<libcamera_stream_t>,
237}
238
239impl Stream {
240 pub(crate) unsafe fn from_ptr(ptr: NonNull<libcamera_stream_t>) -> Self {
241 Self { ptr }
242 }
243
244 pub fn configuration(&self) -> Option<Immutable<StreamConfigurationRef<'_>>> {
246 let cfg = unsafe { libcamera_stream_get_configuration(self.ptr.as_ptr()) };
247 NonNull::new(cfg as *mut libcamera_stream_configuration_t)
248 .map(|p| Immutable(unsafe { StreamConfigurationRef::from_ptr(p) }))
249 }
250}
251
252unsafe impl Send for Stream {}