perf report: Use ui__warning in some more places
[pandora-kernel.git] / Documentation / DocBook / v4l / capture.c.xml
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 &lt;stdio.h&gt;
12 #include &lt;stdlib.h&gt;
13 #include &lt;string.h&gt;
14 #include &lt;assert.h&gt;
15
16 #include &lt;getopt.h&gt;             /* getopt_long() */
17
18 #include &lt;fcntl.h&gt;              /* low-level i/o */
19 #include &lt;unistd.h&gt;
20 #include &lt;errno.h&gt;
21 #include &lt;sys/stat.h&gt;
22 #include &lt;sys/types.h&gt;
23 #include &lt;sys/time.h&gt;
24 #include &lt;sys/mman.h&gt;
25 #include &lt;sys/ioctl.h&gt;
26
27 #include &lt;linux/videodev2.h&gt;
28
29 #define CLEAR(x) memset(&amp;(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 &amp;&amp; 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, &amp;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 &lt; n_buffers);
125
126                 process_image(buffers[buf.index].start, buf.bytesused);
127
128                 if (-1 == xioctl(fd, VIDIOC_QBUF, &amp;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, &amp;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 &lt; n_buffers; ++i)
154                         if (buf.m.userptr == (unsigned long)buffers[i].start
155                             &amp;&amp; buf.length == buffers[i].length)
156                                 break;
157
158                 assert(i &lt; n_buffers);
159
160                 process_image((void *)buf.m.userptr, buf.bytesused);
161
162                 if (-1 == xioctl(fd, VIDIOC_QBUF, &amp;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-- &gt; 0) {
177                 for (;;) {
178                         fd_set fds;
179                         struct timeval tv;
180                         int r;
181
182                         FD_ZERO(&amp;fds);
183                         FD_SET(fd, &amp;fds);
184
185                         /* Timeout. */
186                         tv.tv_sec = 2;
187                         tv.tv_usec = 0;
188
189                         r = select(fd + 1, &amp;fds, NULL, NULL, &amp;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, &amp;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 &lt; 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, &amp;buf))
247                                 errno_exit("VIDIOC_QBUF");
248                 }
249                 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
250                 if (-1 == xioctl(fd, VIDIOC_STREAMON, &amp;type))
251                         errno_exit("VIDIOC_STREAMON");
252                 break;
253
254         case IO_METHOD_USERPTR:
255                 for (i = 0; i &lt; 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, &amp;buf))
266                                 errno_exit("VIDIOC_QBUF");
267                 }
268                 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
269                 if (-1 == xioctl(fd, VIDIOC_STREAMON, &amp;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 &lt; 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 &lt; 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, &amp;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 &lt; 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 &lt; 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, &amp;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, &amp;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 &lt; 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, &amp;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 &amp; 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 &amp; 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 &amp; 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, &amp;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, &amp;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, &amp;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, &amp;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 &lt; min)
505                 fmt.fmt.pix.bytesperline = min;
506         min = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height;
507         if (fmt.fmt.pix.sizeimage &lt; 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, &amp;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, &amp;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>