基于mini2440的视频采集系统的设计

2014-10-20 08:36孙奕严锡君唐跃平黄涛
微型电脑应用 2014年9期
关键词:寄存器线程嵌入式

孙奕,严锡君,唐跃平,黄涛

0 引言

近年来随着电子和通信行业的迅速发展,以及人们意识形态的变化,社会的安全稳定成为人们关注的焦点。视频监控系统作为维护人们日常工作生活正常的有力工具,有着越来越广泛的应用领域。因而在城市中,我们可以在银行、集体宿舍、大型超市等公共场合随处可见摄像头的身影[1]。

嵌入式视频系统广泛应用于掌上终端、PDA、GPS自动导航、3G手机等嵌入式领域,因此,视频信息的采集和处理技术成为嵌入式系统的关键技术。由于视频信息的数据量大,加之人们对视频信息的实时性、图像质量的要求越来越高,而数字化视频系统可以充分利用计算机的快速处理能力,对图像信息进行压缩、分析、存储和显示,因此,基于ARM的数字化处理系统正逐步取代传统的图像处理系统。

S3C2440处理器是三星公司开发的一款基于ARM920T内核的16/32bit的高性能、低功耗的嵌入式处理器,主频400MHz,具备摄像头接口。相对于MPCore多处理器系列处理器、Intel公司的StrongARM/XScale系列处理器,S3C2440处理器更适合应用于对功率和成本都较敏感的嵌入式系统场合。

本文采用基于SamsungS3C2440微处理器的mini2440开发平台设计了一个视频图像采集系统,以OV9650传感器芯片为例,介绍其驱动程序及简单应用程序的设计。

1 系统硬件设计

整个硬件基于S3C2440处理器,64M的SDRAM和64M的Nand Flash[2],构成图像采集系统。图像采集系统的硬件结构如图1所示:

图1 系统硬件结构图

系统的硬件工作流程为:S3C2440从NAND Flash芯片装载并执行引导程序,引导程序将NAND Flash中的内容拷贝到SDRAM中,拷贝完成后在SDRAM中执行软件系统主程序。

本系统的摄像头采用Omni Vision公司生产的COMS摄像头OV9650,通过串行SCCB接口与S3C2440的I2C总线接口相连,对芯片内部寄存器的读写设置曝光时间、增益、饱和度等参数。其具有高敏感度、低功耗,高分辨率,支持大量常用的图像格式、支持自动图像控制等特点。OV9650所具有的以上特点,足以满足本系统对于视频图像采集硬件的全部要求[3]。

视频采集过程如图2所示:

图2 视频采集流程图

图2中ITU-R BT 601/656为视频设备接口,视频采集设备采集到的视频数据从这里输入S3C2440处理器进行相应处理。处理器接收的视频数据先进行T模式运算,接着通过CatchCam模块进行格式转换后,根据不同的格式要求,分别送给预度量器&RGB格式器和编码度量器进行处理后分别发给预处理DMA和编码DMA,并通过AHB总线,存储到视频缓冲区,完成视频采集过程。

2 设备驱动程序的编写

嵌入式系统是以应用为中心,以计算机技术为基础,适用于应用系统对功能、可靠性、成本、体积、功耗有严格要求的专用计算机系统[4]。嵌入式图像处理的应用范围日益广泛,作为图像采集的基础,摄像头驱动的性能显得尤为重要。设备驱动程序是处理和操作硬件控制器的软件,是内核中具有最高优先级且能驻留内存的底层硬件处理程序。

驱动程序主要涉及两部分的内容。首先,通过SCCB接口来配置OV9650内部寄存器。然后,进行摄像头模块主体驱动部分的编写,用于获取图像数据和将数据传输到进程空间。驱动的总体架构如图3所示:

图3 驱动的总体架构

2.1 SCCB驱动

OV9650有多组寄存器,这些寄存器决定了图像的编码方式、分辨率等参数,配置这些寄存器需要另外的数据接口。OV9650的数据接口称为SCCB(serial camera control bus),它是一种类似IIC的串行摄像控制总线。它由两条数据线组成:传输时钟信号的SIO_C和传输数据信号的SIO_D[5]。SCCB的传输协议与IIC的相似。我们用s3c2440的IIC总线接口分别与OV9650的SIO_C和SIO_D相连接来实现SCCB的功能。

