Golang實(shí)現(xiàn)RTP音視頻傳輸示例詳解_第1頁(yè)
Golang實(shí)現(xiàn)RTP音視頻傳輸示例詳解_第2頁(yè)
Golang實(shí)現(xiàn)RTP音視頻傳輸示例詳解_第3頁(yè)
Golang實(shí)現(xiàn)RTP音視頻傳輸示例詳解_第4頁(yè)
Golang實(shí)現(xiàn)RTP音視頻傳輸示例詳解_第5頁(yè)
已閱讀5頁(yè),還剩2頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

第Golang實(shí)現(xiàn)RTP音視頻傳輸示例詳解目錄引言RTP數(shù)據(jù)包頭部字段Golang的相關(guān)實(shí)現(xiàn)結(jié)尾

引言

在Coding之前我們先來(lái)簡(jiǎn)單介紹一下RTP(Real-timeTransportProtocol),正如它的名字所說(shuō),用于互聯(lián)網(wǎng)的實(shí)時(shí)傳輸協(xié)議,通過(guò)IP網(wǎng)絡(luò)傳輸音頻和視頻的網(wǎng)絡(luò)協(xié)議。

由音視頻傳輸工作小組開(kāi)發(fā),1996年首次發(fā)布,并提出了以下使用設(shè)想。

簡(jiǎn)單的多播音頻會(huì)議

使用IP的多播服務(wù)進(jìn)行語(yǔ)音通信。通過(guò)某種分配機(jī)制,獲取多播組地址和端口對(duì)。一個(gè)端口用于音頻數(shù)據(jù)的,另一個(gè)用于控制(RTCP)包,地址和端口信息被分發(fā)給預(yù)期的參與者。如果需要加密,可通過(guò)特定格式進(jìn)行加密。

音視頻會(huì)議

如果在會(huì)議中同時(shí)使用音視頻媒體,那么它們是作為單獨(dú)的RTP會(huì)話(huà)傳輸。音頻,視頻兩個(gè)媒體分別使用不同的UDP端口對(duì)傳輸單獨(dú)的RTP和RTCP數(shù)組包,多播地址可能相同,可能不同。進(jìn)行這種分離的動(dòng)機(jī)是如果參與者只想接受一種媒體,可以進(jìn)行選擇。

Mixer和Translator

我們需要考慮這樣一種情況,在某個(gè)會(huì)議中,大多數(shù)人處于高速網(wǎng)絡(luò)鏈路中,而某個(gè)地方的一小部分人只能低速率連接。為了防止所有人使用低帶寬,可以在低帶寬區(qū)域放置一個(gè)RTP級(jí)的中繼器Mixer。Mixer將接收的音頻報(bào)文重新同步為發(fā)送方20ms恒定間隔,重建音頻為單一流,音頻編碼為低速帶寬的音頻,然后轉(zhuǎn)發(fā)給低速鏈路上的帶寬數(shù)據(jù)包流。

