最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Golang 實現(xiàn) RTP音視頻傳輸示例詳解

 更新時間:2022年07月12日 14:25:04   作者:聲網(wǎng)  
這篇文章主要為大家介紹了Golang實現(xiàn)RTP音視頻傳輸?shù)氖纠斀猓行枰呐笥芽梢越梃b參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

引言

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

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

  • 簡單的多播音頻會議

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

  • 音視頻會議

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

  • Mixer 和 Translator

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

  • 分層編碼

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

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

只有當 Mixer 存在時,才會存在 CSRC 標識符列表。這些字段具有以下含義。前 12 個 8 位組在每一個包中都有。

  • version (V): 2 bits

RTP 版本。

  • 填充 (P): 1 bit

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

  • 擴展 (X): 1 bit

如果設置了擴展位則存在。

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

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

  • 標記 (M): 1 bit

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

  • payload 類型(PT): 7 bits

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

  • 序列號: 16 bits

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

  • 時間戳: 32 bits

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

  • SSRC: 32 bits

標識同步源,這個標識符應該選擇隨機,在同一個 RTP 對話的兩個同步源應該有不同的同步標識。

  • CSRC 列表:0 到 15 項, 其中每項 32 bits

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

Golang 的相關實現(xiàn)

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

  • 易于測試

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

  • 語言層面強大的 Web 開發(fā)能力

能夠基于語言層面快速的對例 JSON 解析,字段封裝 。無需引入三方庫。

  • 性能較為優(yōu)異

相比于 Python,Ruby 等解釋型語言快,比 node, erlang 等語言更易書寫。如果服務中需要用并發(fā),內置關鍵字 go 就可以快速起多個 goroutine。

Go 社區(qū)的RTP有 RTP 相關實現(xiàn),對應的測試也比較全面,簡單介紹一下。

package_test.go (基礎測試)

func TestBasic(t *testing.T) {
  p := &Packet{}
  if err := p.Unmarshal([]byte{}); err == nil {
    t.Fatal("Unmarshal did not error on zero length packet")
  }
  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{},
    },
        // 有效負載
    Payload: rawPkt[20:],
    Raw:     rawPkt,
  }
  // Unmarshal to the used Packet should work as well.
  for i := 0; i < 2; i++ {
    t.Run(fmt.Sprintf("Run%d", i+1), func(t *testing.T) {
      if err := p.Unmarshal(rawPkt); err != nil {
        t.Error(err)
      } else if !reflect.DeepEqual(p, parsedPacket) {
        t.Errorf("TestBasic unmarshal: got %#v, want %#v", p, parsedPacket)
      }
      if parsedPacket.Header.MarshalSize() != 20 {
        t.Errorf("wrong computed header marshal size")
      } else if parsedPacket.MarshalSize() != len(rawPkt) {
        t.Errorf("wrong computed marshal size")
      }
      if p.PayloadOffset != 20 {
        t.Errorf("wrong payload offset: %d != %d", p.PayloadOffset, 20)
      }
      raw, err := p.Marshal()
      if err != nil {
        t.Error(err)
      } else if !reflect.DeepEqual(raw, rawPkt) {
        t.Errorf("TestBasic marshal: got %#v, want %#v", raw, rawPkt)
      }
      if p.PayloadOffset != 20 {
        t.Errorf("wrong payload offset: %d != %d", p.PayloadOffset, 20)
      }
    })
  }
}

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

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])

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

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

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

func TestVP8PartitionHeadChecker_IsPartitionHead(t *testing.T) {
    checker := &amp;VP8PartitionHeadChecker{}
    t.Run("SmallPacket", func(t *testing.T) {
        if checker.IsPartitionHead([]byte{0x00}) {
            t.Fatal("Small packet should not be the head of a new partition")
        }
    })
    t.Run("SFlagON", func(t *testing.T) {
        if !checker.IsPartitionHead([]byte{0x10, 0x00, 0x00, 0x00}) {
            t.Fatal("Packet with S flag should be the head of a new partition")
        }
    })
    t.Run("SFlagOFF", func(t *testing.T) {
        if checker.IsPartitionHead([]byte{0x00, 0x00, 0x00, 0x00}) {
            t.Fatal("Packet without S flag should not be the head of a new partition")
        }
    })
}

