1 //! Module for creating and controlling V4L2 decoders.
2 //!
3 //! Decoders are created using [`v4l2r_decoder_new`] and remain
4 //! active until being given to [`v4l2r_decoder_destroy`]. They expect
5 //! to be fed encoded buffers in the format specified at creation time using
6 //! [`v4l2r_decoder_decode`].
7 //!
8 //! Decoders communicate with the client using an event callback that is invoked
9 //! on a dedicated thread. This callback signals events of interest, like a
10 //! frame being decoded, or a change in the output format (due to e.g. a dynamic
11 //! resolution change). The output format is initially undefined and a format
12 //! change event will be produced before any frame can be decoded.
13 #![allow(non_camel_case_types)]
14 
15 use log::{debug, error, info, warn};
16 use nix::sys::time::{TimeVal, TimeValLike};
17 use std::{
18     ffi::CStr,
19     mem::MaybeUninit,
20     os::raw::{c_char, c_int, c_uint, c_void},
21     path::Path,
22     sync::Arc,
23 };
24 use v4l2r::{
25     bindings,
26     decoder::{
27         stateful::{Decoder, Decoding, DrainError},
28         CompletedInputBuffer, DecoderEvent, DecoderEventCallback, FormatChangedCallback,
29         FormatChangedReply, InputDoneCallback,
30     },
31     device::queue::{direction::Capture, dqbuf::DqBuffer, qbuf::OutputQueueable, FormatBuilder},
32     memory::DmaBufHandle,
33     PixelFormat, PlaneLayout, Rect,
34 };
35 
36 use crate::memory::{
37     v4l2r_video_frame, v4l2r_video_frame_provider, v4l2r_video_frame_provider_queue_frame,
38     DmaBufFd, VideoFrameMemoryType,
39 };
40 
41 type DynCbDecoder = Decoder<
42     Decoding<
43         Vec<DmaBufHandle<DmaBufFd>>,
44         Arc<v4l2r_video_frame_provider>,
45         Box<dyn InputDoneCallback<Vec<DmaBufHandle<DmaBufFd>>>>,
46         Box<dyn DecoderEventCallback<Arc<v4l2r_video_frame_provider>>>,
47         Box<dyn FormatChangedCallback<Arc<v4l2r_video_frame_provider>>>,
48     >,
49 >;
50 
51 /// A V4L2 decoder instance.
52 pub struct v4l2r_decoder {
53     decoder: DynCbDecoder,
54     // Reference to the video frame provider for our callbacks.
55     provider: Option<Arc<v4l2r_video_frame_provider>>,
56     // Keep the size of input buffers at hand.
57     input_buf_size: u64,
58 }
59 
60 /// Callback called when the decoder is done with a buffer submitted using
61 /// [`v4l2r_decoder_decode`].
62 ///
63 /// The first argument is the `cb_data` pointer given
64 /// to [`v4l2r_decoder_new`]. The second argument is the dequeued V4L2 buffer.
65 /// The client can use the `timestamp.tv_sec` member of `buffer` to match this
66 /// buffer with the `bitstream_id` parameter of [`v4l2r_decoder_decode`] and
67 /// understand which buffer has just completed.
68 ///
69 /// This callback is only called during calls to [`v4l2r_decoder_decode`] and
70 /// [`v4l2r_decoder_kick`].
71 pub type v4l2r_decoder_input_done_cb = extern "C" fn(*mut c_void, *const bindings::v4l2_buffer);
72 
73 #[repr(C)]
74 pub struct v4l2r_decoder_frame_decoded_event {
75     /// Dequeued V4L2 buffer that has produced the frame. Useful to check for
76     /// flags and errors.
77     buffer: *const bindings::v4l2_buffer,
78     /// One of the frames previously made available to the decoder using
79     /// [`v4l2r_video_frame_provider_queue_frame`].
80     ///
81     /// [`v4l2r_video_frame_provider_queue_frame`]:
82     /// crate::memory::v4l2r_video_frame_provider_queue_frame
83     frame: v4l2r_video_frame,
84 }
85 
86 /// Event produced every time the output format of the stream changes.
87 /// This includes when the initial format is determined by the decoder, and any
88 /// subsequent dynamic resolution change in the stream.
89 #[repr(C)]
90 pub struct v4l2r_decoder_format_changed_event {
91     /// New format for decoded frames produced after this event.
92     new_format: *mut bindings::v4l2_format,
93     /// Visible rectangle for decoded frames produced after this event.
94     visible_rect: bindings::v4l2_rect,
95     /// Pointer to the video frame provider the client must use to provide
96     /// frames to decode into.
97     ///
98     /// When the client receives this event, it must stop using the previous
99     /// video frame provider (if any) as soon as possible and destroy it using
100     /// `v4l2r_video_frame_provider_drop`. Any video frame still queued to an
101     /// old provider and that has not been seen in a previous `FrameDecoded`
102     /// event can be considered as returned to the client. Upon receiving this
103     /// event, the client is guaranteed to not receive any frame in the previous
104     /// format, or from the previous provider.
105     ///
106     /// The client is responsible for allocating video frames in the new format
107     /// and start giving them to the new provider using
108     /// [`v4l2r_video_frame_provider_queue_frame`].
109     ///
110     /// [`v4l2r_video_frame_provider_queue_frame`]:
111     /// crate::memory::v4l2r_video_frame_provider_queue_frame
112     new_provider: *const v4l2r_video_frame_provider,
113     /// Minimum number of output buffers required by the decoder to operate
114     /// properly.
115     ///
116     /// The client must allocate at least `min_num_frames` (but no more than
117     /// 32), otherwise the decoder might starve.
118     min_num_frames: c_uint,
119 }
120 
121 /// Decoding-related events. These events can be produced at any time between
122 /// calls to [`v4l2r_decoder_new`] and [`v4l2r_decoder_destroy`] and
123 /// are passed to the events callback.
124 #[repr(C)]
125 pub enum v4l2r_decoder_event {
126     // TODO for frames that have a zero-size, just recycle the handles
127     // on-the-spot and pass the relevant event instead!
128     FrameDecoded(v4l2r_decoder_frame_decoded_event),
129     FormatChanged(v4l2r_decoder_format_changed_event),
130     EndOfStream,
131 }
132 
133 /// Events callback. This callback is guaranteed to always be called from the
134 /// same thread, i.e. events are completely sequential.
135 pub type v4l2r_decoder_event_cb = extern "C" fn(*mut c_void, *mut v4l2r_decoder_event);
136 
set_capture_format_cb( f: FormatBuilder, desired_pixel_format: Option<PixelFormat>, visible_rect: Rect, min_num_buffers: usize, decoder: *mut v4l2r_decoder, event_cb: v4l2r_decoder_event_cb, cb_data: *mut c_void, ) -> anyhow::Result<FormatChangedReply<Arc<v4l2r_video_frame_provider>>>137 fn set_capture_format_cb(
138     f: FormatBuilder,
139     desired_pixel_format: Option<PixelFormat>,
140     visible_rect: Rect,
141     min_num_buffers: usize,
142     decoder: *mut v4l2r_decoder,
143     event_cb: v4l2r_decoder_event_cb,
144     cb_data: *mut c_void,
145 ) -> anyhow::Result<FormatChangedReply<Arc<v4l2r_video_frame_provider>>> {
146     // Safe unless the C part did something funny with the decoder returned by
147     // `v4l2r_decoder_new`.
148     let decoder = unsafe { decoder.as_mut().unwrap() };
149     let mut v4l2_format: bindings::v4l2_format = match desired_pixel_format {
150         Some(format) => f.set_pixelformat(format).apply()?,
151         None => f.apply()?,
152     };
153 
154     // Create new memory provider on the heap and update our internal pointer.
155     let new_provider = Arc::new(v4l2r_video_frame_provider::new());
156     // Reference for our own callbacks.
157     decoder.provider = Some(Arc::clone(&new_provider));
158 
159     // Reference owned by the client. Will be dropped when it calls
160     // `v4l2r_video_frame_provider_drop`.
161     let provider_client_ref = Arc::clone(&new_provider);
162 
163     // TODO check return value.
164     event_cb(
165         cb_data,
166         &mut v4l2r_decoder_event::FormatChanged(v4l2r_decoder_format_changed_event {
167             new_format: &mut v4l2_format,
168             visible_rect: visible_rect.into(),
169             new_provider: Arc::into_raw(provider_client_ref),
170             min_num_frames: min_num_buffers as c_uint,
171         }),
172     );
173 
174     Ok(FormatChangedReply {
175         provider: new_provider,
176         // TODO: can't the provider report the memory type that it is
177         // actually serving itself?
178         mem_type: VideoFrameMemoryType,
179         // Since we are using DMABUF, always allocate the maximum number of
180         // V4L2 buffers (32) since they are virtually free. This gives more
181         // flexibility for the client as to how many frames it can allocate.
182         num_buffers: bindings::VIDEO_MAX_FRAME as usize,
183     })
184 }
185 
frame_decoded_cb( decoder: &mut v4l2r_decoder, mut dqbuf: DqBuffer<Capture, v4l2r_video_frame>, event_cb: v4l2r_decoder_event_cb, cb_data: *mut c_void, )186 fn frame_decoded_cb(
187     decoder: &mut v4l2r_decoder,
188     mut dqbuf: DqBuffer<Capture, v4l2r_video_frame>,
189     event_cb: v4l2r_decoder_event_cb,
190     cb_data: *mut c_void,
191 ) {
192     let frame = dqbuf.take_handles().unwrap();
193     debug!(
194         "Video frame {} ({}) decoded from V4L2 buffer {} (flags: {:?})",
195         frame.id,
196         dqbuf.data.timestamp().tv_sec,
197         dqbuf.data.index(),
198         dqbuf.data.flags(),
199     );
200     let mut v4l2_data = dqbuf.data.clone();
201     // Drop the DQBuffer early so the C callback can reuse the V4L2
202     // buffer if it needs to.
203     drop(dqbuf);
204 
205     // Immediately recycle empty frames. We will pass the corresponding
206     // event to the client.
207     if *v4l2_data.get_first_plane().bytesused == 0 {
208         debug!(
209             "Immediately recycling zero-sized frame {} {}",
210             frame.id,
211             v4l2_data.is_last()
212         );
213         // Should be safe as `provider` is initialized in the format
214         // change callback and is thus valid, as well as `frame`.
215         match &decoder.provider {
216             Some(provider) => unsafe {
217                 v4l2r_video_frame_provider_queue_frame(provider.as_ref(), frame);
218             },
219             None => {
220                 error!("Frame decoded callback called while no provider set!");
221             }
222         }
223     } else {
224         // TODO check return value?
225         event_cb(
226             cb_data,
227             &mut v4l2r_decoder_event::FrameDecoded(v4l2r_decoder_frame_decoded_event {
228                 buffer: v4l2_data.as_mut_ptr() as *const _,
229                 frame,
230             }),
231         );
232     }
233 }
234 
235 // A void pointer that can be sent across threads. This is usually not allowed
236 // by Rust, but is necessary for us to call back into the V4L2RustDecoder.
237 struct SendablePtr<T>(*mut T);
238 impl<T> Clone for SendablePtr<T> {
clone(&self) -> Self239     fn clone(&self) -> Self {
240         *self
241     }
242 }
243 impl<T> Copy for SendablePtr<T> {}
244 unsafe impl<T> Send for SendablePtr<T> {}
245 unsafe impl<T> Sync for SendablePtr<T> {}
246 
247 #[allow(clippy::too_many_arguments)]
v4l2r_decoder_new_safe( path: &Path, input_format_fourcc: u32, num_input_buffers: usize, input_buffer_size: usize, output_format_fourcc: u32, input_done_cb: v4l2r_decoder_input_done_cb, event_cb: v4l2r_decoder_event_cb, cb_data: *mut c_void, ) -> *mut v4l2r_decoder248 fn v4l2r_decoder_new_safe(
249     path: &Path,
250     input_format_fourcc: u32,
251     num_input_buffers: usize,
252     input_buffer_size: usize,
253     output_format_fourcc: u32,
254     input_done_cb: v4l2r_decoder_input_done_cb,
255     event_cb: v4l2r_decoder_event_cb,
256     cb_data: *mut c_void,
257 ) -> *mut v4l2r_decoder {
258     let decoder = match Decoder::open(path) {
259         Ok(decoder) => decoder,
260         Err(e) => {
261             error!("failed to open decoder {}: {:#?}", path.display(), e);
262             return std::ptr::null_mut();
263         }
264     };
265 
266     info!(
267         "Opened decoder {} with format {}, {} input buffers of size {}",
268         path.display(),
269         v4l2r::PixelFormat::from(input_format_fourcc),
270         num_input_buffers,
271         input_buffer_size
272     );
273 
274     let format_builder = |f: FormatBuilder| {
275         let pixel_format = input_format_fourcc.into();
276         let format = match f
277             .set_pixelformat(pixel_format)
278             .set_planes_layout(vec![PlaneLayout {
279                 sizeimage: input_buffer_size as u32,
280                 ..Default::default()
281             }])
282             .apply::<v4l2r::Format>()
283         {
284             Ok(format) if format.pixelformat == pixel_format => format,
285             Ok(_) => {
286                 return Err(anyhow::anyhow!(
287                     "Unrecognized OUTPUT format {:?}",
288                     pixel_format
289                 ))
290             }
291             Err(e) => return Err(e.into()),
292         };
293         debug!(
294             "Decoder requires input buffer size of: {}",
295             format.plane_fmt[0].sizeimage
296         );
297         Ok(())
298     };
299     let decoder = match decoder.set_output_format(format_builder) {
300         Ok(decoder) => decoder,
301         Err(e) => {
302             error!("Error while setting output format: {}", e);
303             return std::ptr::null_mut();
304         }
305     };
306 
307     let output_format = match output_format_fourcc {
308         0 => None,
309         fourcc => Some(PixelFormat::from(fourcc)),
310     };
311 
312     let cb_data = SendablePtr(cb_data);
313 
314     let decoder =
315         match decoder.allocate_output_buffers::<Vec<DmaBufHandle<DmaBufFd>>>(num_input_buffers) {
316             Ok(decoder) => decoder,
317             Err(e) => {
318                 error!("Error while allocating OUTPUT buffers: {}", e);
319                 return std::ptr::null_mut();
320             }
321         };
322 
323     // Reserve memory on the heap for our decoder and take a pointer that we
324     // can use in our callbacks.
325     let mut decoder_box = Box::new(MaybeUninit::<v4l2r_decoder>::uninit());
326     let decoder_ptr = SendablePtr(decoder_box.as_mut_ptr());
327 
328     let event_handler = move |event: DecoderEvent<Arc<v4l2r_video_frame_provider>>| {
329         // Make Rust 2021 happy.
330         let decoder_ptr = decoder_ptr;
331         let cb_data = cb_data;
332 
333         let decoder = unsafe { decoder_ptr.0.as_mut().unwrap() };
334 
335         match event {
336             DecoderEvent::FrameDecoded(dqbuf) => {
337                 frame_decoded_cb(decoder, dqbuf, event_cb, cb_data.0)
338             }
339             DecoderEvent::EndOfStream => event_cb(cb_data.0, &mut v4l2r_decoder_event::EndOfStream),
340         };
341     };
342 
343     let res = decoder.start(
344         Box::new(
345             move |buf: CompletedInputBuffer<Vec<DmaBufHandle<DmaBufFd>>>| {
346                 match buf {
347                     CompletedInputBuffer::Dequeued(mut dqbuf) => {
348                         debug!("Input buffer {} done", dqbuf.data.index());
349                         // TODO check return value?
350                         input_done_cb(cb_data.0, dqbuf.data.as_mut_ptr() as *const _);
351                     }
352                     // Just drop canceled buffers for now - the client will remove
353                     // them on its side as well.
354                     // TODO add a status parameter to the callback and invoke it?
355                     // that way the client does not need to clear its own list...
356                     CompletedInputBuffer::Canceled(_) => (),
357                 }
358             },
359         ) as Box<dyn InputDoneCallback<Vec<DmaBufHandle<DmaBufFd>>>>,
360         Box::new(event_handler) as Box<dyn DecoderEventCallback<Arc<v4l2r_video_frame_provider>>>,
361         Box::new(
362             move |f: FormatBuilder,
363                   visible_rect: Rect,
364                   min_num_buffers: usize|
365                   -> anyhow::Result<FormatChangedReply<Arc<v4l2r_video_frame_provider>>> {
366                 // Make Rust 2021 happy.
367                 let decoder_ptr = decoder_ptr;
368                 let cb_data = cb_data;
369 
370                 set_capture_format_cb(
371                     f,
372                     output_format,
373                     visible_rect,
374                     min_num_buffers,
375                     decoder_ptr.0,
376                     event_cb,
377                     cb_data.0,
378                 )
379             },
380         ) as Box<dyn FormatChangedCallback<Arc<v4l2r_video_frame_provider>>>,
381     );
382 
383     let decoder = match res {
384         Ok(decoder) => decoder,
385         Err(e) => {
386             error!("Cannot start decoder: {}", e);
387             return std::ptr::null_mut();
388         }
389     };
390 
391     let input_format: v4l2r::Format = decoder.get_output_format().unwrap();
392 
393     let decoder = v4l2r_decoder {
394         decoder,
395         provider: None,
396         input_buf_size: input_format.plane_fmt[0].sizeimage as u64,
397     };
398 
399     let decoder_box = unsafe {
400         // Replace our uninitialized heap memory with our valid decoder.
401         decoder_box.as_mut_ptr().write(decoder);
402         // Convert the Box<MaybeUninit<v4l2r_decoder>> into Box<v4l2r_decoder>
403         // now that we know the decoder is properly initialized. It would be
404         // better to use Box::assume_init but as of rustc 1.50 this method is
405         // still in nightly only.
406         Box::from_raw(Box::into_raw(decoder_box) as *mut v4l2r_decoder)
407     };
408 
409     info!("Decoder {:p}: successfully started", decoder_box.as_ref());
410 
411     Box::into_raw(decoder_box)
412 }
413 
v4l2r_decoder_decode_safe( decoder: &mut v4l2r_decoder, bitstream_id: i32, fd: c_int, bytes_used: usize, ) -> c_int414 fn v4l2r_decoder_decode_safe(
415     decoder: &mut v4l2r_decoder,
416     bitstream_id: i32,
417     fd: c_int,
418     bytes_used: usize,
419 ) -> c_int {
420     let v4l2_buffer = match decoder.decoder.get_buffer() {
421         Ok(buffer) => buffer,
422         Err(e) => {
423             error!("Error obtaining V4L2 buffer: {}", e);
424             return -1;
425         }
426     };
427     let v4l2_buffer_id = v4l2_buffer.index();
428 
429     match v4l2_buffer
430         .set_timestamp(TimeVal::seconds(bitstream_id as i64))
431         .queue_with_handles(
432             vec![DmaBufHandle::from(DmaBufFd::new(
433                 fd,
434                 decoder.input_buf_size,
435             ))],
436             &[bytes_used],
437         ) {
438         Ok(()) => (),
439         Err(e) => {
440             error!("Error while queueing buffer: {}", e);
441             return -1;
442         }
443     };
444 
445     v4l2_buffer_id as c_int
446 }
447 
448 /// Create a new decoder for a given encoded format.
449 ///
450 /// * `path` is the path to the V4L2 device that will be used for decoding.
451 /// * `input_format_fourcc` is the FOURCC code of the encoded format we will
452 ///   decode, e.g. "H264" or "VP80".
453 /// * `num_input_buffers` is the number of input buffers we wish to use. It
454 ///   should correspond to the number of different buffers containing input data
455 ///   that will be given to this decoder.
456 /// * `input_buffer_size` is the desired size of input buffers. The decoder may
457 ///   adjust this value, so the client should call
458 ///   [`v4l2r_decoder_get_input_format`] to confirm the actual expected value.
459 /// * `output_format_fourcc` is the FOURCC code of the desired pixel format for
460 ///   output frames (e.g. "NV12"). It can also be 0, in which case the decoder
461 ///   will use whichever pixel format is active by default.
462 /// * `input_done_cb` is a pointer to a callback function to be called whenever
463 ///   an encoded input buffer is done being processed. This callback is
464 ///   guaranteed to be invoked during calls to [`v4l2r_decoder_decode`] or
465 ///   [`v4l2r_decoder_kick`], i.e. it will always be called in the current
466 ///   thread.
467 /// * `event_cb` is a pointer to a function to be called for handling the
468 ///   various events produced by the decoder. See [`v4l2r_decoder_event`] for
469 ///   more details on events. This callback is guaranteed to be called from a
470 ///   separate, unique thread, therefore the events can be assumed to be
471 ///   sequential (i.e. two events cannot be produced at the same time from two
472 ///   different threads).
473 /// * `cb_data` is a pointer that will always be passed as the first parameter
474 ///   of the `input_done_cb` and `events_cb`.
475 ///
476 /// # Safety
477 /// The passed `path` must be a valid, zero-terminated C string containining the
478 /// path to the device. Expect a crash if passing an invalid string.
479 #[no_mangle]
v4l2r_decoder_new( path: *const c_char, input_format_fourcc: u32, num_input_buffers: usize, input_buffer_size: usize, output_format_fourcc: u32, input_done_cb: v4l2r_decoder_input_done_cb, event_cb: v4l2r_decoder_event_cb, cb_data: *mut c_void, ) -> *mut v4l2r_decoder480 pub unsafe extern "C" fn v4l2r_decoder_new(
481     path: *const c_char,
482     input_format_fourcc: u32,
483     num_input_buffers: usize,
484     input_buffer_size: usize,
485     output_format_fourcc: u32,
486     input_done_cb: v4l2r_decoder_input_done_cb,
487     event_cb: v4l2r_decoder_event_cb,
488     cb_data: *mut c_void,
489 ) -> *mut v4l2r_decoder {
490     let cstr = CStr::from_ptr(path);
491     let rstr = cstr.to_str().unwrap();
492     let path = Path::new(&rstr);
493 
494     v4l2r_decoder_new_safe(
495         path,
496         input_format_fourcc,
497         num_input_buffers,
498         input_buffer_size,
499         output_format_fourcc,
500         input_done_cb,
501         event_cb,
502         cb_data,
503     )
504 }
505 
506 /// Stop and destroy a decoder.
507 ///
508 /// Stop `decoder` and destroy it. This function DOES take ownership of
509 /// `decoder`, which must absolutely not be used after this call.
510 ///
511 /// It is guaranteed that none of the callbacks passed to [`v4l2r_decoder_new`]
512 /// will be called after this function has returned.
513 ///
514 /// # Safety
515 ///
516 /// `decoder` must be a valid pointer to a decoder returned by
517 /// `v4l2r_decoder_new`. Passing a NULL or invalid pointer will cause a crash.
518 /// `decoder` must not be used again after this function is called.
519 #[no_mangle]
v4l2r_decoder_destroy(decoder: *mut v4l2r_decoder)520 pub unsafe extern "C" fn v4l2r_decoder_destroy(decoder: *mut v4l2r_decoder) {
521     info!("Decoder {:p}: destroying", decoder);
522 
523     if decoder.is_null() {
524         warn!("Trying to destroy a NULL decoder");
525         return;
526     }
527 
528     let decoder = Box::from_raw(decoder);
529     match decoder.decoder.stop() {
530         Ok(_) => (),
531         Err(e) => error!("Error while stopping decoder: {}", e),
532     }
533 }
534 
535 /// Obtain the current input format (i.e. the format set on the *OUTPUT* queue).
536 ///
537 /// Obtain the current input format for `decoder` and write it into `format`.
538 /// This function can be called at any time since a decoder always have a valid
539 /// input format.
540 ///
541 /// Returns 0 in case of success, -1 if an error occured, in which case `format`
542 /// is not overwritten.
543 ///
544 /// # Safety
545 ///
546 /// `decoder` must be a valid pointer to a decoder instance. `format` must point
547 /// to valid memory that can receive a `v4l2_format`
548 #[no_mangle]
v4l2r_decoder_get_input_format( decoder: *const v4l2r_decoder, format: *mut bindings::v4l2_format, ) -> c_int549 pub unsafe extern "C" fn v4l2r_decoder_get_input_format(
550     decoder: *const v4l2r_decoder,
551     format: *mut bindings::v4l2_format,
552 ) -> c_int {
553     assert!(!decoder.is_null());
554     assert!(!format.is_null());
555 
556     let decoder = &*decoder;
557     let format = &mut *format;
558 
559     *format = match decoder.decoder.get_output_format() {
560         Ok(format) => format,
561         Err(e) => {
562             error!("Error while getting output format: {}", e);
563             return -1;
564         }
565     };
566 
567     0
568 }
569 
570 /// Decode the encoded data referenced by `fd`.
571 ///
572 /// The decoder does NOT take ownership of `fd` and won't close it.
573 ///
574 /// `bitstream_id` is the identifier of this input buffer. The produced frames
575 /// will carry this identifier in they timestamp.
576 ///
577 /// `bytes_used` is amount of encoded data within that buffer.
578 ///
579 /// The value returned is the index of the V4L2 buffer `fd` has been queued with.
580 /// It can be used to know when `fd` is done being decoded as a `v4l2_buffer` of
581 /// the same index will be passed as argument to the *input done callback* when
582 /// this is the case.
583 ///
584 /// In case of error, -1 is returned.
585 ///
586 /// # Safety
587 ///
588 /// `decoder` must be a valid pointer to a decoder returned by
589 /// [`v4l2r_decoder_new`]. Passing a NULL or invalid pointer will cause a crash.
590 /// `fd` is expected to be a valid DMABUF FD backed by enough memory for the
591 /// expected input buffer size. Failure to provide a valid FD will return in an
592 /// ioctl error (but no crash).
593 #[no_mangle]
v4l2r_decoder_decode( decoder: *mut v4l2r_decoder, bitstream_id: i32, fd: c_int, bytes_used: usize, ) -> c_int594 pub unsafe extern "C" fn v4l2r_decoder_decode(
595     decoder: *mut v4l2r_decoder,
596     bitstream_id: i32,
597     fd: c_int,
598     bytes_used: usize,
599 ) -> c_int {
600     debug!(
601         "Decoder {:p}: decoding bitstream id {}",
602         decoder, bitstream_id
603     );
604     assert!(!decoder.is_null());
605     let decoder = &mut *decoder;
606 
607     v4l2r_decoder_decode_safe(decoder, bitstream_id, fd, bytes_used)
608 }
609 
610 /// Kick the decoder and see if some input buffers fall as a result.
611 ///
612 /// No, really. Completed input buffers are typically checked when calling
613 /// [`v4l2r_decoder_decode`] (which is also the time when the input done
614 /// callback is invoked), but this mechanism is not foolproof: if the client
615 /// works with a limited set of input buffers and queues them all before an
616 /// output frame can be produced, then the client has no more material to call
617 /// [`v4l2r_decoder_decode`] with and thus no input buffer will ever be
618 /// dequeued, resulting in the decoder being blocked.
619 ///
620 /// This method mitigates this problem by adding a way to check for completed
621 /// input buffers and calling the input done callback without the need for new
622 /// encoded content. It is suggested to call it from the same thread that
623 /// invokes [`v4l2r_decoder_decode`] every time we get a
624 /// [`v4l2r_decoder_frame_decoded_event`]. That way the client can recycle its
625 /// input buffers and the decoding process does not get stuck.
626 ///
627 /// # Safety
628 ///
629 /// `decoder` must be a valid pointer to a decoder returned by
630 /// [`v4l2r_decoder_new`]. Passing a NULL or invalid pointer will cause a crash.
631 #[no_mangle]
v4l2r_decoder_kick(decoder: *const v4l2r_decoder)632 pub unsafe extern "C" fn v4l2r_decoder_kick(decoder: *const v4l2r_decoder) {
633     assert!(!decoder.is_null());
634     let decoder = &*decoder;
635 
636     match decoder.decoder.kick() {
637         Ok(()) => (),
638         Err(e) => {
639             error!("Error while kicking decoder: {}", e);
640         }
641     }
642 }
643 
644 /// Possible responses for the [`v4l2r_decoder_drain`] commmand.
645 #[repr(C)]
646 #[allow(clippy::upper_case_acronyms)]
647 pub enum v4l2r_decoder_drain_response {
648     /// The drain has already completed as [`v4l2r_decoder_drain`] returned.
649     DRAIN_COMPLETED,
650     /// The drain has started but will be completed when we receive a
651     /// [`v4l2r_decoder_event::EndOfStream`] event.
652     DRAIN_STARTED,
653     /// Drain cannot be done at the moment because not enough input buffers
654     /// have been processed to know the output format.
655     TRY_AGAIN,
656     /// An error has occurred.
657     ERROR,
658 }
659 
660 /// # Safety
661 ///
662 /// `decoder` must be a valid pointer to a decoder returned by
663 /// [`v4l2r_decoder_new`]. Passing a NULL or invalid pointer will cause a crash.
664 #[no_mangle]
v4l2r_decoder_drain( decoder: *const v4l2r_decoder, blocking: bool, ) -> v4l2r_decoder_drain_response665 pub unsafe extern "C" fn v4l2r_decoder_drain(
666     decoder: *const v4l2r_decoder,
667     blocking: bool,
668 ) -> v4l2r_decoder_drain_response {
669     assert!(!decoder.is_null());
670     let decoder = &*decoder;
671 
672     match decoder.decoder.drain(blocking) {
673         Ok(true) => v4l2r_decoder_drain_response::DRAIN_COMPLETED,
674         Ok(false) => v4l2r_decoder_drain_response::DRAIN_STARTED,
675         Err(DrainError::TryAgain) => v4l2r_decoder_drain_response::TRY_AGAIN,
676         Err(e) => {
677             error!("Error while draining decoder: {}", e);
678             v4l2r_decoder_drain_response::ERROR
679         }
680     }
681 }
682 
683 /// # Safety
684 ///
685 /// `decoder` must be a valid pointer to a decoder returned by
686 /// [`v4l2r_decoder_new`]. Passing a NULL or invalid pointer will cause a crash.
687 #[no_mangle]
v4l2r_decoder_flush(decoder: *const v4l2r_decoder)688 pub unsafe extern "C" fn v4l2r_decoder_flush(decoder: *const v4l2r_decoder) {
689     assert!(!decoder.is_null());
690     let decoder = &*decoder;
691 
692     match decoder.decoder.flush() {
693         Ok(()) => (),
694         Err(e) => {
695             error!("Error while flushing decoder: {:#?}", e);
696         }
697     }
698 }
699