1.. Permission is granted to copy, distribute and/or modify this 2.. document under the terms of the GNU Free Documentation License, 3.. Version 1.1 or any later version published by the Free Software 4.. Foundation, with no Invariant Sections, no Front-Cover Texts 5.. and no Back-Cover Texts. A copy of the license is included at 6.. Documentation/userspace-api/media/fdl-appendix.rst. 7.. 8.. TODO: replace it to GFDL-1.1-or-later WITH no-invariant-sections 9 10file: media/v4l/v4l2grab.c 11========================== 12 13.. code-block:: c 14 15 /* V4L2 video picture grabber 16 Copyright (C) 2009 Mauro Carvalho Chehab <mchehab@kernel.org> 17 18 This program is free software; you can redistribute it and/or modify 19 it under the terms of the GNU General Public License as published by 20 the Free Software Foundation version 2 of the License. 21 22 This program is distributed in the hope that it will be useful, 23 but WITHOUT ANY WARRANTY; without even the implied warranty of 24 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 GNU General Public License for more details. 26 */ 27 28 #include <stdio.h> 29 #include <stdlib.h> 30 #include <string.h> 31 #include <fcntl.h> 32 #include <errno.h> 33 #include <sys/ioctl.h> 34 #include <sys/types.h> 35 #include <sys/time.h> 36 #include <sys/mman.h> 37 #include <linux/videodev2.h> 38 #include "../libv4l/include/libv4l2.h" 39 40 #define CLEAR(x) memset(&(x), 0, sizeof(x)) 41 42 struct buffer { 43 void *start; 44 size_t length; 45 }; 46 47 static void xioctl(int fh, int request, void *arg) 48 { 49 int r; 50 51 do { 52 r = v4l2_ioctl(fh, request, arg); 53 } while (r == -1 && ((errno == EINTR) || (errno == EAGAIN))); 54 55 if (r == -1) { 56 fprintf(stderr, "error %d, %s\\n", errno, strerror(errno)); 57 exit(EXIT_FAILURE); 58 } 59 } 60 61 int main(int argc, char **argv) 62 { 63 struct v4l2_format fmt; 64 struct v4l2_buffer buf; 65 struct v4l2_requestbuffers req; 66 enum v4l2_buf_type type; 67 fd_set fds; 68 struct timeval tv; 69 int r, fd = -1; 70 unsigned int i, n_buffers; 71 char *dev_name = "/dev/video0"; 72 char out_name[256]; 73 FILE *fout; 74 struct buffer *buffers; 75 76 fd = v4l2_open(dev_name, O_RDWR | O_NONBLOCK, 0); 77 if (fd < 0) { 78 perror("Cannot open device"); 79 exit(EXIT_FAILURE); 80 } 81 82 CLEAR(fmt); 83 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 84 fmt.fmt.pix.width = 640; 85 fmt.fmt.pix.height = 480; 86 fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB24; 87 fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; 88 xioctl(fd, VIDIOC_S_FMT, &fmt); 89 if (fmt.fmt.pix.pixelformat != V4L2_PIX_FMT_RGB24) { 90 printf("Libv4l didn't accept RGB24 format. Can't proceed.\\n"); 91 exit(EXIT_FAILURE); 92 } 93 if ((fmt.fmt.pix.width != 640) || (fmt.fmt.pix.height != 480)) 94 printf("Warning: driver is sending image at %dx%d\\n", 95 fmt.fmt.pix.width, fmt.fmt.pix.height); 96 97 CLEAR(req); 98 req.count = 2; 99 req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 100 req.memory = V4L2_MEMORY_MMAP; 101 xioctl(fd, VIDIOC_REQBUFS, &req); 102 103 buffers = calloc(req.count, sizeof(*buffers)); 104 for (n_buffers = 0; n_buffers < req.count; ++n_buffers) { 105 CLEAR(buf); 106 107 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 108 buf.memory = V4L2_MEMORY_MMAP; 109 buf.index = n_buffers; 110 111 xioctl(fd, VIDIOC_QUERYBUF, &buf); 112 113 buffers[n_buffers].length = buf.length; 114 buffers[n_buffers].start = v4l2_mmap(NULL, buf.length, 115 PROT_READ | PROT_WRITE, MAP_SHARED, 116 fd, buf.m.offset); 117 118 if (MAP_FAILED == buffers[n_buffers].start) { 119 perror("mmap"); 120 exit(EXIT_FAILURE); 121 } 122 } 123 124 for (i = 0; i < n_buffers; ++i) { 125 CLEAR(buf); 126 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 127 buf.memory = V4L2_MEMORY_MMAP; 128 buf.index = i; 129 xioctl(fd, VIDIOC_QBUF, &buf); 130 } 131 type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 132 133 xioctl(fd, VIDIOC_STREAMON, &type); 134 for (i = 0; i < 20; i++) { 135 do { 136 FD_ZERO(&fds); 137 FD_SET(fd, &fds); 138 139 /* Timeout. */ 140 tv.tv_sec = 2; 141 tv.tv_usec = 0; 142 143 r = select(fd + 1, &fds, NULL, NULL, &tv); 144 } while ((r == -1 && (errno = EINTR))); 145 if (r == -1) { 146 perror("select"); 147 return errno; 148 } 149 150 CLEAR(buf); 151 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 152 buf.memory = V4L2_MEMORY_MMAP; 153 xioctl(fd, VIDIOC_DQBUF, &buf); 154 155 sprintf(out_name, "out%03d.ppm", i); 156 fout = fopen(out_name, "w"); 157 if (!fout) { 158 perror("Cannot open image"); 159 exit(EXIT_FAILURE); 160 } 161 fprintf(fout, "P6\\n%d %d 255\\n", 162 fmt.fmt.pix.width, fmt.fmt.pix.height); 163 fwrite(buffers[buf.index].start, buf.bytesused, 1, fout); 164 fclose(fout); 165 166 xioctl(fd, VIDIOC_QBUF, &buf); 167 } 168 169 type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 170 xioctl(fd, VIDIOC_STREAMOFF, &type); 171 for (i = 0; i < n_buffers; ++i) 172 v4l2_munmap(buffers[i].start, buffers[i].length); 173 v4l2_close(fd); 174 175 return 0; 176 } 177