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