国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

流媒體傳輸協(xié)議相關(guān)小結(jié)——NALU、RTP、RTSP、RTMP、SDP等

這篇具有很好參考價值的文章主要介紹了流媒體傳輸協(xié)議相關(guān)小結(jié)——NALU、RTP、RTSP、RTMP、SDP等。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

前言:

本文是博主在學(xué)習(xí)流媒體時進行的小結(jié),涉及內(nèi)容較多。
由于流媒體協(xié)議說復(fù)雜也復(fù)雜,說簡單也簡單,復(fù)雜在需要考慮到每一位比特,簡單在現(xiàn)成的輪子很多,只是會用往往已經(jīng)足夠。因此此文面向那些希望對流媒體協(xié)議有一定的基礎(chǔ)概念的讀者,而非注重實操。

另外,在博主總結(jié)期間參考了前輩們的諸多文章,在此表示感謝!

NAL單元

前言

與H.264/AVC 類似,H265/HEVC也采用視頻編碼層(Video Coding Layer,VCL)和網(wǎng)絡(luò)適配層(Network Abstract Layer, NAL)的雙層結(jié)構(gòu),以適應(yīng)不同網(wǎng)絡(luò)環(huán)境和視頻應(yīng)用。網(wǎng)絡(luò)適配層的主要任務(wù)是對視頻壓縮后的數(shù)據(jù)進行劃分和封裝,并進行必要的標識,使其更好的適應(yīng)各種網(wǎng)絡(luò)環(huán)境。

承載視頻壓縮數(shù)據(jù)的NALU又名VCLU,即VCL NALU,而承載其他信息的則稱為non-VCLU。

HEVC中碼流的封裝結(jié)構(gòu)

視頻編碼過程中輸出包含不同內(nèi)容的壓縮數(shù)據(jù)比特流片段成為SODB(String of Data Bits),添加RBSP尾(rbsp_trailing_bits,由稱為RBSP停止比特的1和多個或是零個0組成)之后就是RBSP。換句話說,RBSP就是整數(shù)字節(jié)化后的SODB。

H.265碼流也有兩種封裝格式,一種是用起始碼作為分界的Annex B格式,另一種則是在NALU頭添加NALU長度前綴的格式,稱為HVCC。

HEVC中圖像分類

HEVC中,每個VCLU包含一個視頻片段(Slice Segment,SS)。

由于時域預(yù)測機制使得圖像之間具有解碼依賴關(guān)系,導(dǎo)致圖像間的關(guān)系變得錯綜復(fù)雜,尤其是采用雙向預(yù)測的時候。因此,視頻流中會間隔地存在一些隨機介入點(Intra Random Access Ponit, IRAP),從IRAP開始,后續(xù)的視頻流(指播放順序在IRAP后的圖像)就可以獨立正確解碼,無須參考IRAP之前的視頻信息。IRAP是個點,之后的第一幀圖像被稱為IRAP圖像。

  • 解碼順序在IRAP之后而播放順序在之前的圖像稱為IRAP的前置(Leading)圖像(類似B幀)
  • 解碼順序在IRAP之后且播放順序在之后的圖像稱為IRAP的后置(Trailing)圖像

而前置圖像又分為RADL(Random Access Decodable Leading)圖像和RASL(Random Access Skipped Leading)圖像。

RADL圖像是不依賴IRAP前的碼流信息的圖像,從IRAP介入后,其可以被解碼;

RASL圖像是要依賴IRAP前的碼流信息的圖像,從IRAP介入后,不可以被解碼(比如雙向預(yù)測的B幀)。

HEVC中規(guī)定了三種IRAP圖像:

  • IDR(Instantaneous Decoding Refresh)圖像

    IDR圖像要求其前置圖像必須都是RADL圖像,即IDR和其后續(xù)(指解碼順序)不用依賴IDR圖像之前的視頻流進行解碼。

  • CRA(Clean Random Access)圖像

    允許前置圖像是RASL,允許參考CRA圖像前的視頻流使得RASL圖像獲得更高的編碼效率。

    當從CRA圖像介入時,RASL圖像就無法正常解碼。

  • BLA(Broken Link Access)圖像

    明確CRA的RASL圖像無須解碼的CRA成為BLA圖像。

還有兩種圖像:

TSA(Temporal sub-layer access):該圖像可以切換到時域?qū)哟笥诨虻扔谠搱D像時域?qū)訕俗R號的時域?qū)?/p>

STSA(Step wise Temporal sub-layer access):從該圖像切換該圖像所屬的時域?qū)印?/p>

吐槽一句:只記住IDR差不多就可以了……

流媒體傳輸協(xié)議相關(guān)小結(jié)——NALU、RTP、RTSP、RTMP、SDP等

該表詳細地給出了圖像的分類,對于無前置圖像的IDR圖像,從該圖像開始,后續(xù)的所有圖像都可以正確解碼,而寫后序圖像的播放順序都在IDR之后。

HEVC中的參數(shù)集 VPS SPS PPS

參考文章:H265學(xué)習(xí)之NALU頭_水笙趙的博客-CSDN博客_h265 nalu

H265/HEVC包含參數(shù)集(VPS,SPS,PPS,SEI),相比 h264 多了一個VPS。

  • VPS(視頻參數(shù)集)
    主要用傳輸視頻分級信息,有利于兼容可分級視頻以及3D視頻,如視頻包含最大的層級,也可包含profile,level等信息。一個給定的視頻序列,無論它的SPS是否相同,都參考相同的VPS。

  • SPS(序列參數(shù)集)
    主要包含一個CVS(Code Video Sequence 編碼視頻序列,指兩個IRAP之間的圖像,是一個GOP編碼后生成的壓縮數(shù)據(jù))所有編碼圖像共享的編碼參數(shù),SPS通過PPS引用而作用圖像。

    內(nèi)容大致可以分為幾個部分:1、自引ID;2、解碼相關(guān)信息,如檔次級別、分辨率、子層數(shù)等;3、某檔次中的功能開關(guān)標識及該功能的參數(shù);4、對結(jié)構(gòu)和變換系數(shù)編碼靈活性的限制信息;5、時域可分級信息;6、VUI。

    可以根據(jù)SPS計算視頻的寬和高:

    width  = sps->pic_width_in_luma_samples;
    height = sps->pic_height_in_luma_samples;
    

    當窗口有裁剪時(conformance_window_flag為1),計算如下:

    sub_width_c  = ((1==chroma_format_idc)||(2 == chroma_format_idc))&&(0==separate_colour_plane_flag)?2:1;
    sub_height_c = (1==chroma_format_idc)&& (0 == separate_colour_plane_flag)?2:1;
    width  -= (sub_width_c*conf_win_right_offset + sub_width_c*conf_win_left_offset);
    height -= (sub_height_c*conf_win_bottom_offset + sub_height_c*conf_win_top_offset);
    

    H264和H265幀率計算公式相同,如下:

    max_framerate = (float)(sps->vui.vui_time_scale) / (float)(sps->vui.vui_num_units_in_tick);
    
  • PPS(圖像參數(shù)集)
    一副圖像序列中的所有Slice Segment通過引用PPS進行解碼,其大致內(nèi)容包括初始圖像控制信息,如初始量化參數(shù)(Quantization Parameter,QP)、分塊信息等。

    此外,為了兼容標準在其他應(yīng)用上的擴展,例如可分級視頻編碼器、多視點視頻編碼器。

之間的關(guān)系可以見下圖:

流媒體傳輸協(xié)議相關(guān)小結(jié)——NALU、RTP、RTSP、RTMP、SDP等

VPS,SPS,PPS和SS存在各級引用關(guān)系,一副圖像中的所有SS引用同一個PPS,一個CVS中所有PPS引用同一個SPS。同一個視頻序列中的所有SPS引用一個VPS。VPS,SPS,PPS存在相同參數(shù),后者會覆蓋前者。

HEVC中字節(jié)流的生成過程

字節(jié)流方式則是NALU按照解碼順序排列成字節(jié)流傳輸。由于NALU里沒有NALU長度信息,所以如果NALU直接連接成字節(jié)流就無法區(qū)分不同的NALU,為了解決這個問題需要在每個NALU前添加起始碼字段。在H.265標準的附錄B中定義了相關(guān)規(guī)范。

NALU字節(jié)流生成過程:

  1. 在每個NALU前插入3字節(jié)起始碼start_code_prefix_one_3bytes,其值為0x000001

  2. 如果NALU類型為VPS_NUT, SPS_NUTPPS_NUT或者AU的第一個NALU,起始碼前還要插入zero_byte,其值為0x00

  3. 在視頻流的首個NALU的起始碼(可能包含zero_byte)前插入leading_zero_8bits,其值為0x00。注意:leading_zero_8bits只能加在第一個NALU前,否則0x00后面跟上4字節(jié)0x00 00 00 01(zero_byte后跟上 leading_zero_8bits)會被認為是前一個NALU的trailing_zero_8bits

  4. 根據(jù)需要在每個NALU后面添加trailing_zero_8bits作為填充數(shù)據(jù),其值為0x00

字節(jié)流的語法格式如下表所示,通過該語法格式可以從字節(jié)流中提取NALU??梢钥吹酵ㄟ^查找起始碼0x000001可以確定NALU的前邊界,通過查找第一個0x00000001可以確定視頻的前邊界,通過查找0x00000001可以確定AU的前邊界。

流媒體傳輸協(xié)議相關(guān)小結(jié)——NALU、RTP、RTSP、RTMP、SDP等

HEVC中NAL的作用機制

流媒體傳輸協(xié)議相關(guān)小結(jié)——NALU、RTP、RTSP、RTMP、SDP等

可以看出,經(jīng)過編碼后的視頻碼流由于時域上的參考關(guān)系,是具有不同的優(yōu)先級的,優(yōu)先級就會被封裝在NAL的頭信息中

HEVC中NAL單元的基本結(jié)構(gòu)

流媒體傳輸協(xié)議相關(guān)小結(jié)——NALU、RTP、RTSP、RTMP、SDP等

從NAL單元的基本結(jié)構(gòu)可知,NAL單元(NALU)由NALU頭和NALU載荷——原始字節(jié)序列負載(Raw Byte sequence payload, RBSP)組成。視頻編碼生成的壓縮比特流片段稱為SODB(String of Data Bits),SODB可能不是正好是整數(shù)字節(jié),需要在其后填充比特變成整字節(jié),填充后的比特流稱為原始字節(jié)載荷序列(Raw Byte Sequence Payload,RBSP)。

SODB生成RBSP的過程如下:

1、RBSP第1字節(jié)取SODB最左端8比特,第2字節(jié)取接下來8比特,以此類推直到SODB剩余內(nèi)容不足8比特。
2、RBSP下一字節(jié)首先包含SODB最后幾個比特,然后添加比特1,如果該字節(jié)還不滿8比特后面填充0。
3、后面可能加入若干16比特的cabac_zero_word作為填充比特,其值為0x00 00。RBSP還不能直接作為NALU Body,因為

由于RBSP中可能含有0x00 00 01,與起始碼沖突,必須先進行沖突避免處理。

流媒體傳輸協(xié)議相關(guān)小結(jié)——NALU、RTP、RTSP、RTMP、SDP等

其中0x00 00 02是預(yù)留碼。

HEVC中NAL頭的語法定義

NALU頭部結(jié)構(gòu)如下:

其語法定義如下:

流媒體傳輸協(xié)議相關(guān)小結(jié)——NALU、RTP、RTSP、RTMP、SDP等

在ffmpeg中的定義如下:

typedef struct H265RawNALUnitHeader {
    uint8_t forbidden_zero_bit;
    uint8_t nal_unit_type;
    uint8_t nuh_layer_id;
    uint8_t nuh_temporal_id_plus1;
} H265RawNALUnitHeader;

頭部算起來,一共16位,兩個字節(jié)

接下來介紹每一個語法元素的作用:

forbidden_zero_bits(1bit)

默認為0,值為1時表示錯誤,當網(wǎng)絡(luò)發(fā)現(xiàn)NAL單元有比特錯誤時可設(shè)置該比特為1,以便接收方糾錯或丟掉該單元。

nuh_layer_id(6bit)

layerId預(yù)留位,取值范圍0~55,用來指示VCL數(shù)據(jù)屬于哪個層或者標識non-VLC數(shù)據(jù),默認全為0,用于未來擴展,如用來表示可分級視頻或3D視頻等。

nal_unit_type(6bits)

用來標識NAL單元類型,取值范圍[0, 63],占用NALU header的第一個字節(jié)的最后一位和第二個字節(jié)的前五位。通常NAL單元類型包括參數(shù)集(VPS,PPS,SPS,SEI)以及slice 數(shù)據(jù)(如IDR,其他類型幀等)。

HEVC中0~40都是有明確含義的。

流媒體傳輸協(xié)議相關(guān)小結(jié)——NALU、RTP、RTSP、RTMP、SDP等

nuh_temporal_id_plus1(3bit)

該字段默認為1。temporal_id表示NAL單元的時域?qū)蛹墸?s>根據(jù)圖像時域?qū)蛹壘涂梢源_定其重要性,如時域?qū)蛹壭〉膱D像不會參考時域?qū)蛹壌蟮膱D像,如通常參數(shù)集 或者idr幀的temporal_id為0。

注:HEVC的NAL頭結(jié)構(gòu)與h264有明顯的不同,HEVC加入了NAL所在的時域?qū)拥腎D,取去除了nal_ref_idc元素,將此此信息合并到了nal_unit_type中。

H265(HEVC) nal 單元頭介紹及rtp發(fā)送中的fu分組發(fā)送詳解_一二三的博客-CSDN博客_nal rtp

該篇文章中講述了HEVC的NALU Header ,以及分組分片中FU分組的發(fā)送過程,寫的比較簡要,但是還是可以讀一讀。


AVC中碼流的封裝結(jié)構(gòu)

與HEVC近似相同,封裝層次如下:

SODB + RBSP trailing bits = RBSP

NAL header(1 byte) + RBSP = NALU

RTP封裝格式(12個字節(jié)) + NALU = 最后f發(fā)送出去的完整包

RBSP就是H.264編碼后出來的純碼流文件,給文件加上后綴.h264,得到xxx.h264。

RBSP

流媒體傳輸協(xié)議相關(guān)小結(jié)——NALU、RTP、RTSP、RTMP、SDP等

一段h264的碼流其實就是多個sequence組成的,

一個sequence是一秒,如果FPS等于30,就有30幀圖像(包括I/P/B幀)

每個sequence均有固定結(jié)構(gòu)單元:1 SPS + 1 PPS + 1 SEI + 1 I 幀 + 若干P幀(加上B幀一共有6種單元情況)

H.264在編碼的時候,生成一個序列時,序列中每個單元前面就會加上00 00 00 01作為分隔符。

看H264的碼流結(jié)構(gòu),NALU頭 + RBSP = NALU

SPS

序列參數(shù)集:固定14個字節(jié)。

序列參數(shù)集。SPS中保存了一組編碼視頻序列(Coded video sequence)的全局參數(shù),所謂的編碼視頻序列即原始視頻的一幀一幀的像素數(shù)據(jù)經(jīng)過編碼之后的結(jié)構(gòu)組成的序列。而每一幀的編碼后數(shù)據(jù)所依賴的參數(shù)保存于圖像參數(shù)集中。

里面包含宏塊編碼方式、圖像大小尺寸、宏塊個數(shù),播放器通過這些參數(shù),調(diào)用播放器里面的對應(yīng)算法去解碼。

具體意義參考博客:

H264編解碼SPS、PPS參數(shù)說明_chen_song_的博客-CSDN博客_h264 sps

h.264中的SPS和PPS_sps pps_thehunters的博客-CSDN博客

H264碼流中SPS PPS詳解<轉(zhuǎn)> - 瓦楞球 - 博客園 (cnblogs.com)

PPS

圖像參數(shù)集:固定4個字節(jié)

具體意義參考博客:
H264編解碼SPS、PPS參數(shù)說明_chen_song_的博客-CSDN博客_h264 sps

h.264中的SPS和PPS_sps pps_thehunters的博客-CSDN博客

H264碼流中SPS PPS詳解<轉(zhuǎn)> - 瓦楞球 - 博客園 (cnblogs.com)

