接上一篇《移动物体监控系统(Part1)——声音报警子系统开发》的项目总结,本文接着讲解摄像头子系统开发。

一、摄像头驱动开发

1、摄像头软件系统架构

当前最流行的摄像头软件架构就是V4L2架构,是linux中关于视频设备的内核驱动。它的主要功能是使程序具有发现设备和操作设备的能力。它主要是用一系列的回调函数来实现这些功能。像设置摄像头的频率、帧频、视频压缩格式和图像参数等等,当然也可以用于其他多媒体的开发,如音频等。V4L2的架构示意图如下:

Android 开发监控摄像头用GLSurfaceView 还是 SurfaceView 监控摄像头程序开发_摄像头驱动

 

 

 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编程接口流程:

Android 开发监控摄像头用GLSurfaceView 还是 SurfaceView 监控摄像头程序开发_监控系统_02

 

 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();

 

  到此,《移动物体监控系统》的第二部分----摄像头子系统开发便完成了。

  接下来,进行《移动物体监控系统》的第三部分----监控主系统设计与开发的经验分享!!!具体内容,详见我的下篇文章。