概要
Darwin Streaming Server簡(jiǎn)稱(chēng)DSS二拐。DSS是Apple公司提供的開(kāi)源實(shí)時(shí)流媒體播放服務(wù)器程序(QuickTime Streaming Server開(kāi)源版本)。整個(gè)程序使用C++編寫(xiě)凳兵,在設(shè)計(jì)上遵循高性能百新,簡(jiǎn)單,模塊化等程序設(shè)計(jì)原則庐扫,務(wù)求做到程序高效饭望,可擴(kuò)充性好仗哨。并且DSS是一個(gè)開(kāi)放源代碼的,基于標(biāo)準(zhǔn)的流媒體服務(wù)器铅辞,可以運(yùn)行在Windows NT和Windows 2000厌漂,以及幾個(gè)UNIX實(shí)現(xiàn)上,包括Mac OS X斟珊,Linux苇倡,F(xiàn)reeBSD,和Solaris操作系統(tǒng)上的囤踩。
特性
支持MP4旨椒、3GPP等文件格式;
支持MPEG-4堵漱、H.264等視頻編解碼格式综慎;
支持RTSP流控協(xié)議,支持HTTP協(xié)議勤庐;
支持RTP流媒體傳輸協(xié)議示惊;
支持單播和組播;
支持基于Web的管理愉镰;
具有完備的日志功能米罚。
此外,該服務(wù)器版本提供了一個(gè)基于模塊的擴(kuò)展方法岛杀。利用DSS提供的API就可以很方便地編寫(xiě)靜態(tài)或動(dòng)態(tài)的模塊,對(duì)DSS進(jìn)行擴(kuò)展崭孤,使其支持其它文件格式类嗤、協(xié)議或者功能。
框架
核心服務(wù)器通過(guò)創(chuàng)建四種類(lèi)型的線(xiàn)程來(lái)完成自己的工作辨宠,具體如下:
- 服務(wù)器自己擁有的主線(xiàn)程(Main Thread)遗锣。這個(gè)線(xiàn)程負(fù)責(zé)檢查服務(wù)器是否需要關(guān)閉,記錄狀態(tài)信息嗤形,或者打印統(tǒng)計(jì)信息精偿。
- 空閑任務(wù)線(xiàn)程(Idle Task Thread)「潮空閑任務(wù)線(xiàn)程管理一個(gè)周期性的任務(wù)隊(duì)列笔咽。該任務(wù)隊(duì)列有兩種類(lèi)型:超時(shí)任務(wù)和套接口任務(wù)。
- 事件線(xiàn)程(Event Thread)霹期。事件線(xiàn)程負(fù)責(zé)偵聽(tīng)套接口事件叶组,比如收到RTSP請(qǐng)求和RTP數(shù)據(jù)包,然后把事件傳遞給任務(wù)線(xiàn)程历造。
- 一個(gè)或者多個(gè)任務(wù)(Task)線(xiàn)程甩十。任務(wù)線(xiàn)程從事件線(xiàn)程中接收RTSP和RTP請(qǐng)求船庇,然后把請(qǐng)求傳遞到恰當(dāng)?shù)姆?wù)器模塊進(jìn)行處理,把數(shù)據(jù)包發(fā)送給客戶(hù)端侣监。缺省情況下鸭轮,核心服務(wù)器為每一個(gè)處理器創(chuàng)建一個(gè)任務(wù)線(xiàn)程。
模塊
媒體服務(wù)器使用模塊來(lái)響應(yīng)各種請(qǐng)求及完成任務(wù)橄霉。有三種類(lèi)型的模塊:
- 內(nèi)容管理模塊
內(nèi)容管理模塊負(fù)責(zé)管理與媒體源相關(guān)的RTSP請(qǐng)求和響應(yīng)窃爷,比如一個(gè)文件或者一個(gè)廣播。每個(gè)模塊負(fù)責(zé)解釋客戶(hù)的請(qǐng)求酪劫,讀取和解析它們的支持文件或者網(wǎng)絡(luò)源吞鸭,并且以RTSP和RTP的方式進(jìn)行響應(yīng)。在某些情況下覆糟,比如流化mp3的模塊刻剥,使用的則是HTTP。
QTSSFileModule滩字,QTSSReflectorModule造虏,QTSSRelayModule,和QTSSMP3StreamingModule都是內(nèi)容管理模塊麦箍。
2.服務(wù)器支持模塊
服務(wù)器支持模塊執(zhí)行服務(wù)器數(shù)據(jù)的收集和記錄功能漓藕。服務(wù)器模塊包括QTSSErrorLogModule, QTSSAccessLogModule挟裂,QTSSWebStatsModule享钞,QTSSWebDebugModule, QTSSAdminModule诀蓉,和QTSSPOSIXFileSystemModule栗竖。
3.訪(fǎng)問(wèn)控制模塊
訪(fǎng)問(wèn)控制模塊提供鑒權(quán)和授權(quán)功能,以及操作URL路徑提供支持渠啤。
訪(fǎng)問(wèn)控制模塊包括QTSSAccessModule狐肢,QTSSHomeDirectoryModule,QTSSHttpFileModule沥曹,和QTSSSpamDefenseModule份名。
數(shù)據(jù)
當(dāng)一個(gè)模塊需要訪(fǎng)問(wèn)客戶(hù)請(qǐng)求的RTSP報(bào)頭時(shí),可以通過(guò)QTSS.h這個(gè)API頭文件中定義的請(qǐng)求對(duì)象來(lái)訪(fǎng)問(wèn)相應(yīng)的請(qǐng)求信息妓美。舉例來(lái)說(shuō)僵腺,RTSPRequestInterface類(lèi)實(shí)現(xiàn)了API字典元素,這些元素可以通過(guò)API來(lái)進(jìn)行訪(fǎng)問(wèn)壶栋。名稱(chēng)是以“Interface”結(jié)尾的對(duì)象想邦,比如RTSPRequestInterface,RTSPSessionInterface委刘,和QTSServerInterface丧没,則用于實(shí)現(xiàn)模塊的API鹰椒。
下面是重要的接口類(lèi):
- QTSServerInterface — 這是內(nèi)部數(shù)據(jù)的存儲(chǔ)對(duì)象,在A(yíng)PI中標(biāo)識(shí)為QTSS_ServerObject呕童。在A(yíng)PI中的每一個(gè)QTSS_ServerAttributes都在基類(lèi)中聲明和實(shí)現(xiàn)漆际。
- RTSPSessionInterace — 這是內(nèi)部數(shù)據(jù)的存儲(chǔ)對(duì)象,在A(yíng)PI中標(biāo)識(shí)為qtssRTSPSessionObjectType夺饲。在A(yíng)PI中的每一個(gè)QTSS_RTSPSessionAttributes都在基類(lèi)中聲明和實(shí)現(xiàn)奸汇。
- RTPSessionInterface — 這是內(nèi)部數(shù)據(jù)的存儲(chǔ)對(duì)象,在A(yíng)PI中標(biāo)識(shí)為QTSS_ClientSessionObject往声。在A(yíng)PI中的每一個(gè)QTSS_ClientSessionAttributes都在基類(lèi)中聲明和實(shí)現(xiàn)擂找。
- RTSPRequestInterface — 這是內(nèi)部數(shù)據(jù)的存儲(chǔ)對(duì)象,在A(yíng)PI中標(biāo)識(shí)為QTSS_RTSPRequestObject浩销。在A(yíng)PI中的每一個(gè)QTSS_RTSPRequestAttributes都在基類(lèi)中聲明和實(shí)現(xiàn)贯涎。
源代碼的組織
Server.tproj
這個(gè)目錄包含核心服務(wù)器(core server)的代碼,可以分成三個(gè)子系統(tǒng):
- 服務(wù)器內(nèi)核慢洋。這個(gè)子系統(tǒng)中的類(lèi)都有一個(gè)QTSS前綴塘雳。QTSServer負(fù)責(zé)處理服務(wù)器的啟動(dòng)和關(guān)閉。QTSServerInterface負(fù)責(zé)保存服務(wù)器全局變量普筹,以及收集服務(wù)器的各種統(tǒng)計(jì)信息败明。QTSSPrefs是存儲(chǔ)服務(wù)器偏好設(shè)定的地方。QTSSModule太防,QTSSModuleInterface妻顶,和QTSSCallbacks類(lèi)的唯一目的就是支持QTSS的模塊API。
- RTSP子系統(tǒng)蜒车。這些類(lèi)負(fù)責(zé)解析和處理RTSP請(qǐng)求讳嘱,以及實(shí)現(xiàn)QTSS模塊API的RTSP部分。其中的幾個(gè)類(lèi)直接對(duì)應(yīng)QTSS API的一些元素(比如醇王,RTSPRequestInterface類(lèi)就是對(duì)應(yīng)于QTSS_RTSPRequestObject對(duì)象)呢燥。每個(gè)RTSP TCP連接都有一個(gè)RTSP會(huì)話(huà)對(duì)象與之相對(duì)應(yīng)崭添。RTSPSession對(duì)象是一個(gè)Task對(duì)象寓娩,負(fù)責(zé)處理與RTSP相關(guān)的事件。
- RTP子系統(tǒng)呼渣。這些類(lèi)處理媒體數(shù)據(jù)的發(fā)送棘伴。RTPSession對(duì)象包含與所有RTSP會(huì)話(huà)ID相關(guān)聯(lián)的數(shù)據(jù)。每個(gè)RTPSession都是一個(gè)Task對(duì)象屁置,可以接受核心服務(wù)器的調(diào)度來(lái)進(jìn)行RTP數(shù)據(jù)包的發(fā)送焊夸。RTPStream對(duì)象代表一個(gè)單獨(dú)的RTP流,一個(gè)RTPSession對(duì)象可以和任何數(shù)目的RTPStream對(duì)象相關(guān)聯(lián)蓝角。這兩個(gè)對(duì)象實(shí)現(xiàn)了QTSS模塊API中的針對(duì)RTP的部分阱穗。
CommonUtilitiesLib
這個(gè)目錄含有一個(gè)工具箱饭冬,包括線(xiàn)程管理,數(shù)據(jù)結(jié)構(gòu)揪阶,網(wǎng)絡(luò)昌抠,和文本解析工具。Darwin流媒體服務(wù)器及其相關(guān)工具通過(guò)這些類(lèi)對(duì)類(lèi)似或者相同的任務(wù)進(jìn)行抽象鲁僚,以減少重復(fù)代碼炊苫;這些類(lèi)的封裝簡(jiǎn)化了較高層次的代碼;借助這些類(lèi)還分離了專(zhuān)用于不同平臺(tái)的代碼冰沙。下面是對(duì)目錄下的各個(gè)類(lèi)的簡(jiǎn)短描述:
- OS類(lèi)侨艾。這些類(lèi)在時(shí)間,條件變量拓挥,互斥鎖唠梨,和線(xiàn)程方面提供了專(zhuān)用于不同平臺(tái)的代碼抽象。這些類(lèi)包括OS撞叽,OSCond姻成,OSMutex,OSThread愿棋,和OSFileSource科展;數(shù)據(jù)結(jié)構(gòu)則包括OSQueue,OSHashTable糠雨,OSHeap才睹,和OSRef。
- 套接口類(lèi)(Sockets)甘邀。這些類(lèi)為T(mén)CP和UDP網(wǎng)絡(luò)通訊方面提供了專(zhuān)用于不同平臺(tái)的代碼抽象琅攘。通常情況下,套接口類(lèi)是異步的(或者說(shuō)是非阻塞的)松邪,可以發(fā)送事件給Task對(duì)象坞琴。這些類(lèi)有:EventContext,Socket逗抑,UDPSocket剧辐,UDPDemuxer,UDPSocketPool邮府,TCPSocket荧关,和TCPListenerSocket。
- 解析工具褂傀。這些類(lèi)負(fù)責(zé)解析和格式化文本忍啤。包括StringParser,StringFormatter仙辟,StrPtrLen同波,和StringTranslator鳄梅。
- Task(任務(wù)):這些類(lèi)實(shí)現(xiàn)了服務(wù)器的異步事件機(jī)制。
QTFileLib
流媒體服務(wù)器的一個(gè)主要特性就是它能夠?qū)⑺饕瓿桑╤inted)的QuickTime電影文件通過(guò)RTSP和RTP協(xié)議提供給客戶(hù)未檩。這個(gè)目錄包含QTFile庫(kù)的源代碼卫枝,包括負(fù)責(zé)解析索引完成的QuickTime文件的代碼。服務(wù)器的RTPFileModule通過(guò)調(diào)用QTFile庫(kù)來(lái)從索引過(guò)的QuickTime文件中取得數(shù)據(jù)包和元數(shù)據(jù)讹挎。QTFile庫(kù)可以解析下面幾種文件類(lèi)型:.mov校赤,.mp4(.mov的一種修改版本),和.3gpp(.mov的一種修改版本)筒溃。
APICommonCode
這個(gè)目錄包含與API相關(guān)的類(lèi)的源代碼马篮,比如moduletils,或者諸如記錄文件的管理這樣的公共模塊函數(shù)怜奖。
APIModules
這個(gè)目錄包含流媒體服務(wù)器模塊目錄浑测,每個(gè)模塊都有一個(gè)目錄。
RTSPClientLib
這個(gè)目錄包含實(shí)現(xiàn)RTSP客戶(hù)端的源代碼歪玲,這些代碼可以用于連接服務(wù)器迁央,只要該連接協(xié)議被支持。
RTCPUtilitiesLib
這個(gè)目錄包含解析RTCP請(qǐng)求的源代碼滥崩。
APIStubLib
這個(gè)目錄包含API的定義和支持文件岖圈。
HTTPUtilitiesLib
這個(gè)目錄包含解析HTTP請(qǐng)求的源代碼。
二次開(kāi)發(fā)模塊添加的要求
每個(gè)DSS模塊必須實(shí)現(xiàn)兩個(gè)函數(shù):一個(gè)是Main函數(shù)钙皮,服務(wù)器在啟動(dòng)時(shí)將調(diào)用這個(gè)函數(shù)進(jìn)行必要的初始化蜂科。另一個(gè)是Dispatch函數(shù),通過(guò)實(shí)現(xiàn)此函數(shù)短条,服務(wù)器可調(diào)用DSS模塊并完成特定處理导匣。對(duì)于編譯到服務(wù)器里面的模塊,其主函數(shù)的地址必須傳遞到服務(wù)器的模塊Main函數(shù)中茸时。
具體實(shí)現(xiàn)時(shí)贡定,Main函數(shù)必須命名為MyModule_Main,其中MyModule是模塊的文件名可都。此函數(shù)的實(shí)現(xiàn)通常如下所示:
QTSS_Error MyModule_Main(void* inPrivateArgs)
{
return _stublibrary_main(inPrivateArgs, MyModuleDispatch);
}
每個(gè)DSS模塊都必須提供一個(gè)Dispatch函數(shù)缓待。服務(wù)器為了特定的目的需要使用某個(gè)模塊時(shí),是通過(guò)調(diào)用該模塊的Dispatch函數(shù)來(lái)實(shí)現(xiàn)的汹粤,調(diào)用時(shí)必須將任務(wù)的名稱(chēng)及相應(yīng)的參數(shù)傳遞給該函數(shù)命斧。在DSS中田晚,使用角色(Role)這個(gè)術(shù)語(yǔ)來(lái)描述特定的任務(wù)嘱兼。Dispatch函數(shù)的格式如下所示:
void MyModuleDispatch(QTSS_Role inRole,QTSS_RoleParamPtr inParams)贤徒;
其中MyModuleDispatch是Dispatch函數(shù)的名稱(chēng)芹壕;MyModule是模塊的文件名汇四;inRole是角色的名稱(chēng),只有注冊(cè)了該角色的模塊才會(huì)被調(diào)用踢涌;inParams則是一個(gè)結(jié)構(gòu)體通孽,可用于傳遞相應(yīng)的參數(shù)。