四、 串流伺服器實作細節
4.5 建立以及傳送 RTP 封包
4.5.2 Live555 封裝演算法分析
因為封包大小不可大於MTU,不然將會被強制分割(IP fragment),而被強制切割 出來的封包也會加上表頭成為新的overhead,在更糟的情況下會發生播延錯誤
(error–propagation)的問題,也就是這些被強制分割的封包中如果損毀或遺失也將產生連 鎖效應使得其他封包無法正常解碼播放,因此才會有RFC3016[7]的誕生。
因此,Live555 RTSPServer所實現的封裝演算法主要是以目前VOP(frame)與MTU中 的較小值作為實際傳送封包的大小,若是VOP太大而無法放進一個封包時,則由程式主 動對VOP進行切割(利用setPacketSizes(1000,1448)這個函數),細分成數個封包來傳送,
此目的在於使MPEG-4 ES所產生的封包數最少,同時避免IP fragmented帶給系統的負 擔,程式碼如下所示,可以在MultiFramedRTPSink.cpp程式中找到這個
isTooBigForAPacket()函數,在該函數中會以一個overflowBytes變數來記錄溢位的位元組 大小。
而超過 MTU 的 VOP 資料便會分裝到其他封包中,而 Live555 RTSPServer 原則上 不會把 VOP 的表頭複製到各分裝的封包,其目的和優點是可以提高封包/通道的使用 率,而其缺點便如圖 4.11 所看到的,單一封包遺失可能造成前後封包無法被解碼的情形 發生。而最後一個封包即使有多餘的空間,我們也不會把下一個 VOP 的資料包裝進來。
不過以目前國內ISP(Internet Service Provider)的平均封包遺失率[10]來說,採用此封 包演算法是相當符合實際需求的,即便是在國外,封包遺失率也大多在1~3%範圍之中,
,因此我們在封包演算法的實作上便是以達到較高封包/頻寬使用率為優先考量。
上述的演算法程式實作在 Live555 的 MultiFramedRTPSink.cpp 程式中,主要實現函數如 下所述:
isTooBigForAPacket()-檢查訊框大小是否有超過一個封包(MTU)的大小限制 sendPacketIfNecessary()-判斷是否有必要把封包傳送出去
上述兩個函數主要由 afterGettingFrame1()呼叫之,而在 packFrame 的過程中,Live
的封裝演算法難免會遇到下一個 frame 打包進來後會超過 MTU 的情形,通常我們一般 的作法是直接把溢位的資料使用 memmove()函數把資料搬到下一個封包中,但因為使用
memmove()這個函數來進行溢位資料在記憶體中的不斷複製與搬移是很沒有效率的一 個重複動作,也就是會增加這個演算法執行時帶給系統的負擔,下面所示的部分為 Live 封裝演算法的核心部分。
當封包有上述四種情形之一時便會進入 sendPacketIfNecessary()函數,這四種傳送封包 的條件解說如下:
1.當封包大小>=我們設定較喜歡傳送的封包大小,也就是 setPacketSizes(1000,1448)中 的 1000,則 isPreferredSize()回傳為真,目的是確保在讀到下一個 VOP 前,封包大小 至少會大於 1000 Bytes。
2.有溢位情形發生時,溢位加速處理函數便是特別為了這個情形所設置的。
3.上一個 frame 的切割標記布林值為 TRUE (以及)允許切割之後把其它的 VOP frame 再 加進來(預設為 false),合起來的意思就是『當 frame 被切割之後,如果遇到下一個 VOP
的 frame,我們不會把它給加進來』。
4.封包開始打包時還允許 frame 一直加進來(但目前程式預設為 true,故第四個判斷條件 不會進入 sendPacketIfNecessary())。
而在 sendPacketIfNecessary()中包含了一個加速溢位處理的機制,其程式碼如下所 述,其目的在於算出每一個封包的『起始位置、封包大小以及封包偏移量』,舉例來說 我們有一個大小為 4000 Bytes 的 frame,故我們將會分成 3 個封包來傳送之,也就是
P1=1436,P2=1436,P3=1128,而 P2 以及 P3 我們可以看到都屬於溢位的封包,一般 沒有經驗的作法我們會使用 memmove()函數進行溢位資料的複製與搬移,而 memmove() 這個動作相對於使用指標自動指向下一個溢位資料在 frame 中的起始點自然是複雜許 多。
上面的程式碼中,newPacketStart 便是每一個封包的起始位址,curPacketSize()會傳回目 前 封 包 的 大 小 並 減 掉 相 關 表 頭 的 大 小 (rtpHeaderSize + fSpecialHeaderSize + frameSpecificHeaderSize()),也就是我們如果以 setPacketSizes 設定最大封包長度為
1448,則 newPacketStart=1448-12=1436,因此我們便可以呼叫 fOutBuf->resetPacketStart() 來設置下一個封包的起始位址。
由此我們可以瞭解要發展出一個高效能的串流應用程式,如同安德定理(Amdahl’s
Law)告訴我們的,我們要作的便是把程式『最常用』的部分加速之。事實上這些溢位處
理函數的程式碼並不會很難,也不會是我們主要談論到的重點,我們在這邊觀察的重點 應該是 Live 的此種作法帶給我們的程式實作上的『觀念啟發』。也就是在串流程式開 發完畢後,應該活用一些 profile 之類的軟體去觀察串流程式的哪一個部分執行時間最 多,進而想辦法去改良之,因為這個改良帶給系統的增益最大。
第五章 串流程式開發手扎
由前面第二章至第四章的剖析中我們瞭解了串流伺服器的核心組成,因此在開發串 流媒體程式時,基於物件導向程式設計(OOP,Object-Oriented Programming)的前提下,
我們便可以直接運用 Live555 所提供的類別(class)來協助程式的開發。
同時 Live555 也已經把串流伺服器的核心元件給模組化,舉例來說便是第二章的 RTSPServer 模組(結合了 socket 與 RTSP)以及第三章提到的封包包裝與傳送模組,如果 我們覺得模組(Module)中某個元件(Class/Object/Instance)的效能不夠好,我們亦可 以動手自己修正或加入新的演算法來增進串流系統的效能,這也是我們為何需要對 Live555 所提供的原始碼(source code)作如此深入追蹤的原因。
Live555 給與我們的收穫在於串流程式設計上的經驗以及實作上的指引,在 4.1 章 節串流伺服器的多工中,我們瞭解了 select()以及 fork()所帶給串流系統效能的影響;
並且使用 select()的話其第五個時間參數為何要設成一百萬秒,試想我們有一個即時監 控伺服器平台,如果這個平台剛好有一個 11.5 天的週期都沒有用戶端連線,在 11.6 天 後此伺服器便無法再接收連線,這當然是一個串流系統上的 nontrival issue。
而在 4.2 章節中的是如何實作 RTSP parser 的指引;在 4.5 章節中,一個 RTP 封包 經過封裝演算法的處理後便會變成一個結構化封包。同時在 Live555 所選擇的封裝演算 法中因為常遇到 frame 大於 MTU 的情形,故必須作溢位資料處理的機制,而 Live 亦針 對這些溢位資料的處理改用對系統負擔比較低的作法來完成之,目的是增進串流系統的
執行效能(安德定理(Amdahl’s Law)的應用)。
綜合以上結論,我們可以說 Live555 可以快速地替我們要開發的串流程式加入所需 要的核心模組,避免重新發明輪子的窘境,如果我們想要替其中一個核心模組甚至是元 件作演算法的再昇華亦是一個很好的研究方向。
第六章 結論
流的軟體技術而成為很好的 Surveillance system,如 NUUO[12]以及ATEME[13],透過本論文的剖析後,其背後所使用的根本技術相信大家能有一個
參考文獻
[1] H. Schulzrinne, A. Rao, and R. Lanphier, "Real Time Streaming Protocol (RTSP)", RFC 2326 ,April 1998.
[2] M. Handley, V. Jacobson, “SDP: Session Description Protocol”,RFC2327, April 1998
[3] http://www.videolan.org/vlc/
[4] http://www.live555.com/
[5] D. Hoffman,G. Fernando,"RTP Format for MPEG1/MPEG2 Video" , RFC 2250,January 1998 3.
[6] H. Schulzrinne, Columbia University, “RTP: A Transport Protocol for Real-Time “, RFC3550. Titl, July 2003.
[7] Y. Kikuchi(Toshiba),T. Nomura(NEC),S. Fukunaga(Oki),Y. Matsui (Matsushita),H.
Kimata(NTT), “Payload Format for MPEG-4 Audio/Visual Streams“,RFC 3016,November 2000
[8] ISO/IEC 14496-2:2001(E)(Page 32)
[9] 張為棟,『整合式多媒體串流平台的發展與實作』,國立交通大學電信所碩士 論文,95 學年度。
[10]電信總局http://www.dgt.gov.tw/Chinese/public-cares/12.5/12.5.2/lost-better.shtml [11] http://www.youtube.com
[12] http://www.nuuo.com/
[13] http://www.ateme.com
[14] H. Schulzrinne , "RTP Profile for Audio and Video Conferences with Minimal Control",RFC1890 ,January 1996
[15] UNIX 網路程式設計網路應用程式設計介面:Socket 與 XTI 作者:W.Richard Stevens 譯者:林慶德 出版:培生
附錄一
1.How to configure and build the code on Windows
1. Unpack and extract the '.tar.gz' file (using an application such as "WinZip").
2. If the 'tools' directory on your Windows machine is something other than
"c:\Program Files\DevStudio\Vc", change the "TOOLS32 =" line in the file
"win32config".
3. In a command shell, 'cd' to the "live" directory, and run genWindowsMakefiles This will generate - in each subdirectory - a "*.mak" makefile suitable for use by (e.g.) Microsoft Visual Studio.
• Alternatively, if you're starting from a Unix machine, you can generate the Windows Makefiles by running ./genWindowsMakefiles
(after - if necessary - changing the "TOOLS32 =" line in the file "win32config", as noted above). Then, copy the "live" directories and its subdirectories (in ASCII mode) to a Windows machine.
• To use these Makefiles from within Visual Studio, use the "Open Workspace" menu command, then (in the file selection dialog) for "Files of type", choose "Makefiles (.mak)". Visual Studio should then prompt you, asking if you want to use this Makefile to set up a new project. Say "OK".
•
• Note that you will need to build each of the "UsageEnvironment", "groupsock",
"liveMedia", and "BasicUsageEnvironment" projects first, before building
"testProgs".
• If you wish, you can build the "WindowsAudioInputDevice" project also.
• Doug Kosovic notes: Visual C++ 2003 no longer comes with the old I/O Streams headers iostreams.h et al, or the corresponding library msvcirt.lib. So anybody trying to build the LIVE555 code with VC++
2003 might find the following useful: A non-sourcecode modification workaround for VC++ 2003 is to copy the missing headers and msvcirt.lib from VC++ 2002. In file 'win32config' add an extra -I switch to COMPILE_OPTS to find the old headers and a -LIBPATH: switch to LINK_OPTS_0 to find msvcirt.lib.
After testProgs.mak compiled ,there will be executable programs generated in testProgs folder.
2.How to configure and build the code on Unix (including Linux, Mac OS X, QNX, and other Posix-compliant systems)
The source code package can be found (as a ".tar.gz" file) here. Use "tar -x" and "gunzip" (or
"tar -xz", if available) to extract the package; then cd to the "live" directory. Then run ./genMakefiles <os-platform>
(os-platform 指的是鍵入你所使用的作業系統)
where <os-platform> is your target platform - e.g., "linux" or "solaris" - defined by a
"config.<os-platform>" file. This will generate a Makefile in the "live" directory and each subdirectory. Then run "make".
(完成”make”之後便會出現已經編譯可執行的範例程式)
附錄二 Overview of Live555 Server’s Module、Architecture and Performance
1. Live555 Server’s module and Function
Live555 Module Including Important Function
#1 Server Socket Bind Fcntl
Listen FD_ZERO Select
FD_ISSET Accept Recvfrom
Sendto Send Close
#2 RTSP_Parser parseRequestString handleCmd_OPTIONS handleCmd_DESCRIBE
handleCmd_SETUP handleCmd_PLAY handleCmd_PAUSE
handleCmd_TEARDOWN
#3Packet_Generator createNewStreamSource MPEG4VideoStreamFramer setPacketSizes
buildAndSendPacket packFrame isTooBigForAPacket sendPacketIfNecessary
2. Live555 Server’s Streaming Architecture
自傳
吳宗修,民國六十七年生於台南市。民國九十四年一月畢業於國立台北科技大學電 機工程系,同年二月進入國立交通大學IC設計產業碩士專班就讀,從事影音多媒體串流 相關研究。民國九十六年一月取得碩士學位,論文題目是「串流伺服器特性剖析」。
研究興趣是C/C++程式開發,希望有一天可以搞懂其中物件導向以及資料結構的奧 妙;生活興趣是電影、太空戰士(史克威爾系列)電玩、籃球以及羽球。
工作方面,曾在威盛電子以及金寶電子服務,分別任職於系統驗證部門(SV)以及硬 體設計部門(CI-2)。