这是源码/*
 ============================================================================
 Name        : v4l_official.c
 Author      : xbp
 Version     :
 Copyright   : Your copyright notice
 Description : Hello World in C, Ansi-style
 ============================================================================
 */#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <getopt.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <malloc.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <asm/types.h>
#include <linux/videodev2.h>#define CLEAR(x) memset(&(x), 0, sizeof(x))typedef enum
{
IO_METHOD_READ,
IO_METHOD_MMAP,
IO_METHOD_USERPTR,
}io_method;struct buffer
{
void * start;
size_t length;
};static char *  dev_name = NULL;
static io_method  io = IO_METHOD_MMAP;
static int fd = -1;
struct buffer * buffers  = NULL;
static unsigned int n_buffers = 0;static void errno_exit(const char * s)
{
fprintf(stderr, "%s error %d, %s\n", s, errno, strerror(errno)); exit(EXIT_FAILURE);
}static int xioctl(int fd, int request, void * arg)
{
int r; do r = ioctl(fd, request, arg);
while (-1 == r && EINTR == errno); return r;
}static void process_image(const void * p)
{
fputc('.', stdout);
fflush(stdout);
}static int read_frame(void)
{
struct v4l2_buffer buf;
unsigned int i; switch (io)
{
case IO_METHOD_READ:
if (-1 == read(fd, buffers[0].start, buffers[0].length))
{
switch (errno)
{
case EAGAIN:
return 0;
case EIO:
/*Could ingore EIO, see spec.*/ /*fall through*/
default:
errno_exit("read");
}
} process_image(buffers[0].start);
break;
case IO_METHOD_MMAP:
CLEAR(buf); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP; if (-1 == xioctl(fd, VIDIOC_DQBUF, &buf))
{
switch (errno)
{
case EAGAIN:
return 0;
case EIO:
/*Could ingore EIO, see spec.*/ /*fall through*/
default:
errno_exit("VIDIOC_DQBUF");
}
} assert(buf.index < n_buffers);
process_image(buffers[0].start); if (-1 == xioctl(fd, VIDIOC_QBUF, &buf))
{
errno_exit("VIDIOC_QBUF");
}
break;
case IO_METHOD_USERPTR:
CLEAR(buf); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = IO_METHOD_USERPTR; if (-1 == xioctl(fd, VIDIOC_DQBUF, &buf))
{
switch (errno)
{
case EAGAIN:
return 0;
case EIO:
/*Could ingore EIO, see spec.*/ /*fall through*/
default:
errno_exit("VIDIOC_DQBUF");
}
} for (i=0; i<n_buffers; ++i)
{
if (buf.m.userptr == (unsigned long)buffers[i].start && buf.length == buffers[i].length)
{
break;
}
} assert(i < n_buffers); if (-1 == xioctl(fd, VIDIOC_QBUF, &buf))
{
errno_exit("VIDIOC_QBUF");
}
break;
} return 1;
}static void mainloop(void)
{
unsigned int count = 100; while (count-- > 0)
{
for (;;)
{
fd_set fds;
struct timeval tv;
int r; FD_ZERO(&fds);
FD_SET(fd, &fds); /*TIMEOUT*/
tv.tv_sec = 2;
tv.tv_usec = 0; r = select(fd+1, &fds, NULL, NULL, &tv); if (-1 == r)
{
if (EINTR == errno)
{
continue;
} errno_exit("select");
} if (0 == r)
{
fprintf(stderr, "select timeout\n");
exit(EXIT_FAILURE);
} if (read_frame())
{
break;
} /*EAGAIN - continus select loop. */
}
}
}static void stop_capturing(void)
{
enum v4l2_buf_type type; switch (io)
{
case IO_METHOD_READ:
/*nothing to do. */
break;
case IO_METHOD_MMAP:
case IO_METHOD_USERPTR:
type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (-1 == xioctl(fd, VIDIOC_STREAMOFF, &type))
{
errno_exit("VIDIOC_STREAMOFF");
} break;
}
}