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