static void_ inline_ sccb_ start(void),sccb总线开始传输数据,内核在对管脚的寄存器配置中用到了一个概念:内存屏障,即smp_mb()函数。引入内存屏障为保证事件的执行次序严格按程序顺序来执行。static void_ inline_ sccb_ write_byte(void),把一个字节写到芯片中,读一个字节函数与此类似,sccb总线的stop函数与start函数类似。有了上面4个基本函数,我们就可以根据sccb总线协议定义读写函数:void sccb_ write(u8 IdAddr,u8 SubAddr,u8 data),void sccb_read(u8 IdAddr,u8 SubAddr)。配置ov9650芯片寄存器的结构体static struct ov9650_reg{ u8 subaddr;u8 value}。打开和关闭OV9650芯片的函数为:static void_ inline_ ov9650_ poweron(void),static void_ inline_ ov9650_ poweroff(void)。

sccb总线函数static int_ inline_ ov9650_ check(void)用于检测从ov9650芯片读回来的制造厂商的ID与我们定义的是否一样,以决定是否调用该驱动。再读取该产品的ID号static u32_ inline_ show_ ov9650_ product_ id(void)。

读取一切正确后配置寄存器,将定义的结构体里的值依据前面的地址写进寄存器中,这样就完成了摄像头内部寄存器的设置。

2.2 图像数据采集驱动

摄像接口有两个相互独立的DMA通道--P通道(预览通道)和C通道(编解码通道)。P通道主要存储用于视频显示的RGB图像数据,C通道主要存储用于编解码的YCbCr图像数据。设置s3c2440摄像接口一个重要的步骤是设置视频尺寸大小,通过源尺寸、目标尺寸和偏移量的设置,可以实现被摄像物体的缩放效果。

摄像接口都是通过DMA实现数据交换的。在DMA数据传递中,需要设置预览DMA控制相关寄存器CIPRCTRL的主突发长度和剩余突发长度,这两个值也可以通过调用标准函数来求得。另外,在完成每一帧视频采集后,会触发一个视频中断。初始化一个缓冲结构体,开辟四块内存,给每块内存提供一个状态,大小初始化为0,物理和虚拟地址通过系统直接赋值。

首先,对驱动模块进行初始化,static int_init camif_init(void)。配置GPIO口的J部分引脚为摄像头模式。给摄像头分配并初始化虚拟内存,地址从0x4F000000开始,大小为1M。映射虚拟内存,并返回映射后的地址。初始化外设的时钟,并将该外设的时钟插入到外设时钟链表里。接着初始化结构体,包括初始化互斥锁、输入格式、状态、命令等。然后将该设备注册为混杂设备,初始化SCCB总线,硬件复位摄像头,初始化ov9650芯片等。

在open()中,打开文件操作的结构体struct s3c2440camif_fh *fh,其中的变量master为:操作标志,仅仅操作那些能执行“set”控制的文件。用kzalloc申请内存的时候,所有申请的元素都被初始化为0。配置摄像头即填充s3c2440camif_dev结构体,将原视频尺寸设为1024*1280,即SXGA的标准,还有编码目标的尺寸和预览目标的尺寸等。在初始化视频缓冲区之后注册两个重要的中断函数,并初始化时钟和软复位摄像头。

在read()函数中,start_ capture (pdev, 0)开始采集图像传到用户空间,关闭两个中断,将所得的数据在内存的4个区域依次拷贝到用户空间里,然后将内存区域重新置为不可用状态。接着使能中断enable_irq(IRQ_S3C2440_CAM_P),读取下一帧数据。

数据采集部分通过ciwdofst=ioread32(S3C244X_CIWD OFST)从输入信号中截取中心部分的图像输出到大小不变的输出图像缓冲中,从而实现对图像的放大或缩小。ciprscc trl=ioread32(S3C244X_CIPRSCCTRL)预览模式控制寄存器中第15位置代表启动预览模式。最后设置图像采集使能寄存器iowrite32(ciimgcpt, S3C244X_CIIMGCPT),其中,29位是使能预览模式,31位是使能全局摄像头接口。

3 视频服务器软件

