Linux QT摄像头采集图像
Linux下利用各种装备是一件令人兴奋的事情。
在Unix的世界里,用户与硬件打交待总是容易的。最近笔者在Linux下搞了摄像头的开发,有一点感引发于这里。
Linux中垄断一个装备等闲都是敞开(open),读取(read)和关闭(close)。利用Read的大多是一些字符型装备,然而对于揭示屏可能摄像头这种字符装备而已,挨个字的读写将使贴切系调用变得频繁,众所周之,系统调用对于系统而已是个不小的开支。于是有内存照射(mmap)等物,本例中将解说在Linux下开发摄像头的等闲过程以及利用Qt举行界面开发的实例。
利用mmap措施获得摄像头数据的措施过程等闲为:
敞开装备 -> 获得装备的消息 -> 哀求装备的缓冲区 -> 获得缓冲区的开始地址及大小 -> 利用mmap获得历程地址空间的缓冲区起始地址 -> 读取缓冲区。
Mmap即便所谓内存照射。许多装备带有自己的数据缓冲区,可能驱动本身在内核空间中维护一片内存区域,为了让用户空间过程平安地拜会,内核经常要从装备内存可能内核空间内存复制数据到用户空间。这么一来便多了复制内存这个环节,浪费了工夫。因而mmap就将目标存储区域照射到一个用户空间的一片内存,这样用户历程拜会这片内存时,内核将积极转换为拜会这个目标存储区。这种转换经常是地址的线性改变而已(许多装备的存储空间在所谓外围总线地址空间(X86)可能总的地址空间(ARM)上都是继续的),因而无须担心其转换的效率。
目前开始解说Video4Linux2的利用。
int fd = open ("/dev/video",O_RDONLY);
if (fd==-1){
perror ("Can't open device");
return -1;
}
struct v4l2_format format;
memset (&format,0,sizoef(format));
format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (-1==ioctl(fd,VIDIOC_G_FMT,&format)){
perror ("While getting format");
return -2;
}
char code[5];
unsigned int i;
for (i=0;i<4;i++) {
code[i] = (format.fmt.pix.pixelformat & (0xff<<i*8))>>i*8;
}
code[4]=0;
struct v4l2_requestbuffers req;
memset (&req,0,sizeof(req));
req.count = 10;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
if (-1==ioctl(fd,VIDIOC_REQBUFS,&req)){
perror ("While requesting buffers");
return -3;
}
if (req.count < 5){
fprintf (stderr, "Can't get enough buffers78.xihuanplaza.com!/n");
return -4;
}
struct buffer * buffers = (struct buffer *)malloc (nbuffer*sizeof(*buffers));
if (!buffers){
perror ("Can't allocate memory for buffers!");
return -4;
}
struct v4l2_buffer buf;
for (nbuffer=0;nbuffer<req.count;++nbuffer) {
memset (&buf,0,sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = nbuffer;
if (-1==ioctl(fd,VIDIOC_QUERYBUF,&buf)){
perror ("While querying buffer");
return -5;
}
buffers[nbuffer].length = buf.length;
buffers[nbuffer].start = mmap (
NULL,
buf.length,
PROT_READ,
MAP_SHARED,
fd,
buf.m.offset
);
if (MAP_FAILED == buffers[nbuffer].start) {
perror ("While mapping memory");
return -6;
}
// 纳入缓存队列
if (ioctl(fd, VIDIOC_QBUF, &buf) == -1) {
return -1;
} }
enum v4l2_buf_type type;
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (-1==ioctl(fd,VIDIOC_STREAMON,&type)){
perror ("While opening stream");
return -7;
}
unsigned int i;
i=0;
while(1) {
memset (&buf,0,sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = i;
if (-1==ioctl(fd,VIDIOC_DQBUF,&buf)){
perror ("While getting buffer's data");
return -8;
}
process_image ( buffers+buf.index,buf.index );
if (-1==ioctl(fd,VIDIOC_QBUF,&buf)){
perror ("While returning buffer's data");
return -9;
}
i = (i+1) & nbuffer;
}