【音視頻】RTSP拉流: RTP負載AAC詳解(三)

??此文為系列文章,此系列主要講解RTSP客戶端的拉流及播放,文章持續更新,會從rtsp的基本協議講起,如何一步步實現音視頻的拉流過程,包括一系列涉及到的協議,rtsp,sdp, rtp(本系列文章的核心內容會放在rtp協議,會重點介紹講解rtp負載部分), rtcp, 從rtp解析aac,h264數據幀,得到幀后如何交給解碼庫(ffmpeg,libVLC,live555等)進行解碼,音視頻同步并播放音頻和視頻,如果內容涉及到TCP和UDP網絡通信內容,可以參考:

【Linux編程】一個基于 C++ 的 TCP 客戶端異步(epoll)框架(一))
【Linux編程】TcpServer 類的設計與實現:構建高性能的 TCP 服務器(二)
【Linux編程】C++ UDP的UdpClient 類詳解與網絡通信實現(三))


文章目錄

  • 1.RTP協議基礎
    • 1.1 RTP協議概述
    • 1.2 RTP頭部結構
  • 2. RTP負載:音頻AAC封裝模式
    • 2.1 單幀模式
    • 2.2 多幀模式
    • 2.3. 分片模式
  • 3.RTP負載:音頻AAC封裝格式
    • 3.1 AU-headers-length
    • 3.2 AU-headers
      • 3.2.1 AU-size
      • 3.2.2 AU-index/AU-index-delta
      • 3.2.3 CTS-flag
      • 3.2.4 CTS-delta
      • 3.2.5 DTS-flag
      • 3.2.6 DTS-delta
      • 3.2.7 RAP-flag
      • 3.2.8 Stream-state
    • 3.3 AAC音頻數據
  • 4. ADTS
    • 4.1 AAC與ADTS的關系
    • 4.2 ADTS 結構
      • 4.2.1 ADTS 頭部詳解


??本篇文章是介紹關于RTSP拉流過程內容,如果涉及到推流協議的了解,請閱讀:
基于FFmpeg進行rtsp推流協議分析過程(詳細教程)(全息講解)

1.RTP協議基礎

1.1 RTP協議概述

??RTP(Real-time Transport Protocol)是一種用于網絡上傳輸實時數據(如音頻、視頻等)的協議,廣泛應用于流媒體、視頻會議、VoIP等場景。RTP協議的核心目標是為實時數據的傳輸提供時間戳、序列號等信息,以便接收端能夠正確地重組數據流,保證數據的實時性和順序性。RTP協議不保證數據的可靠傳輸,通常與RTCP(RTP Control Protocol)配合使用,以實現流量控制、擁塞控制等功能。

1.2 RTP頭部結構

??RTP頭在前面的文章中講解了,RTP頭部是RTP協議的關鍵組成部分,它包含了多個字段,用于描述RTP數據包的特征和傳輸狀態。RTP頭部的結構如下表所示:

在這里插入圖片描述

2. RTP負載:音頻AAC封裝模式

?? 根據 RFC 3640 的定義,RTP 封裝 AAC 數據時主要有以下三種方式:一個 RTP 包攜帶一個 AU、一個 RTP 包攜帶多個 AU、一個 RTP 包攜帶一個 AU 的片段。

2.1 單幀模式

?? 一個 RTP 數據包中只攜帶一個完整的 Access Unit(AU),即一個音頻幀。 每個 RTP 數據包只包含一個完整的音頻幀,不會進行分片。適用于音頻幀較小且網絡 MTU 足夠大的情況。RTP 數據包的 Marker 位(M 位)通常設置為 1,表示這是一個完整的音頻幀。

2.2 多幀模式

?? 一個 RTP 數據包中攜帶多個完整的 Access Unit(AU),即多個音頻幀。 一個 RTP 數據包可以包含多個完整的音頻幀,以提高傳輸效率。每個音頻幀的大小可以通過 AU-header 中的 AU-size 字段指定。RTP 數據包的 Marker 位(M 位)通常設置為 1,表示這是最后一個音頻幀。

2.3. 分片模式

