hls协议分析
目錄
- 1、簡介
- 1.1、 綜述
- 1.2 、HLS 協議編碼格式要求
- 1.3 、HLS 協議優勢
- 1.4 、HLS 協議劣勢
- 1.5 、框架圖
- 2、m3u8文件
- 2.1 、單碼率適配流m3u8文件
- 2.2 、多碼率適配流m3u8文件
- 2.3 、Playlist file
- 2.4 、Tags
- 3、ts文件
- 3.1 、ts文件結構
- 3.2、ts文件結構部分截圖
- 3.3、ts層(ts header)
- 3.4、ts層(adaptation field)
- 3.4.1、視頻流和音頻流加 adaptation field 情況部分截圖
- 3.5、ts層(PAT)
- 3.5.1、PAT情況截圖
- 3.6、ts層(PMT)
- 3.6.1、PMT情況截圖
- 3.7、pes層
- 3.8、es層
- 3.8.1、es層 (h264視頻)
- 3.8.2、es層 (aac音頻)
1、簡介
1.1、 綜述
作為 Apple 提出的一種基于 HTTP 的協議,HLS(HTTP Live Streaming)用于解決實時音視頻流的傳
輸。尤其是在移動端,由于 iOS /H5 不支持 flash,使得 HLS 成了移動端實時視頻流傳輸的首選。HLS
經常用在直播領域,一些國內的直播云通常用 HLS 拉流(將視頻流從服務器拉到客戶端)。 HLS 值得詬
病之處就是其延遲嚴重,延遲通常在 10-30s 之間。
HLS(HTTP Live Streaming) 把整個流分成一個個小的基于 HTTP 的文件來下載,每次只下載一些。
HLS 協議由三部分組成:HTTP、M3U8、TS。這三部分中,HTTP 是傳輸協議,M3U8 是索引文件,TS
是音視頻的媒體信息。
1.2 、HLS 協議編碼格式要求
視頻的編碼格式:H264
音頻的編碼格式:AAC、MP3、AC-3
視頻的封裝格式:ts
保存 ts 索引的 m3u8 文件
1.3 、HLS 協議優勢
1、HLS 相對于 RTMP 來講使用了標準的 HTTP 協議來傳輸數據,可以避免在一些特殊的網絡環境下被屏蔽。
2、HLS 相對 RTMP 在服務器端做負載均衡要簡單得多。因為 HLS 是基于無狀態協議 HTTP 實現的,客戶端只需要按照順序使用下載存儲在服務器的普通 ts 文件進行播放就可以。而 RTMP 是一種有狀態協議,很難對視頻服務器進行平滑擴展,因為需要為每一個播放視頻流的客戶端維護狀態。
3、HLS 協議本身實現了碼率自適應,在不同帶寬情況下,設備可以自動切換到最適合自己碼率的視頻播放。
1.4 、HLS 協議劣勢
1、HLS 協議在直播的視頻延遲時間很難做到 10 s 以下延時,而 RTMP 協議的延時可以降到 1s 左右。
1.5 、框架圖
2、m3u8文件
m3u8 文件是用文件方式對媒體文件進行描述,由一些列標簽組成。
2.1 、單碼率適配流m3u8文件
#EXTM3U#EXT-X-VERSION:3#EXT-X-ALLOW-CACHE:YES#EXT-X-MEDIA-SEQUENCE:2#EXT-X-TARGETDURATION:16#EXTINF:14.357, no desclivestream-2.ts#EXTINF:15.617, no desclivestream-3.ts#EXTINF:14.358, no desclivestream-4.ts#EXTINF:15.618, no desclivestream-5.ts#EXTINF:11.130, no desclivestream-6.ts2.2 、多碼率適配流m3u8文件
#EXTM3U#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1280000http://example.com/low.m3u8#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=2560000http://example.com/mid.m3u8#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=7680000http://example.com/hi.m3u8#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=65000,CODECS="mp4a.40.5"http://example.com/audio-only.m3u8包含多種比特率的 Master Playlist。該文件是一個實際使用中的頂級 m3u8 文件,該文件中又定義了
http://example.com/low.m3u8 、 http://example.com/mid.m3u8 等 幾 個 二 級文件 。 頂 級m3u8 文件主要是做碼率適配的,二級 m3u8 才是真正的切片文件,客戶端會默認選擇碼率最高的請求,如果發現碼率達不到,會請求降低碼率的流。客戶端拿到二級 m3u8 文件后,會繼續請求里面的文件,這時就可以進行播放了。
2.3 、Playlist file
一個 m3u 的 Playlist 就是一個由多個獨立行組成的文本文件,每行由回車/換行區分。每一行可以是一個
URI、空白行或是一個 以 “#” 號開頭的字符串,并且空格只能存在于一行中不同元素間的分隔。
一個 URI 表示一個媒體段或是 “variant Playlist file”(最多支持一層嵌套,即一個 m3u8 文件中嵌套另
一個 m3u8),以 “EXT” 開頭的表示一個 “tag”,否則表示注釋,直接忽略。
2.4 、Tags
1、 #EXTM3U : 每個 m3u8 文件第一行必須是這個 tag,如上面的兩個示例。2、 #EXT-X-VERSION: m3u8文件版本號,比如#EXT-X-VERSION:3。3、 #EXTINF : 指定每個媒體段(ts)的持續時間,這個僅對其后面的 URI 有效, 每兩個媒體段 URI 間被這個 tag 分隔開其格式為: #EXTINF:<duration><title> 比如#EXTINF:14.357, no desc duration:表示持續的時間(秒),"Durations MUST be integers if the protocol version of the Playlist file is less than 3",否則可以是浮點數。4、 #EXT-X-BYTERANGE : 表示媒體段是一個媒體 URI 資源中的一段,只對其后的 media URI 有效, 格式: #EXT-X-BYTERANGE:<n>[@o] n:表示這個區間的大小 o:表示在 URI 中的 offset The EXT-X-BYTERANGE tag appeared in version 4 of the protocol5、 #EXT-X-TARGETDURATION : 指定當前視頻流中的單個切片(即 ts)文件的最大時長(秒)。 所以 #EXTINF : 中指定的時間長度必須小于或是等于這個最大值。這個 tag 在整個 Playlist 文件中只能出現1次(在嵌套的情況下, 一般有真正ts url 的 m3u8 才會出現該 tag)。格式: #EXT-XTARGETDURATION:<s> s:表示最大的秒數。6、 #EXT-X-MEDIA-SEQUENCE : 每一個 media URI 在 Playlist 中只有唯一的序號,相鄰之間序號 +1。 格式:#EXT-X-MEDIA-SEQUENCE:<number> 一個 media URI 并不是必須要包含的,如果沒有,默認為 0.7、 #EXT-X-KEY : 表示怎么對 media segments 進行解碼。其作用范圍是下次該 tag 出現前的所有media URI。 格式為: #EXT-X-KEY:<attribute-list> NONE 或者 AES-128。如果是 NONE,則 URI 以及 IV 屬性必須不存在,如果是 AES-128(Advanced Encryption Standard), 則 URI 必須存在,IV 可以不存在。對于 AES-128 的情況,keytag 和 URI 屬性共同表示了一個 key 文件,通過 URI 可以獲得這個key, 如果沒有 IV(Initialization Vector),則使用序列號作為 IV 進行編解碼,將序列號的高位賦到 16 個字節的 buffer 中, 左邊補 0;如果有 IV,則將該值當成 16 個字節的 16 進制數。8、 #EXT-X-PROGRAM-DATE-TIME : 將一個絕對時間或是日期和一個媒體段中的第一個 sample 相關 聯,只對下一個 media URI 有效, 格式: #EXT-X-PROGRAM-DATE-TIME:<YYYY-MMDDThh:mm:ssZ> 例如: #EXT-X-PROGRAM-DATE-TIME:2010-02-19T14:54:23.031+08:009、 #EXT-X-ALLOW-CACHE : 是否允許做 cache,這個可以在 Playlist 文件中任意地方出現, 并且最多只出現一次,作用效果是所有的媒體段。 格式: #EXT-X-ALLOW-CACHE:<YES|NO>10、 #EXT-X-PLAYLIST-TYPE : 提供關于 Playlist 的可變性的信息,這個對整個 Playlist 文件有效,是可選的, 格式: #EXT-X-PLAYLIST-TYPE:<EVENT|VOD> VOD,即為點播視頻,服務器不能改變 Playlist 文件,換句話說就是該視頻全部的 ts 文件已經被生成好了。 EVENT,就是實時生成 m3u8 和 ts 文件。服務器不能改變或是刪除 Playlist 文件中的任何部分, 但是可以向該文件中增加新的一行內容。它的索引文件一直處于動態變化中, 播放的時候需要不斷下載二級index文件。11、 #EXT-X-ENDLIST : 表示 m3u8 文件的結束,live m3u8 沒有該 tag。它可以在 Playlist 中任意位置出現, 但是只能出現一個,格式: #EXT-X-ENDLIST12、 #EXT-X-MEDIA : 被用來在 Playlist 中表示相同內容的不同語種/譯文的版本, 比如可以通過使用 3個這種 tag 表示 3 種不同語音的音頻, 或者用 2 個這個 tag 表示不同?度的 video。在 Playlist中, 這個標簽是獨立存在的, 其格式: #EXT-X-MEDIA:<attribute-list> 該屬性列表中包含:URI、TYPE、GROUP-ID、LANGUAGE、NAME、DEFAULT、 AUTOSELECT。URI:如果沒有,則表示這個 tag 描述的可選擇版本在主 PlayList 的 EXT-X-STREAM-INF 中存在。TYPE:AUDIO and VIDEO。GROUP-ID:具有相同 ID 的 MEDIAtag,組成一組樣式。LANGUAGE:identifies the primary language used in the rendition。NAME:The value is a quoted-string containing a human-readable description of the rendition.If the LANGUAGE attribute is present then this description SHOULD be in that language。DEFAULT:YES 或是 NO,默認是 No,如果是 YES,則客戶端會以這種選項來播放,除非用戶自己進行選擇。AUTOSELECT:YES 或是 NO,默認是 No,如果是 YES,則客戶端會根據當前播放環境來進行選擇(用戶沒有根據自己偏好進行選擇的前提下)。The EXT-X-MEDIA tag appeared in version 4 of the protocol。13、 #EXT-X-STREAM-INF : 指定一個包含多媒體信息的 media URI 作為 Playlist, 一般做 m3u8 的嵌套使用, 它只對緊跟后面的 URI 有效, 格式: #EXT-X-STREAM-INF:<attribute-list> 常用的屬性如下:BANDWIDTH:帶寬,必須有。PROGRAM-ID:該值是一個十進制整數,唯一地標識一個在 Playlist 文件范圍內的特定的描述。一個 Playlist 文件中可能包含多個有相同 ID 的此 tag。CODECS:指定流的編碼類型,不是必須的。RESOLUTION:分辨率。AUDIO:這個值必須和 AUDIO 類別的 "EXT-X-MEDIA" 標簽中 "GROUP-ID" 屬性值相匹配。VIDEO:同上。14、 #EXT-X-DISCONTINUITY : 當遇到該 tag 的時候說明以下屬性發生了變化:file format :文件格式number and type of tracks :軌道encoding parameters :編碼參數encoding sequence :編碼序號timestamp sequence :時間戳序號15、 #ZEN-TOTAL-DURATION : 表示這個 m3u8 所含 ts 的總時間長度3、ts文件
ts 文件為傳輸流文件,視頻編碼主要格式為 H264/MPEG4,音頻為 AAC/MP3。
ts 文件分為三層:
------ ts 層:Transport Stream,是在 pes 層的基礎上加入數據流的識別和傳輸必須的信息。
------ pes 層: Packet Elemental Stream,是在音視頻數據上加了時間戳等對數據幀的說明信息。
------ es 層:Elementary Stream,即音視頻數據。
3.1 、ts文件結構
PAT(Program Association Table)節目關聯表:主要的作用就是指明了 PMT 表的 PID 值。
PMT(Program Map Table)節目映射表:主要的作用就是指明了音視頻流的 PID 值。
3.2、ts文件結構部分截圖
剛開始的TS包是PAT(Program Association Table):節目關聯表。
再跟的TS包是PMT(Program Map Table):節目映射表。
然后再跟視頻、音頻的TS包。
ts 包大小固定為 188 字節,ts 層分為三個部分:ts header、adaptation field、payload。
ts header :固定 4 個字節。
adaptation field : 可能存在也可能不存在,主要作用是給不足 188 字節的數據做填充。
payload : pes 數據。
可以根據每個ts包的偏移量判斷都是188字節。
3.3、ts層(ts header)
ts 層的內容是通過 PID 值來標識的,主要內容包括:PAT 表、PMT 表、音頻流、視頻流。
解析 ts 流要先找到 PAT 表,只要找到 PAT 就可以找到 PMT,然后就可以找到音視頻流了。
PAT 表的和 PMT 表需要定期插入 ts 流,因為用戶隨時可能加入 ts 流,這個間隔比較小,
通常每隔幾個視頻幀就要加入 PAT和 PMT。
PAT 和 PMT 表是必須的,還可以加入其它表如 SDT(業務描述表)等,不過 hls 流只要有
PAT 和 PMT 就可以播放了。
3.4、ts層(adaptation field)
自適應區的長度要包含傳輸錯誤指示符標識的一個字節。pcr 是節目時鐘參考,pcr、dts、pts 都是對同
一個系統時鐘的采樣值,pcr 是遞增的,因此可以將其設置為 dts 值,音頻數據不需要 pcr。如果沒有字
段,ipad 是可以播放的,但 vlc 無法播放。打包 ts 流時 PAT 和 PMT 表是沒有 adaptation field 的,
不夠的長度直接補 0xff 即可。視頻流和音頻流都需要加 adaptation field,通常加在一個幀的第一個 ts
包和最后一個 ts 包中,中間的 ts 包不加。
adaptation field 詳解:
flag 標志位:0x10就表示有PCR,下面視頻流截圖也是這個情況,0x50是random_access_indicator標志位和PCR_flag標志位都有。
3.4.1、視頻流和音頻流加 adaptation field 情況部分截圖
1、視頻幀:
I幀:第一個TS包和最后一個TS包有adaptation field,根據ts header 最后一個字節判斷。
(第一個TS包要存PCR)
P幀:最后一個TS包有adaptation field,根據ts header 最后一個字節判斷。
2、音頻幀:
最后一個TS包有adaptation field,根據ts header 最后一個字節判斷。
3.5、ts層(PAT)
PAT(Program Association Table)節目關聯表:主要的作用就是指明了 PMT 表的 PID 值。
3.5.1、PAT情況截圖
1、下面0x01字節表示有PMT。
2、下面0XF0 01的后13b就是PMT的PID(4097)。
(注意這個PID與ts header的pid的字節序是不同的)
3.6、ts層(PMT)
PMT(Program Map Table)節目映射表:主要的作用就是指明了音視頻流的 PID 值。
3.6.1、PMT情況截圖
1、下面0xE1 00字節后13b表示PCR的PID(256)。
2、下面0X0F 字節就是stream type AAC。
3、下面0xE1 01字節后13b就是elementary_PID (257)。
4、下面0X1B 字節就是stream type H264。
5、下面0xE1 00字節后13b就是elementary_PID (256)。
3.7、pes層
pes (Packet Elemental Stream)層是在每一個視頻/音頻幀上加上了時間戳等信息,pes 包內容項很多。
pes 層格式如下:
列舉一些pes 包含的常用字段:
截圖分析:
根據0x41字節中獲取payload_unit_start_indicator 為1,表示這個TS包是有pes包頭的(00 00 01 E0 01 FB 80 80 05 21 00 7F E9 B9 )然后后面才是實際的h264數據,由于后面還有兩個payload_unit_start_indicator 為0的,表示這3個TS包合起來才是完整的一幀h264數據。
而且payload_unit_start_indicator 為0的TS包,是沒有pes包頭了,除去4個字節的ts包頭就是h264數據了。如下圖:
3.8、es層
es(Elementary Stream) 層就是音視頻數據。
3.8.1、es層 (h264視頻)
打包 h.264 數據時必須給視頻數據加上一個 nalu(Network Abstraction Layer Unit),nalu 包括
nalu header 和 nalu type,nalu header 固定為 0x00000001(幀開始)或 0x000001(幀中)。
h.264 的數據是由 slice 組成的,slice 的內容包括:視頻、sps、pps 等。nalu type 決定了后面的
h.264 數據內容。
F:1bit,forbidden_zero_bit,h.264 規定必須取 0。
NRI:2bits,nal_ref_idc,取值為 0~3,指示這個 nalu 的重要性,I 幀、sps、pps 通常取 3,P 幀
常取 2,B 幀通常取 0
Type:5bits,取值如下:
打包 es 層數據時 pes 頭和 es 數據之間要加入一個 type=9 的 nalu,關鍵幀 slice 前必須要加入
type=7 和 type=8 的 nalu,而且是緊鄰的。
如下圖所示:
3.8.2、es層 (aac音頻)
《AAC ADTS格式分析》
打包aac音頻必須加上一個adts(Audio Data Transport Stream)頭,共7Byte,adts包括
fixed_header和variable_header兩部分,各28bit。
fixed_header:
variable_header:
總結
- 上一篇: 王家大嫂剧情介绍
- 下一篇: “阴山饶苦雾”上一句是什么