SEI

補充增強信息

具體意義參考博客:SEI(Supplemental Enhancement Information)_拉轟小鄭鄭的博客-CSDN博客

I幀、P幀、B幀

I幀:I幀是關(guān)鍵,丟了I幀當前sequence就廢了,每個sequence有且只有1個I幀

幀內(nèi)編碼幀 ,I幀表示關(guān)鍵幀,你可以理解為這一幀畫面的完整保留;

解碼時只需要本幀數(shù)據(jù)就可以完成(因為包含完整畫面),

I幀大,說明本身壓縮比不高,圖像數(shù)據(jù)更完整,而P幀可以越小,反之I幀越小則P幀則會越大

P幀:前向預(yù)測編碼幀。P幀表示的是這一幀跟之前的一個關(guān)鍵幀(或P幀)的差別,解碼時需要用之前緩存的畫面疊加上本幀定義的差別,生成最終畫面。(也就是差別幀,P幀沒有完整畫面數(shù)據(jù),只有與前一幀的畫面差別的數(shù)據(jù))

B幀:雙向預(yù)測內(nèi)插編碼幀。B幀是雙向差別幀,也就是B幀記錄的是本幀與前后幀的差別

具體特點參考:https://www.cnblogs.com/cy568searchx/p/6125031.html

AVC中NAL單元的基本結(jié)構(gòu)

下圖為NALU頭部結(jié)構(gòu),就1字節(jié),和HEVC的兩字節(jié)不同:

流媒體傳輸協(xié)議相關(guān)小結(jié)——NALU、RTP、RTSP、RTMP、SDP等

第1位:禁止位,值為1表示語法出錯;
第2~3位:為參考級別nal_ref_idc,數(shù)值越高,級別越高;
第4~8:為是NALU類型nal_unit_type(比如整個頭是0x67,即01100111,取后5位00111表示sps)


通常情況下,因為互聯(lián)網(wǎng)是基于分組傳輸?shù)?,接收端收到?shù)據(jù)包往往有延遲和亂序。流媒體要流式傳輸,需要從降低時延和恢復(fù)數(shù)據(jù)包時序入手。發(fā)送端為了降低延遲,往往對傳輸數(shù)據(jù)進行壓縮。而在接收端為了恢復(fù)時序,就需要接收緩沖,即將收到的數(shù)據(jù)包緩存起來,按照封裝信息進行重新排序,最后將重新排序后的數(shù)據(jù)包放入播放緩沖。播放緩沖存在的意義是為了應(yīng)對網(wǎng)絡(luò)波動,導(dǎo)致數(shù)據(jù)遲遲無法完整的被下載到接收緩沖區(qū),在播放端無內(nèi)容可放時,就會出現(xiàn)畫面卡頓。

總而言之,控制流媒體數(shù)據(jù)包到達接收端的時序

RTP協(xié)議 + RTCP協(xié)議

RTP概念及應(yīng)用環(huán)境

RTP全名是Real-time Transport Protocol(實時傳輸協(xié)議)

它是IETF提出的一個標準,對應(yīng)的RFC文檔為RFC3550(RFC1889為其過期版本)。RFC3550不僅定義了RTP,而且定義了配套的相關(guān)協(xié)議RTCP(Real-time Transport Control Protocol,實時傳輸控制協(xié)議)

RTP用來為IP網(wǎng)上的語音、圖像、傳真等多種需要實時傳輸?shù)亩嗝襟w數(shù)據(jù)提供端到端的實時傳輸服務(wù)。RTP為Internet上端到端的實時傳輸提供時間信息和流同步,但并不保證服務(wù)質(zhì)量,服務(wù)質(zhì)量由RTCP來提供。

RTP用于在單播或多播網(wǎng)絡(luò)中傳送實時數(shù)據(jù)。它們典型的應(yīng)用場合有如下幾個。

  • 簡單的多播音頻會議。

    語音通信通過一個多播地址和一對相鄰端口來實現(xiàn)。一個用于音頻數(shù)據(jù)(RTP),另一個用于控制包(RTCP)。

  • 音頻和視頻會議。

    如果在一次會議中同時使用了音頻和視頻會議,這兩種媒體將分別在不同的RTP會話中傳送,每一個會話使用不同的傳輸?shù)刂罚↖P地址+端口)。如果一個用戶同時使用了兩個會話,則每個會話對應(yīng)的RTCP包都使用規(guī)范化名字CNAME(Canonical Name)。與會者可以根據(jù)RTCP包中的CNAME來獲取相關(guān)聯(lián)的音頻和視頻,然后根據(jù)RTCP包中的計時信息(Network time protocol)來實現(xiàn)音頻和視頻的同步。

  • 翻譯器和混合器。

    翻譯器和混合器都是RTP級的中繼系統(tǒng)。翻譯器用在通過IP多播不能直接到達的用戶區(qū),例如發(fā)送者和接收者之間存在防火墻。當與會者能接收的音頻編碼格式不一樣,比如有一個與會者通過一條低速鏈路接入到高速會議,這時就要使用混合器。在進入音頻數(shù)據(jù)格式需要變化的網(wǎng)絡(luò)前,混合器將來自一個源或多個源的音頻包進行重構(gòu),并把重構(gòu)后的多個音頻合并,采用另一種音頻編碼進 行編碼后,再轉(zhuǎn)發(fā)這個新的RTP包。從一個混合器出來的所有數(shù)據(jù)包要用混合器作為它們的同步源(SSRC,見RTP的封裝)來識別,可以通過貢獻源列表(CSRC表,見RTP的封裝)可以確認與會者。


RTP的協(xié)議層次

該圖是一個典型的流媒體傳輸?shù)捏w系結(jié)構(gòu)。

流媒體傳輸協(xié)議相關(guān)小結(jié)——NALU、RTP、RTSP、RTMP、SDP等

RTP被劃分在傳輸層,它建立在UDP上。同UDP協(xié)議一樣,為了實現(xiàn)其實時傳輸功能,RTP也有固定的封裝形式。RTP用來為端到端的實時傳輸提供時間信息和流同步,但并不保證服務(wù)質(zhì)量。服務(wù)質(zhì)量由RTCP來提供。

不少人也把RTP歸為應(yīng)用層的一部分,這是從應(yīng)用開發(fā)者的角度來說的。操作系統(tǒng)中的TCP/IP等協(xié)議棧所提供的是我們最常用的服務(wù),而RTP的實現(xiàn)還是要靠開發(fā)者自己。因此從開發(fā)的角度來說,RTP的實現(xiàn)和應(yīng)用層協(xié)議的實現(xiàn)沒什么不同,所以可將RTP看成應(yīng)用層協(xié)議。

RTP Over UDP

RTP實現(xiàn)者在發(fā)送RTP數(shù)據(jù)時,需先將數(shù)據(jù)封裝成RTP包,而在接收到RTP數(shù)據(jù)包,需要將數(shù)據(jù)從RTP包中提取出來。

從上文中可以推測出,頭部中應(yīng)該有時間戳、數(shù)據(jù)來源等字段,RTP的固定字節(jié)量為12字節(jié),而下圖則展示了RTP協(xié)議封裝時使用的完整頭部結(jié)構(gòu):

流媒體傳輸協(xié)議相關(guān)小結(jié)——NALU、RTP、RTSP、RTMP、SDP等

  • 版本號(V):2比特,用來標志使用的RTP版本。

  • 填充位(P):1比特,如果該位置位,則該RTP包的尾部就包含附加的填充字節(jié)。

  • 擴展位(X):1比特,如果該位置位的話,RTP固定頭部后面就跟有一個擴展頭部。

  • CSRC計數(shù)器(CC):4比特,含有固定頭部后面跟著的CSRC的數(shù)目。

  • 標記位(M):1比特,該位的解釋由配置文檔(Profile)來承擔(dān).

  • 載荷類型(PT):7比特,范圍為0~127,標識了RTP載荷的類型。具體含義可以參考下面的這篇博文:RTP 有效負載(載荷)類型,RTP Payload。有一些媒體內(nèi)容出現(xiàn)的比較晚,包括264,所以只能用后面的96~127動態(tài)位來表示,例如DynamicRTP-Type-96,即為h264。

  • 序列號(SN):16比特,發(fā)送方在每發(fā)送完一個RTP包后就將該域的值增加1,接收方可以由該域檢測包的丟失及恢復(fù)包序列。序列號的初始值是隨機的。但也只是表示了包發(fā)出的先后順序。

  • 時間戳:32比特,記錄了該包中數(shù)據(jù)的第一個字節(jié)的采樣時刻。在一次會話開始時,時間戳初始化成一個初始值。即使在沒有信號發(fā)送時,時間戳的數(shù)值也要隨時間而不斷地增加(時間在流逝嘛)。時間戳是去除抖動和實現(xiàn)同步不可缺少的。

    時間戳的增量與視頻/音頻的時鐘頻率(采樣頻率)有關(guān),增加值為固定量。

    • 以音頻負載類型為例,假設(shè)采樣率為8kHz,則每個采樣的持續(xù)時間為1/8000秒,即0.125毫秒。因此,如果上一個RTP數(shù)據(jù)包的時間戳值是T1,則當前數(shù)據(jù)包的時間戳值應(yīng)該是T1+采樣數(shù)*(時鐘頻率/采樣率)。這里,時鐘頻率指的是RTP時鐘頻率,通常為90kHz。因此,對于音頻負載類型,每個RTP數(shù)據(jù)包的時間戳值應(yīng)該增加:

      timestamp = T1 + (采樣數(shù) * 90000 / 8000)

    • 對于視頻負載類型,時間戳的增加方式類似,只是單位不同。假設(shè)視頻幀率為30幀/秒,則每個視頻幀的間隔為1/30秒,即33.333毫秒。因此,如果上一個RTP數(shù)據(jù)包的時間戳值是T1,則當前數(shù)據(jù)包的時間戳值應(yīng)該是T1+幀數(shù)*(時鐘頻率/幀率)。因此,對于視頻負載類型,每個RTP數(shù)據(jù)包的時間戳值應(yīng)該增加:

      timestamp = T1 + (幀數(shù) * 90000 / 30)

    這里我以抓包H265為例,簡單驗證一下該表達式:

    流媒體傳輸協(xié)議相關(guān)小結(jié)——NALU、RTP、RTSP、RTMP、SDP等

    以上是我抓包的h265碼流,可以看到藍框中不同類型的包的時間戳分別為

    ...3892,...7422,...10951,...14480,...18010

    我們可以計算一下時間戳之間的間隔,分別為

    3530, 3529, 3529, 3530。一開始我以為這是fps,但是原視頻fps = 25.5,1 / 25.5 ≈ 0.03921s,對不上這個數(shù)字。

    后來查閱資料后,應(yīng)該按照上面的式子計算,我們代入?yún)?shù),計算一下時間戳增加的間隔:

    ?timestamp = 1(幀視頻)* 90000 / 25.5 ≈ 3529 ,如果代入單位的話,即可知時間戳沒有單位(該過程省略)。

  • 同步源標識符(Synchronization sourc*e identifier*, SSRC):32比特,同步源就是指RTP包流的來源。在同一個RTP會話中不能有兩個相同的SSRC值。該標識符是隨機選取的 RFC1889推薦了MD5隨機算法。

  • 貢獻源列表(CSRC(Contributing sourc*e IDs*) List):0~15項,每項32比特,用來標志對一個RTP混合器產(chǎn)生的新包有貢獻的所有RTP包的源。由混合器將這些有貢獻的SSRC標識符插入表中。SSRC標識符都被列出來,以便接收端能正確指出交談雙方的身份。

    如果只有一個源的話,這項是沒有的。

RTP Over TCP

RTP默認是采用UDP發(fā)送的,格式為RTP頭+RTP載荷,如果是使用TCP,那么需要在RTP頭之前再加上四個字節(jié)

第一個字節(jié):$,辨識符

第二個字節(jié):通道,在SETUP的過程中獲取

第三第四個字節(jié): RTP包的大小,最多只能12位,第三個字節(jié)保存高4位,第四個字節(jié)保存低8位


RTP載荷 以H264碼流為例

下圖為H264中載荷頭的格式:

流媒體傳輸協(xié)議相關(guān)小結(jié)——NALU、RTP、RTSP、RTMP、SDP等

載荷格式定義三個不同的基本載荷結(jié)構(gòu),接收者可以通過RTP荷載的第一個字節(jié)后5位(如圖2)識別荷載結(jié)構(gòu)。

Nalu_Type NALU內(nèi)容 備注
0 未指定
1 非IDR圖像編碼的slice 比如普通I、P、B幀
2 編碼slice數(shù)據(jù)劃分A 2類型時,只傳遞片中最重要的信息,如片頭,片中宏塊的預(yù)測模式等;一般不會用到;
3 編碼slice數(shù)據(jù)劃分B 3類型是只傳輸殘差;一般不會用到;
4 編碼slice數(shù)據(jù)劃分C 4時則只可以傳輸殘差中的AC系數(shù);一般不會用到;
5 IDR圖像中的編碼slice IDR幀,IDR一定是I幀但是I幀不一定是IDR幀。
6 SEI補充增強信息單元 可以存一些私有數(shù)據(jù)等;
7 SPS 序列參數(shù)集 SPS對如標識符、幀數(shù)以及參考幀數(shù)目、解碼圖像尺寸和幀場模式等解碼參數(shù)進行標識記錄
8 PPS 圖像參數(shù)集 PPS對如熵編碼類型、有效參考圖像的數(shù)目和初始化等解碼參數(shù)進行標志記錄。
9 單元定界符 視頻圖像的邊界
10 序列結(jié)束 表明下一圖像為IDR圖像
11 碼流結(jié)束 表示該碼流中已經(jīng)沒有圖像
12 填充數(shù)據(jù) 啞元數(shù)據(jù),用于填充字節(jié)
13-23 保留
24 單時間聚合包類型A(SATP-A)
25 單時間聚合包類型B (STAP-B)
26 多時間聚合包類型(MTAP)16位位移(MTAP16)
27 多時間聚合包類型(MTAP)24位位移(MTAP24)
28 分片單元FU-A
29 分片單元FU-B
30-31 未被定義
  • 單個NAL包:載荷中只包含一個NAL單元。NAL頭類型的域等于原始NAL單元類型,范圍在1~23之間

  • 聚(組)合包(Aggregation Packet,AP):用于聚合多個NAL單元到單個RTP載荷NALU中,有四種版本

    • 單時間聚合包類型A(SATP-A) NAL單元型號 = 24
    • 單時間聚合包類型B (STAP-B) NAL單元型號 = 25
    • 多時間聚合包類型(MTAP)16位位移(MTAP16) NAL單元型號 = 26
    • 多時間聚合包類型(MTAP)24位位移(MTAP24) NAL單元型號 = 27
  • 分片分組(Fragmentation Packet,F(xiàn)P):一個分組只承載一個NALU的一部分?,F(xiàn)存兩個版本FU-AFU-B,用NAL單元類型 28,29標識

    • Q:FU-A和FU-B版本的不同之處?

    • A:回答來自于Chat-GPT,

      FU-A是一種將原始NALU分解成若干個小分片單元的方法,并在每個分片單元上添加頭部以標識它們的類型和位置。它用于可靠性更高的環(huán)境,例如在實時視頻傳輸中。

      FU-B是一種將NALU分解成若干個小分片單元的方法,不同的是它不添加頭部信息,而是使用隱含的方法來標識分片單元的類型和位置。它用于碼率敏感的環(huán)境,因為它不需要添加額外的頭部信息。

      總的來說,F(xiàn)U-A提供了更高的可靠性,而FU-B提供了更高的效率。兩者都是在H.264視頻編碼中廣泛使用的。

      網(wǎng)絡(luò)上大多是提及Fu-A,很少有提到Fu-B的。

常用的打包時的分包規(guī)則是:如果小于MTU采用單個NAL單元包,如果大于MTU就采用FUs分片方式。

因為常用的打包方式就是單個NAL包和FU-A方式,所以我們只解析這兩種。

單個NAL包

流媒體傳輸協(xié)議相關(guān)小結(jié)——NALU、RTP、RTSP、RTMP、SDP等

