About Kernel Documentation Linux Kernel Contact Linux Resources Linux Blog

Documentation / DocBook / media / v4l / capture.c.xml


Based on kernel version 4.7.2. Page generated on 2016-08-22 22:44 EST.

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 https://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>
Hide Line Numbers


About Kernel Documentation Linux Kernel Contact Linux Resources Linux Blog