xref: /openbmc/linux/Documentation/userspace-api/media/v4l/v4l2grab.c.rst (revision 54f38fcae536ea202ce7d6a359521492fba30c1f)
1*54f38fcaSMauro Carvalho Chehab.. Permission is granted to copy, distribute and/or modify this
2*54f38fcaSMauro Carvalho Chehab.. document under the terms of the GNU Free Documentation License,
3*54f38fcaSMauro Carvalho Chehab.. Version 1.1 or any later version published by the Free Software
4*54f38fcaSMauro Carvalho Chehab.. Foundation, with no Invariant Sections, no Front-Cover Texts
5*54f38fcaSMauro Carvalho Chehab.. and no Back-Cover Texts. A copy of the license is included at
6*54f38fcaSMauro Carvalho Chehab.. Documentation/userspace-api/media/fdl-appendix.rst.
7*54f38fcaSMauro Carvalho Chehab..
8*54f38fcaSMauro Carvalho Chehab.. TODO: replace it to GFDL-1.1-or-later WITH no-invariant-sections
9*54f38fcaSMauro Carvalho Chehab
10*54f38fcaSMauro Carvalho Chehabfile: media/v4l/v4l2grab.c
11*54f38fcaSMauro Carvalho Chehab==========================
12*54f38fcaSMauro Carvalho Chehab
13*54f38fcaSMauro Carvalho Chehab.. code-block:: c
14*54f38fcaSMauro Carvalho Chehab
15*54f38fcaSMauro Carvalho Chehab    /* V4L2 video picture grabber
16*54f38fcaSMauro Carvalho Chehab       Copyright (C) 2009 Mauro Carvalho Chehab <mchehab@kernel.org>
17*54f38fcaSMauro Carvalho Chehab
18*54f38fcaSMauro Carvalho Chehab       This program is free software; you can redistribute it and/or modify
19*54f38fcaSMauro Carvalho Chehab       it under the terms of the GNU General Public License as published by
20*54f38fcaSMauro Carvalho Chehab       the Free Software Foundation version 2 of the License.
21*54f38fcaSMauro Carvalho Chehab
22*54f38fcaSMauro Carvalho Chehab       This program is distributed in the hope that it will be useful,
23*54f38fcaSMauro Carvalho Chehab       but WITHOUT ANY WARRANTY; without even the implied warranty of
24*54f38fcaSMauro Carvalho Chehab       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25*54f38fcaSMauro Carvalho Chehab       GNU General Public License for more details.
26*54f38fcaSMauro Carvalho Chehab     */
27*54f38fcaSMauro Carvalho Chehab
28*54f38fcaSMauro Carvalho Chehab    #include <stdio.h>
29*54f38fcaSMauro Carvalho Chehab    #include <stdlib.h>
30*54f38fcaSMauro Carvalho Chehab    #include <string.h>
31*54f38fcaSMauro Carvalho Chehab    #include <fcntl.h>
32*54f38fcaSMauro Carvalho Chehab    #include <errno.h>
33*54f38fcaSMauro Carvalho Chehab    #include <sys/ioctl.h>
34*54f38fcaSMauro Carvalho Chehab    #include <sys/types.h>
35*54f38fcaSMauro Carvalho Chehab    #include <sys/time.h>
36*54f38fcaSMauro Carvalho Chehab    #include <sys/mman.h>
37*54f38fcaSMauro Carvalho Chehab    #include <linux/videodev2.h>
38*54f38fcaSMauro Carvalho Chehab    #include "../libv4l/include/libv4l2.h"
39*54f38fcaSMauro Carvalho Chehab
40*54f38fcaSMauro Carvalho Chehab    #define CLEAR(x) memset(&(x), 0, sizeof(x))
41*54f38fcaSMauro Carvalho Chehab
42*54f38fcaSMauro Carvalho Chehab    struct buffer {
43*54f38fcaSMauro Carvalho Chehab	    void   *start;
44*54f38fcaSMauro Carvalho Chehab	    size_t length;
45*54f38fcaSMauro Carvalho Chehab    };
46*54f38fcaSMauro Carvalho Chehab
47*54f38fcaSMauro Carvalho Chehab    static void xioctl(int fh, int request, void *arg)
48*54f38fcaSMauro Carvalho Chehab    {
49*54f38fcaSMauro Carvalho Chehab	    int r;
50*54f38fcaSMauro Carvalho Chehab
51*54f38fcaSMauro Carvalho Chehab	    do {
52*54f38fcaSMauro Carvalho Chehab		    r = v4l2_ioctl(fh, request, arg);
53*54f38fcaSMauro Carvalho Chehab	    } while (r == -1 && ((errno == EINTR) || (errno == EAGAIN)));
54*54f38fcaSMauro Carvalho Chehab
55*54f38fcaSMauro Carvalho Chehab	    if (r == -1) {
56*54f38fcaSMauro Carvalho Chehab		    fprintf(stderr, "error %d, %s\\n", errno, strerror(errno));
57*54f38fcaSMauro Carvalho Chehab		    exit(EXIT_FAILURE);
58*54f38fcaSMauro Carvalho Chehab	    }
59*54f38fcaSMauro Carvalho Chehab    }
60*54f38fcaSMauro Carvalho Chehab
61*54f38fcaSMauro Carvalho Chehab    int main(int argc, char **argv)
62*54f38fcaSMauro Carvalho Chehab    {
63*54f38fcaSMauro Carvalho Chehab	    struct v4l2_format              fmt;
64*54f38fcaSMauro Carvalho Chehab	    struct v4l2_buffer              buf;
65*54f38fcaSMauro Carvalho Chehab	    struct v4l2_requestbuffers      req;
66*54f38fcaSMauro Carvalho Chehab	    enum v4l2_buf_type              type;
67*54f38fcaSMauro Carvalho Chehab	    fd_set                          fds;
68*54f38fcaSMauro Carvalho Chehab	    struct timeval                  tv;
69*54f38fcaSMauro Carvalho Chehab	    int                             r, fd = -1;
70*54f38fcaSMauro Carvalho Chehab	    unsigned int                    i, n_buffers;
71*54f38fcaSMauro Carvalho Chehab	    char                            *dev_name = "/dev/video0";
72*54f38fcaSMauro Carvalho Chehab	    char                            out_name[256];
73*54f38fcaSMauro Carvalho Chehab	    FILE                            *fout;
74*54f38fcaSMauro Carvalho Chehab	    struct buffer                   *buffers;
75*54f38fcaSMauro Carvalho Chehab
76*54f38fcaSMauro Carvalho Chehab	    fd = v4l2_open(dev_name, O_RDWR | O_NONBLOCK, 0);
77*54f38fcaSMauro Carvalho Chehab	    if (fd < 0) {
78*54f38fcaSMauro Carvalho Chehab		    perror("Cannot open device");
79*54f38fcaSMauro Carvalho Chehab		    exit(EXIT_FAILURE);
80*54f38fcaSMauro Carvalho Chehab	    }
81*54f38fcaSMauro Carvalho Chehab
82*54f38fcaSMauro Carvalho Chehab	    CLEAR(fmt);
83*54f38fcaSMauro Carvalho Chehab	    fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
84*54f38fcaSMauro Carvalho Chehab	    fmt.fmt.pix.width       = 640;
85*54f38fcaSMauro Carvalho Chehab	    fmt.fmt.pix.height      = 480;
86*54f38fcaSMauro Carvalho Chehab	    fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB24;
87*54f38fcaSMauro Carvalho Chehab	    fmt.fmt.pix.field       = V4L2_FIELD_INTERLACED;
88*54f38fcaSMauro Carvalho Chehab	    xioctl(fd, VIDIOC_S_FMT, &fmt);
89*54f38fcaSMauro Carvalho Chehab	    if (fmt.fmt.pix.pixelformat != V4L2_PIX_FMT_RGB24) {
90*54f38fcaSMauro Carvalho Chehab		    printf("Libv4l didn't accept RGB24 format. Can't proceed.\\n");
91*54f38fcaSMauro Carvalho Chehab		    exit(EXIT_FAILURE);
92*54f38fcaSMauro Carvalho Chehab	    }
93*54f38fcaSMauro Carvalho Chehab	    if ((fmt.fmt.pix.width != 640) || (fmt.fmt.pix.height != 480))
94*54f38fcaSMauro Carvalho Chehab		    printf("Warning: driver is sending image at %dx%d\\n",
95*54f38fcaSMauro Carvalho Chehab			    fmt.fmt.pix.width, fmt.fmt.pix.height);
96*54f38fcaSMauro Carvalho Chehab
97*54f38fcaSMauro Carvalho Chehab	    CLEAR(req);
98*54f38fcaSMauro Carvalho Chehab	    req.count = 2;
99*54f38fcaSMauro Carvalho Chehab	    req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
100*54f38fcaSMauro Carvalho Chehab	    req.memory = V4L2_MEMORY_MMAP;
101*54f38fcaSMauro Carvalho Chehab	    xioctl(fd, VIDIOC_REQBUFS, &req);
102*54f38fcaSMauro Carvalho Chehab
103*54f38fcaSMauro Carvalho Chehab	    buffers = calloc(req.count, sizeof(*buffers));
104*54f38fcaSMauro Carvalho Chehab	    for (n_buffers = 0; n_buffers < req.count; ++n_buffers) {
105*54f38fcaSMauro Carvalho Chehab		    CLEAR(buf);
106*54f38fcaSMauro Carvalho Chehab
107*54f38fcaSMauro Carvalho Chehab		    buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;
108*54f38fcaSMauro Carvalho Chehab		    buf.memory      = V4L2_MEMORY_MMAP;
109*54f38fcaSMauro Carvalho Chehab		    buf.index       = n_buffers;
110*54f38fcaSMauro Carvalho Chehab
111*54f38fcaSMauro Carvalho Chehab		    xioctl(fd, VIDIOC_QUERYBUF, &buf);
112*54f38fcaSMauro Carvalho Chehab
113*54f38fcaSMauro Carvalho Chehab		    buffers[n_buffers].length = buf.length;
114*54f38fcaSMauro Carvalho Chehab		    buffers[n_buffers].start = v4l2_mmap(NULL, buf.length,
115*54f38fcaSMauro Carvalho Chehab				  PROT_READ | PROT_WRITE, MAP_SHARED,
116*54f38fcaSMauro Carvalho Chehab				  fd, buf.m.offset);
117*54f38fcaSMauro Carvalho Chehab
118*54f38fcaSMauro Carvalho Chehab		    if (MAP_FAILED == buffers[n_buffers].start) {
119*54f38fcaSMauro Carvalho Chehab			    perror("mmap");
120*54f38fcaSMauro Carvalho Chehab			    exit(EXIT_FAILURE);
121*54f38fcaSMauro Carvalho Chehab		    }
122*54f38fcaSMauro Carvalho Chehab	    }
123*54f38fcaSMauro Carvalho Chehab
124*54f38fcaSMauro Carvalho Chehab	    for (i = 0; i < n_buffers; ++i) {
125*54f38fcaSMauro Carvalho Chehab		    CLEAR(buf);
126*54f38fcaSMauro Carvalho Chehab		    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
127*54f38fcaSMauro Carvalho Chehab		    buf.memory = V4L2_MEMORY_MMAP;
128*54f38fcaSMauro Carvalho Chehab		    buf.index = i;
129*54f38fcaSMauro Carvalho Chehab		    xioctl(fd, VIDIOC_QBUF, &buf);
130*54f38fcaSMauro Carvalho Chehab	    }
131*54f38fcaSMauro Carvalho Chehab	    type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
132*54f38fcaSMauro Carvalho Chehab
133*54f38fcaSMauro Carvalho Chehab	    xioctl(fd, VIDIOC_STREAMON, &type);
134*54f38fcaSMauro Carvalho Chehab	    for (i = 0; i < 20; i++) {
135*54f38fcaSMauro Carvalho Chehab		    do {
136*54f38fcaSMauro Carvalho Chehab			    FD_ZERO(&fds);
137*54f38fcaSMauro Carvalho Chehab			    FD_SET(fd, &fds);
138*54f38fcaSMauro Carvalho Chehab
139*54f38fcaSMauro Carvalho Chehab			    /* Timeout. */
140*54f38fcaSMauro Carvalho Chehab			    tv.tv_sec = 2;
141*54f38fcaSMauro Carvalho Chehab			    tv.tv_usec = 0;
142*54f38fcaSMauro Carvalho Chehab
143*54f38fcaSMauro Carvalho Chehab			    r = select(fd + 1, &fds, NULL, NULL, &tv);
144*54f38fcaSMauro Carvalho Chehab		    } while ((r == -1 && (errno = EINTR)));
145*54f38fcaSMauro Carvalho Chehab		    if (r == -1) {
146*54f38fcaSMauro Carvalho Chehab			    perror("select");
147*54f38fcaSMauro Carvalho Chehab			    return errno;
148*54f38fcaSMauro Carvalho Chehab		    }
149*54f38fcaSMauro Carvalho Chehab
150*54f38fcaSMauro Carvalho Chehab		    CLEAR(buf);
151*54f38fcaSMauro Carvalho Chehab		    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
152*54f38fcaSMauro Carvalho Chehab		    buf.memory = V4L2_MEMORY_MMAP;
153*54f38fcaSMauro Carvalho Chehab		    xioctl(fd, VIDIOC_DQBUF, &buf);
154*54f38fcaSMauro Carvalho Chehab
155*54f38fcaSMauro Carvalho Chehab		    sprintf(out_name, "out%03d.ppm", i);
156*54f38fcaSMauro Carvalho Chehab		    fout = fopen(out_name, "w");
157*54f38fcaSMauro Carvalho Chehab		    if (!fout) {
158*54f38fcaSMauro Carvalho Chehab			    perror("Cannot open image");
159*54f38fcaSMauro Carvalho Chehab			    exit(EXIT_FAILURE);
160*54f38fcaSMauro Carvalho Chehab		    }
161*54f38fcaSMauro Carvalho Chehab		    fprintf(fout, "P6\\n%d %d 255\\n",
162*54f38fcaSMauro Carvalho Chehab			    fmt.fmt.pix.width, fmt.fmt.pix.height);
163*54f38fcaSMauro Carvalho Chehab		    fwrite(buffers[buf.index].start, buf.bytesused, 1, fout);
164*54f38fcaSMauro Carvalho Chehab		    fclose(fout);
165*54f38fcaSMauro Carvalho Chehab
166*54f38fcaSMauro Carvalho Chehab		    xioctl(fd, VIDIOC_QBUF, &buf);
167*54f38fcaSMauro Carvalho Chehab	    }
168*54f38fcaSMauro Carvalho Chehab
169*54f38fcaSMauro Carvalho Chehab	    type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
170*54f38fcaSMauro Carvalho Chehab	    xioctl(fd, VIDIOC_STREAMOFF, &type);
171*54f38fcaSMauro Carvalho Chehab	    for (i = 0; i < n_buffers; ++i)
172*54f38fcaSMauro Carvalho Chehab		    v4l2_munmap(buffers[i].start, buffers[i].length);
173*54f38fcaSMauro Carvalho Chehab	    v4l2_close(fd);
174*54f38fcaSMauro Carvalho Chehab
175*54f38fcaSMauro Carvalho Chehab	    return 0;
176*54f38fcaSMauro Carvalho Chehab    }
177