编译环境:ubuntu12.04
编译器:arm-linux-gcc 4.4.1
目标板:迅为iTOP4412 (cortex A9)
代码:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
struct buffer
{
void *start;
size_t length;
};
struct buffer *buffers;
unsigned long n_buffers;
unsigned long file_length;
int file_fd;
char *dev_name = "/dev/video4";
int fd;
/*获取一帧图像*/
static int read_frame(void)
{
struct v4l2_buffer buf;
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
ioctl(fd, VIDIOC_DQBUF, &buf); //出队,从队列中取出一个缓冲帧
write(file_fd, buffers[buf.index].start, buffers[buf.index].length); //将图片写入图像件“test.jpg”
ioctl(fd, VIDIOC_QBUF, &buf); //重新入队
return 1;
}
int main(int argc, char **argv)
{
struct v4l2_capability cap;
struct v4l2_format fmt;
struct v4l2_requestbuffers req;
struct v4l2_buffer buf;
file_fd = open("test.jpg", O_RDWR | O_CREAT, 0777);
fd = open(dev_name, O_RDWR | O_NONBLOCK, 0); //非阻塞方式打开摄像头
if (fd < 0)
{
perror("open device failed!");
return -1;
}
/*获取摄像头信息*/
if (ioctl(fd, VIDIOC_QUERYCAP, &cap) < 0)
{
perror("get info failed!");
return -1;
}
printf("Driver Name:%s\n Card Name:%s\n Bus info:%s\n\n ", cap.driver, cap.card, cap.bus_info);
/*************************************************************************************
//查询所有支持的格式
struct v4l2_fmtdesc fmtdesc;
fmtdesc.index = 0;
fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
while(ioctl(fd,VIDIOC_ENUM_FMT,&fmtdesc) != -1)
{
printf("VIDIOC_ENUM_FMT success! fmtdesc.description: %s\n",fmtdesc.description);
fmtdesc.index++;
}
*************************************************************************************/
/*设置摄像头捕捉帧格式及分辨率*/
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = 640; //帧宽
fmt.fmt.pix.height = 480; //帧高
fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG; //数据存储类型设为MJPEG,采集到的即为一张完整的jpg图像
if (ioctl(fd, VIDIOC_S_FMT, &fmt) < 0)
{
perror("set fmt failed!");
return -1;
}
/*申请4个图像缓冲区(位于内核空间)*/
req.count = 4; //缓存数量,即缓存队列里保持多少张照片,一般不超过5个
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP; //MMAP内存映射方式
ioctl(fd, VIDIOC_REQBUFS, &req);
buffers = calloc(req.count, sizeof(*buffers));
/*将申请的4个缓冲区映射到用户空间*/
for (n_buffers = 0; n_buffers < req.count; ++n_buffers)
{
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = n_buffers;
ioctl(fd, VIDIOC_QUERYBUF, &buf);
buffers[n_buffers].length = buf.length;
buffers[n_buffers].start = mmap(NULL,
buf.length,
PROT_READ | PROT_WRITE,
MAP_SHARED,
fd,
buf.m.offset);
}
/*缓冲区入队列*/
int i;
for (i = 0; i < n_buffers; ++i)
{
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = i;
ioctl(fd, VIDIOC_QBUF, &buf);
}
/*使能视频设备输出视频流*/
enum v4l2_buf_type type;
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
ioctl(fd, VIDIOC_STREAMON, &type);
/*select监听*/
fd_set fds;
FD_ZERO(&fds);
FD_SET(fd, &fds);
select(fd + 1, &fds, NULL, NULL, NULL);
read_frame();
for (i = 0; i < n_buffers; ++i)
munmap(buffers[i].start, buffers[i].length);
close(fd);
close(file_fd);
printf("Camera Capture Done.\n");
return 0;
}