libcamera/
request.rs

1#![allow(clippy::manual_strip)]
2
3use std::{any::Any, collections::HashMap, io, ptr::NonNull};
4
5use bitflags::bitflags;
6use libcamera_sys::*;
7
8use crate::{control::ControlList, framebuffer::AsFrameBuffer, stream::Stream};
9
10/// Status of [Request]
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub enum RequestStatus {
13    /// Request is ready to be executed by [ActiveCamera::queue_request()](crate::camera::ActiveCamera::queue_request)
14    Pending,
15    /// Request was executed successfully
16    Complete,
17    /// Request was cancelled, most likely due to call to [ActiveCamera::stop()](crate::camera::ActiveCamera::stop)
18    Cancelled,
19}
20
21impl TryFrom<libcamera_request_status_t> for RequestStatus {
22    type Error = String;
23
24    fn try_from(value: libcamera_request_status_t) -> Result<Self, Self::Error> {
25        match value {
26            libcamera_request_status::LIBCAMERA_REQUEST_STATUS_PENDING => Ok(Self::Pending),
27            libcamera_request_status::LIBCAMERA_REQUEST_STATUS_COMPLETE => Ok(Self::Complete),
28            libcamera_request_status::LIBCAMERA_REQUEST_STATUS_CANCELLED => Ok(Self::Cancelled),
29            _ => Err(format!("Unknown libcamera_request_status: {}", value)),
30        }
31    }
32}
33
34bitflags! {
35    /// Flags to control the behaviour of [Request::reuse()].
36    pub struct ReuseFlag: u32 {
37        /// Reuse the buffers that were previously added by [Request::add_buffer()].
38        const REUSE_BUFFERS = 1 << 0;
39    }
40}
41
42/// A camera capture request.
43///
44/// Capture requests are created by [ActiveCamera::create_request()](crate::camera::ActiveCamera::create_request)
45/// and scheduled for execution by [ActiveCamera::queue_request()](crate::camera::ActiveCamera::queue_request).
46/// Completed requests are returned by request completed callback (see
47/// [ActiveCamera::on_request_completed()](crate::camera::ActiveCamera::on_request_completed)) and can (should) be
48/// reused by calling [ActiveCamera::queue_request()](crate::camera::ActiveCamera::queue_request) again.
49pub struct Request {
50    pub(crate) ptr: NonNull<libcamera_request_t>,
51    buffers: HashMap<Stream, Box<dyn Any + 'static>>,
52}
53
54impl Request {
55    pub(crate) unsafe fn from_ptr(ptr: NonNull<libcamera_request_t>) -> Self {
56        Self {
57            ptr,
58            buffers: Default::default(),
59        }
60    }
61
62    /// Returns an immutable reference of request controls.
63    ///
64    /// See [controls](crate::controls) for available items.
65    pub fn controls(&self) -> &ControlList {
66        unsafe { ControlList::from_ptr(NonNull::new(libcamera_request_controls(self.ptr.as_ptr())).unwrap()) }
67    }
68
69    /// Returns a mutable reference of request controls.
70    ///
71    /// See [controls](crate::controls) for available items.
72    pub fn controls_mut(&mut self) -> &mut ControlList {
73        unsafe { ControlList::from_ptr(NonNull::new(libcamera_request_controls(self.ptr.as_ptr())).unwrap()) }
74    }
75
76    /// Returns request metadata, which contains information relevant to the request execution (i.e. capture timestamp).
77    ///
78    /// See [controls](crate::controls) for available items.
79    pub fn metadata(&self) -> &ControlList {
80        unsafe { ControlList::from_ptr(NonNull::new(libcamera_request_metadata(self.ptr.as_ptr())).unwrap()) }
81    }
82
83    /// Attaches framebuffer to the request.
84    ///
85    /// Buffers can only be attached once. To access framebuffer after executing request use [Self::buffer()] or
86    /// [Self::buffer_mut()].
87    pub fn add_buffer<T: AsFrameBuffer + Any>(&mut self, stream: &Stream, buffer: T) -> io::Result<()> {
88        let ret =
89            unsafe { libcamera_request_add_buffer(self.ptr.as_ptr(), stream.ptr.as_ptr(), buffer.ptr().as_ptr()) };
90        if ret < 0 {
91            Err(io::Error::from_raw_os_error(ret))
92        } else {
93            self.buffers.insert(*stream, Box::new(buffer));
94            Ok(())
95        }
96    }
97
98    /// Returns a reference to the buffer that was attached with [Self::add_buffer()].
99    ///
100    /// `T` must be equal to the type used in [Self::add_buffer()], otherwise this will return None.
101    pub fn buffer<T: 'static>(&self, stream: &Stream) -> Option<&T> {
102        self.buffers.get(stream).and_then(|b| b.downcast_ref())
103    }
104
105    /// Returns a mutable reference to the buffer that was attached with [Self::add_buffer()].
106    ///
107    /// `T` must be equal to the type used in [Self::add_buffer()], otherwise this will return None.
108    pub fn buffer_mut<T: 'static>(&mut self, stream: &Stream) -> Option<&mut T> {
109        self.buffers.get_mut(stream).and_then(|b| b.downcast_mut())
110    }
111
112    /// Returns auto-incrementing sequence number of the capture
113    pub fn sequence(&self) -> u32 {
114        unsafe { libcamera_request_sequence(self.ptr.as_ptr()) }
115    }
116
117    /// Returns request identifier that was provided in
118    /// [ActiveCamera::create_request()](crate::camera::ActiveCamera::create_request).
119    ///
120    /// Returns zero if cookie was not provided.
121    pub fn cookie(&self) -> u64 {
122        unsafe { libcamera_request_cookie(self.ptr.as_ptr()) }
123    }
124
125    /// Capture request status
126    pub fn status(&self) -> RequestStatus {
127        RequestStatus::try_from(unsafe { libcamera_request_status(self.ptr.as_ptr()) }).unwrap()
128    }
129
130    /// Reset the request for reuse.
131    ///
132    /// Reset the status and controls associated with the request, to allow it to be reused and requeued without
133    /// destruction. This function shall be called prior to queueing the request to the camera, in lieu of
134    /// constructing a new request. The application can reuse the buffers that were previously added to the request
135    /// via [Self::add_buffer()] by setting flags to [ReuseFlag::REUSE_BUFFERS].
136    pub fn reuse(&mut self, flags: ReuseFlag) {
137        unsafe { libcamera_request_reuse(self.ptr.as_ptr(), flags.bits()) }
138    }
139}
140
141impl core::fmt::Debug for Request {
142    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
143        f.debug_struct("Request")
144            .field("seq", &self.sequence())
145            .field("status", &self.status())
146            .field("cookie", &self.cookie())
147            .finish()
148    }
149}
150
151impl Drop for Request {
152    fn drop(&mut self) {
153        unsafe { libcamera_request_destroy(self.ptr.as_ptr()) }
154    }
155}
156
157unsafe impl Send for Request {}