#include <asm/types.h> /* for videodev2.h */
#include <fcntl.h> /* low-level i/o */
#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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "v4l2.h"
#define CLEAR(x) memset (&(x), 0, sizeof (x))
static unsigned int n_buffers = 0;
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;
}
void open_camera(struct camera *cam)
{
struct stat st;
if (-1 == stat (cam->device_name, &st)) {
fprintf (stderr, "Cannot identify '%s': %d, %s\n",
cam->device_name, errno, strerror (errno));
exit (EXIT_FAILURE);
}
if (!S_ISCHR (st.st_mode)) {
fprintf (stderr, "%s is no device\n", cam->device_name);
exit (EXIT_FAILURE);
}
cam->fd = open (cam->device_name, O_RDWR /* required */ | O_NONBLOCK, 0);
if (-1 == cam->fd) {
fprintf (stderr, "Cannot open '%s': %d, %s\n",
cam->device_name, errno, strerror (errno));
exit (EXIT_FAILURE);
}
}
void close_camera(struct camera *cam)
{
if (-1 == close (cam->fd))
errno_exit ("close");
cam->fd = -1;
}
int read_frame(struct camera *cam)
{
struct v4l2_buffer buf;
CLEAR (buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
if (quit_flag == 0) {
if (-1 == xioctl (cam->fd, VIDIOC_DQBUF, &buf)) {
switch (errno) {
case EAGAIN:
return 0;
case EIO:
/* Could ignore EIO, see spec. */
/* fall through */
default:
errno_exit ("VIDIOC_DQBUF");
}
}
}
assert (buf.index < n_buffers);
process_image (cam->buffers[buf.index].start, cam);
if (quit_flag == 0) {
if (-1 == xioctl (cam->fd, VIDIOC_QBUF, &buf))
errno_exit ("VIDIOC_QBUF");
}
return 1;
}
void start_capturing(struct camera *cam)
{
unsigned int i;
enum v4l2_buf_type type;
for (i = 0; i < n_buffers; ++i) {
struct v4l2_buffer buf;
CLEAR (buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = i;
if (-1 == xioctl (cam->fd, VIDIOC_QBUF, &buf))
errno_exit ("VIDIOC_QBUF");
}
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (-1 == xioctl (cam->fd, VIDIOC_STREAMON, &type))
errno_exit ("VIDIOC_STREAMON");
}
void stop_capturing(struct camera *cam)
{
enum v4l2_buf_type type;
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (-1 == xioctl (cam->fd, VIDIOC_STREAMOFF, &type))
errno_exit ("VIDIOC_STREAMOFF");
}
void uninit_camera(struct camera *cam)
{
unsigned int i;
for (i = 0; i < n_buffers; ++i)
if (-1 == munmap (cam->buffers[i].start, cam->buffers[i].length))
errno_exit ("munmap");
free (cam->buffers);
}
static void init_mmap(struct camera *cam)
{
struct v4l2_requestbuffers req;
CLEAR (req);
req.count = 4;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
if (-1 == xioctl (cam->fd, VIDIOC_REQBUFS, &req)) {
if (EINVAL == errno) {
fprintf (stderr, "%s does not support "
"memory mapping\n", cam->device_name);
exit (EXIT_FAILURE);
} else {
errno_exit ("VIDIOC_REQBUFS");
}
}
if (req.count < 2) {
fprintf (stderr, "Insufficient buffer memory on %s\n",
cam->device_name);
exit (EXIT_FAILURE);
}
cam->buffers = calloc (req.count, sizeof (*(cam->buffers)));
if (!cam->buffers) {
fprintf (stderr, "Out of memory\n");
exit (EXIT_FAILURE);
}
for (n_buffers = 0; n_buffers < req.count; ++(n_buffers)) {
struct v4l2_buffer buf;
CLEAR (buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = n_buffers;
if (-1 == xioctl (cam->fd, VIDIOC_QUERYBUF, &buf))
errno_exit ("VIDIOC_QUERYBUF");
cam->buffers[n_buffers].length = buf.length;
cam->buffers[n_buffers].start =
mmap (NULL /* start anywhere */,
buf.length,
PROT_READ | PROT_WRITE /* required */,
MAP_SHARED /* recommended */,
cam->fd, buf.m.offset);
if (MAP_FAILED == cam->buffers[n_buffers].start)
errno_exit ("mmap");
}
}
void init_camera(struct camera *cam)
{
struct v4l2_capability *cap;
struct v4l2_cropcap *cropcap;
struct v4l2_crop crop;
struct v4l2_format *fmt;
unsigned int min;
cap = &(cam->v4l2_cap);
cropcap = &(cam->v4l2_cropcap);
fmt = &(cam->v4l2_fmt);
if (-1 == xioctl (cam->fd, VIDIOC_QUERYCAP, cap)) {
if (EINVAL == errno) {
fprintf (stderr, "%s is no V4L2 device\n",
cam->device_name);
exit (EXIT_FAILURE);
} else {
errno_exit ("VIDIOC_QUERYCAP");
}
}
if (!(cap->capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
fprintf (stderr, "%s is no video capture device\n",
cam->device_name);
exit (EXIT_FAILURE);
}
if (!(cap->capabilities & V4L2_CAP_STREAMING)) {
fprintf (stderr, "%s does not support streaming i/o\n",
cam->device_name);
exit (EXIT_FAILURE);
}
#ifdef DEBUG_CAM
printf("\nVIDOOC_QUERYCAP\n");
printf("the camera driver is %s\n", cap->driver);
printf("the camera card is %s\n", cap->card);
printf("the camera bus info is %s\n", cap->bus_info);
printf("the version is %d\n", cap->version);
#endif
/* Select video input, video standard and tune here. */
CLEAR (*cropcap);
cropcap->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (0 == xioctl (cam->fd, VIDIOC_CROPCAP, cropcap)) {
crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
crop.c = cropcap->defrect; /* reset to default */
if (-1 == xioctl (cam->fd, VIDIOC_S_CROP, &crop)) {
switch (errno) {
case EINVAL:
/* Cropping not supported. */
break;
default:
/* Errors ignored. */
break;
}
}
} else {
/* Errors ignored. */
}
CLEAR (*fmt);
fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt->fmt.pix.width = cam->width;
fmt->fmt.pix.height = cam->height;
fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
fmt->fmt.pix.field = V4L2_FIELD_INTERLACED;
if (-1 == xioctl (cam->fd, VIDIOC_S_FMT, fmt))
errno_exit ("VIDIOC_S_FMT");
/* Note VIDIOC_S_FMT may change width and height. */
/* Buggy driver paranoia. */
min = fmt->fmt.pix.width * 2;
if (fmt->fmt.pix
基于GTK的USB视频采集测试程序
5星 · 超过95%的资源 需积分: 12 54 浏览量
2011-11-21
16:53:56
上传
评论 7
收藏 23KB ZIP 举报
窗外云天
- 粉丝: 405
- 资源: 19
- 1
- 2
- 3
- 4
- 5
- 6
前往页