1 #![allow(non_camel_case_types)]
2
3 use log::{error, trace};
4 use std::{
5 collections::VecDeque,
6 os::{
7 fd::{AsFd, BorrowedFd},
8 raw::c_int,
9 unix::io::{AsRawFd, RawFd},
10 },
11 sync::{Arc, Mutex},
12 task::Wake,
13 };
14 use v4l2r::{
15 bindings,
16 device::{
17 poller::Waker,
18 queue::{
19 handles_provider::{GetSuitableBufferError, HandlesProvider},
20 qbuf::{
21 get_free::GetFreeCaptureBuffer, get_indexed::GetCaptureBufferByIndex,
22 CaptureQueueableProvider,
23 },
24 },
25 },
26 memory::{BufferHandles, DmaBufHandle, DmaBufSource, MemoryType, PrimitiveBufferHandles},
27 };
28
29 /// The simplest type used to represent a DMABUF fd. It does not take ownership
30 /// of the FD at any time and does not close it ; thus the using code is
31 /// responsible for managing the given FD's lifetime.
32 ///
33 /// Since no ownership is taken at all, this is mostly useful for using DMABUFs
34 /// managed from unsafe code, i.e. code that calls into us using the C ffi.
35 #[derive(Debug)]
36 pub struct DmaBufFd {
37 fd: RawFd,
38 len: u64,
39 }
40
41 impl DmaBufFd {
42 /// Create a new `RawFd` to be used with the DMABUF API.
43 /// `fd` is the unix raw fd, `len` is the size of the memory behind it (not
44 /// just the amound of used data, but the whole size of the buffer).
45 /// No ownership is taken over `fd`, which will not be closed as the `RawFd`
46 /// is dropped ; thus the caller is responsible for managing its lifetime.
new(fd: RawFd, len: u64) -> DmaBufFd47 pub fn new(fd: RawFd, len: u64) -> DmaBufFd {
48 DmaBufFd { fd, len }
49 }
50 }
51
52 impl AsFd for DmaBufFd {
as_fd(&self) -> BorrowedFd53 fn as_fd(&self) -> BorrowedFd {
54 unsafe { BorrowedFd::borrow_raw(self.fd) }
55 }
56 }
57
58 impl AsRawFd for DmaBufFd {
as_raw_fd(&self) -> RawFd59 fn as_raw_fd(&self) -> RawFd {
60 self.fd
61 }
62 }
63
64 impl DmaBufSource for DmaBufFd {
len(&self) -> u6465 fn len(&self) -> u64 {
66 self.len
67 }
68 }
69
70 /// A struct representing a set of buffers to which decoded frames will be
71 /// output.
72 #[derive(Debug, Default)]
73 #[repr(C)]
74 pub struct v4l2r_video_frame {
75 /// Identifier of the frame. Each frame of the provider must have a unique
76 /// identifier the between 0 and 31 included, and that identifier must
77 /// persist across reuse of the same frame.
78 pub id: u32,
79 /// Number of entries in `fds`, e.g. the number of planes in this frame.
80 pub num_planes: usize,
81 /// DMABUF FDs of the planes for this frame.
82 pub planes: [c_int; 4],
83 }
84
85 #[derive(Debug, Clone, Copy, Default)]
86 pub struct VideoFrameMemoryType;
87
88 impl From<VideoFrameMemoryType> for MemoryType {
from(_: VideoFrameMemoryType) -> Self89 fn from(_: VideoFrameMemoryType) -> Self {
90 MemoryType::DmaBuf
91 }
92 }
93
94 impl BufferHandles for v4l2r_video_frame {
95 type SupportedMemoryType = VideoFrameMemoryType;
96
len(&self) -> usize97 fn len(&self) -> usize {
98 self.num_planes
99 }
100
fill_v4l2_plane(&self, index: usize, plane: &mut bindings::v4l2_plane)101 fn fill_v4l2_plane(&self, index: usize, plane: &mut bindings::v4l2_plane) {
102 plane.m.fd = self.planes[index];
103 // We don't need to set plane.m.length as these buffers are meant for
104 // the CAPTURE queue.
105 }
106 }
107
108 impl PrimitiveBufferHandles for v4l2r_video_frame {
109 // TODO: Uh? This is bullocks but somehow it compiles??
110 type HandleType = DmaBufHandle<DmaBufFd>;
111
112 const MEMORY_TYPE: Self::SupportedMemoryType = VideoFrameMemoryType;
113 }
114
115 struct VideoFrameProviderInternal {
116 frames: VecDeque<v4l2r_video_frame>,
117 waker: Option<Arc<Waker>>,
118 }
119
120 /// A way for the client-side to provide frames to be decoded into in the form
121 /// of video frames. A new provider will be passed by the output format change
122 /// callback every time the output format is changing. The client must pass
123 /// valid frames of the format specified by the format change callback using
124 /// [`v4l2r_video_frame_provider_queue_frame`]. These frames will be decoded
125 /// into and then passed as parameters of the frame output callback.
126 pub struct v4l2r_video_frame_provider {
127 d: Mutex<VideoFrameProviderInternal>,
128 }
129
130 impl v4l2r_video_frame_provider {
131 #[allow(clippy::new_without_default)]
new() -> Self132 pub fn new() -> Self {
133 v4l2r_video_frame_provider {
134 d: Mutex::new(VideoFrameProviderInternal {
135 frames: VecDeque::new(),
136 waker: None,
137 }),
138 }
139 }
140 }
141
142 impl HandlesProvider for v4l2r_video_frame_provider {
143 type HandleType = v4l2r_video_frame;
144
145 // TODO BUG: if the V4L2 buffer queue fails for some reason, there
146 // is no guarantee that the handles will return to the provider, and
147 // they might be definitively lost!
148 // In this case this is probably not too serious as the C side, which
149 // manages the DMABUFs, should receive and error and cancel decoding.
150 // Ideally the handles would be a C++ object that we just pass around,
151 // and which destructor would be called even if the Rust side drops it.
get_handles(&self, waker: &Arc<Waker>) -> Option<Self::HandleType>152 fn get_handles(&self, waker: &Arc<Waker>) -> Option<Self::HandleType> {
153 let mut d = self.d.lock().unwrap();
154 match d.frames.pop_front() {
155 Some(handles) => Some(handles),
156 None => {
157 d.waker = Some(Arc::clone(waker));
158 None
159 }
160 }
161 }
162
get_suitable_buffer_for<'a, Q>( &self, handles: &Self::HandleType, queue: &'a Q, ) -> Result< <Q as CaptureQueueableProvider<'a, Self::HandleType>>::Queueable, GetSuitableBufferError, > where Q: GetCaptureBufferByIndex<'a, Self::HandleType> + GetFreeCaptureBuffer<'a, Self::HandleType>,163 fn get_suitable_buffer_for<'a, Q>(
164 &self,
165 handles: &Self::HandleType,
166 queue: &'a Q,
167 ) -> Result<
168 <Q as CaptureQueueableProvider<'a, Self::HandleType>>::Queueable,
169 GetSuitableBufferError,
170 >
171 where
172 Q: GetCaptureBufferByIndex<'a, Self::HandleType>
173 + GetFreeCaptureBuffer<'a, Self::HandleType>,
174 {
175 trace!("Getting suitable buffer for frame {}", handles.id);
176
177 // Try to get the buffer with the same id as our frame. If that is not
178 // possible, fall back to returning any free buffer.
179 let buffer = queue.try_get_buffer(handles.id as usize).or_else(|e| {
180 error!(
181 "failed to obtain CAPTURE buffer {} by index: {}",
182 handles.id, e
183 );
184 error!("falling back to getting the first available buffer.");
185 queue.try_get_free_buffer()
186 })?;
187
188 Ok(buffer)
189 }
190 }
191
192 /// Make `frame` available to `provider` for being decoded into.
193 ///
194 /// `frame` must be a valid frame of the format provided by the output format
195 /// change callback from which `provider` originated. `frame` will reappear as
196 /// an argument of the frame output callback once it has been decoded into, and
197 /// will remain untouched by the decoder until the client passes it to this
198 /// function again.
199 ///
200 /// Returns `true` upon success, `false` if the provided frame had an invalid
201 /// index or the decoder thread could not be awakened.
202 ///
203 /// This function can safely be called from any thread.
204 ///
205 /// # Safety
206 ///
207 /// `provider` must be a valid pointer provided by the resolution change
208 /// callback. It must *not* be used after the resolution change callback is
209 /// called again.
210 #[no_mangle]
v4l2r_video_frame_provider_queue_frame( provider: *const v4l2r_video_frame_provider, frame: v4l2r_video_frame, ) -> bool211 pub unsafe extern "C" fn v4l2r_video_frame_provider_queue_frame(
212 provider: *const v4l2r_video_frame_provider,
213 frame: v4l2r_video_frame,
214 ) -> bool {
215 trace!("Queueing output frame: {:?}", frame);
216 assert!(!provider.is_null());
217 let provider = &*provider;
218
219 if frame.id >= bindings::VIDEO_MAX_FRAME {
220 error!("Invalid frame id {}, aborting queue.", frame.id);
221 return false;
222 }
223
224 let mut provider = provider.d.lock().unwrap();
225 provider.frames.push_back(frame);
226 if let Some(waker) = provider.waker.take() {
227 waker.wake_by_ref();
228 }
229 true
230 }
231
232 /// Delete a video frame provider.
233 ///
234 /// # Safety
235 ///
236 /// `provider` must be a provider previously passed through the
237 /// `v4l2r_decoder_format_changed_event`. There are only two times when calling
238 /// this function is valid:
239 ///
240 /// 1) After another `v4l2r_decoder_format_changed_event` has been received, the
241 /// old provider can be disposed of after the client is sure it won't make
242 /// any access.
243 /// 2) After the video decoder has been stopped and destroyed, the client must
244 /// drop the last provider it received (if any) itself.
245 #[no_mangle]
v4l2r_video_frame_provider_drop( provider: *const v4l2r_video_frame_provider, )246 pub unsafe extern "C" fn v4l2r_video_frame_provider_drop(
247 provider: *const v4l2r_video_frame_provider,
248 ) {
249 trace!("Destroying video frame provider: {:p}", provider);
250 assert!(!provider.is_null());
251
252 Arc::from_raw(provider);
253 }
254