Rtsp流媒體服務(wù)器小結(jié)_第1頁(yè)
Rtsp流媒體服務(wù)器小結(jié)_第2頁(yè)
Rtsp流媒體服務(wù)器小結(jié)_第3頁(yè)
Rtsp流媒體服務(wù)器小結(jié)_第4頁(yè)
Rtsp流媒體服務(wù)器小結(jié)_第5頁(yè)
已閱讀5頁(yè),還剩8頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

DarwinStreamingServer流媒體服務(wù)器小結(jié)DarwinStreamingServer(簡(jiǎn)稱(chēng)DSS)是QuickTimeStreamingServer開(kāi)放式源代碼的版本,同時(shí)支持FreeBSD、Linux、Solaris、WindowsNT和Windows2000等多個(gè)操作系統(tǒng),是當(dāng)前所有同類(lèi)產(chǎn)品中支持平臺(tái)最多的一個(gè)。DSS源代碼完全采用標(biāo)準(zhǔn)C++語(yǔ)言寫(xiě)成,每個(gè)C++類(lèi)都對(duì)應(yīng)著一對(duì)和類(lèi)同名的.h/.cpp文件。整個(gè)服務(wù)器包括多個(gè)子系統(tǒng),分別存放在獨(dú)立的工程內(nèi),其中,最為重要的是基礎(chǔ)功能類(lèi)庫(kù)(CommonUtilitiesLib)和流化服務(wù)器(StreamingServer)兩個(gè)工程,前者是整個(gè)系統(tǒng)的通用代碼工具箱,包括了線程管理、數(shù)據(jù)結(jié)構(gòu)、網(wǎng)絡(luò)和文本分析等多個(gè)功能模塊。后者包含了DSS對(duì)多個(gè)國(guó)際標(biāo)準(zhǔn)的實(shí)現(xiàn),是整個(gè)服務(wù)器的主工程°DSS實(shí)現(xiàn)了四種IETF制定的國(guó)際標(biāo)準(zhǔn),分別是:實(shí)時(shí)流傳輸協(xié)議RTSP(Real-timeStreamingProtocol,RFC2326)、實(shí)時(shí)傳輸協(xié)議(RTPReal-timeTransferProtocol,RFC1889)、實(shí)時(shí)傳輸控制協(xié)議RTCP(Real-timeTransportControlProtocol,RFC1889)、會(huì)話描述協(xié)議SDP(SessionDescriptionProtocol,RFC2327)?;蛘叽蛴〗y(tǒng)計(jì)信息??臻e任務(wù)線程(IdleTaskthread):空閑任務(wù)線程管理一個(gè)周期性的任務(wù)隊(duì)列,該任務(wù)隊(duì)列有兩種類(lèi)型:超時(shí)任務(wù)和套接口任務(wù)。事件線程(Eventthread):事件線程負(fù)責(zé)偵聽(tīng)套接口事件,比如收到RTSP請(qǐng)求和RTP數(shù)據(jù)包,然后把事件傳遞給任務(wù)線程。一個(gè)或多個(gè)任務(wù)線程(Taskthreads):任務(wù)線程從事件線程中接收RTSP和RTP請(qǐng)求,然后把請(qǐng)求傳遞到恰當(dāng)?shù)姆?wù)器模塊進(jìn)行處理,把數(shù)據(jù)包發(fā)送給客戶(hù)端。?基礎(chǔ)功能類(lèi)庫(kù)(CommonUtilities)1.DarwinStreamingServer支持包括Windows,Linux以及Solaris在內(nèi)的多種操作系統(tǒng)平臺(tái)。我們知道,Windows和Unix(或Unix-like)操作系統(tǒng)之間無(wú)論從內(nèi)核還是編程接口上都有著本質(zhì)的區(qū)別,即使是Linux和Solaris,在編程接口上也大為不同。為此,DSS開(kāi)發(fā)了多個(gè)用于處理時(shí)間、臨界區(qū)、信號(hào)量、事件、互斥量和線程等操作系統(tǒng)相關(guān)的類(lèi),這些類(lèi)為上層提供了統(tǒng)一的使用接口,但在內(nèi)部卻需要針對(duì)不同的操作系統(tǒng)采用不同的方法實(shí)現(xiàn)。OSCond狀態(tài)變量的基本功能和操作,OSMutex互斥量的基本功能和操作,OSThread線程類(lèi),OSFileSource簡(jiǎn)單文件類(lèi),OSQueue隊(duì)列類(lèi),OSHashTable哈希表類(lèi),OSHeap堆類(lèi),OSRef參考引用類(lèi)。2.Task類(lèi),用來(lái)處理事件通知機(jī)制。在Task.h/cpp文件中,定義了三個(gè)主要的類(lèi),分別是:任務(wù)線程池類(lèi)(TaskThreadPoolClass)、任務(wù)線程類(lèi)(TaskThreadClass)以及任務(wù)類(lèi)(TaskClass)。每個(gè)Task對(duì)象有兩個(gè)主要的方法:Signal和Run。當(dāng)服務(wù)器希望發(fā)送一個(gè)事件給某個(gè)Task對(duì)象時(shí),就會(huì)調(diào)用Signal()方法;而Run()方法是在Task對(duì)象獲得處理該事件的時(shí)間片后運(yùn)行的,服務(wù)器中的大部分工作都是在不同Task對(duì)象的Run()函數(shù)中進(jìn)行的。每個(gè)Task對(duì)象的目標(biāo)就是利用很小的且不會(huì)阻塞的時(shí)間片完成服務(wù)器指定某個(gè)工作。任務(wù)線程類(lèi)(TaskThread)是OSThread類(lèi)的一個(gè)子類(lèi),代表專(zhuān)門(mén)用于運(yùn)行任務(wù)類(lèi)的一個(gè)線程。在每個(gè)任務(wù)線程對(duì)象內(nèi)部都有一個(gè)OSQueue_Blocking類(lèi)型的任務(wù)隊(duì)列,存儲(chǔ)該線程需要執(zhí)行的任務(wù)。服務(wù)器調(diào)用一個(gè)任務(wù)的Signal函數(shù),實(shí)際上就是將該任務(wù)加入到某個(gè)任務(wù)線程類(lèi)的任務(wù)隊(duì)列中去。另外,為了統(tǒng)一管理這些任務(wù)線程,DSS還開(kāi)發(fā)了任務(wù)線程池類(lèi),該類(lèi)負(fù)責(zé)生成、刪除以及維護(hù)內(nèi)部的任務(wù)線程列表。這種由事件去觸發(fā)任務(wù)的概念已經(jīng)被集成到了DSS的各個(gè)子系統(tǒng)中。例如,在DSS中經(jīng)常將一個(gè)Task對(duì)象和一個(gè)Socket對(duì)象關(guān)聯(lián)在一起,當(dāng)Socket對(duì)象收到事件(通過(guò)select()函數(shù)),相對(duì)應(yīng)的Task對(duì)象就會(huì)被傳信(通過(guò)Signal()函數(shù));而包含著處理代碼的Run()函數(shù)就將在某個(gè)任務(wù)線程中運(yùn)行。3.Socket類(lèi)DSS中的Socket類(lèi)一般都采用異步模式的(即非阻塞的),而且能夠向?qū)?yīng)的Task對(duì)象傳信(Signal),Socket類(lèi)中具有代表性的類(lèi)是:EventContext、EventThread、Socket、UDPSocket、TCPSocket以及TCPListenerSocket等等。在eventcontext.h/.cpp文件中,定義了兩個(gè)類(lèi):EventContext類(lèi)和EventThread類(lèi)。EventContext提供了檢測(cè)Unix式的文件描述符(Socket就是一種文件描述符)產(chǎn)生的事件(通常是EV_RE或EV_WR)的能力,同時(shí)還可以傳信指定的任務(wù)。EventThread類(lèi)是OSThread類(lèi)的子類(lèi),它本身很簡(jiǎn)單,只是重載了OSThread的純虛函數(shù)Entry(),用以監(jiān)控所有的Socket端口是否有數(shù)據(jù)到來(lái)。EventContext對(duì)象負(fù)責(zé)維護(hù)指定的描述符,其主要函數(shù)包括InitNonBlocking、CleanUp和RequestEvent等。其中InitNonBlocking函數(shù)調(diào)用SocketAPIioctlsocket將用戶(hù)指定的描述符設(shè)置為異步,CleanUp函數(shù)用于關(guān)閉該描述符;另外,用戶(hù)通過(guò)RequestEvent函數(shù)申請(qǐng)對(duì)該描述符中某些事件的監(jiān)聽(tīng)SocketClass、UDPSocketClass和TCPSocketClass三個(gè)類(lèi)都是EventContext的子類(lèi),它們封裝了TCP和UDP的部分實(shí)現(xiàn),同時(shí)擴(kuò)展了EventContext中的事件,但都沒(méi)有改變其運(yùn)行機(jī)制。TCPListenerSocket用于監(jiān)聽(tīng)TCP端口,當(dāng)一個(gè)新連接請(qǐng)求到達(dá)后,該類(lèi)將賦予這個(gè)新連接一個(gè)Socket對(duì)象和一個(gè)Task對(duì)象的配對(duì)。二.服務(wù)器模塊:處理網(wǎng)絡(luò)和協(xié)議。主要有3個(gè)子系統(tǒng):RTSP子系統(tǒng),RTP子系統(tǒng)以及公共服務(wù)子系統(tǒng)。服務(wù)器內(nèi)核:這個(gè)子系統(tǒng)中的類(lèi)都有一個(gè)QTSS前綴。QTSSServer負(fù)責(zé)處理服務(wù)器的啟動(dòng)和關(guān)閉。QTSSServerInterface負(fù)責(zé)保存服務(wù)器全局變量,以及收集服務(wù)器的各種統(tǒng)計(jì)信息。QTSSPrefs是存儲(chǔ)服務(wù)器偏好設(shè)定的地方。QTSSModule,QTSSModuleInterface,和QTSSCallbacks類(lèi)的唯一目的就是支持QTSS的模塊API。RTSP子系統(tǒng)負(fù)責(zé)解析和處理RTSP請(qǐng)求,以及實(shí)現(xiàn)QTSS模塊API的RTSP部分。其中的幾個(gè)類(lèi)直接對(duì)應(yīng)QTSSAPI的一些元素(例如,RTSPRequestInterface類(lèi)就是對(duì)應(yīng)QTSS_RTSPRequestObject對(duì)象)。每一個(gè)RTSP/TCP連接都對(duì)應(yīng)一個(gè)RTSP的session.主要的類(lèi)有RTSPSession,RTSPRequest,RTSPResponseStream和RTSPRequestStream.RTP子系統(tǒng)負(fù)責(zé)媒體數(shù)據(jù)包的發(fā)送,根據(jù)RTCP的反饋進(jìn)行服務(wù)質(zhì)量控制。主要的類(lèi)有RTPSession,RTPStream和RTCPTask.公共服務(wù)子系統(tǒng)負(fù)責(zé)服務(wù)器的啟動(dòng)/關(guān)閉,初始化參數(shù)設(shè)置以及為Module機(jī)制,跨平臺(tái)的多線程和事件機(jī)制等提供支持。DSS提供了一種稱(chēng)為Module的二次開(kāi)發(fā)接口。使用這個(gè)開(kāi)發(fā)接口,我們可以自由擴(kuò)張服務(wù)器的功能。DSS定義了一個(gè)TCPListenerSocket類(lèi)的子類(lèi)RTSPListenerSocket,用于監(jiān)聽(tīng)RTSP連接請(qǐng)求。RTSPListenerSocket類(lèi)做的唯一一件事就是重載了GetSessionTask函數(shù),當(dāng)客戶(hù)的連接請(qǐng)求到達(dá)后,它創(chuàng)建了一個(gè)Socket對(duì)象和RTSPSession對(duì)象的配對(duì)。RTSPSession對(duì)象是Task類(lèi)的子類(lèi),是專(zhuān)門(mén)用于處理RTSP請(qǐng)求的任務(wù)類(lèi)。當(dāng)client端發(fā)出Play請(qǐng)求時(shí),server端的RTSPListenerSocket監(jiān)聽(tīng)到這個(gè)請(qǐng)求,Run創(chuàng)建一個(gè)RTSPSession,這個(gè)RTSPSession被加入到任務(wù)隊(duì)列中,當(dāng)時(shí)間片到達(dá)時(shí),TaskThread線程就會(huì)調(diào)用RTSPSession對(duì)象的函數(shù),在Run函數(shù)中,維護(hù)一個(gè)RTSPSession狀態(tài)機(jī),對(duì)客戶(hù)的RTSP請(qǐng)求做出不同的處理。請(qǐng)求分析完成后,RTSPSession進(jìn)入請(qǐng)求處理狀態(tài)(kProcessingRequest),DSS會(huì)調(diào)用注冊(cè)了“請(qǐng)求處理任務(wù)”(QTSS_RTSTRequest_Role)的module,而QTSSFileModule就是這樣一個(gè)Module。QTSSFileModule定義了一個(gè)分發(fā)函數(shù)QTSSFileModuleDispatch,它根據(jù)傳入的任務(wù)類(lèi)別和任務(wù)參數(shù)調(diào)用相應(yīng)的函數(shù)。此時(shí)傳入的任務(wù)是QTSS_RTSTRequest_Role,相應(yīng)的處理函數(shù)是ProcessRTSPRequest,該函數(shù)根據(jù)傳入的RTSPMethod調(diào)用相應(yīng)的處理函數(shù),此時(shí)傳入的method是play,所以調(diào)用函數(shù)DoPlay。IdleTaskThread,它的Entry中不停的超時(shí)等待,查看它隊(duì)列中的task是否到期,是則調(diào)用該task->signal.IdleTask的SetIdleTimer()里面調(diào)用IdleTaskThread->SetIdleTimer()把該task加入它的fIdleHeap.程序的數(shù)據(jù)流程為四部分,就是:1,task。每個(gè)Task對(duì)象有兩個(gè)主要的方法:Signal和Run。當(dāng)服務(wù)器希望發(fā)送一個(gè)事件給某個(gè)Task對(duì)象時(shí),就會(huì)調(diào)用Signal()方法;而Run()方法是在Task對(duì)象獲得處理該事件的時(shí)間片后運(yùn)行的,應(yīng)用可以通過(guò)繼承Task并重寫(xiě)Run()方法實(shí)現(xiàn)自己的任務(wù)。2,EventContext事件的觸發(fā)者,當(dāng)事件發(fā)生時(shí),調(diào)用Task::signal().3,TaskThread,任務(wù)的驅(qū)動(dòng)線程,對(duì)一個(gè)或者多個(gè)Task進(jìn)行調(diào)度,通過(guò)調(diào)用Task::run()處理事件.4,EventThread,EventContext的驅(qū)動(dòng)線程,可以處理多個(gè)EventContext,發(fā)生事件時(shí)調(diào)用EventContext::process_event(),后者將調(diào)用Task::Signal()流程:1,Client或者Task的子類(lèi)向EventContext注冊(cè)事件。2,EventContext將事件放入EventThread的Pool內(nèi)。3,EventThread調(diào)用select等待多個(gè)事件中任一個(gè)觸發(fā)。4,事件觸發(fā)以后,EventThread調(diào)用EventContext::ProcessEvent()。5,調(diào)用Task::signal()。Task::signal()將task放入TaskThread的隊(duì)列。TaskThread調(diào)度相應(yīng)的Task,執(zhí)行其Run()方法。它的具體實(shí)現(xiàn)在各個(gè)Module中定義。DSS的基本功能單元稱(chēng)為模塊(module),每一個(gè)模塊都是處理某一類(lèi)事件的功能集合。例如QTSSAcessModule就是鑒權(quán)授權(quán)事件的主要處理模塊,類(lèi)似于桌面窗口的事件處理中的事件,DSS服務(wù)器核心處理RTSP請(qǐng)求,定義了若干角色(role),一個(gè)角色就是一項(xiàng)任務(wù),一個(gè)模塊可以注冊(cè)若干個(gè)角色,表示這個(gè)模塊可以處理這些注冊(cè)的任務(wù)。比如一個(gè)模塊注冊(cè)了QTSS_RSTPPreProcess_Role,則可以調(diào)用這個(gè)Module來(lái)預(yù)處理RSTP請(qǐng)求。根據(jù)不同的任務(wù),服務(wù)器會(huì)傳遞不同的對(duì)象給模塊,這些對(duì)象中包含有為完成這個(gè)任務(wù)所包含的一系列數(shù)據(jù)以及為向服務(wù)器傳遞信息而存在的數(shù)據(jù)結(jié)構(gòu)。Darwinstreamingserver的媒體存儲(chǔ)格式hinttrack格式以及被ISO,ISMA等標(biāo)準(zhǔn)組織采納并成為正式標(biāo)準(zhǔn)。Hinttrack是Darwinstreamingserver的擴(kuò)展,通過(guò)在媒體文件中增加hinttrack軌道,存放了一些預(yù)先生成好的媒體描述信息(SDP格式)和媒體數(shù)據(jù)打包的索引信息。通過(guò)ISMA傳輸協(xié)議進(jìn)行傳輸時(shí),可以直接根據(jù)數(shù)據(jù)打包索引信息來(lái)打包發(fā)送,不需要對(duì)信息進(jìn)行重復(fù)的分析格式組裝數(shù)據(jù)包的處理過(guò)程。普通文件可以通過(guò)一些工具添加hinttrack屬性。開(kāi)源的工具有mpeg4ip,mp4info.RTSP數(shù)據(jù)處理

