18c2ecf20Sopenharmony_ci.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later 28c2ecf20Sopenharmony_ci 38c2ecf20Sopenharmony_cifile: media/v4l/v4l2grab.c 48c2ecf20Sopenharmony_ci========================== 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci.. code-block:: c 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci /* V4L2 video picture grabber 98c2ecf20Sopenharmony_ci Copyright (C) 2009 Mauro Carvalho Chehab <mchehab@kernel.org> 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci This program is free software; you can redistribute it and/or modify 128c2ecf20Sopenharmony_ci it under the terms of the GNU General Public License as published by 138c2ecf20Sopenharmony_ci the Free Software Foundation version 2 of the License. 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci This program is distributed in the hope that it will be useful, 168c2ecf20Sopenharmony_ci but WITHOUT ANY WARRANTY; without even the implied warranty of 178c2ecf20Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 188c2ecf20Sopenharmony_ci GNU General Public License for more details. 198c2ecf20Sopenharmony_ci */ 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci #include <stdio.h> 228c2ecf20Sopenharmony_ci #include <stdlib.h> 238c2ecf20Sopenharmony_ci #include <string.h> 248c2ecf20Sopenharmony_ci #include <fcntl.h> 258c2ecf20Sopenharmony_ci #include <errno.h> 268c2ecf20Sopenharmony_ci #include <sys/ioctl.h> 278c2ecf20Sopenharmony_ci #include <sys/types.h> 288c2ecf20Sopenharmony_ci #include <sys/time.h> 298c2ecf20Sopenharmony_ci #include <sys/mman.h> 308c2ecf20Sopenharmony_ci #include <linux/videodev2.h> 318c2ecf20Sopenharmony_ci #include "../libv4l/include/libv4l2.h" 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci #define CLEAR(x) memset(&(x), 0, sizeof(x)) 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci struct buffer { 368c2ecf20Sopenharmony_ci void *start; 378c2ecf20Sopenharmony_ci size_t length; 388c2ecf20Sopenharmony_ci }; 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci static void xioctl(int fh, int request, void *arg) 418c2ecf20Sopenharmony_ci { 428c2ecf20Sopenharmony_ci int r; 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci do { 458c2ecf20Sopenharmony_ci r = v4l2_ioctl(fh, request, arg); 468c2ecf20Sopenharmony_ci } while (r == -1 && ((errno == EINTR) || (errno == EAGAIN))); 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci if (r == -1) { 498c2ecf20Sopenharmony_ci fprintf(stderr, "error %d, %s\\n", errno, strerror(errno)); 508c2ecf20Sopenharmony_ci exit(EXIT_FAILURE); 518c2ecf20Sopenharmony_ci } 528c2ecf20Sopenharmony_ci } 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci int main(int argc, char **argv) 558c2ecf20Sopenharmony_ci { 568c2ecf20Sopenharmony_ci struct v4l2_format fmt; 578c2ecf20Sopenharmony_ci struct v4l2_buffer buf; 588c2ecf20Sopenharmony_ci struct v4l2_requestbuffers req; 598c2ecf20Sopenharmony_ci enum v4l2_buf_type type; 608c2ecf20Sopenharmony_ci fd_set fds; 618c2ecf20Sopenharmony_ci struct timeval tv; 628c2ecf20Sopenharmony_ci int r, fd = -1; 638c2ecf20Sopenharmony_ci unsigned int i, n_buffers; 648c2ecf20Sopenharmony_ci char *dev_name = "/dev/video0"; 658c2ecf20Sopenharmony_ci char out_name[256]; 668c2ecf20Sopenharmony_ci FILE *fout; 678c2ecf20Sopenharmony_ci struct buffer *buffers; 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci fd = v4l2_open(dev_name, O_RDWR | O_NONBLOCK, 0); 708c2ecf20Sopenharmony_ci if (fd < 0) { 718c2ecf20Sopenharmony_ci perror("Cannot open device"); 728c2ecf20Sopenharmony_ci exit(EXIT_FAILURE); 738c2ecf20Sopenharmony_ci } 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci CLEAR(fmt); 768c2ecf20Sopenharmony_ci fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 778c2ecf20Sopenharmony_ci fmt.fmt.pix.width = 640; 788c2ecf20Sopenharmony_ci fmt.fmt.pix.height = 480; 798c2ecf20Sopenharmony_ci fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB24; 808c2ecf20Sopenharmony_ci fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; 818c2ecf20Sopenharmony_ci xioctl(fd, VIDIOC_S_FMT, &fmt); 828c2ecf20Sopenharmony_ci if (fmt.fmt.pix.pixelformat != V4L2_PIX_FMT_RGB24) { 838c2ecf20Sopenharmony_ci printf("Libv4l didn't accept RGB24 format. Can't proceed.\\n"); 848c2ecf20Sopenharmony_ci exit(EXIT_FAILURE); 858c2ecf20Sopenharmony_ci } 868c2ecf20Sopenharmony_ci if ((fmt.fmt.pix.width != 640) || (fmt.fmt.pix.height != 480)) 878c2ecf20Sopenharmony_ci printf("Warning: driver is sending image at %dx%d\\n", 888c2ecf20Sopenharmony_ci fmt.fmt.pix.width, fmt.fmt.pix.height); 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci CLEAR(req); 918c2ecf20Sopenharmony_ci req.count = 2; 928c2ecf20Sopenharmony_ci req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 938c2ecf20Sopenharmony_ci req.memory = V4L2_MEMORY_MMAP; 948c2ecf20Sopenharmony_ci xioctl(fd, VIDIOC_REQBUFS, &req); 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci buffers = calloc(req.count, sizeof(*buffers)); 978c2ecf20Sopenharmony_ci for (n_buffers = 0; n_buffers < req.count; ++n_buffers) { 988c2ecf20Sopenharmony_ci CLEAR(buf); 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 1018c2ecf20Sopenharmony_ci buf.memory = V4L2_MEMORY_MMAP; 1028c2ecf20Sopenharmony_ci buf.index = n_buffers; 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci xioctl(fd, VIDIOC_QUERYBUF, &buf); 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci buffers[n_buffers].length = buf.length; 1078c2ecf20Sopenharmony_ci buffers[n_buffers].start = v4l2_mmap(NULL, buf.length, 1088c2ecf20Sopenharmony_ci PROT_READ | PROT_WRITE, MAP_SHARED, 1098c2ecf20Sopenharmony_ci fd, buf.m.offset); 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci if (MAP_FAILED == buffers[n_buffers].start) { 1128c2ecf20Sopenharmony_ci perror("mmap"); 1138c2ecf20Sopenharmony_ci exit(EXIT_FAILURE); 1148c2ecf20Sopenharmony_ci } 1158c2ecf20Sopenharmony_ci } 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci for (i = 0; i < n_buffers; ++i) { 1188c2ecf20Sopenharmony_ci CLEAR(buf); 1198c2ecf20Sopenharmony_ci buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 1208c2ecf20Sopenharmony_ci buf.memory = V4L2_MEMORY_MMAP; 1218c2ecf20Sopenharmony_ci buf.index = i; 1228c2ecf20Sopenharmony_ci xioctl(fd, VIDIOC_QBUF, &buf); 1238c2ecf20Sopenharmony_ci } 1248c2ecf20Sopenharmony_ci type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci xioctl(fd, VIDIOC_STREAMON, &type); 1278c2ecf20Sopenharmony_ci for (i = 0; i < 20; i++) { 1288c2ecf20Sopenharmony_ci do { 1298c2ecf20Sopenharmony_ci FD_ZERO(&fds); 1308c2ecf20Sopenharmony_ci FD_SET(fd, &fds); 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci /* Timeout. */ 1338c2ecf20Sopenharmony_ci tv.tv_sec = 2; 1348c2ecf20Sopenharmony_ci tv.tv_usec = 0; 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci r = select(fd + 1, &fds, NULL, NULL, &tv); 1378c2ecf20Sopenharmony_ci } while ((r == -1 && (errno = EINTR))); 1388c2ecf20Sopenharmony_ci if (r == -1) { 1398c2ecf20Sopenharmony_ci perror("select"); 1408c2ecf20Sopenharmony_ci return errno; 1418c2ecf20Sopenharmony_ci } 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci CLEAR(buf); 1448c2ecf20Sopenharmony_ci buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 1458c2ecf20Sopenharmony_ci buf.memory = V4L2_MEMORY_MMAP; 1468c2ecf20Sopenharmony_ci xioctl(fd, VIDIOC_DQBUF, &buf); 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci sprintf(out_name, "out%03d.ppm", i); 1498c2ecf20Sopenharmony_ci fout = fopen(out_name, "w"); 1508c2ecf20Sopenharmony_ci if (!fout) { 1518c2ecf20Sopenharmony_ci perror("Cannot open image"); 1528c2ecf20Sopenharmony_ci exit(EXIT_FAILURE); 1538c2ecf20Sopenharmony_ci } 1548c2ecf20Sopenharmony_ci fprintf(fout, "P6\\n%d %d 255\\n", 1558c2ecf20Sopenharmony_ci fmt.fmt.pix.width, fmt.fmt.pix.height); 1568c2ecf20Sopenharmony_ci fwrite(buffers[buf.index].start, buf.bytesused, 1, fout); 1578c2ecf20Sopenharmony_ci fclose(fout); 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci xioctl(fd, VIDIOC_QBUF, &buf); 1608c2ecf20Sopenharmony_ci } 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 1638c2ecf20Sopenharmony_ci xioctl(fd, VIDIOC_STREAMOFF, &type); 1648c2ecf20Sopenharmony_ci for (i = 0; i < n_buffers; ++i) 1658c2ecf20Sopenharmony_ci v4l2_munmap(buffers[i].start, buffers[i].length); 1668c2ecf20Sopenharmony_ci v4l2_close(fd); 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci return 0; 1698c2ecf20Sopenharmony_ci } 170