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