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