必須只包含一個NAL單元。聚合包和分片單元不可以用在單個NAL單元包中,RTP序號必須符合NAL的解碼順序,且NAL單元的第一個字節(jié)和RTP載荷的頭的第一個字節(jié)重合。

打包H264碼流時,只需在幀前面加上12字節(jié)的RTP頭即可。

聚合包封裝類型

(略)

分片單元(以FU-A為例)

流媒體傳輸協(xié)議相關(guān)小結(jié)——NALU、RTP、RTSP、RTMP、SDP等

上圖表示FU-A的RTP載荷形式。

分片只定義于單個NAL單元,而不用于任何聚合包(將多個NALU置于一個Packet)。

NAL單元的一個分片由整數(shù)個連續(xù)NAL單元字節(jié)組成。每個NAL單元字節(jié)必須正好是該NAL單元一個分片的一部分(意思就是不能跨分片)。

相同NAL單元的分片必須使用遞增的RTP序號連續(xù)順序發(fā)送(第一分片與最后分片之間沒有其他的RTP包)。相似地,NAL單元必須按照RTP順序號的順序裝配。

當一個NALU被分片運送在分片單元(FUs)中時,被引用為分片NAL單元。STAPs, MTAPs(?)不可以被分片。 FUs不可以嵌套, 即一個FU 不可以包含另一個FU。運送FU的RTP時戳被設(shè)置成分片NAL單元的時刻。
FU-A由1字節(jié)的分片單元indicator(下圖左圖),1字節(jié)的分片單元header(下圖右圖),和載荷組成。

下面介紹分片單元indicator中各位的作用:

  • F - 1bit 禁止位

    值為1表示語法出錯;

  • NRI - 2 bit 參考級別

    數(shù)值越高,級別越高;

  • FU Type - 5 bit

    NALU類型nal_unit_type(但是這里應(yīng)當按照分不分NALU做區(qū)分

以下介紹分片單元頭的各位作用:

  • S -1 bit 起始位

    設(shè)置成1時,表示分片為NAL單元的開始。

    當荷載不是分片NAL單元載荷的開始,就設(shè)為0。

  • E - 1 bit 結(jié)束位

    當設(shè)置成1, 結(jié)束位指示分片NAL單元的結(jié)束,即載荷的最后字節(jié)也是分片NAL單元的最后一個字節(jié)。

    當跟隨的 FU荷載不是分片NAL單元的最后分片,結(jié)束位設(shè)置為0。

  • R - 1 bit 保留位

    必須設(shè)置為0,接收者必須忽略該位

  • Type - 5 bit 用于標識NALU中(視頻數(shù)據(jù))的類型

打包時,原始的NAL頭的前三位為FU標識的前三位,原始的NAL頭的后五位為FU header的后五位。

以該碼流信息為例,前十二個字節(jié)是RTP Header,7c是FU indicator,85是FU header,轉(zhuǎn)換為二進制如下:

0111 1100 1000 0101,按照順序解析如下:

0 —— 是F
11 —— 是NRI
11100 —— 是FU Type,這里是28,即FU-A
1 —— 是S,Start,說明是分片的第一包
0 —— 是E,End,如果是分片的最后一包,設(shè)置為1,這里不是
0 —— 是R,Remain,保留位,總是0
00101 —— 是NAl Type,這里是5,說明是IDR幀中的編碼Slice(不知道為什么是關(guān)鍵幀請自行谷歌)

流媒體傳輸協(xié)議相關(guān)小結(jié)——NALU、RTP、RTSP、RTMP、SDP等

打包時,F(xiàn)Uindicator的F、NRI是NAL Header中的F、NRI,Type是28;FU Header的S、E、R分別按照分片起始位置設(shè)置,Type是NAL Header中的Type。

解包時,取FU indicator的前三位和FU Header的后五位,即0110 0101(0x65)為NALU header。

RTP載荷 以H265碼流為例

參考文章:H265碼流RTP封裝方式詳解_一二三的博客-CSDN博客_rtp h265

此處還是需要擺一下H265中 NALU 格式的定義,為2字節(jié)大?。?/p>

流媒體傳輸協(xié)議相關(guān)小結(jié)——NALU、RTP、RTSP、RTMP、SDP等

相比較H264的NALU頭,265中去掉了nal_ref_idc字段,并加入了nal所在時間層的ID,即TID一項,各字段的含義在首篇NALU中已經(jīng)解析過,此處簡單提一下:

  • F:禁止位,通常情況下為0, 如果為1,表示該幀無效

  • Type:幀類型,6bits(9~14位),0-31是vcl nal單元;32-63,是非vcl nal單元,VCL是指攜帶編碼數(shù)據(jù)的數(shù)據(jù)流,而non-VCL則是控制數(shù)據(jù)流。

  • LayerID:6 bits,表示NAL所在的Access unit所屬的層,該字段是為了HEVC的繼續(xù)擴展設(shè)置,一般為0

  • TID:3bits,一般為1,此字段指定nal單元加1的時間標識符。時間id的值等于tid-1,tid的值為0是非法的,以確保nal單元報頭中至少只有一個比特等于1,以便能夠在nal單元頭和nal單元有效負載數(shù)據(jù)中獨立考慮啟動代碼仿真(這句話我也沒明白)。

此處以VPS包為例,見下圖:

流媒體傳輸協(xié)議相關(guān)小結(jié)——NALU、RTP、RTSP、RTMP、SDP等

Single NAL Unit Packets(SNUs)封裝模式

RTP屬于應(yīng)用層協(xié)議,封裝完之后要置于數(shù)據(jù)鏈路層傳輸,參考文章中說數(shù)據(jù)幀大小小于MTU,我認為是不對的。

使用協(xié)議封裝完的數(shù)據(jù),在傳輸層,最大上限應(yīng)該是MSS。當然,在這里先不是很重要,嘻嘻。

如果傳輸數(shù)據(jù)幀小于最大載荷值,可采用單獨一幀封裝到一個RTP包中,封裝格式如下:

流媒體傳輸協(xié)議相關(guān)小結(jié)——NALU、RTP、RTSP、RTMP、SDP等

PayloadHeader一般與NALU Header定義完全一致;

DONL:Decoding Order Number,當使用多slice編碼模式時使用,用于判斷一幀的每個slice是否收齊,一般使用單slice就無此字段,所以通常境況下,單一幀模式封裝方式與H264一致。

H265幀去掉起始位直接作為負載,這里不做過多介紹。

Aggregation Packets (APs)封裝模式

當幀很小,可以多幀組合封裝到一個RTP包,比如VPS、SPS、PPS,可以看到幀大小確實很小。

流媒體傳輸協(xié)議相關(guān)小結(jié)——NALU、RTP、RTSP、RTMP、SDP等

其格式如下:

流媒體傳輸協(xié)議相關(guān)小結(jié)——NALU、RTP、RTSP、RTMP、SDP等

PayloadHeader 負載頭,與H264 NALUheader類似,有F,TYPE,LayerID,TID組成,一般F=0,LayerID=0,TID=1,這里Type必須為48,標識組合包頭。

不帶DONL的組合包封裝模式與H264類似,這里不做多說,一般情況下很少用到組合幀封裝方式,小于MTU的幀一般是單一幀封裝,減少解封裝復(fù)雜性。

Fragmentation Units(FUs)封裝模式

當視頻幀大于最大負載,需要對幀進行分包發(fā)送,從而避免IP層分片,這里采用FU分片模式,格式如下:

流媒體傳輸協(xié)議相關(guān)小結(jié)——NALU、RTP、RTSP、RTMP、SDP等

這里PayloadHeaderF=0,LayerID=0,TID=1,Type必須為49表示FU分片。

FU header定義與FU-A定義基本一致,由于NALU Type在H265中為6bits表示,所以這里去掉了R,只保留S/E/TYPE格式如下:

流媒體傳輸協(xié)議相關(guān)小結(jié)——NALU、RTP、RTSP、RTMP、SDP等

S:1bit,1-表示是首個分片報文,0 - 非首個分片報文
E:1bit,1-表示最后一個分片報文,0 -非最后一個分片報文
FuType:6 bits,對應(yīng)的NALU type

RTP載荷PS流(有些老舊的知識)

PS流指program streaming,是使用MPEG-2標準對多媒體數(shù)據(jù)進行編碼的一種方式。

每個IDR NALU 前一般都會包含SPS、PPS 等NALU,因此將SPS、PPS、IDR 的NALU 封裝為一個PS包,包括PS頭,然后加上PS system header,PS system map,PES header + h264 raw data

所以一個IDR NALU PS 包由外到內(nèi)順序是:

PS header > PS system header > PS system Map > PES header > h264 raw data。

對于其它非關(guān)鍵幀的PS 包,就簡單多了,直接加上PS頭和PES頭就可以了,順序為:

PS header > PES header > h264raw data。

以上是對只有視頻video 的情況,如果要把音頻Audio也打包進PS 封裝,也可以。當有音頻數(shù)據(jù)時,將數(shù)據(jù)加上PES header 放到視頻PES 后就可以了。順序如下:

PS 包 = PS頭 > PES(video) > PES(audio),再用RTP 封裝發(fā)送就可以了。

GB28181 對RTP 傳輸?shù)臄?shù)據(jù)負載類型有規(guī)定(參考GB28181 附錄B),負載類型中96-127。

RFC2250中建議 96 表示 PS 封裝,建議 97 為 MPEG-4,建議 98 為H264;

即我們接收到的RTP 包首先需要判斷負載類型,若負載類型為96,則采用PS 解復(fù)用,將音視頻分開解碼。若負載類型為98,直接按照H264 的解碼類型解碼。

如果打包格式不標準,那這個方法就不可靠了。

PS流包頭

流媒體傳輸協(xié)議相關(guān)小結(jié)——NALU、RTP、RTSP、RTMP、SDP等

主要參數(shù)有三個:

  1.    `Pack start code`:包起始碼字段,值為0x000001BA的位串,用來標志一個包的開始。
    
  2.    `System clock reference base`,`system clock reference extenstion`:系統(tǒng)時鐘參考字段。
    
  3.    `Pack stuffing length`:包填充長度字段,3 位整數(shù),規(guī)定該字段后填充字節(jié)的個數(shù)
    
PS system header 系統(tǒng)標題

流媒體傳輸協(xié)議相關(guān)小結(jié)——NALU、RTP、RTSP、RTMP、SDP等

System header當且僅當pack是第一個數(shù)據(jù)包時才存在,即PS包頭之后就是系統(tǒng)標題。取值0x000001BB的位串,指出系統(tǒng)標題的開始,暫時不需要處理,讀取Header Length直接跳過即可。

PS system map 系統(tǒng)映射

System Map也是當且僅當pack是第一個數(shù)據(jù)包時才存在,即系統(tǒng)標題之后就是節(jié)目流映射。取值0x000001BC的位串,指出節(jié)目流映射的開始,暫時不需要處理,讀取Header Length直接跳過即可。前5字節(jié)的結(jié)構(gòu)同System Header。

舉例如下:

流媒體傳輸協(xié)議相關(guān)小結(jié)——NALU、RTP、RTSP、RTMP、SDP等

前14個字節(jié)是PS包頭(注意,沒有擴展);

接下來的00 00 01 bb是系統(tǒng)標題起始碼;

接下來的00 0c說明了系統(tǒng)標題的長度(不包括起始碼和長度字節(jié)本身);

接下來的12個字節(jié)是系統(tǒng)標題的具體內(nèi)容,這里不做解析;

繼續(xù)看到00 00 01 bc,這是PS System Map起始碼;

緊接著的00 1e同樣代表長度;跳過e1 ff,基本沒用;

接著2個字節(jié)代表program_stream_info長度,這里是00 00,即便有值,一般也可以直接跳過;

接下來是00 18,代表基本流長度,說明了后面還有24個字節(jié);

接下來的1b,意思是H264編碼格式;

下一個字節(jié)e0,意思是視頻流;

接下里00 0c,同樣代表接下的長度12個字節(jié);

跳過這12個字節(jié),看到90,這是G.711音頻格式;

下一個字節(jié)是c0,代表音頻流;

接下來的00 00同樣代表長度,這里是0;

接下來4個字節(jié)是CRC,循環(huán)冗余校驗。

到這里PS system map流解析完畢。

PES header

PES(Packetized Elementary Stream)頭是MPEG-2 Program Stream(PS)格式中用于對音頻和視頻數(shù)據(jù)進行封裝的數(shù)據(jù)單元。

這個長度確實巨夸張……

流媒體傳輸協(xié)議相關(guān)小結(jié)——NALU、RTP、RTSP、RTMP、SDP等

一些要介紹的字段如下:

  1.    Packet start code prefix:值為0x000001的位串,它和后面的stream id 構(gòu)成了標識分組開始的分組起始碼,用來標志一個包的開始。
    
  2.    Stream id:在媒體流中,它規(guī)定了基本流的號碼和類型。0x(C0~DF)指音頻,0x(E0~EF)為視頻
    
  3.    PES packet length:16 位字段,指出了PES 分組中跟在該字段后的字節(jié)數(shù)目。值為0 表示PES 分組長度要么沒有規(guī)定要么沒有限制。這種情況只允許出現(xiàn)在有效負載包含來源于傳輸流分組中某個視頻基本流的字節(jié)的PES 分組中。
    
  4.    PTS_DTS:2 位字段。當值為'10'時,PTS 字段應(yīng)出現(xiàn)在PES 分組標題中;當值為'11'時,PTS 字段和DTS 字段都應(yīng)出現(xiàn)在PES 分組標題中;當值為'00'時,PTS 字段和DTS 字段都不出現(xiàn)在PES分組標題中。值'01'是不允許的。
    
  5.    ESCR:1位。置'1'時表示ESCR 基礎(chǔ)和擴展字段出現(xiàn)在PES 分組標題中;值為'0'表示沒有ESCR 字段。
    
  6.    ESrate:1 位。置'1'時表示ES rate 字段出現(xiàn)在PES 分組標題中;值為'0'表示沒有ES rate 字段。
    
  7.    DSMtrick mode:1 位。置'1'時表示有8 位特技方式字段;值為'0'表示沒有該字段。
    
  8.    Additionalinfo:1 位。附加版權(quán)信息標志字段。置'1'時表示有附加拷貝信息字段;值為'0'表示沒有該字段。
    
  9.    CRC:1 位。置'1'時表示CRC 字段出現(xiàn)在PES 分組標題中;值為'0'表示沒有該字段。
    
  10.    Extensionflag:1 位標志。置'1'時表示PES 分組標題中有擴展字段;值為'0'表示沒有該字段。
    

PES header data length: 8 位。PES 標題數(shù)據(jù)長度字段。指出包含在PES 分組標題中的可選字段和任何填充字節(jié)所占用的總字節(jié)數(shù)。該字段之前的字節(jié)指出了有無可選字段。


RTCP概述

RTCP作為控制協(xié)議,其承載的信息量遙遠大于RTP本身。

RTCP的主要功能是:服務(wù)質(zhì)量的監(jiān)視與反饋、媒體間的同步,以及多播組中成員的標識。

在RTP會話期間,各參與者周期性地傳送RTCP包。RTCP包中含有已發(fā)送的數(shù)據(jù)包的數(shù)量、丟失的數(shù)據(jù)包的數(shù)量等統(tǒng)計資料,因此,各參與者可以利用這些信息動態(tài)地改變傳輸速率,甚至改變有效載荷類型。RTP和RTCP配合使用,它們能以有效的反饋和最小的開銷使傳輸效率最佳化,因而特別適合傳送網(wǎng)上的實時數(shù)據(jù)。

根據(jù)此前的協(xié)議結(jié)構(gòu)圖,可以看到RTCP同樣使用UDP進行傳輸。但RTCP封裝的僅僅是一些控制信息,因而分組很短,所以可以將多個RTCP分組封裝在一個UDP包中。RTCP有如下五種分組類型。

類型 縮寫表示 用途
200 SR(Sender Report) 發(fā)送端報告
201 RR(Receiver Report) 接收端報告
202 SDES(Source Description Items) 源點描述
203 BYE 結(jié)束傳輸
204 APP 特定應(yīng)用

上述五種分組的封裝大同小異,本文中以SR類型為例。

發(fā)送端報告分組SR(Sender Report)用來使發(fā)送端以多播方式向所有接收端報告發(fā)送情況。

