HTTP-FLV協議

1、簡介

       FLV (Flash Video) 是 Adobe 公司推出的另一種視頻格式,是一種在網絡上傳輸的流媒體數據存儲容器格式。其格式相對簡單輕量,不需要很大的媒體頭部信息。整個FLV由 The FLV Header, The FLV Body 以及其它 Tag 組成。因此加載速度極快。採用 FLV 格式封裝的文件後綴爲 .flv。而HTTP-FLV 即將流媒體數據封裝成 FLV 格式,然後通過 HTTP 協議傳輸給客戶端。

       HTTP協議中有個約定:content-length字段,http的body部分的長度服務器回覆http請求的時候如果有這個字段,客戶端就接收這個長度的數據然後就認爲數據傳輸完成了,如果服務器回覆http請求中沒有這個字段,客戶端就一直接收數據,直到服務器跟客戶端的socket連接斷開。

       http-flv直播就是利用第二個原理,服務器回覆客戶端請求的時候不加content-length字段,在回覆了http內容之後,緊接着發送flv數據,客戶端就一直接收數據了。

 

2、優缺點

(1)優點

       HTTP-FLV 依靠 MIME 的特性,根據協議中的 Content-Type 來選擇相應的程序去處理相應的內容,使得流媒體可以通過 HTTP 傳輸。相較於 RTMP 協議,HTTP-FLV 能夠較好的穿透防火牆,它是基於 HTTP/80 傳輸,有效避免被防火牆攔截。除此之外,它可以通過 HTTP 302 跳轉靈活調度/負載均衡,支持使用 HTTPS 加密傳輸,也能夠兼容支持 Android,iOS 的移動端。

(2)缺點

       由於HTTP-FLV的傳輸特性,會讓流媒體資源緩存在本地客戶端,在保密性

TYPE[1byte] + body size[3byte] + timestamp [4byte] +streamID [3byte] +[body data]+[previousTagSize 4byte]

方面不夠好。因爲網絡流量較大,它也不適合做拉流協議。

 

3、FLV格式

       首先我們都知道在媒體格式裏,幾乎都以h264視頻編碼。如今httpflv直播的flv數據也都是h264&aac爲主的。flv封裝單元是以tag來表示的,一個tag可以是音頻tag或者視頻tag,或者腳本tag及其其他類型。值得注意的是flv裏面字節序是網絡字節序,

flv的格式:

flvheader+[腳本tag(metadata)]+[第一個視頻tag(h264_spspps)]+[第一個音頻tag(aac_header)]+[第二個視頻tag(h264第一個關鍵幀)]+ 後面就是音頻和視頻tag交互存在

tag的格式:

TYPE[1byte] + body size[3byte] + timestamp [4byte] +streamID [3byte] +[body data]+[previousTagSize 4byte]

這裏的timestamp是這樣存在的[ time tamp 3b,time tamp ex 1b]
h264
視頻tagbody:
這裏存儲的h264是沒有nal分割符的,在tbody裏面是這樣存儲的,

[isKeyFrame(1byte)]+0x01+[compositionTime 3byte]+[h264 size 4byte]

compositionTimeh264編碼結果dtspts之間的偏移。
aac視頻tagbody

0xaf+0x01+aac raw

(1)單位說明

(2)FLV 文件頭和文件體 (E.2, E.3)

從整個文件上看,FLV = FLV File Header + FLV File Body。

    通常,FLV 的前 13 個字節(flv header + PreviousTagSize0)完全相同,所以,程序中會單獨定義一個常量來指定。

(3)FLV Tag (E.4)

       Timestamp 和 TimestampExtended 組成了這個 TAG 包數據的 PTS 信息,PTS = Timestamp | TimestampExtended << 24。

(4)AudioTag (E.4.2)