nServerparsestherequestNp>DoneServercallsmodulesregisleredforRTSPPreprocessorroleServercallsmoddiesregisleredforRTSPPostpraces$cxroleSevercallsniaduleregisteredforRTSPRequestrolyServerreceivesanRTSPrequestServercansmodulesregisteredhrRTSPRouteroleServercallsmodulesregisteredforRTSPFilterroleYesX.nServerparsestherequestNp>DoneServercallsmodulesregisleredforRTSPPreprocessorroleServercallsmoddiesregisleredforRTSPPostpraces$cxroleSevercallsniaduleregisteredforRTSPRequestrolyServerreceivesanRTSPrequestServercansmodulesregisteredhrRTSPRouteroleServercallsmodulesregisteredforRTSPFilterroleYesX...、No/Didanodule—^respondtothe—\client?y*c>idamodiie\?^e5respondtothe》\client?/^/Dldamodule*—irespondtotlie\client?J首先經(jīng)由“RTSPFilterRole”對(duì)封包資料做某些改變等前置處理。當(dāng)RTSPFilterRole完成,開(kāi)始進(jìn)行對(duì)該請(qǐng)求封包的分析以取得各種參數(shù)并建立一個(gè)RTSPsession及一個(gè)Clientsession.RTSPsession主要負(fù)責(zé)處理此一請(qǐng)求所建立的RTSP連線階段的請(qǐng)求/回應(yīng)。Clientsession則負(fù)責(zé)串流傳送階段的維護(hù)工作。對(duì)該請(qǐng)求分析完畢后,server呼叫各模塊中的”RTSPRouteRole”對(duì)RTSP對(duì)象進(jìn)行參數(shù)修改和設(shè)定。他可以改變文件的處理目錄。接著呼叫”P(pán)reprocessorRole”判斷該請(qǐng)求屬于RTSP圭寸包中的哪一種類(lèi)型,以便把該請(qǐng)求傳送到對(duì)應(yīng)的函數(shù)處理此一請(qǐng)求,若無(wú)法判別屬于哪一類(lèi)型,則將其傳送到”RTSPRequestRole”,此一角色處理所有在”P(pán)reprocessorRole"中未定義的類(lèi)型。

