8968da9b86
This patch touches on places where it shouldn't: image files and code examples. Also, it doesn't fix all array occurrences. So, let's revert it. This reverts commit ffbab694ede33c294e5864a5e0bf4d1474446a71.
170 lines
4.8 KiB
ReStructuredText
170 lines
4.8 KiB
ReStructuredText
.. -*- coding: utf-8; mode: rst -*-
|
|
|
|
file: media/v4l/v4l2grab.c
|
|
==========================
|
|
|
|
.. code-block:: c
|
|
|
|
/* V4L2 video picture grabber
|
|
Copyright (C) 2009 Mauro Carvalho Chehab <mchehab@infradead.org>
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation version 2 of the License.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <fcntl.h>
|
|
#include <errno.h>
|
|
#include <sys/ioctl.h>
|
|
#include <sys/types.h>
|
|
#include <sys/time.h>
|
|
#include <sys/mman.h>
|
|
#include <linux/videodev2.h>
|
|
#include "../libv4l/include/libv4l2.h"
|
|
|
|
#define CLEAR(x) memset(&(x), 0, sizeof(x))
|
|
|
|
struct buffer {
|
|
void *start;
|
|
size_t length;
|
|
};
|
|
|
|
static void xioctl(int fh, int request, void *arg)
|
|
{
|
|
int r;
|
|
|
|
do {
|
|
r = v4l2_ioctl(fh, request, arg);
|
|
} while (r == -1 && ((errno == EINTR) || (errno == EAGAIN)));
|
|
|
|
if (r == -1) {
|
|
fprintf(stderr, "error %d, %s\\n", errno, strerror(errno));
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
struct v4l2_format fmt;
|
|
struct v4l2_buffer buf;
|
|
struct v4l2_requestbuffers req;
|
|
enum v4l2_buf_type type;
|
|
fd_set fds;
|
|
struct timeval tv;
|
|
int r, fd = -1;
|
|
unsigned int i, n_buffers;
|
|
char *dev_name = "/dev/video0";
|
|
char out_name[256];
|
|
FILE *fout;
|
|
struct buffer *buffers;
|
|
|
|
fd = v4l2_open(dev_name, O_RDWR | O_NONBLOCK, 0);
|
|
if (fd < 0) {
|
|
perror("Cannot open device");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
CLEAR(fmt);
|
|
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
|
fmt.fmt.pix.width = 640;
|
|
fmt.fmt.pix.height = 480;
|
|
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB24;
|
|
fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
|
|
xioctl(fd, VIDIOC_S_FMT, &fmt);
|
|
if (fmt.fmt.pix.pixelformat != V4L2_PIX_FMT_RGB24) {
|
|
printf("Libv4l didn't accept RGB24 format. Can't proceed.\\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
if ((fmt.fmt.pix.width != 640) || (fmt.fmt.pix.height != 480))
|
|
printf("Warning: driver is sending image at %dx%d\\n",
|
|
fmt.fmt.pix.width, fmt.fmt.pix.height);
|
|
|
|
CLEAR(req);
|
|
req.count = 2;
|
|
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
|
req.memory = V4L2_MEMORY_MMAP;
|
|
xioctl(fd, VIDIOC_REQBUFS, &req);
|
|
|
|
buffers = calloc(req.count, sizeof(*buffers));
|
|
for (n_buffers = 0; n_buffers < req.count; ++n_buffers) {
|
|
CLEAR(buf);
|
|
|
|
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
|
buf.memory = V4L2_MEMORY_MMAP;
|
|
buf.index = n_buffers;
|
|
|
|
xioctl(fd, VIDIOC_QUERYBUF, &buf);
|
|
|
|
buffers[n_buffers].length = buf.length;
|
|
buffers[n_buffers].start = v4l2_mmap(NULL, buf.length,
|
|
PROT_READ | PROT_WRITE, MAP_SHARED,
|
|
fd, buf.m.offset);
|
|
|
|
if (MAP_FAILED == buffers[n_buffers].start) {
|
|
perror("mmap");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < n_buffers; ++i) {
|
|
CLEAR(buf);
|
|
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
|
buf.memory = V4L2_MEMORY_MMAP;
|
|
buf.index = i;
|
|
xioctl(fd, VIDIOC_QBUF, &buf);
|
|
}
|
|
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
|
|
|
xioctl(fd, VIDIOC_STREAMON, &type);
|
|
for (i = 0; i < 20; i++) {
|
|
do {
|
|
FD_ZERO(&fds);
|
|
FD_SET(fd, &fds);
|
|
|
|
/* Timeout. */
|
|
tv.tv_sec = 2;
|
|
tv.tv_usec = 0;
|
|
|
|
r = select(fd + 1, &fds, NULL, NULL, &tv);
|
|
} while ((r == -1 && (errno = EINTR)));
|
|
if (r == -1) {
|
|
perror("select");
|
|
return errno;
|
|
}
|
|
|
|
CLEAR(buf);
|
|
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
|
buf.memory = V4L2_MEMORY_MMAP;
|
|
xioctl(fd, VIDIOC_DQBUF, &buf);
|
|
|
|
sprintf(out_name, "out%03d.ppm", i);
|
|
fout = fopen(out_name, "w");
|
|
if (!fout) {
|
|
perror("Cannot open image");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
fprintf(fout, "P6\\n%d %d 255\\n",
|
|
fmt.fmt.pix.width, fmt.fmt.pix.height);
|
|
fwrite(buffers[buf.index].start, buf.bytesused, 1, fout);
|
|
fclose(fout);
|
|
|
|
xioctl(fd, VIDIOC_QBUF, &buf);
|
|
}
|
|
|
|
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
|
xioctl(fd, VIDIOC_STREAMOFF, &type);
|
|
for (i = 0; i < n_buffers; ++i)
|
|
v4l2_munmap(buffers[i].start, buffers[i].length);
|
|
v4l2_close(fd);
|
|
|
|
return 0;
|
|
}
|