crtmpserver系列(一):流媒體概述

薰衣草的旋律發表於2016-10-16

概述

所謂流媒體按照字面意思理解就是像流一樣的媒體,看起來像是廢話。流媒體現在司空見慣,所以一般人大概不會有疑問。事實上在流媒體還沒有出現的時候,基本上通過網路播放電影就不太現實。通過網路播放電影的時候必須先將整個檔案下載到電腦上然後才能播放,所以一般都要緩衝很久,這也是為什麼最開始迅雷等下載工具流行的原因,其實大多數都是用來下電影了。

流媒體最大的特點即是能夠做到邊下載邊播放,而不需要預先將整個檔案全部下載完成之後才能播放,這樣極大的改善了使用者體驗,也提高了實時性,使得網路直播成為可能。

那麼流媒體是如何做到邊下載邊播放的呢,我們要了解流媒體系統的組成。

流媒體系統的組成

一個完整的流媒體系統由這些部分組成,訊號採集,編碼,傳輸,解碼,輸出。

訊號採集:我們所說的流媒體系統都是要在計算機系統上面進行處理的,而系統中最主要的元素是音訊和視訊,從物理上面來說音訊實際上是一種通過物理震動形成的機械波,音訊採集即是將這種物理波轉換為電訊號進而轉換成二進位制的音訊資料,一般採集得到的原始音訊資料是PCM資料。視訊是什麼,視訊實際上是順序呈現出來的一幅幅連續的靜止影象,所以視訊實際上是由一幅幅靜止的影象組成,視訊的採集就是連續不斷的採集這些靜止的影象的過程,這些一幅幅的影象一般被稱為幀。那麼這些被稱為幀的靜止影象又是怎麼被採集的呢,實際上影象的表現形式並不是像聲音一樣的波,初中的物理我們就學過成像,我們之所以能夠看到影象,是因為照射在物體上的光反射到我們的眼睛進入視網膜,傳導到視神經最後被我們大腦感知。所以影象的採集是對光訊號的採集與轉換,將光訊號轉換為二進位制的影象幀的過程,一般我們得到的原始影象資料格式是YUV格式。

編碼:什麼是編碼,為什麼要編碼。假設我們的網路容量是無限的,傳輸速度也是無限大的,這當然是不需要編碼的。而實際上並不是,我們採集到的原始音視訊資料量是很大的,所以我們需要想辦法,將採集到的原始的音視訊二進位制資料量儘量變小,方便在網路上進行傳輸,同時又需要在還原(解碼)的時候儘量接近原始音視訊(損失,編碼也有分為有損和無損)。我們有時候稱編碼也叫壓縮編碼,其實壓縮這個概念類似我們平時的壓縮檔案的原理一樣,舉個簡單的例子,例如有一個文字檔案其內容是00000000000000000000000000000000000000000000000000 這麼一串字串,實際就是50個0字元,我們完全可以用最簡單的描述來壓縮,例如我們壓縮之後檔案內容變成50’0’表示這裡有50個0字元。在還原的時候這裡直接用50個0字元填充即可,這樣是不是會節約大量的空間呢,如果不是50個0而是一萬個0字元呢,這樣經過壓縮之後的壓縮比會更大,也就是說重複的冗餘資料越多,壓縮效率越高。當然實際的壓縮演算法肯定沒這麼簡單,說這麼個簡單的例子只是為了說明原理而已。視訊的編碼演算法有很多種,而且要複雜很多,每一種演算法的執行效率,壓縮比,損失率都不一樣。而原理都是一樣的,在最常見的概念中,有幀內壓縮和幀間壓縮。

什麼是幀內壓縮呢,假設一副影象的背景是純紅色,前面站個人(拍證件照的場景)。在編碼的時候一副影象被分成很多小塊(巨集塊),這樣由於背景中會有很多相鄰的小塊都是純紅色,很多純紅色的小塊都可以根據其周圍的小塊推斷出來,而不需要單獨編碼,這就是幀內壓縮,這種壓縮是在一個幀內部進行的,跟其前後的影象沒有關係。

那麼幀間壓縮又是什麼,如果一個視訊中相鄰的2副影象,背景都是純紅色,背景中有一個球在影象1中的位置是A點。在影象2中的位置是B點。實際上如果把影象1和影象2疊在一起會發現他們除了球的位置不一樣之外,其他的部分是一樣的,也就是說這兩幅相鄰的影象有很大一部分是相同的。在編碼第2副影象的時候完全可以只編碼其與上一副影象的不同部分。如果影象1我們需要完全編碼,影象1被稱為關鍵幀(一般稱為I幀),而影象2在還原的時候需要參考影象1,所以稱為參考幀(一般稱為P幀)。如果沒有關鍵幀,那麼參考幀是無法還原的。當然在編碼的時候,一幀不僅可以參考其上一幀,還可以參考其下一幀(雙向預測的幀間壓縮),例如一個球從左滾到右,這種運動是可以做預測的。這種當前幀的編碼參考其相鄰影象的演算法就是幀間壓縮演算法。

