libcamera/
framebuffer_allocator.rs1use std::{
2 collections::HashMap,
3 io,
4 ptr::NonNull,
5 sync::{Arc, Mutex},
6};
7
8use libcamera_sys::*;
9
10use crate::{camera::Camera, framebuffer::AsFrameBuffer, stream::Stream};
11
12struct FrameBufferAllocatorInstance {
15 ptr: NonNull<libcamera_framebuffer_allocator_t>,
16 streams: HashMap<usize, StreamAllocState>,
18}
19
20#[derive(Debug)]
21struct StreamAllocState {
22 count: usize,
23 free_requested: bool,
24}
25
26unsafe impl Send for FrameBufferAllocatorInstance {}
27
28impl Drop for FrameBufferAllocatorInstance {
29 fn drop(&mut self) {
30 for (stream_ptr, _) in self.streams.drain() {
32 unsafe { libcamera_framebuffer_allocator_free(self.ptr.as_ptr(), stream_ptr as *mut _) };
33 }
34
35 unsafe { libcamera_framebuffer_allocator_destroy(self.ptr.as_ptr()) }
36 }
37}
38
39pub struct FrameBufferAllocator {
40 inner: Arc<Mutex<FrameBufferAllocatorInstance>>,
41}
42
43impl FrameBufferAllocator {
44 pub fn new(cam: &Camera<'_>) -> Self {
45 Self {
46 inner: Arc::new(Mutex::new(FrameBufferAllocatorInstance {
47 ptr: NonNull::new(unsafe { libcamera_framebuffer_allocator_create(cam.ptr.as_ptr()) }).unwrap(),
48 streams: HashMap::new(),
49 })),
50 }
51 }
52
53 pub fn alloc(&mut self, stream: &Stream) -> io::Result<Vec<FrameBuffer>> {
56 let mut inner = self.inner.lock().unwrap();
57 let key = stream.ptr.as_ptr() as usize;
58 if inner.streams.contains_key(&key) {
59 return Err(io::Error::new(
60 io::ErrorKind::AlreadyExists,
61 "buffers already allocated for this stream",
62 ));
63 }
64
65 let ret = unsafe { libcamera_framebuffer_allocator_allocate(inner.ptr.as_ptr(), stream.ptr.as_ptr()) };
66 if ret < 0 {
67 Err(io::Error::from_raw_os_error(-ret))
68 } else {
69 let buffers = unsafe { libcamera_framebuffer_allocator_buffers(inner.ptr.as_ptr(), stream.ptr.as_ptr()) };
70
71 let len = unsafe { libcamera_framebuffer_list_size(buffers) };
72
73 inner.streams.insert(
74 key,
75 StreamAllocState {
76 count: len,
77 free_requested: false,
78 },
79 );
80
81 Ok((0..len)
82 .map(|i| unsafe { libcamera_framebuffer_list_get(buffers, i) })
83 .map(|ptr| NonNull::new(ptr.cast_mut()).unwrap())
84 .map(|ptr| {
85 unsafe {
90 libcamera_framebuffer_metadata(ptr.as_ptr())
91 .cast_mut()
92 .cast::<u32>()
93 .write(u32::MAX)
94 };
95
96 FrameBuffer {
97 ptr,
98 stream_key: key,
99 _alloc: self.inner.clone(),
100 }
101 })
102 .collect())
103 }
104 }
105
106 pub fn free(&mut self, stream: &Stream) -> io::Result<()> {
108 let mut inner = self.inner.lock().unwrap();
109 let key = stream.ptr.as_ptr() as usize;
110 let state = inner
111 .streams
112 .get_mut(&key)
113 .ok_or_else(|| io::Error::new(io::ErrorKind::NotFound, "no buffers allocated for stream"))?;
114
115 state.free_requested = true;
116 if state.count == 0 {
117 let ret = unsafe { libcamera_framebuffer_allocator_free(inner.ptr.as_ptr(), stream.ptr.as_ptr()) };
118 if ret < 0 {
119 return Err(io::Error::from_raw_os_error(-ret));
120 }
121 inner.streams.remove(&key);
122 }
123 Ok(())
124 }
125
126 pub fn allocated(&self) -> bool {
128 let inner = self.inner.lock().unwrap();
129 unsafe { libcamera_framebuffer_allocator_allocated(inner.ptr.as_ptr()) }
130 }
131}
132
133pub struct FrameBuffer {
134 ptr: NonNull<libcamera_framebuffer_t>,
135 stream_key: usize,
136 _alloc: Arc<Mutex<FrameBufferAllocatorInstance>>,
137}
138
139impl core::fmt::Debug for FrameBuffer {
140 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
141 f.debug_struct("FrameBuffer")
142 .field("metadata", &self.metadata())
143 .field("planes", &self.planes())
144 .finish()
145 }
146}
147
148unsafe impl Send for FrameBuffer {}
149
150impl AsFrameBuffer for FrameBuffer {
151 unsafe fn ptr(&self) -> NonNull<libcamera_framebuffer_t> {
152 self.ptr
153 }
154}
155
156impl FrameBuffer {
157 pub fn cookie(&self) -> u64 {
159 unsafe { libcamera_framebuffer_cookie(self.ptr.as_ptr()) }
160 }
161
162 pub fn set_cookie(&self, cookie: u64) {
164 unsafe { libcamera_framebuffer_set_cookie(self.ptr.as_ptr(), cookie) }
165 }
166}
167
168impl Drop for FrameBuffer {
169 fn drop(&mut self) {
170 let mut inner = self._alloc.lock().unwrap();
171 if let Some(state) = inner.streams.get_mut(&self.stream_key) {
172 if state.count > 0 {
173 state.count -= 1;
174 }
175 if state.count == 0 && state.free_requested {
176 unsafe {
177 let _ = libcamera_framebuffer_allocator_free(inner.ptr.as_ptr(), self.stream_key as *mut _);
178 }
179 inner.streams.remove(&self.stream_key);
180 }
181 }
182 }
183}