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

下載本文檔

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

文檔簡介

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

最后,來到“PostprocessorRole”,此角色負責統(tǒng)計的工作,例如存取記錄等。在處理”PreporcessorRole"或是“RTSPRequestRole"中的各模塊時,可能會產(chǎn)生串流媒體資料。需要產(chǎn)生媒體資料時,程式會呼叫Clientsession中的“QTSS_Play”物件,此物件會觸發(fā)在“RTPSendPacketsRole”中的各個模塊,同時進入RTPsubsystem中。RTPsubsystem:RTPsubsystem主要包括RTP封包傳送及RTCP串流控制兩部份。在封包傳送方面,“RTPSendPacketsRole”在RTPsession中經(jīng)由呼叫“QTSS_Write”或“QTSS_WriteV”把媒體資料傳送到客戶端。在傳送過程中,每送一次封包后,Server等待一個時間值再繼續(xù)呼叫”RTPSendPacketsRole"傳送封包。在串流控制方面,當Server接收到RTCP封包時會先判定此RTCP封包屬于哪一種封包,RFC1889中定義了五種RTCP封包,分別是:SR(Sourcedescription),RR(Receiverdescription),SDES(SourceDescriptionItems,includeitems),APP(Applicationspecificfunctions)及BYE。根據(jù)封包的種類,Server會呼叫“RTCPProcessRole”中相應(yīng)的模塊進行處理。一個clientSession對應(yīng)多個rtpstream.passingAuthenticationmeans"youareavaliduserofthesystem".Itdoesnotmean"youhaveaccesstotherequestedfile".Authorizationistheotherhalf,whichistheprocessofallowingtheuseraccesstotherequestedcontent.rtspSession的流程:當client端發(fā)出Play請求時,server端的RTSPListenerSocket監(jiān)聽到這個請求,Run在GetSessionTask()函數(shù)中創(chuàng)建一個RTSPSession,這個RTSPSession被加入到任務(wù)隊列中,當signal通知數(shù)據(jù)到達時,TaskThread線程就會調(diào)用RTSPSession對象的函數(shù),在Run函數(shù)中,維護一個RTSPSession狀態(tài)機,對客戶的RTSP請求做出不同的處理。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啟動播放時,先建立rtspSession,然后進入run(),讀了一個請求后,調(diào)用setupRequest,然后,clearupRequest.循環(huán)直到return出run()的while(true)函數(shù)。在setupRequest的FindRTPSession中,會去給fRTPSession賦值。所以在cleanupRequest中把它置為NULL。三.關(guān)鍵模塊分析直播模塊結(jié)構(gòu)分析:ReflectorSocket:publicIdleTask,publicUDPSocketGetlncomingData()負責接收數(shù)據(jù)ProcessPacket(),負責把數(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找出對應(yīng)的RTPStream,RTPStream的fCookieAttrID=sStreamCookieAttr屬性記錄的是它對應(yīng)的reflectorStream.判斷該rtpStream對應(yīng)的reflectorStream是否就是調(diào)用方的這個fstream.QTSS_Write(*theStreamPtr,&thePacket,..)theStreamPtr為RTPStream}ReflectorStream:ThisobjectsupportsreflectinganRTPmulticaststreamtoNRTPStreams.BindSockets()用來把reflectorSocket和reflectorSender聯(lián)系起來((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;在同時開啟多個窗口播放同一個sdp文件時,都是使用同一個ReflectorSession對象,F(xiàn)indOrCreateSession也不會調(diào)用SetupReflectorSession函數(shù),即ReflectorStream、ReflectorSocket等對象也不會被再次創(chuàng)建。注意對于一個新的播放鏈接來說RTSPSession、RTPSession都是新創(chuàng)建的對象,所以需要重新創(chuàng)建RTPSessionOutput^象。在QTSSReflectorModule.cpp的DoSetup()函數(shù)中,由DoSessionSetup進入FindOrCtreateSession(),建立出ReflectorSession,里面創(chuàng)建ReflectorStream,綁定它對于的ReflectorSocket.ReflectorSession*FindOrCreateSession{ReflectorSession*theSessiontheSession=NEWReflectorSession(inPath);Sourceinfo通過讀取sdp文件,對應(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類型為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類有的屬性有: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->從他對應(yīng)的rtpSession找到rtpStream,判斷該rtpStream對應(yīng)的reflectorStream是否就是調(diào)用方的這個fstream.是則調(diào)用該rtpStream的write函數(shù)發(fā)送數(shù)據(jù)包。播放一下,馬上出錯原因是,在請求sdp文件失敗返回后,調(diào)用了fileModule的doDescribe,返回出錯,再調(diào)用QTSS_Teardown,銷毀rtpSession.Signal(killEvent),在它的~RTPSessionInterface()中調(diào)用RTSPSession的DecrementObjectHolderCount()的signal(killEvent),刪除rtspSession.Udpsocket句柄釋放在eventSocket的虛構(gòu)函數(shù)中close.點播模塊分析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類型為QTRTPFile,在DoDescribe函數(shù)中,調(diào)用CreateQTRTPFile()函數(shù),根據(jù)inPath,*outFile二NewFileSession(),并(*outFile)->fFile.Initialize(inPath)FileSession類中,主要結(jié)構(gòu)有QTRTPFilefFile;fAdjustedPlayTime;QTSS_PacketStructfPacketStruct;

溫馨提示

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

評論

0/150

提交評論