免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2179 | 回复: 0
打印 上一主题 下一主题

音/视频通讯的嵌入式linux视频监控 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-12-20 09:44 |只看该作者 |倒序浏览
视频监控它是一种防范能力较强的综合系统。视频监控以其直观、准确、及时和信息内容丰富而广泛应用于许多场合。近年来,随着计算机、网络以及图像处理、传输技术的飞速发展,视频监控技术也有了长足的发展。如今视频监控已遍布城市的角落,生活更是因为有了它提高了质量,下面跟大家分享一篇在网上下载的论文。结合佰锐科技音视频的相关知识进行阐述。

1  引 言

目前,基于PC 的传统视频监控系统在安防领域使用仍较广泛,这种系统虽然功能较强,但稳定性不好、视频前端较为复杂、可靠性较差、功耗高。近年来,随着高性能嵌入式处理器和网络技术的快速发展,数字化、小型化、网络化的嵌入式网络视频监控系统将会得到广泛应用,这种系统把图像采集、视频压缩和网络功能集中在一起,可以直接连入以太网, 具有体积小、功耗低、稳定性高、成本低等优点。视频编码有两种实现方式:一种是通过专用芯片实现视频图像的硬件压缩,另一种是在通用处理器基础上利用软件方式实现压缩, 相对于硬件压缩方式,软件压缩具有可扩展性好、算法灵活等特点。

本文设计和实现了一个嵌入式视频监控系统,该系统基于嵌入式Linux操作系统和 ARM9 微处理器平台,通过软件压缩方式利用Xvid 编码器实现视频压缩编码,通过RTP将视频数据发送到网络上进行传输,远程客户端可通过终端软件接收并解码视频流以实现视频监控。

2  系统硬件设计

系统硬件系统采用的ARM9内核芯片S3C2440[3]作为硬件平台的中央处理器,该处理器主频可达 400MHz,硬件接口和资源丰富,存储单元包括Flash 和 SDRAM,Flash 具有掉电保持数据的特性,用于存储Bootloader 启动程序、Linux 内核映像、文件系统以及用户应用程序等。SDRAM  数据存取速度大大高于 Flash  存储器,用于为操作系统和应用程序提供运行空间。平台利用RS232 接口输出调试信息,通过以太网控制器芯片 DM9000 扩展了一个网口,用于与外部网络进行通信,通过 USB   HOST 接口连接USB 摄像头采集图像数据,经处理器压缩并打包成视频流后经以太网进行传输,终端用户接收到视频流,解码后即可把视频图像显示出来。

3  系统软件设计

软件平台采用的嵌入式操作系统为Linux 2.6.13,Linux 具有内核小、效率高、源码开放、内核直接提供网络支持等优点,但嵌入式系统的硬件资源有限,因此需根据实际需求对内核进行裁剪,配置所需的功能模块,然后再移植到硬件平台上。

嵌入式系统的软件开发采用交叉编译调试的方式,在宿主机上安装Linux 系统,建立交叉编译环境,在宿主机编写程序代码,再利用交叉编译工具生成目标机上可用的可执行文件,最后向目标机平台移植。

3.1 视频采集模块

视频采集模块通过嵌入式 Linux 操作系统调用 Video4Linux(V4L)和底层设备驱动程序来完成视频捕获。V4L 是Linux  中关于视频设备的内核驱动,它为Linux 下的各种视频设备提供了统一的编程接口,应用程序通过这些接口函数就可以操纵各种不同的设备。

(1)打开视频设备。Linux下的视频设备文件一般为“/dev/video0 ”,通过调用函数 v4l_open(  ) ,利用 vd->fd=open(“/dev/video0”,O_RDWR)打开设备并获得设备文件描述符vd->fd。

(2) 获取设备和图像信息。通过 v4l_get_capability(  ) 函数获取设备信息,通过v4l_get_picture( )函数获取图像信息。