?? 一個 RTP 數據包中只攜帶一個 AU 的一個片段,多個 RTP 數據包共同組成一個完整的 AU。一個 AU 被分割成多個片段,每個片段攜帶在不同的 RTP 數據包中。所有分片的 RTP 數據包具有相同的時間戳,但序列號不同。最后一個分片的 RTP 數據包的 Marker 位(M 位)設置為 1,表示這是該 AU 的最后一個分片。適用于音頻幀較大且網絡 MTU 較小的情況,避免因音頻幀過大而導致的 IP 碎片化。

3.RTP負載:音頻AAC封裝格式

3.1 AU-headers-length

?? AU-headers-length 是在 RTP 封裝 AAC 音頻數據時的關鍵字段。它位于 RTP 載荷的起始位置,緊跟在 RTP 頭部之后。該字段的長度固定為 2 字節,其值以 bit 為單位,表示后續所有 AU-header(Audio Unit Header,音頻單元頭)的總長度。由于每個 AU-header 的長度固定為 16 bit,因此 AU-headers-length 的值總是 16 的倍數。這一特性使得接收端能夠快速準確地解析出后續的 AU-header 數量和位置。

?? 例如,當一個 RTP 包中只包含一個 AU-header 時,AU-headers-length 的值為 16;若包含兩個 AU-header,則其值為 32,以此類推。通過這種方式,接收端可以根據 AU-headers-length 的值,輕松計算出后續 AU-header 的數量,即 AU-headers-length 的值除以 16。這種設計不僅提高了數據解析的效率,還確保了數據傳輸的靈活性,允許一個 RTP 包中可以包含多個音頻單元(Audio Unit),從而適應不同的音頻編碼和傳輸需求。在實際應用中,AU-headers-length 字段的值對于接收端正確解析 RTP 包中的音頻數據至關重要。接收端首先讀取該字段的值,確定后續 AU-header 的總長度,進而可以準確地提取出每個 AU-header 的內容。每個 AU-header 包含了音頻單元的大小、索引等信息,這些信息對于后續音頻數據的解碼和播放具有重要意義。因此,AU-headers-length 字段在 RTP 封裝 AAC 數據的過程中,起到了橋梁的作用,連接了 RTP 頭部和音頻數據,確保了數據傳輸的完整性和準確性。

3.2 AU-headers

?? AU-headers(Access Unit Headers)是用于音頻編碼數據流中的頭部信息,主要在音頻數據的傳輸和解析過程中發揮重要作用。在音頻編碼標準中,AU-headers通常用于標識音頻數據的起始位置、長度、時間戳等關鍵信息,以便接收端能夠正確地解析和播放音頻流。AU-headers是音頻數據流中的一個組成部分,它位于音頻幀的前面,用于描述音頻幀的相關信息。根據不同的音頻編碼標準,AU-headers的結構和內容可能會有所不同。例如,在AAC(Advanced Audio Coding)編碼中,AU-headers通常包含音頻幀的長度、索引等信息,這些信息需要SDP內容來確定。
在此之前放一個SDP示例:

v=0
o=- 0 0 IN IP4 127.0.0.1
s=Stream
c=IN IP4 0.0.0.0
t=0 0
m=video 0 RTP/AVP 96
a=rtpmap:96 H264/90000
a=fmtp:96 packetization-mode=1; sprop-parameter-sets=Z2QAKKzZQHgGf58BagICAoAAAAMAgAAAGQeMGMs=,aO+CPLA=; profile-level-id=640028
a=control:trackID=0
m=audio 0 RTP/AVP 97
a=rtpmap:97 mpeg4-generic/48000/2
a=fmtp:97 profile-level-id=1; mode=AAC-hbr; sizelength=13; indexlength=3; indexdeltalength=3; config=119056e500
a=control:trackID=1

注: SDP來自于RTSP請求信息的DESCRIBE方法。

3.2.1 AU-size

?? 表示音頻幀的長度(以字節為單位)。該字段的長度由SDP(Session Description Protocol)中的sizeLength參數決定,sizeLength的單位為bit。例如,sizeLength = 13,表示AU-size字段占用13位,能夠表示的最大音頻幀長度為8191字節。這一字段對于接收端正確讀取音頻幀的大小至關重要。

