libcamera/
stream.rs

1use std::{marker::PhantomData, ptr::NonNull};
2
3use libcamera_sys::*;
4
5use crate::{
6    geometry::{Size, SizeRange},
7    pixel_format::{PixelFormat, PixelFormats},
8    utils::Immutable,
9};
10
11/// Stream role hint for generating configuration.
12///
13/// Used in [Camera::generate_configuration()](crate::camera::Camera::generate_configuration).
14#[derive(Debug, Clone, Copy)]
15pub enum StreamRole {
16    Raw,
17    StillCapture,
18    VideoRecording,
19    ViewFinder,
20}
21
22impl TryFrom<libcamera_stream_role::Type> for StreamRole {
23    type Error = ();
24
25    fn try_from(value: libcamera_stream_role::Type) -> Result<Self, Self::Error> {
26        match value {
27            libcamera_stream_role::LIBCAMERA_STREAM_ROLE_RAW => Ok(StreamRole::Raw),
28            libcamera_stream_role::LIBCAMERA_STREAM_ROLE_STILL_CAPTURE => Ok(StreamRole::StillCapture),
29            libcamera_stream_role::LIBCAMERA_STREAM_ROLE_VIDEO_RECORDING => Ok(StreamRole::VideoRecording),
30            libcamera_stream_role::LIBCAMERA_STREAM_ROLE_VIEW_FINDER => Ok(StreamRole::ViewFinder),
31            _ => Err(()),
32        }
33    }
34}
35
36impl From<StreamRole> for libcamera_stream_role::Type {
37    fn from(role: StreamRole) -> Self {
38        match role {
39            StreamRole::Raw => libcamera_stream_role::LIBCAMERA_STREAM_ROLE_RAW,
40            StreamRole::StillCapture => libcamera_stream_role::LIBCAMERA_STREAM_ROLE_STILL_CAPTURE,
41            StreamRole::VideoRecording => libcamera_stream_role::LIBCAMERA_STREAM_ROLE_VIDEO_RECORDING,
42            StreamRole::ViewFinder => libcamera_stream_role::LIBCAMERA_STREAM_ROLE_VIEW_FINDER,
43        }
44    }
45}
46
47/// A list of available stream formats.
48pub struct StreamFormatsRef<'d> {
49    ptr: NonNull<libcamera_stream_formats_t>,
50    _phantom: PhantomData<&'d ()>,
51}
52
53impl StreamFormatsRef<'_> {
54    pub(crate) unsafe fn from_ptr(ptr: NonNull<libcamera_stream_formats_t>) -> Self {
55        Self {
56            ptr,
57            _phantom: Default::default(),
58        }
59    }
60
61    /// Returns all available [PixelFormat]s.
62    pub fn pixel_formats(&self) -> Immutable<PixelFormats> {
63        Immutable(unsafe {
64            PixelFormats::from_ptr(NonNull::new(libcamera_stream_formats_pixel_formats(self.ptr.as_ptr())).unwrap())
65        })
66    }
67
68    /// Returns all supported stream [Size]s for a given [PixelFormat].
69    pub fn sizes(&self, pixel_format: PixelFormat) -> Vec<Size> {
70        let sizes = unsafe { libcamera_stream_formats_sizes(self.ptr.as_ptr(), &pixel_format.0) };
71        let len = unsafe { libcamera_sizes_size(sizes) };
72
73        (0..len)
74            .map(|i| Size::from(unsafe { *libcamera_sizes_at(sizes, i as _) }))
75            .collect()
76    }
77
78    /// Returns a [SizeRange] of supported stream sizes for a given [PixelFormat].
79    pub fn range(&self, pixel_format: PixelFormat) -> SizeRange {
80        SizeRange::from(unsafe { libcamera_stream_formats_range(self.ptr.as_ptr(), &pixel_format.0) })
81    }
82}
83
84impl core::fmt::Debug for StreamFormatsRef<'_> {
85    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
86        let mut map = f.debug_map();
87        for pixel_format in self.pixel_formats().into_iter() {
88            map.entry(&pixel_format, &self.sizes(pixel_format));
89        }
90        map.finish()
91    }
92}
93
94pub struct StreamConfigurationRef<'d> {
95    ptr: NonNull<libcamera_stream_configuration_t>,
96    _phantom: PhantomData<&'d ()>,
97}
98
99impl StreamConfigurationRef<'_> {
100    pub(crate) unsafe fn from_ptr(ptr: NonNull<libcamera_stream_configuration_t>) -> Self {
101        Self {
102            ptr,
103            _phantom: Default::default(),
104        }
105    }
106
107    pub fn get_pixel_format(&self) -> PixelFormat {
108        PixelFormat(unsafe { self.ptr.as_ref() }.pixel_format)
109    }
110
111    pub fn set_pixel_format(&mut self, pixel_format: PixelFormat) {
112        unsafe { self.ptr.as_mut() }.pixel_format = pixel_format.0;
113    }
114
115    pub fn get_size(&self) -> Size {
116        unsafe { self.ptr.as_ref() }.size.into()
117    }
118
119    pub fn set_size(&mut self, size: Size) {
120        unsafe { self.ptr.as_mut() }.size = size.into()
121    }
122
123    pub fn get_stride(&self) -> u32 {
124        unsafe { self.ptr.as_ref() }.stride
125    }
126
127    pub fn set_stride(&mut self, stride: u32) {
128        unsafe { self.ptr.as_mut() }.stride = stride
129    }
130
131    pub fn get_frame_size(&self) -> u32 {
132        unsafe { self.ptr.as_ref() }.frame_size
133    }
134
135    pub fn set_frame_size(&mut self, frame_size: u32) {
136        unsafe { self.ptr.as_mut() }.frame_size = frame_size
137    }
138
139    pub fn get_buffer_count(&self) -> u32 {
140        unsafe { self.ptr.as_ref() }.buffer_count
141    }
142
143    pub fn set_buffer_count(&mut self, buffer_count: u32) {
144        unsafe { self.ptr.as_mut() }.buffer_count = buffer_count;
145    }
146
147    /// Returns initialized [Stream] for this configuration.
148    ///
149    /// Stream is only available once this configuration is applied with
150    /// [ActiveCamera::configure()](crate::camera::ActiveCamera::configure). It is invalidated if camera is
151    /// reconfigured.
152    pub fn stream(&self) -> Option<Stream> {
153        let stream = unsafe { libcamera_stream_configuration_stream(self.ptr.as_ptr()) };
154        // Stream is valid after camera->configure(), but might be invalidated after following reconfigurations.
155        // Unfortunatelly, it's hard to handle it with lifetimes so invalid StreamRef's are possible.
156        NonNull::new(stream).map(|p| unsafe { Stream::from_ptr(p) })
157    }
158
159    /// Returns a list of available stream formats for this configuration.
160    pub fn formats(&self) -> StreamFormatsRef<'_> {
161        unsafe {
162            StreamFormatsRef::from_ptr(
163                NonNull::new(libcamera_stream_configuration_formats(self.ptr.as_ptr()).cast_mut()).unwrap(),
164            )
165        }
166    }
167}
168
169impl core::fmt::Debug for StreamConfigurationRef<'_> {
170    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
171        f.debug_struct("StreamConfigurationRef")
172            .field("pixel_format", &self.get_pixel_format())
173            .field("size", &self.get_size())
174            .field("stride", &self.get_stride())
175            .field("frame_size", &self.get_frame_size())
176            .field("buffer_count", &self.get_buffer_count())
177            .finish()
178    }
179}
180
181/// Handle to a camera stream.
182///
183/// Obtained from [StreamConfigurationRef::stream()] and is valid as long as camera configuration is unchanged.
184#[derive(Clone, Copy, Hash, PartialEq, Eq)]
185pub struct Stream {
186    /// libcamera_stream_t is used as unique key across various libcamera structures
187    /// and adding a lifetime would be really inconvenient. Dangling pointer should not
188    /// cause any harm by itself as collection loopup will fail gracefully, however,
189    /// it is important to never dereference this pointer to obtain libcamera_stream_configuration_t.
190    pub(crate) ptr: NonNull<libcamera_stream_t>,
191}
192
193impl Stream {
194    pub(crate) unsafe fn from_ptr(ptr: NonNull<libcamera_stream_t>) -> Self {
195        Self { ptr }
196    }
197}
198
199unsafe impl Send for Stream {}