傳輸:經過採集,編碼我們現在已經獲得了音視訊資料幀,但是一般觀看視訊的一定不是在採集編碼的現場,否則就不需要傳輸了,傳輸的過程就是將編碼後的音視訊資料通過網路(網際網路,或者有線電視網等,我們只討論網際網路)傳輸到希望觀看的觀眾那裡。資料從一個地方傳遞到另一個地方這個過程就是傳輸。傳輸過程中最重要的當然是流媒體協議了,為什麼還需要流媒體協議?在流媒體播放的時候會有一些播放邏輯,例如,播放,暫停,跳轉,停止,快進,快退。另外在編碼之後的資料從一端傳遞到另一端,另一端需要將編碼之後的資料還原成編碼之前的原始資料才能播放。如何還原?必須得知道之前編碼是使用什麼演算法編碼的,在還原的時候才能採用相應的解碼演算法進行還原。那麼編碼的時候使用的是什麼演算法,這個也需要從一端通知到另一端,這個資訊也是在流媒體傳輸協議中會有的。除此之外還會有其他的一些邏輯資訊,例如視訊的幀率,關鍵幀的間隔(GOP Size)等。總結為一句話,編碼過後的音視訊資料通過網路從一端傳遞到另一端,在另一端對資料還原的時候需要一些資訊,並且需要支援一些播放場景的邏輯,這些都需要在流媒體協議中進行描述。目前最流行的流媒體協議,Adobe公司的RTMP,RTSP,微軟的MMS等。

解碼:經過編碼壓縮的資料必須還原成編碼之前的原始資料才能播放顯示,這個還原過程就是解碼的過程。

輸出:輸出的過程就是播放出來的過程,與採集的時候一樣,實際上這是將採集的原始音視訊資料經過模數轉換轉換成物理訊號,視訊訊號通過顯示器顯示出來,音訊訊號通過音響放出來。

媒體檔案封裝

我們之前討論的是媒體的流式播放,其實這個流式主要是指傳輸是流動的,而且視訊幀可以邊傳輸,邊解碼播放。如果我們希望將播放的內容儲存到磁碟上,就必須要有一種檔案格式來組織這些資料,以一定的結構來儲存這些音視訊資料。為什麼不直接將網路傳輸過來的內容直接寫到一個檔案中儲存呢,如果直接將所有傳輸過來的資料不加任何結構組織直接儲存的話,那麼在播放的時候如何播放?如何知道這些二進位制資料哪些是音訊哪些是視訊,如何知道每一幀音視訊資料在檔案中的邊界,如何知道該音視訊的內容是通過什麼編碼演算法編碼的,如何知道播放一幀資料之後再隔多長時間播放下一幀資料,如果像有的電影檔案需要多種字幕又如何組織。所以這就必須要有一種檔案格式能夠組織這些音視訊資料並且附加這些播放必須的資訊在檔案中。這就是媒體檔案的封裝。現存有很多種媒體檔案,有的是某個公司的專利,有的是國際標準,例如MP4,MP3,AVI,RMVB等等等等。所以如果要儲存這些流媒體資料到檔案中,則必須通過一定的檔案封裝格式將這些音視訊資料儲存在具有一定格式的媒體檔案中。

傳輸協議

目前使用的最多的流媒體傳輸協議當然是RTMP和RTSP了。微軟的MMS基本在工作中接觸的不多,特別是當前比較火爆的網際網路直播。還有一個需要特別提到的HTML5出來之後,很多以前通過flash客戶端承載RTMP協議的播放方式被以HLS替換了。但是實時性要求比較高的直播還是需要通過RTMP或者RTSP協議。HLS嚴格來說,其實我感覺都不能叫流媒體協議,HLS實際上基本可以認為是一個TS檔案的播放列表,沒有流媒體協議中的那些邏輯功能,播放,暫停,停止。應該說HLS僅僅是特定情況下出來的,主要是針對跨平臺的瀏覽器進行直播。我們所看到的HLS大部分都是通過移動裝置,PC機器上的瀏覽器來播放的。

需要指出的是,在與蘋果的HLS爭奪市場的過程中,同時出現了多種類似的技術,都是用的HTTP協議,一般我們稱為HTTP漸進式下載。例如微軟的Live Smooth Streaming 中文名稱為直播平滑流,這種技術需要微軟IIS7及以上版本的web伺服器和Silverlight客戶端支援。另外一種是開源的技術好像並不是某個公司出品,叫Http Pseudo-Streaming 中文名是偽流。目前只看到一個基於Apache伺服器的外掛H264 Streaming Module for Apache,客戶端貌似也是使用Flash Player。還有一種叫HTTP Dynamic Streaming 中文稱做HTTP動態流,是Adobe公司的技術方案,其服務端需要Flash Media Server支援,客戶端則是Flash Player。其實現在的Flash Media Server 也已經支援HLS了。蘋果的HLS就不說了現在很多伺服器以及開原始碼都支援HLS,客戶端呢只要支援HTML5的瀏覽器基本也都支援HLS,現在的HLS已經是主流。最後要說的是新出現的一種技術標準,MPEG-DASH目的為了統一這些技術方案,還在標準化中,如果真的標準化,也有可能取代HLS,畢竟HLS還沒有稱為正式標準,只是蘋果公司提交了個草案。

RTMP協議的發展得益於flash播放器的廣泛傳播,而RTSP協議則得益於其協議的開源。本系列要講解的crtmpserver就是基於RTMP協議的開源流媒體伺服器,開發語言為C++。等同的產品還有Red5 語言為Java也是開源。另外一個比較有影響力是wowza屬於閉源產品。此外RTMPDump專案是用的比較多的RTMP客戶端開源專案,其中的librtmp庫使用的很廣泛,C語言編寫。另外OpenRTMFP是基於p2p技術的RTMP。

相關文章