一 概述
實時傳輸協議(Real-time Transport Protocol或簡寫RTP)是一個網絡傳輸協議,它是由IETF的多媒體傳輸工作小組1996年在RFC 1889中公布的。
RTP協議詳細說明了在互聯網上傳遞音頻和視頻的標准數據包格式。它一開始被設計為一個多播協議,但后來被用在很多單播應用中。RTP協議常用於流媒體系統(配合RTSP協議),視頻會議和一鍵通(Push to Talk)系統(配合H.323或SIP),使它成為IP電話產業的技術基礎。RTP協議和RTP控制協議RTCP一起使用,而且它是創建在UDP協議上的。
當RTSP會話建立成功,並開始傳輸時,音視頻數據以RTP協議打包發送給客戶端;
二 RTP報頭解析
V:RTP協議的版本號,占2位,當前協議版本號為2
P:填充標標志,占1位,如果P=1,則在該報文的尾部填充一個或多個額外的八位組,它們不是有效載荷的一部分。
X:擴展標志,占1位,如果X=1,則在RTP報頭后跟有一個擴展報頭
CC:CSRC計數器,占4位,指示CSRC 標識符的個數
M:標記,占1位,不同的有效載荷有不同的含義,對於視頻,標記一幀的結束;對於音頻,標記會話的開始
PT:有效載荷類型,占7位,用於說明RTP報文中有效載荷的類型,如GSM音頻、JPEM圖像等
sequence number:序列號,占16位,用於標識發送者所發送的RTP報文的序列號,每發送一個報文,序列號增1。接收者通過序列號來檢測報文丟失情況,重新排序報文,恢復數據
timestamp:時間戳,占32位,時戳反映了該RTP報文的第一個八位組的采樣時刻。接收者使用時戳來計算延遲和延遲抖動,並進行同步控制
SSRC:同步信源標識符,占32位,用於標識同步信源。該標識符是隨機選擇的,對弈同一個視頻源,每個會話都有自己獨立的同步信源
CSRC:特約信源標識符,每個CSRC信源占32位,可以有0-15個,具體數量由CC決定,每個CSRC標識了包含在該RTP報文有效載荷中的所有特約信源
三 H264/H265 RTP打包分析1.RTP包頭的封裝
打包時,每幀數據包均需要添加二中所述RTP包頭,對於每路視頻流,RTP包頭除序列號外,基本保持不變;另一個要注意的時,由於包頭需要按位填充,當填充/發送數據時,應注意發送端數據的大小端限制。2.數據流的包頭
此處以h264,h265,aac,g711來舉例說明
g711數據在發送時,不需要額外的頭部信息,其他三種數據流,在rtp包頭后,應按格式封裝自己的數據頭
其中h264為一個字節,h265為兩個字節,aac數據為四個字節
1.h264打包
視頻包時需要考慮到MTU的大小,每包數據不能超過MTU的大小,通常情況下,設備是不知道當前網絡的MTU大小的。
因此都會在代碼中指定一個大小,開發時,可以參考ffmpeg中給定該值的大小
H264數據打包格式如下:
RTP頭+h264字節頭+視頻數據幀
h264字節頭為兩個字節,格式如下
第一個字節
根據ffmpeg代碼,F為0,此處type為28,
nri = buff[0] & 0x60;
buff[0] 為視頻幀的第一個數據
第二個字節
此處type = buff[0] & 0x1f;
其中S E R的解釋如下,
注意當數據包被分成多包數據后,處S E R三位,其他均與第一包保持一致,不得改變
2.h265打包
打包和h264過程類似,區別就是H265的數據頭為三個字節,
h265的三個字節,結構如下:
第一第二個字節
參考ffmpeg代碼 此處F為0,Type為49,LayerId為0,TID為1
第三個字節
其中FuType = (buf[0] >> 1) & 0x3F;
S E的用法和h264中相同,此處不再敘述3.aac打包
aac在打包為RTP數據包時,每幀數據前還應該由四個字節頭,即格式如下
RTP包頭+AAC字節頭+AAC數據
當AAC數據前由ADTS頭時, 打包時應該跳過7字節的ADTS頭
AAC字節頭定義如下
字節1:0x00
字節2:0x01
字節3:(data_len & 0x1fe0) >> 5
字節4:(data_len &0x1f) << 3
四 參考代碼
ffmpeg代碼 rtpenc_h264_hevc.c文件
void ff_rtp_send_h264_hevc(AVFormatContext *s1, const uint8_t *buf1, int size);
此處注意,該函數將h264和h265的nalu打包放在了同一個函數中,注意根據判斷語句來區分。