linux下usb camera图像采集(V4l2)
head.h
-
#include <stdio.h>
-
#include <stdlib.h>
-
#include <string.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 <linux/videodev2.h>
-
#define DEVICE "/dev/video"
-
static struct v4l2_requestbuffers req;
-
struct buffer
-
{
-
void* start;
-
unsigned int length;
-
};
-
static struct buffer *buffers;
-
static struct v4l2_buffer buf;
usb_camera.c
-
#include "head.h"
-
int main()
-
{
-
int fd;
-
fd=open_device();
-
get_device_info(fd);
-
get_frame_fmt(fd);
-
get_current_frame_info(fd);
-
try_format_support(fd);
-
set_frame_format(fd);
-
apply_memory_buf(fd);
-
memory_mapping(fd);
-
buffer_enqueue(fd);
-
close(fd);
-
return 0;
-
}
-
int open_device()
-
{
-
int fd;
-
if(-1==(fd=open(DEVICE,O_RDWR)))
-
printf("info:Can't open video device\n");
-
else
-
printf("info:Open the device :%d\n",fd);
-
return fd;
-
}
-
int get_device_info(int fd)
-
{
-
struct v4l2_capability cap;
-
if(-1==ioctl(fd,VIDIOC_QUERYCAP,&cap))
-
printf("info:VIDIOC_QUERYCAP ERROR\n");
-
else
-
printf("info:Driver Name:%s....Card Name:%s....Bus info:%s....Driver Version:%u.%u.%u\n",
version的各字段提取如下:
driver = version >> 16 & 0xfff
card = version >> 8 & 0xfff
bus_info = version & 0xfff
-
return 1;
-
}
-
int get_frame_fmt(int fd)
-
{
-
struct v4l2_fmtdesc fmtdesc;
-
fmtdesc.index=0;
-
fmtdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
printf("info:Support format:");
-
while(ioctl(fd,VIDIOC_ENUM_FMT,&fmtdesc)!=-1)
-
{
-
printf("\t%d.%s",fmtdesc.index+1,fmtdesc.description);
-
fmtdesc.index++;
-
}
-
printf("\n");
-
return 1;
-
}
-
int get_current_frame_info(int fd)
-
{
-
struct v4l2_format fmt;
-
fmt.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
ioctl(fd,VIDIOC_G_FMT,&fmt);
-
printf("info:Current version data formats information:\n\t宽度(px):%d\n\t高度(px):%d\n",fmt.fmt.pix.width,fmt.fmt.pix.height);
-
struct v4l2_fmtdesc fmtdesc;
-
fmtdesc.index=0;
-
fmtdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
while(ioctl(fd,VIDIOC_ENUM_FMT,&fmtdesc)!=-1)
-
{
-
if(fmtdesc.pixelformat & fmt.fmt.pix.pixelformat)
-
{
-
printf("\tformat:%s\n",fmtdesc.description);
-
break;
-
}
-
fmtdesc.index++;
-
}
-
return 1;
-
}
-
int try_format_support(int fd)
-
{
-
struct v4l2_format fmt;
-
fmt.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
//fmt.fmt.pix.pixelformat=V4L2_PIX_FMT_RGB32;
-
fmt.fmt.pix.pixelformat=V4L2_PIX_FMT_YUYV;
-
if(ioctl(fd,VIDIOC_TRY_FMT,&fmt)==-1)
-
if(errno==EINVAL)
-
printf("info:not support format RGB32!\n");
-
return 1;
-
}
-
int set_frame_format(int fd)
-
{
-
struct v4l2_format 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_YUYV;
-
fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
-
if(ioctl(fd,VIDIOC_S_FMT,&fmt)==-1)
-
if(errno==EINVAL)
-
printf("info:set frame format error!\n");
-
return 1;
-
}
-
int apply_memory_buf(int fd)
-
{
-
//struct v4l2_requestbuffers req;
-
req.count=4;
-
req.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
req.memory=V4L2_MEMORY_MMAP;
-
if(-1==ioctl(fd,VIDIOC_REQBUFS,&req))
-
printf("info:VIDIOC_REQBUFS FAILED\n");
-
else
-
printf("info:VIDIOC_REQBUFS SUCCESS\n");
-
return 1;
-
}
-
int memory_mapping(int fd)
-
{
-
unsigned int n_buffers;
-
buffers = (struct buffer*)calloc(req.count,sizeof(struct buffer));
-
if (!buffers) {
-
fprintf (stderr, "Out of memory\n");
-
exit (EXIT_FAILURE);
-
}
-
// 映射
-
for (n_buffers = 0; n_buffers < req.count; ++n_buffers) {
-
//struct v4l2_buffer buf;
-
memset(&buf,0,sizeof(buf));
-
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
buf.memory = V4L2_MEMORY_MMAP;
-
buf.index = n_buffers;
-
// 查询序号为n_buffers 的缓冲区,得到其起始物理地址和大小
-
if (-1 == ioctl (fd, VIDIOC_QUERYBUF, &buf))
-
exit(-1);
-
buffers[n_buffers].length = buf.length;
-
// 映射内存
编号为126的缓冲区[buffers[n_buffers]]在其起始位置[.start]处调用内存映射函数[mmap](null, buffer长度[buf.length]、可读性和可写性 flags [PROT_READ | PROT_WRITE]、共享模式[MAP_SHARED]、文件描述符[fd]以及偏移量[buf.m.offset])。
-
if (MAP_FAILED == buffers[n_buffers].start)
-
exit(-1);
-
}
-
printf("info:memory mapping success\n");
-
return 1;
-
}
-
int buffer_enqueue(int fd)
-
{
-
unsigned int i;
-
enum v4l2_buf_type type;
-
// 将缓冲帧放入队列
-
for (i = 0; i < 4; ++i)
-
{
-
struct v4l2_buffer buf;
-
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
buf.memory = V4L2_MEMORY_MMAP;
-
buf.index = i;
-
if(-1==ioctl (fd, VIDIOC_QBUF, &buf))
-
printf("buffer enqueue failed\n");
-
}
-
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
//open stream
-
if(-1==ioctl (fd, VIDIOC_STREAMON, &type))
-
printf("info:open stream failed\n");
-
else
-
printf("info:open stream success\n");
-
return 1;
-
}
