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