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