基于Linux的视频传输系统完整方案.docx
《基于Linux的视频传输系统完整方案.docx》由会员分享,可在线阅读,更多相关《基于Linux的视频传输系统完整方案.docx(93页珍藏版)》请在冰豆网上搜索。
基于Linux的视频传输系统完整方案
目录
1原创性声明----------------------------------------------------3
2摘要----------------------------------------------------------4
3系统方案------------------------------------------------------4
3.1功能与指标----------------------------------------------4
3.2方案选择与论证------------------------------------------4
系统组成框图--------------------------------------------4
硬件平台介----------------------------------------------4
视频采集方案的选择--------------------------------------4
视频编码方案的选择--------------------------------------5
视频传输方案的选择--------------------------------------6
显示方案选择--------------------------------------------6
3.4系统软件实现--------------------------------------------6
3.4.1服务器--------------------------------------------6
(1)视频采集模块-------------------------------------6
(2)视频压缩模块------------------------------------10
(3)网络传输发送模块---------------------------------13
3.4.2客户端--------------------------------------------19
(1)网络传输接收模块--------------------------------19
(2)视频解码模块------------------------------------19
(3)视频显示模块------------------------------------22
四系统测试----------------------------------------------------25
附录:
源代码
参考书目
2006年英特尔杯大学生电子设计竞赛嵌入式系统专题邀请赛
参赛作品原创性声明
本人郑重声明:
所呈交的参赛作品报告,是本人和队友独立进行研究工作所取得的成果。
除文中已经注明引用的内容外,本论文不包含任何其他个人或集体已经发表或撰写过的作品成果,不侵犯任何第三方的知识产权或其他权利。
本人完全意识到本声明的法律结果由本人承担。
参赛队员签名:
日期:
年月日
2摘要
本系统在LINUX平台下实现了视频的采集、压缩、传输及组播,图象清晰,实时性较好。
本设计采用USB摄像头结合LINUX下自带的驱动模块VIDEO4LINUX实现视频采集。
在XVID视频编解码平台下实现视频的压缩和解压。
视频传输采用专门为流媒体传输设计的RTP协议,达到了较高的实时性。
ABSTRACT
OnthebasisofLinuxplatform,thissystemrealizesthevideodata'scollection,compressionandnetworktransmission.Thevideodata'scollectionisrealizedthroughUSBcameraandVideo4Linux.Thevideodata'scodinganddecodingisrealizedundertheXvidplatform.AndthenetworktransmissionisrealizedbyRtpprotocalwhichisdesignedforstreammedia.Allofthesemakehignreal-timeperformance.
关键词:
视频RTPXVIDSDL
3系统方案
3.1实现功能与指标
本系统可用于足球赛场向场内或场外观众提供更逼真的更精彩的比赛画面,使场内观众可以零距离的观看射门等精彩画面。
用户可用笔记本电脑由局域网连接服务器,运行客户端软件即可欣赏近距离的比赛画面。
服务器由USB摄像头采集数字视频信息,经过MPEG4视频编码,然后通过JRTP网络传输协议向连接到服务器的客户端传输视频信息,实现视频的实时组播。
采集到的YUV图像大约为100KB压缩后每帧图像大小平均为5KB,在局域网环境下延迟小于0.5秒,视频清晰无失真。
鉴于服务器的主频限制,组播最大连接数为5,可同时向5个用户提供视频信息。
3.2方案选择与论证
系统组成框图:
USB摄像头
基于GENE8310的服务器
10
网络
远程登录主机
硬件平台介绍:
GENE-8310是AAEON提供的第三代无风扇解决方案,在低功耗情况下可以获取更高的性能表现,主要表现在:
卓越性能与可控的功耗,多种显示模式,可扩展性,GENE8310主频为500M可以做视频采集处理与传输的服务器。
视频采集方案的选择:
LINUX有自带的摄像头驱动模块Video4Linux.Video4Linux为针对视频设备的应用程序编程提供一系列的接口函数,对于USB摄像头,其驱动程序中需要提供基本的I/O操作接口函数如openclose的实现以及内存影射功能和对I/O操作的控制接口函数ioctl等。
LINUX下视频采集如下所示
视频应用程序
Video4Linux2
设备驱动程序
视频采集设备
视频编解码方案的选择
Xvid作为第二代MPEG-4编码具有多方面的优点,XVID是DIVX开发小组因不满DIVX被封闭而在其基础上开发的源码开放的视频编码解码平台。
对于第二代的MPEG4视频编码内核来说。
XVID的各种特点都有代表性和先进意义。
1.它支持多种编码模式:
除了最原始的单重估定码流压缩(1-passCBR)之外,XVID提供了包括:
单重质量模式动态码流压缩单重量化(Quantization)模式动态码流压缩、和包括外部控制和内部控制的两种双重(2-pass)动态码流压缩模式。
2.在量化方式上Xvid不仅提供了标准的MPEG量化方式,还特地提供了更适合低码流压缩的.h263量化方式。
3.除了量化方式迭择,Xvid还提供了强大的对压缩过程中的量化幅度的范围控制。
用户可以选定压缩时允许使用的量化幅度范围。
例如设定一个量化的上限,就可以避免可能出现的画质大幅下降的情况。
4.在运动侦测(MotionSearch)和曲线平衡分配(Curve)方面,XVID对画面帧进行运动侦测以及对全片段的运动侦测结果进行分析后,重新以曲线平衡分配每一帧的量化幅度,以做到:
需要高码流的运动画面可以分配更多空间、更高的码流、更低的量化幅度来保持画面的细节;而对于不包含太多运动信息的静态画面,则消减分配预算。
这种把好钢用在刀刃上的做法,是Xvid作为第二代MPEG-4编码的核心内容。
5.Xvid提供了多极运动侦测精度,包括半像素插值的技术以16x16像素的微区块为单元标示上运动矢量:
以及4分运动矢量(inter4vmotionvectors)的方式,以8x8的像素区块为单元更细致的纪录运动向量以供二重分析。
6.动态关键帧距是另一个Xvid所具有的,在空间和画面之间获得最大平衡的技术。
我们知道在视频压缩中不是每一帧都记录着全部的画面信息,事实上只有关键帧记录着完整的画面信息,而后续的P帧(P-Frame)仅仅是纪录下与之前一帧的差值。
如果关键帧之间的画面变化很大,则会浪费宝贵的空间在P-Frame上;而加入把变化很大的那一帧记录在关键帧里,那么由于后续的帧不再有更大的变化,就可以节省P帧所需的空间。
因此,根据画面镜头切换和运动幅度来变换关键帧的位置,对于视频压缩下的画面质量提高,就有着事半功倍的效果。
鉴于XVID以上种种优点,我们采用XVID实现视频的编解码。
视频传输方案的选择
视频传输可以选择TCP与UDP,TCP是一个面向连接协议,传输信息前需要建立连接,系统资源开销大,但可靠性较高。
UDP是一个无连接协议,传输数据之前源端和终端不需要建立连接,资源开销小,实时性较高。
实时传输协议(Real-timeTransportProtocol,RTP)是在Internet上处理多媒体数据流的一种网络协议,利用它能够在一对一(Unicast,单播)或者一对多(Multicast,多播)的网络环境中实现传流媒体数据的实时传输。
RTP通常使用UDP来进行多媒体数据的传输,具有UDP传输的优点。
鉴于可靠性考虑,在本系统中,信息传输之前服务器和客户端用TCP建立连接。
然后服务器通过RTP向客户端发送视频信息,这样就达到了可靠性和实时性的平衡。
显示方案选择
SDL(SimpleDirectMediaLayer)是一个跨平台的多媒体游戏支持库。
其中包含了对图形、声音、线程等等的支持,目前可以运行在许多平台上,其中包括XWindow、XWindowwithDGA、LinuxFrameBuffer控制台等等。
因为SDL专门为游戏和多媒体应用而设计开发,所以它对图形的支持非常优秀,尤其是高级图形能力,比如Alpha混和、透明处理、YUV覆盖、Gamma校正等等。
而且在SDL环境中能够非常方便地加载支持OpenGL的Mesa库,从而提供对二维和三维图形的支持。
本系统客户端接受到的视频解压后为YUV格式,考虑到SDL在YUV覆盖方面的优势,我们选择SDL实现视频信息接收接压后的显示。
3.3系统软件实现
3.3.1服务器
服务器实现了采集数据然后压缩后进行实时传输,用了三个线程分别实现了视频的采集压缩(线程1),通过TCP协议建立连接(线程2),压缩后视频流的传输(线程3)。
服务器应用程序运行后,服务器即创建线程1进行视频采集,线程2处于阻塞状态。
一旦有客户端建立连接,则线程2获得客户端IP信息。
以此IP信息为参数建立线程3,线程3通过JRTP协议向客户端传递视频流。
此后客户端继续处于阻塞状态,直到有新的客户端连接。
服务器端的重要的模块包括视频采集模块,视频压缩模块,和网络传输发送模块。
(1)视频采集模块
Linux内核公开支持的OV511等摄像头芯片,但由于较陈旧在市面不容易找到。
我们选用LOGITECH的QUICKCAMCOOL摄像头并从网上下载摄像头驱动程序qc-usb-0.6.3.tar.gz然后进行解压、编译、安装。
假定已经搭建好嵌入式Linux的开发环境,下面第一步工作就是USB摄像头的安装与驱动。
确定USB摄像头被正常驱动后,下一步就是使用Video4Linux提供的API函数集来编写视频采集程序。
在Linux下,所有外设都被看成是一种特殊的文件,称为设备文件。
系统调用是内核和应用程序之间的接口,而设备驱动程序则是内核和外设之间的接口。
他完成设备的初始化和释放、对设备文件的各种操作和中断处理等功能,为应用程序屏蔽了外设硬件的细节,使得应用程序可以像普通文件一样对外设进行操作。
Linux系统中的视频子系统Video4Linux为视频应用程序提供了一套统一的API,视频应用程序通过标准的系统调用即可操作各种不同的视频捕获设备。
Video4Linux向虚拟文件系统注册视频设备文件,应用程序通过操作视频设备文件实现对视频设备的访问。
Linux下视频采集流程如图1所示
开启视频设备()
获取设备信息及图像信息()
初始化窗,颜色模式,帧状态()
捕捉视频帧数据()
关闭视频设备()
送压缩模块
是否中止采集
终止
开始
N
Y
图2LINUX下视频采集流程图
Video4Linux视频设备数据结构的定义
structvdIn{
intfd;//文件描述符
char*videodevice;//视频捕捉接口文件
structvideo_mmapvmmap;
structvideo_capabilityvideocap;//包含设备的基本信息(设备名称、支持的最大最小分辨率、信号源信息等)
intmmapsize;
structvideo_mbufvideombuf;映射的帧信息,实际是映射到摄像头存储缓冲区的帧信息,包括帧的大小(size),最多支持的帧数(frames)每帧相对基址的偏移(offset)
structvideo_picturevideopict;//采集图像的各种属性
structvideo_windowvideowin;
structvideo_channelvideochan;
intcameratype;//是否能capture,彩色还是黑白,是否能裁剪等等。
值如VID_TYPE_CAPTURE等
char*cameraname;//设备名称
charbridge[9];
intpalette;//availablepalette
intchannel;//信号源个数
intgrabMethod;
unsignedchar*pFramebuffer;//指向内存映射的指针
unsignedchar*ptframe[4];//指向压缩后的帧的指针数组
intframelock[4];//
pthread_mutex_tgrabmutex;//视频采集线程和传输线程的互斥信号
intframesizeIn;//视频帧的大小
volatileintframe_cour;//指向压缩后的帧的指针数组下标
intbppIn;//采集的视频帧的BPP
inthdrwidth;//采集的视频帧的宽度
inthdrheight;//采集的视频帧的高度
intformatIn;//采集的视频帧的格式
intsignalquit;//停止视频采集的信号
};
在视频采集之前,先要对Video4Linux进行初始化
初始化阶段用ioctl(intfd,indcmd,…)函数和设备进行“对话”。
Fd是设备的文件描述符,cmd是用户程序对设备的控制命令,省略号一般是一个表示类型长度的参数,也可以没有。
初始化步骤如下:
1.打开视频:
open(vd->videodevice,O_RDWR))
2.读video_capability中信息包括设备名称,支持最大最小分辨率,信号源信息等。
调用函数ioctl(vd->fd,VIDIOCGCAP,&(vd->videocap))成功后可读取vd->capability各分量
3.对采集图象的各种属性进行设置,分为两步首先获取摄象头缓冲区中video_picture中信息调用函数ioctl(vd->fd,VIDIOCGPICT,&(vd->picture));然后改变video_picture中分量的值,为vd->videopict分量赋新值,调用ioctl(vd->fd,VIDIOCSPICT,&vd->videopict)即可实现
4.对图象截取有两种方式:
第一种是用read()直接读取数据,第二种是用mmap是把设备文件映射到内存,用内存映射法一个显而易见的好处是效率高,因为进程可以直接读写内存,而不需要任何数据的拷贝,所以我们选择这种方法。
具体做法是
1获取摄象头存储缓冲区的帧信息调用ioctl(vd->fd,VIDIOCGMBUF,&(vd->videombuf))
2把摄象头对应的设备文件映射到内存区。
调用函数vd->pFramebuffer=(unsignedchar*)mmap(0,vd->videombuf.size,PROT_READ|PROT_WRITE,MAP_SHARED,vd->fd,0),成功调用后设备文件内容映射到内存区,
返回的映象内存区指针给vd->pFramebuffer,失败时返回-1。
3修改vd->vmmap中的设置,例如设置图象帧的垂直水平分辨率,彩色显示格式:
vd->vmmap.height=vd->hdrheight;
vd->vmmap.width=vd->hdrwidth;
vd->vmmap.format=vd->formatIn;
图象采集可分为单帧采集和连续帧采集,在本系统中采用连续帧采集的方法采集。
将vd->videombuf.framese的值赋为2确定采集完毕摄像头帧缓冲区帧数据进行循环的次数。
在循环语句中,采集其中的vd->pFramebuffer+vd->videombuf.offsets[vd->vmmap.frame],使用ioctl(vd->fd,VIDIOCMCAPTURE,&(vd->vmmap)函数,若调用成功,则激活设备真正开始一帧图像的截取,是非阻塞的。
接着使用ioctl(vd->fd,VIDIOCSYNC,&vd->vmmap.frame)函数判断该帧图像是否截取完毕,成功返回表示截取完毕,之后就可将采集到的帧进行压缩,然后将压缩后的文件保存到发送缓冲区中。
最后修改vd->vmmap.frame,vd->frame_cour的值进行下一次采集。
(2)视频压缩模块
对图像帧的编码是通过调用xvidcore-1.1.0函数库的函数实现的,在使用XVID之前要对XVID进行初始化,在初始化过程中,首先对编码器的各项参数即结构体xvid_enc_create中的各成员进行设定,然后调用xvid_encore(NULL,XVID_ENC_CREATE,&xvid_enc_create,NULL)建立编码器,初始化函数如下:
Intenc_init(intuse_assembler)
{
intxerr;
xvid_plugin_single_tsingle;//运算参数
xvid_plugin_2pass1_trc2pass1;
xvid_plugin_2pass2_trc2pass2;
xvid_enc_plugin_tplugins[7];
xvid_gbl_init_txvid_gbl_init;//xvid初始化参数
xvid_enc_create_txvid_enc_create;//xvid编码参数
/*Setversion--versioncheckingwilldonebyxvidcore*/
/*------------------------------------------------------------------------
*XviD初始化参数
*----------------------------------------------------------------------*/
memset(&xvid_gbl_init,0,sizeof(xvid_gbl_init));
xvid_gbl_init.version=XVID_VERSION;
xvid_gbl_init.debug=0;//设置版本号
/*DowehavetoenableASMoptimizations?
*/
if(use_assembler){
xvid_gbl_init.cpu_flags=0;
}
xvid_global(NULL,XVID_GBL_INIT,&xvid_gbl_init,NULL);//初始化
/*------------------------------------------------------------------------
*XviD编码器参数
*----------------------------------------------------------------------*/
memset(&xvid_enc_create,0,sizeof(xvid_enc_create));
xvid_enc_create.version=XVID_VERSION;//设置版本号
xvid_enc_create.width=XDIM;//编码器输入宽度
xvid_enc_create.height=YDIM;//编码器输入高度
xvid_enc_create.profile=XVID_PROFILE_S_L3;//编码的框架级别
/*initplugins*/
xvid_enc_create.zones=NULL;
xvid_enc_create.num_zones=0;
xvid_enc_create.plugins=NULL;
xvid_enc_create.num_plugins=0;
/*Nofancythreadtests*/
xvid_enc_create.num_threads=0;
/*Framerate-Dosomequickfloatfps=fincr/fbasehack*/
if((ARG_FRAMERATE-(int)ARG_FRAMERATE)xvid_enc_create.fincr=1;
xvid_enc_create.fbase=(int)ARG_FRAMERATE;
}else{
xvid_enc_create.fincr=FRAMERATE_INCR;
xvid_enc_create.fbase=(int)(FRAMERATE_INCR*ARG_FRAMERATE);
}
if(ARG_MAXKEYINTERVAL>0){
xvid_enc_create.max_key_interval=ARG_MAXKEYINTERVAL;
}else{
xvid_enc_create.max_key_interval=(int)ARG_FRAMERATE*10;
}
//关键帧之间的间距
xvid_enc_create.max_bframes=0;//B帧设置
xvid_enc_create.bquant_ratio=150;
xvid_enc_create.bquant_offset=100;
xvid_enc_