更多的相關實現(xiàn)可以去 GitHub(https://github.com/pion/rtp) 上看一下實現(xiàn)源碼。

結尾

如果人為去關注相關的傳輸細節(jié),可能在底層耗費大量時間,目前市面上有很多相關的實現(xiàn)方案,有開源的,和一些公司提供的一些方案。目前經(jīng)過業(yè)界實踐,陌陌,小米眾多公司都采用了聲網(wǎng)的 SDK 去進行相關的業(yè)務時間,部分公司甚至已經(jīng)將核心業(yè)務交由處理,可見其穩(wěn)定性。個人去測試了一下他們的云課堂相關服務,回放,在線演示等功能十分便捷,可以節(jié)約大量開發(fā)時間。

以上就是Golang 實現(xiàn) RTP音視頻傳輸示例詳解的詳細內容,更多關于Golang RTP音視頻傳輸?shù)馁Y料請關注腳本之家其它相關文章!

相關文章

  • Golang中sync.Mutex的源碼分析

    Golang中sync.Mutex的源碼分析

    這篇文章將帶大家從源碼分析一下Golang中sync.Mutex的使用,文中的示例代碼講解詳細,對我們學習Golang有一定的幫助,需要的可以參考一下
    2023-03-03
  • Go語言實現(xiàn)二進制與十進制互轉的示例代碼

    Go語言實現(xiàn)二進制與十進制互轉的示例代碼

    這篇文章主要和大家詳細介紹了Go語言中實現(xiàn)二進制與十進制互相轉換的示例代碼,文中的代碼簡潔易懂,感興趣的小伙伴可以跟隨小編一起學習一下
    2023-05-05
  • Golang中的錯誤處理深入分析

    Golang中的錯誤處理深入分析

    Go錯誤處理類似C語言,沒有提供任何異常,以及類java語言使用的try/catch異常處理機制。Go異常處理僅簡化為預定義的Error類型,Go沒有提供異常處理機制,不能拋出類似許多其他語言的異常。相反,Golang集成了新的錯誤處理機制,如panic和recovery
    2023-01-01
  • go語言beego框架jwt身份認證實現(xiàn)示例

    go語言beego框架jwt身份認證實現(xiàn)示例

    這篇文章主要為大家介紹了go語言beego框架jwt身份認證實現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步早日升職加薪
    2022-04-04
  • golang開發(fā)及數(shù)字證書研究分享

    golang開發(fā)及數(shù)字證書研究分享

    這篇文章主要為大家介紹了golang開發(fā)以及數(shù)字證書的研究示例分享,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步
    2021-11-11
  • go等待一組協(xié)程結束的操作方式

    go等待一組協(xié)程結束的操作方式

    這篇文章主要介紹了go等待一組協(xié)程結束的操作方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-05-05
  • 淺析Go中序列化與反序列化的基本使用

    淺析Go中序列化與反序列化的基本使用

    序列化是指將對象轉換成字節(jié)流,從而存儲對象或將對象傳輸?shù)絻却?、?shù)據(jù)庫或文件的過程,反向過程稱為“反序列化”。本文主要介紹了Go中序列化與反序列化的基本使用,需要的可以參考一下
    2023-04-04
  • Golang?gRPC?HTTP協(xié)議轉換示例

    Golang?gRPC?HTTP協(xié)議轉換示例

    這篇文章主要為大家介紹了Golang?gRPC?HTTP協(xié)議轉換示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-06-06
  • Golang 1.18新特性模糊測試用法詳解

    Golang 1.18新特性模糊測試用法詳解

    模糊測試是一種軟件測試技術。其核心思想是將自動或半自動生成的隨機數(shù)據(jù)輸入到一個程序中,并監(jiān)視程序異常,如崩潰,斷言失敗,以發(fā)現(xiàn)可能的程序錯誤,比如內存泄漏,本文給大家介紹了Golang 1.18 新特性模糊測試,感興趣的同學可以參考閱讀下
    2023-05-05
  • Go語言二維數(shù)組的傳參方式

    Go語言二維數(shù)組的傳參方式

    這篇文章主要介紹了Go語言二維數(shù)組的傳參方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04

最新評論

和田县| 周口市| 乐清市| 重庆市| 维西| 咸丰县| 华蓥市| 波密县| 叙永县| 即墨市| 凤山市| 新昌县| 安岳县| 中阳县| 临江市| 益阳市| 南康市| 临武县| 新兴县| 延安市| 台南县| 弥勒县| 桃江县| 余干县| 疏勒县| 武胜县| 济阳县| 阜康市| 丽水市| 青铜峡市| 太保市| 明水县| 宜黄县| 米脂县| 宜兰市| 龙南县| 广饶县| 二连浩特市| 永善县| 湘潭市| 凤山县|