摘要:而我們喜歡的這些直播,他們用到的傳輸協(xié)議有一個(gè)通用名流媒體傳輸協(xié)議。要認(rèn)識(shí)流媒體協(xié)議,就離不開下面的三大系列名詞。
【前五篇】系列文章傳送門:
網(wǎng)絡(luò)協(xié)議 9 - TCP協(xié)議(下):聰明反被聰明誤
網(wǎng)絡(luò)協(xié)議 10 - Socket 編程(上):實(shí)踐是檢驗(yàn)真理的唯一標(biāo)準(zhǔn)
網(wǎng)絡(luò)協(xié)議 11 - Socket 編程(下):眼見為實(shí)耳聽為虛
網(wǎng)絡(luò)協(xié)議 12 - HTTP 協(xié)議:常用而不簡(jiǎn)單
網(wǎng)絡(luò)協(xié)議 13 - HTTPS 協(xié)議:加密路上無盡頭
????大家都會(huì)關(guān)注“在瀏覽器輸入一個(gè)地址,然后回車,會(huì)發(fā)生什么”這樣一個(gè)問題,但是有沒有想過這樣一個(gè)問題:主播開始直播,用戶打開客戶端觀看,這個(gè)過程發(fā)生了什么?
????隨著技術(shù)的發(fā)展,直播技術(shù)對(duì)人們生活的滲透日益加深。從最開始的游戲直播,到前幾天爆出來的教育直播,甚至現(xiàn)在都有直播招聘。
????而我們喜歡的這些直播,他們用到的傳輸協(xié)議有一個(gè)通用名-流媒體傳輸協(xié)議。
????要認(rèn)識(shí)流媒體協(xié)議,就離不開下面的三大系列名詞。
三大系列名詞系列一:AVI、MPEG、RMVB、MP4、MOV、FLV、WebM、WMV、ASF、MKV。是不是就 MP4 看著熟悉?
系列二:H.261、H.262、H.263、H.264、H.265。能認(rèn)出來幾個(gè)?別著急,重點(diǎn)關(guān)注 H.264。
系列三:MPEG-1、MPEG-2、MPEG-4、MPEG-7。是不是更懵逼了?
????在解釋上面的三大系列名詞之前,咱們先來了解下,視頻究竟是什么?
????博主記得小時(shí)候,經(jīng)常會(huì)玩一種叫動(dòng)感畫冊(cè)的東西。一本很小的畫冊(cè)上,每一頁都畫了一幅圖,用手快速的翻過每一頁,就能看到一個(gè)很短的“動(dòng)畫片”。
????沒錯(cuò),咱們看到的視頻,本質(zhì)上就是一連串快速播放的圖片。
????每一張圖片,我們稱為一幀。只要每秒鐘的數(shù)據(jù)足夠多,也就是播放速度足夠快,人眼就看不出是一張張獨(dú)立的圖片。對(duì)于人眼而言,這個(gè)播放臨界速度是每秒 30 幀,而這里的 30 也就是我們常說的幀率(FPS)。
????每一張圖片,都是由像素組成,而每個(gè)像素又是由 RGB 組成,每個(gè) 8 位,共 24 位。
????我們假設(shè)一個(gè)視頻中的所有圖片的像素都是 1024*768,可以大概估算下視頻的大?。?/p>
每秒鐘大小 = 30 幀 x 1024 x 768 x 24 = 566,231,010 Bits = 70,778,880 Bytes
????按我們上面的估算,一分鐘的視頻大小就是 4,,246,732,800 Bytes,這里已經(jīng)有 4 個(gè) G 了。
????是不是和我們?nèi)粘=佑|到的視頻大小明顯不符?這是因?yàn)槲覀冊(cè)趥鬏數(shù)倪^程中,將視頻壓縮了。
????為什么要壓縮視頻?按我們上面的估算,一個(gè)一小時(shí)的視頻,就有 240G,這個(gè)數(shù)據(jù)量根本沒辦法存儲(chǔ)和傳輸。因此,人們利用編碼技術(shù),給視頻“瘦身”,用盡量少的 Bit 數(shù)保持視頻,同時(shí)要保證播放的時(shí)候,畫面仍然很清晰。實(shí)際上,編碼就是壓縮的過程。
視頻和圖片的壓縮特點(diǎn)我們之所以能夠?qū)σ曨l流中的圖片進(jìn)行壓縮,因?yàn)橐曨l和圖片有下列這些特點(diǎn):
空間冗余:圖像的相鄰像素之間有較強(qiáng)的相關(guān)性,一張圖片相鄰像素往往是漸變的,而不是突變的,沒必要每個(gè)像素都完整的保存,可以隔幾個(gè)保存一個(gè),中間的用算法計(jì)算出來。
時(shí)間冗余:視頻序列的相鄰圖像之間內(nèi)容相似。一個(gè)視頻中連續(xù)出現(xiàn)的圖片也不是突變的,可以根據(jù)已有的圖片進(jìn)行預(yù)測(cè)和推斷。
視覺冗余:人的視覺系統(tǒng)對(duì)某些細(xì)節(jié)不敏感,因此不會(huì)注意到每一個(gè)細(xì)節(jié),可以允許丟失一些數(shù)據(jù)。
編碼冗余:不同像素值出現(xiàn)的概率不同,概率高的用的字節(jié)少,概率低的用的字節(jié)多,類似霍夫曼編碼的思路。
????從上面這些特點(diǎn)中可以看出,用于編碼的算法非常復(fù)雜,而且多種多樣。雖然算法多種,但編碼過程實(shí)際上是類似的,如下圖:
視頻編碼的兩大流派????視頻編碼的算法這么多,能不能形成一定的標(biāo)準(zhǔn)呢?當(dāng)然能,這里咱們就來認(rèn)識(shí)下視頻編碼的兩大流派。
流派一:ITU(International tELECOMMUNICATIONS Union)的 VCEG(Video Coding Experts Group),這個(gè)稱為國(guó)際電聯(lián)下的 VCEG。既然是電信,可想而知,他們最初是做視頻編碼,主要側(cè)重傳輸。我們上面的系列名詞二,就是這個(gè)組織制定的標(biāo)準(zhǔn)。
流派二:ISO(International Standards Organization)的 MPEG(Moving Picture Experts Group),這個(gè)是 ISO 旗下的 MPEG。本來是做視頻存儲(chǔ)的,就像咱們場(chǎng)面常說的 VCD 和 DVD。后來也慢慢側(cè)重視頻傳輸了。系列名詞三就是這個(gè)組織制定的標(biāo)準(zhǔn)。
后來,ITU-T(國(guó)際電信聯(lián)盟電信標(biāo)準(zhǔn)化部門)與 MPEG 聯(lián)合制定了 H.264/MPEG-4 AVC,這也是我們重點(diǎn)關(guān)注的。
直播數(shù)據(jù)傳輸????視頻經(jīng)過編碼之后,生動(dòng)活潑的一幀幀圖像就變成了一串串讓人看不懂的二進(jìn)制。這個(gè)二進(jìn)制可以放在一個(gè)文件里,然后按照一定的格式保存起來,這里的保存格式,就是系列名詞一。
????編碼后的二進(jìn)制文件就可以通過某種網(wǎng)絡(luò)協(xié)議進(jìn)行封裝,放在互聯(lián)網(wǎng)上傳輸,這個(gè)時(shí)候就可以進(jìn)行網(wǎng)絡(luò)直播了。
????網(wǎng)絡(luò)協(xié)議將編碼好的視頻流,從主播端推送到服務(wù)器,在服務(wù)器上有個(gè)運(yùn)行了同樣協(xié)議的服務(wù)端來接收這些網(wǎng)絡(luò)數(shù)據(jù)包,從而得到里面的視頻流,這個(gè)過程稱為接流。
????服務(wù)端接到視頻流之后,可以滴視頻流進(jìn)行一定的處理,比如轉(zhuǎn)碼,也就是從一個(gè)編碼格式轉(zhuǎn)成另一種格式,這樣才能適應(yīng)各個(gè)觀眾使用的客戶端,保證他們都能看到直播。
????流處理完畢后,就可以等待觀眾的客戶端來請(qǐng)求這些視頻流。觀眾的客戶端請(qǐng)求視頻流的過程稱為拉流。
????如果有非常多的觀眾同時(shí)看一個(gè)視頻直播,都從一個(gè)服務(wù)器上拉流,壓力就非常大,因此需要一個(gè)視頻的分發(fā)網(wǎng)絡(luò),將視頻預(yù)先加載到就近的邊緣節(jié)點(diǎn),這樣大部分觀眾就能通過邊緣節(jié)點(diǎn)拉取視頻,降低服務(wù)器的壓力。
????當(dāng)觀眾將視頻流拉下來后,就需要進(jìn)行解碼,也就是通過上述過程的逆過程,將一串串看不懂的二進(jìn)制轉(zhuǎn)變成一幀幀生動(dòng)的圖片,在客戶端播放出來。
????整個(gè)直播過程,可以用下圖來描述:
????接下來,我們依次來看一下每個(gè)過程:
編碼:將豐富多彩的圖片變成二進(jìn)制流????雖然我們說視頻是一張張圖片的序列,但如果每張圖片都完整,就太大了,因而會(huì)將視頻序列分成三種幀:
I幀,也稱關(guān)鍵幀。里面是完整的圖片,只需要本幀數(shù)據(jù),就可以完成解碼。
P幀,前向預(yù)測(cè)編碼幀。P 幀表示的是這一幀跟之前一個(gè)關(guān)鍵幀(或 P 幀)的差別,解碼時(shí)需要用之前緩存的畫面,疊加上和本幀定義的差別,生成最終畫面。
B幀,雙向預(yù)測(cè)內(nèi)插編碼幀。B 幀記錄的是本幀與前后幀的差別。要解碼 B 幀,不僅要取得之前的緩存畫面,還要解碼之后的畫面,通過前后畫面的數(shù)據(jù)與本幀數(shù)據(jù)的疊加,取得最終的畫面。
????可以看出,I 幀最完整,B 幀壓縮率最高,而壓縮后幀的序列,應(yīng)該是 IBBP 間隔出現(xiàn)。這就是通過時(shí)序進(jìn)行編碼。
????在一幀中,分成多個(gè)片,每個(gè)片中分成多個(gè)宏塊,每個(gè)宏塊分成多個(gè)子塊,這樣將一張大圖分解成一個(gè)個(gè)小塊,可以方便進(jìn)行空間上的編碼。如下圖:
????盡管時(shí)空非常立體的組成了一個(gè)序列,但總歸還是要壓縮成一個(gè)二進(jìn)制流。這個(gè)流是有結(jié)構(gòu)的,是一個(gè)個(gè)的網(wǎng)絡(luò)提取層單元(NALU,Network Abstraction Layer Unit)。變成這種格式就是為了傳輸,因?yàn)榫W(wǎng)絡(luò)上的傳輸,默認(rèn)的是一個(gè)個(gè)的包,因而這里也就分成了一個(gè)個(gè)的單元。
????如上圖,每個(gè) NALU 首先是一個(gè)起始標(biāo)識(shí)符,用于標(biāo)識(shí) NALU 之間的間隔。然后是 NALU 的頭,里面主要配置了 NALU 的類型。最后的 Payload 里面是 NALU 承載的數(shù)據(jù)。
????在 NALU 頭里面,主要的內(nèi)容是類型 NAL Type,其中:
0x07 表示 SPS,是序列參數(shù)集,包括一個(gè)圖像序列的所有信息,如圖像尺寸、視頻格式等。
0x08 表示 PPS,是圖像參數(shù)集,包括一個(gè)圖像的所有分片的所有相關(guān)信息,包括圖像類型、序列號(hào)等。
????在傳輸視頻流之前,剝削要傳輸者兩類參數(shù),不然就無法解碼。為了保證容錯(cuò)性,每一個(gè) I 幀之前,都會(huì)傳一遍這兩個(gè)參數(shù)集合。
????如果 NALU Header 里面的表示類型是 SPS 或 PPS,則 Payload 中就是真正的參數(shù)集的內(nèi)容。
????如果類型是幀,則 Payload 中是真正的視頻數(shù)據(jù)。當(dāng)然也是一幀幀保存的。前面說了,一幀的內(nèi)容還是挺多的,因而每一個(gè) NALU 里面保存的是一片。對(duì)于每一片,到底是 I 幀,還是 P 幀,亦或是 B 幀,在片結(jié)構(gòu)里面也有 Header,這里面有個(gè)類型用來標(biāo)識(shí)幀的類型,然后是片的內(nèi)容。
????這樣,整個(gè)格式就出來了。一個(gè)視頻,可以拆分成一系列的幀,每一幀拆分成一系列的片,每一片都放在一個(gè) NALU 里面,NALU 之間都是通過特殊的起始標(biāo)識(shí)符分隔,在每一個(gè) I 幀的第一片前面,要插入多帶帶保存 SPS 和 PPS 的 NALU,最終形成一個(gè)長(zhǎng)長(zhǎng)的 NALU 序列。
推流:將數(shù)據(jù)流打包傳輸?shù)綄?duì)端????形成 NALU 序列后,還需要將這個(gè)二進(jìn)制的流打包成網(wǎng)絡(luò)包進(jìn)行發(fā)送。這里我們以 RTMP 協(xié)議為例,進(jìn)入第二個(gè)過程,推流。
????RTMP 是基于 TCP 的,因而也需要雙方建立一個(gè) TCP 連接。在有 TCP 的連接的基礎(chǔ)上,還需要建立一個(gè) RTMP 連接,也就是在程序里面,我們調(diào)用 RTMP 類庫的 Connet 函數(shù),顯式創(chuàng)建一個(gè)連接。
????RTMP 為什么需要建立一個(gè)多帶帶的連接呢?
????因?yàn)橥ㄐ烹p方需要商量一些事情,保證后續(xù)的傳輸能正常進(jìn)行。其實(shí)主要就是兩個(gè)事情:
確定版本號(hào)。如果客戶端、服務(wù)端的版本號(hào)不一致,就不能正常工作;
確定時(shí)間戳。視頻播放中,時(shí)間是很重要的一個(gè)元素,后面的數(shù)據(jù)流互通的時(shí)候,經(jīng)常要帶上時(shí)間戳的差值,因而一開始雙方就要知道對(duì)方的時(shí)間戳。
????溝通這些事情,需要發(fā)送 6 條消息:
客戶端發(fā)送 C0、C1、C2
服務(wù)端發(fā)送 S0、S1、S2
????首先,客戶端發(fā)送 C0 表示自己的版本號(hào),不必等對(duì)方回復(fù),然后發(fā)送 C1 表示自己的時(shí)間戳。
????服務(wù)器只有在收到 C0 的時(shí)候,才會(huì)返回 S0,表明自己的版本號(hào),如果版本不匹配,可以斷開連接。
????服務(wù)器發(fā)送完 S0 后,也不用等待,就直接發(fā)送自己的時(shí)間戳 S1。
????客戶端收到 S1 時(shí),發(fā)一個(gè)知道了最煩時(shí)間戳的 ACK C2。同理,服務(wù)器收到 C1 的時(shí)候,發(fā)一個(gè)知道了對(duì)方時(shí)間戳的 ACK S2。
????于是,握手完成。
????握手之后,雙方需要互相傳遞一些控制信息,例如 Chunk 塊的大小、窗口大小等。
????真正傳輸數(shù)據(jù)的時(shí)候,還是需要?jiǎng)?chuàng)建一個(gè)流 Stream,然后通過這個(gè) Stream 來推流。
????推流的過程,就是講 NALU 放在 Message 里面發(fā)送,這個(gè)也稱為 RTMP Packet 包。其中,Message 的格式就像下圖所示:
????發(fā)送的時(shí)候,去掉 NALU 的起始標(biāo)識(shí)符。因?yàn)檫@部分對(duì)于 RTMP 協(xié)議來講沒有用。接下來,將 SPS 和 PPS 參數(shù)集封裝成一個(gè) RTMP 包發(fā)送,然后發(fā)送一個(gè)個(gè)片的 NALU。
????RTMP 在收發(fā)數(shù)據(jù)的時(shí)候并不是以 Message 為單位的,而是把 Message 拆分成 Chunk 發(fā)送,而且必須在一個(gè) Chunk 發(fā)送完成之后,才能開始發(fā)送下一個(gè) Chunk。每個(gè) Chunk 中都帶有 Message ID,表示屬于哪個(gè) Message,接收端也會(huì)按照這個(gè) ID 將 Chunk 組裝成 Message。
????前面連接的時(shí)候,設(shè)置 Chunk 塊大小就是指這個(gè) Chunk。將大的消息變?yōu)樾〉膲K再發(fā)送,可以在低帶寬的情況下,減少網(wǎng)絡(luò)擁塞。
????下面用一個(gè)分塊的示例,來了解下 RTMP 是如何分塊的。
????假設(shè)一個(gè)視頻的消息長(zhǎng)度是 307,而 Chunk 大小約定為 128,那么消息就會(huì)被拆分為 3 個(gè) Chunk。
????第一個(gè) Chunk 的 Type = 0,表示 Chunk 頭是完整的。頭里面 Timestamp 為 1000,總長(zhǎng)度 Length 為 307,類型為 9,是個(gè)視頻,Stream ID 為 12346,正文部分承擔(dān) 128 個(gè)字節(jié)的 Data。
????第二個(gè) Chunk 也要發(fā)送 128 個(gè)字節(jié),但是由于 Chunk 頭和第一個(gè)一樣,因此它的 Chunk Type = 3,表示頭和第一個(gè) Chunk 一樣。
????第三個(gè) Chunk 要發(fā)送的 Data 的長(zhǎng)度為 51 個(gè)字節(jié),Chunk Type 還是用的 3。
????就這樣,數(shù)據(jù)源源不斷的到達(dá)流媒體服務(wù)器,整個(gè)過程就像下圖:
????這個(gè)時(shí)候,大量觀看直播的觀眾就可以通過 RTMP 協(xié)議從流媒體服務(wù)器上拉取。為了減輕服務(wù)器壓力,我們會(huì)使用分發(fā)網(wǎng)絡(luò)。
????分發(fā)網(wǎng)絡(luò)分為中心和邊緣兩層。邊緣層服務(wù)器部署在全國(guó)各地及橫跨各大運(yùn)營(yíng)商里,和用戶距離很近。而中心層是流媒體服務(wù)集群,負(fù)責(zé)內(nèi)容的轉(zhuǎn)發(fā)。
????智能負(fù)載均衡系統(tǒng),根據(jù)用戶的地理位置信息,就近選擇邊緣服務(wù)器,為用戶提供推/拉流服務(wù)。中心層也負(fù)責(zé)轉(zhuǎn)碼服務(wù)。例如,將 RTMP 協(xié)議的碼流轉(zhuǎn)換成 HLS 碼流。
拉流:觀眾的客戶端看到直播視頻????接下來,我們?cè)賮砜纯从^眾通過 RTMP 拉流的過程。
????先讀到的是 H.264 的解碼參數(shù),例如 SPS 和 PPS,然后對(duì)收到的 NALU 組成一個(gè)個(gè)幀,進(jìn)行解碼,交給播放器播放,這樣客戶端就能看到直播視頻了。
小結(jié)視頻名詞比較多,編碼兩大流派達(dá)成了一致,都是通過時(shí)間、空間的各種算法來壓縮數(shù)據(jù);
壓縮好的數(shù)據(jù),為了傳輸而組成一系列的 NALU,按照幀和片依次排列;
排列好的 NALU,在網(wǎng)絡(luò)傳輸?shù)氖?,要按?RTMP 包的格式進(jìn)行包裝,RTMP 的包會(huì)拆分成 Chunk 進(jìn)行傳輸;
推送到流媒體集群的視頻流經(jīng)過轉(zhuǎn)碼和分發(fā),可以被客戶端通過 RTMP 協(xié)議拉取,然后組合成 NALU,解碼成視頻格式進(jìn)行播放。
參考:
RTMP 協(xié)議規(guī)范;
劉超 - 趣談網(wǎng)絡(luò)協(xié)議系列課;
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/29820.html
摘要:而我們喜歡的這些直播,他們用到的傳輸協(xié)議有一個(gè)通用名流媒體傳輸協(xié)議。要認(rèn)識(shí)流媒體協(xié)議,就離不開下面的三大系列名詞。 【前五篇】系列文章傳送門: 網(wǎng)絡(luò)協(xié)議 9 - TCP協(xié)議(下):聰明反被聰明誤 網(wǎng)絡(luò)協(xié)議 10 - Socket 編程(上):實(shí)踐是檢驗(yàn)真理的唯一標(biāo)準(zhǔn) 網(wǎng)絡(luò)協(xié)議 11 - Socket 編程(下):眼見為實(shí)耳聽為虛 網(wǎng)絡(luò)協(xié)議 12 - HTTP 協(xié)議:常用而不簡(jiǎn)單 網(wǎng)絡(luò)...
摘要:支持流媒體協(xié)議。流媒體數(shù)據(jù)量大,如果出現(xiàn)回源,壓力會(huì)比較大,所以往往采取主動(dòng)推送的模式,將熱點(diǎn)數(shù)據(jù)主動(dòng)推送到邊緣節(jié)點(diǎn)。除此之外,流媒體還有個(gè)關(guān)鍵的防盜鏈問題。在服務(wù)端,取出過期時(shí)間,和當(dāng)前節(jié)點(diǎn)時(shí)間進(jìn)行比較,確認(rèn)請(qǐng)求是否過期。 【前五篇】系列文章傳送門: 網(wǎng)絡(luò)協(xié)議 13 - HTTPS 協(xié)議:加密路上無盡頭 網(wǎng)絡(luò)協(xié)議 14 - 流媒體協(xié)議:要說愛你不容易 網(wǎng)絡(luò)協(xié)議 15 - P2P 協(xié)...
摘要:支持流媒體協(xié)議。流媒體數(shù)據(jù)量大,如果出現(xiàn)回源,壓力會(huì)比較大,所以往往采取主動(dòng)推送的模式,將熱點(diǎn)數(shù)據(jù)主動(dòng)推送到邊緣節(jié)點(diǎn)。除此之外,流媒體還有個(gè)關(guān)鍵的防盜鏈問題。在服務(wù)端,取出過期時(shí)間,和當(dāng)前節(jié)點(diǎn)時(shí)間進(jìn)行比較,確認(rèn)請(qǐng)求是否過期。 【前五篇】系列文章傳送門: 網(wǎng)絡(luò)協(xié)議 13 - HTTPS 協(xié)議:加密路上無盡頭 網(wǎng)絡(luò)協(xié)議 14 - 流媒體協(xié)議:要說愛你不容易 網(wǎng)絡(luò)協(xié)議 15 - P2P 協(xié)...
閱讀 2789·2021-09-23 11:44
閱讀 1677·2021-09-13 10:24
閱讀 2624·2021-09-08 09:36
閱讀 1236·2019-08-30 15:54
閱讀 2253·2019-08-30 13:54
閱讀 3314·2019-08-30 10:57
閱讀 1852·2019-08-29 18:43
閱讀 3619·2019-08-29 15:10