“MJPG-streamer”是一个轻量级的视频服务器软件,一个可以从单一输入组件获取图像并传输到多个输出组件的命令行应用程序。用于从摄像头采集图像,把它们以流的形式通过基于IP的网络传输到浏览器如Firehox,Cambozola,Windows的移动设备或者其他拥有浏览器的移动设备。可以利用某些硬件压缩功能来降低服务器CPU的开销。为嵌入式设备和一些常规服务器提供了一个轻量且更少CPU消耗的方案,因为它无需为视频帧压缩浪费大量的计算效率。

MJPG-streamer主函数的定义在mjpg-streamer.c文件。主函数的处理流程如图4所示:

图4 主函数处理流程图

MJPG-streamer采用模块化的设计方法,以功能块(组件)为单位进行描述。软件中定义了各组件的输入、输出,以及组件之间的衔接关系。可自行根据对功能的需求,选择需要的模块。这种模块化的程序设计简化了代码的编写、调试、维护,程序员只需要遵守设计的规范,就可以轻松的改写软件,或者编写新的模块以增强软件的功能[6]。

MJPG-streamer最主要并且最常用的组件是input_uvc输入组件和output_http输出组件。input_uvc的主要功能是获取摄像头拍照的图像并将其压缩编码,包括5个组件接口函数,这些组件接口函数是各个组件提供给外部使用的。函数input_run(void)使用pthread_create函数创建工作线程。并使用pthread_detach函数将该线程设置为分离状态。在input_uvc组件中,input_run函数创建cam_thread线程,该线程负责抓取摄像头采集的一帧图像进行格式转换并把它复制到全局缓冲区。其工作流程如图5所示:

图5 输入组件工作线程流程图

工作流程不断循环,直至线程退出。退出前使用pthread_cleanup_pop函数调用cam_ cleanup线程释放在工作线程中被分配的资源。

Output_ http输出组件中的http.c文件内定义了服务器对客户端请求的响应。send_ snapshot、send_ stream、send_error、send_ file分别定义了如何响应客户端发送截图、发送视频流、发送错误信息、发送文件的请求信息。Command函数执行客户端指定控制命令,并发送反馈信息。server_thread服务线程的作用是打开一个TCP socket并等待客户端连接。如有客户端链接,则为每一个连接到服务器的客户端创建一个client_ thread专门服务于该客户端。系统客户端采用网页形式,右边为摄像头所拍摄的画面,界面如图6所示:

图6 客户端采集界面图

用户通过浏览器与服务器通信,从而可以观察到前端摄像头所监控的画面,虽然在实时性上略有欠缺,但画面无较大失真现象,图像质量没有明显下降,整体上基本满足系统要求。这款工具的源代码简洁,注释清晰。组件功能明确,衔接清晰。使用Linux C语言进行开发,可移植到不同的计算机平台,也可以在根据GPL v2的条款下进行改进和发行。

4 总结

随着社会信息化的进步,视频监控作为一项重要的工具,几乎涉及了所有行业。视频图像采集在视频监控系统中扮演着重要的角色。本文给出的camera图像处理芯片的驱动程序可以流畅地预览和高分辨率抓取图像。在此基础上,通过开源视频服务器软件MJPG-streamer进行进一步处理,并将这款开源软件进行处理后,构成一个实时远程监控系统。

[1]屠添翼,石跃祥.视频监控系统中的图像采集和视频有效存储[J].计算机应用研究.2005年,08期.

[2]柳亚东,路林吉.嵌入式视频控制服务器的设计[J].微型电脑应用, 2009 (7).

[3]马明龙.基于ARM9的视频采集和处理系统的设计[D].长春工业大学.2010.

[4]邓俊华,杜玉晓.基于S3C2410处理器的Linux移植[J].微型电脑应用, 2009 (8).

[5]马超,刘政林,邹雪城.SCCB在ARM9嵌入式平台上的实现[J].计算机与数字工程,2006,34 (7):137-140.

[6]Field R T.Software architecture in an open source world[C]// 27 th International Conference on Software Engineering,ICSE,2005:43.

猜你喜欢
寄存器线程嵌入式
STM32和51单片机寄存器映射原理异同分析
Focal&Naim同框发布1000系列嵌入式扬声器及全新Uniti Atmos流媒体一体机
基于C#线程实验探究
Lite寄存器模型的设计与实现
基于国产化环境的线程池模型研究与实现
TS系列红外传感器在嵌入式控制系统中的应用
搭建基于Qt的嵌入式开发平台
移位寄存器及算术运算应用
浅谈linux多线程协作
倍福 CX8091嵌入式控制器