C++流媒体开源库Live555详细介绍
C++流媒体开源库Live555详细介绍
1、Live555简介
Live555是一个为流媒体提供解决方案的跨平台的C++开源项目,它使用了RTP/RTCP、RTSP、SIP开放标准协议,实现了标准流媒体传输。Live555实现了对多种音视频编码格式的音视频数据的流化、接收和处理等支持,包括MPEG,H.265,H.264,H.263 +,DV或JPEG视频和多种音频编码。同时由于良好的设计,Live555非常容易扩展对其他格式的支持。
使用Live555可以开发客户端拉取远端的音视频流(比如使用VLC播放远端的视频流),也可以开发提供音视频流资源的Live555流媒体服务器。Live555已经被用于多款播放器的流媒体播放功能的实现,如VLC(VideoLan)、MPlayer。当前盛行的网络直播,也大量地使用到了Live555的流媒体技术。
2、Live555源码目录说明
Live555的目录结构:
1)BasicUsageEnvironment
该目录中定义了UsageEnvironment类的基本实现(即子类),用于简单的控制台应用程序,利用select 实现事件获取和处理。这个库利用Unix 或者Windows 的控制台作为输入输出,可以用来开发简单的控制台应用程序。
2)UsageEnvironment
该目录中定义了UsageEnvironment和TaskScheduler抽象类,用于调度延迟事件,为异步读取事件分配处理程序以及输出错误/警告消息。另外其中还有HashTable类定义了通用散列表的接口。
3)groupsock
该目录是对网络接口的封装,用于收发数据包。groupsock 主要是面向多播数据的收发的,它也同时支持单播数据的收发。
4)liveMedia
该目录中有一系列类,基类是Medium,这些类针对不同的流媒体类型和编码,这是Live555的核心部分。
5)testProgs
该目录实现一些使用BasicUsageEnvironment的简单程序来演示如何使用这些库开发应用程序。
6)proxyServer
是一个基于Live555的流媒体代理服务器,只要支持Onvif协议的摄像机都能接入,适用于将局域网内摄像机加入到代理服务器中从而提高对外服务性能同时,只需要开放默认554端口,可以有效保护内网摄像机安全。
7)WindowsAudioInputDevice
这是liveMedia库的AudioInputDevice抽象类的实现。这可以由Windows应用程序用于从输入设备读取PCM音频样本。
3、Live555中的关键概念与流程介绍
3.1、liveMedia的运转
1)Source和Sink
Source是生产数据的对象,例如从RTP读取数据。MediaSource是所有Source的基类。
Sink是消费数据的对象,例如把接受到的数据存储到文件中。MediaSink是所有Sink的基类。
2)数据流
Source -> Source(filters) -> Sink
从其它Source 接收数据的source 也叫做filters。Module是一个filters或Sink,数据接收的终点是Sink 类,Sink 类实现对数据的处理是通过实现纯虚函数continuePlaying(),通常情况下,continuePlaying 调用getNextFrame 来为Source 设置数据缓冲区,处理数据的回调函数等。不通常的情况下调用processBuffer,从接下来的socket writable或incoming data处理数据。
3)基于liveMedia的应用程序的控制流程
基于liveMedia的应用程序是事件驱动的,使用如下方式的循环:
while(1)
{
//查找度网络句柄的列表和延迟队列,发现需要完成的任务;
//完成任务
}
对于每个sink,在进入这个循环之前,应用程序通常调用下面的方法来启动需要做的生成任务: SinkObject->startPlaying()。任何时候,一个Module 需要获取数据都通过调用刚好在它之前的那个Module 的getNextFrame() 方法。
3.2、RTSP介绍
RTSP(实时流媒体协议,Real Time Streaming Protocol),是由Real network 和Netscape共同提出的如何有效地在IP 网络上传输流媒体数据的应用层协议。
RTSP 提供一种可扩展的框架,使能够提供能控制的,按需传输实时数据,比如音频和视频文件。源数据可以包括现场数据的反馈和存贮的文件。rtsp 对流媒体提供了诸如暂停,快进等控制,而它本身并不传输数据,rtsp 作用相当于流媒体服务器的远程控制。传输数据可以通过传输层的tcp,udp协议,rtsp 也提供了基于rtp 传输机制的一些有效的方法。
RTSP 中常用方法有:OPTION 、DESCRIBE 、SETUP 、PLAY 和TEARDOWN 。
OPTION:目的是得到服务器提供的可用方法。服务器回应可用的方法,例如:
Public: OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE, SCALE。
DESCRIBE:为了得到会话描述信息(具体见附录SDP格式)。
SETUP:客户端提醒服务器建立会话,并确定传输模式,其中Transport 参数设置了传输模式。
PLAY:播放请求。
TEARDOWN:关闭请求。
客户端和服务端简单的交互流程如下:
3.3、RTSP连接的建立
RTSPServer 类用于构建一个RTSP 服务器,该类同时在其内部定义了RTSPClientSession类,用于处理单独的客户会话。相关流程如下:
1)首先创建RTSP 服务器,在创建过程中,先建立Socket(ourSocket) 在TCP 的554 端口进行监听;
2)把连接处理函数句柄(RTSPServer::incomingConnectionHandler)和socket 句柄传给任务调度器(taskScheduler)。
3)任务调度器把socket 句柄放入后面select 调用中用到的socket 句柄集(fReadSet)中,同时将socket 句柄和incomingConnectionHandler 句柄关联起来。
4)主程序开始进入任务调度器的主循环(doEventLoop),在主循环中调用系统函数select 阻塞,等待网络连接。
5)RTSP 客户端输入(rtsp://192.168.2.20/live)连接服务器;
6)select 返回对应的scoket,进而根据前面保存的对应关系, 可找到对应处理函数句柄;
7)在incomingConnectionHandler 中创建RTSPClientSession,开始对这个客户端的会话进行处理。
3.4、DESCRIBE 请求消息处理过程
RTSP 服务器收到客户端的DESCRIBE 请求后,根据请求URL(rtsp://192.168.2.20/1.mpg),找到对应的流媒体资源, 返回响应消息。live555中的ServerMediaSession 类用来处理会话中描述,它包含多个(音频或视频)的子会话描述(ServerMediaSubsession)。相关处理流程如下
1)服务器收到请求,主循环中的select调用返回,根据socket 句柄找到对应的incomingRequestHandler;
2)进行消息的解析,如果发现请求是DESCRIBE 则进入handleCmd_DESCRIBE 函数;
3)根据客户端请求URL 的后缀(例如是.mpg), 调用成员函数DynamicRTSPServer::lookupServerMediaSession查找对应的流媒信息ServerMediaSession;
4)如果ServerMediaSession 不存在,但是本地存在live文件,则创建一个新的ServerMediaSession;
5)在创建ServerMediaSession 过程中,根据文件后缀.mpg,创建媒体MPEG-1or2的解复用器(MPEG1or2FileServerDemux);
6)由MPEG1or2FileServerDemux 创建一个子会话描述
MPEG1or2DemuxedServerMediaSubsession;
7)由ServerMediaSession 完成组装响应消息中的SDP 信息;
8)返回响应消息给客户端,完成DESCRIBE消息交互。
3.5、SETUP 和PLAY 请求消息处理过程
RTSPClientSession类, 用于处理单独的客户会话。其类成员函数handleCmd_SETUP()处理客户端的SETUP 请求。调用parseTransportHeader()对SETUP 请求的传输头解析,调用子会话(实现类OnDemandServerMediaSubsession)的getStreamParameters()函数获取流媒体发送传输参数。将这些参数组装成响应消息,返回给客户端。
获取发送传输参数的过程:
1)调用子会话( 具体实现类MPEG1or2DemuxedServerMediaSubsession) 的createNewStreamSource() 创建MPEG1or2VideoStreamFramer,选择发送传输参数;
2)并调用子会话的createNewRTPSink()创建MPEG1or2VideoRTPSink。同时将这些信息保存在StreamState 类对象中,用于记录流的状态。
客户端发送两个SETUP 请求,分别用于建立音频和视频的RTP 接收。PLAY 请求消息处理过程如下:
1)RTSPClientSession 类成员函数handleCmd_PLAY()处理客户端的播放请求。2)调用子会话的startStream(), 在一系列调用中的buildAndSendPacke 内部先设置RTP 包头;
3)内部再调用MultiFramedRTPSink::packFrame()填充编码帧数据;
4)packFrame 内部通过一系列繁琐调用,发送RTP 数据包;
5)计算下一个数据包发送时间,把MultiFramedRTPSink::sendNext()函数句柄传给任务调度器, 作为一个延时事件调度;
6)在主循环中, 当MultiFramedRTPSink::sendNext() 被调度时, 又开始调用MultiFramedRTPSink::buildAndSendPacket()开始新的发送数据过程,这样客户端可以源源不断的收到服务器传来的RTP 包了。
4、最后
通过Live555的学习可以搭建简单的RTSP服务器和客户端播放器,理解Live555的基本流程和原理。本文只是简单的介绍,Live555的功能很强大,支持的协议很多,支持的多媒体流构建的视频播放器非常强大,值得相关开发人员去深入学习。