GNU Linux-libre 4.14.295-gnu1
[releases.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     }