xref: /openbmc/linux/Documentation/userspace-api/media/v4l/v4l2grab.c.rst (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
1059b1c5bSMauro Carvalho Chehab.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
254f38fcaSMauro Carvalho Chehab
354f38fcaSMauro Carvalho Chehabfile: media/v4l/v4l2grab.c
454f38fcaSMauro Carvalho Chehab==========================
554f38fcaSMauro Carvalho Chehab
654f38fcaSMauro Carvalho Chehab.. code-block:: c
754f38fcaSMauro Carvalho Chehab
854f38fcaSMauro Carvalho Chehab    /* V4L2 video picture grabber
954f38fcaSMauro Carvalho Chehab       Copyright (C) 2009 Mauro Carvalho Chehab <mchehab@kernel.org>
1054f38fcaSMauro Carvalho Chehab
1154f38fcaSMauro Carvalho Chehab       This program is free software; you can redistribute it and/or modify
1254f38fcaSMauro Carvalho Chehab       it under the terms of the GNU General Public License as published by
1354f38fcaSMauro Carvalho Chehab       the Free Software Foundation version 2 of the License.
1454f38fcaSMauro Carvalho Chehab
1554f38fcaSMauro Carvalho Chehab       This program is distributed in the hope that it will be useful,
1654f38fcaSMauro Carvalho Chehab       but WITHOUT ANY WARRANTY; without even the implied warranty of
1754f38fcaSMauro Carvalho Chehab       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1854f38fcaSMauro Carvalho Chehab       GNU General Public License for more details.
1954f38fcaSMauro Carvalho Chehab     */
2054f38fcaSMauro Carvalho Chehab
2154f38fcaSMauro Carvalho Chehab    #include <stdio.h>
2254f38fcaSMauro Carvalho Chehab    #include <stdlib.h>
2354f38fcaSMauro Carvalho Chehab    #include <string.h>
2454f38fcaSMauro Carvalho Chehab    #include <fcntl.h>
2554f38fcaSMauro Carvalho Chehab    #include <errno.h>
2654f38fcaSMauro Carvalho Chehab    #include <sys/ioctl.h>
2754f38fcaSMauro Carvalho Chehab    #include <sys/types.h>
2854f38fcaSMauro Carvalho Chehab    #include <sys/time.h>
2954f38fcaSMauro Carvalho Chehab    #include <sys/mman.h>
3054f38fcaSMauro Carvalho Chehab    #include <linux/videodev2.h>
3154f38fcaSMauro Carvalho Chehab    #include "../libv4l/include/libv4l2.h"
3254f38fcaSMauro Carvalho Chehab
3354f38fcaSMauro Carvalho Chehab    #define CLEAR(x) memset(&(x), 0, sizeof(x))
3454f38fcaSMauro Carvalho Chehab
3554f38fcaSMauro Carvalho Chehab    struct buffer {
3654f38fcaSMauro Carvalho Chehab	    void   *start;
3754f38fcaSMauro Carvalho Chehab	    size_t length;
3854f38fcaSMauro Carvalho Chehab    };
3954f38fcaSMauro Carvalho Chehab
4054f38fcaSMauro Carvalho Chehab    static void xioctl(int fh, int request, void *arg)
4154f38fcaSMauro Carvalho Chehab    {
4254f38fcaSMauro Carvalho Chehab	    int r;
4354f38fcaSMauro Carvalho Chehab
4454f38fcaSMauro Carvalho Chehab	    do {
4554f38fcaSMauro Carvalho Chehab		    r = v4l2_ioctl(fh, request, arg);
4654f38fcaSMauro Carvalho Chehab	    } while (r == -1 && ((errno == EINTR) || (errno == EAGAIN)));
4754f38fcaSMauro Carvalho Chehab
4854f38fcaSMauro Carvalho Chehab	    if (r == -1) {
49d7894721SKwang Son		    fprintf(stderr, "error %d, %s\n", errno, strerror(errno));
5054f38fcaSMauro Carvalho Chehab		    exit(EXIT_FAILURE);
5154f38fcaSMauro Carvalho Chehab	    }
5254f38fcaSMauro Carvalho Chehab    }
5354f38fcaSMauro Carvalho Chehab
5454f38fcaSMauro Carvalho Chehab    int main(int argc, char **argv)
5554f38fcaSMauro Carvalho Chehab    {
5654f38fcaSMauro Carvalho Chehab	    struct v4l2_format              fmt;
5754f38fcaSMauro Carvalho Chehab	    struct v4l2_buffer              buf;
5854f38fcaSMauro Carvalho Chehab	    struct v4l2_requestbuffers      req;
5954f38fcaSMauro Carvalho Chehab	    enum v4l2_buf_type              type;
6054f38fcaSMauro Carvalho Chehab	    fd_set                          fds;
6154f38fcaSMauro Carvalho Chehab	    struct timeval                  tv;
6254f38fcaSMauro Carvalho Chehab	    int                             r, fd = -1;
6354f38fcaSMauro Carvalho Chehab	    unsigned int                    i, n_buffers;
6454f38fcaSMauro Carvalho Chehab	    char                            *dev_name = "/dev/video0";
6554f38fcaSMauro Carvalho Chehab	    char                            out_name[256];
6654f38fcaSMauro Carvalho Chehab	    FILE                            *fout;
6754f38fcaSMauro Carvalho Chehab	    struct buffer                   *buffers;
6854f38fcaSMauro Carvalho Chehab
6954f38fcaSMauro Carvalho Chehab	    fd = v4l2_open(dev_name, O_RDWR | O_NONBLOCK, 0);
7054f38fcaSMauro Carvalho Chehab	    if (fd < 0) {
7154f38fcaSMauro Carvalho Chehab		    perror("Cannot open device");
7254f38fcaSMauro Carvalho Chehab		    exit(EXIT_FAILURE);
7354f38fcaSMauro Carvalho Chehab	    }
7454f38fcaSMauro Carvalho Chehab
7554f38fcaSMauro Carvalho Chehab	    CLEAR(fmt);
7654f38fcaSMauro Carvalho Chehab	    fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
7754f38fcaSMauro Carvalho Chehab	    fmt.fmt.pix.width       = 640;
7854f38fcaSMauro Carvalho Chehab	    fmt.fmt.pix.height      = 480;
7954f38fcaSMauro Carvalho Chehab	    fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB24;
8054f38fcaSMauro Carvalho Chehab	    fmt.fmt.pix.field       = V4L2_FIELD_INTERLACED;
8154f38fcaSMauro Carvalho Chehab	    xioctl(fd, VIDIOC_S_FMT, &fmt);
8254f38fcaSMauro Carvalho Chehab	    if (fmt.fmt.pix.pixelformat != V4L2_PIX_FMT_RGB24) {
83d7894721SKwang Son		    printf("Libv4l didn't accept RGB24 format. Can't proceed.\n");
8454f38fcaSMauro Carvalho Chehab		    exit(EXIT_FAILURE);
8554f38fcaSMauro Carvalho Chehab	    }
8654f38fcaSMauro Carvalho Chehab	    if ((fmt.fmt.pix.width != 640) || (fmt.fmt.pix.height != 480))
87d7894721SKwang Son		    printf("Warning: driver is sending image at %dx%d\n",
8854f38fcaSMauro Carvalho Chehab			    fmt.fmt.pix.width, fmt.fmt.pix.height);
8954f38fcaSMauro Carvalho Chehab
9054f38fcaSMauro Carvalho Chehab	    CLEAR(req);
9154f38fcaSMauro Carvalho Chehab	    req.count = 2;
9254f38fcaSMauro Carvalho Chehab	    req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
9354f38fcaSMauro Carvalho Chehab	    req.memory = V4L2_MEMORY_MMAP;
9454f38fcaSMauro Carvalho Chehab	    xioctl(fd, VIDIOC_REQBUFS, &req);
9554f38fcaSMauro Carvalho Chehab
9654f38fcaSMauro Carvalho Chehab	    buffers = calloc(req.count, sizeof(*buffers));
9754f38fcaSMauro Carvalho Chehab	    for (n_buffers = 0; n_buffers < req.count; ++n_buffers) {
9854f38fcaSMauro Carvalho Chehab		    CLEAR(buf);
9954f38fcaSMauro Carvalho Chehab
10054f38fcaSMauro Carvalho Chehab		    buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;
10154f38fcaSMauro Carvalho Chehab		    buf.memory      = V4L2_MEMORY_MMAP;
10254f38fcaSMauro Carvalho Chehab		    buf.index       = n_buffers;
10354f38fcaSMauro Carvalho Chehab
10454f38fcaSMauro Carvalho Chehab		    xioctl(fd, VIDIOC_QUERYBUF, &buf);
10554f38fcaSMauro Carvalho Chehab
10654f38fcaSMauro Carvalho Chehab		    buffers[n_buffers].length = buf.length;
10754f38fcaSMauro Carvalho Chehab		    buffers[n_buffers].start = v4l2_mmap(NULL, buf.length,
10854f38fcaSMauro Carvalho Chehab				  PROT_READ | PROT_WRITE, MAP_SHARED,
10954f38fcaSMauro Carvalho Chehab				  fd, buf.m.offset);
11054f38fcaSMauro Carvalho Chehab
11154f38fcaSMauro Carvalho Chehab		    if (MAP_FAILED == buffers[n_buffers].start) {
11254f38fcaSMauro Carvalho Chehab			    perror("mmap");
11354f38fcaSMauro Carvalho Chehab			    exit(EXIT_FAILURE);
11454f38fcaSMauro Carvalho Chehab		    }
11554f38fcaSMauro Carvalho Chehab	    }
11654f38fcaSMauro Carvalho Chehab
11754f38fcaSMauro Carvalho Chehab	    for (i = 0; i < n_buffers; ++i) {
11854f38fcaSMauro Carvalho Chehab		    CLEAR(buf);
11954f38fcaSMauro Carvalho Chehab		    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
12054f38fcaSMauro Carvalho Chehab		    buf.memory = V4L2_MEMORY_MMAP;
12154f38fcaSMauro Carvalho Chehab		    buf.index = i;
12254f38fcaSMauro Carvalho Chehab		    xioctl(fd, VIDIOC_QBUF, &buf);
12354f38fcaSMauro Carvalho Chehab	    }
12454f38fcaSMauro Carvalho Chehab	    type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
12554f38fcaSMauro Carvalho Chehab
12654f38fcaSMauro Carvalho Chehab	    xioctl(fd, VIDIOC_STREAMON, &type);
12754f38fcaSMauro Carvalho Chehab	    for (i = 0; i < 20; i++) {
12854f38fcaSMauro Carvalho Chehab		    do {
12954f38fcaSMauro Carvalho Chehab			    FD_ZERO(&fds);
13054f38fcaSMauro Carvalho Chehab			    FD_SET(fd, &fds);
13154f38fcaSMauro Carvalho Chehab
13254f38fcaSMauro Carvalho Chehab			    /* Timeout. */
13354f38fcaSMauro Carvalho Chehab			    tv.tv_sec = 2;
13454f38fcaSMauro Carvalho Chehab			    tv.tv_usec = 0;
13554f38fcaSMauro Carvalho Chehab
13654f38fcaSMauro Carvalho Chehab			    r = select(fd + 1, &fds, NULL, NULL, &tv);
137*db839726SDaniel Lundberg Pedersen		    } while ((r == -1 && (errno == EINTR)));
13854f38fcaSMauro Carvalho Chehab		    if (r == -1) {
13954f38fcaSMauro Carvalho Chehab			    perror("select");
14054f38fcaSMauro Carvalho Chehab			    return errno;
14154f38fcaSMauro Carvalho Chehab		    }
14254f38fcaSMauro Carvalho Chehab
14354f38fcaSMauro Carvalho Chehab		    CLEAR(buf);
14454f38fcaSMauro Carvalho Chehab		    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
14554f38fcaSMauro Carvalho Chehab		    buf.memory = V4L2_MEMORY_MMAP;
14654f38fcaSMauro Carvalho Chehab		    xioctl(fd, VIDIOC_DQBUF, &buf);
14754f38fcaSMauro Carvalho Chehab
14854f38fcaSMauro Carvalho Chehab		    sprintf(out_name, "out%03d.ppm", i);
14954f38fcaSMauro Carvalho Chehab		    fout = fopen(out_name, "w");
15054f38fcaSMauro Carvalho Chehab		    if (!fout) {
15154f38fcaSMauro Carvalho Chehab			    perror("Cannot open image");
15254f38fcaSMauro Carvalho Chehab			    exit(EXIT_FAILURE);
15354f38fcaSMauro Carvalho Chehab		    }
154d7894721SKwang Son		    fprintf(fout, "P6\n%d %d 255\n",
15554f38fcaSMauro Carvalho Chehab			    fmt.fmt.pix.width, fmt.fmt.pix.height);
15654f38fcaSMauro Carvalho Chehab		    fwrite(buffers[buf.index].start, buf.bytesused, 1, fout);
15754f38fcaSMauro Carvalho Chehab		    fclose(fout);
15854f38fcaSMauro Carvalho Chehab
15954f38fcaSMauro Carvalho Chehab		    xioctl(fd, VIDIOC_QBUF, &buf);
16054f38fcaSMauro Carvalho Chehab	    }
16154f38fcaSMauro Carvalho Chehab
16254f38fcaSMauro Carvalho Chehab	    type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
16354f38fcaSMauro Carvalho Chehab	    xioctl(fd, VIDIOC_STREAMOFF, &type);
16454f38fcaSMauro Carvalho Chehab	    for (i = 0; i < n_buffers; ++i)
16554f38fcaSMauro Carvalho Chehab		    v4l2_munmap(buffers[i].start, buffers[i].length);
16654f38fcaSMauro Carvalho Chehab	    v4l2_close(fd);
16754f38fcaSMauro Carvalho Chehab
16854f38fcaSMauro Carvalho Chehab	    return 0;
16954f38fcaSMauro Carvalho Chehab    }
170