(3) 内存映射。获取图像的方式有两种:read(   )直接读取和mmap(   ) 内存映射。直接读取方式通过内核缓冲区来读取图像数据,而本文使用内存映射方式mmap(   ),内存映射方式可以直接把设备文件映射到内存中,进程可以像访问普通内存一样对文件进行访问,读取效率 更高。初始化内存映射时,需在内存中开辟一块空间,利用 ioctl(vd->fd,VIDIOCGMBUF, &(vd->mbuf))操作取得需要映射的内存空间大小 vd->mbuf.size ,利用 mmap(  ) 函数,即vd->map=(unsigned  char*)  mmap(0,  vd->mbuf.size,  PROT_READ  |  PROT_WRITE, MAP_SHARED, vd->fd, 0)操作,把设备文件的内容映射到内存,vd->map 指针所指向的内存区即为采集的图像数据,且此内存区具有可读写和共享属性。

(4)初始化采集参数。设置采集视频图像的宽度、高度、格式等信息。

(5)采集视频数据。利用ioctl(vd->fd, VIDIOCMCAPTURE, &(vd->mmap))操作采集一帧图 像并存放到内存映射区,采集一帧图像后要进行同步操作,利用ioctl(vd->fd, VIDIOCSYNC, &(vd->  frame_current))操作判断该帧图像是否获取完毕。对于获取到的视频图像,通过视频 压缩模块压缩成MPEG-4 视频流,再通过视频传输模块把数据发送到以太网进行传输。


3.2 视频压缩模块

从摄像头直接采集过来的图像由于数据量较大,不利于进行网络传输,因此需先对其进 行压缩编码。MPEG-4 是目前网络多媒体传输的主要格式,具有高效的压缩率,它利用很窄的带宽,通过帧重建技术来压缩图像数据,以求利用最少的数据获得最佳的图像质量 ,可满足实时视频传输的要求。本文用软件方式进行视频编码,选择开源高效的 Xvid  视频编码器对采集的视频图像数据进行MPEG-4 压缩编码。

Xvid 视频编码器选用0.9.2 版本,因为该版本已经实现了MPEG-4 的Simple Profile (SP) 特性,而 1.0 以后的版本增加了很多Advanced SP  (ASP )特性及其他功能,ASP 特性的加入会增加运算复杂度,降低编码速度,由于嵌入式系统的处理能力有限,一般只使用 Xvid的SP 特性,因此实验选用Xvid0.9.2 编码器,交叉编译并移植到嵌入式系统内。

在宿主机Linux 操作系统中对Xvid0.9.2 进行交叉编译的步骤如下:

(1) 解压缩Xvid 源码: tar –xzvf xvidcore- 0.9.2.tar.gz

(2)  进入build/generic  目录,创建编译配置文件。由于Xvid 没有针对ARM 的汇编优化, 因此编译时需将汇编关闭;还需指定程序所运行的平台为arm-linux。

执行命令: ./configure --disable-assembly --host=arm-linux

(3) 编译:make; make install 。

(4) 交叉编译完成后会生成静态库libxvidcore.a 和动态库libxvidcore.so.*,用户程序可利用库文件所提供的编程接口调用Xvid 里面的函数。

摄像头采集的视频帧为 YUV420 格式,通过 Xvid 编码器的 encoder_encode 函数实现视频压缩,该函数定义如下:
    int encoder_encode(Encoder * pEnc, XVID_ENC_FRAME * pFrame, XVID_ENC_STATS * pResult); 其中,pEnc 为编码器实例的句柄;pFrame 是XVID_ENC_FRAME 类型的结构体变量,负责传递参数信息给编码器,这些信息包含色彩空间、编码质量、输入输出数据缓冲区指针等;pResult 是XVID_ENC_STATS 类型的结构体变量,可以返回编码操作执行的状态信息。 

3.3 视频传输模块

视频传输模块负责把压缩后的视频流传输到以太网,对实时性要求较高,本文使用实时传输协议(Real-time   Transport   Protocol,RTP),它可以在一对一或者一对多的网络环境中实现流媒体数据的实时传输。JRTPLIB[7]是一个利用C++语言实现的开源RTP 库,它完全遵循RFC 1889 设计,使用 SOCKET 机制实现网络通讯,可运行于包括Linux 和Windows 在内的多种不同操作系统上。

本文使用JRTPLIB 进行实时流媒体编程,发送端操作系统为Linux,接收端为Windows。在Linux 平台上用JRTPLIB 进行实时多媒体编程前,需先对JRTPLIB 进行交叉编译。

