这里仅介绍流媒体server端的实现思路。及编码注意问题,不会贴代码的详细实现。
直接入正题先介绍一下系统硬件框架:
server端连接PC机用VLC播放例如以下图:
server端应用程序能够分为图像採集、视频硬件编码压缩、RTP打包发送。三个部分。採用C++语言编程。引入C、C++语言混合共享库的方式实现。
图像採集模块主要负责视频数据的採集。并将採集到的数据暂存到DDR2内存中,作为硬件编码模块的数据源。Linux3.0.8内核下视频採集是基于V4L2(Video for Linux 2)框架实现的.V4L2是Linux内核中关于视频设备的应用程序接口,它为音视频设备的应用程序编程提供了一套接口规范.完好的摄像头驱动包括了摄像头源数据与处理器硬件模块FIMC0的数据共享,暂存到DDR2中的数据源,会经过FIMC0转码成NV12格式。应用程序中能够通过V4L2提供的应用程序接口来控制FIMC0的转码格式。这样应用程序就完毕了指定颜色空间的实时视频採集。过程如图下图所看到的:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbGl1a3VuMzIx/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" />
完毕原始视频数据採集后。须要将视频硬件编码压缩成H.264,这里选用的H.264,主要因为它编码效率高、能以较低的数据速率传送基于IP(网际协议)的视频流。在视频质量、压缩效率和数据包恢复丢失等方面有较大的优势,能非常好适应以太网传输,是眼下监控系统最为理想的信源压缩编码标准。
编码过程是通过调用S5PV210处理器的硬件编码单元MFC,对转码得到的NV12格式的数据进行编码压缩处理。
因为210的MFC支持H.264、H.263、VC1、MPEG2、MPEG4等多种视频编码标准。并且每种编码格式相应多组參数可供开发者选择,适应多种不同环境多种要求下的视频编码。为了均衡视频质量和成像速度。
在权衡考虑网络传输条件和摄像头成像质量后。须要选择适中的MFC编码器品质因数,这样在保证高品质H.264图像压缩的前提下,减少了client的显示延迟。
编码压缩过程完毕后,下一步就要进行。视频RTP打包工作了。原始的 H.264 视频编码数据,不能直接用于网络传输,easy造成丢包及传输错误,须要对其进行封装。
因此在client应用程序中添加了RTP打包子功能。视频数据的整个打包封装步骤例如以下图 所看到的。另外。在实时性要求较高的应用场合,RTP 是使用UDP 进行传输数据。以下就简介一下RTP+UDP包的结构:
RTP 载荷经常使用的打包方式有三种:单NAL 单元方式。非交错方式以及交错方式。各种方式有其同意的NAL 单元类型。经常使用的类型有单个NAL 单元包(NAL unit),聚合包(STAP-A。STAP-B,MTAP),分片单元(FU-A,FU-B)等。当中。NAL unit 包中必须包括一个完整的编码后的NAL 单元。聚合包中包括一个或多个NAL 单元。而分片单元Fus 同意将一个NAL单元分片到几个RTP 包中。依据TI 提供的H.264 压缩算法及其压缩后的NAL 单元数据特点,本文採用NAL unit 和FU-A 两种包类型。
其相应的RTP 载荷格式主要是头部不同,描写叙述例如以下。
NAL unit
头部为一个字节,三个标志的含义例如以下。
F:1 bit,0 表示NAL 单元类型的八位组和载荷不同意包括比特错误或其他语法错误,1 则相反。H.264规范要求该位为0;
NRI:2 bits。与编码后的网络抽象层NAL 单元中的NAL 单元类型字节里NRI 值保持一致。
Type:5 bits,H.264 规范定义其取值范围为1~23。
在该类型包设计时取值同上,即与NAL 单元类型字节里nal_unit_type 同样。
程序设计时该字节与NAL 单元第一字节设置为同样就可以,对于编码后的NAL 单元。第一字节即是NAL 单元类型字节。
FU-A
头部包括两个字节,第一字节为FU indicator,第二字节为FU header。FU indicator,该字节与NAL unit 头部结构同样。标志F 和NRI 设置方法同上,对于Type 标志,规范中该类型值设置为28。
FU header,各标志含义例如以下。
S:1 bit,開始标志位。
对于NAL 单元第一个分片,设置为1。其他为0。
E:1 bit。结束标志位。对于最后一个分片。设置为1。其他为0
R:1 bit,保留位。设置为0,接收者必须忽略该位。
Type:5 bits,NAL 单元荷载类型。与编码后的网络抽象层NAL 单元中的NAL 单元类型字节nal_unit_type 值保持一致。
对于原始压缩数据。不仅要进行RTP 载荷打包,还须要添加RTP 头来组成完整的RTP 包。我是用的是JRTPLIB 库实现RTP 的自己主动打包以及传输功能。RTP包头所需的一些參数如:Market,帧间延时时间,时间戳由函数SendPacket 參数传入。
写到这里server端功能模块基本介绍完了。再说一下程序设计关键点。例如以下:
(1)因为MFC驱动中的视频源数据的颜色空间必须为NV12,因此在通过V4L2框架初始化/video0 输出视频格式时。注意要将格式设置为NV12。从而才干正确解码。
(2) 通过MFC硬编码后的一帧视频包括若干个NAL 单元。每一个NAL 单元都由一个起始码开头,对于S5PV210的MFC硬件编码H.264 压缩算法起始码由00 00 00 01 四个字节组成。
(3) 因为UDP协议会对大于1500 字节的数据包进行自己主动拆包。从而导致丢包概率会大大添加。
因此须要设置RTP 荷载包的最大长度为1400。
在封装荷载头,RTP头,UDP头和IP头后长度依旧会小于1500字节,减少丢包概率。
(4) 參数M。PT。timestamp 设置。
M。对于NAL_unit 包类型即单个NAL单元长度值小于1400字节,值为1。当单个NAL单元长度大于1400时,须要进行分片处理。FU-A 类型除该NAL 单元的最后一个分片设置为1 外,其他为0;载荷类型PT 依据标准设置为96;时间戳在SendPacket 函数中传入的是其增量timestamp_inc,对于NAL unit。因为视频採用的是PAL 制式。故值设为9000/25。对于同一NAL 单元的全部FU-A 分片包,timestamp 值应同样。因此,除第一个包设置值以外,其他为0。
server端程序流程图例如以下:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbGl1a3VuMzIx/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" />