SR分組的主要內(nèi)容有:相應(yīng)的RTP流的SSRC,RTP流中最新產(chǎn)生的RTP分組的時間戳和NTP,RTP流包含的分組數(shù),RTP流包含的字節(jié)數(shù)。其封裝如下圖所示:

流媒體傳輸協(xié)議相關(guān)小結(jié)——NALU、RTP、RTSP、RTMP、SDP等

  • 版本(V):同RTP包頭域。
  • 填充(P):同RTP包頭域。
  • 接收報告計數(shù)器(RC):5比特,該SR包中的接收報告塊的數(shù)目,可以為零。
  • 包類型(PT):8比特,SR包是200。
  • 長度域(Length):16比特,其中存放的是該SR包以32比特為單位的總長度減一。
  • 同步源(SSRC):SR包發(fā)送者的同步源標識符。與對應(yīng)RTP包中的SSRC一樣。
  • NTP Timestamp(Network time protocol)SR包發(fā)送時的絕對時間值。NTP的作用是同步不同的RTP媒體流。
  • RTP Timestamp:與NTP時間戳對應(yīng),與RTP數(shù)據(jù)包中的RTP時間戳具有相同的單位和隨機初始值。
  • Sender’s packet count:從開始發(fā)送包到產(chǎn)生這個SR包這段時間里,發(fā)送者發(fā)送的RTP數(shù)據(jù)包的總數(shù). SSRC改變時,這個域清零。
  • Sender`s octet count:從開始發(fā)送包到產(chǎn)生這個SR包這段時間里,發(fā)送者發(fā)送的凈荷數(shù)據(jù)的總字節(jié)數(shù)(不包括頭部和填充)。發(fā)送者改變其SSRC時,這個域要清零。
  • 同步源n的SSRC標識符:該報告塊中包含的是從該源接收到的包的統(tǒng)計信息。
  • 丟失率(Fraction Lost):表明從上一個SR或RR包發(fā)出以來從同步源n(SSRC_n)來的RTP數(shù)據(jù)包的丟失率。
  • 累計的包丟失數(shù)目:從開始接收到SSRC_n的包到發(fā)送SR,從SSRC_n傳過來的RTP數(shù)據(jù)包的丟失總數(shù)。
  • 收到的擴展最大序列號:從SSRC_n收到的RTP數(shù)據(jù)包中最大的序列號,
  • 接收抖動(Interarrival jitter):RTP數(shù)據(jù)包接受時間的統(tǒng)計方差估計
  • 上次SR時間戳(Last SR,LSR):取最近從SSRC_n收到的SR包中的NTP時間戳的中間32比特。如果目前還沒收到SR包,則該域清零。
  • 上次SR以來的延時(Delay since last SR,DLSR):上次從SSRC_n收到SR包到發(fā)送本報告的延時。

使用RTP的會話過程并不復(fù)雜

當應(yīng)用程序建立一個RTP會話時,應(yīng)用程序?qū)⒋_定一對目的傳輸?shù)刂?。目的傳輸?shù)刂酚梢粋€網(wǎng)絡(luò)地址和一對端口組成,有兩個端口:一個給RTP包,一個給RTCP包,使得RTP/RTCP數(shù)據(jù)能夠正確發(fā)送。RTP數(shù)據(jù)發(fā)向偶數(shù)的UDP端口,而對應(yīng)的控制信號RTCP數(shù)據(jù)發(fā)向相鄰的奇數(shù)UDP端口(偶數(shù)的UDP端口+1),這樣就構(gòu)成一個UDP端口對。 RTP的發(fā)送過程如下,接收過程則相反。

1) RTP協(xié)議從上層接收流媒體信息碼流(如H.263),封裝成RTP數(shù)據(jù)包;RTCP從上層接收控制信息,封裝成RTCP控制包。

2) RTP將RTP 數(shù)據(jù)包發(fā)往UDP端口對中偶數(shù)端口;RTCP將RTCP控制包發(fā)往UDP端口對中的奇數(shù)端口。


相關(guān)協(xié)議

  • 實時流協(xié)議RTSP(Real-Time Streaming Protocol)是IETF提出的協(xié)議,對應(yīng)的RFC文檔為RFC2362。

    從總結(jié)構(gòu)圖中可以看出,RTSP是一個應(yīng)用層協(xié)議(TCP/IP網(wǎng)絡(luò)體系中)。它以C/S(Client/Server)模式工作,它是一個多媒體播放控制協(xié)議,主要用來使用戶在播放流媒體時可以像操作本地的影碟機一樣進行控制,即可以對流媒體進行暫停/繼續(xù)、后退和前進等控制。

  • 資源預(yù)定協(xié)議RSVP(Resource Reservation Protocol)是IETF提出的協(xié)議,對應(yīng)的RFC文檔為RFC2208。

    從總結(jié)構(gòu)圖中可以看出,RSVP工作在IP層之上傳輸層之下,是一個網(wǎng)絡(luò)控制協(xié)議。RSVP通過在路由器上預(yù)留一定的帶寬,能在一定程度上為流媒體的傳輸提供服務(wù)質(zhì)量。在某些試驗性的系統(tǒng)如網(wǎng)絡(luò)視頻會議工具vic中就集成了RSVP。


常見問題

怎樣重組亂序的數(shù)據(jù)包

可以根據(jù)RTP包的序列號來排序。

怎樣獲得數(shù)據(jù)包的時序

可以根據(jù)RTP包的時間戳來獲得數(shù)據(jù)包的時序。

聲音和圖像怎么同步

根據(jù)聲音流和圖像流的相對時間(即RTP包的時間戳),以及它們的絕對時間(即對應(yīng)的RTCP包中的RTCP),可以實現(xiàn)聲音和圖像的同步。

接收緩沖和播放緩沖的作用

接收緩沖用來排序亂序了的數(shù)據(jù)包;播放緩沖用來消除播放的抖動,實現(xiàn)等時播放。

參考文章

RTP協(xié)議全解析(H264碼流和PS流)_對牛亂彈琴的博客-CSDN博客_rtp協(xié)議詳解

RTP協(xié)議分析_彭令鵬的博客-CSDN博客_rtp協(xié)議

RTSP協(xié)議

RTSP概述

RTSP(Real-Time Streaming Protocol),實時流媒體協(xié)議,標準編號RFC2326,RTSP 2.0 于2016年發(fā)布為RFC 7826。

此前,IETF多媒體傳輸小組,發(fā)布了舊版的RTP,經(jīng)過更新后,標準編號為RFC3550的RTP標準正式出爐,其是一個基于TCP/UDP的傳輸層協(xié)議,為流媒體數(shù)據(jù)提供具有實時特征的端對端傳送服務(wù),應(yīng)用于主波或者單播網(wǎng)絡(luò)環(huán)境下的交互式音視頻或者流媒體系統(tǒng)中。

但是,RTP本身只用于傳輸數(shù)據(jù),而不提供任何確保及時交付或是服務(wù)質(zhì)量的保證,因此在RFC3550修訂版中,定義了RTCP(實時傳輸控制協(xié)議),以便調(diào)整、控制傳輸過程。

其在流媒體傳輸框架中的層次如下圖所示,可見,是與HTTP一樣,被劃分到應(yīng)用層協(xié)議中,但是,與HTTP不同的是,RTSP是一種有狀態(tài)的協(xié)議,其命令是需要按照順序來發(fā)送,而且客戶端和服務(wù)器雙方都可以發(fā)送request請求。

再多提一句,HTTP的默認端口為80,RTSP則為554.

流媒體傳輸協(xié)議相關(guān)小結(jié)——NALU、RTP、RTSP、RTMP、SDP等

RTSP是一個可擴展的框架,其功能如下:

  • 支持控制、按需交付實時音視頻數(shù)據(jù)
  • 控制多個數(shù)據(jù)傳輸會話
  • 提供選擇傳輸方式的能力,可以選擇UDP、組播UDP、TCP
  • 提供了一種基于RTP的選擇傳輸機制

RTSP包含了兩種,一是Normal RSTP,數(shù)據(jù)通過RTP傳輸,是較為常見的種類;另一種則是Real RTSP,數(shù)據(jù)通過RDT傳輸,專屬于RealNetworks公司的RTSP服務(wù)器軟件。

RTSP只負責(zé)傳輸媒體控制信息,并不負責(zé)數(shù)據(jù)傳輸,而是使用RTP和RTCP完成數(shù)據(jù)傳輸與數(shù)據(jù)監(jiān)控。下圖可以很好的表示RTSP在協(xié)議層中的位置以及簡要的工作機制。

RTSP傳輸?shù)囊话闶荰S、MP4格式的流,其傳輸一般需要2~3個通道,命令和數(shù)據(jù)通道分離。使用RTSP協(xié)議傳輸流媒體數(shù)據(jù)需要有專門的媒體播放器和媒體服務(wù)器,也就是需要支持RTSP協(xié)議的客戶端和服務(wù)器??梢钥吹?,RSTP本身是基于TCP進行控制信息的傳輸?shù)摹F鋾捊换チ鞒倘缦聢D所示:

如果客戶端要播放RTSP媒體流,就需要知道媒體源的URL,RTSP的URL格式一般如下:

rtsp://host[:port]/[abs_path]/content_name

  • host: 有效的域名或IP地址;

  • port: 端口號,缺省為554,若為缺省可不填寫,否則必須寫明。

例如,一個完整的RTSP URL可寫為:

rtsp://192.168.1.67:554/test.xxx

又如目前市面上常用的海康網(wǎng)絡(luò)攝像頭的RTSP地址格式為:

rtsp://[username]:[password]@[ip]:[port]/[codec]/[channel]/[subtype]/av_stream

示例:

rtsp://admin:12345@192.168.1.67:554/h264/ch1/main/av_stream

rtsp://admin:12345@192.168.1.67/mpeg4/ch1/sub/av_stream

RTSP消息交互過程詳解

RTSP是一種基于文本的協(xié)議,用CRLF(回車換行)作為每一行的結(jié)束符,其好處是,在使用過程中可以方便地增加自定義參數(shù),也方便抓包分析。從消息傳送方向上來分,RTSP的報文有兩類:請求報文和響應(yīng)報文。請求報文是指從客戶端向服務(wù)器發(fā)送的請求(也有少量從服務(wù)器向客戶端發(fā)送的請求),響應(yīng)報文是指從服務(wù)器到客戶端的回應(yīng)。

RTSP請求報文的常用方法與作用:

流媒體傳輸協(xié)議相關(guān)小結(jié)——NALU、RTP、RTSP、RTMP、SDP等

一次基本的RTSP交互過程如下(C表示客戶端,S表示服務(wù)端):

流媒體傳輸協(xié)議相關(guān)小結(jié)——NALU、RTP、RTSP、RTMP、SDP等

首先客戶端會通過發(fā)送OPTION消息至服務(wù)器端,請求服務(wù)器可以使用的方法,服務(wù)器給予回應(yīng)。對應(yīng)上圖中的①。

客戶端連接到流媒體服務(wù)器并發(fā)送一個RTSP描述請求(DESCRIBE request),服務(wù)器通過一個SDP(Session Description Protocol)描述來進行反饋(DESCRIBE response),反饋信息包括流數(shù)量、媒體類型等信息。對應(yīng)上圖中的②。

客戶端分析該SDP描述,并為會話中的每一個流發(fā)送一個RTSP連接建立請求(SETUP request),該命令會告訴服務(wù)器用于接收媒體數(shù)據(jù)的端口,服務(wù)器響應(yīng)該請求(SETUP response)并建立連接之后,就開始傳送媒體流(RTP包)到客戶端。對應(yīng)上圖中的③。

在播放過程中客戶端還可以向服務(wù)器發(fā)送請求來控制快進、快退和暫停等。最后,客戶端可發(fā)送一個終止請求(TEARDOWN request)來結(jié)束流媒體會話。參見下圖,為RTSP客戶端的狀態(tài)機:

  • 初始態(tài)(Init): SETUP請求已經(jīng)發(fā)出,等待回復(fù),尚未創(chuàng)建會話
  • 就緒態(tài)(Ready): 收到SETUP回復(fù),或在播放態(tài)收到pause回復(fù),會話已創(chuàng)建好,可以進行數(shù)據(jù)傳輸。
  • 播放態(tài)(Playing):收到PLAY回復(fù),媒體數(shù)據(jù)開始傳輸,客戶端播放媒體。
  • 記錄態(tài)(Recording): 收到RECORD回復(fù),客戶端開始錄制數(shù)據(jù)。

值得一提的是,服務(wù)器端是通過調(diào)用多次accept()函數(shù)來完成各狀態(tài)的接收,這么做也正常,如果對方在還沒有正常傳輸數(shù)據(jù)的時候就斷開連接,服務(wù)器端也因為長久沒有收到SYN就斷開連接,也是可以理解的。

RTSP報文重要字段介紹

在正式開始介紹報文信息詳解之前,先對信息中比較重要的字段進行介紹??蛻舳巳绻欢螘r間內(nèi)(默認是60s)沒有任何響應(yīng),那么rtsp服務(wù)器就會關(guān)閉該會話,所以客戶端需要發(fā)送心跳包給服務(wù)器。

  • RTSP層面上,定期向server發(fā)無效的控制信息(要帶有session id的cmd,比如,空消息體的get_parameter命令,)
  • RTP層面上,定期向server發(fā)送rtp包,包內(nèi)容隨意。
Accept:

用于指定客戶端可以接受的媒體描述信息類型。比如:

Accept: application/rtsl, application/sdp;level=2
Bandwidth:

用于描述客戶端可用的帶寬值。

CSeq:

指定了RTSP請求回應(yīng)對的序列號,在每個請求或回應(yīng)中都必須包括這個頭字段。對每個包含一個給定序列號的請求消息,都會有一個相同序列號的回應(yīng)消息。

Rang:

用于指定一個時間范圍,可以使用SMPTE、NTP或clock時間單元。

Session:

Session頭字段標識了一個RTSP會話。Session ID 是由服務(wù)器在SETUP的回應(yīng)中選擇的,客戶端一當?shù)玫絊ession ID后,在以后的對Session 的操作請求消息中都要包含Session ID.

Transport:

Transport頭字段包含客戶端可以接受的轉(zhuǎn)輸選項列表,包括傳輸協(xié)議,地址端口,TTL等。服務(wù)器端也通過這個頭字段返回實際選擇的具體選項。如:

Transport: RTP/AVP;multicast;ttl=127;mode="PLAY",

RTP/AVP;unicast;client_port=3456-3457;mode="PLAY"

unicast表示單播

RTSP報文信息詳解

首先,我們介紹一下RTSP通信過程中,請求與回應(yīng)的模板如下所示:

RTSP請求:

[方法] [URI] [RTSP版本]<CR LF>
       [消息頭]<CR LF><CR LF>
       [消息體]<CR LF>

RTSP回應(yīng):

[RTSP版本] [狀態(tài)碼] [狀態(tài)碼解釋]<CR LF>
           [消息頭]<CR LF><CR LF>
           [消息體]<CR LF>

下面我們通過具體的消息實例,來進一步了解一下RTSP的工作過程:

OPTIONS

OPTIONS請求是客戶端向服務(wù)器詢問可用的方法,請求和回復(fù)實例如下:

C->S:  OPTIONS rtsp://example.com/media.mp4 RTSP/1.0
       CSeq: 1
       Require: implicit-play
       Proxy-Require: gzipped-messages
 
S->C:  RTSP/1.0 200 OK
       CSeq: 1
       Public: OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE
DESCRIBE

客戶端向服務(wù)器請求媒體資源描述,Accept字段中指定客戶端可以接受的媒體信息類型。服務(wù)器端通過SDP(Session Description Protocol)格式回應(yīng)客戶端的請求(后文我們也會介紹一下SDP協(xié)議)。資源描述中會列出所請求媒體的媒體流及其相關(guān)信息,典型情況下,音頻和視頻分別作為一個媒體流傳輸。實例如下:

C->S: DESCRIBE rtsp://example.com/media.mp4 RTSP/1.0
      CSeq: 2
	  Accept:application/sdp, application/rtsl,application/mheg
 
S->C: RTSP/1.0 200 OK
      CSeq: 2
      Content-Base: rtsp://example.com/media.mp4
      Content-Type: application/sdp
      Content-Length: 460
 
      m=video 0 RTP/AVP 96
      a=control:streamid=0
      a=range:npt=0-7.741000
      a=length:npt=7.741000
      a=rtpmap:96 MP4V-ES/5544
      a=mimetype:string;"video/MP4V-ES"
      a=AvgBitRate:integer;304018
      a=StreamName:string;"hinted video track"
      
      m=audio 0 RTP/AVP 97
      a=control:streamid=1
      a=range:npt=0-7.712000
      a=length:npt=7.712000
      a=rtpmap:97 mpeg4-generic/32000/2
      a=mimetype:string;"audio/mpeg4-generic"
      a=AvgBitRate:integer;65790
      a=StreamName:string;"hinted audio track"

媒體初始化是任何基于RTSP系統(tǒng)的必要條件,RTSP規(guī)范并沒有規(guī)定它必須通過DESCRIBE方法完成。RTSP客戶端可以通過以下方法來接收媒體描述信息:

a) 通過DESCRIBE方法;

b) 其它一些協(xié)議(HTTP,email附件,等);

c) 通過命令行或標準輸入設(shè)備

SETUP

SETUP請求確定了具體的媒體流如何傳輸,該請求必須在PLAY請求之前發(fā)送。SETUP請求包含媒體流的URL和客戶端用于接收RTP數(shù)據(jù)(audio or video)的端口以及接收RTCP數(shù)據(jù)(meta information)的端口。服務(wù)器端的回復(fù)通常包含客戶端請求參數(shù)的確認,并會補充缺失的部分,比如服務(wù)器選擇的發(fā)送端口。每一個媒體流在發(fā)送PLAY請求之前,都要首先通過SETUP請求來進行相應(yīng)的配置。

C->S: SETUP rtsp://example.com/media.mp4/streamid=0 RTSP/1.0
      CSeq: 3
      Transport: RTP/AVP;unicast;client_port=8000-8001
 
S->C: RTSP/1.0 200 OK
      CSeq: 3
      Transport: RTP/AVP;unicast;client_port=8000-8001;server_port=9000-9001;ssrc=1234ABCD
      Session: 12345678

重要的是,服務(wù)器端還會將該傳輸會話的ID帶給客戶端,也就是Session ID,之后客戶端的請求都需要帶這個唯一標識碼。另外,如果發(fā)現(xiàn)setup的client端口已經(jīng)被強占的話,可以不用關(guān)閉會話,只需要再次調(diào)用setup來重新配置端口,不過要帶上當前的Session ID。

PLAY

客戶端通過PLAY請求來播放一個或全部媒體流,PLAY請求可以發(fā)送一次或多次,發(fā)送一次時,URL為包含所有媒體流的地址,發(fā)送多次時,每一次請求攜帶的URL只包含一個相應(yīng)的媒體流。

C->S: PLAY rtsp://example.com/media.mp4 RTSP/1.0
      CSeq: 4
      Range: npt=5-20 //(表示播放第5-20秒的內(nèi)容
      Session: 12345678
 
S->C: RTSP/1.0 200 OK
      CSeq: 4
      Session: 12345678
      RTP-Info: url=rtsp://example.com/media.mp4/streamid=0;seq=9810092;rtptime=3450012

Range可能包含一個時間參數(shù),單位是秒,相當于seek操作,該參數(shù)以UTC格式指定了播放開始的時間。如果在這個指定時間后收到消息,那么播放立即開始。時間參數(shù)可能用來幫助同步從不同數(shù)據(jù)源獲取的數(shù)據(jù)流。不含Range的PLAY請求也是合法的。它從媒體流開頭開始播放,直到媒體流被暫停。如果媒體流通過PAUSE暫停,媒體流傳輸將在暫停點(the pause point)重新開始。

如果媒體流正在播放,那么這樣一個PLAY請求將不起更多的作用,只是客戶端可以用此來測試服務(wù)器是否存活。

如果要實現(xiàn)快進/快退功能,也是通過PLAY命令向服務(wù)器請求,快進 / 快退倍速通過SCALE字段提供,如下:

C->S  PLAY rtsp://video.foocorp.com:554/streams/example.rm RTSP/1.0
CSeq: 4 
Session: 12345678
SCALE: 4    // 設(shè)置快進/快退倍速
User-Agent: VLC media player (LIVE555 Streaming Media v2005.11.10)    

S->C  RTSP/1.0 200 OK
CSeq: 4
Session: 12345678
SCALE: 4
PAUSE

PAUSE請求會暫停一個或所有媒體流,后續(xù)可通過PLAY請求恢復(fù)播放。PAUSE請求中攜帶所請求媒體流的URL。若參數(shù)range存在,則指明在何處暫停,稱這個時間為暫停點,若該參數(shù)不存在,則暫停立即生效,且暫停時長不確定。

如果請求URL中指定了具體的媒體流,那么只有該媒體流的播放和Record被暫停(halt)。比如,指定暫停音頻,播放將會無聲。如果請求URL指定了一組流,那么在該組中的所有流的傳輸將被暫停。

C->S: PAUSE rtsp://example.com/media.mp4 RTSP/1.0
      CSeq: 5
      Session: 12345678
 
S->C: RTSP/1.0 200 OK
      CSeq: 5
      Session: 12345678
TEARDOWN

結(jié)束會話請求,該請求會停止所有媒體流,并釋放服務(wù)器上的相關(guān)會話數(shù)據(jù)。

C->S: TEARDOWN rtsp://example.com/media.mp4 RTSP/1.0
      CSeq: 8
      Session: 12345678
 
S->C: RTSP/1.0 200 OK
      CSeq: 8

這里的Cseq = 8,相當于中間還有兩次PLAY或是其他操作。

GET_PARAMETER

檢索指定URI數(shù)據(jù)中的參數(shù)值。不攜帶消息體的GET_PARAMETER可用來測試服務(wù)器端或客戶端是否可通(類似ping的功能)。

S->C: GET_PARAMETER rtsp://example.com/media.mp4 RTSP/1.0
      CSeq: 9
      Content-Type: text/parameters
      Session: 12345678
      Content-Length: 15
 
      packets_received
      jitter
 
C->S: RTSP/1.0 200 OK
      CSeq: 9
      Content-Length: 46
      Content-Type: text/parameters
 
      packets_received: 10
      jitter: 0.3838
SET_PARAMETER

用于設(shè)置指定媒體流的參數(shù)。

每條請求都應(yīng)當只包含一個參數(shù)以允許客戶端在設(shè)置失敗的時候確認失敗原因。如果請求中包含多個參數(shù),服務(wù)器必須在所有參數(shù)設(shè)置成功的情況下生效,否則返回參數(shù)錯誤的key(如下例子)。
服務(wù)器應(yīng)當允許同一參數(shù)多次設(shè)置同一值,但是可以拒絕設(shè)置為不同的值,由服務(wù)器根據(jù)時機情況而定。需要注意的是,對于媒體流參數(shù)(如端口等)不可通過該方法設(shè)置,必須通過SETUP請求來設(shè)置。
以下為設(shè)置失敗的例子,服務(wù)器返回"Invalid Parameter"

C->S: SET_PARAMETER rtsp://example.com/media.mp4 RTSP/1.0
      CSeq: 10
      Content-length: 20
      Content-type: text/parameters
 
      barparam: barstuff	// 格式<key>:<value>
 
S->C: RTSP/1.0 451 Invalid Parameter
      CSeq: 10
      Content-length: 10
      Content-type: text/parameters
 
      barparam	// 返回參數(shù)錯誤的鍵
REDIRECT

重定向請求,用于服務(wù)器通知客戶端新的服務(wù)地址,響應(yīng)報文中必須包含Location頭,以指明新的服務(wù)器URL,客戶端需要向這個新地址重新發(fā)起請求。重定向請求中可能包含Range參數(shù),指明重定向生效的時間。

客戶端若需向新服務(wù)地址發(fā)起請求,必須先TEARDOWN當前會話,再向指定的新主機SETUP一個新的會話。

S->C: REDIRECT rtsp://example.com/media.mp4 RTSP/1.0
      CSeq: 11
      Location: rtsp://bigserver.com:8001
      Range: clock=19960213T143205Z-
ANNOUNCE

ANNOUNCE請求有兩個用途:

(1)C->S:客戶端向服務(wù)器端發(fā)布URL指定的媒體信息描述,如EOF終止符;

(2) S->C:實時更新對話描述。若媒體表示中新增了一個媒體流,例如在直播過程中,則整個媒體表示的description都要被重新發(fā)送,而不是只發(fā)送新增部分。

C->S: ANNOUNCE rtsp://example.com/media.mp4 RTSP/1.0
      CSeq: 7
      Date: 23 Jan 1997 15:35:06 GMT
      Session: 12345678
      Content-Type: application/sdp
      Content-Length: 332
 
      v=0
      o=mhandley 2890844526 2890845468 IN IP4 126.16.64.4
      s=SDP Seminar
      i=A Seminar on the session description protocol
      u=http://www.cs.ucl.ac.uk/staff/M.Handley/sdp.03.ps
      e=mjh@isi.edu (Mark Handley)
      c=IN IP4 224.2.17.12/127
      t=2873397496 2873404696
      a=recvonly
      m=audio 3456 RTP/AVP 0
      m=video 2232 RTP/AVP 31
 
S->C: RTSP/1.0 200 OK
      CSeq: 7
RECORD

請求錄制指定范圍的媒體數(shù)據(jù),請求中可指定錄制的起止時間戳,UTC格式,包含開始錄制點和結(jié)束錄制點;若未指定時間范圍,則使用presentation description中的開始和結(jié)束時間,這種情況下,如果會話已開始,則立即啟動錄制操作。

服務(wù)器決定將錄制數(shù)據(jù)保存在請求URI還是其他URI。
如果是保存在其他URI,則server返回201并包含描述請求狀態(tài)和錄制資源位置信息。

C->S: RECORD rtsp://example.com/media.mp4 RTSP/1.0
      CSeq: 6
      Session: 12345678
 
S->C: RTSP/1.0 200 OK
      CSeq: 6
      Session: 12345678

以上就是RTSP中常用的命令及其實例介紹。

RTP包傳輸方式

RTP包的傳輸方式在SETUP中指定,分為兩種:

  • Over UDP傳輸,默認傳輸方式,SETUP帶的參數(shù)為RTP/AVP/UDP或者RTP/AVP,如下:

    C->S: SETUP rtsp://example.com/foo/bar/baz.rm RTSP/1.0
          CSeq: 302
          Transport: RTP/AVP;unicast;client_port=4588-4589
    S->C: RTSP/1.0 200 OK
          CSeq: 302
          Date: 23 Jan 1997 15:35:06 GMT
          Session: 47112344
          Transport: RTP/AVP;unicast; client_port=4588-4589;server_port=6256-6257
    

    可以看到通過UDP傳輸,RTP接收端口是4588,對應(yīng)發(fā)送端口為6256;RTCP交互端口為4589,對應(yīng)端口為6257.
    這樣的話,對于ts stream,需要創(chuàng)建3個socket(rtsp, ts rtp, ts rtcp);
    而對于fMP4,需要創(chuàng)建5個socket(rtsp, audio rtp, audio rtcp, video rtp, video rtcp)。
    連接示意圖:

    流媒體傳輸協(xié)議相關(guān)小結(jié)——NALU、RTP、RTSP、RTMP、SDP等

  • Over TCP傳輸,SETUP帶的參數(shù)為RTP/AVP/TCP,如下:

    C->S: SETUP rtsp://foo.com/bar.file RTSP/1.0
          CSeq: 2
          Transport: RTP/AVP/TCP;interleaved=0-1
    
    S->C: RTSP/1.0 200 OK
          CSeq: 2
          Date: 05 Jun 1997 18:57:18 GMT
          Transport: RTP/AVP/TCP;interleaved=0-1
    

    通過TCP傳輸?shù)脑挘琑TSP命令、RTP包和RTCP包是在同一個TCP連接上傳輸?shù)模疽鈭D如下:

    為了區(qū)分RTP包和RTCP包,新增了一層RTSP Interleaved Frame:

RTSP傳輸報文示例

下文過程是通過PC對??禂z像頭視頻流的拉取和播放,并使用Wireshark抓取的信息流,可以更加直觀的了解到整個協(xié)議的工作流程:

OPTIONS rtsp://10.3.8.202:554 RTSP/1.0
CSeq: 2
User-Agent: LibVLC/2.2.8 (LIVE555 Streaming Media v2016.02.22)
 
RTSP/1.0 200 OK
CSeq: 2
Public: OPTIONS, DESCRIBE, PLAY, PAUSE, SETUP, TEARDOWN, SET_PARAMETER, GET_PARAMETER
Date:  Mon, Jan 29 2018 16:56:47 GMT
 
DESCRIBE rtsp://10.3.8.202:554 RTSP/1.0
CSeq: 3
User-Agent: LibVLC/2.2.8 (LIVE555 Streaming Media v2016.02.22)
Accept: application/sdp
 
RTSP/1.0 401 Unauthorized
CSeq: 3
WWW-Authenticate: Digest realm="IP Camera(10789)", nonce="6b9a455aec675b8db81a9ceb802e4eb8", stale="FALSE"
Date:  Mon, Jan 29 2018 16:56:47 GMT
 
DESCRIBE rtsp://10.3.8.202:554 RTSP/1.0
CSeq: 4
Authorization: Digest username="admin", realm="IP Camera(10789)", nonce="6b9a455aec675b8db81a9ceb802e4eb8", uri="rtsp://10.3.8.202:554", response="3fc4b15d7a923fc36f32897e3cee69aa"
User-Agent: LibVLC/2.2.8 (LIVE555 Streaming Media v2016.02.22)
Accept: application/sdp
 
RTSP/1.0 200 OK
CSeq: 4
Content-Type: application/sdp
Content-Base: rtsp://10.3.8.202:554/
Content-Length: 551
 
v=0
o=- 1517245007527432 1517245007527432 IN IP4 10.3.8.202
s=Media Presentation
e=NONE
b=AS:5050
t=0 0
a=control:rtsp://10.3.8.202:554/
m=video 0 RTP/AVP 96
c=IN IP4 0.0.0.0
b=AS:5000
a=recvonly
a=x-dimensions:2048,1536
a=control:rtsp://10.3.8.202:554/trackID=1
a=rtpmap:96 H264/90000
a=fmtp:96 profile-level-id=420029; packetization-mode=1; sprop-parameter-sets=Z00AMp2oCAAwabgICAoAAAMAAgAAAwBlCA==,aO48gA==
a=Media_header:MEDIAINFO=494D4B48010200000400000100000000000000000000000000000000000000000000000000000000;
a=appversion:1.0
 
SETUP rtsp://10.3.8.202:554/trackID=1 RTSP/1.0
CSeq: 5
Authorization: Digest username="admin", realm="IP Camera(10789)", nonce="6b9a455aec675b8db81a9ceb802e4eb8", uri="rtsp://10.3.8.202:554/", response="ddfbf3e268ae954979407369a104a620"
User-Agent: LibVLC/2.2.8 (LIVE555 Streaming Media v2016.02.22)
Transport: RTP/AVP;unicast;client_port=57844-57845
 
RTSP/1.0 200 OK
CSeq: 5
Session:       1273222592;timeout=60
Transport: RTP/AVP;unicast;client_port=57844-57845;server_port=8218-8219;ssrc=5181c73a;mode="play"
Date:  Mon, Jan 29 2018 16:56:47 GMT
 
PLAY rtsp://10.3.8.202:554/ RTSP/1.0
CSeq: 6
Authorization: Digest username="admin", realm="IP Camera(10789)", nonce="6b9a455aec675b8db81a9ceb802e4eb8", uri="rtsp://10.3.8.202:554/", response="b5abf0b230de4b49d6c6d42569f88e91"
User-Agent: LibVLC/2.2.8 (LIVE555 Streaming Media v2016.02.22)
Session: 1273222592
Range: npt=0.000-
 
RTSP/1.0 200 OK
CSeq: 6
Session:       1273222592
RTP-Info: url=rtsp://10.3.8.202:554/trackID=1;seq=65373;rtptime=3566398668
Date:  Mon, Jan 29 2018 16:56:47 GMT
 
GET_PARAMETER rtsp://10.3.8.202:554/ RTSP/1.0
CSeq: 7
Authorization: Digest username="admin", realm="IP Camera(10789)", nonce="6b9a455aec675b8db81a9ceb802e4eb8", uri="rtsp://10.3.8.202:554/", response="bb2309dcd083b25991c13e165673687b"
User-Agent: LibVLC/2.2.8 (LIVE555 Streaming Media v2016.02.22)
Session: 1273222592
 
RTSP/1.0 200 OK
CSeq: 7
Date:  Mon, Jan 29 2018 16:56:47 GMT
 
TEARDOWN rtsp://10.3.8.202:554/ RTSP/1.0
CSeq: 8
Authorization: Digest username="admin", realm="IP Camera(10789)", nonce="6b9a455aec675b8db81a9ceb802e4eb8", uri="rtsp://10.3.8.202:554/", response="e08a15c27d3daac14fd4b4bcab424a5e"
User-Agent: LibVLC/2.2.8 (LIVE555 Streaming Media v2016.02.22)
Session: 1273222592
 
RTSP/1.0 200 OK
CSeq: 8
Session:       1273222592
Date:  Mon, Jan 29 2018 16:57:03 GMT

RTSP擴展

點播的case,如何判斷End of stream?

1> 服務(wù)器主動發(fā)"ANNOUNCE" cmd告訴player碼流傳輸結(jié)束。

S->C: ANNOUNCE rtsp://172.16.12.6:5554/… RTSP/1.0
      CSeq: 4
      Session: 370384394
      x-notice: 2101 "End-of-Stream Reached" event-data=20210706T025811Z

2> 可以從DESCRIBE的SDP info中拿到duration,那么播放時長(playtime + 1)達到duration,那就認為數(shù)據(jù)傳輸結(jié)束。
3> 最新的規(guī)范(RTSP 2.0)中,服務(wù)器發(fā)送"PLAY_NOTIFY"cmd給客戶端,通知eos。

S->C: PLAY_NOTIFY rtsp://example.com/… RTSP/2.0
      Cseq:854
      Notify-Reason: end-of-stream

4>無法拿到duration,那么設(shè)置100秒超時,如果100秒內(nèi)server沒有發(fā)送播放數(shù)據(jù)給player,那就認為數(shù)據(jù)傳輸結(jié)束。

RTSP重定向的情況:

DESCRIBE請求返回303說明要進行重定向,響應(yīng)頭中會說明重定向的url。
客戶端需要對重定向url重新進行OPTION和DESCRIBE請求。

C->S:
DESCRIBE rtsp://172.16.74.210:559/2305_3a__3a_MOV00000002305106151_3a__3a_2305106151_f.mpg RTSP/1.0
CSeq: 2
User-Agent: MODPlayer

S->C:
RTSP/1.0 303 See Other
Server: Orbit2x
CSeq: 2
Location: rtsp://172.17.178.142:554/2305_3a__3a_MOV00000002305106151_3a__3a_2305106151_f.mpg
C->S:
OPTIONS rtsp://172.17.178.142:554/2305_3a__3a_MOV00000002305106151_3a__3a_2305106151_f.mpg RTSP/1.0
CSeq: 1
User-Agent: MODPlayer

S->C:
RTSP/1.0 200 OK
Server: Orbit2x
CSeq: 1
Public: OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE, GET_PARAMETER
C->S:
DESCRIBE rtsp://172.17.178.142:554/2305_3a__3a_MOV00000002305106151_3a__3a_2305106151_f.mpg RTSP/1.0
CSeq: 2
User-Agent: MODPlayer

S->C:
RTSP/1.0 200 OK
Server: Orbit2x
CSeq: 2
Public: OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE, GET_PARAMETER
Content-Type: application/sdp
Content-Length: 178
媒體數(shù)據(jù)直接基于UDP傳輸:

transport是RAW/RAW/UDP,傳輸?shù)臄?shù)據(jù)沒有封包為RTP包,直接以UDP包的形式傳輸。

SETUP rtsp://172.17.245.46:554/378289119.ts RTSP/1.0
Transport: RAW/RAW/UDP;unicast;destination=10.134.37.122;client_port=15500
User-Agent: MODPlayer
CSeq: 3

RTSP/1.0 200 OK
Server: Orbit2x
CSeq: 3
Session: 26931165;timeout=60
Transport: RAW/RAW/UDP;unicast;destination=10.134.37.122;client_port=15500;source=172.17.245.46;server_port=10000
-----------------------------------------------------------------------------------
udp的url是:udp://172.17.245.46:10000 --> 注意這是一個單播地址,不是udp組播地址(224. ~ 239.)
SDP:

SDP(Session Description Protocol)是一個用來描述多媒體會話的應(yīng)用層控制協(xié)議,是一個基于文本的協(xié)議。
用來會話建立過程中的媒體類型,以及協(xié)商編碼方案等。
SDP由許多文本行組成,文本行的格式為<類型>=<值>,<類型>是一個字母,<值>是結(jié)構(gòu)化的文本串,其格式視<類型>而定。
SDP文本行例子:

v=<version> (協(xié)議版本)
o=<username> <session id> <version> <network type> <address type> <address> (所有者/創(chuàng)建者和會話標識符)
s=<session name>    (會話名稱)
i=<session description> (會話信息)
u=<URI> (URI 描述)
e=<email address> (Email 地址)
p=<phone number> (電話號碼)
c=<network type> <address type> <connection address> (連接信息)
b=<modifier>:<bandwidth-value> (帶寬信息)
t=<start time> <stop time> (會話活動時間)
r=<repeat interval> <active duration> <list of offsets from start-time>(0或多次重復(fù)次數(shù))
z=<adjustment time> <offset> <adjustment time> <offset> ....
k=<method>
k=<method>:<encryption key> (加密密鑰)
a=<attribute> (0 個或多個會話屬性行)
a=<attribute>:<value>
m=<media> <port> <transport> <fmt list> (媒體名稱和傳輸?shù)刂?

RTSP2.0

直接搬運RTSP 2.0_aflyeaglenku的博客-CSDN博客的內(nèi)容

2016年12月,RTSP 2.0協(xié)議正式發(fā)布,rfc索引是7826

新標準還是有不少修改的,除了完善一些原協(xié)議的中的定義,主要修改就是對接口method進行了修改,比如刪除了RECORDANNOUNCE方法,新增了PLAY_NOTIFY方法。

刪除了RECORD,這表示你不能再通過這個接口來控制服務(wù)器進行數(shù)據(jù)的錄制了,可以選擇在PLAY方法中,添加一些參數(shù),來實現(xiàn)服務(wù)器對直播數(shù)據(jù)進行錄制,還可以分隔錄制。

刪除了ANNOUNCE,這意味著不能像RTMP一樣,客戶端通過向服務(wù)器推送數(shù)據(jù),來實現(xiàn)本機數(shù)據(jù)對外直播了,這可能需要其他的推送途徑來進行替代了。

至于PLAY_NOTIFY,它替代原來Server向Client端發(fā)送ANNOUNCE方法,所實現(xiàn)的功能,也就是告訴客戶端,需要根據(jù)新參數(shù)來調(diào)整直播播放狀態(tài)。

刪除通過UDP傳輸RTSP消息的形式(RTSP消息可以基于UDP傳輸嗎?);

刪除通過發(fā)PLAY消息來keep alive的方式,改用SET_PARAMETER來做;

RTSP Server也可向Client發(fā)TEARDOWN消息;

支持IPV6;

RTSP請求,支持pipelining的形式,也就是聚合Request。比如可以不等服務(wù)器返回,把SETUP和PLAY一起發(fā)送,這樣可以提高至少一個RTT的啟動時間。當然需要在消息里加上相關(guān)字段。

重寫了狀態(tài)機,完善了服務(wù)器對客戶端來說在各個狀態(tài)之間的轉(zhuǎn)換和行為;

RTSP消息內(nèi)支持URI了;

擴展了REDIRECT方法,等等。

參考文章

實時流協(xié)議 - 維基百科,自由的百科全書 (wikipedia.org)wiki yyds

網(wǎng)絡(luò)流媒體協(xié)議之——RTSP協(xié)議_牧羊女說的博客-CSDN博客_rtsp用了哪種運輸層協(xié)議

RTSP協(xié)議學(xué)習(xí)筆記_雷霄驊的博客-CSDN博客_range: npt

流媒體網(wǎng)絡(luò)協(xié)議 – RTSP_Ritchie_Lin的博客-CSDN博客_rtsp socket

網(wǎng)絡(luò)流媒體協(xié)議之——RTSP協(xié)議 - yooooooo - 博客園 (cnblogs.com)

RTSP 2.0_aflyeaglenku的博客-CSDN博客

RTMP協(xié)議

概念與摘要

RTMP協(xié)議從屬于應(yīng)用層,被設(shè)計用來在適合的傳輸協(xié)議(如TCP)上復(fù)用和打包多媒體傳輸流(如音頻、視頻和互動內(nèi)容)。RTMP提供了一套全雙工的可靠的多路復(fù)用消息服務(wù),類似于TCP協(xié)議[RFC0793],用來在一對結(jié)點之間并行傳輸帶時間戳的音頻流,視頻流,數(shù)據(jù)流。通常情況下,不同類型的消息會被分配不同的優(yōu)先級,當網(wǎng)絡(luò)傳輸能力受限時,優(yōu)先級用來控制消息在網(wǎng)絡(luò)底層的排隊順序。

RTMP塊流

實時消息傳遞協(xié)議塊流(RTMP塊流)。它作為一款高級多媒體流協(xié)議提供了流的多路復(fù)用和打包服務(wù)。RTMP塊流被設(shè)計用來傳輸實時消息協(xié)議,它可以使用任何協(xié)議來發(fā)送消息流。每個消息都包含時間戳和有效類型標識。RTMP塊流和RTMP適用于各種視聽傳播的應(yīng)用程序,包括一對一的,和一對多的視頻直播、點播服務(wù)、互動會議應(yīng)用程序。

當使用一個可靠的傳輸協(xié)議如TCP[RFC0793]時,RTMP塊流提供了一種可以在多個流中,基于時間戳的端到端交付所有消息的方法。RTMP塊流不提供任何優(yōu)先級或類似形式的控制,但可以使用更高級別的協(xié)議來提供這樣的優(yōu)先級。例如,一個視頻服務(wù)器可以根據(jù)發(fā)送的時間或確認每個消息的時間,來決定為一個網(wǎng)絡(luò)差的用戶丟棄視頻信息,以確保音頻信息的及時接收。

RTMP塊流不僅包含了自己的協(xié)議控制信息,同時也提供了一個更高級別的協(xié)議機制,用來嵌入用戶控制信息。

消息格式

消息格式可以被分割成多個塊,用來在更高的協(xié)議中支持多路復(fù)用。在創(chuàng)建塊消息格式時,應(yīng)該包含以下字段:

  • 時間戳
    消息的時間戳。這個字段占用4字節(jié)。

  • 長度
    消息的有效長度。如果消息頭不能被忽略,它應(yīng)該包括長度。這個字段在塊頭中占用3字節(jié)。

  • 類型ID
    各種類型的協(xié)議控制消息的ID。這些消息使用RTMP塊流協(xié)議和更高級別的協(xié)議來傳輸信息。所有其他類型的ID可以用在高級協(xié)議,這對于RTMP塊流來說,是不透明的。事實上,RTMP塊流中沒有要求使用這些值作為類型;所有(無協(xié)議的)消息可能是相同的類型,或者應(yīng)用程序使用這個字段來區(qū)分多個連接,而不是類型。這個字段在塊頭中占用1字節(jié)。

  • 消息流ID
    消息流ID可以是任意值。當同一個塊流被復(fù)用到不同的消息流中時,可以通過消息流ID來區(qū)分它們。另外,對于RTMP塊流而言,這是一個不透明值。該字段占用4字節(jié),使用小端序。

握手

RTMP連接從握手開始。它包含三個固定大小的塊,不像其他的協(xié)議,是由頭部大小可變的塊組成的。

客戶端(初始化連接的一端)和服務(wù)端發(fā)送同樣的三個塊。為了方便描述,客戶端發(fā)送的三個塊命名為C0,C1,C2;服務(wù)端發(fā)送的三個塊命名為S0,S1,S2。

  • 握手序列

    客戶端通過發(fā)送C0和C1消息來啟動握手過程??蛻舳吮仨毥邮盏絊1消息,然后發(fā)送C2消息??蛻舳吮仨毥邮盏絊2消息,然后發(fā)送其他數(shù)據(jù)。

    服務(wù)端必須接收到C0或者C1消息,然后發(fā)送S0和S1消息。服務(wù)端必須接收到C1消息,然后發(fā)送S2消息。服務(wù)端必須接收到C2消息,然后發(fā)送其他數(shù)據(jù)。

  • C0和S0格式

    C0和S0包由一個字節(jié)組成,下面是C0/S0包內(nèi)的字段:

    0 1 2 3 4 5 6 7
    +-+-+-+-+-+-+-+-+
    |   version     |
    +-+-+-+-+-+-+-+-+
     C0 and S0 bits
    
  • 版本(8比特)

    在C0包內(nèi),這個字段代表客戶端請求的RTMP版本號。在S0包內(nèi),這個字段代表服務(wù)端選擇的RTMP版本號。此文檔使用的版本是3。版本0-2用在早期的產(chǎn)品中,現(xiàn)在已經(jīng)被棄用;版本4-31被預(yù)留用于后續(xù)產(chǎn)品;版本32-255(為了區(qū)分RTMP協(xié)議和文本協(xié)議,文本協(xié)議通常以可打印字符開始)不允許使用。如果服務(wù)器無法識別客戶端的版本號,應(yīng)該回復(fù)版本3。客戶端可以選擇降低到版本3,或者中止握手過程。

  • C1和S1格式

    C1和S1包長度為1536字節(jié),包含以下字段:

    0                   1                   2                   3
     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                        time (4 bytes)                         |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                        zero (4 bytes)                         |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                        random bytes                           |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                         random bytes                          |
    |                            (cont)                             |
    |                             ....                              |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                             C1 and S1 bits
    
  • 時間(4字節(jié))

    本字段包含一個時間戳,客戶端應(yīng)該使用此字段來標識所有流塊的時刻。時間戳取值可以為零或其他任意值。為了同步多個塊流,客戶端可能希望多個塊流使用相同的時間戳。

  • Zero(4字節(jié))

    本字段必須為零。

  • 隨機數(shù)據(jù)(1528字節(jié))

    本字段可以包含任意數(shù)據(jù)。由于握手的雙方需要區(qū)分另一端,此字段填充的數(shù)據(jù)必須足夠隨機(以防止與其他握手端混淆)。不過沒必要為此使用加密數(shù)據(jù)或動態(tài)數(shù)據(jù)。

  • C2和S2格式

    C2和S2包長度為1536字節(jié),作為C1和S1的回應(yīng),包含以下字段:

    0                   1                   2                   3
     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                        time (4 bytes)                         |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                       time2 (4 bytes)                         |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                        random echo                            |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                         random echo                           |
    |                            (cont)                             |
    |                             ....                              |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                             C2 and S2 bits
    
  • 時間(4字節(jié))

    本字段必須包含對端發(fā)送的時間戳。

  • 時間(4字節(jié))

    本字段必須包含時間戳,取值為接收對端發(fā)送過來的握手包的時刻。

  • 隨機數(shù)據(jù)(1528字節(jié))

    本字段必須包含對端發(fā)送過來的隨機數(shù)據(jù)。握手的雙方可以使用時間1和時間2字段來估算網(wǎng)絡(luò)連接的帶寬和/或延遲,但是不一定有用。

RTMP握手

握手過程示意圖
+-------------+                           +-------------+
|    Client   |       TCP/IP Network      |    Server   |
+-------------+            |              +-------------+
      |                    |                     |
Uninitialized              |               Uninitialized
      |          C0        |                     |
      |------------------->|         C0          |
      |                    |-------------------->|
      |          C1        |                     |
      |------------------->|         S0          |
      |                    |<--------------------|
      |                    |         S1          |
 Version sent              |<--------------------|
      |          S0        |                     |
      |<-------------------|                     |
      |          S1        |                     |
      |<-------------------|                Version sent
      |                    |         C1          |
      |                    |-------------------->|
      |          C2        |                     |
      |------------------->|         S2          |
      |                    |<--------------------|
   Ack sent                |                  Ack Sent
      |          S2        |                     |
      |<-------------------|                     |
      |                    |         C2          |
      |                    |-------------------->|
 Handshake Done            |               Handshake Done
      |                    |                     |
          Pictorial Representation of Handshake
                     握手示意圖

下面是握手示意圖中提到的狀態(tài):

  • 未初始化
    協(xié)議版本號在此階段發(fā)送??蛻舳撕头?wù)器均處于未初始化狀態(tài)。客戶端發(fā)送攜帶協(xié)議版本號的C0包。如果服務(wù)器支持此版本,回復(fù)S0和S1包。如果服務(wù)器不支持此版本,使用適當?shù)膭幼骰貜?fù)。在RTMP協(xié)議中,此動作是中止連接。
    注: 在”C0和S0格式”章節(jié)中提及,如果服務(wù)器不支持客戶端的版本號,可以選擇降到版本3或中止。

  • 發(fā)送版本
    客戶端和服務(wù)器雙方在未初始化狀態(tài)后,會進入發(fā)送版本狀態(tài)。之后,客戶端等待S1包,服務(wù)器等待C1包。待接收到數(shù)據(jù)包,客戶端發(fā)送C2包,服務(wù)器發(fā)送S2包。然后,雙方都進入答復(fù)狀態(tài)。客戶端等待C2的答復(fù),服務(wù)器等待S2的答復(fù)。

  • 握手完成
    客戶端和服務(wù)器交換消息。

SDP協(xié)議

這是一個在眾多流媒體協(xié)議中會被使用到的協(xié)議,webrtc中也用到了該協(xié)議,所以單開一個篇幅來介紹。

SDP概述

SDP(SessionDescription Protocol )會話描述協(xié)議,用于描述多媒體會話,它為會話通知、會話初始和其它形式的多媒體會話初始等操作提供服務(wù)。

SDP的設(shè)計宗旨是通用性協(xié)議,所有它可以應(yīng)用于很大范圍的網(wǎng)絡(luò)環(huán)境和應(yīng)用程序,但 SDP 不支持會話內(nèi)容或媒體編碼的協(xié)商操作。

SDP信息包括:

  • 會話名稱和目標;
  • 會話活動時間;
  • 構(gòu)成會話的媒體;
  • 有關(guān)接收媒體的信息、地址等。

SDP格式

SDP 由一個會話級描述(session level description)和多個媒體級描述(media level description)組成。會話級描述的作用域是整個會話,在 SDP 中,從 v= 行開始到第一個 m= 行之前都是屬于會話級描述的內(nèi)容。媒體級描述對某個媒體流的內(nèi)容進行描述,例如某個音頻流或者某個視頻流,從某個 “m=” 行開始到下個 “m=” 行之前是屬于一個媒體級描述的內(nèi)容。如下圖所示:

流媒體傳輸協(xié)議相關(guān)小結(jié)——NALU、RTP、RTSP、RTMP、SDP等

SDP 信息是文本信息,UTF-8 編碼采用 ISO 10646 字符設(shè)置。SDP 會話描述如下(標注*符號的表示可選字段):

常規(guī)描述
  • v= (協(xié)議版本)
  • o= (所有者/創(chuàng)建者和會話標識符)
  • s= (會話名稱)
  • i=* (會話信息)
  • u=* (URI 描述)
  • e=* (Email 地址)
  • p=* (電話號碼)
  • c=* (連接信息 ― 如果包含在所有媒體中,則不需要該字段)
  • b=* (帶寬信息)
(1個或更多)時間描述:
  • z=* (時間區(qū)域調(diào)整)
  • k=* (加密密鑰)
  • a=* (0個或多個會話屬性線路)
  • t= (會話活動時間)
  • r=* (0或多次重復(fù)次數(shù))
(0個或更多)媒體描述
  • m= (媒體名稱和傳輸?shù)刂罚?/li>
  • i=* (媒體標題)
  • c=* (連接信息 — 如果包含在會話層則該字段可選)
  • b=* (帶寬信息)
  • k=* (加密密鑰)
  • a=* (0個或多個會話屬性線路)

SDP格式詳解

1 - v: protocol version
v=0

v 的含義是 SDP 協(xié)議的版本號,目前 v 都是 0。

2 - o: owner/creator and session identifier
o=<username> <session-id> <session-version> <nettype> <addrtype> <unicast-address>

會話所有者有關(guān)的參數(shù),包括用戶名、session 信息,地址信息等。

  • username: 會話發(fā)起者的名稱。如果不提供則用"-"表示,用戶名不能包含空格;
  • session-id: 主叫方的會話標識符;
  • session-version: 會話版本號,一般為 0;
  • nettype: 網(wǎng)絡(luò)類型,目前僅使用 IN 來表示 Internet 網(wǎng)絡(luò)類型;
  • addrtype: 地址類型,可以是 IPV4 和 IPV6 兩種地址類型;
  • unicast-address:會話發(fā)起者的 IP 地址。
3 - s: session name
s=<session name>

本次會話的標題或會話的名稱(Session name)。

4 - t: time the session is active
t=<start-time> <stop-time>

會話的起始時間和結(jié)束時間(Time session starts and stops),如果沒有規(guī)定這兩個時間的話,都寫為 0 即可。

5 - m: media name
m=<media> <port>/<number of ports> <proto> <fmt> ...

媒體行,描述了發(fā)送方所支持的媒體類型等信息(Media information)。

  • media:媒體類型,可以為 “audio”、“video”、“text”、“application”、“message”,表示音頻類型、視頻類型、文本類型、應(yīng)用類型、消息類型等,以后也可能擴展其他類型;

  • port/number of ports: 流傳輸端口號。表示在對應(yīng)的本地端口上發(fā)送流;

  • proto:流傳輸協(xié)議。舉例說明:

    • RTP/SAVPF 表示用 UDP 傳輸 RTP 包;

    • TCP/RTP/SAVPF 表示用 TCP 傳輸 RTP 包;

    • UDP/TLS/RTP/SAVPF 表示用 UDP 來傳輸 RTP 包,并且使用 TLS 加密;

      注:最后的 SAVPF 還有其他幾種值:AVP, SAVP, AVPF, SAVPF。

      • AVP 意為 AV profile
      • S 意為 secure
      • F 意為 feedback
    • fmt 表示媒體格式描述,它可能是一串數(shù)字,代表多個媒體,這個字段的含義與 proto 字段的類型相關(guān)。在后面,可以使用"a=rtpmap:"、“a=fmtp:”、“a=rtcp-fb” 等擴展字段來對 fmt 進行說明。

6 - c: connection data
c=<nettype> <addrtype> <connection-address>

一個會話描述必須在每個媒體層都包含“c=”字段或者在會話層包含一個“c=”字段。如果這兩個層都出現(xiàn)的話,則媒體層出現(xiàn)的“c=”會覆蓋會話層出現(xiàn)的“c=”字段的值。

  • nettype: 是一個文本字符串,目前只定義了“IN”,表示“Internet”,未來會定義其他值。
  • addrtype: 目前只定義了 IP4 和 IP6。
  • connection-address: 標志連接的地址。取決于 addrtype 字段的不同,在 connection-address 之后可能也會跟隨其他的字段。
7 - b: bandwidth
b=<bwtype>:<bandwidth>

這個字段的意思是本會話或者媒體所需占用的帶寬。 bwtype 可以為 “CT” 或者 “AS”,給出了 bandwidth(單位 kbps)數(shù)字所代表的含義:

CT:表示會話所占的所有的帶寬的大小。當用于 RTP 會話時,表示所有的 RTP 會話所占用的帶寬。

AS:這個帶寬類型是針對特定應(yīng)用的。通常,這表示某應(yīng)用所占用的最大帶寬。當用于 RTP 會話時,表示單一 RTP 會話所占用的帶寬.

可以理解為 CT 代表的是整個通話過程的帶寬,AS 代表的是某個流的帶寬。

8 - Encryption Keys (“k=”)
k=<method>

k=<method>:<encryption key>

如果在一個安全的信道上傳輸 SDP 消息,那么 SDP 之中也可以攜帶密鑰,攜帶的方式就是采用字段 “k=”。當然這種方式目前已經(jīng)不推薦了。

字段 “k=” 可以是全局的,也可以是放在某個 “m=” 中的,分別代表應(yīng)用于所有的媒體流,或者單獨應(yīng)用于某條媒體流。定義格式有如下幾種:

  • k=clear:

在這種方法中,密鑰是沒有經(jīng)過任何轉(zhuǎn)換的。除非傳輸通道是絕對安全的,否則不應(yīng)當使用這種方法。

  • k=base64:

在這種方法中,密鑰經(jīng)過 base64 的編碼。除非保證傳輸通道絕對安全,否則不應(yīng)當使用這種方法。

  • k=uri:

在這種方法中,給出一個 URI。通過這個 URI,可以獲得密鑰,訪問 URI 的過程中可能還需要認證。

  • k=prompt

在這種方法中,沒有給出密鑰。但是加上這個字段后,當用戶加入會話時會提示其輸入密鑰。這種方式目前也不推薦。

9 - a: attributes
a=<attribute>

a=<attribute>:<value>

a 表示的是屬性。a 字段是擴展 SDP 的主要方式,有會話層屬性和媒體層屬性。會話層的屬性應(yīng)用于所有的媒體流,媒體層的屬性只應(yīng)用于當前的媒體流。

屬性有兩種方式:

  • 特性屬性,a= 表示,例如:“a=recvonly”
  • 值屬性,以a=:表示,例如"a=ice-ufrag:khLS"

常用的屬性列表如下:

表列 A 表列 B 表列 C
a=rtpmap: RTP/AVP(Audio Video Profile) list m=audio 54278 RTP/SAVPF 111 103 104 0 8 106 105 13 126 a=rtpmap:111 opus/48000/2
a=fmtp: Format transport a=fmtp:111 minptime=10
a=rtcp: Explicit RTCP port (and address) a=rtcp:54278 IN IP4 180.6.6.6
a=mid: Media identification grouping a=mid:audio
a=ssrc: “ssrc” indicates a property (known as a"source-level attribute") of a media source (RTP stream) within an RTP session a=ssrc:189858836 msid:GUKF430Khp9jEQiPrdYe0LbTAALiNAKAIfl2 ea392930-e126-4573-bea3-bfba519b4d59
a=ssrc-group: Ssrc identification grouping a=ssrc-group:SIMULCAST 32040 32142 a=ssrc:32040 imageattr:96 [x=1280,y=720] a=ssrc:32142 imageattr:96 [x=640,y=480]
a=ice-ufrag: a=ice-pwd: The “ice-ufrag” and “ice-pwd” attributes convey the username fragment and password used by ICE for message integrity a=ice-ufrag:kwlYyWNjhC9JBe/V a=ice-pwd:AU/SQPupllyS0SDG/eRWDCfA
a=ice-pwd:
a=fingerprint: A certificate fingerprint is a secure one-way hash of the DER (distinguished encoding rules) form of the certificate. a=fingerprint:sha-256 D1:2C:BE:AD:C4:F6:64:5C:25:16:11:9C:AF:E7:0F:73:79:36:4E:9C:1E:15:54:39:0C:06:8B:ED:96:86:00:39
a=candidate: It contains a transport address for a candidate that can be used for connectivity checks. a=candidate:4022866446 1 udp 2113937151 192.168.0.197 36768 typ host generation 0
a=ptime: Length of time in milliseconds for each packet a=ptime:20
a=recvonly Receive only mode a=recvonly
a=sendrecv Send and receive mode a=sendrecv
a=sendonly Send only mode a=sendonly
a=type: Type of conference
a=sdplang: Language for the session description
a=framerate: Maximum video frame rate in frames per second a=framerate:15
a=inactive Inactive mode a=inactive

SDP示例

Anatomy of a WebRTC SDP - webrtcHacks

sdp會話描述由一個會話級描述和多個媒體級描述組成。會話級描述的作用域是整個會話,媒體級描述描述的是一個視頻流或者音頻流

會話級描述v=開始到第一個媒體級描述結(jié)束

媒體級描述m=開始到下一個媒體級描述結(jié)束

這個網(wǎng)站里面鼠標移動到 SDP 某一行時,就會顯示這一行 SDP 的具體含義。

以下是一個非常非常完整的SDP示例,建議使用查詢字段的方法:

// SDP 版本信息
v=0

// session 信息
// o=<username> <session-id> <session-version> <nettype> <addrtype> <unicast-address>
o=- 1873022542326151139 2 IN IP4 127.0.0.1

// s=<session name>
s=-

// t=<start-time> <stop-time>,如果不規(guī)定開始和結(jié)束時間,兩個都填 0 即可
t=0 0
// 使用 "a=" 來擴展的 bundle 屬性,其含義是 audio 和 video 使用同一個端口發(fā)送/接收,具體可以參考下方的 RFC 文檔:
// https://tools.ietf.org/html/draft-ietf-mmusic-sdp-bundle-negotiation-54
a=group:BUNDLE audio video

// 列出當前SDP中所有的 media stream id,以空格分割
// WMS 的含義是這里面的 media stream id 適配 webrtc 的 media stream
// 參考 RFC 文檔: https://datatracker.ietf.org/doc/html/draft-ietf-mmusic-msid-01#section-3
a=msid-semantic: WMS 34b34ced3c5623ea4213vx3

// m=<media> <port> <proto> <fmt> ...
// port=10 無實際含義,真正通信使用的端口由 ICE Candidate 指定
// proto=UDP/TLS/RTP/SAVP 表示用 UDP 來傳輸 RTP 包,并使用 DTLS 加密
// 后面的一串數(shù)字是 fmt,表示所有 codec 的 payloadtype
m=audio 10 UDP/TLS/RTP/SAVPF 111 114 115 116 123 124 125
// c=<nettype> <addrtype> <connection-address>
c=IN IP4 0.0.0.0
    
// a=rtcp:<port> [nettype addrtype connection-address]
a=rtcp:10 IN IP4 0.0.0.0
    
// ICE 信息,參考 RFC 文檔: https://tools.ietf.org/html/rfc5245#section-15.4
a=ice-ufrag:aZ/b
a=ice-pwd:3tFwvgPAA2PK3pPWoJjVz4FJ
a=ice-options:trickle renomination

// DTLS 信息,參考 RFC 文檔: https://tools.ietf.org/html/rfc4572#section-5
a=fingerprint:sha-256 5F:78:37:05:D7:83:46:05:F7:3F:17:35:2A:7E:81:D3:2D:26:71:87:8B:9F:57:02:53:30:E3:3E:B6:3E:49:D5

// a=setup:<role>
// role可選active/passive/actpass/holdconn,
// 分別表示端點將發(fā)起一個傳出連接、端點將接受傳入連接、
// 端點愿意接受傳入連接或啟動傳出連接、端點暫時不想建立連接
// 參考 rfc: https://tools.ietf.org/html/rfc4145#section-4
a=setup:actpass

// a=mid:<token>
// 這個 token 在 a=group 那一行中也有出現(xiàn),
// 也就是說這里描述的媒體正是需要被 bundle 的
// 參考 rfc: https://tools.ietf.org/html/rfc5888#section-6
a=mid:audio

// 以下是這個媒體支持的所有 RTP 擴展頭,
// 參考rfc: https://tools.ietf.org/html/rfc8285
// a=extmap:<value>["/"<direction>] <URI> <extensionattributes>
// value=ID
// direction 可選 sendonly/recvonly/sendrecv/inactive,默認值 sendrecv
// URI 就是這個擴展頭的 URI,通信雙方可以通過 URI 標明擴展頭的含義讓雙方都能理解
// 這里表示 ID=1 的擴展頭是 audio level 擴展頭,表示 RTP 包中會攜帶音頻包音量大小
// 參考 https://tools.ietf.org/html/rfc6464#section-4
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level

// rtp stream 信息,參考 rfc: https://tools.ietf.org/html/draft-ietf-avtext-rid-09
a=extmap:13 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id

// 流的方向,sendrecv 表示可以收也可以發(fā)
// 參考 rfc:https://tools.ietf.org/html/rfc3264
a=sendrecv

// 這一行表示 rtcp 和 rtp 復(fù)用一個端口,
// 參考 rfc:https://tools.ietf.org/html/rfc5761 
// 和 rfc:https://tools.ietf.org/html/rfc8035
a=rtcp-mux

// a=rtpmap:<payload type> <encoding name>/<clock rate> [/<encoding parameters>]
// opus codec 的 payload,
// 表明 fmt=111 就是用來傳輸 opus 數(shù)據(jù)的
// 參考 rfc: https://datatracker.ietf.org/doc/html/rfc7587
a=rtpmap:111 opus/48000/2

// a=rtcp-fb:<payload type> [...]
// 表示支持的 rtcp 反饋報文類型
// 這個反饋報文是 tcc 帶寬探測用的
// 參考 https://tools.ietf.org/html/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=rtcp-fb:111 transport-cc

// nack,表示 fmt=111 支持 nack 重傳包
a=rtcp-fb:111 nack
    
// a=fmtp 用來描述 codec 的一些特性,例如這里表示期望的 opus 最小打包時間是 10ms,并且使用 inbandfec
a=fmtp:111 minptime=10;useinbandfec=1

// 指明了音頻 RTX 包的 payloadtype
// 參考 rfc:https://tools.ietf.org/html/rfc4588#section-8.6
a=rtpmap:114 rtx/48000/2

// apt 表示 fmt=114 的 RTX 包是用來重傳 fmt=111 音頻的
a=fmtp:114 apt=111

// 指明了 rsfec 包的 payloadtype
a=rtpmap:123 rsfec/48000/2

// 指明了 red 包的 payloadtype
// 參考 https://tools.ietf.org/html/rfc2198
a=rtpmap:124 red/48000/2

// 指明了音頻 RTX 包的 payloadtype
a=rtpmap:125 rtx/48000/2

// apt 表示 fmt=125 的 RTX 包是用來重傳 fmt=124 的 red 包的
a=fmtp:125 apt=124

// ssrc-group 指明了一組 ssrc 之間的關(guān)系,F(xiàn)ID 表明后一個 ssrc 是前一個 ssrc 的 rtx
// https://tools.ietf.org/html/rfc5576#section-4.2
a=ssrc-group:FID 2952055605 1713037948

// cname 的內(nèi)容是一個 16 位 Base64 字符串,含義是傳輸級的標識符,同一個 PeerConnection 的值相同
// 參考 https://datatracker.ietf.org/doc/html/rfc8834#section-4.9
a=ssrc:2952055605 cname:vqdagKn92E0lhuXn

// 這里出現(xiàn)了兩個字符串,
// 前一個是 media stream id,后一個是 sender track id
// media stream 主要用于音視頻同步,每個 track 以 media stream id 作為 sync label 進行同步
// 參考 https://datatracker.ietf.org/doc/html/draft-ietf-mmusic-msid
a=ssrc:2952055605 msid:34b34ced3c5623ea4213vx3 34b34ced3c5623ea4213vx3a0

// media stream id
a=ssrc:2952055605 mslabel:34b34ced3c5623ea4213vx3

// sender track id
a=ssrc:2952055605 label:34b34ced3c5623ea4213vx3a0

// video media
m=video 10 UDP/TLS/RTP/SAVPF 96 97 101 102 103

c=IN IP4 0.0.0.0

a=rtcp:10 IN IP4 0.0.0.0

a=ice-ufrag:aZ/b

a=ice-pwd:3tFwvgPAA2PK3pPWoJjVz4FJ

a=ice-options:trickle renomination

a=fingerprint:sha-256 5F:78:37:05:D7:83:46:05:F7:3F:17:35:2A:7E:81:D3:2D:26:71:87:8B:9F:57:02:53:30:E3:3E:B6:3E:49:D5

a=setup:actpass

a=mid:video

// 傳輸時間偏移擴展頭
// 參考 https://datatracker.ietf.org/doc/html/rfc5450
a=extmap:2 urn:ietf:params:rtp-hdrext:toffset

// abs-send-time 擴展頭,gcc 帶寬探測用的
a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time

// 視頻朝向擴展頭
// 參考 https://datatracker.ietf.org/doc/html/rfc6184
a=extmap:4 urn:3gpp:video-orientation

// transport-cc 擴展頭,tcc 帶寬探測用的
a=extmap:5 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01

// 擴展頭的內(nèi)容是對播放延遲限制的值
a=extmap:6 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay

// 視頻內(nèi)容類型擴展頭
a=extmap:7 http://www.webrtc.org/experiments/rtp-hdrext/video-content-type

// 這個擴展頭用于傳輸每幀的時間信息
a=extmap:8 http://www.webrtc.org/experiments/rtp-hdrext/video-timing

// 視頻的色域空間擴展頭
a=extmap:12 http://www.webrtc.org/experiments/rtp-hdrext/color-space

// 傳輸視頻 SDES 信息的擴展頭
// 參考:https://datatracker.ietf.org/doc/html/draft-ietf-avtext-rid-06
a=extmap:13 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id

a=sendrecv

a=rtcp-mux

// 支持 rtcp 壓縮
// 參考 https://datatracker.ietf.org/doc/html/rfc5506#section-1
a=rtcp-rsize

// 指明 fmt=96 就是用來傳輸 H264 編碼的視頻的
a=rtpmap:96 H264/90000

// remb 反饋報文,gcc 帶寬探測用的
a=rtcp-fb:96 goog-remb

a=rtcp-fb:96 transport-cc

// FIR(完整幀內(nèi)請求)反饋報文
// 參考 https://datatracker.ietf.org/doc/html/rfc5104
a=rtcp-fb:96 ccm fir

a=rtcp-fb:96 nack

// PLI NACK 反饋報文
// 參考 https://datatracker.ietf.org/doc/html/rfc5104
a=rtcp-fb:96 nack pli

// 后面的是一些 H264 的參數(shù)
a=fmtp:96 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f

a=rtpmap:97 rtx/90000

a=fmtp:97 apt=96;packetization-mode=1

a=rtpmap:101 red/90000

a=fmtp:101 packetization-mode=1

a=rtpmap:102 rtx/90000

a=fmtp:102 apt=101;packetization-mode=1

a=rtpmap:103 rsfec/90000

a=fmtp:103 packetization-mode=1

// ssrc-group:SIM 表示后面的這些 ssrc 是同一個流的 simulcast
a=ssrc-group:SIM 2955842370 1032318052

a=ssrc-group:FID 2955842370 521905126

a=ssrc-group:FID 1032318052 1492521545

a=ssrc:2955842370 cname:vqdagKn92E0lhuXn

a=ssrc:2955842370 msid:34b34ced3c5623ea4213vx3 34b34ced3c5623ea4213vx3v0

a=ssrc:2955842370 mslabel:34b34ced3c5623ea4213vx3

a=ssrc:2955842370 label:34b34ced3c5623ea4213vx3v0

a=ssrc:1032318052 cname:vqdagKn92E0lhuXn

a=ssrc:1032318052 msid:34b34ced3c5623ea4213vx3 34b34ced3c5623ea4213vx3

a=ssrc:1032318052 mslabel:34b34ced3c5623ea4213vx3

a=ssrc:1032318052 label:34b34ced3c5623ea4213vx3v0

a=ssrc:521905126 cname:vqdagKn92E0lhuXn

a=ssrc:521905126 msid:34b34ced3c5623ea4213vx3 34b34ced3c5623ea4213vx3v0

a=ssrc:521905126 mslabel:34b34ced3c5623ea4213vx3

a=ssrc:521905126 label:34b34ced3c5623ea4213vx3v0

a=ssrc:1492521545 cname:vqdagKn92E0lhuXn

a=ssrc:1492521545 msid:34b34ced3c5623ea4213vx3 34b34ced3c5623ea4213vx3v0

a=ssrc:1492521545 mslabel:34b34ced3c5623ea4213vx3

a=ssrc:1492521545 label:34b34ced3c5623ea4213vx3v0

// 使用的 rsfec 的版本
a=rsfec-version:1

參考文獻

RTSP協(xié)議學(xué)習(xí)筆記_雷霄驊的博客-CSDN博客_range: npt

音視頻 - 玩轉(zhuǎn) WebRTC 通信:一文讀懂 SDP 協(xié)議 - 個人文章 - SegmentFault 思否

從零開始寫一個RTSP服務(wù)器(一)RTSP協(xié)議講解_JT同學(xué)的博客-CSDN博客_rtsp 服務(wù)器

低延遲協(xié)議總結(jié)

參考文章

低延遲流媒體協(xié)議SRT、WebRTC、LL-HLS、UDP、TCP、RTMP詳解 - 掘金 (juejin.cn)

弱網(wǎng)對抗相關(guān)

參考文章

音視頻學(xué)習(xí) – 弱網(wǎng)對抗技術(shù)相關(guān)實踐 - 專欄 - 聲網(wǎng) RTE 開發(fā)者社區(qū) (rtcdeveloper.cn)

弱網(wǎng)優(yōu)化_dog head的博客-CSDN博客文章來源地址http://www.zghlxwxcb.cn/news/detail-449821.html

到了這里,關(guān)于流媒體傳輸協(xié)議相關(guān)小結(jié)——NALU、RTP、RTSP、RTMP、SDP等的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • 流媒體協(xié)議之RTSP詳解

    流媒體協(xié)議之RTSP詳解

    RTSP(Real Time Streaming Protocol):實時流媒體協(xié)議,是由Real network 和 Netscape共同提出的如何有效地在IP網(wǎng)絡(luò)上傳輸流媒體數(shù)據(jù)的應(yīng)用層協(xié)議,RTSP提供一種可擴展的框架,使能夠提供能控制的,按需傳輸實時數(shù)據(jù),如音頻流、視頻流、metadata; 遵循規(guī)范IETF RFC 2326,4567,6064,其語法和操作參

    2024年02月05日
    瀏覽(24)
  • 流媒體協(xié)議RTSP初篇(一)

    流媒體協(xié)議RTSP初篇(一)

    今日天氣微涼,小雨稀稀拉拉的落下,寫寫文章開心一點。 一、前情提要之工作流程 RTSP、RTP、RTCP、SDP四個協(xié)議一般是打包使用的,各司其職完成傳輸媒體流的使命。大致流程如下: 身份卡: 老板 : RTSP 秘書 : SDP RTCP : 質(zhì)量經(jīng)理 RTP : 小工 小劇場: 老板A: 有媒體資源 老板

    2024年02月07日
    瀏覽(28)
  • Golang 流媒體音視頻網(wǎng)絡(luò)傳輸開源項目-LAL

    Golang 流媒體音視頻網(wǎng)絡(luò)傳輸開源項目-LAL

    lal是開源直播流媒體網(wǎng)絡(luò)傳輸項目,主要由三部分組成: lalserver:流媒體轉(zhuǎn)發(fā)服務(wù)器。類似于 nginx-rtmp-module 等服務(wù),但支持更多的協(xié)議,提供更豐富的功能。 demo:一些小應(yīng)用,比如推、拉流客戶端,壓測工具,流分析工具,調(diào)度示例程序等。類似于ffmpeg、ffprobe等應(yīng)用。

    2023年04月16日
    瀏覽(31)
  • 深入淺出基于HLS流媒體協(xié)議視頻加密的解決方案

    深入淺出基于HLS流媒體協(xié)議視頻加密的解決方案

    一套簡單的基于HLS流媒體協(xié)議,使用video.js + NodeJS + FFmpeg等相關(guān)技術(shù)實現(xiàn)的m3u8+ts+aes128視頻加密及播放的解決方案示例。 項目簡介 起初是為了將工作中已有的基于Flash的視頻播放器替換為不依賴Flash的HTML5視頻播放器,主要使用了現(xiàn)有的video.js開源播放器做的定制化開發(fā)。當完

    2023年04月09日
    瀏覽(25)
  • 基于Nginx+rtmp搭建支持hls協(xié)議的點播流媒體服務(wù)器(windows/Linux)

    基于Nginx+rtmp搭建支持hls協(xié)議的點播流媒體服務(wù)器(windows/Linux)

    前言:公司最近因為客戶端視頻文件過大導(dǎo)致視頻加載時間很長,讓我將視頻播放做成流媒體點播的形式,于是查閱了幾十篇相關(guān)文章以及文檔,最終將功能實現(xiàn)??赡苁谴嬖诎姹静町?,絕大部分文章介紹的教程并不能成功實施,尤其是點播功能,所以我把我工作中驗證成功

    2024年02月02日
    瀏覽(20)
  • LiveNVR監(jiān)控流媒體Onvif/RTSP功能-概覽負載統(tǒng)計展示取流中、播放中、錄像中點擊柱狀圖快速定位相關(guān)會話

    LiveNVR監(jiān)控流媒體Onvif/RTSP功能-概覽負載統(tǒng)計展示取流中、播放中、錄像中點擊柱狀圖快速定位相關(guān)會話

    實時展示取流中、播放中、錄像中等使用數(shù)目 取流中:當前拉流到平臺的實時通道數(shù)目 播放中:當前觀看直播和回放的在線人數(shù)之和 錄像中:當前正在云端錄像(服務(wù)器集中錄像)的通道數(shù)目,開啟錄像是編輯通道配置錄像保留(天) 點擊柱狀圖,可以查看對應(yīng)的會話信息, 包

    2024年04月15日
    瀏覽(29)
  • 搭建RTSP流媒體服務(wù)器(用于測試分析RTSP協(xié)議)(rtsp-simple-server+FFmpeg+vlc+wireshark)

    搭建RTSP流媒體服務(wù)器(用于測試分析RTSP協(xié)議)(rtsp-simple-server+FFmpeg+vlc+wireshark)

    本文所搭建的流媒體服務(wù)器是在虛擬機centos7中安裝rtsp-simple-server充當服務(wù)器,在windows本機中安裝FFmpeg用于推流,使用vlc播放器播放rtsp-simple-server中的視頻充當拉流,并用wireshark抓包分析RTSP協(xié)議。 在https://github.com/aler9/rtsp-simple-server/releases下載linux版本,進入文件夾解壓 tar

    2024年02月09日
    瀏覽(32)
  • 流媒體服務(wù)器(17)—— 流媒體開源服務(wù) MediaSoup 初識

    流媒體服務(wù)器(17)—— 流媒體開源服務(wù) MediaSoup 初識

    目錄 前言 正文 一、簡單介紹 二、關(guān)鍵特色 1. 超強 SFU 功能 2. Node.js 模塊 3. 客戶端 SDK 三、架構(gòu)組成 1. 關(guān)鍵實例 2. 重要模塊 四、發(fā)展現(xiàn)狀 https://liuzhen.blog.csdn.net/article/details/115603863 https://liuzhen.blog.csdn.net/article/details/115603863 最近收看了一期微軟(中國)關(guān)于云原生、大數(shù)據(jù)

    2023年04月09日
    瀏覽(22)
  • 使用Nginx搭建流媒體

    參考地址 安裝 ffmpeg 1、下載安裝ffmpeg 2、安裝依賴 3、編譯安裝 ffmpeg 4、創(chuàng)建全局鏈接 5、驗證 安裝nginx 1、下載依賴包 2、 解壓安裝nginx 3、配置啟動腳本 4、修改 nginx.conf 文件 在原有的nginx.conf 文件中 server 里面增加如下配置 5、 啟動 nginx 6、上傳視頻測試驗證 參數(shù)說明 022

    2024年02月07日
    瀏覽(49)
  • 探索:區(qū)塊鏈視頻流媒體平臺

    探索:區(qū)塊鏈視頻流媒體平臺

    如今,幾乎所有人都在關(guān)注視頻流媒體, 疫情加速了全球流媒體平臺的發(fā)展。 Netflix、Disney+和HBO Max等熱門視頻流媒體平臺受益于該行業(yè)的快速增長。但也有很多失敗的嘗試,包括Quibi和CNN+。 歸根結(jié)底,其實是有兩種類型的視頻流平臺:基于廣告的和基于訂閱的?;趶V告平

    2024年02月16日
    瀏覽(19)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包