(1) JRTPLIB 初始化

通过调用RTPSessionParams    类的 SetOwnTimestampUnit( )方法设置一个恰当的时间戳,调用  SetMaximumPacketSize(   )方法设置允许传输的最大RTP 包字节数(默认为 1400 字节);通过调用RTPUDPv4TransmissionParams    类的 SetPortbase(   )方法设置发送端数据传输所用的端口号(需为偶数)。初始化完这两个变量后,通过 RTPSession  类的 Create(  )方法创建一个RTP会话。

(2) JRTPLIB 数据传输

RTP 会话创建完成后,还需指定数据发送的目标地址,RTP 协议允许一个会话包含多个目标地址,增加或删除目标地址可通过RTPSession 类的AddDestination(  )  、DeleteDestination( )、ClearDestinations( )方法来实现。

目标地址指定之后,通过RTPSession 类的 SendPacket( )方法即可向指定的目标地址发送流媒体数据。SendPacket( )是一个重载函数,具有多种形式,本文使用的形式为: int SendPacket(const void *data, size_t len, uint8_t pt, bool mark, uint32_t timestampinc); 当一帧数据所占字节数大于允许传输的最大RTP 包字节数MaxPacketSize 时,需对一帧数据进行分割传输,使每次发送的字节数不大于MaxPacketSize,可使用 SendPacket( )的mark参数来标识传输的 RTP 包是否属于同一帧数据,若一帧数据需分成N  次发送,则前N-1 次发送的RTP 包的mark 标志设为0,第N 次发送的RTP 包的mark 标志设为1,即以mark=1 来判断分割传输的数据是否发送完成。实现过程如下:
    do{
    if(length>MaxPacketSize){
     mark=0;

    发送长度为MaxPacketSize 的RTP 包;
    length=length-MaxPacketSize;
     }
    else{
     mark=1;

         发送长度为length 的RTP 包;

        break;   //一帧数据发送完成
     }
     }while(1);

(3) JRTPLIB 数据接收

接收数据时,以BeginDataAccess( )函数开始,以EndDataAccess( )函数结束。为了能正确接收同一数据源的数据报,必须先对数据源表(source table)加锁,BeginDataAccess( )函数可实现这一加锁操作,确保在使用数据源表的同时轮询(poll)线程不能访问它,此时可进行数据接收操作,当正确接收一个数据报后,调用EndDataAccess(  )函数即可实现对数据源表 的解锁。

对于分割传输的 RTP 包,根据 RTP 包的 mark 标志来判断一帧数据是否接收完成,若mark=0,则表示此RTP 包为分割传输的数据包,需循环接收直到mark=1为止,然后把这些RTP包重新组合成完整的一帧数据。 

3.4 视频解码与回放

接收到的视频流数据经过 Xvid 解码器的 decoder_decode  函数进行解码,该函数定义如下:
    int decoder_decode(DECODER * dec, XVID_DEC_FRAME * frame); 其中,dec 为解码器实例的句柄,frame 为 XVID_DEC_FRAME  结构体变量,包含解码前后图像数据的缓冲区指针、码流长度等信息。

4  结 语

嵌入式Linux 和ARM9 处理器平台的网络视频监控系统,测 试表明该系统性能稳定,除可查看监控图像外,还可实现抓图和录像等功能。这种嵌入式视频监控系统与传统视频监控系统相比,更适合于远距离传输,且抗干扰能力强、灵活性更好、易安装和维护,可用于家庭、小区、工厂、商店等监控场合,应用前景广阔。 如果要自己完全开发一套可用的系统,还是需要花费大量的时间及精力,如果是公司商用的话,可以考虑一些商用的开发包,如(Anychat ) http://www.anychat.cn/ 可以节约开发时间,缩短项目开发周期;节省开发费用;减少人力资源投入平台自主开发,提升企业综合竞争力;产品跨平台,应用领域广阔;API接口丰富,方便与第三方业务集成;专业技术支持,性能稳定可靠。是即时通讯的重重之选! 

测试下载地址:http://www2.bairuitech.com/downloads/bairuisoft/AnyChatCoreSDK_V3.0.rar

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP