33 * @author Milos Liska <xliska@fi.muni.cz>
44 * @author Martin Piatka <piatka@cesnet.cz>
55 * @author Martin Pulec <martin.pulec@cesnet.cz>
6+ *
7+ * The implementation is based on capture.c.rst example in
8+ * Documentation/userspace-api/media/v4l subdir of Linux kernel
9+ * tree (the IO_METHOD_MMAP variant).
610 */
7- /*
11+ /*
812 * Copyright (c) 2012-2026 CESNET, zájmové sdružení právických osob
913 * All rights reserved.
1014 *
5458#include <stdio.h>
5559#include <stdlib.h>
5660#include <string.h>
57- #include <sys/ioctl.h>
5861#include <sys/mman.h>
5962#include <unistd.h>
6063
@@ -114,7 +117,7 @@ static void enqueue_all_finished_frames(struct vidcap_v4l2_state *s) {
114117 struct v4l2_dispose_deq_buffer_data * dequeue_data ;
115118 while ((dequeue_data = simple_linked_list_pop (s -> buffers_to_enqueue )) != NULL ) {
116119 s -> dequeued_buffers -= 1 ;
117- if (ioctl (s -> fd , VIDIOC_QBUF , & dequeue_data -> buf ) != 0 ) {
120+ if (xioctl (s -> fd , VIDIOC_QBUF , & dequeue_data -> buf ) != 0 ) {
118121 log_perror (LOG_LEVEL_ERROR , "Unable to enqueue buffer" );
119122 }
120123 free (dequeue_data );
@@ -127,7 +130,7 @@ static void vidcap_v4l2_common_cleanup(struct vidcap_v4l2_state *s) {
127130 }
128131
129132 int type = V4L2_BUF_TYPE_VIDEO_CAPTURE ;
130- if (s -> fd != -1 && ioctl (s -> fd , VIDIOC_STREAMOFF , & type ) != 0 ) {
133+ if (s -> fd != -1 && xioctl (s -> fd , VIDIOC_STREAMOFF , & type ) != 0 ) {
131134 log_perror (LOG_LEVEL_ERROR , MOD_NAME "Stream stopping error" );
132135 };
133136
@@ -164,7 +167,7 @@ static void vidcap_v4l2_common_cleanup(struct vidcap_v4l2_state *s) {
164167}
165168
166169static void print_fps (int fd , struct v4l2_frmivalenum * param ) {
167- int res = ioctl (fd , VIDIOC_ENUM_FRAMEINTERVALS , param );
170+ int res = xioctl (fd , VIDIOC_ENUM_FRAMEINTERVALS , param );
168171
169172 if (res == -1 ) {
170173 log_perror (LOG_LEVEL_WARNING , MOD_NAME "Unable to get FPS" );
@@ -173,7 +176,7 @@ static void print_fps(int fd, struct v4l2_frmivalenum *param) {
173176
174177 switch (param -> type ) {
175178 case V4L2_FRMIVAL_TYPE_DISCRETE :
176- while (ioctl (fd , VIDIOC_ENUM_FRAMEINTERVALS , param ) == 0 ) {
179+ while (xioctl (fd , VIDIOC_ENUM_FRAMEINTERVALS , param ) == 0 ) {
177180 printf ("%u/%u " , param -> discrete .numerator ,
178181 param -> discrete .denominator );
179182 param -> index ++ ;
@@ -249,7 +252,7 @@ static void show_help(_Bool full)
249252
250253 struct v4l2_capability capab ;
251254 memset (& capab , 0 , sizeof capab );
252- if (ioctl (fd , VIDIOC_QUERYCAP , & capab ) != 0 ) {
255+ if (xioctl (fd , VIDIOC_QUERYCAP , & capab ) != 0 ) {
253256 log_perror (LOG_LEVEL_WARNING , MOD_NAME "Unable to query device capabilities" );
254257 }
255258
@@ -268,12 +271,12 @@ static void show_help(_Bool full)
268271 struct v4l2_format fmt ;
269272 memset (& fmt , 0 , sizeof (fmt ));
270273 fmt .type = V4L2_BUF_TYPE_VIDEO_CAPTURE ;
271- if (ioctl (fd , VIDIOC_G_FMT , & fmt ) != 0 ) {
274+ if (xioctl (fd , VIDIOC_G_FMT , & fmt ) != 0 ) {
272275 log_perror (LOG_LEVEL_WARNING , MOD_NAME "Unable to get video format" );
273276 goto next_device ;
274277 }
275278
276- while (full && ioctl (fd , VIDIOC_ENUM_FMT , & format ) == 0 ) {
279+ while (full && xioctl (fd , VIDIOC_ENUM_FMT , & format ) == 0 ) {
277280 printf ("\t\t" );
278281 if (fmt .fmt .pix .pixelformat == format .pixelformat ) {
279282 printf ("(*) " );
@@ -287,7 +290,7 @@ static void show_help(_Bool full)
287290 memset (& size , 0 , sizeof (size ));
288291 size .pixel_format = format .pixelformat ;
289292
290- if (ioctl (fd , VIDIOC_ENUM_FRAMESIZES , & size ) == -1 ) {
293+ if (xioctl (fd , VIDIOC_ENUM_FRAMESIZES , & size ) == -1 ) {
291294 log_perror (LOG_LEVEL_ERROR , MOD_NAME "Unable to get frame size iterator" );
292295 goto next_device ;
293296 }
@@ -299,7 +302,7 @@ static void show_help(_Bool full)
299302
300303 switch (size .type ) {
301304 case V4L2_FRMSIZE_TYPE_DISCRETE :
302- while (ioctl (fd , VIDIOC_ENUM_FRAMESIZES , & size ) == 0 ) {
305+ while (xioctl (fd , VIDIOC_ENUM_FRAMESIZES , & size ) == 0 ) {
303306 printf ("\t\t\t" );
304307 if (fmt .fmt .pix .width == size .discrete .width &&
305308 fmt .fmt .pix .height == size .discrete .height ) {
@@ -403,7 +406,7 @@ static void vidcap_v4l2_probe(struct device_info **available_cards, int *count,
403406
404407 struct v4l2_capability capab ;
405408 memset (& capab , 0 , sizeof capab );
406- if (ioctl (fd , VIDIOC_QUERYCAP , & capab ) != 0 ) {
409+ if (xioctl (fd , VIDIOC_QUERYCAP , & capab ) != 0 ) {
407410 log_perror (LOG_LEVEL_WARNING , MOD_NAME "Unable to query device capabilities" );
408411 }
409412
@@ -423,12 +426,12 @@ static void vidcap_v4l2_probe(struct device_info **available_cards, int *count,
423426 format .index = 0 ;
424427
425428 int fmt_idx = 0 ;
426- while (ioctl (fd , VIDIOC_ENUM_FMT , & format ) == 0 ) {
429+ while (xioctl (fd , VIDIOC_ENUM_FMT , & format ) == 0 ) {
427430 struct v4l2_frmsizeenum size ;
428431 memset (& size , 0 , sizeof (size ));
429432 size .pixel_format = format .pixelformat ;
430433
431- if (ioctl (fd , VIDIOC_ENUM_FRAMESIZES , & size ) == -1 ) {
434+ if (xioctl (fd , VIDIOC_ENUM_FRAMESIZES , & size ) == -1 ) {
432435 log_perror (LOG_LEVEL_WARNING , MOD_NAME "Unable to get frame size iterator" );
433436 goto next_device ;
434437 }
@@ -440,19 +443,19 @@ static void vidcap_v4l2_probe(struct device_info **available_cards, int *count,
440443
441444 switch (size .type ) {
442445 case V4L2_FRMSIZE_TYPE_DISCRETE :
443- while (ioctl (fd , VIDIOC_ENUM_FRAMESIZES , & size ) == 0 ) {
446+ while (xioctl (fd , VIDIOC_ENUM_FRAMESIZES , & size ) == 0 ) {
444447 frame_int .width = size .discrete .width ;
445448 frame_int .height = size .discrete .height ;
446449 frame_int .index = 0 ;
447450
448- if (ioctl (fd , VIDIOC_ENUM_FRAMEINTERVALS , & frame_int ) == -1 ) {
451+ if (xioctl (fd , VIDIOC_ENUM_FRAMEINTERVALS , & frame_int ) == -1 ) {
449452 log_perror (LOG_LEVEL_WARNING , MOD_NAME "Unable to get FPS" );
450453 goto next_device ;
451454 }
452455
453456 switch (frame_int .type ) {
454457 case V4L2_FRMIVAL_TYPE_DISCRETE :
455- while (ioctl (fd , VIDIOC_ENUM_FRAMEINTERVALS , & frame_int ) == 0 ) {
458+ while (xioctl (fd , VIDIOC_ENUM_FRAMEINTERVALS , & frame_int ) == 0 ) {
456459 write_mode (& cards [card_count - 1 ].modes [fmt_idx ++ ],
457460 size .discrete .width , size .discrete .height ,
458461 frame_int .discrete .numerator , frame_int .discrete .denominator ,
@@ -635,13 +638,13 @@ static int vidcap_v4l2_init(const struct vidcap_params *params, void **state)
635638 }
636639
637640 struct v4l2_format fmt = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE };
638- if (ioctl (s -> fd , VIDIOC_G_FMT , & fmt ) != 0 ) {
641+ if (xioctl (s -> fd , VIDIOC_G_FMT , & fmt ) != 0 ) {
639642 log_perror (LOG_LEVEL_ERROR , MOD_NAME "Unable to get video format" );
640643 goto error ;
641644 }
642645
643646 struct v4l2_streamparm stream_params = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE };
644- if (ioctl (s -> fd , VIDIOC_G_PARM , & stream_params ) != 0 ) {
647+ if (xioctl (s -> fd , VIDIOC_G_PARM , & stream_params ) != 0 ) {
645648 log_perror (LOG_LEVEL_ERROR , MOD_NAME "Unable to get stream params" );
646649 goto error ;
647650 }
@@ -659,7 +662,7 @@ static int vidcap_v4l2_init(const struct vidcap_params *params, void **state)
659662 fmt .fmt .pix .bytesperline = 0 ;
660663
661664 struct v4l2_format req_fmt = fmt ;
662- if (ioctl (s -> fd , VIDIOC_S_FMT , & fmt ) != 0 ) {
665+ if (xioctl (s -> fd , VIDIOC_S_FMT , & fmt ) != 0 ) {
663666 log_perror (LOG_LEVEL_ERROR , MOD_NAME "Unable to set video format" );
664667 goto error ;
665668 }
@@ -671,7 +674,7 @@ static int vidcap_v4l2_init(const struct vidcap_params *params, void **state)
671674 }
672675 struct v4l2_streamparm req_stream_params = stream_params ;
673676 if (opts .numerator != 0 && opts .denominator != 0 &&
674- ioctl (s -> fd , VIDIOC_S_PARM , & stream_params ) != 0 ) {
677+ xioctl (s -> fd , VIDIOC_S_PARM , & stream_params ) != 0 ) {
675678 log_perror (LOG_LEVEL_ERROR ,
676679 MOD_NAME "Unable to set stream params" );
677680 goto error ;
@@ -686,7 +689,7 @@ static int vidcap_v4l2_init(const struct vidcap_params *params, void **state)
686689 s -> dst_fmt .fmt .pix .bytesperline = 0 ;
687690 s -> dst_fmt .fmt .pix .colorspace = V4L2_COLORSPACE_DEFAULT ;
688691
689- if (ioctl (s -> fd , VIDIOC_G_PARM , & stream_params ) != 0 ) {
692+ if (xioctl (s -> fd , VIDIOC_G_PARM , & stream_params ) != 0 ) {
690693 log_perror (LOG_LEVEL_ERROR , MOD_NAME "Unable to get stream params" );
691694 goto error ;
692695 }
@@ -758,7 +761,7 @@ static int vidcap_v4l2_init(const struct vidcap_params *params, void **state)
758761 }
759762 s -> buffer_count = reqbuf .count ;
760763
761- if (ioctl (s -> fd , VIDIOC_STREAMON , & reqbuf .type ) != 0 ) {
764+ if (xioctl (s -> fd , VIDIOC_STREAMON , & reqbuf .type ) != 0 ) {
762765 log_perror (LOG_LEVEL_ERROR , MOD_NAME "Unable to start stream" );
763766 goto error ;
764767 };
@@ -824,7 +827,7 @@ static struct video_frame * vidcap_v4l2_grab(void *state, struct audio_frame **a
824827 buf .type = V4L2_BUF_TYPE_VIDEO_CAPTURE ;
825828 buf .memory = V4L2_MEMORY_MMAP ;
826829
827- if (ioctl (s -> fd , VIDIOC_DQBUF , & buf ) != 0 ) {
830+ if (xioctl (s -> fd , VIDIOC_DQBUF , & buf ) != 0 ) {
828831 log_perror (LOG_LEVEL_ERROR , MOD_NAME "Unable to dequeue buffer" );
829832 return NULL ;
830833 };
@@ -847,7 +850,7 @@ static struct video_frame * vidcap_v4l2_grab(void *state, struct audio_frame **a
847850 out -> tiles [0 ].data_len );
848851
849852 // we do not need the driver buffer any more
850- if (ioctl (s -> fd , VIDIOC_QBUF , & buf ) != 0 ) {
853+ if (xioctl (s -> fd , VIDIOC_QBUF , & buf ) != 0 ) {
851854 log_perror (LOG_LEVEL_ERROR , "[V4L2 capture] Unable to enqueue buffer" );
852855 } else {
853856 s -> dequeued_buffers -= 1 ;
0 commit comments