流媒体是一种在网络上在线播放多媒体的技术。由于其边下载边播放的特性,缩短了用户初始等待的延迟,但其数据也需要采用流式传输,具有较高的实时需求,因此比起一般的本地播放处理更为复杂。客户端是流媒体系统中一个基本的组成部分,一般是一个具有网络通信功能的播放器,比较著名的具有流媒体功能的播放器有realplayer、Windows media player等。这里以在Windows平台上自主开发的一套客户端播放器为实例,介绍流媒体客户端的系统结构和工作原理。
一、系统结构
根据工作平台的不同,客户端的形式也有多种,除了PC机,还可以运行在机顶盒或无线便携式设备上。但是客户端的工作流程却都是相似,即从网络中接收从流服务器传输过来的各类媒体数据流,存入一个缓冲队列,然后对其中的每一帧数据调用各类解码器重建成原始的数据格式,最后经同步后在设备上播放出来。
从功能层次上看,播放器主模块可以分为四个层次:RTSP会话控制层、RTP数据传输层、解码层和显示播放层(如图1所示)。播放器与服务器之间的通信主要是由位于应用层的RTSP协议和位于传输层的RTP 协议(Real-time Transport Protocol)来实现的。
RTSP会话控制层由播放器主线程来完成,负责RTSP相关控制指令的传送与接收分析。RTP数据传输层和解码层分别由从主线程产生的接收和解码线程来完成,接收和解码线程对应视频数据和音频数据又各自分别独立为两个不同的线程处理数据的接收和解码任务。显示播放层同样也实现视频、音频两个独立的播放任务。
对于各层之间的信息交互,首先由RTSP会话控制层向流媒体服务器提出请求并建立连接,然后RTP数据传输层负责对网络上传送过来的实时视频、音频数据进行预处理,主要是统计相关数据信息并依照RTP包头在缓冲队列中进行排序。根据RTP数据包头时戳信息,按时送达到解码层进行解码。解码线程选择匹配的解码器进行解码,并最终在显示播放层完成最终的播放。
二、工作原理
1. RTSP会话连接
RTSP[2]是基于TCP协议的一个实时流控制协议。通过此协议,可以为服务器和客户端建立会话控制连接,为多媒体流提供远程控制功能,诸如播放、暂停、跳跃、停止等。因此对于客户端应该首先连接服务器端的RTSP端口。建立RTSP连接后,客户端发送DESCRIBE方法给服务器,其中包含了点播文件的URL。如果存在认证步骤,服务器就会返回一个错误码,接着,客户端会将用户输入的用户名和密码包含进RTSP包并再次发送DESCRIBE。服务器收到后会传送媒体描述文件SDP(符合RFC2327标准)到客户端播放器。客户端读取SDP描述文件来配置音频、视频解码同步信息,例如:文件名、网络类型、RTP数据传输通道端口号、编码类型、采样率等。在配置好音视频相关信息后,客户端发送SETUP方法给服务器,配置相关的传输网络协议,传输方式和端口等信息。最后在创建好接收解码线程后,客户端发送PLAY方法,通知服务器往本地RTP接收端口发送音视频数据。会话结束后,客户端发送TEARDOWN到服务器断开连接。此外,在会话期间,客户端可以通过改变PLAY指令的参数,以及PAUSE指令实现播放暂停跳跃等VCR功能。图2中的TEST,RESEND和ECHO指令是我们为智能流服务增加的几个RTSP指令。
2. 解码前的RTP数据处理
RTP[3]传输通常基于传输效率较高数据可靠性较低的UDP协议,是一个针对实时数据的传输协议。在UDP数据包之前增加了一个RTP包头,其中包含了一些可以较好保证流数据连续性实时性的信息,如序列号、时间戳等。序列号可以保证到达客户端的RTP包的连续,而时间戳可以同步音视频包。
在RTSP的SETUP包中,客户端会通知服务器本地RTP接收端口。因此在创建接收线程时,首先创建本地UDP的socket端口并绑定。然后循环等待接收从服务器传来的RTP音视频数据包,并将接收到数据按序列号顺序插入到一个缓冲队列中。初始缓冲长度可以由用户设定。新的数据包根据其序列号插入到队列中正确的位置。
一旦缓冲增加到初始阈值,客户端将启动解码线程,开始循环读取缓冲的头部节点数据。每次客户端将读取缓冲中具有相同时间戳的数据作为一个整体送入解码器中。由于视频的一帧数据被拆分成几个时间戳相同的RTP数据包,而音频没有这样处理,每个RTP包的时间戳都不一样。因此,每次送入解码器的是视频的一帧或是音频的一个RTP包单元的数据,具体如图3所示。
从接收到解码,音视频数据都是在互为独立的线程中处理,因此可能会由于网络或终端环境因素而失去同步。
3. 解码后数据处理
解码器每次解码一帧视频或是一个音频包(后面统称为一个数据单元),由于被解码后的数据并不一定就马上需要被播放,为了保证安全性,从将一帧解码到将此帧显示出来,中间可以经过一段缓冲存储过程。
可以设计一个缓存,包含了一些长度(视频是16,音频是32)固定的数组,分别用来存储解码后数据内容以及播放时间信息和当前填充状态。解码后的每一个数据单元被存入缓存,然后到播放时间时再从缓存中取出相应的数据单元。每取出一个数据单元则将新的一个数据单元填入被取出数据留出的空间。如此可以循环使用该固定长度的缓存空间。
这段缓存对于视频,每一帧已解码的数据被填入到同一个数组单元之中;对于音频,每一个RTP包单元的数据解码之后被填入到一个数组单元中。同时建立了两个索引,一个用于填入数据,一个用于取出数据。
以视频为例,初始时首先连续解码16帧的数据,将缓冲数组填满,如图4(a)所示:1表示已有数据填入,0表示数据已经取出。
当第15组数据填完后,填值索引重新指向第0个数组。然后播放器继续解下一帧。但是第0组里已经有数据,所以无法再往第0组填入数据,此时填值操作进行等待。此时取值索引初始时也指向第0组数据,当当前时间等于第0组的播放时间时,开始取出并播放第0组的解码数据,取值索引移到第一组,此时第0组无数据。
第0组数据播放之后,将重新唤醒解码线程,将已解出的下一帧数据填入到第0组之中,填值索引也移至第1组。然后播放器继续解下一帧,但是第一组里数据尚未被取出显示,所以无法填入新数据,解码线程又开始等待,所示。如此循环下去,即完成了解码到显示之间的工作。
对于音频,不同的在于,每次播放将从缓存中取出固定长度或采样点数的音频数据。
4. 音视频同步
前面曾提到,解码到缓存中的音视频数据由于不相关性是存在不同步的可能的,这样在播放时会破坏服务质量,因此需要在播放前取出缓存中数据时对音视频进行重同步。同步机制采用的是一个以系统时钟为标准的计时循环。由于音频对播放速率的均匀性要求更严,因此音频的播放是根据其本身的帧率按一定的速率不断的取出数据进行播放的。视频则是根据计时器所更新的系统时钟来确定是否播放,也就是说,当系统时钟超过下一帧视频的播放时间后,该视频将被播放。系统时钟的更新以音频为基准。如果视频失去同步,比如过分落后于当前系统时钟,则会选择跳帧来尽快赶上计时器时间;如果超过当前系统时钟过多,则会暂时等待计时器计时增加。同样,音频出现意外情况时,也会作类似的处理。这样,在以上机制的保证下,音视频能够始终按照一定的基准达到同步,并且能够抵制外界变化对同步造成的影响。
5. 音视频播放
音视频媒体的播放可以调用DirectShow接口实现,分别使用DirectDraw和DirectSound通过驱动系统硬件设备来播放音视频数据。DirectShow技术在音视频采集,视频聊天,视频点播,视频叠加,媒体播放等领域都有相当成熟的应用。在程序启动时,需要先初始化音视频的一些播放配置信息。如果是视频,在解码后如果到达某一帧的播放期限,则经过同步检测后将数据内容作为参数调用函数进行显示。音频则是在初始化后启动一个播放线程,在这个线程中存在一个循环,不断读取缓存中的音频数据,然后进行播放。
三、结束语
流媒体技术是多媒体数据在互联网上传输很有前途应用最广泛的技术,客户端播放器作为其中一个重要的组成部分,其性能的好坏直接影响到用户的服务质量。在客户端中,音视频数据的处理从接收到解码都是在相互独立的线程中,然后利用数据的时间戳进行同步保护。客户端的通信与传输需要遵从RTP和RTSP,这是其支持流媒体播放的一个重要标准
流媒体客户端的结构与原理浅析
最新推荐文章于 2021-05-02 00:42:16 发布