基于S3C2410和嵌入式Internet的家庭视频监控系统设计
姓名:张建申请学位级别:硕士专业:控制理论与控制工程
指导教师:曹广益
20070101
上海交通大学硕士学位论文
基于S3C2410和嵌入式Internet的家庭视频监控系统设计
摘 要
随着经济的快速发展,生活节奏的提高,人们照顾家庭的时间越来越少,感觉时间也越来越紧张:不但要周旋在繁杂的工作之中,同时也要兼顾自己的“家”。怎样才能够解决这个矛盾,做到“鱼与熊掌兼得”成了人们关注的重点。嵌入式技术、网络技术以及多媒体技术的发展解决了人们的烦恼。将嵌入式系统与多媒体技术以及网络技术相结合,构建一个灵活高效、扩展性强、可靠性高的监控系统系统将成为首选方案。
传统的网络视频监控系统如模拟视频监控,都是应用到专用的视频监控领域,采用专有线路、模拟电视信号等实现,需要较多的硬件,整个系统昂贵,建设安装复杂,需要专业人士完成。这些要求都导致了该类系统难以普及进入普通家庭。
鉴于这种情况,本文提出了一种新的监控方案。系统包括了处在家庭监控现场的视频监控终端与视频监控网络平台两个部分。其中视频监控终端采用了韩国三星公司的S3C2410微处理器,该处理器主频最高可达203MHz,处理速度快,视频监控设备采集的视频图像经过MPEG-4压缩算法编码压缩后送入该处理器,经过处理后MPEG-4数据流被送入视频监控网络平台,利用RTP实时传输协议以及无连接数据报协议UDP/IP等将该数据流打包后利用Internet网络进行实时传输
5
上海交通大学硕士学位论文
到用户端。
整个系统采用模块式结构,各个模块具有相对的性,这增强了系统的健壮性与灵活性,当需要更换其中一个模块时其他模块并不需要做很大的改动,有利于系统的更新换代。另外采用嵌入式的方法,系统成本较低,易于推广使用。
关键词:视频监控,嵌入式Linux,Video4Linux,MPEG-4,实时传输协议
6
上海交通大学硕士学位论文
DESIGN OF FAMILY VIDEO SURVEILLANCE SYSTEM BASED ON
S3C2410 AND EMBEDDED INTERNET
ABSTRACT
With the fast development of economy and the improvement of the living peace, people have less and less time to care for the family and feel more and more nervous. They not only devote themselves to the complicated jobs but also care for their families. How to solve this contradiction has become people’s focus. The development of embedded technology, network technology and multimedia technology has solved people’s annoyance. It is people’s first choice that constructing a flexible, high efficient, high extended and high reliable surveillance system which combines the embedded system multimedia and the network technology.
The traditional network video surveillance systems such as the analog video surveillance system are all applied to the special video surveillance field. They use owner-use circuit and analog television signal to implement and need a lot of hardware and therefore the cost is high. Because it is complicated to implement this kind of system, it needs experts to complete. All these lead to its difficulty to enter the common family.
Given to this condition the author comes up a new kind of solution. The system consists of two parts which are the video surveillance
7
上海交通大学硕士学位论文
terminals and the network while the former is on the family surveillance field. The video surveillance terminal uses the microprocessor S3C2410 which is produced by SAMSUNG Company in South Korea and the main frequency of the microprocessor is up to 203MHz which is very fast. The video captured by the video device is coded and compressed by the MPEG-4 algorithm and is sent to the microprocessor. After processed by it the MPEG-4 data stream is sent to video surveillance network. Then the MPEG-4 data stream is packed by the Real-time Transport Protocol and User Data-diagram Protocol and the Internet Protocol. Finally the data packet is transmitted to the user.
The whole system is based on module constructer. Each module has relative independence. This enhances the robustness and flexibility. When one module needs replacing another doesn’t need great change. It has great advantage to upgrade the system. Also the system uses the embedded solution which leads to the low cost and is easy to use and spread.
Key words: video surveillance, embedded Linux, Video4Linux, MPEG-4, Real-time Transport Protocol
8
上海交通大学硕士学位论文
上海交通大学 学位论文原创性声明
本人郑重声明:所呈交的学位论文,是本人在导师的指导下,独
立进行研究工作所取得的成果。除文中已经注明引用的内容外,本论文不包含任何其他个人或集体已经发表或撰写过的作品成果。对本文的研究做出重要贡献的个人和集体,均已在文中以明确方式标明。本人完全意识到本声明的法律后果由本人承担。
日期: 2007年 1月 16日
学位论文作者签名:张建
3
上海交通大学硕士学位论文
上海交通大学 学位论文版权使用授权书
本学位论文作者完全了解学校有关保留、使用学位论文的规定,同意学校保留并向国家有关部门或机构送交论文的复印件和电子版,允许论文被查阅和借阅。本人授权上海交通大学可以将本学位论文的全部或部分内容编入有关数据库进行检索,可以采用影印、缩印或扫描等复制手段保存和汇编本学位论文。 保密□,在 年解密后适用本授权书。 本学位论文属于
不保密□。 (请在以上方框内打“√”)
学位论文作者签名: 张建 指导教师签名:曹广益
日期:2007年 1月 16 日 日期: 2007年1月 16日
4
上海交通大学硕士学位论文
第一章 序论
1.1 课题背景
随着经济的快速发展,人们生活节奏的提高,照顾家庭的时间将会越来越少。人们越来越感觉时间的紧张:不但要周旋在繁杂的工作之中,同时也要兼顾自己的“家”。怎样才能够解决这个矛盾,做到“鱼与熊掌兼得”成为人们关心的问题。现代科技的高速发展使两者的兼顾成为一种可能。
远程监控系统主要用于完成远程现场点的数据采集、处理、实时监控等功能。传统的远程监控系统采用自动控制技术、计算机技术并己广泛地应用于工业自动化、工业控制领域。然而,由于传统的远程监控系统没有或无法解决实时大数据量处理远程通信等问题,或者其成本等原因,其应用受到很大的。
网络通讯技术、嵌入式处理技术及图像压缩处理技术以及传输技术的快速发展.使得家庭能够采用最新的通讯和图像处理技术,组建家庭视频监控系统。通过在家中组建远程视频监控系统,人们在可以繁忙工作的同时,在远程就了解自己家庭概况,及时做出分析与判断。
目前,在国内外市场上,数控模拟系统已发展非常成熟、性能稳定,在实际工程应用中得到广泛应用,特别是在大、中型视频监控工程中的应用尤为广泛。但随着计算机技术和图像处理技术的发展,以计算机技术及图像视频压缩为核心的数字系统正迅速崛起,但尚不完全成熟,仍需进一步完善和发展。视频监控市场正处在数字和模拟混合应用并将逐渐向数字系统过渡的阶段。
数字信号控制的模拟视频监控系统分为基于微处理器的视频切换控制加PC机的多媒体管理和基于PC机实现对矩阵主机的切换控制及对系统的多媒体管理两种类型[1]。数控模拟视频监控系统的传输工具主要是同轴电缆,通常只适合于小范围的区域监控,系统的扩展能力差,新的设备也很难添加到原有的系统之中。而且在模拟监控系统中,由于各部分运作,相互之间的控制协议很难互通,联动只能在有限的范围内进行,无法形成有效的报警联动。
3
上海交通大学硕士学位论文
90年代末,随着微处理器、微机的功能、性能的增强和提高,多媒体技术、视频压缩编码技术、网络通讯技术的发展,视频监控系统在功能、性能、可靠性、结构方式等方面的要求都发生了很大的变化。模拟系统已无法满足更高的要求,数字监控系统应运而生。数字化监控系统的核心技术就是图像压缩存储技术和网络传输技术。数字监控系统的输入、控制、显示、存储这四大部分均采用数字化图像压缩处理技术,是经过数字化处理的图像,可利用现有的网络技术,将现场图像传输到远端监控中心。
前端一体化、视频数字化、监控网络化、系统集成化是视频监控系统公认的发展方向,而数字化是网络化的前提,网络化又是系统集成化的基础,所以,视频监控发展的最大两个特点就是数字化和网络化。
视频监控系统的数字化首先应该是系统中信息流(包括视频、音频、控制等)从模拟状态转为数字状态,这将彻底打破“经典闭路电视系统是以摄像机成像技术为中心”的结构,根本上改变视频监控系统从信息采集、数据处理、传输、系统控制等的方式和结构形式。信息流的数字化、编码压缩、开放式的协议,使视频监控系统与安防系统中其它各子系统间实现无缝连接,并在统一的操作平台上实现管理和控制,这也是系统集成化的含义[2]。
视频监控系统的网络化将意味着系统的结构将由集中式向集散式系统过渡,集散式系统采用多层分级的结构形式,具有微内核技术的实时多任务、多用户、分布式操作系统以实现抢先任务调度算法的快速响应,组成集散式监控系统的硬件和软件采用标准化、模块化和系列化的设计,系统设备的配置具有通用性强、开放性好、系统组态灵活、控制功能完善、数据处理方便、人机界面友好以及系统安装、调试和维修简单化,系统运行互为热备份,容错可靠等功能。
系统的网络化在某种程度上打破了布控区域和设备扩展的地域和数量界限。系统网络化将使整个网络系统硬件和软件资源的共享以及任务和负载的共享,这也是系统集成的一个重要概念。
1.2嵌入式系统概述
在现在日益信息化的社会中,计算机和网络已经全面渗透到日常生活的每一个角落。对于我们每个人,需要的已经不再仅仅是那种放在桌上处理文档,进
4
上海交通大学硕士学位论文
行工作管理和生产控制的计算机\"机器\";各种各样的新型嵌入式系统设备在应用数量上已经远远超过通用计算机,任何一个普通人可能拥有从大到小的各种使用嵌入式技术的电子产品,小到mp3,PDA等微型数字化产品,大到网络家电,智能家电,车载电子设备。而在工业和服务领域中,使用嵌入式技术的数字机床,智能工具,工业机器人,服务机器人也将逐渐改变传统的工业和服务方式。目前嵌入式系统技术已经成为了最热门的技术之一,吸引了大批的优秀人才投入其中。
1.2.1嵌入式系统的概念
嵌入式系统(Embedded System)是以应用为中心,以计算机技术为基础,软硬件可裁减的,能满足应用系统对功能、可靠性、成本、体积、功耗等指标的严格要求的专用计算机系统。它可以实现对设备的控制、监视或管理等功能。嵌入式系统的概念是相对于通用计算机系统而提出的。通用计算机系统是对执行非嵌入式应用的计算机系统的统称。它包括硬件和软件两部分。硬件包括处理器/微处理器、存储器及外设器件和I/0端口、图形控制器等。软件部分包括操作系统软件(要求实时和多任务操作)和应用程序。应用程序控制着系统的运行,而操作系统控制着应用程序编程与硬件的交互作用。有时设计人员把这两种软件组合在一起。这种系统具有软件代码小,高度智能化,响应速度快等特点,特别适合于要求实时的和多任务的体系。
与普通的计算机系统一样,嵌入式系统也是一种软硬件混合系统,整个系统是由硬件和软件两大部分组成。前者是整个系统的物理基础,它提供软件运行平台和通信(包括人---机交互)接口,后者实际控制系统的运行。硬件部分又包括嵌入式处理器、外围设备和外围电路三个部分;软件部分分为嵌入式操作系统和应用软件两个层次,如下图所示。
图1-1 嵌入式系统软件结构
Figure 1-1 software structure of embedded system
应用软件 嵌入式操作系统 外围设备
外围电路
处理器
嵌入式系统的核心是嵌入式微处理器。嵌入式微处理器一般具备以下4个
5
上海交通大学硕士学位论文
特点:
1)对实时多任务有很强的支持能力,能完成多任务并且有较短的中断响应时间,从而使内部的代码和实时内核心的执行时间减少到最低限度。
2)具有功能很强的存储区保护功能。这是由于嵌入式系统的软件结构已模块化,而为了避免在软件模块之间出现错误的交叉作用,需要设计强大的存储区保护功能,同时也有利于软件诊断。
3)可扩展的处理器结构,以能最迅速地开展出满足应的最高性能的嵌入式微处理器。
4)嵌入式微处理器必须功耗很低,尤其是用于便携式的无线及移动的计算和通信设备中靠电池供电的嵌入式系统更是如此,如需要功耗只有mW甚至µW级。
1.2.2 嵌入式系统的特点
嵌入式系统可以称为后PC时代和后网络时代的新秀。与传统的通用计算机,数字产品相比,它具有以下特点:
1.嵌入式系统通常是面向特定应用的嵌入式CPU与通用型的最大不同就是嵌入式CPU大多工作在为特定用户群设计的系统中,它通常都具有低功耗、体积小、集成度高等特点,能够把通用CPU中许多由板卡完成的任务集成在芯片内部,从而有利于嵌入式系统设计趋于小型化,移动能力大大增强,跟网络的耦合也越来越紧密。
2.嵌入式系统是将先进的计算机技术、半导体技术和电子技术与各个行业的具体应用相结合后的产物。这一点就决定了它必然是一个技术密集、资金密集、高度分散、不断创新的知识集成系统。
3.嵌入式系统的硬件和软件都必须高效率地设计,量体裁衣、去除冗余,力争在同样的硅片面积上实现更高的性能,这样才能在具体应用中对处理器的选择更具有竞争力。
4.嵌入式系统和具体应用有机地结合在一起,它的升级换代也是和具体产品同步进行,因此嵌入式系统产品一旦进入市场,具有较长的生命周期。
5.为了提高执行速度和系统可靠性,嵌入式系统中的软件一般都固化在存
6
上海交通大学硕士学位论文
储器芯片或单片机本身中,而不是存贮于磁盘等载体中。
6.嵌入式系统本身不具备自举开发能力,即使设计完成以后用户通常也是不能对其中的程序功能进行修改的,必须有一套开发工具和环境才能进行开发。
1.3视频监控系统的现状与发展
1.3.1 远程视频监控系统概述
视频监控系统对于保障人们日常生产和生活的安全具有重要意义,是大型企业诸如集团化公司、邮电、银行等信息交流广泛的企业生产与管理的必备系统。视频监控系统也随之经历了三个时代[3]。
在九十年代初以前,主要是以模拟设备为主的闭路电视监控系统,称为第一代模拟监控系统。九十年代中期,随着计算机处理能力的提高和视频技术的发展,人们利用计算机的高速数据处理能力进行视频的采集和处理,利用显示器的高分辨率实现图像的多画面显示,从而大大提高图像质量,这种基于PC机的多媒体主控台系统称为第二代数字化本地视频监控系统。九十年代末,随着网络带宽、计算机处理能力和存储容量的快速提高,以及各种实用视频处理技术的出现,视频监控步入了全数字化的网络时代,称为第三代远程视频监控系统。
第二代和第三代视频监控系统可以统称为数字视频监控系统。数字监控与传统的模拟监控相比,具有很多优点:
便于计算机处理。由于对视频图像进行了数字化,所以可以充分利用
计算机的快速处理能力,对其进行压缩、分析、存储和显示。通过视频分析,可以即时发现异常情况并进行联动报警,从而实现无人值守。 适合远距离传输。数字信息抗干扰能力强,不易受传输线路信号衰减
的影响,而且能够进行加密传输,因而可以在数千公里之外实时监控现场。特别是在现场环境恶劣或不便于直接深入现场的情况下,数字视频监控能达到亲临现场的效果。
便于查找。在传统的模拟监控系统中,当出现问题时需要花大量时
间 观看录像带才能找到现场记录;而数字视频监控系统中,利用计
7
上海交通大学硕士学位论文
算机建立的索引,在几分钟内就能找到相应的现场记录。
提高了图像的质量与监控效率。利用计算机可以对不清晰的图像进行
去噪、锐化等处理,通过调整图像大小,借助显示器的高分辨率,可以观看到清晰的高质量的图像。此外,可以在一台显示器上同时观看16路甚至32路视频图像。
系统易于管理和维护。数字视频监控系统主要由电子设备组成、集成
度高、视频传输可利用有线或无线信道。这样,整个系统是模块化结构、体积小、易于安装、使用和维护。
正是由于数字视频监控具有传统模拟监控无法比拟的优点,而且符合当前信息社会中数字化、网络化和智能化的发展趋势,所以数字视频监控正在逐步取代模拟监控,广泛应用于各行各业。
远程视频监控系统是数字视频监控系统的一种。它是以计算机技术为核心,结合先进的多媒体技术、网络通信技术、数字图像压缩技术的一种远程监控系统。远程监控系统能将监控现场的监控信息通过计算机网络传输到网络中的其他计算机上,并与信息管理系统融合在一起,达到远程监控的目的。
远程视频监控系统打破了“闭路电视系统”模拟方式的结构,从根本上改变了视频监控系统信息采集、传输处理、系统控制的方式和结构形式。也标志着监控正在走向现代“四化”阶段:
前端一体化
监控系统前端一体化意味着多种技术的整合、嵌入式构架、实用和适应性更强以及不同探测设备的整合输出,为系统集成化奠定了基础。
传输网络化
视频监控系统的网络化意味着系统的结构将由集总式向集散式系统发展,集散式系统采用多层分级的结构形式,将使整个网络系统硬件和软件资源以及任务和负载得以共享,这也是系统集成与整合的重要基础。
处理数字化
信息处理数字化意味着信息流的数字化、编码压缩、开放式的协议,具有微内核技术的实时多任务、多用户、分布式操作系统,以实现抢先任务调
8
上海交通大学硕士学位论文
度算法的快速响应,硬件和软件采用标准化、模块化和系列化的设计,系统设备的配置具有通用性强、开放性好、系统组态灵活、控制功能完善、数据处理方便、人机界面友好以及系统安装、调试和维修简单化,容错可靠等功能、
系统集成化
系统集成化正是由于构建系统的各子系统均实现了网络化和数字化,特别是使视频监控系统与弱电系统中其他各子系统间实现无缝连接,从而实现了在统一的操作平台上进行管理和控制。
1.3.2 远程视频监控系统体系结构
一个比较典型的远程视频监控系统,它涉及到远程监控现场构成、监控中心构成、视频进入计算机网络、视频图像传输、现场及远程多点控制等多方面内容。一般远程监控系统包括本地和远程监控两部分,由远程监控现场和监控中心组成,在远程监控现场和监控中心之间通过网络通信线路连接。其典型的结构如图所示[1]。
现场摄像机 现场摄像机现场摄像机 视频切换矩阵/编解码器显示器 现场监控主机 视频流视频流控制指令传输网络传输模块 9
监控中心主机 控制指令接收模块
图1-2 远程监控系统典型结构 Figure 1-2 typical structure of remote surveillance system
在每个远程监控现场均有若干摄像机。摄像机的镜头、云台可控,并可加装传感器、警灯、警号等外围报警设备。每个监控现场由一台配置较好的计算
上海交通大学硕士学位论文
机作为基本监控中枢,内含视频采集压缩卡和视频服务软件,它对监控现场的视频图像进行实时播放、实时采集及实时存储,同时还要向监控中心发送实时图像。还可以控制该现场的摄像机切换,镜头、云台动作,及处理报警信息等。同时它也能接收监控中心发送的控制命令,并执行相应的操作。
监控中心由一台或多台配置相对较高的监控主机组成。在监控中心可以任意对各个现场实行监控。它既可以完成对远程现场视频图像数据的实时接收、播放、存储及控制该现场摄像机切换,镜头、云台动作,又可以接收处理各现场的报警信息。监控人员将在监控中心完成对远程监控现场的监控动作,以及对设备报警进行处理。
主机、视频采集压缩卡、视频图像处理软件、图像发送软件与主控软件,构成了远程监控中心单元。摄像机及音频、报警采集器为前端采集单元,网络工作站及监控中心接收控制软件为用户接收单元,各部分协调工作,形成有机而完整的现代化远程视频监控系统。
1.4 研究工作
本课题将要设计并实现一个以S3C2410微处理器为核心的家用嵌入式视频服务器。该系统以韩国三星公司的ARM9芯片S3C2410为主CPU,同时采用代码开放的操作系统Linux。USB摄像头采集的视频信号经过处理后经视频压缩算法MPEG-4压缩后,通过内部总线送到CPU,然后经过Internet网络实时传输到用户的监视器上,从而解除了工作之余对家庭的担忧。 论文的研究工作主要集中在一下几个方面: 1) 系统整体平台的构建; 2) USB摄像头驱动的开发;
3) 基于Video4Linux的视频采集程序的开发; 4) 基于MPEG-4算法的视频数据压缩; 5) 基于RTP/UDP/IP协议的数据传输。
10
上海交通大学硕士学位论文
第二章 嵌入式Linux家庭视频监控系统平台设计
2.1 系统的方案设计与原理
视频监控系统总体结构分为两个部分:视频监控终端设备,视频监控网络平
台系统。视频监控终端设备和视频监控网络平台都直接连接在Internet上,通过RTP/UDP/IP协议传递数据。视频监控终端设备负责采集实时视频数据,是整个监护系统的数据终端。由于整个系统采用模块化的设计方法,所以任何实现我们所定制的彩信监护终端协议的设备,如果直接连接在Internet上即可成为这个系统的一部分。当监控网络平台发送命令要求获得数据时,终端把实时数据通过Internet发送给它。
2.1.1 系统构成
这是一种客户/服务器模式的结构体系。USB HUB可以连接比较多的USB设备,
RAM/ROM/FLASH
图2-1 系统总体结构图
Figure 2-1 total structure diagram of system
11
地址总线 S3C2410微处理器 MPEG 4视频压缩模块USB HUBUSB视频设备数据总线 RTP/UDP/IP 协议其他USB设备Internet网络 用户端监控设备 上海交通大学硕士学位论文
图2-1中USB视频设备所用的是USB摄像头。USB 摄像头以及S3C2410微处理器构成整个系统的视频监控终端设备,放在监控现场,而Internet网络与用户端监控设备一起构成监控网络平台,通过网络用户可随时了解监控现场的情况。
2.1.2 系统工作原理与流程
由图2-1可见该系统主要由CPU芯片、Flash芯片、SDRAM内存、以太网络接口组成。其中CPU采用SUMSANG公司的ARM系列嵌入式处理器S3C2410。为了节省开支,在系统方案中MPEG-4音视频编码采用软件算法来实现,它完成对从摄像头传送过来的视频数据的压缩和编码。根据网络带宽、拓扑结构以及对图像质量的要求,本系统选用基于MPEG-4标准的分层可扩展性编码方案。压缩后的视频数据通过Internet网络进行传输。
下面通过系统的应用软件结构来说明系统的工作原理和流程。
视频监控终端WEB服务器 网络连接(TCP/IP)HTTP/TCP/IPCGI程序 控制指令 摄像头控制 摄像头 控制指令数据读写 嵌入式数据 视频请求视频调度与传输 RTP/UDP/IP 存储管理与调度 已编码视频未编码视频 视频编码
图2-2 系统软件结构图
Figure 2-2 system software structure diagram
视频监控终端WEB服务器的应用软件结构如图所示。其主要由WEB服务器、CGI程序、嵌入式数据库MSQL、视频调度与传输模块、存储管理与调度模块、摄像头
12
上海交通大学硕士学位论文
控制模块等几个重要部分组成。
系统通过摄像头采集图像,对现场图像进行高速捕捉,然后将捕捉到的图像通过USB总线传输到S3C2410处理器进行处理,并将图像压缩,保存为JPEG格式的文件。程序调用Encoder编码器可以将多幅JPEG格式的图像合成一段AVI视频流,实现视频回放,这在安全监控、事故鉴定、车辆防盗等领域中都有广泛应用。最后,系统还可以通过以太网口或UART口将保存的图片和视频流传到服务器上,实现网络监控。
视频监控终端WEB服务器通过HTTP协议与用户端监控设备浏览器软件进行信息交互,提供其他应用程序模块的接口以及视频数据浏览界面和摄像头控制界面。此外,它还要对用户端的访问权限进行控制,过滤用户端的请求和控制信息,处理多个用户端的请求和控制的同步和优先级问题。 本系统选择适合于嵌入式系统的Boa WEB服务器。Boa是一个单任务的HTTP服务器,支持能够实现动态WEB技术的CGI技术,源代码开放、性能高。同时服务器程序本身所占空间很小,因而十分适用于嵌入式系统。 同时,本系统采用了CGI(公用网关接口) 来实现动态WEB技术,CGI规定了WEB服务器调用其他可执行程序(CGI程序)的接口协议标准。WEB服务器通过调用CGI程序实现和浏览器的交互,也就是CGI程序接受浏览器发送给WEB服务器的信息,进行处理,将响应结果再回送给WEB服务器及浏览器。CGI程序可以用任何程序设计语言编写,但是为了提高可移植性以及执行速度,在此用C语言编写的CGI程序。 1. 嵌入式数据库MSQL
在系统中,用户信息的存储,用户的登录登出,视频设备参数的存储与查询,视频文件的存储与查询等,都需要一个嵌入式数据库。综合考虑,本系统使用mSQL(MiniSQL)作为本系统的后台数据库[4]。mSQL是一款优秀的嵌入式数据库,体系结构小巧,占用系统资源少,特别适合在嵌入式Linux系统中使用。同时,mSQL提供专门的API函数,使得用C语言编写的CGI程序可以与mSQL的数据库引擎进行通信。
2. 存储管理与调度模块
存储管理模块的主要功能是将压缩和编码后的视频信息根据一定的策略存储至磁盘中特定的区域,并将视频文件信息存储到嵌入式数据库中,以供检索与
13
上海交通大学硕士学位论文
回放,同时响应视频调度与传输模块的请求,按照一定的磁盘调度策略和优先级顺序从磁盘中读取视频数据至内存缓冲区。对于存储管理,本系统采用等长分组存储策略,即将视频信息按照时序关系分割成若干数据单元,这些数据单元称为分组,将每个分组存储于一个大小固定的存储单元内。
3. 视频调度与传输模块
视频调度与传输模块为监控端提供所需的实时视频信息,是该系统能工作的核心模块。该模块根据所采取的网络传输与控制协议与用户端建立连接,监听用户端的请求;同时又根据不同的服务类型采取相应的调度策略创建视频流,然后将视频数据分组、打包,发送到用户端,并根据路由器和用户端反馈的网络状态信息进行差错处理和拥塞控制。
视频图像的传输质量直接影响系统的监控质量,在设计远程监控系统时,要充分考虑传输网络因素。在选择网络时,应考虑以下几个因素[3]: 数字视频信号虽已经经过压缩,但数据量还是很大,特别是当几路视频信号同时在网络传输时,大量的数据传输会使得网络变得很拥挤,而这会必然造成数据的延迟及丢失。这就要求传输网络的带宽要高,一次能传输大量的数据。
监控系统一边要求实现远程实时监控,及远程监控现场的情景要实时地显现在监控中心地主机上,这就要求传输网络地传输速度要很快。
因为传输的视频信号的数据量很大,故一般选用效率较高地UDP协议传输视频信号,UDP是无连接的,不可靠的协议,所以要求传输网络的可靠性要高,这样系统才能运行得很好。
网络传输协议
网络传输协议主要是TCP/IP,TCP/IP分层模型如图2-3所示。
应用层
可靠数据流 用户数据包(UDP)
网际层(IP) 网络接口层
图2-3 TCP/IP协议分层模型
Figure 2-3 hierarchical classification model of TCP/IP Protocol
在TCP/IP分层模型中,传输层建立在IP层之上,包含两种传输协议:传输控制协议TCP和用户数据报协议UDP。TCP是面向连接的传输协议,在传输数据之前,必须在发送方和接受方之间建立通信信道,它拥有重传机制和拥塞控
14
上海交通大学硕士学位论文
制机制,提供高可靠性的服务。而UDP是无连接的数据报传输,它不需要建立连接和撤销连接,而直接把数据送到接收端,并且还取消了重发校验机制,能够达到较高的通信速率。所以UDP的主要特点是传输的高效率,但可靠性较低。一般情况下,TCP和UDP共存于一个网中,前者提供高可靠性服务,后者提供高效率服务,高可靠性的TCP用于对传输质量要求较高的情形,如文件传输、远程登录等;高效率的UDP用于对传输效率要求较高及网络的可靠性较高的场合,如实时语音图像传输。
视频图像传输的数据量大,并且对监控系统来说,用户对图像传输的实时性要求很高,如果选用可靠性很高的TCP,会因为TCP的建立撤销连接、确认和超时重传等很多保证可靠性的措施而大大降低传输的效率,这会造成图像传输很大的延时,失去实时监控的意义。而选用高效率的UDP,由于取消了重发校验等机制,能够达到较高的通信速率,虽然也许会出现少量的丢帧现象,但对数据量很大的视频图像的影响并不是很大,用户可以接受。并且,随着网络传输技术的发展,出现了很多可靠性很高且传输很快的网络,基于UDP的网络应用在这种网络上会运行的很好,弥补了UDP的不足。
根据以上分析在本系统中采用UDP网络通讯协议进行视频数据的传输,而采用UDP的IP传送方式有点播、广播和组播三种,其中组播是服务器只向特定的用户组发送一个数据包,组中的各用户可以共享这一数据包,而组外的用户却无法接收到。为了达到多点监控,本系统采用IP组播方式,采用组播技术的优点有以下几点:可以让服务器承担大量客户端的视频数据播送要求;由于数据包拷贝数量和发送目的地址少,大大减少了网络中传输的数据总量,从而保证较高的服务质量;减小了视频数据流传输的带宽占用,减轻了服务器的负担。
在应用层使用实时传输协议RTP进行视频数据的传输。它是一种提供端对端的实时媒体传输服务的协议,由实时传输协议RTP和实时传输控制协议RTCP两个部分组成。RTP用于实时视频数据的传输,而RTCP则用来监控实时视频数据的传输。RTP/UDP/IP的方式兼顾了视频传输的实时性与QoS保证。同时针对传输网络状况的不确定性,还可以采取一定的拥塞控制和差错控制策略。 在第四章将详细分析并给出RTP协议的具体实现。
4. 摄像头控制模块
15
上海交通大学硕士学位论文
该模块主要实现对摄像头的控制。在用户端,用户通过浏览器向WEB服务器发送摄像头控制命令,该命令经WEB服务器接收和处理后,再通过CGI程序发送给摄像机控制模块,然后被转换成相应的对摄像头控制的硬件操作指令,从而实现对摄像头云台镜头的远程控制。
5. 用户端浏览
用户使用浏览器对监控现场进行监控,浏览器所运行的平台与嵌入式WEB服务器所运行的平立,可以使用Microsoft Internet Explorer浏览器进行浏览,提高了该系统的大众化与普及程度。
2.2 嵌入式系统开发平台及Linux内核裁剪及移植
鉴于嵌入式系统的专用性,各系统之间的差别是巨大的,但是也要承认很多嵌入式系统,尤其是应用目标相近的嵌入式系统,其系统的软硬件核心是相似的。视频监控终端设备采用的是32位嵌入式系统。首先根据所选择的MPU类型,以公开的嵌入式Linux源代码为基础,根据设计的嵌入式目标板的情况修改已经成熟的适用于嵌入式系统的Bootloader程序。然后根据标准Linux裁减出合适的内核和文件系统。把这些固化到目标板Flash中,就构成了本文的视频监控终端设备的基板。
2.2.1 嵌入式Linux操作系统简介
Linux操作系统是一种开放源码,可裁剪内核,运行于个人计算机和工作站上的类UNIX操作系统。它最初是由一名芬兰学生Linux Torvalds开发的,后来成立了一个由他领导的内核开发小组对Linux内核进行了完善。这使Linux在短期内就成为了一个稳定成熟的操作系统,在x86, Alpha, Sparc, MIPS, PPC, Motorola, NEC,ARM等硬件平台上运行稳定高效。作为一种成熟,稳定并在短时间内得到广泛应用的开源操作系统,Linux具有一些它自己的特点[5]。
真正的多用户、多任务操作系统; 符合POSIX标准;
具有完善的内核编程接口;
提供shell命令解释程序和编程语言;
16
上海交通大学硕士学位论文
提供强大的管理功能,包括远程管理功能; 具有简单易用的图形用户接口; 具有大量的应用程序和工具;
在Linux下开发的应用程序有很好的可移植性。
由于Linux具有开放性,可以支持不同的设备,支持不同的配置,而且成本极低,是一种可以运行于各种硬件平台的操作系统,因此Linux进入嵌入式领域己是大势所趋,其巨大的市场潜力与酝酿中的无限商机吸引了众多的厂商进入这一领域。Linux用于嵌入式系统,有它自身的一些优点。
由于其源代码公开,人们可以任意修改,以满足自己的应用,并且查错 也很容易。
遵从GPL,无须为每例应用交纳许可证费。
有大量的应用软件可用。其中大部分都遵从GPL,是开放源代码和免费的。
可以稍加修改后应用于用户自己的系统。
有大量的免费的优秀的开发工具,且都遵从GPL,是开放源代码的。 有庞大的开发人员群体。无需专门的人才,只要懂Unix/Linux和C语言即
可.随着Linux在中国的普及,这类人才越来越多。所以软件的开发和 维 护 成 本很低。
优秀的网络功能,这在Internet时代尤其重要。 稳定。这是Linux本身具备的一个很大优点。 内核精悍,运行所需资源少,十分适合嵌入式应用。
支持的硬件数量庞大。嵌入式Linux和普通Linux并无本质区别,PC上用到的硬件嵌入式Linux几乎都支持。而且各种硬件的驱动程序源代码都可以得到,为用户编写自己专有硬件的驱动程序带来很大方便。 正是考虑到嵌入式Linux具有以上众多优点,在开发本系统时嵌入式Linux作为主要操作系统。为了使Linux操作系统能在所用的开发板上运行,必须进行操作系统的移植。在移植Linux操作系统之前先建立系统编译环境。
2.2.2 交叉编译环境的建立
基于Linux操作系统的应用开发环境一般是由目标系统硬件(开发板)和宿
17
上海交通大学硕士学位论文
主PC机所构成。目标硬件开发板用于运行操作系统和系统应用软件,而目标板所用到的操作系统的内核编译、应用程序的开发和调试则需要通过宿主PC机来完成(所以称为交叉编译)。双方之间一般通过串口、并口或以太网接口建立连接关系。单独拿出一台PC机,在该PC上安装桌面的Linux操作系统(如Red Hat Linux9.0),可以采用默认的安装选项(注意要包含FTP服务),这台PC作为Linux服务器,除管理员以外,一般不直接让其他人去操作。
将该Linux服务器接入局域网,并新建一些合法用户,以便其他的PC机(在此将其称为工作站)的合法用户能访问到Linux服务器。而其他的PC机(工作站)仍然使用Windows操作系统。
需要的软件工具包括 : ftp客户端程序。 Telnet工具。
移植到某一特定ARM平台的Linux操作系统内核源码。 GNU编译工具,可由相关网站下载。
在某工作站PC上安装ftp客户端程序和Telnet工具 ,安装完毕后应该可以在该工站PC和Linux服务器之间进行文件的传输,并在工作站PC可以通过Telnet登陆到Linux服务器(可能需要将Linux服务器 的防火墙服务关闭才能完成)。
Linux服务器的安装:将工作站PC上的Linux操作系统内核源码压缩包和GNU编译工具通过ftp传送到Linux服务器的某个目录(如合法的用户目录),然后在该目录下解压,并将GNU编译工具安装到默认的工作目录即可,以上工作通过在工作站PC使用Telnet工具完成,而不需要在Linux服务器上进行。Linux操作系统内核的编译一般有一个比较固定的步骤,会根据MakeFile文件的不同而略有差异,可参考相关文档,编译的工作在工作站PC使用Telnet工具完成。按固定的步骤编译内核完成以后,会在相应目录生成可执行的二进制文件,通过ftp将该可执行的二进制文件传回工作站PC,然后通过ADS或SDT下的烧写工具写入开发板的Flash即可。
18
上海交通大学硕士学位论文
2.2.3 Bootloader的架构和功能
Bootloader引导程序是嵌入式开发很重要的组成部分。它是嵌入式系统上电后执行的第一个程序,并由它最终将操作系统启动起来并将控制权交给操作系统。Bootloader引导程序最基本的功能是对硬件系统的初始化和内核启动参数设置并启动内核。Bootloader的主要功能有:
初始化CPU 的主频、SDRAM、中断、串口等硬件; 启动Linux内核并提供一个RAMDISK; 通过串口下载内核或RAMDISK到目标板上; 将修改过的内核或RAMDISK写入到Flash内; 为用户提供一个命令接口。
在嵌入式系统开发过程中,Bootloader还与主机通信,不断检测从主机传来的控制信息和数据信息,完成相应的操作。
Linux运行在保护模式下,但是当机器启动复位的时候却处于实模式下。所以写Bootloader的工作也是在实模式之下的。
Botloader的实现除了依赖于CPU的体系结构,还依赖于目标板的设置,本系统的Bootloader引导程序分为stagel和stage2两个阶段。依赖于CPU的体系机构的代码 ,比如设备初始化等,放在stagel中,采用ARM汇编语言来实现,这样可以达到短小精悍的目的。stage2用C语言来实现,可以实现复杂的功能,同时代码具有更好的可读性和可移植性。
Bootloader的stage1
stage1是Bootloader一开始就执行的操作,其目的是为了stage2的执行以及随后的内核的执行,设置好一些基本的硬件环境。
包括以下步骤 :
①屏蔽所有的中断。为中断提供服务的通常是操作系统,因此在执行Bootloader的过程中可以不响应任何中断。中断屏蔽通过写CPU的中断屏蔽寄存器来完成。
②设置CPU的时钟频率和速度。
③初始化RAM设置系统的内存控制器的功能寄存器和各内存库控制寄存器等。
19
上海交通大学硕士学位论文
④为加载stage2准备RAM空间。 ⑤拷贝stage2到RAM中。 ⑥跳转到stage2的入口点。 Bootloader的stage2
stage2的主要的功能是通过串口下载Linux内核到目标板上。 包括以下几个步骤:
①初始化本阶段要使用到的硬件设备。这通常包括:初始化至少一个串口,以便和终端用户进行I/O输出信息;初始化计时器等。
②检测系统的内存映射。所谓内存映射就是指在整个4GB物理地址空间中有哪些地址范围被分配用来寻址系统的RAM单元。
③加载内核映像和根文件系统从Flash读入到Rom中。这里包括两个方面:a.内核映像所占用的内存范围;b.根文件系统所占用的内存范围。在规划内存占用的布局时,主要考虑基地址和映像的大小两个方面。
④设置内核的启动参数。
⑤调用内核。Bootloader调用Linux内核的方法是直接跳转到内核的第一条指令处。
2.2.4 设置软件开发环境
为了和目标板进行通讯,必须要在主机上终端运行仿真程序minicom。建议在宿主机上安装RED HAT Linux9.0版本。以下以在SHELL模式下安装编译器和源代码为例介绍安装过程 :
首先以ROOT身份进入系统。把RED HAT Linux9.0的安装光盘放入光驱中,执行装载光驱命令:
moumt /dev/cdrom /mnt/cdrom
如果系统不能识别/mnt/cdrom,可以使用如下命令(假设cdrom为/dev/had),则用mount -t iso9660 /dev/hdb/mnt
如果在安装RED HAT Linux9.0的时候已经默认安装了CDROM,以上命令不需执行,直接进入CDROM所在目录。
mkdir /usr/local/arm
20
上海交通大学硕士学位论文
mount /dev/cdrom /mnt/cdrom cd/
cp /mnt/cdrom/bin/cross-2.95.3.tar.bz2 /usr/local/arm/ cp /mnt/cdrom/bin/Linux_for_s3c2410.gz tar zxvf Linux_for_s3c2410.gz cd /usr/local/arm/ tar -jxvf cross-2.95.3.tar.bz2
程序执行完后,Linux源代码和编译环境都已建立起来了。
2.2.5 Linux内核编译
首先以ROOT身份进入系统。然后完成下列步骤,就可以在
/Linux/arch/arm/boot/得到内核的映像文件zImage。在shell命令下输入命令进行内核配置: make menuconfig
该命令执行之后生成文件.config。它保存这个配置信息,下一次再执行make menuconfig的时候将生成新的.config文件。
输入命令 :make dep 输入命令 :make clean 输入命令 :make zImage
通过各个目录的Makefile进行,将会在各个目录下生成一系列目标文件,上述步骤完成后,就完成了对Linux的编译工作。
Linux内核的编译、修改、移植实际上与上层的应用程序,如命令解释器shell、登陆程序login相关。这些程序应根据需要重新定制。
利用终端仿真程序minicom和Bootloader引导程序通过串口就可以把Linux内核移植到目标系统板。移植完成后,Linux就可以在目标系统板上运行了。
21
上海交通大学硕士学位论文
第三章 视频采集及压缩模块软件设计
嵌入式视频终端软件分为两部分:一部分是USB摄像头驱动的开发,这部分是作为Linux内核的一部分驻留在内核中,提供对硬件和操作系统的支持。第二部分是应用软件的开发,本章将详细讲述这两部分的软件设计和开发。
3.1 视频采集摄像头驱动设计
3.1.1 Linux设备驱动开发简介
系统调用是操作系统内核和应用程序之间的接口,设备驱动程序是操作系统内核和机器硬件之间的接口。设备驱动程序为应用程序屏蔽了硬件的细节,这样在应用程序看来,硬件设备只是一个设备文件, 应用程序可以像操作普通文件一样对硬件设备进行操作。设备驱动程序是内核的一部分,它完成以下的功能:
对设备初始化和释放。
把数据从内核传送到硬件和从硬件读取数据。
读取应用程序传送给设备文件的数据和回送应用程序请求的数据。 检测和处理设备出现的错误。
在Linux操作系统下有两类主要的设备文件类型,一种是字符设备,另一种是块设备。字符设备和块设备的主要区别是:在对字符设备发出读/写请求时,实际的硬件I/O一般就紧接着发生了,块设备则不然,它利用一块系统内存作缓冲区,当用户进程对设备请求能满足用户的要求,就返回请求的数据,如果不能,就调用请求函数来进行实际的I/O操作。块设备是主要针对磁盘等慢速设备设计的,以免耗费过多的CPU时间来等待。用户进程是通过设备文件来与实际的硬件打交道。每个设备文件都有其文件属性(c/b)表示是字符设备还是块设备。另外每个文件都有两个设备号,第一个是主设备号,标识驱动程序,第二个是从设备号,标识使用同一个设备驱动程序的不同的硬件设备,比如有两个软盘,就可以用从设备号来区分他们。设备文件的主设备号必须与设备驱动程序在登记时申请的主设备号一致,否则用户进程将无法访问到驱动程序。在用户进程调用驱动程序时,系统进入核心态,这时不再是抢先式调度。也就是说,系统必须在你的驱动程序的
22
上海交通大学硕士学位论文
子函数返回后才能进行其他的工作。
在系统内部,I/O设备的存取通过一组固定的入口点来进行,这组入口点是由每个设备的设备驱动程序提供的。一般来说,字符型设备驱动程序能够提供如下几个入口点[5]:
(1)open入口点。打开设备准备I/O操作。对字符特别设备文件进行打开操作,都会调用设备的open入口点。Open子程序必须对将要进行的I/O操作做好必要的准备工作,如清除缓冲区等。如果设备是独占的,即同一时刻只能有一个程序访问此设备,则open子程序必须设置一些标志以表示设备处于忙状态。 (2)close入口点。关闭一个设备。当最后一次使用设备终结后,调用close子程序。独占设备必须清楚标志。
(3)read入口点。从设备上读数据。对于有缓冲区的I/O操作,一般是从缓冲区里读数据。对于字符型设备文件进行读操作将调用read子程序。
(4)write入口点。向设备写数据。对于有缓冲区的I/O操作,一般是把数据写入缓冲区里。对字符型设备文件进行写操作将调用write子程序。 (5)ioctl入口点。执行读、写之外的操作。
Linux下对于一个硬件的驱动,可以有两种方式:直接加载到内核代码中,启动内核时就会驱动此硬件设备。另一种就是以模块方式,编译生成一个.o文件。模块(module)是在内核空间运行的程序,实际上是一种目标对象文件,没有链接,不能运行,但是可以装载到系统中作为内核的一部分运行,从而可以动态扩充内核的功能。模块最主要的用处就是用来实现设备驱动程序。当应用程序需要时再加载进内核空间运行。通常所指的一个硬件的驱动程序就是指一个驱动模块。
对于任何一个硬件设备,它在/dev下面存在一个对应的逻辑设备节点,也就是通常所说的设备文件。这个节点是通过mknod命令建立的,其中指定了主设备号和次设备号。主设备号表明了某一类设备,一般对应着确定的驱动程序;次设备号一般是区分不同属性,例如不同的使用方法,不同的位置,不同的操作。这个设备号是从/proc/devices文件中获得的,所以一般是先有驱动程序在内核中,才有设备节点在目录中。主设备号的主要作用,就是声明设备所使用的
23
上海交通大学硕士学位论文
驱动程序。驱动程序和设备号是一一对应的,当你打开一个设备文件时,操作系统就已经知道这个设备所对应的驱动程序。
对于一个硬件,Linux是这样来进行驱动的[6]:首先,我们必须提供一个.o的驱动模块文件(这里我们只说明模块方式,其实内核方式是类似的)。我们要使用这个驱动程序,首先要加载运行它(insmod *.o)。这样驱动就会根据自己的类型(字符设备类型或块设备)向系统注册,注册成功系统会反馈一个主设备号,这个主设备号就是系统对它的唯一标识(例如硬盘块设备在/proc/devices中显示的主设备号为3,我们用ls -l /dev/had看到的主设备就肯定是3)。驱动就是根据此主设备号来创建一个一般放置在/dev目录下的设备文件(mknod命令用来创建它,它必须用主设备号这个参数)。在我们要访问此硬件时,就可以对设备文件通过open、read、write等命令进行。而驱动就会接收到相应的read、write操作而根据自己的模块中的相应函数进行了。
其中还有几个比较有关系的东西:一个是/lib/modules/2.4.XX目录,它下面就是针对当前内核版本的模块。只要你的模块依赖关系正确(可以通过depmod设置),你就可以通过modprobe 命令加载而不需要知道具体模块文件位置。 另一个是/etc/modules.conf文件,它定义了一些常用设备的别名。系统就可以在需要此设备支持时,正确寻找驱动模块。例如alias eth0 e100,就代表第一块网卡的驱动模块为e100.o。他们之间的关系如图3-1所示:
图3-1 Linux驱动流程框图
Figure 3-1 Flow chart of device driver of Linux
24
上海交通大学硕士学位论文
3.1.2 USB摄像头驱动程序开发
USB是英文“Universal Serial Bus”的缩写,意为“通用串行总线”。是由Compaq(康柏)、DEC、IBM、Intel、NEC、微软以及Northern Telecom(北方电讯)等公司于1994年11月共同提出的,主要目的就是为了解决接口标准太多的弊端。USB使用一个4针插头作为标准插头,并通过这个标准接头,采用菊花瓣形式把所有外设连接起来,它采用串行方式传输数据,目前最大数据传输率为12Mbps, 支持多数据流和多个设备并行操作,允许外设热插拔。
目前USB接口虽然只发展了2代(USB1.0/1.1,USB2.0),但是USB综合了一个多平台标准的所有优点——包括降低成本,增加兼容性,可连接大量的外部设备,融合先进的功能和品质,使其逐步成为PC接口标准,进入了高速发展期[7]。
要使用USB设备需要正确的配置Linux内核,要启用Linux USB支持,首先进入\"USB support\"节并启用\"Support for USB\"选项(对应模块为usbcore.o)。尽管这个步骤相当直观明了,但接下来的 Linux USB 设置步骤则会让人感到糊涂。特别地,现在需要选择用于系统的正确 USB 主控制器驱动程序。选项是\"EHCI\" (对应模块为ehci-hcd.o)、\"UHCI\" (对应模块为usb-uhci.o)、\"UHCI (alternate driver)\"和\"OHCI\"(对应模块为usb-ohci.o)。这是Linux的USB让人开始感到困惑的地方。要理解\"EHCI\"及其同类是什么,首先要知道每块支持插入 USB设备的主板或PCI卡都需要有USB主控制器芯片组。这个特别的芯片组与插入系统的USB设备进行相互操作,并负责处理允许USB设备与系统其它部分通信所必需的所有低层次细节。Linux USB驱动程序有三种不同的USB主控制器选项是因为在主板和 PCI卡上有三种不同类型的USB芯片。\"EHCI\"驱动程序设计成为实现新的高速USB 2.0协议的芯片提供支持。\"OHCI\"驱动程序用来为非PC系统上的(以及带有SiS和ALi芯片组的PC主板上的)USB芯片提供支持。\"UHCI\"驱动程序用来为大多数其它PC主板(包括Intel和Via)上的USB实现提供支持。只需选择与希望启用的USB支持的类型对应的\"?HCI\"驱动程序即可。如有疑惑,为保险起见,可以启用\"EHCI\"、\"UHCI\"(两者中任选一种,它们之间没有明显的区别)和\"OHCI\"。在应用中我们启用OHCI。
Linux系统中对USB设备的支持是通过如图所示的结构实现的。Linux内
25
上海交通大学硕士学位论文
核中的USB Core为设备和主控制器提供API接口。USB Core包含所有的USB设备和主控制器的一些通用操作,为向上和向下操作提供一个接口。根据上面的分析可知,在Linux系统中,设备驱动可分为字符设备、块设备以及网络设备。其中,字符设备面向字符I/O操作,没有缓冲,顺序读取;而块设备面向数据块,所有操作都通过内核地址空间的I/O缓冲区完成,支持随机存取操作。
USB设备通过快速串行通信的方式工作,应作为字符设备来处理。系统加载设备驱动的方式有模块加载和内核初始化加载两种:前者通过用户使用insmod命令动态加载到内核中,通过rmmod命令卸载驱动模块;后者是把驱动编进内核,在内核初始化时自动加载。USB主口程序由HCD(主机控制器驱动)、USBD (USB驱动程序)以及客户程序组成。其中USBD负责管理所有HCD、设备驱动和所有连接到USB总线上的设备,是USB主机软件的核心。如图3-2所示,Linux系统中USB子系统采用分层结构,其中USBD和HCD提供了支持设备驱动程序开发的API。USB设备驱动程序不是通过I/O操作访问设备,而是通过USB Core提供的标准接口与设备交互,它采用由管道组成的通道与设备进行通信。设备驱动程序根据USBD创建所需的管道,并为其分配传输所需的缓冲空间。
USB设备驱动USB设备驱动USB CORE (USBD) USB主控制器驱动(HCD)USB主控制器驱动(HCD)
图3-2 Linux下USB系统软件结构 Figure 3-2 USB system software structure in Linux
在Linux kernel源码目录中driver/usb/usb-skeleton.c为我们提供了一个基础的USB驱动程序。我们称为USB骨架。通过它我们仅需要修改极少的部分,就可以完成一个USB设备的驱动。Linux USB 驱动程序需要做的第一件事情就是在Linux USB 子系统里注册,并提供相关信息。例如这个驱动程序支持那种设备,当被支持的设备从系统插入或拔出时,会有哪些动作。所有这些信息都
26
上海交通大学硕士学位论文
传送到USB 子系统中,在程序中是这样表示的: static struct usb_driver camera_driver = { .owner = THIS_MODULE, .name = \"cameragrab\ .id_table = device_table, .probe = camera_probe,
.disconnect = camera_disconnect };
变量owner是一种模块锁定机制,用于告诉内核在调用open()函数之前给哪个模块的使用计数增一。变量name是一个字符串,它对驱动程序进行描述。probe 和disconnect 是函数指针,当设备与在id_table 中变量信息匹配时,此函数被调用。
Usb驱动程序在注册时会发送一个命令给usb_register,通常在驱动程序的初始化函数里。当要从系统卸载驱动程序时,需要注销usb子系统。即需要usb_unregister 函数处理:
static int __init usb_camera_init () { if (usb_register (&camera_driver) < 0) return -1; return 0; }
static void __exit usb_camera_exit () { usb_deregister (&camera_driver); }
module_init (usb_camera_init); module_exit (usb_camera_exit);
当usb设备插入时,为了使linux-hotplug(Linux中PCI、USB等设备热插拔支持)系统自动装载驱动程序,需要创建一个MODULE_DEVICE_TABLE。当系统插入一个ID匹配的USB设备到USB总线时,驱动会在USB core中注册。驱动程序中probe 函数也就会被调用。usb_device 结构指针、接口号和接
27
上海交通大学硕士学位论文
口ID都会被传递到函数中。驱动程序需要确认插入的设备是否可以被接受,如果不接受,或者在初始化的过程中发生任何错误,probe函数返回一个NULL值。否则返回一个含有设备驱动程序状态的指针。通过这个指针,就可以访问所有结构中的回调函数。
static struct usb_device_id device_table [] = {
{ USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) }, { } };
MODULE_DEVICE_TABLE (usb, device_table);
函数probe()是USB设备插入后先要调用的,它首先检查制造商和产品的标志或者类型的定义,如果它们相符合,那么该接口号将会和该驱动支持的接口号进行比较。函数disconnect()当系统停用此设备时被调用,函数要清除所有申请的内核内存空间以及释放系统资源。一个简单的probe()和disconnect()函数原型如下[8]:
void *probe(struct usb_device *dev,unsigned int interface,const struct usb_device_id *id_table) { struct driver_context *context;
If(dev->descriptor.idvendor==0x0547&& dev->descriptor.idproduct==0x2131&&
interface==1){
MOD_INC_USE_COUNT;
context=allocate_driver_resources();
return context;
}
return NULL; }
static void _disconnect(struct usb_device *dev,void *drv_context)
{ struct driver_context *s=drv_context; s->remove_pending=1; wake_up(&s->wait);
sleep_on(&s->remove_ok); free_driver_resource(s); MOD_DEC_USE_COUNT; }
其中dev指定需要加载的硬件设备,它含有所有指向USB描述符的指针。Interface指定接口号。drv_context返回一个指向probe()函数中的context指
28
上海交通大学硕士学位论文
针。如果一个USB驱动想把它和某一个设备绑定,那么该驱动程序必须返回一个指针。这个指针引用了该设备驱动的背景结构。
USB的数据传输是通过统一的USB数据传输块(Universal Request Block, URB)来进行的,URB包含了一次USB数据传输所必须的所有信息,其中主要包括:USB设备信息、数据传输管道、数据传输缓冲区、数据传输缓冲区长度、回调函数、不同类型数据传输必需参数、数据传输过程控制参数等。因此当底层有数据传回的时候我们需要把URB里面的信息通过函数 static int camera_move_data (struct usb_camera *camera, struct urb *urb); 导出到我们定义的摄像头结构体中。结构体usb_camera中包含了驱动程序中最主要的信息,可以看为一个实际usb摄像头的虚拟设备,其中最主要的内容包括:
struct video_device *vdev:这是V4L子系统里面要用到的虚拟设备,在下一节会具体解释;
struct usb_device *dev:要向usb子系统注册的usb设备;
int maxwidth; int maxheight; int minwidth; int minheight:设置插入的摄像头支持的视频图像的大小范围;
int brightness;int colour;int contrast;int hue;int whiteness:设置插入的摄像头支持的色彩、对比度等。
struct semaphore lock:信号量,避免对摄像头的使用产生冲突。
struct camera_frame frame[CAMERA_NUMFRAMES];用于存放每一帧的信息。 char *fbuf:video_device用到的缓冲区。
当然还包括其他很多信息,限于篇幅在这里不一一列出了。
在驱动程序里,最后一点是我们要注册devfs。我们创建一个缓冲用来保存那些被发送给usb设备的数据和那些从设备上接受的数据,同时USB urb 被初始化,并且我们在devfs子系统中注册设备,允许devfs用户访问我们的设备。注册过程如下:
29
上海交通大学硕士学位论文
/* initialize the devfs node for this device and register it */ sprintf(name, \"skel%d\skel->devfs = devfs_register
(usb_devfs_handle, name,
DEVFS_FL_DEFAULT, USB_MAJOR, USB_SKEL_MINOR_BASE + skel->minor, S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, &skel_fops, NULL);
如果devfs_register函数失败,不用担心,devfs子系统会将此情况报告给用户。当然最后,如果设备从usb总线拔掉,设备指针会调用disconnect 函数。驱动程序就需要清除那些被分配了的所有私有数据、关闭urbs,并且从devfs上注销调自己。
现在,驱动就已经和设备绑定上了,任何用户态程序要操作此设备都可以通过file_operations结构所定义的函数进行了。
3.2 基于Video4Linux的视频采集模块开发
摄像头驱动程序安装好后为了进行视频采集必须加入Video4Linux模块,从
而可以通过Video4Linux模块提供的编程接口(API)从摄像头设备中获取图像帧。
3.2.1 Video4Linux简介
Video4Linux(简称V4L)是Linux中关于视频设备的内核驱动,它为针对视频设备的应用程序编程提供一系列接口函数,这些视频设备包括现今市场上流行的TV卡、视频捕捉卡和USB摄像头等。对于USB口摄像头,其驱动程序中需要提供基本的I/O操作接口函数open、read、write、close的实现。对中断的处理实现,
30
上海交通大学硕士学位论文
内存映射功能以及对I/O通道的控制接口函数ioct1的实现等,并把它们定义在struct file_operations中。这样当应用程序对设备文件进行诸如open、close、read、write等系统调用操作时,Linux内核将通过file_operations结构访问驱动程序提供的函数[9]。
3.2.2 视频编程所涉及的数据结构及用途
typedef struct v4l_struct { int fd;
struct video_capability capability; struct video_channel channel[4]; struct video_picture picture; struct video_window window; struct video_capture capture; struct video_buffer buffer; struct video_mmap mmap; struct video_mbuf mbuf; unsigned char *map; int frame; int framestat[2]; }vd;
video_capability 结构包含设备的基本信息,如设备名称、支持的最大最小分
辨率、信号源信息等。它包含以下分量:name[32] 指定设备名称,maxwidth,maxheight,minwidth,minheight指定摄像头能捕捉的最大和最小的图像尺寸。Channels指定信号源个数,Type表示所截取的图像是否能被捕捉,是彩色还是黑白,是否能裁剪等等。
video_channel结构指定各个信号源的属性,它包含以下分量:Channel 指定
信号源的编号,name为每个信号源的名称,Type指定所输入的信号类型,包含以下两种输入, VIDEO_TYPE_TV表示输入为电视信号,
31
上海交通大学硕士学位论文
VIDEO_TYPE_CAMERA表示输入为摄像头信号。Norm表示电视信号所使用的制式,有VIDEO_MODE_PAL、VIDEO_MODE_NTSC、VIDEO_MODE_SECAM、VIDEO_MODE_AUTO等几种选项。
video_picture 结构用来设置采集图像的各种属性。它包含以下几个分量:
brightness、hue、colour、contrast来为采集的图像提供类似电视信号的控制,whiteness来为灰度图像提供额外控制。
video_window结构用来采集的图像的显示方法。它包括以下几个分量:x用
来描述窗口左上方的X坐标,y用来描述窗口左上方的y坐标 ,width用来描述采集图像的宽度,height用来描述采集图像的高度,当采用色度键时chromakey用来表示颜色,用RGB32格式表示的。
video_mbuf结构用来描述利用mmap进行映射的帧的信息,实际上是输入到摄
像头存储器缓冲中的帧信息。它包含以下几个分量size表示每帧大小,frames 用来表示最多支持的帧数,offsets表示每帧相对基址的偏移。
video_buffer结构用来对最底层的buffer进行描述,它包含以下几个分量:void
*baseBase描述buffer的物理地址,height描述frame buffer的高度,width描述frame buffer的宽度,depth描述frame buffer的深度,bytesperline描述每两个相邻的线之间的存储器字节数。 video_mmap用于内存映射。
3.2.3 视频编程流程
在Linux中,视频设备是设备文件,摄像头所对应的设备文件为/dev/video0,可以像访问普通文件一样对其进行读写,下面是对摄像头进行编程的一般流程:
1)打开视频设备: 2)读取设备信息
3)更改设备当前设置(如果有必要) 4)进行视频采集, 5)对采集的视频进行处理 6)关闭视频设备。
下面对其中的关键步骤进行说明[10]。
32
上海交通大学硕士学位论文
1.打开视频设备: open(”/dev/video0”,vd->fd);
2.读取设备中信息:ioctl(vd->fd, VIDIOCGCAP, &(vd->capability)),成功后可读取vd->capability结构中各分量的值,如printf(”maxheight = %d” vd->capability.maxheight);
3.读video_picture中信息:ioctl(vd->fd, VIDIOCGPICT, &(vd->picture));
4.改变video_picture中分量的值。先为分量赋新值,再调用VIDIOCSPICT命令,如 vd->picture.colour = 32768;
if(ioctl(vd->fd, VIDIOCSPICT, &(vd->picture)) < 0) {
perror(\"VIDIOCSPICT ERROR\"); return -1; }
5.初始化channel。首先必须得到vd->capability结构中的信息。实现过程如下[11]: for (i = 0; i < vd->capability.channels; i++) {
vd->channel[i].channel = i;
if (ioctl(vd->fd, VIDIOCGCHAN, &(vd->channel[i])) < 0) {
perror(\"v4l_get_channel:\"); return -1; } }
6.视频采集。完成以上初始化设备工作后,就可以对视频图像采集与截取了,通常情况下有两种方法[12]:一种是read()直接读取,另外一种mmap()内存映射。read()通过内核缓冲区来读取数据,而mmap()通过把设备文件映射到内存中,绕过了内核缓冲区,最快的磁盘访问往往还是慢于最慢的内存访问,所以mmap()方式加速了I/O访问。另外,mmap()系统调用使得进程之间通过映射同一文件实现共享内存,各进程可以像访问普通内存一样对文件进行访问,访问时只需要使用指针而不用调用文件操作函数。因为mmap()的以上优点,所以在程序实现中采用
33
上海交通大学硕士学位论文
了内存映射方式,即mmap()方式。
利用mmap()方式对视频进行采集与裁剪的操作如下。
①先使用ioct1(vd->fd,VIDIOCGMBUF,&vd->mbuf)函数获得摄像头存储缓冲区的帧信息,之后修改video_mmap中的设置,例如重新设置图像帧的垂直及水平分辨率、彩色显示格式以及当前帧的状态。可利用如下语句 vd->mmap.height=120; vd->mmap.width=160;
vd->mmap.format=VIDEO_PALETTE_RGB24;
vd->framestat[0] = vd->framestat[1] = 0; vd->frame = 0;
②接着把摄像头对应的设备文件映射到内存区,命令为vd->map=(unsigned char*)mmap(0,vd->mbuf.size,PROT_READ|PROT_WRITE,MAP_SHARED,vd->fd,0)。这样设备文件的内容就映射到内存区,该映射内容区可读可写并且不同进程间可共享。该函数成功时返回映像内存区的指针,失败时返回-1。下面对mmap函数中的每个参数进行说明。第一个参数表示共享内存享的起始地址,在此处设为0表示由系统分配。第二个参数表示映射到调用进程地址空间的字节数,此处为vd->mbuf.size。第三个参数指定共享内存的访问权限,它有以下几个值 PROT_READ(可读),PROT_WRITE(可写), PROT_EXEC(可执行),此处设为可读和可写。第四个参数指定共享内存的属性,有MAP_SHARED、 MAP_PRIVATE、MAP_ FIXED三种属性,一般情况下从MAP_SHARED MAP_PRIVATE中选一个,MAP_ FIXED使用。
③视频截取。把视频映射到内存后就可进行视频的截取。命令为ioctl(vd->fd, VIDIOCMCAPTURE, &(vd->mmap)) ;若调用成功,开始一帧的截取,该操作是非阻塞的,是否截取完毕留给VIDIOCSYNC来判断。
④调用VIDIOCSYNC等待一帧截取结束。 if(ioctl(vd->fd, VIDIOCSYNC, &frame) < 0) {
perror(\"VIDIOCSYNC ERROR!!\"); return -1; }
34
上海交通大学硕士学位论文
函数调用成功,表明一帧图像截取完成,可以开始进行下一次视频截取。其中frame是当前截取的帧的序号。
⑤由于采集是采用双缓冲的方式,这样在处理一帧时可以采集另一帧。frame表示当前采集的是哪一帧图像,framestat[2]表示帧的状态。如没开始采集和等待采集结束。帧在内存中的地址由vd->map + vd->mbuf.offsets[vd->frame]确定。采集结束后调用munmap命令取消映射:munmap(vd->map, vd->mbuf.size)。
上面比较详细的介绍了视频设备编程的流程以及方法,下面将给出一个基于摄像头的视频采集的具体实现。
3.3 摄像头采集模块的具体实现
针对日常生活中广泛用到的ZC301摄像头,下面给出其视频采集程序的具体实现。它可以用来采集一张完整的jpeg图片。它采用了与上面介绍的相似的数据结构和函数,不过还是重新再叙述一下,它们的具体代码将在附录一中给出。 static int GetVideoPict (struct vdIn *vd); %获取图片属性信息。 static int SetVideoPict (struct vdIn *vd); %设置图片属性。 static int isSpcaChip (const char *BridgeName); %测试芯片类型
static int GetStreamId (const char *BridgeName); %测试输出数据的格式 static int GetDepth (int format); %获取颜色深度。 void exit_fatal(char *messages); %错误显示。
int init_videoIn(struct vdIn *vd,char *device,int width,int height,int format,int grabmethod); %初始化设备。
int convertframe(unsigned char *dst,unsigned char *src, int width,int height, int formatIn, int size); %把共享缓冲区中的数据放入一个变量中,通知系统已获帧。 int v4lGrab (struct vdIn *vd,char *filename ); %从摄像头采集图片。 int close_v4l (struct vdIn *vd); %关闭摄像头。
int get_jpegsize (unsigned char *buf, int insize); %获取jpeg图片大小。
35
上海交通大学硕士学位论文
3.4 基于MPEG 4压缩算法的视频压缩
由视频采集模块获取的视频图像由于数据量较大,而网络带宽有限,所以为了使视频图像在以太网上传输,同时提高传输效率与视频图像质量,需要将原始的视频图像进行压缩编码。目前制订视频编码标准的国际组织主要有ITU-T与ISO/IEC。ITU-T的建议标准H.系列(如H.261,H.263等)主要用于实时视频通信,如视频电视会议、可视电话等。而ISO/IEC的建议标准MPEG系列(如MPEG-1 ,MPEG -2,MPEG-4等)主要用于数字电视广播、DVD等。国际电信联盟视频编码专家组(ITU-T VCEG)和国际标准化组织运动图像专家组(ISO MPEG)于2001年合作形成了联合视频组JVT(Joint Video Team),共同开发新一代的低比特率视频标准H.2(很多非正式场合也被称为H.26L)。H.2是ITU的正式名称, 其MPEG正式名称是MPEG-4 Part 10或ISO/IEC 14496-10 AVC。
3.4.1 常见压缩编码算法简介
1、JPEG/M-JPEG[13]
①JPEG是一种静止图像的压缩标准,它是一种标准的帧内压缩编码方式。当硬件处理速度足够快时,JPEG能用于实时动图像的视频压缩。在画面变动较小的情况下能提供相当不错的图像质量,传输速度快,使用相当安全,缺点是数据量较大。
②M-JPEG源于JPEG压缩技术,是一种简单的帧内JPEG压缩,压缩图像质量较好,在画面变动情况下无马赛克,但是由于这种压缩本身技术,无法做到大比例压缩,录像时每小时约1-2GB空间,网络传输时需要2M带宽,所以无论录像或网络发送传输,都将耗费大量的硬盘容量和带宽,不适合长时间连续录像的需求,不大实用于视频图像的网络传输。
2、H.261/H.263
①H.261标准通常称为P*,H.261对全色彩、实时传输动图像可以达到较高的压缩比,算法由帧内压缩加前后帧间压缩编码组合而成,以提供视频压缩和解压缩的快速处理。由于在帧间压缩算法中只预测到后1帧,所以在延续时间上比较有优势,但图像质量难以做到很高的清晰度,无法实现大压缩比和变速率录
36
上海交通大学硕士学位论文
像等。
②H.263的基本编码方法与H.261是相同的,均为混合编码方法,但H.263为适应极低码率的传输,在编码的各个环节上作了改进,如以省码字来提高编码图像的质量,此外,H.263还吸取了MPEG的双向运动预测等措施,进一步提高帧间编码的预测精度,一般说,在低码率时,采用H.263只要一半的速率可获得和H.261相当的图像质量。
3、MPEG
MPEG是压缩运动图像及其伴音的视音频编码标准,它采用了帧间压缩,仅存储连续帧之间有差别的地方 ,从而达到较大的压缩比。MPEG现有MPEG-1、MPEG-2和MPEG-4三个版本,以适应于不同带宽和图像质量的要求。
①MPEG-1的视频压缩算法依赖于两个基本技术,一是基于16*16(像素*行)块的运动补偿,二是基于变换域的压缩技术来减少空域冗余度,压缩比相比M-JPEG要高,对运动不激烈的视频信号可获得较好的图像质量,但当运动激烈时,图像会产生马赛克现象。 MPEG-1以1.5Mbps的数据率传输视音频信号,MPEG-1在视频图像质量方面相当于VHS录像机的图像质量,视频录像的清晰度的彩色模式≥240TVL,两路立体声伴音的质量接近CD的声音质量。 MPEG-1是前后帧多帧预测的压缩算法,具有很大的压缩灵活性,能变速率压缩视频,可视不同的录像环境,设置不同的压缩质量,从每小时80MB至400MB不等,但数据量和带宽还是比较大。
②MPEG-2它是获得更高分辨率(720*572)提供广播级的视音频编码标准。MPEG-2作为MPEG-1的兼容扩展,它支持隔行扫描的视频格式和许多高级性能包括支持多层次的可调视频编码,适合多种质量如多种速率和多种分辨率的场合。它适用于运动变化较大,要求图像质量很高的实时图像。对每秒30帧、720*572分辨率的视频信号进行压缩,数据率可达3-10Mbps。由于数据量太大,不适合长时间连续录像的需求。
③MPEG-4是为移动通信设备在Internet网实时传输视音频信号而制定的低速率、高压缩比的视音频编码标准。 MPEG-4标准是面向对象的压缩方式,不是像MPEG-1和MPEG-2那样简单地将图像分为一些像块,而是根据图像的内容,其中的对象(物体、人物、背景)分离出来,分别进行帧内、帧间编码,并允许
37
上海交通大学硕士学位论文
在不同的对象之间灵活分配码率,对重要的对象分配较多的字节,对次要的对象分配较少的字节,从而大大提高了压缩比,在较低的码率下获得较好的效果, MPEG-4支持MPEG-1、MPEG-2中大多数功能,提供不同的视频标准源格式、码率、帧频下矩形图形图像的有效编码。
总之,MPEG-4有三个方面的优势: 具有很好的兼容性;
MPEG-4比其他算法提供更好的压缩比,最高达200:1;
MPEG-4在提供高压缩比的同时,对数据的损失很小。所以,MPEG-4
的应用能大幅度的降低录像存储容量,获得较高的录像清晰度,特别适用于长时间实时录像的需求,同时具备在低带宽上优良的网络传输能力。 4、H.2
H.2是ITU-T的VCEG(视频编码专家组)和ISO/IEC的MPEG(活动图像编码专家组)的联合视频组(JVT:joint video team)开发的一个新的数字视频编码标准,它既是ITU-T的H.2,又是ISO/IEC的MPEG-4的第10 部分。1998年1月份开始草案征集,1999年9月,完成第一个草案,2001年5月制定了其测试模式TML-8,2002年6月的 JVT第5次会议通过了H.2的FCD板。
H.2和以前的标准一样,也是DPCM加变换编码的混合编码模式。但它采用“回归基本”的简洁设计,不用众多的选项,获得比H.263++好得多的压缩性能;加强了对各种信道的适应能力,采用“网络友好”的结构和语法,有利于对误码和丢包的处理;应用目标范围较宽,以满足不同速率、不同解析度以及不同传输(存储)场合的需求;它的基本系统是开放的,使用无需版权。
在技术上,H.2标准中有多个闪光之处,如统一的VLC符号编码,高精度、多模式的位移估计,基于4×4块的整数变换、分层的编码语法等[14]。它将编码过程分为帧内编码和帧间编码两个部分。帧内采用改进的DCT 变换并量化,帧间采用1/2象素运动矢量预测补偿技术,使运动补偿更加精确,量化后采用改进的变长编码表(VLC)的量化数据进行熵编码,得到最终的编码系数。这些措施使得H.2算法具有很的高编码效率,在相同的重建图像质量下,能够比H.263节约50%左右的码率。H.2的码流结构网络适应性强,增加了差错恢复能力,能
38
上海交通大学硕士学位论文
够很好地适应IP和无线网络的应用。
如果是从单个画面清晰度比较,MPEG4有优势;从动作连贯性上的清晰度H.2有优势!但是由于H.2采用众多的新技术, 使得它的复杂度比MPEG-4视频部分高,即H. 2更高的压缩比是以运算复杂度的大幅度增加为代价的,对硬件有更高的要求。而本课题没有专门的视频边解码硬件,所以采用MPEG-4算法进行视频图像的压缩与解压缩。
3.4.2 MPEG-4视频编码技术
MPEG-4视频编码标准支持MPEG-1、MPEC-2中的大多数功能,它包含了H.263的核心设计,并增加了优先特性和各种各样创造性的新特性。它提供不同的视频标准源格式、码率、帧频下矩形图像的有效编码,同时也支持基于内容的图像编码。采纳了基于对象(Object-Based)的编码、基于模型(Model-based)的编码等第二代编码技术是MPEG-4标准的主要特征[14]。
MPEG-4视频编码中主要包含以下关键技术: ● 离散余弦编码(DCT)
DCT主要完成图像数据由空域转向频域,各系数相互,这意味着各系数可分开处理,同时,图像的高频系数大部分接近于零。人的视觉系统对低频比对高频敏感的多,因此可以用更大的量化步长来量化高频系数,使大部分高频系数为零,从得到较高的压缩比,而人眼很难察觉。
● 量化
量化是针对DCT变换系数进行的,量化过程就是以某个量化步长去除DCT系数。量化步长的大小称为量化精度,量化步长越小,量化精度就越细,包含的信息越多,但所需的传输频带越高。不同的DCT变换系数对人类视觉感应的重要性是不同的,因此编码器根据视觉感应准则,对一个8×8的DCT变换块中的个DCT变换系数采用不同的量化精度,以保证尽可能多地包含特定的DCT空间频率信息,又使量化精度不超过需要。
● Intra块DC系数和AC系数的帧内预测
由于Intra编码方式的各块之间的DC和AC有较强的连续性,所以我们量化后可以进一步进行预测。DC和AC的预测方向有两个:水平方向和垂直方向。其预测方向主要取决于相邻块DC系数的相关性,AC的预测只对块的第一行或
39
上海交通大学硕士学位论文
第一列进行预测。是对第一行进行预测还是对第一列进行预测主要取决于预测方向,其预测方向和DC预测方向一致。
● 之型扫描与游程编码
由于经量化后,大多数非零DCT系数集中于8*8二维矩阵的左上角,即低频分量区,之型扫描后,这些非零DCT系数就集中于一维排列数组的前部,后面跟着长串的量化为零的DCT系数,这些就为游程编码创造了条件。所谓游程编码就是对扫描后个系数进行编码:用非0系数的大小(Level)、其前面连续0的个数(Run)及终止标志(Last:\"0\"便是其后还有不为0的系数;\"1\"表示该系数为最后不为0的数,余下的系数全为0)加起来构成一个三维矢量(Last,Run,Level)。然后就可以对这些矢量进行Huffman编码。
● 变字长编码(VLC)
游程编码形成的三维矢量是一种有效表示方式,实际传输前,还须对其进行比特流编码,产生用于传输的数字比特流。其中用得最多的就是Huffman编码,Huffman编码中,根据所有编码信号的概率生成一个码表,码表中对大概率信号分配较少的比特表示,对小概率信号分配较多的比特表示,使得整个码流的平均长度趋于最短。
● 运动估计
运动估计用于帧间编码,即P帧和B帧编码。通过在参考帧图像中搜索到与当前块最接近的块。从而使传输的误差块可以用更少的比特表示,从而达到压缩目的。运动估计的准确程度对帧间编码的压缩效果非常重要。运动估计以宏块或块为单位进行,计算被压缩图像与参考图像的对应位置上的宏块或块间的位置偏移。这种位置偏移是叫运动矢量(MV),一个运动矢量代表水平和垂直两个方向上的位移。现在MPEG-4所用的运动估计算法主要有:MVFAST(Motion Vector Field Adaptive Search Technique),改进的PMVFAST(Predictive MVFAST)和EPZS (Enhanced Predictive Zonal Search) 算法。
● 运动补偿
运动补偿实际上是一种预测编码的思想,因此,运动补偿又可称为运动预测。运动预测的过程为:根据前面在运动估计中得到的匹配MV,在当前宏块/块和参考帧中的匹配宏块/块之间进行预测(即计算差值),编码器只需对预测
40
上海交通大学硕士学位论文
误差和使用的MV进行码流编码。帧内图像I帧不参照任何过去的或者将来的其他图像帧,压缩编码采用类似JPEG压缩算法。每幅图像分成8×8的图像块,对每个图像块进行离散余弦变换DCT。DCT变换后对每个系数进行量化,然后对量化后的系数进行DC、AC预测,对预测后的差值按照Zig-zag进行扫描,然后再进行游程编码,最后用霍夫曼(Huffman)编码或者用算术编码得到最后的码流。 其中DC预测后的DC差值可直接查表得到对应的码字。预测图像P帧的编码是以图像宏块为基本编码单元,一个宏块定义为16×16像素的图像块。预测图像P使用两种类型的参数来表示:一种参数是当前要编码的图像宏块与参考图像的宏块之间的差值,另一种参数是宏块的运动矢量。通过运动估计求得最佳运动矢量,然后通过运动补偿得到的宏块与编码宏块相应像素值之差的到差值模块。然后仿照I帧编码算法对差值进行编码,计算出的运动矢量也要进行Huffman编码。双向预测图像B帧的编码方法与预测图像P的算法类似。不过,它除 了可以参考过去的图像之外,它还参考将来的图像,参考过去帧和将来帧的均值帧。除了这三个参考帧之外,它还有一种参考模式,即直接模式。直接模式就是以将来的P帧的运动矢量的一半作为自己的运动矢量,以此矢量进行运动补偿,这样的方法连MV都不用编码传输,加上其量化步长一般比I帧和P帧大,所以可以达到高的压缩率。
MPEG-4具有高速压缩、基于内容交互和基于内容分级扩展等特点,并且具有基于内容方式表示的视频数据。它把任一个视频序列看成一个或多个视频对象(VO)的集合。VO是场景中的某个物体,由时间上连续的许多帧构成,它是一个承上启下的概念,一个或多个VO组成一个视频场景(VS),每个VO可能有一个或多个VOL层次,VOL引入了主要用来扩展VO的时域或空域分辨率,它把VO的一些属性信息进行编码。VOP是某一时刻某一帧画面的VO,VOP编码就是对某一时刻该帧画面VO的形状、运动和纹理等三类信息进行编码。
基于内容的视频编码过程由以下三步完成[15]: 1.VO的形成: 先从原始视频流中分割出VO。
2.编码: 对各VO分别编码,即对不同VO的运动信息、形状信息和纹理信息这三类信息分别编码,分配不同的码字。
3. 复合:将各个VO的码流复合成一个符合MPEG-4标准的位流。
41
上海交通大学硕士学位论文
在编码和复合阶段可以加入用户的交互控制或由智能化算法进行控制。MPEG-4视频编码器算法如图3-3所示。
图3-3 MPEG-4视频编码器的算法方框图[15]
Figure 3-3 algorithm diagram of MPEG-4 video encoder
3.4.3 MPEG 4视频压缩的具体实现
在几种开放源代码的MPEG-4编码软件中,选择 xvidcore作为本系统中视频图像压缩模块中的核心算法。xvid是一个高效的而且具有可移植性的编码软件,目前版本为xvidcore- 1.0.2。xvid支持Simple Profile和Advanced Profile,支持I/PFrames、B-Frames、Interlacing和GMC,以钻石和方块模式来进行PMVFast和EPZS运行估计,是目前比较流行的MPEG-4编码软件。
对xvidcore-1.0.2进行交叉编译比较简单,有以下主要步骤[16]: ① 解压缩xvidcore源代码:tar-zxvf xvidcore-1.0.2.tar; ② 设置环境变量:export xvidcore=\"the path of xvidcore\"; ③ cd $xvidcore/build/generic;
④ 生成makefile:./configure-host=localhost build=arm-linux-gcc; ⑤ 编译源代码:make;make install;
⑥ 将交叉编译生成的库文件libxvidcore.so.*拷贝到交叉编译器工作目录的lib子目录中,该库文件为系统的其它模块提供了编程接口.
具体源代码可以从这里下载:http://www.xkxz.com/soft/3018.htm。
42
上海交通大学硕士学位论文
第四章 基于Internet的视频监控平台设计
摄像头采集过来的图像经MPEG-4压缩后变成MPEG-4流,为了达到远程监控的目的,必须把MPEG-4流利用Internet进行传输。如何在Internet上传输MPEG-4视频流成为一个值得关注的问题。MPEG小组提出了基于IP的MPEG-4视频传输,也就是直接将MPEG-4数据流打成IP包进行传输。虽然IP协议简洁高效,但是它是无连接的,没有服务质量的保证,而MPEG-4数据流在很多场合下需要较好的实时性和无差错性,这就给MPEG-4的多媒体传输框架带来了很大的挑战。在这种背景下,RTP协议应运而生了[17]。
4.1 RTP协议简介
RTP是由IETF组织制订的针对多媒体应用(如视频、音频等)的新型实时传输协议,它提供的服务包括负载类型标识、序列编号、时间戳和传输控制等。RTP本身不具有传输数据的能力,它必须和底层的网络协议结合起来才能完成数据传输服务。典型的RTP应用是基于UDP之上的,它们共同完成传输层功能。RTP 本身并不能为按序传输数据包提供可靠的保证,也不提供流量控制和拥塞控制, 这些都由实时传输控制协议RTCP 来负责完成[18]。通常RTCP 会采用与RTP 相同的分发机制, 向会话中的所有成员周期性地发送控制信息,应用程序通过接收这些数据, 从中获取相关资料, 从而能够对服务质量进行控制或者对网络状况进行诊断。当应用程序开始一个RTP 会话时将使用两个端口: 一个给RTP , 一个给RTCP。在RTP 会话期间, 各参与者周期性地传送RTCP 包。RTCP 包中含有已发送的数据包的数量、丢失的数据包的数量等统计资料, 因此, 服务器可以利用这些信息动态地改变传输速率, 甚至改变有效载荷类型。RTP 和RTCP 配合使用, 它们能以有效的反馈和最小的开销使传输效率最佳化, 因而特别适合传送网上的实时数据。
RTP协议具有简单、支持多点传输、数据流和控制流的分离、协议可扩展性等特点。使用RTP来传输MPEG-4数据流有以下几个优点: (1)能使MPEG-4数据流与其它的RTP负载保持同步; (2)使用RTCP协议可监控MPEG-4的传输性能;
43
上海交通大学硕士学位论文
(3)可利用RTP合成器将MPEG-4数据流和其它来自多终端系统的实时数据
流合成一个整体数据流进行传输; (4)可使用RTP的解释器转换数据流的类型。
因此,可以认为使用MPEG-4 over RTP 是替代MPEG-4 over IP的一个较好的选择[19]。
4.1.1 RTP数据协议
RTP数据协议负责对流媒体数据进行封包并实现媒体流的实时传输,每一个RTP数据报都由头部(Header)和负载(Payload)两个部分组成,其中头部前12个字节的含义是固定的,而负载则可以是音频或视频数据。RTP数据报的
=
头部格式如图所示[20]:
图4-1 RTP头部格式
Figure 4-1 header formation of RTP
V2 P X CC M PT 序列号
时间戳 SSRC标志 CSRC标志
下面对其中几个比较重要的域进行介绍[21]。
CSRC计数(CC) 表示CSRC标志的数目。CSRC标志紧跟在RTP固定
头部之后,用来表示RTP数据报额来源,RTP协议允许在同一个会话中存在多个数据源,它们可以通过RTP混和器合并为一个数据源。例如,可以产生一个CSRC列表表示一个电话会议,该会议通过一个RTP混和器将所有讲话者的语音数据组合为一个RTP数据源。
负载类型(PT) 长度为1字节,表明RTP数据包内的数据格式,包括所
采用的编码算法、采样频率、承载通道等。例如,类型2表明该RTP数据包中承载的是用ITU G.721算法编码的语音数据,采样频率为8000Hz,并且采用单声道。
44
上海交通大学硕士学位论文
序列号 长度为2字节,RTP传输会话中对RTP包依次编号,其中第一个
包的编号可以为0或者一个随机数,每发送一个包其顺序号加1,接收端可以根据它来检查数据包是否已丢失并按顺序号来处理数据包。在质量控制中可根据时间戳和顺序号来计算丢包率、延迟和抖动等参数。
时间戳 长度为4字节,记录了负载中第一个字节的采样时间,接收方能
够根据时间戳确定数据的到达是否受到了延迟抖动的影响,并为播放提供同步功能。
从RTP数据报的格式可以看出,它包含了传输媒体的类型、格式、序列号、时间戳以及是否有附加数据等信息,这些都为实时的流媒体传输提供了相应的基础。RTP协议的目的是提供实时数据的端到端传输服务,因此在RTP中没有连接的概念,它可以建立在底层的面向连接或者面向非连接的传输稀有之上;RTP也不依赖特别的网络地址格式,而仅仅只需要底层传输协议支持组帧和分段就可以了;另外RTP本身还不提供任何可靠性机制,这些都要由传输协议或者应用程序自己来保证。在典型的应用场合下,RTP一般是在传输协议之上作为应用程序的一部分来实现的,如下图所示
应用程序 RTP/RTCP
UDP
IPv4/IPv6 局域网/广域网
图4-2 RTP与各种网络协议的关系
Figure 4-2 relation between RTP and other internet protocol
TCP
4.1.2 RTCP控制协议
RTCP控制协议需要与RTP数据协议一起配合使用,当应用程序启动一个RTP会话时将同时占用两个端口,分别供RTP和RTCP使用。RTP本身并不能为按序传输数据包提供可靠的保证,也不提供流量控制和拥塞控制,这些都由RTCP来负责完成。通常RTCP会采用与RTP相同的分发机制,向会话中的所有成员周期性地发送控制信息,应用程序通过接收这些数据,从中获取会话参
45
上海交通大学硕士学位论文
与者地相关资料,以及网络状况、分组丢失概率等反馈信息,从而能够对服务质量进行控制或者对网络状况进行诊断。
RTCP协议的功能是通过不同的RTCP数据报来实现的,主要有如下几种类型[22]:
SR 发送端报告,所谓发送端是指发出RTP数据报的应用程序或者终
端,发送端同时也可以是接收端。
RR 接收端报告,所谓接收端是指仅接收但不发送RTP数据报的应用
程序或者终端。
SDES 源描述,主要功能是作为会话成员有关标志信息的载体,如用
户名、邮件地址、电话号码等,此外还具有向会话成员传达会话控制信息的功能。
BYE 表示结束,主要功能是指示某一个或者几个源不再有效,及通知
会话中的其他成员自己将退出会话。
APP 应用特定函数,由应用程序自己定义,解决了RTCP的扩展性问
题,并且为协议的实现者提供了很大的灵活性。
RTCP数据报携带有服务质量监控的必要信息,能够对服务质量进行动态的调整,并能够对网络拥塞进行有效的控制。由于RTCP数据报采用的是多播方式,因此会话中的所有成员都可以通过RTCP数据报返回的控制信息来了解参与者的当前情况。
4.2 MPEG-4数据流的RTP封装与传输
第一节简单分析了RTP/RTCP协议,下面将介绍利用该协议进行MPEG-4数据流的封装与传输。
4.2.1 MPEG-4数据流的封装
由于视频数据一般都比较大,所以不考虑几个访问单元串联封装的情况, 采用以.视频对象平面(VOP)为基本封装单元[23],使用SDP(Session Describe Protocol)来指定视频流的属性(例如媒体类型、封装格式、编码结构等),直接将视频数据分片并映射到RTP包中的封装方案。一般将一个完整的VOP映射到一
46
上海交通大学硕士学位论文
个RTP包中,这样可以保证RTP时间戳可以唯一表示VOP分帧时间;但也允许将多个完整的较小的(或者空的)VOP映射到同一个RTP包中以减小总负载,这些VOP应按照解码顺序连续,并且第一个VOP后的VOP时间戳在解码时通过计算得到, 此时RTP包头标志位应置1且RTP负载开始符合起始码;有些VOP映射到RTP包中时导致访问单元超过MTU,引起下层数据的分包,不利于RTP处理,此时也允许将过大的VOP分割并分别映射到不同的RTP包中,一般采用同步字作为分割点,这样分割后的RTP包载荷是完整的一个或多个由同步字划分的单元,可以保证在有RTP包丢失的情况下,其余的用同步字划分的数据还可以正常解码,若是文件中没有同步字,我们可以选择宏块为分割点,这样即使有RTP包丢失,也不影响其他RTP包的正常解码[24]。
RTP包封装MPEG-4数据的算法描述如下: while(MPEG-4数据流结束前) {
if(发现下一个VOP起始码)
{
if(当前分段长度≤去除头部字段长度的路径MTU值)
{
把此段数据打入RTP包 }
else {
把尽可能多的宏块打入RTP包 }
} else {
对剩余数据打包 }
}
47
上海交通大学硕士学位论文
4.2.2 MPEG-4数据流的传输
MPEG4数据流[25]分别被封装上RTP报头、UDP报头和IP报头,然后IP数据包通过Internet向接收端发送。当发送端收到已被正常编码压缩的MPEG-4码流后,按照RTP数据传输协议的报文格式装入RTP报文的数据负载段,并配置RTP报文头部的时间戳、同步信息、序列号等参数,此时数据报文已被流化了[26];同时发送端周期性地接收RTCP包,将Qos反馈控制信息发送到视频服务器,服务器利用这些信息动态地改变自身参数设置。接收端收到IP包后先分析RTP包头,判断版本、长度、负载类型等信息的有效性,更新缓冲区的RTP信息,如收到的字节数、视频帧数、包数、序列号数等信息;按照RTP时间戳和包序列号等进行信源同步,整理RTP包顺序,重构视频帧;最后根据负载类型标识进行解码,将数据放入缓存供解码器解码输出;同时接收端根据RTP包中的信息周期性回送包含Qos反馈控制信息的RTCP包到数据发送端以检测发送端和接收端数据的一致性。传输模型如下图所示:
MPEG-4视频流 解码器 视频服务器质量反馈控制质量反馈控制缓冲存储器 RTP协议 RTCP协议 RTCP协议 RTP协议 UDP协议 UDP协议 IP协议 Internet IP协议
图4-3 MPEG-4数据流的RTP传输模型
Figure 4-3 RTP transport model of MPEG-4 data stream
[27]
4.3 RTP数据传输的具体实现
要在Linux平台上进行实时RTP传送编程,可以考虑使用一些开放源代码
48
上海交通大学硕士学位论文
的RTP库[28],如LIBRTP、JRTPLIB等。JRTPLIB是一个面向对象的RTP库,它完全遵循RFC 18设计,在很多场合下是一个非常不错的选择。JRTPLIB是一个用C++语言实现的RTP库,这个库使用SOCEKT机制实现网络通讯,因此可以运行在 Windows、Linux、FreeBSD、Solaris、Unix和VxWorks等多种操作系统上。
4.3.1 JRTPLIB 库的使用方法
1)在使用JRTPLIB进行实时流媒体数据传输之前,首先应该生成 RTPSession类的一个对象来表示此次RTP会话,然后调用Create()方法来对其进行初始化操作。RTPSession类的Create()方法只有一个参数,用来指明此次RTP 会话所采用的端口号[29]。 RTPSession sess; sess.Create(6000);
2)设置恰当的时戳单元,是RTP 会话初始化过程所要进行的另外一项重要工作,这是通过调用RTPSession类的SetTimestampUnit()方法来实现的,该方法同样也只有一个参数,表示的是以秒为单元的时戳单元。sess.SetTimestampUnit(1.0/50.0);
3)当RTP会话成功建立起来之后,接下去就可以开始进行流媒体数据的实时传输了。首先需要设置好数据发送的目标地址,RTP协议允许同一会话存在多个目标地址,这可以通过调用RTPSession类的AddDestination()、DeleteDestination()和ClearDestinations()方法来完成。例如,下面的语句表示的是让RTP会话将数据发送到本地主机的 8000 端口:
unsigned long addr = ntohl(inet_addr(\"127.0.0.1\")); sess.AddDestination(addr, 8000);
4)目标地址全部指定之后,接着就可以调用RTPSession类的SendPacket() 方法,向所有的目标地址发送流媒体数据。
对于同一个RTP会话来讲,负载类型、标识和时戳增量通常来讲都是相同的,JRTPLIB允许将它们设置为会话的默认参数,这是通过调用
49
上海交通大学硕士学位论文
RTPSession类的SetDefaultPayloadType()、SetDefaultMark()和
SetDefaultTimeStampIncrement()方法来完成的。为RTP会话设置这些默认参数的好处是可以简化数据的发送,例如,如果为RTP会话设置了默认参数:
sess.SetDefaultPayloadType(0); sess.SetDefaultMark(false);
sess.SetDefaultTimeStampIncrement(10);
之后在进行数据发送时只需指明要发送的数据及其长度就可以了: sess.SendPacket(buffer, 5);
5)对于流媒体数据的接收端,首先需要调用RTPSession类的PollData()方法来接收发送过来的RTP或者RTCP数据报。由于同一个RTP会话中允许有多个参与者(源),你既可以通过调用RTPSession类的GotoFirstSource() 和GotoNextSource()方法来遍历所有的源,也可以通过
调
用
RTPSession
类
的
GotoFirstSourceWithData()
和
GotoNextSourceWithData()方法来遍历那些携带有数据的源。在从RTP会话中检测出有效的数据源之后,接下去就可以调用 RTPSession类的GetNextPacket()方法从中抽取RTP数据报,当接收到的RTP数据报处理完之后,一定要记得及时释放。
JRTPLIB为RTP数据报定义了三种接收模式,其中每种接收模式都具体规定了哪些到达的RTP数据报将会被接受,而哪些到达的RTP数据报将会被拒绝。通过调用RTPSession类的SetReceiveMode()方法可以设置下列这些接收模式:
RECEIVEMODE_ALL 缺省的接收模式,所有到达的 RTP 数
据报都将被接受;
RECEIVEMODE_IGNORESOME 除了某些特定的发送者之
外,所有到达的RTP数据报都将被接受,而被拒绝的发送者列表可以通过调用AddToIgnoreList()、DeleteFromIgnoreList()和ClearIgnoreList()方法来进行设置;
RECEIVEMODE_ACCEPTSOME 除了某些特定的发送者之
外,所有到达的RTP数据报都将被拒绝,而被接受的发送者列表
50
上海交通大学硕士学位论文
可以通过调用AddToAcceptList()、DeleteFromAcceptList()和ClearAcceptList()方法来进行设置。下面是采用第三种接收模式的程序示例[30]。
if (sess.GotoFirstSourceWithData()) { do {
sess.AddToAcceptList(remoteIP, allports,portbase);
sess.SetReceiveMode(RECEIVEMODE_ACCEPTSOME); RTPPacket *pack;
pack = sess.GetNextPacket(); // 处理接收到的数据 delete pack;
} while (sess.GotoNextSourceWithData()); }
4.3.2 程序流程图
获得接收端的IP地址和端口号 获得用户指定的端口号 创建RTP会话 创建RTP会话 设置接收模式 指定RTP数据接收端 接受RTP数据 设置RTP会话默认参数 检索RTP数据源 发送流媒体数据 获取RTP数据报 图4-4 发送数据流程 Figure 4-4 sequence of sending data 删除RTP数据报 图4-5接收数据流程 Figure 4-5 sequence of receiving data 51
上海交通大学硕士学位论文
4.3.3 环境搭建及编译方法
(1)Toolchain的安装
首先找到xscale-arm-toolchain.tgz文件,假设该文件包放在/tmp/下 #cd /
#tar -zxvf /tmp/xscale-arm-toolchain.tgz 再设置环境变量
#export PATH=/usr/local/arm-linux/bin:$PATH 最后检查一下交叉编译工具是否安装成功 #arm-linux-g++ --version
看是否显示arm-linux-g++的版本,如有则安装成功。 (2)JRTPLIB 库的交叉编译及安装
首先从 JRTPLIB 的网站 http://lumumba.luc.ac.be/jori/jrtplib/jrtplib.html 下载最新的源码包,此处使用的是jrtplib-2.8.tar,假设下载后的源码包放在/tmp下,执行下面的命令对其解压缩:
#cd /tmp
#tar -zxvf jrtplib-2.8.tar
然后要对jrtplib进行配置和编译 #cd jrtplib-2.8
#./configure CC=arm-linux-g++ cross-compile=yes 修改Makefile文件
将链接命令ld 和ar改为arm-linux-ld和 arm-linux-ar #make
最后再执行如下命令就可以完成 JRTPLIB 的安装: #make install (3)程序编译 a、配置编译环境
可以用export来配置,也可以用编写Makefile的方法。这里采用
Makefile。
编写Makefile&:
52
上海交通大学硕士学位论文
INCL = -I/usr/local/include
CFLAGS = -pipe -O2 -fno-strength-reduce LFLAGS = /usr/local/lib/libjrtp.a -L/usr/X11R6/lib LIBS = -LX11 -LXext /usr/local/lib/libjrtp.a CC = arm-linux-g++ main:main.o
$(CC) $(LFLAGS) $(INCL) -o main main.o $(LIBS) main.o:main.cpp clean: rm -f main rm -f *.o
.SUFFIXES:.cpp .cpp.o:
$(CC) -c $(CFLAGS) $(INCL) -o $@ $< /* $@表示目标的完整名字 ,$<表示第一个依赖文件的名字 */
b、编译
假设发送和接收程序分别放在/tmp/send和/tmp/receive目录下 #cd /tmp/send #make
#cd /tmp/receive #make
具体程序的代码将在附录二中给出。经过编译安装之后,即可进行视频的发送与接收了。
53
上海交通大学硕士学位论文
第五章 总结与展望
-.研究课题工作总结
本课题的任务是研究与实现基于S3C2410嵌入式Linux的远程家庭视频监控系统,在研究期间主要完成了以下工作:
1. 在开始阶段,查阅了大量有关家庭视频监控系统和基于嵌入式Linux应用的专业文献、书籍、期刊、技术文档等参考资料。经过分析,确定了采用韩国Samsung公司的32位高性能微处理器S3C2410作为硬件系统的CPU,该CPU基于ARM920T内核,具有体积小、高性能、低成本和低功耗等特点,系统集成了多种逻辑单元,主频最高可达203MHz,是目前使用较广泛的微处理器之一。由于系统复杂,任务较多,所以在系统中移植了操作系统,,基于Linux系统的开源性,在此选择嵌入式Linux作为系统的软件平台核心,充分利用嵌入式Linux功能强大、开发资源丰富、免费等重要优势;同时考虑到成本与方便,系统采用的网络环境为有线Internet。 2. 移植并实现了USB摄像头在Linux系统下的驱动程序。
3. 利用Video4Linux提供的接口函数,实现了利用摄像头采集图像的过程。 4. 基于MPEG-4压缩算法,采用开源的MPEG压缩软件进行视频压缩。 5. 利用RTP/UDP/IP协议实现了视频数据的发送与接收。 二.文章的创新点
采用了基于模块的设计方法,如视频采集模块,视频压缩模块、视频传输模块等,各个模块的性增强了系统的健壮性,同时也增强了系统的灵活性,当需要更换其中一个模块时其他模块并不需要做很大的改动,有利于系统的更新换代。
三.系统的不足之处与建议
本系统在设计和实现的过程中本着精简和易于移植的原则,硬件资源具有较多, 同时由于时间有限,系统功能相对比较简单,存在着以下一些不足之处:
系统没有考虑网络因素,当网络状况不是很好时,视频质量不是很好。
需要加入流量控制与带宽控制的算法和代码,有利于为用户提供较好的
54
上海交通大学硕士学位论文
视频质量。
基于S3C2410的硬件平台能够满足系统的基本要求,但是随着系统功能
和算法的复杂度的提高,系统硬件也要进行升级。
系统采用的压缩算法是基于MPEG-4的,但是现在H.2的研究正是目前
的热点,但是它也更复杂,需要专门的硬件进行实现,像TI公司的TMS320DM2就是一款较好的DSP芯片可以提供较好的处理效果,在以后的系统升级可以考虑。
目前系统监控界面还不是很友好,如何做到在Windows平台下进行监控
是下一步的重点。
通过这次研究,我对Linux操作系统、嵌入式系统的开发有了较深的理解,同时也接收了较多比较新颖的知识,如MPEG-4与H.2压缩编码算法,同时对TCP/IP协议族,特别是RTP/UDP/IP协议有了较深的认识。
55
上海交通大学硕士学位论文
参考文献
[1] 陈学光,陈维荣,崔校玉等著,一种基于多媒体的远程视频监控系统方案,
铁道学报,2001
[2] 彭强,杨天武,陈维荣,远程视频监控系统中的解码技术及显示控制策略,
电力系统自动化,2002
[3] 四维科技编,Visual C++视频/音频开发实用工程案例精选,北京:人民邮电
出版社,2004
[4] 基于嵌入式WEB的视频服务器的设计 http://www.ChinaAvs.com
[5] 孙天泽,袁文菊,张海锋著, 嵌入式设计及驱动开发指南-基于ARM9
处理器,电子工业出版社,2005
[6] Alessandro Rubini,Jonathan Corbet著,魏永明、骆刚、姜君译,LINUX 设
备驱动程序(第二版),中国电力出版社,2004
[7] 赵明,Linux下的硬件驱动——USB设备(上、下) http://www-900.ibm.com/d eveloperWorks/cn/linux/l-usb/index1.shtml
[8] Detlef Fliegl, Programming Guide for Linux USB Device Drivers,
http://usb.cs.tum.edu
[9] Alan Cox
,Video4Linux Programming,
http://kernelbook.sourceforge.net/videobook.pdf
[10] Ling_Shi
著,基于Video4Linux的视频设备编程,
http://202.38..185/seminar/040409/v4l.ppt
[11] Video4Linux Kernel API Reference , http://linux.bytesex.org/v4l2/API.html [12] 基于嵌入式
Linux
系统的
S3C2410
的视频采集系统,
http://www.gd-emb.org/detail/id-191.html [13] H.2
与
MPEG4
区
别
,
http://blog.21ic.com/user1/2981/archives/2006/32537.html
[14] 视频监控中数字视频编码技术浅析,
http://www.video.com.cn/news/afjk/jsqy/200507/1121133809828.html [15] 胡晓峰等著,多媒体技术教程,北京:人民邮电出版社,2005
[16] 张洋,王健著,基于Intel PXA255平台的网络摄像机设计,单片机及嵌入
式系统应用,2005
56
上海交通大学硕士学位论文
[17] RFC18,RTP-A Transport Protocol for Real-time Applications[S] [18] RFC10,RTP-Profile for Audio and Video conferences with Minimal
Control[S]
[19] 陈庆余,朱光喜著,一种MPEG-4 over RTP的实现方法,数字电视,2001 [20] RFC2038,RTP Payload Format for MPEG-4[S]
[21] 许先斌,朱平,安晖著,运用RTP协议实时传输MPEG-4流,计算机工程
与设计,2003
[22] 柏海涛,张建州著,基于MPEG-4实时视频传输系统的设计,现代计算机,
2005
[23] 汪理虎,刘春生著,RTP/RTCP协议下MPEG-4视频流传输系统应用研究,
工业控制计算机,2006
[24] 钟玉琢,王琪,贺玉文著,基于对象的多媒体数据压缩编码国际标准——
MPEG4及其校验模型[M]北京科学出版社,2000,10:433-435 [25] 田毅柯,卢朝阳,高西全著,MPEG-4视频标准及其算法[J],现代电子
技术,2002,1:38-41
[26] 李向阳,卞得森著,流媒体及其应用技术[J],现代电视技术,2002,4:18-27 [27] 梁振军著,计算机网络通信与协议[M],北京:石油工业出版社,1990,
12
[28] 樊振萍,唐继勇著,基于RTP协议和MPEG-4的流媒体系统分析与实现,
西部广播电视,2004
[29] 肖磊,陈卓,郑重等著,流媒体技术与应用完全手册[M],北京:清华大学
出版社,2003
[30] 徐延明,林立志,王罡著,Linux编程指南与实践[M],北京:人民邮电出
版社,2000
57
上海交通大学硕士学位论文
附录一 视频采集程序
1. 所定义的数据结构及头文件SPCAV4L_H #ifndef SPCAV4L_H #define SPCAV4L_H #include #include #define VIDEO_PALETTE_JPEG 21 #define BRIDGE_ZC3XX 0 #define MAX_BRIDGE 2 #define JPEG 0 #define UNOW 1 struct bridge_list { int num; const char *name; }; struct vdIn { int fd; char *videodevice ; struct video_mmap vmmap; struct video_capability videocap; int mmapsize; struct video_mbuf videombuf; struct video_picture videopict; struct video_channel videochan; int cameratype ; char *cameraname; char bridge[9]; 58 上海交通大学硕士学位论文 int palette; // available palette int grabMethod ; unsigned char *pFramebuffer; unsigned char *ptframe; int framesizeIn ; int hdrwidth; int hdrheight; int formatIn; int bppIn; }; int init_videoIn(struct vdIn *vd,char *device,int width,int height,int format,int grabmethod); int v4lGrab (struct vdIn *vd,char *filename ); int close_v4l (struct vdIn *vd); int get_jpegsize (unsigned char *buf, int insize); void exit_fatal(char *messages); #endif /* SPCAV4L_H */ 2. 主程序 #include int main (int argc, char *argv[]) { char videodevice[] = \"/dev/video0\"; char jpegfile[] = \"/tmp/1.jpg\"; int grabmethod = 0; int format = VIDEO_PALETTE_JPEG; int width = 176; int height =144; if(init_videoIn(&videoIn, videodevice, width, height, format,grabmethod)== 0) memset(&videoIn, 0, sizeof (struct vdIn)); { v4lGrab(&videoIn, jpegfile); if(grabmethod==1) printf(\"you use mmap method!\n\"); else if(grabmethod==0) printf(\"you use read method!\n\"); printf(\"you have get a picture in %s\n\ } else 59 上海交通大学硕士学位论文 printf(\"can't open your camera!\n\"); close_v4l (&videoIn); return 0; } 3. 定义各个子函数 #include \"spcav4l.h\" static int init_v4l (struct vdIn *vd); static int isSpcaChip ( const char * BridgeName ); static int GetStreamId ( const char * BridgeName ); static int GetDepth (int format); static struct bridge_list Blist[]={ {BRIDGE_ZC3XX,\"ZC301-2\}; int init_videoIn (struct vdIn *vd, char *device, int width, int height, int format, int grabmethod) { int err = -1; int i; if (vd == NULL || device == NULL) return -1; if (width == 0 || height == 0) return -1; if(grabmethod < 0 || grabmethod > 1) grabmethod = 1; //read by default; vd->videodevice = NULL; vd->cameraname = NULL; vd->videodevice = NULL; vd->videodevice = (char *) realloc (vd->videodevice, 32); vd->cameraname = (char *) realloc (vd->cameraname, 32); snprintf (vd->videodevice, 32, \"%s\ memset (vd->cameraname, 0, sizeof (vd->cameraname)); memset(vd->bridge, 0, sizeof(vd->bridge)); vd->hdrwidth = width; vd->hdrheight = height; vd->formatIn = format; vd->bppIn = GetDepth (vd->formatIn); vd->grabMethod = grabmethod; vd->pFramebuffer = NULL; err = init_v4l (vd); vd->ptframe = NULL; vd->ptframe = (unsigned char *) realloc (vd->ptframe, (size_t) 60 上海交通大学硕士学位论文 vd->framesizeIn ); return err; } int close_v4l (struct vdIn *vd) { int i; if (vd->grabMethod) { munmap (vd->pFramebuffer, vd->mmapsize); } else { free(vd->pFramebuffer); vd->pFramebuffer = NULL; } close (vd->fd); /* dealloc the whole buffers */ if (vd->videodevice) { free (vd->videodevice); vd->videodevice = NULL; } if (vd->cameraname) { free (vd->cameraname); vd->cameraname = NULL; } if (vd->ptframe) { } int convertframe(unsigned char *dst,unsigned char *src, int width,int height, int formatIn, int size) { int jpegsize =0; switch (formatIn){ case VIDEO_PALETTE_JPEG: jpegsize = get_jpegsize(src, size); if (jpegsize < 0) break; free (vd->ptframe); vd->ptframe = NULL; } 61 上海交通大学硕士学位论文 memcpy(dst,src,jpegsize); break; default: break; } return jpegsize; } int v4lGrab(struct vdIn *vd, char *filename) { FILE *fp; static int frame = 0; int len; int size; int erreur = 0; int jpegsize = 0; if (vd->grabMethod) { vd->vmmap.height = vd->hdrheight; vd->vmmap.width = vd->hdrwidth; vd->vmmap.format = vd->formatIn; if ((ioctl (vd->fd, VIDIOCMCAPTURE, &(vd->vmmap))) < 0) { perror (\"cmcapture\"); } if (ioctl (vd->fd, VIDIOCSYNC, &vd->vmmap.frame) < 0) { perror (\"cvsync err\n\"); erreur = -1; } jpegsize= convertframe(vd->ptframe, vd->pFramebuffer + vd->videombuf.offsets[vd->vmmap.frame], vd->hdrwidth,vd->hdrheight,vd->formatIn,vd->framesizeIn); } else { /* read method */ size = vd->framesizeIn; len = read (vd->fd, vd->pFramebuffer, size); if (len < 0 ) { return -1; } 62 上海交通大学硕士学位论文 jpegsize= convertframe(vd->ptframe, vd->pFramebuffer ,vd->hdrwidth,vd->hdrheight,vd->formatIn,vd->framesizeIn); fp = fopen(filename, \"w\"); if(!fp) return -1; fwrite(vd->ptframe, jpegsize, 1, fp); fclose(fp); return 0; } return erreur; } static int GetVideoPict (struct vdIn *vd) { if (ioctl (vd->fd, VIDIOCGPICT, &vd->videopict) < 0) exit_fatal (\"Couldnt get videopict params with VIDIOCGPICT\"); return 0; } static int SetVideoPict (struct vdIn *vd) { if (ioctl (vd->fd, VIDIOCSPICT, &vd->videopict) < 0) exit_fatal (\"Couldnt set videopict params with VIDIOCSPICT\"); return 0; } static int init_v4l (struct vdIn *vd) { int f; int erreur = 0; int err; if ((vd->fd = open (vd->videodevice, O_RDWR)) == -1) exit_fatal (\"ERROR opening V4L interface\"); if (ioctl (vd->fd, VIDIOCGCAP, &(vd->videocap)) == -1) exit_fatal (\"Couldn't get videodevice capability\"); snprintf (vd->cameraname, 32, \"%s\ erreur = GetVideoPict (vd); if (ioctl (vd->fd, VIDIOCGCHAN, &vd->videochan) == -1) { vd->cameratype = UNOW; } else { if (vd->videochan.name){ snprintf (vd->bridge, 9, \"%s\ 63 上海交通大学硕士学位论文 vd->cameratype = GetStreamId (vd->bridge); } else { vd->cameratype = UNOW; } } /* Only jpeg webcam allowed */ if(vd->cameratype != JPEG) { } vd->videopict.palette = vd->formatIn; vd->videopict.depth = GetDepth (vd->formatIn); vd->bppIn = GetDepth (vd->formatIn); vd->framesizeIn = (vd->hdrwidth * vd->hdrheight >> 2 ); // here alloc the output ringbuffer jpeg only erreur = SetVideoPict (vd); erreur = GetVideoPict (vd); if (vd->formatIn != vd->videopict.palette || vd->bppIn != vd->videopict.depth) exit_fatal (\"could't set video palette Abort !\"); if (erreur < 0) exit_fatal (\"could't set video palette Abort !\"); if (vd->grabMethod) { // MMAP VIDEO acquisition memset (&(vd->videombuf), 0, sizeof (vd->videombuf)); if (ioctl (vd->fd, VIDIOCGMBUF, &(vd->videombuf)) < 0) { perror (\" init VIDIOCGMBUF FAILED\n\"); } vd->pFramebuffer =(unsigned char *) mmap (0, vd->videombuf.size, PROT_READ | PROT_WRITE,MAP_SHARED, vd->fd, 0); vd->mmapsize = vd->videombuf.size; vd->vmmap.height = vd->hdrheight; vd->vmmap.width = vd->hdrwidth; vd->vmmap.format = vd->formatIn; vd->vmmap.frame = 0; if (ioctl (vd->fd, VIDIOCMCAPTURE, &(vd->vmmap))) { perror (\"cmcapture\"); exit_fatal (\"Not a JPEG webcam sorry Abort !\"); } } else 上海交通大学硕士学位论文 { vd->pFramebuffer =(unsigned char *) realloc (vd->pFramebuffer, (size_t) vd->framesizeIn); } return erreur; } static int isSpcaChip (const char *BridgeName) { int i = -1; int find = -1; int size = 0; for (i = 0; i < MAX_BRIDGE -1; i++) { size = strlen (Blist[i].name) ; if (strncmp (BridgeName, Blist[i].name, size) == 0) { find = i; break; } } return find; } static int GetStreamId (const char *BridgeName) { int i = -1; int match = -1; if ((match = isSpcaChip (BridgeName)) < 0) { return match; } switch (match) { case BRIDGE_ZC3XX: i = JPEG; break; break; } return i; } static int GetDepth (int format) { 65 上海交通大学硕士学位论文 int depth; switch (format) { case VIDEO_PALETTE_JPEG: { depth = 8; } break; default: depth = -1; break; } return depth; } void exit_fatal(char *messages) { printf(\"%s \n\ exit(1); } int get_jpegsize (unsigned char *buf, int insize) { int i; for ( i= 1024 ; i< insize; i++) { } return -1; } if ((buf[i] == 0xFF) && (buf[i+1] == 0xD9)) return i+2; 66 上海交通大学硕士学位论文 附录二 基于JRTPLIB的视频发送与接收程序 发送程序: #include /* 错误处理函数*/ void checkerror(int err) { if (err < 0) { char* errstr = RTPGetErrorString(err); printf(\"Error:%s.\\n\ exit(-1); } } int main(int argc, char** argv) { RTPSession sess; unsigned long destip; int destport; int portbase = 6000; int status, index; char buffer[128]; if (argc != 3) { printf(\"Usage: ./sender destip destport.\\n\"); return -1; } /* 获得接收端的IP地址和端口号*/ destip = inet_addr(argv[1]); if (destip == INADDR_NONE) { printf(\"Bad IP address specified.\\n\"); return -1; } destip = ntohl(destip); destport = atoi(argv[2]); /* 创建RTP会话*/ status = sess.Create(portbase); checkerror(status); 67 上海交通大学硕士学位论文 /* 指定RTP数据接收端*/ status = sess.AddDestination(destip, destport); checkerror(status); /*设置RTP会话默认参数*/ sess.SetDefaultPayloadType(0); sess.SetDefaultMark(false); sess.SetDefaultTimeStampIncrement(10); /*发送流媒体数据*/ index = 1; do { sprintf(buffer, \"%d: RTP packet\ sess.SendPacket(buffer, strlen(buffer)); printf(\"Send packet !\\n\"); } while(1); return 0; } 接收程序: #include if (err < 0) { char* errstr = RTPGetErrorString(err); printf(\"Error:%s\\n\ exit(-1); } } int main(int argc, char** argv) { RTPSession sess; int localport,portbase; int status; unsigned long remoteIP; if (argc != 4) { printf(\"Usage: ./sender localport.\\n\"); return -1; } /*获得用户指定的端口号*/ remoteIP = inet_addr(argv[1]); 68 上海交通大学硕士学位论文 localport = atoi(argv[2]); portbase = atoi(argv[3]); /*创建RTP会话*/ status = sess.Create(localport); checkerror(status); /*RTPHeader *rtphdr*/ unsigned long timestamp1; unsigned char * RawData; unsigned char temp[30]; int lengh ,i; bool allports = 1; sess.AddToAcceptList(remoteIP, allports,portbase); do { /*设置接收模式*/ sess.SetReceiveMode(RECEIVEMODE_ACCEPTSOME); sess.AddToAcceptList(remoteIP, allports,portbase); /*接受RTP数据*/ status = sess.PollData(); /*检索RTP数据源*/ if (sess.GotoFirstSourceWithData()) { do { RTPPacket* packet; /*获取RTP数据报*/ while ((packet = sess.GetNextPacket()) != NULL) { printf(\"Got packet !\\n\"); timestamp1 = packet->GetTimeStamp(); lengh=packet->GetPayloadLength(); RawData=packet->GetPayload(); for(i=0;i printf(\" timestamp: %d lengh=%d data:%s.\\n\ /*删除RTP数据报*/ delete packet; } } while (sess.GotoNextSourceWithData()); } } while(1); return 0; } 69 上海交通大学硕士学位论文 致 谢 转眼之间,两年多的研究生生活即将结束。回顾这样一段不平常的经历,我谨向所有关心、帮助和鼓励我的老师、同学、朋友及亲人致以诚挚的谢意。 首先要感谢我的恩师曹广益教授与朱新坚教授。曹老师与朱老师有着渊博丰富的知识、创新发散的思维、严谨的工作态度,我想这些是我一生都值得学习和难以忘记的。在学习、研究和生活等各方面他们给予了我悉心的指导和亲切的关怀。正是他们的帮助,正确的引导使得我能够从容面对各种困难和应付各种压力。在今后的学习、生活和工作中,我将时刻牢记他们的教诲,以满腔热血投身到祖国的建设,用优异的成绩报答他们的厚爱。 感谢燃料电池研究所的所有老师和同学们。他们给予了我热情的帮助,他们是:吴秋轩博士、畅志周博士、刘呈则博士、张树人硕士、郭斌硕士、周洁硕士。 特别感谢204寝室的全体同学,他们是杨建、潘志光、张洁、吉守龙、朱俊、杨友明、章真,他们在学习和生活上给予了我很多的帮助和鼓励,我们共同度过的快乐时光令我终生难忘。 另外,我要感谢B0403294班的全体同学,我非常怀念和他们共同度过的美好时光。 最后,衷心地感谢我的父母家人、朋友,是他们始终如一的关爱和支持给予了我不断前进的动力。 再次感谢所有关心过、帮助过我的人们。 70 上海交通大学硕士学位论文 攻读硕士学位期间发表的学术论文 【1】 张建,吴秋轩,曹广益. 无刷直流电机模糊伺服控制器设计. 计算机仿真, 已录用 71
因篇幅问题不能全部显示,请点此查看更多更全内容