3.2.2 AU-index/AU-index-delta

?? 用于標識 序列號。AU-Index 出現在第一個 AU-header 中,而 AU-Index-delta 出現在后續的 AU-header 中,表示相對于前一個 AU 的序列號差值

?? AU-index表示音頻幀在整個音頻流中的序號。該字段的長度由SDP中的indexLength參數決定。在某些情況下,AU-index字段可能用于標識音頻幀的順序,特別是在音頻流中包含多個音頻幀的情況下。例如,當一個RTP包中包含多個音頻幀時,AU-index字段可以幫助接收端對音頻幀進行排序和管理。例如,indexlength = 3 時,表示AU-index字段占用3位數據長度。

?? AU-index-delta表示音頻幀序號的增量。該字段的長度由SDP中的indexDeltaLength參數決定。在某些音頻編碼標準中,AU-index-delta字段用于表示當前音頻幀序號與前一個音頻幀序號的差值。這種表示方式可以節省一些空間,特別是在音頻幀序號變化較小的情況下。

3.2.3 CTS-flag

?? 表示是否包含 CTS-delta 字段。值為 1 表示存在 CTS-delta 字段,值為 0 表示不存在,該字段由SDP 中的 CTSDeltaLength 參數定義了 CTS-delta 字段的位數,如果 CTSDeltaLength 為 0或不存在,則表示 CTS-delta 字段不存在。

3.2.4 CTS-delta

?? 表示 Composition Time Stamp (CTS) 的偏移量,相對于 RTP 頭部的時間戳,該字段的存在與否由 CTS-flag 字段決定,而 CTS-flag 的存在與否由 CTSDeltaLength 參數決定。

3.2.5 DTS-flag

?? 表示是否包含 DTS-delta 字段。值為 1 表示存在 DTS-delta 字段,值為 0 表示不存在, 該字段由SDP 中的 DTSDeltaLength 參數定義了 DTS-delta 字段的位數。如果 DTSDeltaLength 為 0,則表示 DTS-delta 字段不存在。

3.2.6 DTS-delta

?? 表示 Decoding Time Stamp (DTS) 的偏移量,相對于 CTS,該字段的存在與否由 DTS-flag 字段決定,而 DTS-flag 的存在與否由 DTSDeltaLength 參數決定。

3.2.7 RAP-flag

?? 表示該 Access Unit 是否為隨機訪問點。值為 1 表示是隨機訪問點,值為 0 表示不是,該字段由SDP 中的 randomAccessIndication 參數定義了 RAP-flag 字段的存在與否。值為 1 表示存在 RAP-flag 字段,值為 0 表示不存在。

3.2.8 Stream-state

?? 表示 MPEG-4 系統流的狀態,每個狀態由一個模數計數器的值標識。該字段由SDP 中的 streamStateIndication 參數定義了 Stream-state 字段的位數。如果 streamStateIndication 為 0或不存在,則表示 Stream-state 字段不存在。

3.3 AAC音頻數據

?? 之后就是裸的AAC音頻壓縮流了,RTP負載中封裝AAC音頻數據主要使用兩種格式:ADTS和LATM。ADTS格式較為簡單,但封裝開銷較大,而LATM格式更加高效,適合低延遲和低帶寬的實時傳輸應用。在實際應用中,根據網絡帶寬、延遲要求和音頻質量需求的不同,選擇適當的封裝格式是關鍵。但是在封裝RTP協議時,需要特別注意的是,在封裝AAC音頻時,往往去掉了ADTS信息的,解析時得到的是裸的AAC音頻壓縮流,我們在解碼時需要將ADTS還原。

4. ADTS

4.1 AAC與ADTS的關系

?? ADTS(Audio Data Transport Stream,音頻數據傳輸流)是AAC音頻的一種封裝格式,主要用于音頻數據的傳輸。ADTS為每幀AAC音頻數據添加了一個頭部信息,該頭部包含了音頻數據的編碼參數和幀的長度等信息。
?? 在實際應用中,AAC音頻數據通常被封裝在ADTS格式中進行傳輸。發送端將AAC音頻數據編碼成ADTS格式,接收端則解析ADTS頭部信息,提取AAC音頻數據進行解碼。這種封裝方式使得AAC音頻能夠在各種網絡環境中高效、可靠地傳輸。

