RTSP伺服器處理用戶端點播的基本流程

來源:互聯網
上載者:User

RTSP伺服器處理用戶端點播的基本流程

 

轉自:

http://blog.csdn.net/huangxinfeng/archive/2010/03/22/5404233.aspx

  處理串連請求的基本流程:

l  Step 1:與用戶端建立RTSP串連(調用incomingConnectionHandler方法),建立ClientSession並關聯fClientSocket與incomingRequestHandler(調用incomingConnectionHandler1)。

l  Step 2:接收用戶端請求(調用incomingRequestHandler方法)。

l  Step 3:從用戶端Socket讀取資料,並對請求資料(即the request string)進行轉換(調用parseRTSPRequestString方法,該方法在RTSPCommon類中)。

l  Step 4:根據分離出來的指令進行分別處理:

n  OPTIONS→handleCmd_OPTIONS

n  DESCRIBE→handleCmd_DESCRIBE

handleCmd_DESCRIBE這一個方法比較重要,首先根據urlSuffix尋找ServerMediaSession是否存在(調用lookupServerMediaSession方法,該方法中通過HashTable來尋找)。

在testOnDemandRTSPServer項目工程中,僅僅是通過streamName來確認session是否為NULL。而在完整的live555MediaServer項目工程中,則是通過DynamicRTSPServer類來處理,其首先是尋找檔案是否存在,若檔案不存在,則判斷ServerMediaSession(即smsExists)是否存在,如果存在則將其remove(調用removeServerMediaSession方法);若檔案存在,則根據檔案名稱建立一個ServerMediaSession(調用createNewSMS方法,若在該方法中找不到對應的副檔名,則將返回NULL)。

如果通過lookupServerMediaSession返回的是NULL,則向用戶端發送響應訊息並將fSessionIsActive置為FALSE;否則,為該session組裝一個SDP描述資訊(調用generateSDPDescription方法,該方法在ServerMediaSession類中),組裝完成後,產生一個RTSP URL(調用rtspURL方法,該方法在RTSPServer類中)。

n  SETUP→handleCmd_SETUP

handleCmd_SETUP方法中,有兩個關鍵的名詞,一個是urlPreSuffix,代表了session name(即stream name);一個是urlSuffix,代表了subsession name(即track name),後面經常用到的streamName和trackId分別與這兩個名詞有關。

接下來會建立session's state,包括incrementReferenceCount等。緊接著,會針對確定的subsession(track)尋找相應的資訊。接著,在request string尋找一個"Transport:" header,目的是為了從中提取用戶端請求的一些參數(調用parseTransportHeader方法,該方法在RTSPServer類中),如clientsDestinationAddressStr、ClientRTPPortNum等。

再接著是getStreamParameters(該方法在ServerMediaSession類中被定義為純虛函數並在OnDemandServerMediaSubsession類中被重定義),然後通過fIsMulticast和streamingMode來組裝不同的響應訊息。

n  PLAY→handleCmd_PLAY:處理播放請求,具體的實現流程請參見後面的步驟。

n  PAUSE→handleCmd_PAUSE:處理暫停請求,在執行了該請求後,最終會調用StopPlaying方法,並將fAreCurrentlyPlaying置為FALSE。

n  TEARDOWN→handleCmd_TEARDOWN:處理停止請求,將fSessionIsActive置為FALSE。

n  GET_PARAMETER→handleCmd_GET_PARAMETER:該方法主要是維持用戶端與伺服器通訊的生存狀態,just for keep alive。

n  SET_PARAMETER→handleCmd_SET_PARAMETER:該方法未針對SET_PARAMETER作實現,使用該方法會調用handleCmd_notSupported方法,並將最終引發與用戶端中斷連線。

l  Step 5:根據Step 4的不同指令進行訊息響應(調用send方法),該訊息響應是即時的。

l  Step 6:處理用戶端發送“SETUP”指令後即開始播放的特殊情況。

l  Step 7:將RequestBuffer進行重設,以便於為之後到來的請求做好準備。

l  Step 8:檢查fSessionIsActive是否為FALSE,如果是則刪除當前的ClientSession。

 

  處理PLAY的基本流程:

l  Step 1:對rtspURL及相關header的處理,涉及較多的細節。

l  Step 2:根據不同的header對流進行縮放比例或定位的處理。

如果為sawScaleHeader,則進行縮放比例的處理(調用setStreamScale方法,該方法在OnDemandServerMediaSubsession類中實現)。

如果為sawRangeHeader,則進行尋找流的處理(即是對流進行定位,調用seekStream方法,該方法在OnDemandServerMediaSubsession類中實現;同時,該方法的調用是在初始播放前及播放過程中由於使用者拖動播放進度條而產生的系列請求)。

在OnDemandServerMediaSubsession類中,seekStream方法中調用了seekStreamSource方法,該方法在對應的媒體格式檔案的FileServerMediaSubsession類中實現(如針對WAV格式,則在WAVAudioFileServerMediaSubsession類中實現;針對MP3格式,則在MP3AudioFileServerMediaSubsession類中實現)。

同理,OnDemandServerMediaSubsession類中的setStreamScale方法中所調用的setStreamSourceScale方法亦是類似的實現機制。

l  Step 3:開始進行流式播放(調用startStream方法,該方法在OnDemandServerMediaSubsession類中實現)。

n  Step 3.1:根據clientSessionId從fDestinationsHashTable中尋找到destinations(包括了用戶端的IP地址、RTP連接埠號碼、RTCP連接埠號碼等資訊)。

n  Step 3.2:調用startPlaying方法,在該方法中根據RTPSink或UDPSink分別調用startPlaying方法。

如果是調用RTPSink的startPlaying方法,則接著會調用MediaSink類中的startPlaying方法,並在該方法中調用MultiFramedRTPSink類中的continuePlaying方法,之後便是buildAndSendPacket了。這裡已經來到重點了,即是關於不斷讀取Frame並Send的要點。在MultiFramedRTPSink類中,通過buildAndSendPacket、packFrame、afterGettingFrame、afterGettingFrame1、sendPacketIfNecessary和sendNext構成了一個迴圈圈,資料包的讀取和發送在這裡迴圈進行著。特別注意的是sendPacketIfNecessary方法中的後面代碼(nextTask() = envir().taskScheduler().scheduleDelayedTask(uSecondsToGo, (TaskFunc*)sendNext, this);),通過Delay amount of time後,繼續下一個Task,並回過來繼續調用buildAndSendPacket方法。

在packFrame方法中,正常情況下,需要調用getNextFrame方法(該方法在FramedSource類中,並且對不同媒體格式的Frame的擷取出現在FramedSource類的getNextFrame方法中,通過調用doGetNextFrame方法來實現)來擷取新的Frame。

如果是調用UDPSink的startPlaying方法,則接著會調用MediaSink類中的startPlaying方法,並在該方法中調用BasicUDPSink類中的continuePlaying方法。在這之後由若干個方法構成了一個迴圈圈:continuePlaying1、afterGettingFrame、afterGettingFrame1、sendNext。並在afterGettingFrame1方法中實現了packet的發送(fGS->output(envir(), fGS->ttl(), fOutputBuffer, frameSize);)。

Step 3.3:針對RTPSink建立RTCP instance(RTP與RTCP的配套使用決定了其必須這麼做,否則可能就跟直接使用UDP發送資料包沒什麼兩樣了^_^),建立RTCP instance時,將incomingReportHandler控制代碼作為BackgroundHandlerProc,以便於處理RTCP的報告,並開始startNetworkReading。這裡RTP/RTCP的使用方式有兩種,一種建立在TCP之上,一種建立在UDP之上。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.