由於 AAC 編碼的特殊性,這裏着重說明了 AAC 編碼的 Tag 格式。

       AudioTagHeader 的第一個字節,也就是接跟着 StreamID 的 1 個字節包含了音頻類型,採樣率等的基本信息。

       AudioTagHeader 之後跟着的就是 AUDIODATA 部分了。但是,這裏有個特例,如果音頻格式(SoundFormat)是 AAC,AudioTagHeader 中會多出 1 個字節的數據 AACPacketType,這個字段來表示 AACAUDIODATA 的類型:0 = AAC sequence header,1 = AAC raw。

       AudioSpecificConfig 結構描述非常複雜,在標準文檔中是用僞代碼描述的,這裏先假定要編碼的音頻格式,做一下簡化。

       音頻編碼爲:AAC-LC,音頻採樣率爲 44100。

       在 FLV 的文件中,一般情況下 AAC sequence header 這種包只出現1次,而且是第一個 audio tag,爲什麼需要這種 tag,因爲在做 FLV demux 的時候,如果是 AAC 的音頻,需要在每幀 AAC ES 流前邊添加 7 個字節 ADST 頭,ADST 是解碼器通用的格式,也就是說 AAC 的純 ES 流要打包成 ADST 格式的 AAC 文件,解碼器才能正常播放。就是在打包 ADST 的時候,需要 samplingFrequencyIndex 這個信息,samplingFrequencyIndex 最準確的信息是在 AudioSpecificConfig 中,這樣,你就完全可以把 FLV 文件中的音頻信息及數據提取出來,送給音頻解碼器正常播放了。

(5)VideoTag (E.4.3)

由於 AVC(H.264) 編碼的特殊性,這裏着重說明了 AVC(H.264) 編碼的 Tag 格式。

       VideoTagHeader 的第一個字節,也就是接跟着 StreamID 的 1 個字節包含着視頻幀類型及視頻 CodecID 等最基本信息。

       VideoTagHeader 之後跟着的就是 VIDEODATA 部分了。但是,這裏有個特例,如果視頻格式(CodecID)是 AVC,VideoTagHeader 會多出 4 個字節的信息。

       AVCDecoderConfigurationRecord 包含着是 H.264 解碼相關比較重要的 SPS 和 PPS 信息,在給 AVC 解碼器送數據流之前一定要把 SPS 和 PPS 信息送出,否則的話,解碼器不能正常解碼。而且在解碼器 stop 之後再次 start 之前,如 seek,快進快退狀態切換等,都需要重新送一遍 SPS 和 PPS 的信息。AVCDecoderConfigurationRecord 在 FLV 文件中一般情況也只出現 1 次,也就是第一個 video tag。

       AVCDecoderConfigurationRecord 長度爲 sizeof(UI8) * (11 + sps_size + pps_size)。

(6)SCRIPTDATA (E.4.4)

ScriptTagBody 內容用 AMF 編碼

       一個 SCRIPTDATAVALUE 記錄包含一個有類型的 ActionScript 值。

(7)onMetadata (E.5)

FLV metadata object 保存在 SCRIPTDATA 中, 叫 onMetaData。不同的軟件生成的 FLV 的 properties 不同。

(8)keyframes 索引信息

       官方的文檔中並沒有對 keyframes index 做描述,但是,flv 的這種結構每個 tag 又不像 TS 有同步頭,如果沒有 keyframes index 的話,需要按順序讀取每一個tag, seek 及快進快退的效果會非常差。後來在做 flv 文件合成的時候,發現網上有的 flv 文件將 keyframes 信息隱藏在 Script Tag 中。

       keyframes 幾乎是一個非官方的標準, 也就是民間標準。兩個常用的操作 metadata 的工具是 flvtool2 和 FLVMDI,都是把 keyframes 作爲一個默認的元信息項目。在 FLVMDI 的主頁上有描述:

keyframes: (Object) This object is added only if you specify the /k switch. 'keyframes' is known to FLVMDI and if /k switch is not specified, 'keyframes' object will be deleted. 'keyframes' object has 2 arrays: 'filepositions' and 'times'. Both arrays have the same number of elements, which is equal to the number of key frames in the FLV. Values in times array are in 'seconds'. Each correspond to the timestamp of the n'th key frame. Values in filepositions array are in 'bytes'. Each correspond to the fileposition of the nth key frame video tag (which starts with byte tag type 9).

       也就是說 keyframes 中包含着 2 個內容 “filepositions” 和 “times”分別指的是關鍵幀的文件位置和關鍵幀的 PTS。通過 keyframes 可以建立起自己的 Index,然後在 seek 和快進快退的操作中,快速有效地跳轉到你想要找的關鍵幀位置進行處理。

(9)FLV 分析工具

 

參考:

(1)官方文檔:Adobe Flash Video File Format Specification Version 10.1:

http://download.macromedia.com/f4v/video_file_format_spec_v10_1.pdf

(2)https://segmentfault.com/a/1190000010791731?utm_medium=hao.caibaojian.com&utm_source=hao.caibaojian.com&share_user=1030000000178452

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章