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