视频采集模块的软件设计主要是利用V4L为视频设备的应用编程提供的一套统一的API接口。它为针对视频设备的应用程序编程提供一系列接口函数,对USB口接口摄像头来说,其驱动程序通过提供基本的I/O操作接口函数open、read、write、close来实现。ZC301P芯片采用片内EG压缩技术,即利用V4L编程接口采集出的数据是就压缩后的EG文件,能够拍摄最大分辨率640×480的照片。程序中专门定义了一个名为V4LDevice的结构体,同时定义一个全局变量vd。V4L编程的一般过程为:打开视频设备、读取当前参数、设置相关参数、读取或循环读取视频数据、对视频数据进行相关处理[11]。
3.1.3 视频采集的流程
图9 视频采集流程图
开始时打开视频设备,系统中摄像头对应的设备文件为/dev/video0,采用grab_fd=open("/dev/video0", O_RDWR)系统调用函数。然后,用 ioctl(grab_fd,VIDIOCGCAP,&grab_cap)函数来读取struct video_capability中有关摄像头的信息。该函数成功返回后,这些信息从内核空间拷贝到用户程序空间grab_cap各成员分量中,使用 printf函数就可得到各成员分量信息。用ioctl(grab_fd,VIDIOCGPICT,&grab_pic)函数读取摄像头缓冲中voideo_picture信息。在用户空间程序中可以改变这些信息,首先给分量赋新值,然后再调用VIDIOCSPICT ioctl函数。对设备进行初始化工作后,截取视频图像,然后使用 mmap函数对内存进行映射。mmap函数通过绕过内核的缓冲区然后将设备文件的内容映射到RAM中,由于内存访问快于磁盘访问,因此直接内存映射方式可以加速对I/O的访问。因为mmap函数的系统调用从而使各进程之间可以用映射同一个文件的方式来共享内存,各进程访问该文件时如同访问普通的内存一样,访问时避免了使用文件调用函数而只需要应用指针,因此程序实现时采用内存映射mmap方式[12]。视频采集流程如图9所示。
3.2 视频的编解码
视频的数据量很大,存储容量和传输带宽都要求很高。因此视频压缩技术就变得很重要。它的原理是:视频数据有很大的相关性,也就是通常所说的哟大量的冗余信息,它对我们来说是无用的,所以需要尽量减少冗余。冗余可分为时间冗余和空间冗余,时间冗余采用帧间的编码技术去除,包括运动补偿,运动估计和运动表示。空间冗余则利用帧编码和熵编码技术,一般采用熵编码,量化编码和变换编码。
系统所选用的USB摄像头基于ZC301芯片,该摄像头采用片内EG压缩技术;设备驱动后通过V4L(Video for Linux)接口对其操作,可以直接从摄像头读取EG格式的数据。定制内核的时候已经加入了对V4L 和ZC301 USB摄像头设备的支持,因此可以直接利用V4L提供的API接口指令从USB摄像头中读出图像[13]。
3.3 视频播放的实现
帧缓冲(framebuffer)是Linux为显示设备提供的一个接口,图形模式之下它允许上层应用程序直接读写显示缓冲区域。因为这种操作是统一的、抽象的,因此,用户不必关心一些如换页机制等具体细节。本质上来说帧缓冲抽象了图形设备硬件,然而在开发者看来,FrameBuffer 如同一片显示缓存区域,写入显示缓存区域一定格式的数据相当于向屏幕上输出相应的内容[14]。帧缓冲是出现在Linux2.2.xx内核中的一种驱动程序接口,该设备提供了LCD控制器的抽象描述。它同时代表了LCD控制器上的显存,应用程序通过定义好的接口可以访问LCD控制器,而不需要知道底层的任何操作。它几乎支持所有的硬件,提供了统一的API接口,很好地实现了硬件无关性。视频显示流程图如图10所示。
视频显示模块软件设计主要是利用Linux系统提供的Framebuffer直接写屏实现的。Framebuffer是一种用来供用户态进程实现直接写屏的抽象对象,可以被看做是显存的一个映像,用户只需要通过应用程序直接读写Framebuffer内容就可以完成对屏幕的显示控制。Framebuffer是用来一个视频输出设备从包含完整的帧数据的一个内存缓冲区中来驱动一个视频显示设备。mmap函数将Framebuffer设备映射到内存,最后将前述中获得的图像数据写入对应的内存中就可以显示了。 ARM音视频采集与回放系统的设计(5):http://www.youerw.com/tongxin/lunwen_1387.html