Merge branch 'next-seccomp' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris...
[sfrench/cifs-2.6.git] / Documentation / media / uapi / v4l / v4l2grab.c.rst
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/media/uapi/fdl-appendix.rst.
7 ..
8 .. TODO: replace it to GFDL-1.1-or-later WITH no-invariant-sections
9
10 file: 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     }