• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, FormatBuilder, OutputQueueable},
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     let mut v4l2_format: bindings::v4l2_format = match desired_pixel_format {
147         Some(format) => f.set_pixelformat(format).apply()?,
148         None => f.apply()?,
149     };
150 
151     // Create new memory provider on the heap and update our internal pointer.
152     let new_provider = Arc::new(v4l2r_video_frame_provider::new());
153     // Reference for our own callbacks.
154     decoder.provider = Some(Arc::clone(&new_provider));
155 
156     // Reference owned by the client. Will be dropped when it calls
157     // `v4l2r_video_frame_provider_drop`.
158     let provider_client_ref = Arc::clone(&new_provider);
159 
160     // TODO check return value.
161     event_cb(
162         cb_data,
163         &mut v4l2r_decoder_event::FormatChanged(v4l2r_decoder_format_changed_event {
164             new_format: &mut v4l2_format,
165             visible_rect: visible_rect.into(),
166             new_provider: Arc::into_raw(provider_client_ref),
167             min_num_frames: min_num_buffers as c_uint,
168         }),
169     );
170 
171     Ok(FormatChangedReply {
172         provider: new_provider,
173         // TODO: can't the provider report the memory type that it is
174         // actually serving itself?
175         mem_type: VideoFrameMemoryType,
176         // Since we are using DMABUF, always allocate the maximum number of
177         // V4L2 buffers (32) since they are virtually free. This gives more
178         // flexibility for the client as to how many frames it can allocate.
179         num_buffers: bindings::VIDEO_MAX_FRAME as usize,
180     })
181 }
182 
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, )183 fn frame_decoded_cb(
184     decoder: &mut v4l2r_decoder,
185     mut dqbuf: DqBuffer<Capture, v4l2r_video_frame>,
186     event_cb: v4l2r_decoder_event_cb,
187     cb_data: *mut c_void,
188 ) {
189     let frame = dqbuf.take_handles().unwrap();
190     debug!(
191         "Video frame {} ({}) decoded from V4L2 buffer {} (flags: {:?})",
192         frame.id,
193         dqbuf.data.timestamp().tv_sec,
194         dqbuf.data.index(),
195         dqbuf.data.flags(),
196     );
197     let mut v4l2_data = dqbuf.data.clone();
198     // Drop the DQBuffer early so the C callback can reuse the V4L2
199     // buffer if it needs to.
200     drop(dqbuf);
201 
202     // Immediately recycle empty frames. We will pass the corresponding
203     // event to the client.
204     if *v4l2_data.get_first_plane().bytesused == 0 {
205         debug!(
206             "Immediately recycling zero-sized frame {} {}",
207             frame.id,
208             v4l2_data.is_last()
209         );
210         // Should be safe as `provider` is initialized in the format
211         // change callback and is thus valid, as well as `frame`.
212         match &decoder.provider {
213             // SAFETY: `provider` is a valid pointer to a frame provider.
214             Some(provider) => unsafe {
215                 v4l2r_video_frame_provider_queue_frame(provider.as_ref(), frame);
216             },
217             None => {
218                 error!("Frame decoded callback called while no provider set!");
219             }
220         }
221     } else {
222         // TODO check return value?
223         event_cb(
224             cb_data,
225             &mut v4l2r_decoder_event::FrameDecoded(v4l2r_decoder_frame_decoded_event {
226                 buffer: v4l2_data.as_mut_ptr() as *const _,
227                 frame,
228             }),
229         );
230     }
231 }
232 
233 // A void pointer that can be sent across threads. This is usually not allowed
234 // by Rust, but is necessary for us to call back into the V4L2RustDecoder.
235 struct SendablePtr<T>(*mut T);
236 impl<T> Clone for SendablePtr<T> {
clone(&self) -> Self237     fn clone(&self) -> Self {
238         *self
239     }
240 }
241 impl<T> Copy for SendablePtr<T> {}
242 unsafe impl<T> Send for SendablePtr<T> {}
243 unsafe impl<T> Sync for SendablePtr<T> {}
244 
245 #[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_decoder246 fn v4l2r_decoder_new_safe(
247     path: &Path,
248     input_format_fourcc: u32,
249     num_input_buffers: usize,
250     input_buffer_size: usize,
251     output_format_fourcc: u32,
252     input_done_cb: v4l2r_decoder_input_done_cb,
253     event_cb: v4l2r_decoder_event_cb,
254     cb_data: *mut c_void,
255 ) -> *mut v4l2r_decoder {
256     let decoder = match Decoder::open(path) {
257         Ok(decoder) => decoder,
258         Err(e) => {
259             error!("failed to open decoder {}: {:#?}", path.display(), e);
260             return std::ptr::null_mut();
261         }
262     };
263 
264     info!(
265         "Opened decoder {} with format {}, {} input buffers of size {}",
266         path.display(),
267         v4l2r::PixelFormat::from(input_format_fourcc),
268         num_input_buffers,
269         input_buffer_size
270     );
271 
272     let format_builder = |f: FormatBuilder| {
273         let pixel_format = input_format_fourcc.into();
274         let format = match f
275             .set_pixelformat(pixel_format)
276             .set_planes_layout(vec![PlaneLayout {
277                 sizeimage: input_buffer_size as u32,
278                 ..Default::default()
279             }])
280             .apply::<v4l2r::Format>()
281         {
282             Ok(format) if format.pixelformat == pixel_format => format,
283             Ok(_) => {
284                 return Err(anyhow::anyhow!(
285                     "Unrecognized OUTPUT format {:?}",
286                     pixel_format
287                 ))
288             }
289             Err(e) => return Err(e.into()),
290         };
291         debug!(
292             "Decoder requires input buffer size of: {}",
293             format.plane_fmt[0].sizeimage
294         );
295         Ok(())
296     };
297     let decoder = match decoder.set_output_format(format_builder) {
298         Ok(decoder) => decoder,
299         Err(e) => {
300             error!("Error while setting output format: {}", e);
301             return std::ptr::null_mut();
302         }
303     };
304 
305     let output_format = match output_format_fourcc {
306         0 => None,
307         fourcc => Some(PixelFormat::from(fourcc)),
308     };
309 
310     let cb_data = SendablePtr(cb_data);
311 
312     let decoder =
313         match decoder.allocate_output_buffers::<Vec<DmaBufHandle<DmaBufFd>>>(num_input_buffers) {
314             Ok(decoder) => decoder,
315             Err(e) => {
316                 error!("Error while allocating OUTPUT buffers: {}", e);
317                 return std::ptr::null_mut();
318             }
319         };
320 
321     // Reserve memory on the heap for our decoder and take a pointer that we
322     // can use in our callbacks.
323     let mut decoder_box = Box::new(MaybeUninit::<v4l2r_decoder>::uninit());
324     let decoder_ptr = SendablePtr(decoder_box.as_mut_ptr());
325 
326     let event_handler = move |event: DecoderEvent<Arc<v4l2r_video_frame_provider>>| {
327         // Make Rust 2021 happy.
328         let decoder_ptr = decoder_ptr;
329         let cb_data = cb_data;
330 
331         // SAFETY: `decoder_ptr` will be initialized with a valid decoder by the time this
332         // callback is called.
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                 // SAFETY: `decoder_ptr` will be initialized with a valid decoder by the time this
371                 // callback is called.
372                 let decoder = unsafe { decoder_ptr.0.as_mut().unwrap() };
373 
374                 set_capture_format_cb(
375                     f,
376                     output_format,
377                     visible_rect,
378                     min_num_buffers,
379                     decoder,
380                     event_cb,
381                     cb_data.0,
382                 )
383             },
384         ) as Box<dyn FormatChangedCallback<Arc<v4l2r_video_frame_provider>>>,
385     );
386 
387     let decoder = match res {
388         Ok(decoder) => decoder,
389         Err(e) => {
390             error!("Cannot start decoder: {}", e);
391             return std::ptr::null_mut();
392         }
393     };
394 
395     let input_format: v4l2r::Format = decoder.get_output_format().unwrap();
396 
397     let decoder = v4l2r_decoder {
398         decoder,
399         provider: None,
400         input_buf_size: input_format.plane_fmt[0].sizeimage as u64,
401     };
402 
403     // SAFETY: `decoder` is a `v4l2r_decoder`, the same type expected by `decoder_box`.
404     let decoder_box = unsafe {
405         // Replace our uninitialized heap memory with our valid decoder.
406         decoder_box.as_mut_ptr().write(decoder);
407         // Convert the Box<MaybeUninit<v4l2r_decoder>> into Box<v4l2r_decoder>
408         // now that we know the decoder is properly initialized. It would be
409         // better to use Box::assume_init but as of rustc 1.50 this method is
410         // still in nightly only.
411         Box::from_raw(Box::into_raw(decoder_box) as *mut v4l2r_decoder)
412     };
413 
414     info!("Decoder {:p}: successfully started", decoder_box.as_ref());
415 
416     Box::into_raw(decoder_box)
417 }
418 
v4l2r_decoder_decode_safe( decoder: &mut v4l2r_decoder, bitstream_id: i32, fd: c_int, bytes_used: usize, ) -> c_int419 fn v4l2r_decoder_decode_safe(
420     decoder: &mut v4l2r_decoder,
421     bitstream_id: i32,
422     fd: c_int,
423     bytes_used: usize,
424 ) -> c_int {
425     let v4l2_buffer = match decoder.decoder.get_buffer() {
426         Ok(buffer) => buffer,
427         Err(e) => {
428             error!("Error obtaining V4L2 buffer: {}", e);
429             return -1;
430         }
431     };
432     let v4l2_buffer_id = v4l2_buffer.index();
433 
434     match v4l2_buffer
435         .set_timestamp(TimeVal::seconds(bitstream_id as i64))
436         .queue_with_handles(
437             vec![DmaBufHandle::from(DmaBufFd::new(
438                 fd,
439                 decoder.input_buf_size,
440             ))],
441             &[bytes_used],
442         ) {
443         Ok(()) => (),
444         Err(e) => {
445             error!("Error while queueing buffer: {}", e);
446             return -1;
447         }
448     };
449 
450     v4l2_buffer_id as c_int
451 }
452 
453 /// Create a new decoder for a given encoded format.
454 ///
455 /// * `path` is the path to the V4L2 device that will be used for decoding.
456 /// * `input_format_fourcc` is the FOURCC code of the encoded format we will
457 ///   decode, e.g. "H264" or "VP80".
458 /// * `num_input_buffers` is the number of input buffers we wish to use. It
459 ///   should correspond to the number of different buffers containing input data
460 ///   that will be given to this decoder.
461 /// * `input_buffer_size` is the desired size of input buffers. The decoder may
462 ///   adjust this value, so the client should call
463 ///   [`v4l2r_decoder_get_input_format`] to confirm the actual expected value.
464 /// * `output_format_fourcc` is the FOURCC code of the desired pixel format for
465 ///   output frames (e.g. "NV12"). It can also be 0, in which case the decoder
466 ///   will use whichever pixel format is active by default.
467 /// * `input_done_cb` is a pointer to a callback function to be called whenever
468 ///   an encoded input buffer is done being processed. This callback is
469 ///   guaranteed to be invoked during calls to [`v4l2r_decoder_decode`] or
470 ///   [`v4l2r_decoder_kick`], i.e. it will always be called in the current
471 ///   thread.
472 /// * `event_cb` is a pointer to a function to be called for handling the
473 ///   various events produced by the decoder. See [`v4l2r_decoder_event`] for
474 ///   more details on events. This callback is guaranteed to be called from a
475 ///   separate, unique thread, therefore the events can be assumed to be
476 ///   sequential (i.e. two events cannot be produced at the same time from two
477 ///   different threads).
478 /// * `cb_data` is a pointer that will always be passed as the first parameter
479 ///   of the `input_done_cb` and `events_cb`.
480 ///
481 /// # Safety
482 /// The passed `path` must be a valid, zero-terminated C string containining the
483 /// path to the device. Expect a crash if passing an invalid string.
484 #[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_decoder485 pub unsafe extern "C" fn v4l2r_decoder_new(
486     path: *const c_char,
487     input_format_fourcc: u32,
488     num_input_buffers: usize,
489     input_buffer_size: usize,
490     output_format_fourcc: u32,
491     input_done_cb: v4l2r_decoder_input_done_cb,
492     event_cb: v4l2r_decoder_event_cb,
493     cb_data: *mut c_void,
494 ) -> *mut v4l2r_decoder {
495     let cstr = CStr::from_ptr(path);
496     let rstr = cstr.to_str().unwrap();
497     let path = Path::new(&rstr);
498 
499     v4l2r_decoder_new_safe(
500         path,
501         input_format_fourcc,
502         num_input_buffers,
503         input_buffer_size,
504         output_format_fourcc,
505         input_done_cb,
506         event_cb,
507         cb_data,
508     )
509 }
510 
511 /// Stop and destroy a decoder.
512 ///
513 /// Stop `decoder` and destroy it. This function DOES take ownership of
514 /// `decoder`, which must absolutely not be used after this call.
515 ///
516 /// It is guaranteed that none of the callbacks passed to [`v4l2r_decoder_new`]
517 /// will be called after this function has returned.
518 ///
519 /// # Safety
520 ///
521 /// `decoder` must be a valid pointer to a decoder returned by
522 /// `v4l2r_decoder_new`. Passing a NULL or invalid pointer will cause a crash.
523 /// `decoder` must not be used again after this function is called.
524 #[no_mangle]
v4l2r_decoder_destroy(decoder: *mut v4l2r_decoder)525 pub unsafe extern "C" fn v4l2r_decoder_destroy(decoder: *mut v4l2r_decoder) {
526     info!("Decoder {:p}: destroying", decoder);
527 
528     if decoder.is_null() {
529         warn!("Trying to destroy a NULL decoder");
530         return;
531     }
532 
533     let decoder = Box::from_raw(decoder);
534     match decoder.decoder.stop() {
535         Ok(_) => (),
536         Err(e) => error!("Error while stopping decoder: {}", e),
537     }
538 }
539 
540 /// Obtain the current input format (i.e. the format set on the *OUTPUT* queue).
541 ///
542 /// Obtain the current input format for `decoder` and write it into `format`.
543 /// This function can be called at any time since a decoder always have a valid
544 /// input format.
545 ///
546 /// Returns 0 in case of success, -1 if an error occured, in which case `format`
547 /// is not overwritten.
548 ///
549 /// # Safety
550 ///
551 /// `decoder` must be a valid pointer to a decoder instance. `format` must point
552 /// to valid memory that can receive a `v4l2_format`
553 #[no_mangle]
v4l2r_decoder_get_input_format( decoder: *const v4l2r_decoder, format: *mut bindings::v4l2_format, ) -> c_int554 pub unsafe extern "C" fn v4l2r_decoder_get_input_format(
555     decoder: *const v4l2r_decoder,
556     format: *mut bindings::v4l2_format,
557 ) -> c_int {
558     assert!(!decoder.is_null());
559     assert!(!format.is_null());
560 
561     let decoder = &*decoder;
562     let format = &mut *format;
563 
564     *format = match decoder.decoder.get_output_format() {
565         Ok(format) => format,
566         Err(e) => {
567             error!("Error while getting output format: {}", e);
568             return -1;
569         }
570     };
571 
572     0
573 }
574 
575 /// Decode the encoded data referenced by `fd`.
576 ///
577 /// The decoder does NOT take ownership of `fd` and won't close it.
578 ///
579 /// `bitstream_id` is the identifier of this input buffer. The produced frames
580 /// will carry this identifier in they timestamp.
581 ///
582 /// `bytes_used` is amount of encoded data within that buffer.
583 ///
584 /// The value returned is the index of the V4L2 buffer `fd` has been queued with.
585 /// It can be used to know when `fd` is done being decoded as a `v4l2_buffer` of
586 /// the same index will be passed as argument to the *input done callback* when
587 /// this is the case.
588 ///
589 /// In case of error, -1 is returned.
590 ///
591 /// # Safety
592 ///
593 /// `decoder` must be a valid pointer to a decoder returned by
594 /// [`v4l2r_decoder_new`]. Passing a NULL or invalid pointer will cause a crash.
595 /// `fd` is expected to be a valid DMABUF FD backed by enough memory for the
596 /// expected input buffer size. Failure to provide a valid FD will return in an
597 /// ioctl error (but no crash).
598 #[no_mangle]
v4l2r_decoder_decode( decoder: *mut v4l2r_decoder, bitstream_id: i32, fd: c_int, bytes_used: usize, ) -> c_int599 pub unsafe extern "C" fn v4l2r_decoder_decode(
600     decoder: *mut v4l2r_decoder,
601     bitstream_id: i32,
602     fd: c_int,
603     bytes_used: usize,
604 ) -> c_int {
605     debug!(
606         "Decoder {:p}: decoding bitstream id {}",
607         decoder, bitstream_id
608     );
609     assert!(!decoder.is_null());
610     let decoder = &mut *decoder;
611 
612     v4l2r_decoder_decode_safe(decoder, bitstream_id, fd, bytes_used)
613 }
614 
615 /// Kick the decoder and see if some input buffers fall as a result.
616 ///
617 /// No, really. Completed input buffers are typically checked when calling
618 /// [`v4l2r_decoder_decode`] (which is also the time when the input done
619 /// callback is invoked), but this mechanism is not foolproof: if the client
620 /// works with a limited set of input buffers and queues them all before an
621 /// output frame can be produced, then the client has no more material to call
622 /// [`v4l2r_decoder_decode`] with and thus no input buffer will ever be
623 /// dequeued, resulting in the decoder being blocked.
624 ///
625 /// This method mitigates this problem by adding a way to check for completed
626 /// input buffers and calling the input done callback without the need for new
627 /// encoded content. It is suggested to call it from the same thread that
628 /// invokes [`v4l2r_decoder_decode`] every time we get a
629 /// [`v4l2r_decoder_frame_decoded_event`]. That way the client can recycle its
630 /// input buffers and the decoding process does not get stuck.
631 ///
632 /// # Safety
633 ///
634 /// `decoder` must be a valid pointer to a decoder returned by
635 /// [`v4l2r_decoder_new`]. Passing a NULL or invalid pointer will cause a crash.
636 #[no_mangle]
v4l2r_decoder_kick(decoder: *const v4l2r_decoder)637 pub unsafe extern "C" fn v4l2r_decoder_kick(decoder: *const v4l2r_decoder) {
638     assert!(!decoder.is_null());
639     let decoder = &*decoder;
640 
641     match decoder.decoder.kick() {
642         Ok(()) => (),
643         Err(e) => {
644             error!("Error while kicking decoder: {}", e);
645         }
646     }
647 }
648 
649 /// Possible responses for the [`v4l2r_decoder_drain`] commmand.
650 #[repr(C)]
651 #[allow(clippy::upper_case_acronyms)]
652 pub enum v4l2r_decoder_drain_response {
653     /// The drain has already completed as [`v4l2r_decoder_drain`] returned.
654     DRAIN_COMPLETED,
655     /// The drain has started but will be completed when we receive a
656     /// [`v4l2r_decoder_event::EndOfStream`] event.
657     DRAIN_STARTED,
658     /// Drain cannot be done at the moment because not enough input buffers
659     /// have been processed to know the output format.
660     TRY_AGAIN,
661     /// An error has occurred.
662     ERROR,
663 }
664 
665 /// # Safety
666 ///
667 /// `decoder` must be a valid pointer to a decoder returned by
668 /// [`v4l2r_decoder_new`]. Passing a NULL or invalid pointer will cause a crash.
669 #[no_mangle]
v4l2r_decoder_drain( decoder: *const v4l2r_decoder, blocking: bool, ) -> v4l2r_decoder_drain_response670 pub unsafe extern "C" fn v4l2r_decoder_drain(
671     decoder: *const v4l2r_decoder,
672     blocking: bool,
673 ) -> v4l2r_decoder_drain_response {
674     assert!(!decoder.is_null());
675     let decoder = &*decoder;
676 
677     match decoder.decoder.drain(blocking) {
678         Ok(true) => v4l2r_decoder_drain_response::DRAIN_COMPLETED,
679         Ok(false) => v4l2r_decoder_drain_response::DRAIN_STARTED,
680         Err(DrainError::TryAgain) => v4l2r_decoder_drain_response::TRY_AGAIN,
681         Err(e) => {
682             error!("Error while draining decoder: {}", e);
683             v4l2r_decoder_drain_response::ERROR
684         }
685     }
686 }
687 
688 /// # Safety
689 ///
690 /// `decoder` must be a valid pointer to a decoder returned by
691 /// [`v4l2r_decoder_new`]. Passing a NULL or invalid pointer will cause a crash.
692 #[no_mangle]
v4l2r_decoder_flush(decoder: *const v4l2r_decoder)693 pub unsafe extern "C" fn v4l2r_decoder_flush(decoder: *const v4l2r_decoder) {
694     assert!(!decoder.is_null());
695     let decoder = &*decoder;
696 
697     match decoder.decoder.flush() {
698         Ok(()) => (),
699         Err(e) => {
700             error!("Error while flushing decoder: {:#?}", e);
701         }
702     }
703 }
704