QTSS源代码分析
1.系统结构和流程图
1.1系统结构
图1 Apple给的服务器架构
1.1.1DSS服务器是一个多线程的架构
核心服务器的作用是充当网络客户和服务器模块的接口,其中网络客户使用RTP和RTSP协议来发送请求和接收响应,而服务器模块则负责处理请求和向客户端发送数据包。核心服务器通过创建四种类型的线程来完成自己的工作,具体如下:
(1)服务器自己拥有的主线程(Main Thread)。这个线程负责检查服务器是否需要关闭,记录状态信息,或者打印统计信息。
(2)空闲任务线程(Idle Task Thread)。空闲任务线程管理一个周期性的任务队列。该任务队列有两种类型:超时任务和套接口任务。
(3)事件线程(Event Thread)。事件线程负责侦听套接口事件,比如收到RTSP请求和RTP数据包,然后把事件传递给任务线程。
(4)一个或者多个任务(Task)线程。任务线程从事件线程中接收RTSP和RTP请求,然后把请求传递到恰当的服务器模块进行处理,把数据包发送给客户端。缺省情况下,核心服务器为每一个处理器创建一个任务线程。
每一个Task对象都有两个主要的方法:即Signal和Run。服务器调用Signal方法来把一个事件发送给Task对象,而Run方法则用来为Task对象指定处理事件的时机。信号机制使用的是同步信号灯机制而不是互斥锁。
1.2 服务器对象
图2 服务器对象数据模型
服务器对象中有一个预置信息字典。服务器内部有一个模块列表,列表中的每一个模块都有一个字典,用于存放自己的预置信息。服务器中还有一个RTP客户会话的列表,每一个会话都可能有一个RTSP会话以及一个或多个RTP媒体流。通过API来遍历服务器中所有活跃的会话和流是有可能的。
(1)QTServer是一个核心服务器对象,这个对象的一部分可以通过API和QTSServerInterface基类来进行访问。
(2)Dictionary是一种把键值对实现为对象数据的数据存储类。由API定义的所有服务器对象都是从这个基类继承下来的。
(3)Module是管理模块的类。每个模块的实例负责装载,初始化,以及执行一个静态或者动态的API模块。
(4)RTSP和RTP会话。流的读写是由会话通过一个流对象来管理的。RTSP会话在RTSPSession::Run方法中会调用每个模块中注册过的RTSP角色(Role)。被调用的API模块角色有QTSS_RTSPFilter_Role,QTSS_RTSPRoute_Role,QTSS_RTSPAuthenticate_Role, QTSS_RTSPAuthorize_Role,QTSS_RTSPPreProcessor_Role,QTSS_RTSPRequest_Role, QTSS_RTSPPostProcessor_Role,和QTSS_RTSPSessionClosingRole。RTSP会话还会调用注册为QTSS_RTSPIncomingData_Role角色的模块。RTP会话除了处理数据的读写之外,还调用下面的角色:QTSS_RTPSendPackets_Role,QTSS_RTCPProcess_Role,和QTSS_ClientSessionClosing_Role。
图3 更详细的服务器模块
1.3模块角色表
名称 | 常数 | 任务 |
Register(注册)角色 | QTSS_Register_Role | 注册模块支持的角色。 |
Initialize(初始化)角色 | QTSS_Initialize_Role | 执行模块的初始化任务。 |
Shutdown(关闭)角色 | QTSS_Shutdown_Role | 执行清除现场任务。 |
Reread Preferences(再次读取预置信息)角色 | QTSS_RereadPrefs_Role | 重新读取模块的预置信息。 |
Error Log(错误纪录)角色 | QTSS_ErrorLog_Role | 记录错误信息。 |
RTSP Filter(过滤器)角色 | QTSS_RTSPFilter_Role | 修改RTSP请求的内容。 |
RTSP Route(路由)角色 | QTSS_RTSPRoute_Role | 把来自客户端的请求路由到恰当的文件夹。 |
RTSP Preprocessor(预处理器)角色 | QTSS_RTSPPreProcessor_Role | 在服务器处理客户请求之前,先行进行处理。 |
RTSP Request(请求)角色 | QTSS_RTSPRequest_Role | 在没有其它角色处理客户请求的情况下,对客户请求进行处理 |
RTSP Postprocessor(后处理器)角色 | QTSS_RTSPPostProcessor_Role | 在请求得到响应之后,执行诸如纪录统计信息这样的任务。 |
RTP Send Packets(发送数据包)角色 | QTSS_RTPSendPackets_Role | 发送数据包。 |
Client Session Closing(客户会话关闭)角色 | QTSS_ClientSessionClosing_Role | 在客户会话关闭时执行任务。 |
RTCP Process(处理)角色 | QTSS_RTCPProcess_Role | 处理RTCP接受方的报告。 |
Open File Preprocess(打开文件预处理)角色 | QTSS_OpenFilePreProcess_Role | 处理打开文件的请求。 |
Open File(打开文件)角色 | QTSS_OpenFile_Role | 处理没有被Open File Preprocess角色处理过的打开文件请求。 |
Advise File(建议文件)角色 | QTSS_AdviseFile_Role | 在模块(或者服务器)调用RQTSS_Advise回调函数,获取文件对象的时候,进行响应。 |
Read File(读取文件)角色 | QTSS_ReadFile_Role | 读取文件。 |
Request Event File(请求事件文件)角色 | QTSS_RequestEventFile_Role | 客户端可能请求接收当文件变为可供读取时发出的通知,这个角色负责处理这些请求。 |
Close File(关闭文件)角色 | QTSS_CloseFile_Role | 关闭先前打开的文件。 |
1.4数据流图
图4 Socket数据通过RTSP会话对象的signal()方法,进入任务队列
图4 RTSP会话对象建立请求处理,调用RTP对象读取视频文件,然后调用SendPacket()方法把包发过去。