4.2 ADTS 結構

?? ADTS(Audio Data Transport Stream)是AAC(Advanced Audio Coding)的一種常見傳輸流格式,通常用于封裝AAC音頻數據,使其適合在網絡上傳輸。ADTS幀由兩部分組成:

  • ADTS頭部(Header):包含音頻的采樣率、聲道數、幀長度等信息。
  • AAC音頻數據(Payload):實際的AAC音頻編碼數據。

4.2.1 ADTS 頭部詳解

?? ADTS頭部通常為7個字節(當存在CRC校驗時為9個字節)。千字文,不如表格來的直接:
在這里插入圖片描述

在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/895539.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/895539.shtml
英文地址,請注明出處:http://en.pswp.cn/news/895539.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Dockerfiles 的 Top 10 常見 DevOps/SRE 面試問題及答案

1. RUN 和 CMD 之間有什么區別? RUN : 在鏡像構建過程中執行命令,創建一個新的層。通常用于安裝軟件包。 示例: RUN apt-get update && apt-get install -y curlCMD : 指定容器啟動時默認運行的命令。它在運行時執行,而不是在構建過程…

【ARM】JTAG接口介紹

1、 文檔目標 對 JTAG 接口有更多的認識,在遇到關于 JTAG 接口問題時有一些排查的思路。 2、 問題場景 在使用調試器過程時,免不了要接觸到 JTAG 接口,當出現連接不上時,就不知道從哪來進行排查。 3、軟硬件環境 1 軟件版本&am…

opencascade 獲取edge起始點 會出現終點與實際不同的情況

在使用 OpenCASCADE 獲取 TopoDS_Edge 的起始點和終點時,可能會出現終點與實際不一致的情況。這通常是由于以下原因導致的: 幾何曲線的方向問題:在某些情況下,幾何曲線的方向可能與拓撲邊的方向不一致,導致通過幾何曲線…

【電腦】u盤重裝win7

u盤必須8GB以上 1. CPU型號 首先查看CPU的型號看看到底能不能裝win7 2. 下載光盤映像文件 網址 看電腦是多少位的機器(32位下載x86 64位下載x64) 一共是這么多個版本按需下載對應的版本 電腦小白推薦無腦下載旗艦版 將鏈接復制到迅雷進行下載 3. 下載軟碟通 網址 下…

C++-AVL樹

一、AVL樹的概念 1.二叉搜索樹 二叉搜索樹(BST,Binary Search Tree),也稱二叉排序樹或二叉查找樹。 二叉搜索樹:一棵二叉樹,可以為空;如果不為空,滿足以下性質: 非空左子…

【網絡安全 | 漏洞挖掘】后端接受非預期參數的故事

未經許可,不得轉載。 文章目錄 正文正文 在對某項目進行測試時,我遵循了一套系統化的方法論,以確保全面理解其安全性。 首先,我創建了一個賬戶,并從用戶的角度探索主域及其各項功能。此階段,我避免使用 Burp Suite 或其他工具,而是嘗試真正理解該應用的設計邏輯與交互…

01.01、判定字符是否唯一

01.01、[簡單] 判定字符是否唯一 1、題目描述 實現一個算法,確定一個字符串 s 的所有字符是否全都不同。 在這一題中,我們的任務是判斷一個字符串 s 中的所有字符是否全都不同。我們將討論兩種不同的方法來解決這個問題,并詳細解釋每種方法…

w208基于spring boot物流管理系統設計與實現

🙊作者簡介:多年一線開發工作經驗,原創團隊,分享技術代碼幫助學生學習,獨立完成自己的網站項目。 代碼可以查看文章末尾??聯系方式獲取,記得注明來意哦~🌹贈送計算機畢業設計600個選題excel文…

《剛剛問世》系列初窺篇-Java+Playwright自動化測試-22- 操作鼠標拖拽 - 下篇(詳細教程)