最后,來(lái)到“PostprocessorRole”,此角色負(fù)責(zé)統(tǒng)計(jì)的工作,例如存取記錄等。在處理”P(pán)reporcessorRole"或是“RTSPRequestRole"中的各模塊時(shí),可能會(huì)產(chǎn)生串流媒體資料。需要產(chǎn)生媒體資料時(shí),程式會(huì)呼叫Clientsession中的“QTSS_Play”物件,此物件會(huì)觸發(fā)在“RTPSendPacketsRole”中的各個(gè)模塊,同時(shí)進(jìn)入RTPsubsystem中。RTPsubsystem:RTPsubsystem主要包括RTP封包傳送及RTCP串流控制兩部份。在封包傳送方面,“RTPSendPacketsRole”在RTPsession中經(jīng)由呼叫“QTSS_Write”或“QTSS_WriteV”把媒體資料傳送到客戶(hù)端。在傳送過(guò)程中,每送一次封包后,Server等待一個(gè)時(shí)間值再繼續(xù)呼叫”RTPSendPacketsRole"傳送封包。在串流控制方面,當(dāng)Server接收到RTCP封包時(shí)會(huì)先判定此RTCP封包屬于哪一種封包,RFC1889中定義了五種RTCP封包,分別是:SR(Sourcedescription),RR(Receiverdescription),SDES(SourceDescriptionItems,includeitems),APP(Applicationspecificfunctions)及BYE。根據(jù)封包的種類(lèi),Server會(huì)呼叫“RTCPProcessRole”中相應(yīng)的模塊進(jìn)行處理。一個(gè)clientSession對(duì)應(yīng)多個(gè)rtpstream.passingAuthenticationmeans"youareavaliduserofthesystem".Itdoesnotmean"youhaveaccesstotherequestedfile".Authorizationistheotherhalf,whichistheprocessofallowingtheuseraccesstotherequestedcontent.rtspSession的流程:當(dāng)client端發(fā)出Play請(qǐng)求時(shí),server端的RTSPListenerSocket監(jiān)聽(tīng)到這個(gè)請(qǐng)求,Run在GetSessionTask()函數(shù)中創(chuàng)建一個(gè)RTSPSession,這個(gè)RTSPSession被加入到任務(wù)隊(duì)列中,當(dāng)signal通知數(shù)據(jù)到達(dá)時(shí),TaskThread線程就會(huì)調(diào)用RTSPSession對(duì)象的函數(shù),在Run函數(shù)中,維護(hù)一個(gè)RTSPSession狀態(tài)機(jī),對(duì)客戶(hù)的RTSP請(qǐng)求做出不同的處理。rtspSession的run函數(shù)中,casekReadingFirstRequest:initializedvaluedfInputStream.ReadRequest()讀取數(shù)據(jù)if(err==QTSS_RequestArrived)fState=kHTTPFilteringRequest;casekHTTPFilteringRequest:fState=kHaveNonTunnelMessage;casekReadingRequest:if((err=fInputStream.ReadRequest())==QTSS_NoErr)?fState=kHaveNonTunnelMessage;casekHaveNonTunnelMessage:fRequest=NEWRTSPRequest(this);fState=kFilteringRequest;casekFilteringRequest:this->SetupRequest();//setuprtpSessionRTSPRequest::Parse()if(fRTPSession==NULL)theErr=this->CreateNewRTPSession(theMap);fState=kRoutingRequest;casekRoutingRequest:if(fRequest->SkipAuthorization())fState=kPreprocessingRequest;casekPreprocessingRequest:theModule=QTSServerInterface::GetModule(QTSSModule::kRTSPPreProcessorRole,fCurrentModule);(void)theModule->CallDispatch(QTSS_RTSPPreProcessor_Role,&fRoleParams);fModuleState.isGlobalLocked=false;在reflectorModule模塊中ProcessRTSPRequest()處理if(*theMethod==qtssAnnounceMethod)