多媒體應(yīng)用程序應(yīng)該能調(diào)節(jié)傳輸速率以匹配接收者容量或適應(yīng)網(wǎng)絡(luò)擁塞??梢詫⒄{(diào)節(jié)速率的任務(wù)通過(guò)將分層編碼和分層傳輸系統(tǒng)相結(jié)合來(lái)實(shí)現(xiàn)接收器。在基于IP多播的RTP上下文中,每個(gè)RTP會(huì)話(huà)均承載在自己的多播組上。然后,接收者可以只通過(guò)加入組播組合適的子集來(lái)調(diào)整接收帶寬。

RTP數(shù)據(jù)包頭部字段

只有當(dāng)Mixer存在時(shí),才會(huì)存在CSRC標(biāo)識(shí)符列表。這些字段具有以下含義。前12個(gè)8位組在每一個(gè)包中都有。

version(V):2bits

RTP版本。

填充(P):1bit

如果設(shè)置了填充位,包中包含至少一個(gè)填充8位組,其他填充位不屬于Payload。

擴(kuò)展(X):1bit

如果設(shè)置了擴(kuò)展位則存在。

CSRC數(shù)量(CC):4bits

CSRC數(shù)量包含在固定頭中,CSRC標(biāo)識(shí)符數(shù)量。

標(biāo)記(M):1bit

標(biāo)記由配置文件定義。用于標(biāo)記數(shù)據(jù)包流中例如幀邊界之類(lèi)的重要事件。

payload類(lèi)型(PT):7bits

該字段指出RTP有效載荷格式,由應(yīng)用程序進(jìn)行解釋。接收者必須忽略無(wú)法理解的有效載荷類(lèi)型的數(shù)據(jù)包。

序列號(hào):16bits

每次RTP數(shù)據(jù)包發(fā)送時(shí)增加,可能用于接收者檢測(cè)包丟失并且恢復(fù)包序列。

時(shí)間戳:32bits

該字段反映了RTP數(shù)據(jù)包中第一個(gè)8位組的采樣時(shí)刻。

SSRC:32bits

標(biāo)識(shí)同步源,這個(gè)標(biāo)識(shí)符應(yīng)該選擇隨機(jī),在同一個(gè)RTP對(duì)話(huà)的兩個(gè)同步源應(yīng)該有不同的同步標(biāo)識(shí)。

CSRC列表:0到15項(xiàng),其中每項(xiàng)32bits

該字段表示對(duì)該payload數(shù)據(jù)做出貢獻(xiàn)所有SSRC。

Golang的相關(guān)實(shí)現(xiàn)

RTP的實(shí)現(xiàn)有一些,不過(guò)通過(guò)Go實(shí)現(xiàn)有一些好處。

這里的易于測(cè)試不僅僅是體現(xiàn)在容易書(shū)寫(xiě),能夠快速通過(guò)源碼,函數(shù)直接生成相應(yīng)測(cè)試函數(shù)。而且更重要的是能夠提供相應(yīng)的基準(zhǔn)測(cè)試,提供計(jì)時(shí),并行執(zhí)行,內(nèi)存統(tǒng)計(jì)等參數(shù)供開(kāi)發(fā)者進(jìn)行相應(yīng)調(diào)整。

語(yǔ)言層面強(qiáng)大的Web開(kāi)發(fā)能力

能夠基于語(yǔ)言層面快速的對(duì)例JSON解析,字段封裝。無(wú)需引入三方庫(kù)。

性能較為優(yōu)異

相比于Python,Ruby等解釋型語(yǔ)言快,比node,erlang等語(yǔ)言更易書(shū)寫(xiě)。如果服務(wù)中需要用并發(fā),內(nèi)置關(guān)鍵字go就可以快速起多個(gè)goroutine。

Go社區(qū)的RTP有RTP相關(guān)實(shí)現(xiàn),對(duì)應(yīng)的測(cè)試也比較全面,簡(jiǎn)單介紹一下。

package_test.go(基礎(chǔ)測(cè)試)

funcTestBasic(t*testing.T){

p:=Packet{}

iferr:=p.Unmarshal([]byte{});err==nil{

t.Fatal("Unmarshaldidnoterroronzerolengthpacket")

rawPkt:=[]byte{

0x90,0xe0,0x69,0x8f,0xd9,0xc2,0x93,0xda,0x1c,0x64,

0x27,0x82,0x00,0x01,0x00,0x01,0xFF,0xFF,0xFF,0xFF,0x98,0x36,0xbe,0x88,0x9e,

parsedPacket:=Packet{

//固定頭部

Header:Header{

Marker:true,

Extension:true,

ExtensionProfile:1,

Extensions:[]Extension{

{0,[]byte{

0xFF,0xFF,0xFF,0xFF,

Version:2,

PayloadOffset:20,

PayloadType:96,

SequenceNumber:27023,

Timestamp:3653407706,

SSRC:476325762,

CSRC:[]uint32{},

//有效負(fù)載

Payload:rawPkt[20:],

Raw:rawPkt,

//UnmarshaltotheusedPacketshouldworkaswell.

fori:=0;ii++{

t.Run(fmt.Sprintf("Run%d",i+1),func(t*testing.T){

iferr:=p.Unmarshal(rawPkt);err!=nil{

t.Error(err)

}elseif!reflect.DeepEqual(p,parsedPacket){

t.Errorf("TestBasicunmarshal:got%#v,want%#v",p,parsedPacket)

ifparsedPacket.Header.MarshalSize()!=20{

t.Errorf("wrongcomputedheadermarshalsize")

}elseifparsedPacket.MarshalSize()!=len(rawPkt){

t.Errorf("wrongcomputedmarshalsize")

ifp.PayloadOffset!=20{

t.Errorf("wrongpayloadoffset:%d!=%d",p.PayloadOffset,20)

raw,err:=p.Marshal()

iferr!=nil{

t.Error(err)

}elseif!reflect.DeepEqual(raw,rawPkt){

t.Errorf("TestBasicmarshal:got%#v,want%#v",raw,rawPkt)

ifp.PayloadOffset!=20{

t.Errorf("wrongpayloadoffset:%d!=%d",p.PayloadOffset,20)

}

基本測(cè)試中,利用Golang自帶的Unmarshal快速將byte切片轉(zhuǎn)換為相應(yīng)結(jié)構(gòu)體。減少了相關(guān)封包,解包等代碼的工作量。在網(wǎng)絡(luò)傳輸中,也能夠在語(yǔ)言層面直接完成大端,小端編碼的轉(zhuǎn)換,減少編碼的煩惱。

h.SequenceNumber=binary.BigEndian.Uint16(rawPacket[seqNumOffset:seqNumOffset+seqNumLength])

h.Timestamp=binary.BigEndian.Uint32(rawPacket[timestampOffset:timestampOffset+timestampLength])

h.SSRC=binary.BigEndian.Uint32(rawPacket[ssrcOffset:ssrcOffset+ssrcLength])

其中關(guān)于切片的相關(guān)操作十分便捷,可以獲取數(shù)組中的某一段數(shù)據(jù),操作比較靈活,在協(xié)議數(shù)據(jù)的傳輸過(guò)程中,通過(guò)切片,獲取某段數(shù)據(jù)進(jìn)行相應(yīng)處理。

m:=copy(buf[n:],p.Payload)

p.Raw=buf[:n+m]

在實(shí)現(xiàn)完成后,Golang的子測(cè)試能夠進(jìn)行嵌套測(cè)試。對(duì)執(zhí)行特定測(cè)試用例特別有用,只有子測(cè)試完成后,父測(cè)試才會(huì)返回。

funcTestVP8PartitionHeadChecker_IsPartitionHead(t*testing.T){

checker:=amp;VP8PartitionHeadChecker{}

t.Run("SmallPacket",func(t*testing.T){

ifchecker.IsPartitionHead([]byte{0x00}){

t.Fatal("Smallpacketshouldnotbetheheadofanewpartition")

t.Run("SFlagON",func(t*testing.T){

if!checker.IsPartitionHead([]byte{0x10,0x00,0x00,0x00}){

t.Fatal("PacketwithSflagshouldbetheheadofanewpartition")

t.Run("SFlagOFF",func(t*testing.T){

ifchecker.IsPartitionHead([]byte{0x00,0x00,0x00,0x00}){

t.Fatal("PacketwithoutSflagshouldnotbetheheadofanewpartition")

}

更多的相關(guān)實(shí)現(xiàn)可以去GitHub(/pion/rtp)上看一下實(shí)現(xiàn)源碼。

結(jié)尾

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論