H264 流媒体 编码汇总
實時傳輸協(xié)議(RTP)和實時控制協(xié)議(RTCP)
RTP是一種提供端對端傳輸服務(wù)的實時傳輸協(xié)議,用來支持在單目標(biāo)廣播和多目標(biāo)廣播網(wǎng)絡(luò)服務(wù)中傳輸實時數(shù)據(jù),而實時數(shù)據(jù)的傳輸則由RTCP協(xié)議來監(jiān)視和控制。
RTP定義在RFC
使用RTP協(xié)議的應(yīng)用程序運行在RTP之上,而執(zhí)行RTP的程序運行在UDP的上層,目的是為了使用UDP的端口號和檢查和。如圖16-12所示,RTP可以看成是傳輸層的子層。由多媒體應(yīng)用程序生成的聲音和電視數(shù)據(jù)塊被封裝在RTP信息包中,每個RTP信息包被封裝在UDP消息段中,然后再封裝在IP數(shù)據(jù)包中。
1889中。信息包的結(jié)構(gòu)包含廣泛用于多媒體的若干個域,包括聲音點播(audio-on-demand)、影視點播(video ondemand)、因特網(wǎng)電話(Internettelephony)和電視會議(videoconferencing)。RTP的規(guī)格沒有對聲音和電視的壓縮格式制定標(biāo)準,它可以被用來傳輸普通格式的文件。例如,WAV或者GSM(Global System forMobilecommunications)格式的聲音、MPEG-1和MPEG-2的電視,也可以用來傳輸專有格式存儲的聲音和電視文件。| TCP/IP模型 | |
| 應(yīng)用層(application) | |
| 傳輸層 | RTP |
| UDP | |
| IP | |
| 數(shù)據(jù)鏈路層(data link) | |
| 物理層(physical) |
圖16-12 RTP是傳輸層上的協(xié)議
從應(yīng)用開發(fā)人員的角度來看,可把RTP執(zhí)行程序看成是應(yīng)用程序的一部分,因為開發(fā)人員必需把RTP集成到應(yīng)用程序中。在發(fā)送端,開發(fā)人員必需把執(zhí)行RTP協(xié)議的程序?qū)懭氲絼?chuàng)建RTP信息包的應(yīng)用程序中,然后應(yīng)用程序把RTP信息包發(fā)送到UDP的套接接口(socketinterface),如圖16-13所示;同樣,在接收端,RTP信息包通過UDP套接接口輸入到應(yīng)用程序,因此開發(fā)人員必需把執(zhí)行RTP協(xié)議的程序?qū)懭氲綇腞TP信息包中抽出媒體數(shù)據(jù)的應(yīng)用程序。
| TCP/IP模型 | |
| 應(yīng)用層(application) | |
| RTP | |
| | 套接接口 |
| UDP | |
| IP | |
| 數(shù)據(jù)鏈路層(data link) | |
| 物理層(physical) |
圖16-13 RTP和UDP之間的接口
現(xiàn)以用RTP傳輸聲音為例來說明它的工作過程。假設(shè)音源的聲音是64kb/s的PCM編碼聲音,并假設(shè)應(yīng)用程序取20毫秒的編碼數(shù)據(jù)為一個數(shù)據(jù)塊(chunk),即在一個數(shù)據(jù)塊中有160個字節(jié)的聲音數(shù)據(jù)。應(yīng)用程序需要為這塊聲音數(shù)據(jù)添加RTP標(biāo)題生成RTP信息包,這個標(biāo)題包括聲音數(shù)據(jù)的類型、順序號和時間戳。然后RTP信息包被送到UDP套接接口,在那里再被封裝在UDP信息包中。在接收端,應(yīng)用程序從套接接口處接收RTP信息包,并從RTP信息包中抽出聲音數(shù)據(jù)塊,然后使用RTP信息包的標(biāo)題域中的信息正確地譯碼和播放聲音。
如果應(yīng)用程序不使用專有的方案來提供有效載荷類型(payloadtype)、順序號或者時間戳,而是使用標(biāo)準的RTP協(xié)議,應(yīng)用程序就更容易與其他的網(wǎng)絡(luò)應(yīng)用程序配合運行,這是大家都希望的事情。例如,如果有兩個不同的公司都在開發(fā)因特網(wǎng)電話軟件,他們都把RTP合并到他們的產(chǎn)品中,這樣就有希望:使用不同公司電話軟件的用戶之間能夠進行通信。
這里需要強調(diào)的是,RTP本身不提供任何機制來確保把數(shù)據(jù)及時遞送到接收端或者確保其他的服務(wù)質(zhì)量,它也不擔(dān)保在遞送過程中不丟失信息包或者防止信息包的次序不被打亂。的確,RTP的封裝只是在系統(tǒng)端才能看到,中間的路由器并不區(qū)分那個IP數(shù)據(jù)報是運載RTP信息包的。
RTP允許給每個媒體源分配一個單獨的RTP信息包流,例如,攝像機或者麥克風(fēng)。例如,有兩個團體參與的電視會議,這就可能打開4個信息包流:兩臺攝像機傳送電視流和兩個麥克風(fēng)傳送聲音流。然而,許多流行的編碼技術(shù),包括MPEG-1和MPEG-2在編碼過程中都把聲音和電視圖像捆綁在一起以形成單一的數(shù)據(jù)流,一個方向就生成一個RTP信息包流。
RTP信息包沒有被限制只可應(yīng)用于單目標(biāo)廣播,它們也可以在一對多(one-to-many)的多目標(biāo)廣播樹或者在多對多(many-to-many)的多目標(biāo)廣播樹上傳送。例如,多對多的多目標(biāo)廣播,在這種應(yīng)用場合下,所有發(fā)送端通常都把他們的RTP信息包流發(fā)送到具有相同多目標(biāo)廣播地址的多目標(biāo)廣播樹上。
16.6.2 RTP信息包標(biāo)題域
RTP標(biāo)題由4個信息包標(biāo)題域和其他域組成:有效載荷類型(payload type)域,順序號(sequencenumber)域,時間戳(timestamp)域和同步源標(biāo)識符(Synchronization SourceIdentifier)域等。RTP信息包的標(biāo)題域的結(jié)構(gòu)如下圖所示:
| Payload Type | Sequence Number | Timestamp | Synchronization Source Identifier | Miscellaneous Fields |
1. 有效載荷類型
RTP信息包中的有效載荷域(Payload TypeField)的長度為7位,因此RTP可支持128種不同的有效載荷類型。對于聲音流,這個域用來指示聲音使用的編碼類型,例如PCM、自適應(yīng)增量調(diào)制或線性預(yù)測編碼等等。如果發(fā)送端在會話或者廣播的中途決定改變編碼方法,發(fā)送端可通過這個域來通知接收端。表16-01列出了目前RTP所能支持的聲音有效載荷類型。
表16-01目前RTP所能支持的聲音有效載荷類型
| 有效載荷號 | 聲音類型 | 采樣率(kHz) | 數(shù)據(jù)率(kb/s) |
| 0 | PCM mu-law | 8 | 64 |
| 1 | 1016 | 8 | 4.8 |
| 2 | G.721 | 8 | 32 |
| 3 | GSM | 8 | 32 |
| 6 | DVI | 16 | 64 |
| 7 | LPC | 8 | 2.4 |
| 9 | G.722 | 8 | 48~64 |
| 14 | MPEG Audio | 90 | - |
| 15 | G.728 | 8 | 16 |
對電視流,有效載荷類型可以用來指示電視編碼的類型,例如motion JPEG,MPEG-1,MPEG-2或者H.231等等。發(fā)送端也可以在會話或者期間隨時改變電視的編碼方法。表16-02列出了目前RTP所能支持的某些電視有效載荷類型。
表16-02目前RTP所能支持的聲音有效載荷類型
| 有效載荷號 | 電視格式 |
| 26 | Motion JPEG |
| 28 | - |
| 31 | H.261 |
| 32 | MPEG-1 video |
| 33 | MPEG-2 video |
2. 順序號
順序號(Sequence NumberField)域的長度為16位。每發(fā)送一個RTP信息包順序號就加1,接收端可以用它來檢查信息包是否有丟失以及按順序號處理信息包。例如,接收端的應(yīng)用程序接收到一個RTP信息包流,這個RTP信息包在順序號86和89之間有一個間隔,接收端就知道信息包87和88已經(jīng)丟失,并且采取措施來處理丟失的數(shù)據(jù)。
3. 時間戳
時間戳(Timestamp)域的長度為32字節(jié)。它反映RTP數(shù)據(jù)信息包中第一個字節(jié)的采樣時刻(時間)。接收端可以利用這個時間戳來去除由網(wǎng)絡(luò)引起的信息包的抖動,并且在接收端為播放提供同步功能。
4. 同步源標(biāo)識符
同步源標(biāo)識符(SynchronizationSourceIdentifier,SSRC)域的長度為32位。它用來標(biāo)識RTP信息包流的起源,在RTP會話或者期間的每個信息包流都有一個清楚的SSRC。SSRC不是發(fā)送端的IP地址,而是在新的信息包流開始時源端隨機分配的一個號碼。
16.6.3 實時傳輸控制協(xié)議
實時傳輸控制協(xié)議(Real-timeControl Protocol,RTCP)也定義在1996年提出的RFC1889中。多媒體網(wǎng)絡(luò)應(yīng)用把RTCP和RTP一起使用,尤其是在多目標(biāo)廣播中更具吸引力。當(dāng)從一個或者多個發(fā)送端向多個接收端廣播聲音或者電視時,也就是在RTP會話期間,每個參與者周期性地向所有其他參與者發(fā)送RTCP控制信息包,如圖16-14所示。RTCP用來監(jiān)視服務(wù)質(zhì)量和傳送有關(guān)與會者的信息。對于RTP會話或者廣播,通常使用單個多目標(biāo)廣播地址,屬于這個會話的所有RTP和RTCP信息包都使用這個多目標(biāo)廣播地址,通過使用不同的端口號可把RTP信息包和RTCP信息包區(qū)分開來。
RTCP的主要功能是為應(yīng)用程序提供會話質(zhì)量或者廣播性能質(zhì)量的信息。每個RTCP信息包不封裝聲音數(shù)據(jù)或者電視數(shù)據(jù),而是封裝發(fā)送端和/或者接收端的統(tǒng)計報表。這些信息包括發(fā)送的信息包數(shù)目、丟失的信息包數(shù)目和信息包的抖動等情況,這些反饋信息對發(fā)送端、接收端或者網(wǎng)絡(luò)管理員都是很有用的。RTCP規(guī)格沒有指定應(yīng)用程序應(yīng)該使用這個反饋信息做什么,這完全取決于應(yīng)用程序開發(fā)人員。例如,發(fā)送端可以根據(jù)反饋信息來修改傳輸速率,接收端可以根據(jù)反饋信息判斷問題是本地的、區(qū)域性的還是全球性的,網(wǎng)絡(luò)管理員也可以使用RTCP信息包中的信息來評估網(wǎng)絡(luò)用于多目標(biāo)廣播的性能。
16.6.4 實時流放協(xié)議
實時流放協(xié)議(Real-Time StreamingProtocol,RTSP)是一個剛開始開發(fā)的協(xié)議,它的設(shè)想描述在RFC
播放的數(shù)據(jù)流被分成許多信息包,信息包的大小很適用于客戶機和服務(wù)器之間的帶寬。當(dāng)客戶機已經(jīng)接收到足夠多的信息包之后,用戶軟件就可開始播放一個信息包,同時對另一個信息包解壓縮和接收第三個信息包。這樣用戶就不需要把整個媒體文件從服務(wù)器上下載之后就可立即播放。廣播源可以是現(xiàn)場的數(shù)據(jù)流也可以是存儲的數(shù)據(jù)流。
RTSP協(xié)議想要提供控制多種應(yīng)用數(shù)據(jù)傳送的功能,提供一種選擇傳送通道的方法,例如UDP, TCP,IP多目標(biāo)廣播通道,以及提供一種基于RTP協(xié)議的遞送方法。正在設(shè)計的RTSP將工作在RTP的上層,用來控制和傳送實時的內(nèi)容。
RTSP能夠與資源保留協(xié)議一起使用,用來設(shè)置和管理保留帶寬的流式會話或者廣播。
2326文件中。RTSP是應(yīng)用級的實時流放協(xié)議,它主要目標(biāo)是為單目標(biāo)廣播和多目標(biāo)廣播上的流式多媒體應(yīng)用提供牢靠的播放性能,以及支持不同廠家提供的客戶機和服務(wù)機之間的協(xié)同工作能力。
在windows使用vs2008編譯live555
在windows使用vs2008編譯live5551.live555 源代碼簡介
liveMedia項目的源代碼包括四個基本的庫,各種測試代碼以及IVE555 Media Server。
四個基本的庫分別是UsageEnvironment&TaskScheduler,groupsock,liveMedia,BasicUsageEnvironment。
UsageEnvironment和TaskScheduler類用于事件的調(diào)度,實現(xiàn)異步讀取事件的句柄的設(shè)置以及錯誤信息的輸出。另外,還有一個HashTable類定義了一個通用的hash表,其它代碼要用到這個表。這些都是抽象類,在應(yīng)用程序中基于這些類實現(xiàn)自己的子類。
groupsock類是對網(wǎng)絡(luò)接口的封裝,用于收發(fā)數(shù)據(jù)包。正如名字本身,Groupsock主要是面向多播數(shù)據(jù)的收發(fā)的,它也同時支持單播數(shù)據(jù)的收發(fā)。Groupsock定義了兩個構(gòu)造函數(shù)
? ?Groupsock(UsageEnvironment& env, struct in_addrconst& groupAddr,
? ?????????Port port,u_int8_t ttl);
? ?Groupsock(UsageEnvironment& env, struct in_addrconst& groupAddr,
? ?????????structin_addr const& sourceFilterAddr,
? ?????????Portport);
前者是用于SIM(source-independent multicast)組,后者用于SSM(source-specificmulticast)組。groupsock庫中的Helper例程提供了讀寫socket等函數(shù),并且屏蔽了不同的操作系統(tǒng)之間的區(qū)別,這是在GroupsockHelper.cpp文件中實現(xiàn)的。
liveMedia庫中有一系列類,基類是Medium,這些類針對不同的流媒體類型和編碼。
各種測試代碼在testProgram目錄下,比如openRTSP等,這些代碼有助于理解liveMedia的應(yīng)用。
LIVE555 Media Server是一個純粹的RTSP服務(wù)器。支持多種格式的媒體文件:
? ???* TS流文件,擴展名ts。
? ???* PS流文件,擴展名mpg。
? ???* MPEG-4視頻基本流文件,擴展名m4e。
? ???* MP3文件,擴展名mp3。
? ???* WAV文件(PCM),擴展名wav。
? ???* AMR音頻文件,擴展名.amr。
? ???* AAC文件,ADTS格式,擴展名aac。
2.在windows下編譯live555
(1).下載 live555,http://www.live555.com/
? ? (2). 編輯win32config,TOOLS32=C:\Program Files\Microsoft Visual Studio9.0\VC
? ?????即保證這個路徑是你的Vs2008路徑。
? ? (3). 編輯"LINK_OPTS_0 =$(linkdebug) msvcirt.lib" in win32config to "LINK_OPTS_0 =$(linkdebug) msvcrt.lib",由于編譯器所要LINK的運行庫不一樣了
? ? (4).修改groupsock/makefile.head,替換"INCLUDES = -Iinclude-I../UsageEnvironment/include" 為"INCLUDES = -Iinclude-I../UsageEnvironment/include -DNO_STRSTREAM".
? ? (5).運行g(shù)enWindowsMakefiles.cmd 生成VS能夠編譯的*.mak文件
? ? (6).將以下內(nèi)容保存為live/compile.bat
call "C:\Program Files\Microsoft Visual Studio9\VC\vcvarsall.bat"
cd liveMedia
nmake /B -f liveMedia.mak
cd ../groupsock
nmake /B -f groupsock.mak
cd ../UsageEnvironment
nmake /B -f UsageEnvironment.mak
cd ../BasicUsageEnvironment
nmake /B -f BasicUsageEnvironment.mak
cd ../testProgs
nmake /B -f testProgs.mak
cd ../mediaServer
nmake /B -f mediaServer.mak
有關(guān)這一點來說,建議把vs2008的編譯環(huán)境加入到環(huán)境變量中,那么以后需用命令行編譯程序都可行了,可以參考 http://blog.chinaunix.net/u3/94873/showart_1907792.html的前部分設(shè)置VS2008的環(huán)境設(shè)置。
? ? (7).在命令行下運行compile.bat,就會看到很多編譯過程出現(xiàn)在CMD中了。
以上的編譯并不是 DEBUG模式,要調(diào)試時,應(yīng)先在win32config加入一行"NODEBUG=1"
進行編譯后,可以在要調(diào)試的程序路徑下輸入如:C:\works\VCCode\video\live555-latest\live\testProgs>devenvopenRTSP.exe,這樣就會把相關(guān)的調(diào)試環(huán)境搭建起來進行調(diào)試了。
文 字體大小:大 中 小
live555庫的應(yīng)用指南
Real Time Streaming Protocol或者RTSP(實時流媒體協(xié)議),是由 Real network和Netscape共同提出的如何有效地在IP網(wǎng)絡(luò)上傳輸流媒體數(shù)據(jù)的應(yīng)用層協(xié)議。RTSP提供一種可擴展的框架,使能夠提供能控制的,按需傳輸實時數(shù)據(jù),比如音頻和視頻文件。源數(shù)據(jù)可以包括現(xiàn)場數(shù)據(jù)的反饋和存貯的文件。rtsp對流媒體提供了諸如暫停,快進等控制,而它本身并不傳輸數(shù)據(jù),rtsp作用相當(dāng)于流媒體服務(wù)器的遠程控制。傳輸數(shù)據(jù)可以通過傳輸層的tcp,udp協(xié)議,rtsp也提供了基于rtp傳輸機制的一些有效的方法。? ???RTSP協(xié)議是一個非常類似HTTP協(xié)議的流控制協(xié)議。它們都使用純文本來發(fā)送信息,而且rtsp協(xié)議的語法也和HTTP類似。Rtsp一開始這樣設(shè)計,也是為了能夠兼容使用以前寫的HTTP協(xié)議分析代 碼 。這是個好消息。
它們主要的區(qū)別是HTTP協(xié)議是沒有狀態(tài)的, http協(xié)議在發(fā)送一個命令后,連接會斷開,而且命令之間沒有依賴性。不同的是RTSP的命令需要知道現(xiàn)在正處于一個什么狀態(tài),也就是說rtsp的命令總是按照順序來發(fā)送,某個命令總在另外一個命令之前要發(fā)送。Rtsp不管處于什么狀態(tài)都不會去斷掉連接。
HTTP 協(xié)議默 認使用80端口,而RTSP默認使用554端口。如果一些服務(wù)器因為某些安全的原因而封掉了這個端口,那代理和防火墻可能不讓RTSP消息通過,需要管理員去放開554端口,而使得rtsp協(xié)議能通過。
基本類
在Mplayer中如果使用live選項進行編譯,則需要安裝live555庫。live555實現(xiàn)RTP/RTSP功能。
使用環(huán)境(usageEnvironment):UsageEnvironment和TaskScheduler類用在調(diào)度不同事件。還有HashTable類定義,這些都是抽象基類。在使用過程中可以利用環(huán)境的特定功能。
groupsock:封裝網(wǎng)絡(luò)接口和socket。特別是還封裝了multicast應(yīng)用,這個multicast并不是Mbone意義的multicast,而是將多個寫而不讀socket組合處理,用來模擬multicast。
liveMedia:定義一個類棧,根類是Medium類-不同的流類型和編解碼器。
BasicUsageEnvironment:定義一個usageEnvironment的實現(xiàn),這個里面除了有一個TaskScheduler以外,都是一些說明性的東西。TaskSheduler里面是一些調(diào)度相關(guān)的函數(shù),其中doEventLoop是主控函數(shù),定義為純虛函數(shù)。
testProgs:目錄下是一個簡單的實現(xiàn),使用了BasicUsageEnvironment來展示如何使用這些庫。
BasicTaskScheduler0:主要成員變量有fdelayQueue, fReadHandlers,fLastHandledSocketNum;這里主要的處理函數(shù)是scheduleDelayedTask,通過定時器觸發(fā)一個時間,比如RTCP包的發(fā)送等。
BasicTaskScheduler:中又添加了fMaxNumSockets和fReadSet。其中freadHandlers類中定義一個鏈表,將所有的句柄,對應(yīng)的處理函數(shù) 和處理函數(shù)參數(shù)作鏈接成一個鏈表,通過成員函數(shù)assignHandler管理。這里面主要的函數(shù)是turnOnBackgroundReadHandling,這個函數(shù)把句柄和處理函數(shù)注冊到select中,這樣可以完成數(shù)據(jù)包的等待及其處理操作。
MediaSession類中定義了一個mediaSubSession鏈表;MediaSubSession中又SessionId,服務(wù)端口號,rtp/rtcp ChannelId和MediaSink指針,等等一些參數(shù)信息。
H.264
1. 基類
Medium:定義媒體名字和環(huán)境信息,處理任務(wù)名,靜態(tài)函數(shù)close和lookupByName和一些虛函數(shù)來指明該medium類型,是媒體幀的基類。
MediaSource類:實現(xiàn)基類中medium類型的虛函數(shù),
FramedSoruce:定義了getNextFrame和doGetNextFrame純虛函數(shù)是使用到的一些變量。
2. 相關(guān)類
H264VideoStreamFramer;H264VideoFileSink:H264VideoRTPSource:H264VideoRTPSinik
H.264利用NAL封裝數(shù)據(jù),通過RTP傳輸數(shù)據(jù)包。相關(guān)的處理在RTPSource/Sink中。
Mplayer
從RTSP或者SIP中渠道SDP描述,然后調(diào)用Live555中的mediaSession類創(chuàng)建Session。通過成員函數(shù)initializeWithSDP分析SDP描述。
OpenRTSP
1. Client
1. 創(chuàng)建TaskScheduler和UsageEnvironment實例;
2. 調(diào)用createClient創(chuàng)建media實例;
在openRTSP.c中,main完成配置以后,開始如下循環(huán):
startPlayingStreams();
env->taskScheduler().doEventLoop(); // does notreturn
在BasicTaskScheduler0類中,定義為while(1) SingleStep();
SingleStep的處理是通過select監(jiān)聽一組句柄,這組句柄通過iter組成的鏈表串接起來,對每個句柄有處理函數(shù),如果有句柄上有數(shù)據(jù),那么調(diào)用對應(yīng)的處理函數(shù)。
2. liev555mediaserver
創(chuàng)建過程:
1. 創(chuàng)建TaskScheduler:這里僅僅初始化一個fdset并且socket數(shù)目初始化為0。
2. 以TaskScheduler為參數(shù)創(chuàng)建UsageEnvironment對象。
3. 以前述environment和服務(wù)端口號(554/8554)以及用戶認證對象為參數(shù)創(chuàng)建 RTSPServer對象,這里是用子類DynamicRTSPServer的創(chuàng)建函數(shù)創(chuàng)建。在createNew成員函數(shù)中建立socket,分配發(fā)送緩沖區(qū),和創(chuàng)建RTSPServer對象。這里通過turnOnBackgroundReadHandling函數(shù)將要處理的句柄和處理函數(shù)關(guān)聯(lián)起來。
4. 執(zhí)行env->taskScheduler().doEventLoop();
從RFC2326中可以看出通常的交互流程是發(fā)送describe,然后發(fā)送setup,再play。所以以請求MPG多媒體URI為例分析如下:
C->M: DESCRIBE rtsp://foo/twister RTSP/1.0
CSeq: 1
M->C: RTSP/1.0 200 OK
CSeq: 1
Content-Type: application/sdp
Content-Length: 164
v=0
o=- 2890844256 2890842807 IN IP4 172.16.2.93
s=RTSP Session
i=An Example of RTSP Session Usage
a=control:rtsp://foo/twister
t=0 0
m=audio 0 RTP/AVP 0
a=control:rtsp://foo/twister/audio
m=video 0 RTP/AVP 26
a=control:rtsp://foo/twister/video
C->M: SETUP rtsp://foo/twister/audio RTSP/1.0
CSeq: 2
Transport: RTP/AVP;unicast;client_port=8000-8001
M->C: RTSP/1.0 200 OK
CSeq: 2
Transport: RTP/AVP;unicast;client_port=8000-8001;
server_port=9000-9001
Session: 12345678
C->M: SETUP rtsp://foo/twister/video RTSP/1.0
CSeq: 3
Transport: RTP/AVP;unicast;client_port=8002-8003
Session: 12345678
M->C: RTSP/1.0 200 OK
CSeq: 3
Transport: RTP/AVP;unicast;client_port=8002-8003;
server_port=9004-9005
Session: 12345678
C->M: PLAY rtsp://foo/twister RTSP/1.0
CSeq: 4
Range: npt=0-
Session: 12345678
M->C: RTSP/1.0 200 OK
CSeq: 4
Session: 12345678
RTP-Info: url=rtsp://foo/twister/video;
seq=9810092;rtptime=3450012
C->M: PAUSE rtsp://foo/twister/video RTSP/1.0
CSeq: 5
Session: 12345678
M->C: RTSP/1.0 460 Only aggregate operationallowed
CSeq: 5
C->M: PAUSE rtsp://foo/twister RTSP/1.0
CSeq: 6
Session: 12345678
M->C: RTSP/1.0 200 OK
CSeq: 6
Session: 12345678
C->M: SETUP rtsp://foo/twister RTSP/1.0
CSeq: 7
Transport: RTP/AVP;unicast;client_port=10000
M->C: RTSP/1.0 459 Aggregate operation notallowed
CSeq: 7
函數(shù) handleCmd_DESCRIBE處理describe請求,生成含SDP信息響應(yīng)消息,lookupServerMediaSession函數(shù)是虛函數(shù),在創(chuàng)建RTSPServer對象時,用的是子類DynamicRTSPServer的創(chuàng)建函數(shù),所以上述函數(shù)使用的是類DynamicRTSPServer中的定義。函數(shù)打開,并且分析流媒體文件。createNewSMS根據(jù)請求的文件后綴來調(diào)用對應(yīng)的處理函數(shù)。如果是MPG,那么創(chuàng)建ServerMediaSession對象并添加到RTSPserver中,這個對象是可以通過Hash類定位的。然后創(chuàng)建一個Mpeg1or2FileServerDemux對象demux,然后將創(chuàng)建demux對象中的音頻,視頻子會話對象并且通過函數(shù) addSubsession將他們添加到ServerMediaSession中鏈表中。響應(yīng)函數(shù)會依次調(diào)用會話中注冊的子會話的 sdpLines函數(shù)以取得SDP信息。sdpLines是一個純虛函數(shù),如果URI指定的MPG文件,那么sdpLines 函數(shù)在OnDemandServerMediaSubsession中定義實現(xiàn)。此時,對每個子會話那么會創(chuàng)建一個sink對象。對應(yīng)MPG文件,在MPEG1or2DemuxedServerMediaSubsession類定義的createNewRTPSink會創(chuàng)建對象:
音頻:MPEG1or2AudioRTPSink::AudioRTPSink::MultiFramedRTPSink::RTPSink::MediaSink::Media
視頻:MPEG1or2VideoRTPSink::VideoRTPSink::MultiFramedRTPSink::RTPSink::MediaSink::Media
而SDP信息的獲取在函數(shù) setSDPLinesFromRTPSink中處理。(AudioRTPSink指定媒體類型,時間標(biāo)簽頻率和載荷格式名“MPA”,視頻名字是“MPV")
這里類結(jié)構(gòu) MPEG1or2DemuxedServerMediaSubsession::OnDemandServerMediaSubsession ::ServerMediaSubsession::Medium
函數(shù) handleCmd_SETUP處理setup請求,
MPEG1or2Demux類是mpeg相關(guān)的一個主要類,創(chuàng)建該類時會分析媒體文件。該類定義中有個數(shù)組,OutputDescriptorfOutput[256];MPEG1or2Demux的構(gòu)造函數(shù)中初始化。
在windows使用vs2008編譯live555
1.live555 源代碼簡介
liveMedia項目的源代碼包括四個基本的庫,各種測試代碼以及IVE555 Media Server。
四 個基本的庫分別是UsageEnvironment&TaskScheduler,groupsock,liveMedia,BasicUsageEnvironment。
UsageEnvironment和TaskScheduler類用于事件的調(diào)度,實現(xiàn)異步讀取事件的句柄的設(shè)置以及錯誤信息的輸出。另外,還有一個HashTable類定義了一個通用的hash表,其它代碼要用到這個表。這些都是抽象類,在應(yīng)用程序中基于這些類實現(xiàn)自己的子類。
groupsock類是對網(wǎng)絡(luò)接口的封裝,用于收發(fā)數(shù)據(jù)包。正如名字本身,Groupsock主要是面向多播數(shù)據(jù)的收發(fā)的,它也同時支持單播數(shù)據(jù)的收發(fā)。Groupsock定義了兩個構(gòu)造函數(shù)
Groupsock(UsageEnvironment& env, struct in_addrconst& groupAddr,
Port port, u_int8_t ttl);
Groupsock(UsageEnvironment& env, struct in_addrconst& groupAddr,
struct in_addr const& sourceFilterAddr,
Port port);
前 者是用于SIM(source-independent multicast)組,后者用于SSM(source-specificmulticast)組。groupsock庫中的Helper例程提供了讀寫socket等函數(shù),并且屏蔽了不同的操作系統(tǒng)之間的區(qū)別,這是在GroupsockHelper.cpp文件中實現(xiàn)的。
liveMedia庫中有一系列類,基類是Medium,這些類針對不同的流媒體 類型和編碼。
各種測試代碼在testProgram目錄下,比如openRTSP等,這些代碼有助于理解liveMedia的應(yīng)用。
LIVE555 Media Server是一個純粹的RTSP服務(wù)器。支持多種格式的媒體文件:
* TS流文件,擴展名ts。
* PS流文件,擴展名mpg。
* MPEG-4視頻基本流文件,擴展名m4e。
* MP3文件,擴展名mp3。
* WAV文件(PCM),擴展名wav。
* AMR音頻文件,擴展名.amr。
* AAC文件,ADTS格式,擴展名aac。
2.在windows下編譯live555
(1).下載 live555,http://www.live555.com/
(2). 編輯 win32config,TOOLS32=C:\Program Files\Microsoft VisualStudio 9.0\VC
即保證這個路徑是你的Vs2008 路徑。
(3). 編輯"LINK_OPTS_0 = $(linkdebug) msvcirt.lib" in win32config to"LINK_OPTS_0 = $(linkdebug) msvcrt.lib",由于編譯器所要LINK的運行庫不一樣了
(4). 修改groupsock/makefile.head,替換"INCLUDES = -Iinclude-I../UsageEnvironment/include" 為"INCLUDES = -Iinclude-I../UsageEnvironment/include -DNO_STRSTREAM".
(5). 運行g(shù)enWindowsMakefiles.cmd 生成VS能夠編譯的*.mak文件
(6). 將以下內(nèi)容保存為live/compile.bat
call "C:\Program Files\Microsoft Visual Studio9\VC\vcvarsall.bat"
cd liveMedia
nmake /B -f liveMedia.mak
cd ../groupsock
nmake /B -f groupsock.mak
cd ../UsageEnvironment
nmake /B -f UsageEnvironment.mak
cd ../BasicUsageEnvironment
nmake /B -f BasicUsageEnvironment.mak
cd ../testProgs
nmake /B -f testProgs.mak
cd ../mediaServer
nmake /B -f mediaServer.mak
有 關(guān)這一點來說,建議把vs2008的編譯環(huán)境加入到環(huán)境變量中,那么以后需用命令行編譯程序都可行了,可以參考 http://blog.chinaunix.net/u3/94873/showart_1907792.html的前部分設(shè)置VS2008的環(huán)境設(shè)置。
(7). 在命令行下運行compile.bat,就會看到很多編譯過程出現(xiàn)在CMD中了。
以上的編譯并不是 DEBUG模式,要調(diào)試時,應(yīng)先在win32config加入一行"NODEBUG=1"
進行編譯后,可以在要調(diào)試的程序路徑下輸入如:C:\works\VCCode\video\live555-latest\live\testProgs>devenvopenRTSP.exe,這樣就會把相關(guān)的調(diào)試環(huán)境搭建起來進行調(diào)試了。
liveMedia項目的源代碼包括四個基本的庫,各種測試代碼以及IVE555 Media Server。
四個基本的庫分別是UsageEnvironment&TaskScheduler,groupsock,liveMedia,BasicUsageEnvironment。
UsageEnvironment和TaskScheduler類用于事件的調(diào)度,實現(xiàn)異步讀取事件的句柄的設(shè)置以及錯誤信息的輸出。另外,還有一個HashTable類定義了一個通用的hash表,其它代碼要用到這個表。這些都是抽象類,在應(yīng)用程序中基于這些類實現(xiàn)自己的子類。
groupsock類是對網(wǎng)絡(luò)接口的封裝,用于收發(fā)數(shù)據(jù)包。正如名字本身,Groupsock主要是面向多播數(shù)據(jù)的收發(fā)的,它也同時支持單播數(shù)據(jù)的收發(fā)。Groupsock定義了兩個構(gòu)造函數(shù)
Groupsock(UsageEnvironment& env, struct in_addrconst& groupAddr,
Port port, u_int8_t ttl);
Groupsock(UsageEnvironment& env, struct in_addrconst& groupAddr,
struct in_addr const& sourceFilterAddr,
Port port);
前者是用于SIM(source-independent multicast)組,后者用于SSM(source-specificmulticast)組。groupsock庫中的Helper例程提供了讀寫socket等函數(shù),并且屏蔽了不同的操作系統(tǒng)之間的區(qū)別,這是在GroupsockHelper.cpp文件中實現(xiàn)的。
liveMedia庫中有一系列類,基類是Medium,這些類針對不同的流媒體 類型和編碼。
各種測試代碼在testProgram目錄下,比如openRTSP等,這些代碼有助于理解liveMedia的應(yīng)用。
LIVE555 Media Server是一個純粹的RTSP服務(wù)器。支持多種格式的媒體文件:
* TS流文件,擴展名ts。
* PS流文件,擴展名mpg。
* MPEG-4視頻基本流文件,擴展名m4e。
* MP3文件,擴展名mp3。
* WAV文件(PCM),擴展名wav。
* AMR音頻文件,擴展名.amr。
* AAC文件,ADTS格式,擴展名aac。
用live555開發(fā)應(yīng)用程序
基于liveMedia的程序,需要通過繼承UsageEnvironment抽象類和TaskScheduler抽象類,定義相應(yīng)的類來處理事件調(diào)度,數(shù)據(jù)讀寫以及錯誤處理。live項目的源代碼里有這些類的一個實現(xiàn),這就是“BasicUsageEnvironment”庫。BasicUsageEnvironment主要是針對簡單的控制臺應(yīng)用程序,利用select實現(xiàn)事件獲取和處理。這個庫利用Unix或者Windows的控制臺作為輸入輸出,處于應(yīng)用程序原形或者調(diào)試的目的,可以用這個庫用戶可以開發(fā)傳統(tǒng)的運行與控制臺的應(yīng)用。
通過使用自定義的“UsageEnvironment”和“TaskScheduler”抽象類的子類,這些應(yīng)用程序就可以在特定的環(huán)境中運行,不需要做過多的修改。需要指出的是在圖形環(huán)境(GUI toolkit)下,抽象類 TaskScheduler 的子類在實現(xiàn)doEventLoop()的時候應(yīng)該與圖形環(huán)境自己的事件處理框架集成。
先來熟悉在liveMedia庫中Source,Sink以及Filter等概念。Sink就是消費數(shù)據(jù)的對象,比如把接收到的數(shù)據(jù)存儲到文件,這個文件就是一個Sink。Source就是生產(chǎn)數(shù)據(jù)的對象,比如通過RTP讀取數(shù)據(jù)。數(shù)據(jù)流經(jīng)過多個'source'和'sink's,下面是一個示例:
'source1' -> 'source2' (a filter) ->'source3' (a filter) -> 'sink'
從其它 Source接收數(shù)據(jù)的source也叫做"filters"。Module是一個sink或者一個filter。
數(shù)據(jù)接收的終點是 Sink類,MediaSink是所有Sink類的基類。MediaSink的定義如下:
class MediaSink: public Medium {
public:
static Boolean lookupByName(UsageEnvironment& env,char const* sinkName,
MediaSink*& resultSink);
typedef void (afterPlayingFunc)(void* clientData);
Boolean startPlaying(MediaSource& source,
afterPlayingFunc* afterFunc,
void* afterClientData);
virtual void stopPlaying();
// Test for specific types of sink:
virtual Boolean isRTPSink() const;
FramedSource* source() const {return fSource;}
protected:
MediaSink(UsageEnvironment& env); // abstract baseclass
virtual ~MediaSink();
virtual BooleansourceIsCompatibleWithUs(MediaSource&source);
// called by startPlaying()
virtual Boolean continuePlaying() = 0;
// called by startPlaying()
static void onSourceClosure(void* clientData);
// should be called (on ourselves) by continuePlaying() whenit
// discovers that the source we're playing from has closed.
FramedSource* fSource;
private:
// redefined virtual functions:
virtual Boolean isSink() const;
private:
// The following fields are used when we're being played:
afterPlayingFunc* fAfterFunc;
void* fAfterClientData;
};
Sink 類實現(xiàn)對數(shù)據(jù)的處理是通過實現(xiàn)純虛函數(shù)continuePlaying(),通常情況下continuePlaying調(diào)用fSource->getNextFrame來為Source設(shè)置數(shù)據(jù)緩沖區(qū),處理數(shù)據(jù)的回調(diào)函數(shù)等,fSource是MediaSink的類型為FramedSource*的類成員;
基于liveMedia的應(yīng)用程序的控制流程如下:
應(yīng)用程序是事件驅(qū)動的,使用如 下方式的循環(huán)
while (1) {
通過查找讀網(wǎng)絡(luò)句柄的列表和延遲隊列(delay queue)來發(fā)現(xiàn)需要完成的任務(wù)
完成這個任務(wù)
}
對于每個sink,在進入這個循環(huán)之 前,應(yīng)用程序通常調(diào)用下面的方法來啟動需要做的生成任務(wù):
someSinkObject->startPlaying();
任何時候,一個Module需要獲取數(shù)據(jù)都通過調(diào)用剛好在它之前的那個Module的FramedSource::getNextFrame()方法。這是通過純虛函數(shù)FramedSource:oGetNextFrame() 實現(xiàn)的,每一個Source module都有相應(yīng)的實現(xiàn)。
Each 'source' module's implementation of "doGetNextFrame()" worksby arranging for an 'after getting' function to be called (from anevent handler) when new data becomes available for thecaller.
注意,任何應(yīng)用程序都要處理從'sources'到'sinks'的數(shù)據(jù)流,但是并非每個這樣的數(shù)據(jù)流都與從網(wǎng)絡(luò)接口收發(fā)數(shù)據(jù)相對應(yīng)。
比如,一個服務(wù)器應(yīng)用程序發(fā)送RTP數(shù)據(jù)包的時候用到一個或多 個"RTPSink" modules。這些"RTPSink"modules以別的方式接收數(shù)據(jù),通常是文件 "*Source" modules (e.g., to read data from afile), and, as a side effect, transmit RTP packets.
一個簡單的RTSP客戶端程序
在另一個文章里,給出了這個簡單的客戶端的程序的代碼,可以通過修改Makefile來裁剪liveMedia,使得這個客戶端最小化。此客戶端已經(jīng)正常運行。
首先是OPTION
然 后是DESCRIBE
建立Media Session,調(diào)用的函數(shù)是MediaSession::createNew,在文件liveMedia/MediaSession.cpp中實現(xiàn)。
為這個Media Session建立RTPSource,這是通過調(diào)用MediaSubsession::initiate來實現(xiàn)的的,這個方法在liveMedia/MediaSession.cpp中實現(xiàn)。
在然 后是SETUP
最后是PLAY
rtp數(shù)據(jù)的句 柄:MultiFramedRTPSource::networkReadHandler在liveMedia/MultiFramedRTPSource.cpp中
rtcp數(shù)據(jù)處理的句 柄:RTCPInstance::incomingReportHandler在liveMedia/RTCP.cpp中
rtp數(shù)據(jù)處 理的句柄的設(shè)置:MultiFramedRTPSource: oGetNextFrame在liveMedia/MultiFramedRTPSource.cpp中,被FileSink::continuePlaying調(diào)用在FileSink.cpp中.
rtcp數(shù)據(jù)處理的句柄設(shè)置 fRTCPInstance = RTCPInstance::createNew在/liveMedia/MediaSession.cpp中調(diào)用,
createNew 調(diào)用了構(gòu)造函數(shù)RTCPInstance::RTCPInstance,這個構(gòu)造函數(shù)有如下調(diào)用
TaskScheduler::BackgroundHandlerProc* handler =(TaskScheduler::BackgroundHandlerProc*)&incomingReportHandler;
*********************************************************************************************************************
通過分析live庫提供的例子程序OpenRTSP,可以清晰地了解客戶端接收來自網(wǎng)絡(luò)上媒體數(shù)據(jù)的過程。注意,RTP協(xié)議和RTCP協(xié)議接收的數(shù)據(jù)分別是視音頻數(shù)據(jù)和發(fā)送/接收狀況的相關(guān)信息,其中,RTP協(xié)議只負責(zé)接收數(shù)據(jù),而RTCP協(xié)議除了接收服務(wù)器的消息之外,還要向服務(wù)器反饋。
A.? ?????main函數(shù)流程
main(int argc,char *argv[])
{
1.? ???????創(chuàng)建BasicTaskScheduler對象
2.? ???????創(chuàng)建BisicUsageEnvironment對象
3.? ???????分析argv參數(shù),(最簡單的用法是:openRTSP rtsp://172.16.24.240/mpeg4video.mp4)以便在下面設(shè)置一些相關(guān)參數(shù)
4.? ???????創(chuàng)建RTSPClient對象
5.? ???????由RTSPClient對象向服務(wù)器發(fā)送OPTION消息并接受回應(yīng)
6.? ???????產(chǎn)生SDPDescription字符串(由RTSPClient對象向服務(wù)器發(fā)送DESCRIBE消息并接受回應(yīng),根據(jù)回應(yīng)的信息產(chǎn)生SDPDescription字符串,其中包括視音頻數(shù)據(jù)的協(xié)議和解碼器類型)
7.? ???????創(chuàng)建MediaSession對象(根據(jù)SDPDescription在MediaSession中創(chuàng)建和初始化MediaSubSession子會話對象)
8.? ???????while循環(huán)中配置所有子會話對象(為每個子會話創(chuàng)建RTPSource和RTCPInstance對象,并創(chuàng)建兩個GroupSock對象,分別對應(yīng) RTPSource和RTCPInstance對象,把在每個GroupSock對象中創(chuàng)建的socket描述符置入BasicTaskScheduler::fReadSet中,RTPSource對象的創(chuàng)建的依據(jù)是SDPDescription,例如對于MPEG4文件來說,視音頻RTPSource分別對應(yīng)MPEG4ESVideoRTPSource和MPEG4GenericRTPSource對象。RTCPInstance對象在構(gòu)造函數(shù)中完成將Socket描述符、處理接收RTCP數(shù)據(jù)的函數(shù)(RTCPInstance::incomingReportHandler)以及RTCPInstance本身三者綁定在一個HandlerDescriptor對象中,并置入BasicTaskScheduler::fReadHandler中。完成綁定后會向服務(wù)器發(fā)送一條消息。)
9.? ???????由RTSPClient對象向服務(wù)器發(fā)送SETUP消息并接受回應(yīng)。
10.? ?????while循環(huán)中為每個子會話創(chuàng)建接收器(FileSink對象),在FileSink對象中根據(jù)子會話的codec等屬性缺省產(chǎn)生記錄視音頻數(shù)據(jù)的文件 名,視音頻文件名分別為:video-MP4V-ES-1和audio-MPEG4-GENERIC-2,無后綴名
11.? ?????while循環(huán)中為每個子會話的視音頻數(shù)據(jù)裝配相應(yīng)的接收函數(shù),將每個子會話中的RTPSource中的GroupSock對象中的SOCKET描述符, 置入BasicTaskScheduler::fReadSet中,并將描述符、處理接收RTP數(shù)據(jù)的函數(shù)(MultiFramedRTPSource::networkReadHandler)以及RTPSource本身三者綁定在一個HandlerDescriptor對象中,并置入BasicTaskScheduler::fReadHandler中,并將FileSink的緩沖區(qū)和包含寫入文件操作的一個函數(shù)指針配置給RTPSource對象,這個緩沖區(qū)將會在networkReadHandler中接收來自網(wǎng)絡(luò)的視音頻數(shù)據(jù)(分析和去掉RTP包頭的工作由RTPSource完成),而這個函數(shù)指針在networkReadHandler中被調(diào)用以完成將緩沖區(qū)中的數(shù)據(jù)寫入文件。
12.? ?????由RTSPClient對象向服務(wù)器發(fā)送PLAY消息并接受回應(yīng)。
13.? ?????進入while循環(huán),調(diào)用BasicTaskScheduler::SingleStep()函數(shù)接受數(shù)據(jù),直到服務(wù)器發(fā)送TREADOWN消息給客戶端,客戶端接收到該消息后釋放資源,程序退出。
}
淺談vlc模塊管理方式-插件
vlc中所有的模塊均以動態(tài)庫(插件)方式來管理,就連main模塊也不例外。可以在windows下查看vlc安裝目錄下plugin目錄,里面包含了所有的動態(tài)庫。當(dāng)vlc啟動的時候,主模塊采用動態(tài)加入的方式.
具體實現(xiàn)如下:
?
? ?上面一段是老外解釋的,還是說的比較清楚了,后來我仔細看了下,自己也做了相關(guān)的試驗。其實他的核心就是采用宏定義將該模塊的入口函數(shù)導(dǎo)出,以讓其他函數(shù)調(diào)用。同時入口函數(shù)里面初始化了于該模塊相關(guān)的所有函數(shù)指針。
? ?主模塊的庫是libvlc。在modules_in.h中,通過宏定義,導(dǎo)出了vlc_entry__MODULE_NAME函數(shù),MODULE_NAME的宏定義在libvlc.c的31行,(#define MODULE_NAMEmain)這樣也就說明了該模塊的入口函數(shù)是vlc_entry__main。在modules.c中存在函數(shù)__module_InitBank,該函數(shù)最后調(diào)用module_LoadMain,在module_LoadMain中,調(diào)用了AllocateBuiltinModule函數(shù)(AllocateBuiltinModule( p_this, vlc_entry__main);),此處明確指出了需要調(diào)用主模塊的入口函數(shù)vlc_entry__main,哈哈,看到了吧,此處說明了main模塊要載入了,果然在AllocateBuiltinModule函數(shù)中存在調(diào)用pf_entry( p_module)1212行,該調(diào)用實質(zhì)是vlc_entry__main的調(diào)用,現(xiàn)在一切真像大白了。
????除了主模塊的載入外,其他模塊的載入和主模塊有點不同。他們不是通過這樣直接指定模塊名字調(diào)用相應(yīng)的函數(shù)指針的方式,而是采用在動態(tài)庫中直接找到_vlc_entry*函數(shù)的地址,并調(diào)用該函數(shù)完成具體模塊的初始化工作。具體的函數(shù)調(diào)用流程如下:
????1。通過__module_Need(modules.h)找到需要載入的模塊;
????2。在上面函數(shù)中通過AllocatePlugin(Modules.h)函數(shù)來完成載入;
????3.在AllocatePlugin函數(shù)中,CallEntry實現(xiàn)具體的模塊入口的調(diào)用,其實現(xiàn)原理就是通過在動態(tài)庫文件中查找_vlc_entry*函數(shù)的地址(C語言風(fēng)格的動態(tài)庫)。
????4。回到最上層的__module_Need函數(shù)中,調(diào)用模塊初始化的pf_activate來激活,最后當(dāng)需要卸載時,調(diào)用pf_deactivate函數(shù)即可。
????以上就是vlc獨特的管理模塊的方式,只是一個大概的原理,具體里面還有很多數(shù)據(jù)結(jié)構(gòu)還未仔細研究,不過可以看的出vlc這樣做的好處能比較靈活的管理各種模塊,并動態(tài)改變。雖然代碼都有C寫的,但是實現(xiàn)后的靈活度還是很高的。
TS流、ES流、PES流介紹分析
IP數(shù)據(jù)報有首部和數(shù)據(jù)兩部分組成的,首部的前一部分是固定長度20字節(jié),是所有IP數(shù)據(jù)報必須具有的。首部包括:總長度、標(biāo)識、MF、DF、片偏移。
數(shù)字信號實際傳送的是數(shù)據(jù)流,一般數(shù)據(jù)流包括以下三種:
ES流:也叫基本碼流,包含視頻、音頻或數(shù)據(jù)的連續(xù)碼流。
PES流:也叫打包的基本碼流,是將基本的碼流ES流根據(jù)需要分成長度不等的數(shù)據(jù)包,并加上包頭就形成了打包的基本碼流PES流。
TS流:也叫傳輸流,是由固定長度為188字節(jié)的包組成,含有獨立時基的一個或多個節(jié)目,適用于誤碼較多的環(huán)境。liveMedia項目(http://www.live555.com/)的源代碼包括四個基本的庫,各種測試代碼以及MediaServer。四個基本的庫分別是: UsageEnvironment&TaskScheduler,groupsock, liveMedia和BasicUsageEnvironment。
UsageEnvironment和TaskScheduler類用于事件的調(diào)度,實現(xiàn)異步讀取事件的句柄的設(shè)置以及錯誤信息的輸出。另外,還有一個HashTable類定義了一個通用的hash表,其它代碼要用到這個表。這些都是抽象類,在應(yīng)用程序中基于這些類來實現(xiàn)自己的子類。
groupsock類是對網(wǎng)絡(luò)接口的封裝,用于收發(fā)數(shù)據(jù)包。正如名字本身,groupsock主要是面向多播數(shù)據(jù)的收發(fā)的,它也同時支持單播數(shù)據(jù)的收發(fā)。
liveMedia庫中有一系列類,基類是Medium,這些類針對不同的流媒體類型和編碼。
各種測試代碼在testProgram目錄下,比如openRTSP等,這些代碼有助于理解liveMedia的應(yīng)用。
Media Server是一個純粹的RTSP服務(wù)器。支持多種格式的媒體文件:
* TS流文件,擴展名ts。
* PS流文件,擴展名mpg。
* MPEG-4視頻基本流文件,擴展名m4e。
* MP3文件,擴展名mp3。
* WAV文件(PCM),擴展名wav。
* AMR音頻文件,擴展名.amr。
* AAC文件,ADTS格式,擴展名aac。
用live555開發(fā)應(yīng)用程序
基于liveMedia的程序,需要通過繼承UsageEnvironment抽象類和TaskScheduler抽象類,定義相應(yīng)的類來處理事件調(diào)度,數(shù)據(jù)讀寫以及錯誤處理。live項目的源代碼里有這些類的一個基本實現(xiàn),這就是“BasicUsageEnvironment”庫。BasicUsageEnvironment主要是針對簡單的控制臺應(yīng)用程序,利用select實現(xiàn)事件獲取和處理。這個庫利用Unix或者Windows的控制臺作為輸入輸出,處于應(yīng)用程序原形或者調(diào)試的目的,可以用這個庫用戶可以開發(fā)傳統(tǒng)的運行與控制臺的應(yīng)用。
通過使用自定義的“UsageEnvironment”和“TaskScheduler”抽象類的子類,這些應(yīng)用程序就可以在特定的環(huán)境中運行,不需要做過多的修改。需要指出的是在圖形環(huán)境(GUI toolkit)下,抽象類 TaskScheduler 的子類在實現(xiàn)doEventLoop()的時候應(yīng)該與圖形環(huán)境自己的事件處理框架集成。
基本概念
先來熟悉在liveMedia庫中Source,Sink以及Filter等概念。Sink就是消費數(shù)據(jù)的對象,比如把接收到的數(shù)據(jù)存儲到文件,這個文件就是一個Sink。Source就是生產(chǎn)數(shù)據(jù)的對象,比如通過RTP讀取數(shù)據(jù)。數(shù)據(jù)流經(jīng)過多個'source'和'sink's,下面是一個示例:
'source1' -> 'source2' (a filter) ->'source3' (a filter) -> 'sink'
從其它Source接收數(shù)據(jù)的source也叫做"filters"。Module是一個sink或者一個filter。數(shù)據(jù)接收的終點是Sink類,MediaSink是所有Sink類的基類。Sink類實現(xiàn)對數(shù)據(jù)的處理是通過實現(xiàn)純虛函數(shù)continuePlaying(),通常情況下continuePlaying調(diào)用fSource->getNextFrame來為Source設(shè)置數(shù)據(jù)緩沖區(qū),處理數(shù)據(jù)的回調(diào)函數(shù)等,fSource是MediaSink的類型為FramedSource*的類成員。
基本控制流程
基于liveMedia的應(yīng)用程序的控制流程如下:
應(yīng)用程序是事件驅(qū)動的,使用如下方式的循環(huán)
while (1) {
通過查找讀網(wǎng)絡(luò)句柄的列表和延遲隊列(delay queue)來發(fā)現(xiàn)需要完成的任務(wù)
完成這個任務(wù)
}
對于每個sink,在進入這個循環(huán)之前,應(yīng)用程序通常調(diào)用下面的方法來啟動需要做的生成任務(wù):?
Each 'source' module's implementation of "doGetNextFrame()" worksby arranging for an 'after getting' function to be called (from anevent handler) when new data becomes available for thecaller.
Note that the flow of data from 'sources' to 'sinks' happens withineach application, and doesn't necessarily correspond to the sendingor receiving of network packets. For example, a server application(such as "testMP3Streamer") that sends RTP packets will do so usingone or more "RTPSink" modules. These "RTPSink" modules receive datafrom other, "*Source" modules (e.g., to read data from a file),and, as a side effect, transmit RTP packets.
live555代碼解讀之一:RTSP連接的建立過程
RTSPServer類用于構(gòu)建一個RTSP服務(wù)器,該類同時在其內(nèi)部定義了一個RTSPClientSession類,用于處理單獨的客戶會話。
首先創(chuàng)建RTSP服務(wù)器(具體實現(xiàn)類是DynamicRTSPServer),在創(chuàng)建過程中,先建立Socket(ourSocket)在TCP的554端口進行監(jiān)聽,然后把連接處理函數(shù)句柄(RTSPServer::incomingConnectionHandler)和socket句柄傳給任務(wù)調(diào)度器(taskScheduler)。
任務(wù)調(diào)度器把socket句柄放入后面select調(diào)用中用到的socket句柄集(fReadSet)中,同時將socket句柄和incomingConnectionHandler句柄關(guān)聯(lián)起來。接著,主程序開始進入任務(wù)調(diào)度器的主循環(huán)(doEventLoop),在主循環(huán)中調(diào)用系統(tǒng)函數(shù)select阻塞,等待網(wǎng)絡(luò)連接。
當(dāng)RTSP客戶端輸入(rtsp://192.168.1.109/1.mpg)連接服務(wù)器時,select返回對應(yīng)的scoket,進而根據(jù)前面保存的對應(yīng)關(guān)系,可找到對應(yīng)處理函數(shù)句柄,這里就是前面提到的incomingConnectionHandler了。在incomingConnectionHandler中創(chuàng)建了RTSPClientSession,開始對這個客戶端的會話進行處理。
live555代碼解讀之二:DESCRIBE請求消息處理過程
RTSP服務(wù)器收到客戶端的DESCRIBE請求后,根據(jù)請求URL(rtsp://192.168.1.109/1.mpg),找到對應(yīng)的流媒體資源,返回響應(yīng)消息。live555中的ServerMediaSession類用來處理會話中描述,它包含多個(音頻或視頻)的子會話描述(ServerMediaSubsession)。
上節(jié)我們談到RTSP服務(wù)器收到客戶端的連接請求,建立了RTSPClientSession類,處理單獨的客戶會話。在建立RTSPClientSession的過程中,將新建立的socket句柄(clientSocket)和RTSP請求處理函數(shù)句柄RTSPClientSession::incomingRequestHandler傳給任務(wù)調(diào)度器,由任務(wù)調(diào)度器對兩者進行一對一關(guān)聯(lián)。當(dāng)客戶端發(fā)出RTSP請求后,服務(wù)器主循環(huán)中的select調(diào)用返回,根據(jù)socket句柄找到對應(yīng)的incomingRequestHandler,開始消息處理。先進行消息的解析,如果發(fā)現(xiàn)請求是DESCRIBE則進入handleCmd_DESCRIBE函數(shù)。根據(jù)客戶端請求URL的后綴(例如是1.mpg),調(diào)用成員函數(shù)DynamicRTSPServer::lookupServerMediaSession查找對應(yīng)的流媒體信息ServerMediaSession。如果ServerMediaSession不存在,但是本地存在1.mpg文件,則創(chuàng)建一個新的ServerMediaSession。在創(chuàng)建ServerMediaSession過程中,根據(jù)文件后綴.mpg,創(chuàng)建媒體MPEG-1or2的解復(fù)用器(MPEG1or2FileServerDemux)。再由MPEG1or2FileServerDemux創(chuàng)建一個子會話描述MPEG1or2DemuxedServerMediaSubsession。最后由ServerMediaSession完成組裝響應(yīng)消息中的SDP信息(SDP組裝過程見下面的描述),然后將響應(yīng)消息發(fā)給客戶端,完成一次消息交互。
SDP消息組裝過程:
ServerMediaSession負責(zé)產(chǎn)生會話公共描述信息,子會話描述由MPEG1or2DemuxedServerMediaSubsession產(chǎn)生。MPEG1or2DemuxedServerMediaSubsession在其父類成員函數(shù)OnDemandServerMediaSubsession::sdpLines()中生成會話描述信息。在sdpLines()實現(xiàn)里面,創(chuàng)建一個虛構(gòu)(dummy)的FramedSource(具體實現(xiàn)類為MPEG1or2AudioStreamFramer和MPEG1or2VideoStreamFramer)和RTPSink(具體實現(xiàn)類為MPEG1or2AudioRTPSink和MPEG1or2VideoRTPSink),最后調(diào)用setSDPLinesFromRTPSink(...)成員函數(shù)生成子會話描述。
以上涉及到的類以及繼承關(guān)系:
Medium <- ServerMediaSession
Medium <- ServerMediaSubsession <-OnDemandServerMediaSubsession <-MPEG1or2DemuxedServerMediaSubsession
Medium <- MediaSource <- FramedSouse<- FramedFileSource <-ByteStreamFileSource
Medium <- MediaSource <- FramedSouse<- MPEG1or2DemuxedElementaryStream
Medium <- MPEG1or2FileServerDemux
Medium <- MPEG1or2Demux
Medium <- MediaSource <- FramedSouse<- MPEG1or2DemuxedElementaryStream
Medium <- MediaSource <- FramedSouse<- FramedFilter <-MPEGVideoStreamFramer <-MPEG1or2VideoStreamFramer
Medium <- MediaSink <- RTPSink<- MultiFramedRTPSink <- VideoRTPSink<- MPEG1or2VideoRTPSink
live555代碼解讀之三:SETUP 和PLAY請求消息處理過程
前面已經(jīng)提到RTSPClientSession類,用于處理單獨的客戶會話。其類成員函數(shù)handleCmd_SETUP()處理客戶端的SETUP請求。調(diào)用parseTransportHeader()對SETUP請求的傳輸頭解析,調(diào)用子會話(這里具體實現(xiàn)類為OnDemandServerMediaSubsession)的getStreamParameters()函數(shù)獲取流媒體發(fā)送傳輸參數(shù)。將這些參數(shù)組裝成響應(yīng)消息,返回給客戶端。
獲取發(fā)送傳輸參數(shù)的過程:調(diào)用子會話(具體實現(xiàn)類MPEG1or2DemuxedServerMediaSubsession)的createNewStreamSource(...)創(chuàng)建MPEG1or2VideoStreamFramer,選擇發(fā)送傳輸參數(shù),并調(diào)用子會話的createNewRTPSink(...)創(chuàng)建MPEG1or2VideoRTPSink。同時將這些信息保存在StreamState類對象中,用于記錄流的狀態(tài)。
客戶端發(fā)送兩個SETUP請求,分別用于建立音頻和視頻的RTP接收。
PLAY請求消息處理過程
RTSPClientSession類成員函數(shù)handleCmd_PLAY()處理客戶端的播放請求。首先調(diào)用子會話的startStream(),內(nèi)部調(diào)用MediaSink::startPlaying(...),然后是MultiFramedRTPSink::continuePlaying(),接著調(diào)用MultiFramedRTPSink::buildAndSendPacket(...)。buildAndSendPacke內(nèi)部先設(shè)置RTP包頭,內(nèi)部再調(diào)用MultiFramedRTPSink::packFrame()填充編碼幀數(shù)據(jù)。
packFrame內(nèi)部通過 FramedSource::getNextFrame(),接著MPEGVideoStreamFramer::doGetNextFrame(),再接著經(jīng)過MPEGVideoStreamFramer::continueReadProcessing(),FramedSource::afterGetting(...),??MultiFramedRTPSink::afterGettingFrame(...),??MultiFramedRTPSink::afterGettingFrame1(...)等一系列繁瑣調(diào)用,最后到了 MultiFramedRTPSink::sendPacketIfNecessary(),這里才真正發(fā)送RTP數(shù)據(jù)包。然后是計算下一個數(shù)據(jù)包發(fā)送時間,把MultiFramedRTPSink::sendNext(...)函數(shù)句柄傳給任務(wù)調(diào)度器,作為一個延時事件調(diào)度。在主循環(huán)中,當(dāng)MultiFramedRTPSink::sendNext()被調(diào)度時,又開始調(diào)用MultiFramedRTPSink::buildAndSendPacket(...)開始新的發(fā)送數(shù)據(jù)過程,這樣客戶端可以源源不斷的收到服務(wù)器傳來的RTP包了。
發(fā)送RTP數(shù)據(jù)包的間隔計算方法:
Update the time at which the next packet should be sent, based onthe duration of the frame that we just packed into it.
涉及到一些類有:
MPEGVideoStreamFramer: A filter that breaks up an MPEG videoelementary stream into headers and frames
MPEG1or2VideoStreamFramer: A filter that breaks up an MPEG 1 or 2video elementary stream into frames for: Video_Sequence_Header,GOP_Header, Picture_Header
MPEG1or2DemuxedElementaryStream: A MPEG 1 or 2 Elementary Stream,demultiplexed from a Program Stream
MPEG1or2Demux: Demultiplexer for a MPEG 1 or 2 Program Stream
ByteStreamFileSource: A file source that is a plain byte stream(rather than frames)
MPEGProgramStreamParser: Class for parsing MPEG programstream
StreamParser: Abstract class for parsing a byte stream
StreamState:A class that represents the state of an ongoing stream 復(fù)合/分離的過程稱為系統(tǒng)復(fù)接/分接,據(jù)傳輸媒體的質(zhì)量不同,MPEG-2中定義了兩種復(fù)合信息流:傳送流(TS)和節(jié)目流(PS:ProgramStream)
RTSP點播消息流程
Real Time Streaming Protocol或者RTSP(實時流媒體協(xié)議),是由Real network 和Netscape共同提出的如何有效地在IP網(wǎng)絡(luò)上傳輸流媒體數(shù)據(jù)的應(yīng)用層協(xié)議。RTSP提供一種可擴展的框架,使能夠提供可控制的,按需傳輸實時數(shù)據(jù),比如音頻和視頻文件。源數(shù)據(jù)可以包括現(xiàn)場數(shù)據(jù)的反饋和存貯的文件。rtsp對流媒體提供了諸如暫停,快進等控制,而它本身并不傳輸數(shù)據(jù),rtsp作用相當(dāng)于流媒體服務(wù)器的遠程控制。傳輸數(shù)據(jù)可以?
通過傳輸層的tcp,udp協(xié)議,rtsp也提供了基于rtp傳輸機制的一些有效的方法。
RTSP消息格式:?
RTSP的消息有兩大類,一是請求消息(request),一是回應(yīng)消息(response),兩種消息的格式不同.?
請求消息:?
方法 URI RTSP版本 CR LF?
消息頭 CR LF CR LF?
消息體 CR LF?
其中方法包括OPTION回應(yīng)中所有的命令,URI是接受方的地址,例如?
:rtsp://192.168.20.136?
RTSP版本一般都是 RTSP/1.0.每行后面的CRLF表示回車換行,需要接受端有相應(yīng)的解?
析,最后一個消息頭需要有兩個CR LF?
回應(yīng)消息:?
RTSP版本 狀態(tài)碼 解釋 CR LF?
消息頭 CR LF CR LF?
消息體 CR LF?
其中RTSP版本一般都是RTSP/1.0,狀態(tài)碼是一個數(shù)值,200表示成功,解釋是與狀態(tài)碼對應(yīng)?
的文本解釋.?
簡單的rtsp交互過程:?
C表示rtsp客戶端,S表示rtsp服務(wù)端?
1.C->S:OPTION request//詢問S有哪些方法可用?
1.S->C:OPTION response//S回應(yīng)信息中包括提供的所有可用方法?
?
2.C->S:DESCRIBE request//要求得到S提供的媒體初始化描述信息?
2.S->C:DESCRIBE response//S回應(yīng)媒體初始化描述信息,主要是sdp?
?
3.C->S:SETUP request//設(shè)置會話的屬性,以及傳輸模式,提醒S建立會?
話?
3.S->C:SETUP response//S建立會話,返回會話標(biāo)識符,以及會話相關(guān)信息?
?
?
4.C->S:PLAY request //C請求播放?
4.S->C:PLAY response//S回應(yīng)該請求的信息?
?
S->C:發(fā)送流媒體數(shù)據(jù)?
5.C->S:TEARDOWN request//C請求關(guān)閉會話?
5.S->C:TEARDOWN response//S回應(yīng)該請求?
?
上述的過程是標(biāo)準的、友好的rtsp流程,但實際的需求中并不一定按部就班來。?
其中第3和4步是必需的!第一步,只要服務(wù)器客戶端約定好,有哪些方法可用,則option請求可以不要。第二步,如果我們有其他途徑得到媒體初始化描述信息(比如http請求等等),則我們也不需要通過rtsp中的describe請求來完成。第五步,可以根據(jù)系統(tǒng)需求的設(shè)計來決定是否需要。?
?
rtsp中常用方法:?
?
1.OPTION?
目的是得到服務(wù)器提供的可用方法:?
OPTIONS rtsp://192.168.20.136:5000/xxx666RTSP/1.0?
CSeq: 1 //每個消息都有序號來標(biāo)記,第一個包通常是option請求消息?
User-Agent: VLC media player (LIVE555 Streaming Mediav2005.11.10)?
?
服務(wù)器的回應(yīng)信息包括提供的一些方法,例如:?
RTSP/1.0 200 OK?
Server: UServer 0.9.7_rc1?
Cseq: 1 //每個回應(yīng)消息的cseq數(shù)值和請求消息的cseq相對應(yīng)?
Public: OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE,SCALE,?
GET_PARAMETER //服務(wù)器提供的可用的方法?
2.DESCRIBE?
C向S發(fā)起DESCRIBE請求,為了得到會話描述信息(SDP):?
DESCRIBE rtsp://192.168.20.136:5000/xxx666RTSP/1.0?
?
CSeq: 2?
token:?
Accept: application/sdp?
User-Agent: VLC media player (LIVE555 Streaming Mediav2005.11.10)?
?
服務(wù)器回應(yīng)一些對此會話的描述信息(sdp):?
RTSP/1.0 200 OK?
Server: UServer 0.9.7_rc1?
Cseq: 2?
x-prev-url: rtsp://192.168.20.136:5000?
x-next-url: rtsp://192.168.20.136:5000?
x-Accept-Retransmit: our-retransmit?
x-Accept-Dynamic-Rate: 1?
Cache-Control: must-revalidate?
Last-Modified: Fri, 10 Nov 2006 12:34:38GMT?
Date: Fri, 10 Nov 2006 12:34:38 GMT?
Expires: Fri, 10 Nov 2006 12:34:38 GMT?
Content-Base:rtsp://192.168.20.136:5000/xxx666/?
Content-Length: 344?
Content-Type: application/sdp?
?
v=0 //以下都是sdp信息?
o=OnewaveUServerNG 1451516402 1025358037 IN IP4192.168.20.136?
s=/xxx666?
u=http:///?
e=admin@?
c=IN IP4 0.0.0.0?
t=0 0?
a=isma-compliance:1,1.0,1?
?
a=range:npt=0-?
m=video 0 RTP/AVP 96//m表示媒體描述,下面是對會話中視頻通道的媒體描述?
a=rtpmap:96 MP4V-ES/90000?
a=fmtp:96?
profile-level-id=245;config=000001B0F5000001B509000001000000012000C888B0E0E0FA62D089028307?
?
a=control:trackID=0//trackID=0表示視頻流用的是通道0?
?
3.SETUP?
客戶端提醒服務(wù)器建立會話,并確定傳輸模式:?
SETUP rtsp://192.168.20.136:5000/xxx666/trackID=0RTSP/1.0?
CSeq: 3?
Transport:RTP/AVP/TCP;unicast;interleaved=0-1?
User-Agent: VLC media player (LIVE555 Streaming Mediav2005.11.10)?
//uri中帶有trackID=0,表示對該通道進行設(shè)置。Transport參數(shù)設(shè)置了傳輸模式,包?
的結(jié)構(gòu)。接下來的數(shù)據(jù)包頭部第二個字節(jié)位置就是interleaved,它的值是每個通道都?
不同的,trackID=0的interleaved值有兩個0或1,0表示rtp包,1表示rtcp包,接受端?
根據(jù)interleaved的值來區(qū)別是哪種數(shù)據(jù)包。?
?
服務(wù)器回應(yīng)信息:?
RTSP/1.0 200 OK?
Server: UServer 0.9.7_rc1?
Cseq: 3?
Session: 6310936469860791894 //服務(wù)器回應(yīng)的會話標(biāo)識符?
Cache-Control: no-cache?
Transport:RTP/AVP/TCP;unicast;interleaved=0-1;ssrc=6B8B4567?
4.PLAY?
客戶端發(fā)送播放請求:?
PLAY rtsp://192.168.20.136:5000/xxx666RTSP/1.0?
CSeq: 4?
Session: 6310936469860791894?
Range: npt=0.000- //設(shè)置播放時間的范圍?
User-Agent: VLC media player (LIVE555 Streaming Mediav2005.11.10)?
服務(wù)器回應(yīng)信息:?
RTSP/1.0 200 OK?
Server: UServer 0.9.7_rc1?
Cseq: 4?
Session: 6310936469860791894?
Range: npt=0.000000-?
RTP-Info:url=trackID=0;seq=17040;rtptime=1467265309?
//seq和rtptime都是rtp包中的信息?
5.TEARDOWN?
客戶端發(fā)起關(guān)閉請求:?
TEARDOWN rtsp://192.168.20.136:5000/xxx666RTSP/1.0?
CSeq: 5?
Session: 6310936469860791894?
User-Agent: VLC media player (LIVE555 Streaming Mediav2005.11.10)?
服務(wù)器回應(yīng):?
RTSP/1.0 200 OK?
Server: UServer 0.9.7_rc1?
Cseq: 5?
Session: 6310936469860791894?
Connection: Close?
?
以上方法都是交互過程中最為常用的,其它還有一些重要的方法如?
get/set_parameter,pause,redirect等等?
ps:?
sdp的格式?
v=<version>?
o=<username><session id><version> <networktype> <address type><address>?
s=<sessionname>?
i=<sessiondescription>?
u=<URI>?
e=<emailaddress>?
p=<phonenumber>?
c=<network type><address type><connectionaddress>?
b=<modifier>:<bandwidth-value>?
t=<start time><stop time>?
r=<repeat interval><active duration><list of offsets fromstart-time>?
z=<adjustment time><offset> <adjustmenttime> <offset>....?
k=<method>?
k=<method>:<encryptionkey>?
a=<attribute>?
a=<attribute>:<value>?
m=<media><port><transport> <fmtlist>?
v = (協(xié)議版本)?
o = (所有者/創(chuàng)建者和會話標(biāo)識符)?
s = (會話名稱)?
i = * (會話信息)?
u = * (URI 描述)?
e = * (Email 地址)?
p = * (電話號碼)?
c = * (連接信息)?
b = * (帶寬信息)?
z = * (時間區(qū)域調(diào)整)?
k = * (加密密鑰)?
a = * (0 個或多個會話屬性行)?
時間描述:?
t = (會話活動時間)?
r = * (0或多次重復(fù)次數(shù))?
媒體描述:?
m = (媒體名稱和傳輸?shù)刂?#xff09;?
i = * (媒體標(biāo)題)?
c = * (連接信息 — 如果包含在會話層則該字段可選)?
b = * (帶寬信息)?
k = * (加密密鑰)?
a = * (0 個或多個媒體屬性行)?
參考文章:rfc2326(rtsp);rfc2327(sdp)?
RTSP點播消息流程實例(客戶端:VLC, RTSP服務(wù)器:LIVE555 MediaServer)?
?
1)C(Client)-> M(MediaServer)?
OPTIONS rtsp://192.168.1.109/1.mpgRTSP/1.0?
CSeq: 1?
user-Agent: VLC media player(LIVE555 Streaming Mediav2007.02.20)?
?
1)M -> C?
RTSP/1.0 200 OK?
CSeq: 1?
Date: wed, Feb 20 2008 07:13:24 GMT?
Public: OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY,PAUSE?
?
2)C -> M?
DESCRIBE rtsp://192.168.1.109/1.mpgRTSP/1.0?
CSeq: 2?
Accept: application/sdp?
User-Agent: VLC media player(LIVE555 Streaming Mediav2007.02.20)?
?
2)M -> C?
RTSP/1.0 200 OK?
CSeq: 2?
Date: wed, Feb 20 2008 07:13:25 GMT?
Content-Base: rtsp://192.168.1.109/1.mpg/?
Content-type: application/sdp?
Content-length: 447?
v=0?
o =- 2284269756 1 IN IP4 192.168.1.109?
s=MPEG-1 or 2 program Stream, streamed by the LIVE555 MediaServer?
i=1.mpg?
t=0 0?
a=tool:LIVE555 Streaming Media v2008.02.08?
a=type:broadcast?
a=control:*?
a=range:npt=0-66.181?
a=x-qt-text-nam:MPEG-1 or Program Stream, streamed by theLIVE555 Media Server?
a=x-qt-text-inf:1.mpg?
m=video 0 RTP/AVP 32?
c=IN IP4 0.0.0.0?
a=control:track1?
m=audio 0 RTP/AVP 14?
c=IN IP4 0.0.0.0?
a=control:track2?
?
3)C -> M?
SETUP rtsp://192.168.1.109/1.mpg/track1RTSP/1.0?
CSeq: 3?
Transport: RTP/AVP;unicast;client_port=1112-1113?
User-Agent: VLC media player(LIVE555 Streaming Mediav2007.02.20)?
?
3)M -> C?
RTSP/1.0 200 OK?
CSeq: 3?
Date: wed, Feb 20 2008 07:13:25 GMT?
Transport:RTP/AVP;unicast;destination=192.168.1.222;source=192.168.1.109;client_port=1112-1113;server_port=6970-6971?
Session: 3?
?
4)C -> M?
SETUP rtsp://192.168.1.109/1.mpg/track2RTSP/1.0?
CSeq: 4?
Transport: RTP/AVP;unicast;client_port=1114-1115?
Session: 3?
User-Agent: VLC media player(LIVE555 Streaming Mediav2007.02.20)?
?
4)M -> C?
RTSP/1.0 200 OK?
CSeq: 4?
Date: wed, Feb 20 2008 07:13:25 GMT?
Transport:RTP/AVP;unicast;destination=192.168.1.222;source=192.168.1.109;client_port=1114-1115;server_port=6972-6973?
Session: 3?
?
5)C -> M?
PLAY rtsp://192.168.1.109/1.mpg/ RTSP/1.0?
CSeq: 5?
Session: 3?
Range: npt=0.000-?
User-Agent: VLC media player(LIVE555 Streaming Mediav2007.02.20)?
?
5)M -> C?
RTSP/1.0 200 OK?
CSeq: 5?
Range: npt=0.000-?
Session: 3?
RTP-Info:url=rtsp://192.168.1.109/1.mpg/track1;seq=9200;rtptime=214793785,url=rtsp://192.168.1.109/1.mpg/track2;seq=12770;rtptime=31721
TS流與PS流的區(qū)別在于TS流的包結(jié)構(gòu)是固定長度的,而PS流的包結(jié)構(gòu)是可變長度。PS包與TS包在結(jié)構(gòu)上的這種差異,導(dǎo)致了它們對傳輸誤碼具有不同的抵抗能力,因而應(yīng)用的環(huán)境也有所不同。TS碼流由于采用了固定長度的包結(jié)構(gòu),當(dāng)傳輸誤碼破壞了某一TS包的同步信息時,接收機可在固定的位置檢測它后面包中的同步信息,從而恢復(fù)同步,避免了信息丟失。而PS包由于長度是變化的,一旦某一PS包的同步信息丟失,接收機無法確定下一包的同步位置,就會造成失步,導(dǎo)致嚴重的信息丟失。因此,在信道環(huán)境較為惡劣,傳輸誤碼較高時,一般采用TS碼流;而在信道環(huán)境較好,傳輸誤碼較低時,一般采用PS碼流由于TS碼流具有較強的抵抗傳輸誤碼的能力,因此目前在傳輸媒體中進行傳輸?shù)腗PEG-2碼流基本上都采用了TS碼流的包
格。
用live555開發(fā)流媒體播放器應(yīng)用程序的方法
總結(jié)
以上是生活随笔為你收集整理的H264 流媒体 编码汇总的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 程序员自我提高的几点建议 很实诚
- 下一篇: 我们正处在“后开源”时代?