returnDoAnnounce(inParams);if(*theMethod==qtssDescribeMethod)returnDoDescribe(inParams);if(*theMethod==qtssSetupMethod)returnDoSetup(inParams);caseqtssPlayMethod:returnDoPlay(inParams,(*theOutput)->GetReflectorSession());fState=kProcessingRequest;if(fRequest->HasResponseBeenSent()){fState=kPostProcessingRequest;break;}casekPostProcessingRequest:fState=kSendingResponse;casekSendingResponse:fState=kCleaningUp;casekCleaningUp:this->CleanupRequest();fState=kReadingRequest;在client啟動(dòng)播放時(shí),先建立rtspSession,然后進(jìn)入run(),讀了一個(gè)請(qǐng)求后,調(diào)用setupRequest,然后,clearupRequest.循環(huán)直到return出run()的while(true)函數(shù)。在setupRequest的FindRTPSession中,會(huì)去給fRTPSession賦值。所以在cleanupRequest中把它置為NULL。三.關(guān)鍵模塊分析直播模塊結(jié)構(gòu)分析:ReflectorSocket:publicIdleTask,publicUDPSocketGetlncomingData()負(fù)責(zé)接收數(shù)據(jù)ProcessPacket(),負(fù)責(zé)把數(shù)據(jù)包填入ReflectorSender的OSQueue。ReflectorSocketPool:UDPSocketPair*ReflectorSocketPool::ConstructUDPSocketPair(){returnNEWUDPSocketPair(NEWReflectorSocket(),NEWReflectorSocket());}ReflectorSender:publicUDPDemuxerTaskReflectPackets()從它的ReflectorStream中找到ReflectorOutput,調(diào)用SendPacketsToOutput(),里面調(diào)用WritePacket()ReflectorOutput*theOutput=fStream->fOutputArray[bucketIndex][bucketMemberIndex];classRTPSessionOutput:publicReflectorOutputRTPSessionOutput::WritePacket(){由它的RTPSessionfClientSession找出對(duì)應(yīng)的RTPStream,RTPStream的fCookieAttrID=sStreamCookieAttr屬性記錄的是它對(duì)應(yīng)的reflectorStream.判斷該rtpStream對(duì)應(yīng)的reflectorStream是否就是調(diào)用方的這個(gè)fstream.QTSS_Write(*theStreamPtr,&thePacket,..)theStreamPtr為RTPStream}ReflectorStream:ThisobjectsupportsreflectinganRTPmulticaststreamtoNRTPStreams.BindSockets()用來(lái)把reflectorSocket和reflectorSender聯(lián)系起來(lái)((ReflectorSocket*)fSockets->GetSocketA())->AddSender(&fRTPSender);((ReflectorSocket*)fSockets->GetSocketB())->AddSender(&fRTCPSender);UDPSocketPair*fSockets;ReflectorSenderfRTPSender;ReflectorSenderfRTCPSender;fOutputArray,記錄RTPSessionOutput信息,typedefReflectorOutput**Bucket;Bucket*fOutputArray;在它的構(gòu)造函數(shù)中指定了fRTPSender.fStream=this;fRTCPSender.fStream=this;在同時(shí)開(kāi)啟多個(gè)窗口播放同一個(gè)sdp文件時(shí),都是使用同一個(gè)ReflectorSession對(duì)象,F(xiàn)indOrCreateSession也不會(huì)調(diào)用SetupReflectorSession函數(shù),即ReflectorStream、ReflectorSocket等對(duì)象也不會(huì)被再次創(chuàng)建。注意對(duì)于一個(gè)新的播放鏈接來(lái)說(shuō)RTSPSession、RTPSession都是新創(chuàng)建的對(duì)象,所以需要重新創(chuàng)建RTPSessionOutput^象。在QTSSReflectorModule.cpp的DoSetup()函數(shù)中,由DoSessionSetup進(jìn)入FindOrCtreateSession(),建立出ReflectorSession,里面創(chuàng)建ReflectorStream,綁定它對(duì)于的ReflectorSocket.ReflectorSession*FindOrCreateSession{ReflectorSession*theSessiontheSession=NEWReflectorSession(inPath);Sourceinfo通過(guò)讀取sdp文件,對(duì)應(yīng)ffmpeg輸出的rtp流。theSession->SetupReflectorSession(theInfo,inParams,theSetupFlag,sOneSSRCPerStream,sTimeoutSSRCSecs);該函數(shù)里面:fStreamArray=NEWReflectorStream*[fSourceInfo->GetNumStreams()];for(UInt32x=0;x<fSourceInfo->GetNumStreams();x++)fStreamArray[x]=NEWReflectorStream(fSourceInfo->GetStreamInfo(x));fStreamArray[x]->BindSockets(inParams,inFlags,filterState,filterTimeout);}doSetup()中建立outPut和rtpSession,reflectorSession的關(guān)系。RTPSessionOutput*theNewOutput=NEWRTPSessionOutput(inParams->inClientSession,theSession,sServerPrefs,sStreamCookieAttr);theSession類(lèi)型為ReflectorSession.theSession->AddOutput(theNewOutput,true);(void)QTSS_SetValue(inParams->inClientSession,sOutputAttr,0,&theNewOutput,sizeof(theNewOutput));theErr=QTSS_AddRTPStream(inParams->inClientSession,inParams->inRTSPRequest,&newStream,0);該函數(shù)中*outStream=NEWRTPStream(theSSRC,this);QTSS_ErrortheErr=(*outStream)->Setup(request,inFlags);建立該rtpStream和client的socket聯(lián)系。//Placethestreamcookieinthisstreamforfuturereferencevoid*theStreamCookie=theSession->GetStreamCookie(theTrackID);theStreamCookie為reflectorStream.theErr=QTSS_SetValue(newStream,sStreamCookieAttr,0,&theStreamCookie,sizeof(theStreamCookie));RTPStream類(lèi)有的屬性有:UDPSocketPair*fSockets;RTPSessionInterface*fSession;在ReflectorStream::PushPacket中,把packet拷貝到reflectorSocket,調(diào)用ProcessPacket//FindtheappropriateReflectorSenderforthispacket.ReflectorSender*theSender=(ReflectorSender*)this->GetDemuxer()->GetTask(theRemoteAddr,0);theSender->fPacketQueue.EnQueue(&thePacket->fQueueElem);在ReflectorStream.cpp的ReflectorSocket::Run()中調(diào)用GetlncomingData()和ReflectPackets()收發(fā)包。ReflectorSender->由reflectStream找到ReflectorOutput->從他對(duì)應(yīng)的rtpSession找到rtpStream,判斷該rtpStream對(duì)應(yīng)的reflectorStream是否就是調(diào)用方的這個(gè)fstream.是則調(diào)用該rtpStream的write函數(shù)發(fā)送數(shù)據(jù)包。播放一下,馬上出錯(cuò)原因是,在請(qǐng)求sdp文件失敗返回后,調(diào)用了fileModule的doDescribe,返回出錯(cuò),再調(diào)用QTSS_Teardown,銷(xiāo)毀rtpSession.Signal(killEvent),在它的~RTPSessionInterface()中調(diào)用RTSPSession的DecrementObjectHolderCount()的signal(killEvent),刪除rtspSession.Udpsocket句柄釋放在eventSocket的虛構(gòu)函數(shù)中close.點(diǎn)播模塊分析RTPSession:Run()有(void)fModule->CallDispatch(QTSS_RTPSendPackets_Role,&theParams);它調(diào)用QTSSFileModuleDispatch的SendPackets(),RTSPSession:Run()有CasekProcessingRequest:(void)theModule->CallDispatch(QTSS_RTSPRequest_Role,&fRoleParams);調(diào)用ProcessRTSPRequest().QTSServer.cpp中定義好了sCallbacks.addr[]=(QTSS_Callback)QTSS_APIFileSession:里面有QTRTPFilefFile;SDPSourceInfofSDPSource;FileSession中fFile類(lèi)型為QTRTPFile,在DoDescribe函數(shù)中,調(diào)用CreateQTRTPFile()函數(shù),根據(jù)inPath,*outFile二NewFileSession(),并(*outFile)->fFile.Initialize(inPath)FileSession類(lèi)中,主要結(jié)構(gòu)有QTRTPFilefFile;fAdjustedPlayTime;QTSS_PacketStructfPacketStruct;

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論