Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) .. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3) file: media/v4l/capture.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4) =========================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) .. code-block:: c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)     /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)      *  V4L2 video capture example
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)      *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)      *  This program can be used and distributed without restrictions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)      *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)      *      This program is provided with the V4L2 API
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14)      * see https://linuxtv.org/docs.php for more information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15)      */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17)     #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18)     #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19)     #include <string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20)     #include <assert.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22)     #include <getopt.h>             /* getopt_long() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24)     #include <fcntl.h>              /* low-level i/o */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25)     #include <unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26)     #include <errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27)     #include <sys/stat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28)     #include <sys/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29)     #include <sys/time.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30)     #include <sys/mman.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31)     #include <sys/ioctl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33)     #include <linux/videodev2.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35)     #define CLEAR(x) memset(&(x), 0, sizeof(x))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37)     enum io_method {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	    IO_METHOD_READ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	    IO_METHOD_MMAP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	    IO_METHOD_USERPTR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41)     };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43)     struct buffer {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 	    void   *start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	    size_t  length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46)     };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48)     static char            *dev_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49)     static enum io_method   io = IO_METHOD_MMAP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50)     static int              fd = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51)     struct buffer          *buffers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52)     static unsigned int     n_buffers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53)     static int              out_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54)     static int              force_format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55)     static int              frame_count = 70;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57)     static void errno_exit(const char *s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58)     {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	    fprintf(stderr, "%s error %d, %s\\n", s, errno, strerror(errno));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	    exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63)     static int xioctl(int fh, int request, void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64)     {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	    int r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	    do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 		    r = ioctl(fh, request, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	    } while (-1 == r && EINTR == errno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	    return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74)     static void process_image(const void *p, int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75)     {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	    if (out_buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 		    fwrite(p, size, 1, stdout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	    fflush(stderr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	    fprintf(stderr, ".");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	    fflush(stdout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84)     static int read_frame(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85)     {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	    struct v4l2_buffer buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	    unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	    switch (io) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	    case IO_METHOD_READ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 		    if (-1 == read(fd, buffers[0].start, buffers[0].length)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 			    switch (errno) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 			    case EAGAIN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 				    return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 			    case EIO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 				    /* Could ignore EIO, see spec. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 				    /* fall through */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 			    default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 				    errno_exit("read");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 			    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 		    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 		    process_image(buffers[0].start, buffers[0].length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 		    break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	    case IO_METHOD_MMAP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 		    CLEAR(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 		    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 		    buf.memory = V4L2_MEMORY_MMAP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 		    if (-1 == xioctl(fd, VIDIOC_DQBUF, &buf)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 			    switch (errno) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 			    case EAGAIN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 				    return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 			    case EIO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 				    /* Could ignore EIO, see spec. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 				    /* fall through */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 			    default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 				    errno_exit("VIDIOC_DQBUF");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 			    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 		    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 		    assert(buf.index < n_buffers);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 		    process_image(buffers[buf.index].start, buf.bytesused);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 		    if (-1 == xioctl(fd, VIDIOC_QBUF, &buf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 			    errno_exit("VIDIOC_QBUF");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 		    break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	    case IO_METHOD_USERPTR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 		    CLEAR(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 		    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 		    buf.memory = V4L2_MEMORY_USERPTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 		    if (-1 == xioctl(fd, VIDIOC_DQBUF, &buf)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 			    switch (errno) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 			    case EAGAIN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 				    return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 			    case EIO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 				    /* Could ignore EIO, see spec. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 				    /* fall through */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 			    default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 				    errno_exit("VIDIOC_DQBUF");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 			    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 		    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 		    for (i = 0; i < n_buffers; ++i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 			    if (buf.m.userptr == (unsigned long)buffers[i].start
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 				&& buf.length == buffers[i].length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 				    break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 		    assert(i < n_buffers);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 		    process_image((void *)buf.m.userptr, buf.bytesused);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 		    if (-1 == xioctl(fd, VIDIOC_QBUF, &buf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 			    errno_exit("VIDIOC_QBUF");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 		    break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	    return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)     static void mainloop(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)     {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	    unsigned int count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	    count = frame_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	    while (count-- > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 		    for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 			    fd_set fds;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 			    struct timeval tv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 			    int r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 			    FD_ZERO(&fds);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 			    FD_SET(fd, &fds);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 			    /* Timeout. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 			    tv.tv_sec = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 			    tv.tv_usec = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 			    r = select(fd + 1, &fds, NULL, NULL, &tv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 			    if (-1 == r) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 				    if (EINTR == errno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 					    continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 				    errno_exit("select");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 			    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 			    if (0 == r) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 				    fprintf(stderr, "select timeout\\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 				    exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 			    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 			    if (read_frame())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 				    break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 			    /* EAGAIN - continue select loop. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 		    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 	    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)     static void stop_capturing(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)     {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 	    enum v4l2_buf_type type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 	    switch (io) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	    case IO_METHOD_READ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 		    /* Nothing to do. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 		    break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	    case IO_METHOD_MMAP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 	    case IO_METHOD_USERPTR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 		    type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 		    if (-1 == xioctl(fd, VIDIOC_STREAMOFF, &type))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 			    errno_exit("VIDIOC_STREAMOFF");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 		    break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)     static void start_capturing(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)     {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 	    unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	    enum v4l2_buf_type type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 	    switch (io) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 	    case IO_METHOD_READ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 		    /* Nothing to do. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 		    break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	    case IO_METHOD_MMAP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 		    for (i = 0; i < n_buffers; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 			    struct v4l2_buffer buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 			    CLEAR(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 			    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 			    buf.memory = V4L2_MEMORY_MMAP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 			    buf.index = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 			    if (-1 == xioctl(fd, VIDIOC_QBUF, &buf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 				    errno_exit("VIDIOC_QBUF");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 		    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 		    type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 		    if (-1 == xioctl(fd, VIDIOC_STREAMON, &type))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 			    errno_exit("VIDIOC_STREAMON");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 		    break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 	    case IO_METHOD_USERPTR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 		    for (i = 0; i < n_buffers; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 			    struct v4l2_buffer buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 			    CLEAR(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 			    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 			    buf.memory = V4L2_MEMORY_USERPTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 			    buf.index = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 			    buf.m.userptr = (unsigned long)buffers[i].start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 			    buf.length = buffers[i].length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 			    if (-1 == xioctl(fd, VIDIOC_QBUF, &buf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 				    errno_exit("VIDIOC_QBUF");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 		    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 		    type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 		    if (-1 == xioctl(fd, VIDIOC_STREAMON, &type))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 			    errno_exit("VIDIOC_STREAMON");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 		    break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 	    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)     static void uninit_device(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)     {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	    unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 	    switch (io) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	    case IO_METHOD_READ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 		    free(buffers[0].start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 		    break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 	    case IO_METHOD_MMAP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 		    for (i = 0; i < n_buffers; ++i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 			    if (-1 == munmap(buffers[i].start, buffers[i].length))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 				    errno_exit("munmap");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 		    break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	    case IO_METHOD_USERPTR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 		    for (i = 0; i < n_buffers; ++i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 			    free(buffers[i].start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 		    break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 	    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 	    free(buffers);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)     static void init_read(unsigned int buffer_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)     {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 	    buffers = calloc(1, sizeof(*buffers));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 	    if (!buffers) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 		    fprintf(stderr, "Out of memory\\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 		    exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 	    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 	    buffers[0].length = buffer_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 	    buffers[0].start = malloc(buffer_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	    if (!buffers[0].start) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 		    fprintf(stderr, "Out of memory\\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 		    exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 	    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)     static void init_mmap(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)     {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 	    struct v4l2_requestbuffers req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 	    CLEAR(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 	    req.count = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 	    req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 	    req.memory = V4L2_MEMORY_MMAP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 	    if (-1 == xioctl(fd, VIDIOC_REQBUFS, &req)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 		    if (EINVAL == errno) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 			    fprintf(stderr, "%s does not support "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 				     "memory mappingn", dev_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 			    exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 		    } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 			    errno_exit("VIDIOC_REQBUFS");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 		    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 	    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 	    if (req.count < 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 		    fprintf(stderr, "Insufficient buffer memory on %s\\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 			     dev_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 		    exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 	    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 	    buffers = calloc(req.count, sizeof(*buffers));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 	    if (!buffers) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 		    fprintf(stderr, "Out of memory\\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 		    exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 	    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 	    for (n_buffers = 0; n_buffers < req.count; ++n_buffers) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 		    struct v4l2_buffer buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 		    CLEAR(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 		    buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 		    buf.memory      = V4L2_MEMORY_MMAP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 		    buf.index       = n_buffers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 		    if (-1 == xioctl(fd, VIDIOC_QUERYBUF, &buf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 			    errno_exit("VIDIOC_QUERYBUF");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 		    buffers[n_buffers].length = buf.length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 		    buffers[n_buffers].start =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 			    mmap(NULL /* start anywhere */,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 				  buf.length,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 				  PROT_READ | PROT_WRITE /* required */,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 				  MAP_SHARED /* recommended */,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 				  fd, buf.m.offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 		    if (MAP_FAILED == buffers[n_buffers].start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 			    errno_exit("mmap");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 	    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)     static void init_userp(unsigned int buffer_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)     {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 	    struct v4l2_requestbuffers req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 	    CLEAR(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 	    req.count  = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 	    req.type   = V4L2_BUF_TYPE_VIDEO_CAPTURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 	    req.memory = V4L2_MEMORY_USERPTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 	    if (-1 == xioctl(fd, VIDIOC_REQBUFS, &req)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 		    if (EINVAL == errno) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 			    fprintf(stderr, "%s does not support "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 				     "user pointer i/on", dev_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 			    exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 		    } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 			    errno_exit("VIDIOC_REQBUFS");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 		    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 	    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 	    buffers = calloc(4, sizeof(*buffers));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 	    if (!buffers) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 		    fprintf(stderr, "Out of memory\\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 		    exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 	    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 	    for (n_buffers = 0; n_buffers < 4; ++n_buffers) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 		    buffers[n_buffers].length = buffer_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 		    buffers[n_buffers].start = malloc(buffer_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 		    if (!buffers[n_buffers].start) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 			    fprintf(stderr, "Out of memory\\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 			    exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 		    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 	    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)     static void init_device(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)     {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 	    struct v4l2_capability cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 	    struct v4l2_cropcap cropcap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 	    struct v4l2_crop crop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 	    struct v4l2_format fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 	    unsigned int min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 	    if (-1 == xioctl(fd, VIDIOC_QUERYCAP, &cap)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 		    if (EINVAL == errno) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 			    fprintf(stderr, "%s is no V4L2 device\\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 				     dev_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 			    exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 		    } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 			    errno_exit("VIDIOC_QUERYCAP");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 		    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 	    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 	    if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 		    fprintf(stderr, "%s is no video capture device\\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 			     dev_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 		    exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 	    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 	    switch (io) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 	    case IO_METHOD_READ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 		    if (!(cap.capabilities & V4L2_CAP_READWRITE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 			    fprintf(stderr, "%s does not support read i/o\\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 				     dev_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 			    exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 		    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 		    break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 	    case IO_METHOD_MMAP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 	    case IO_METHOD_USERPTR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 		    if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 			    fprintf(stderr, "%s does not support streaming i/o\\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 				     dev_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 			    exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 		    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 		    break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 	    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 	    /* Select video input, video standard and tune here. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 	    CLEAR(cropcap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 	    cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 	    if (0 == xioctl(fd, VIDIOC_CROPCAP, &cropcap)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 		    crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 		    crop.c = cropcap.defrect; /* reset to default */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 		    if (-1 == xioctl(fd, VIDIOC_S_CROP, &crop)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 			    switch (errno) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 			    case EINVAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 				    /* Cropping not supported. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 				    break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 			    default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 				    /* Errors ignored. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 				    break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 			    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 		    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 	    } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 		    /* Errors ignored. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 	    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 	    CLEAR(fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 	    fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 	    if (force_format) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 		    fmt.fmt.pix.width       = 640;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 		    fmt.fmt.pix.height      = 480;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 		    fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 		    fmt.fmt.pix.field       = V4L2_FIELD_INTERLACED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 		    if (-1 == xioctl(fd, VIDIOC_S_FMT, &fmt))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 			    errno_exit("VIDIOC_S_FMT");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 		    /* Note VIDIOC_S_FMT may change width and height. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 	    } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 		    /* Preserve original settings as set by v4l2-ctl for example */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 		    if (-1 == xioctl(fd, VIDIOC_G_FMT, &fmt))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 			    errno_exit("VIDIOC_G_FMT");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 	    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 	    /* Buggy driver paranoia. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 	    min = fmt.fmt.pix.width * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 	    if (fmt.fmt.pix.bytesperline < min)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 		    fmt.fmt.pix.bytesperline = min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 	    min = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 	    if (fmt.fmt.pix.sizeimage < min)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 		    fmt.fmt.pix.sizeimage = min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 	    switch (io) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 	    case IO_METHOD_READ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 		    init_read(fmt.fmt.pix.sizeimage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 		    break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 	    case IO_METHOD_MMAP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 		    init_mmap();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 		    break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 	    case IO_METHOD_USERPTR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) 		    init_userp(fmt.fmt.pix.sizeimage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 		    break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 	    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)     static void close_device(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)     {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) 	    if (-1 == close(fd))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) 		    errno_exit("close");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 	    fd = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)     static void open_device(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)     {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 	    struct stat st;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) 	    if (-1 == stat(dev_name, &st)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 		    fprintf(stderr, "Cannot identify '%s': %d, %s\\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) 			     dev_name, errno, strerror(errno));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 		    exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) 	    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 	    if (!S_ISCHR(st.st_mode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 		    fprintf(stderr, "%s is no devicen", dev_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 		    exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 	    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 	    fd = open(dev_name, O_RDWR /* required */ | O_NONBLOCK, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 	    if (-1 == fd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 		    fprintf(stderr, "Cannot open '%s': %d, %s\\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 			     dev_name, errno, strerror(errno));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 		    exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 	    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)     static void usage(FILE *fp, int argc, char **argv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)     {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) 	    fprintf(fp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) 		     "Usage: %s [options]\\n\\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) 		     "Version 1.3\\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) 		     "Options:\\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) 		     "-d | --device name   Video device name [%s]n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) 		     "-h | --help          Print this messagen"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) 		     "-m | --mmap          Use memory mapped buffers [default]n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) 		     "-r | --read          Use read() callsn"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) 		     "-u | --userp         Use application allocated buffersn"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) 		     "-o | --output        Outputs stream to stdoutn"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 		     "-f | --format        Force format to 640x480 YUYVn"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) 		     "-c | --count         Number of frames to grab [%i]n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) 		     "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) 		     argv[0], dev_name, frame_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)     static const char short_options[] = "d:hmruofc:";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)     static const struct option
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)     long_options[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 	    { "device", required_argument, NULL, 'd' },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) 	    { "help",   no_argument,       NULL, 'h' },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 	    { "mmap",   no_argument,       NULL, 'm' },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) 	    { "read",   no_argument,       NULL, 'r' },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) 	    { "userp",  no_argument,       NULL, 'u' },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) 	    { "output", no_argument,       NULL, 'o' },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) 	    { "format", no_argument,       NULL, 'f' },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) 	    { "count",  required_argument, NULL, 'c' },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) 	    { 0, 0, 0, 0 }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)     };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)     int main(int argc, char **argv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)     {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) 	    dev_name = "/dev/video0";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) 	    for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) 		    int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) 		    int c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) 		    c = getopt_long(argc, argv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) 				    short_options, long_options, &idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) 		    if (-1 == c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) 			    break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) 		    switch (c) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) 		    case 0: /* getopt_long() flag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) 			    break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) 		    case 'd':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) 			    dev_name = optarg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) 			    break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) 		    case 'h':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) 			    usage(stdout, argc, argv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) 			    exit(EXIT_SUCCESS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) 		    case 'm':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) 			    io = IO_METHOD_MMAP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) 			    break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) 		    case 'r':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) 			    io = IO_METHOD_READ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) 			    break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) 		    case 'u':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) 			    io = IO_METHOD_USERPTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) 			    break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) 		    case 'o':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) 			    out_buf++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) 			    break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) 		    case 'f':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) 			    force_format++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) 			    break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) 		    case 'c':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) 			    errno = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) 			    frame_count = strtol(optarg, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) 			    if (errno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) 				    errno_exit(optarg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) 			    break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) 		    default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) 			    usage(stderr, argc, argv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) 			    exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) 		    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) 	    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) 	    open_device();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) 	    init_device();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) 	    start_capturing();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) 	    mainloop();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) 	    stop_capturing();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) 	    uninit_device();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) 	    close_device();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) 	    fprintf(stderr, "\\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) 	    return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)     }