接上一篇《移动物体监控系统(Part1)——声音报警子系统开发》的项目总结,本文接着讲解摄像头子系统开发。
一、摄像头驱动开发
1、摄像头软件系统架构
当前最流行的摄像头软件架构就是V4L2架构,是linux中关于视频设备的内核驱动。它的主要功能是使程序具有发现设备和操作设备的能力。它主要是用一系列的回调函数来实现这些功能。像设置摄像头的频率、帧频、视频压缩格式和图像参数等等,当然也可以用于其他多媒体的开发,如音频等。V4L2的架构示意图如下:
V4L2的软件架构
V4L2架构主要分为四个部分:
(1)用户空间的应用程序;
(2)V4L2驱动核心;
(3)具体的V4L2驱动;
(4)底层硬件。
应用:由于V4L2支持许多USB 网络摄像头、相关设备,使它们的输出标准化,因此程序员可以轻松地向其应用程序添加视频支持。可以实现图片、视频、音频等的采集。在远程会议、可视电话、视频监控系统和嵌入式多媒体终端中都有广泛的应用。
2、摄像头驱动使能及测试
在使用摄像头采集图像或视频之前,需要根据自己摄像头的驱动芯片加载合适的驱动模块到内核中,本项目采用的是基于ZC3XX系列芯片的USB摄像头。接下来在内核中使能摄像头驱动:
(1)在Linux终端下,执行 make menuconfig 命令;
(2)进行配置界面,按如下流程操作:
Device Drivers --->(设备驱动选项)
<*> Multimedia support --->(多媒体范畴)
[*] Video capture adapters --->(视频捕获)
[*] V4L USB devices --->(V4L2设备驱动)
<*> GSPCA based webcams --->(万能摄像头驱动)
<*> ZC3XX USB Camera Driver(ZC3XX的USB驱动)
(3)保存配置文件,退出配置模式,重新编译内核
make uImage ARCH=arm CROSS_COMPILE=arm-linux-
(4)摄像头驱动测试
将USB摄像头插入到开发板上,打开串口控制台SecureCRT,运行一段摄像头程序(可以去网上下载一份摄像头测试源码),测试监测画面功能是否正常。
二、V4L2图像编程接口深度学习
1、V4L2编程接口流程:
V4L2编程接口流程图
程序部分源码为:
/*获取驱动信息*/
ioctl (fd, VIDIOC_QUERYCAP, &cap);
/*设置图像格式*/
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = 320;
fmt.fmt.pix.height = 240;
fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
ioctl (fd, VIDIOC_S_FMT, &fmt) ;
/*申请图像缓冲区*/
req.count = 4;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
ioctl (fd, VIDIOC_REQBUFS, &req);
buffers = calloc (req.count, sizeof (*buffers));
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;
// 把内核空间中的图像缓冲区映射到用户空间,,通过mmap建立映射关系
buffers[n_buffers].start = mmap (NULL , buf.length, PROT_READ | PROT_WRITE ,
MAP_SHARED , fd, buf.m.offset); }
/*图像缓冲入队*/
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);
}
//开始捕捉图像数据
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
ioctl (fd, VIDIOC_STREAMON, &type);
fd_set fds;
FD_ZERO (&fds);
FD_SET (fd, &fds);
select(fd + 1, &fds, NULL, NULL, NULL);
/*读取一幅图像*/
read_frame();
到此,《移动物体监控系统》的第二部分----摄像头子系统开发便完成了。
接下来,进行《移动物体监控系统》的第三部分----监控主系统设计与开发的经验分享!!!具体内容,详见我的下篇文章。