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