1.簡介 上一篇中,宏哥說的宏哥在最后提到網站的反爬蟲機制,那么宏哥在自己本地做一個網頁,沒有那個反爬蟲的機制,谷歌瀏覽器是不是就可以驗證成功了,宏哥就想驗證一下自己想法,其次有人私信宏哥說是有那種…

神經網絡常見激活函數 8-SELU函數

SELU 縮放指數線性單元:SELU(Scaled Exponential Linear Unit) 函數導函數 SELU函數 S E L U ( x ) { λ x x > 0 λ α ( e x ? 1 ) x ≤ 0 \rm SELU(x) \left\{ \begin{array}{} \lambda x \quad & x > 0 \\ \lambda \alph…

【Elasticsearch】多字段查詢方式匯總

在 Elasticsearch 中,實現多字段查詢的常見方式有以下幾種,每種方式適用于不同的場景: --- ### 1. **multi_match 查詢** - **用途**:在多個字段中執行同一查詢,支持多種匹配策略。 - **關鍵參數**&#xff1a…

多線之旅:wait 與 notify

今天小編繼續來分享下多線程中的一些內容。 在多線程環境下,由于線程調度的不確定性,所以我們有時候無法很好的去保證其線程的執行順序。 但是呢,我們又要實現這個順序執行,所以我們可以使用到這兩個方法,wait 和 no…

批量修改mysql字符串字段子字符串

替換子字符串 使用 REPLACE 函數替換字段中的特定子字符串。 示例: 將 table_name 表中 column_name 字段的所有 old_value 替換為 new_value。 UPDATE table_name SET column_name REPLACE(column_name, old_value, new_value) WHERE column_name LIKE %old_val…

達夢:AWR 生成

目錄標題 AWR 性能診斷與報告生成1. 檢查 AWR 系統狀態2. 查看數據庫中的所有表空間3. 查看現有的 AWR 快照4. 設置 AWR 快照的時間間隔5. 創建 AWR 快照6. 查看最新的 AWR 快照7. 生成 AWR HTML 報告8. 將 AWR 報告保存到指定文件鏈接總結 自動工作集負載信息庫 AWR 報告解析指…

股票數據接口API實例代碼python、JAVA等多種語言演示免費獲取實時數據、歷史數據、CDMA、KDJ等指標數據配有API說明文檔

? 本文中所有接口均可直接在瀏覽器打開獲取數據,為了便于大家驗證有效性,已經做好了超鏈接,直接點擊即可! 滬深兩市股票列表 API接口鏈接(可點擊驗證):https://api.mairui.club/hslt/list/b…

深入理解DOM:22個核心知識點與代碼示例

本文系統介紹DOM相關的22個核心概念,每個知識點均提供代碼示例及簡要說明,幫助開發者全面掌握DOM操作技巧。 一、DOM基礎概念 1. DOM概念 DOM(Document Object Model)是HTML/XML的編程接口,通過JavaScript可動態修改…

【Map vs Set】:Java數據存儲的“雙子星”對決

個人主頁:?喜歡做夢 歡迎 👍點贊 ?關注 ??收藏 💬評論 目錄 🍰一、搜索 🍮1.概念 🍮2.模型 🍰二、Map 🍨1.什么是Map? 🍨2.Map的實例化 &…

【C語言 】C語言 桌游開發數字競拍(源碼)【獨一無二】

👉博__主👈:米碼收割機 👉技__能👈:C/Python語言 👉專__注👈:專注主流機器人、人工智能等相關領域的開發、測試技術。 【C語言 】C語言 桌游開發數字競拍(源碼…

Reinforcement Learning Heats Up 強化學習持續升溫

Reinforcement Learning Heats Up 強化學習持續升溫 核心觀點:強化學習正成為構建具有高級推理能力大語言模型(LLMs)的重要途徑。 最新進展 模型示例:近期出現了如DeepSeek - R1及其變體(DeepSeek - R1 - Zero&#xf…

Whisper+T5-translate實現python實時語音翻譯

1.首先下載模型,加載模型 import torch import numpy as np import webrtcvad import pyaudio import queue import threading from datetime import datetime from faster_whisper import WhisperModel from transformers import AutoTokenizer, AutoModelForSeq2…