hello大家好!我叫石頭~
今天我想跟大家掰扯掰扯FLV相關的技術,如果你們之前有看過相關的文章,應該對FLV Header和FLV Body有所耳聞,先給2個圖,混混眼熟,第一張是對flv format格式的抽象解讀,第二章是對一個具體文件的格式解析。


streamAnalyzer4分析工具鏈接
接下來的文章里面我會以
真實數據和控制數據來區(qū)分人為添加的數據和音視頻真正的數據。
真實數據:就是用來真正記錄我們視頻顯示,音頻播放的數據。
描述數據:就是用來告訴取數據(解析)的程序,這個文件里面的數據,你該怎么去處理。
我們都知道,數據是以二進制(010111001...)的形式存在存儲介質的,但是這些01數據表示什么東西呢,如果我們不加一些其他的信息的話,這些01數據我們就沒辦法去解析,所以flv格式的文件就是一些人為規(guī)定的描述信息?實際的數據組成。
到這里我們就知道flv是某些人或者某些組織共同約定的一種存數據,讀數據的方式
這里我想舉個例子,嚴謹性不做過多討論。
flv文件 = flv header + flv body
老外也很喜歡用header + body來也形象的描述他們想表達的事物,那我就用人來類比flv文件。我們人是在3維的空間,所以我們可以用3維(距離我多遠,在房間的哪里,),或者二維(高度,寬度,膚色)的信息來刻畫一個具體的人在空間的具體位置,但是如果我們要是把一個人壓縮到一維的空間去存儲(類似與存儲視頻數據,因為文件數據都是在一維空間上存儲),等到時候還原到3維的時候我們該怎么還原呢,所以我們在一維的空間存一個人的肉的時候就要插入一些說明信息,比如:說明從哪里到哪里是表示手,哪里到哪里是表示手指,等等,所以我們在計算機中約定的一些協(xié)議,格式,等都是為了我們能在讀真實的數據的時候能通過控制數據來還原真實數據原有的樣子。如果不加這些描述數據,那么一個人從3維放到1維去存儲,到時取出來的時候就是一坨肉泥了.
順便說一句:出現各種協(xié)議,數據格式,等等加了描述數據的數據都是由于我們的計算機體系結構決定的,目前計算機是以存儲器為中心,所以在時間維度上,必定”取數據“不知道怎么還原數據。
2.FLV Header(flv 頭信息 9Byte)
flv header就是人為加的描述數據,但是這個“頭“應該設置多大呢,我們該表示什么信息呢,這些東西經過一堆人開n個會議,巴拉巴拉...討論N久之后終于決定設置為9Byte。

1-3:文件格式標識,必須為 46 4C 56【Signature】
(46, 4c, 56是16進制,對應的ASCII為 46 = "F", 4c = "L", 56 = "V")
4-4:版本,必須為 01【Version】
5-5:媒體標識位(flags):上面的是0x05(0000 0101)下面的順序都是從左到右
1-5bit,必須為 0;【TypeFlagsReserved】
6-6bit,音頻標識;【TypeFlagsAudio】
7-7bit,必須為 0;【TypeFlagsReserved】
8-8bit,視頻標識;【TypeFlagsVideo】
6-9:FLV頭長度,必須為 00 00 00 09【DataOffset】
3.FLV Body
FLV Body =( previousTagsize +Tag) * N,仔細看第一張圖。
Tag = Tag Header + Tag Data
3.1 previousTagsize
大?。?4字節(jié)
表示前一個tag的大小
3.2 Tag Header
TAG類型:
- 音頻類型(0x08)
- 視頻類型(0x09)
- 腳本類型(0x12)
Tips:下面的順序都是從左到右
1-1:TAG類型 下面的順序都是從左到右
1-2bit,必須為 0;【Reserved】
3-3bit,0 = 未加密,1 = 加密;【Filter】
4-8bit,8 = 音頻,9 = 視頻,12(16進制) = 腳本數據;【TagType】
2-4:數據大小,從 StreamID 到 Tag 結尾,也等于 TagLen -11【DataSize】
數據區(qū)的大小,不包括包頭。包頭總大小是11個字節(jié)。
5-7:時間戳,當前幀時戳,單位是毫秒。相對于FLV文件的第一個TAG時戳。第一個tag的時戳總是0。
——不是時戳增量,rtmp中是時戳增量。
8-8:擴展時間戳,如果時戳大于0xFFFFFF,將會使用這個字節(jié)。這個字節(jié)是時戳的高8位,
上面的三個字節(jié)是低24位。單位毫秒【TimestampExtended】
9-11:流ID【StreamID】 總是0
3.3 Tag Data
3.3.1 Tag Data: video 類型

第1個字節(jié)的前4位的數值表示幀類型。
第1個字節(jié)的后4位的數值表示。
1-1:視頻參數【VideoTagHeader】
1-4bit,幀類型【FrameType】
1 = keyframe (for AVC, a seekable frame)——h264的IDR,關鍵幀,可重入幀。
2 = inter frame (for AVC, a non-seekable frame)——h264的普通幀
3 = disposable inter frame (H.263 only)
4 = generated key frame (reserved for server use only)
5 = video info/command frame
5-8bit,編碼類型【CodecID】
1 = JPEG (currently unused)
2 = Sorenson H.263
3 = Screen video
4 = On2 VP6
5 = On2 VP6 with alpha channel
6 = Screen video version 2
7 = AVC(H.264)
[2-5]:H.264視頻類型,注,只有在 CodecID=AVC 時,才有此數據
AVCPacketType
CompositionTime (ISO 14496-12, 8.15.3)
3.3.2 Tag Data : Audio 類型

1-1:音頻頭【AudioTagHeader】
1-4bit,音頻格式【SoundFormat】
0 = Linear PCM, platform endian
1 = ADPCM
2 = MP3
3 = Linear PCM, little endian
4 = Nellymoser 16 kHz mono
5 = Nellymoser 8 kHz mono
6 = Nellymoser
7 = G.711 A-law logarithmic PCM , reserved
8 = G.711 mu-law logarithmic PCM , reserved
9 = reserved
10 = AAC (supported in Flash Player 9,0,115,0 and higher)
11 = Speex (supported in Flash Player 10 and higher)
14 = MP3 8 kHz , reserved
15 = Device-specific sound , reserved
5-6bit,采樣率【SoundRate】
0 = 5.5kHz
1 = 11kHz
2 = 22kHz
3 = 44kHz
7-7bit,位寬,0 = 8bit samples, 1= 16bit samples【SoundSize】
8-8bit,通道,0 = Mono, 1 = Stereo【SoundType】
[2-2]:AAC音頻類型,注,只有在 SoundFormat=AAC 時,才有此數據
0 = AAC sequence header
1 = AAC raw
TIPS:
注:SoundFormat
如果 SoundFormat=10 即AAC格式,官方建議使用44.1kHz采樣率和雙聲道,即SoundType=1,SoundRate=3;Flash Player會忽略這兩個參數,并從音頻比特流中解析獲得。
如果 SoundFormat=11 即Speex格式,音頻使用壓縮的16kHz采樣率的單聲道,各參數取值為SoundRate=0,SoundSize=1,SoundType=0。
3.3.3 Tag Data : Script 類型
該類型Tag又通常被稱為Metadata Tag,這個Tag存放關于FLV視頻和音頻的參數信息,如duration、width、height等。通常該類型Tag會跟在File Header后面作為第一個Tag出現,而且只有一個,并且不是必須的。
一般來說,該Tag Data結構包含兩個AMF包。
AMF(Action Message Format)是Adobe設計的一種通用數據封裝格式,在Adobe的很多產品中應用,
簡單來說,AMF將不同類型的數據用統(tǒng)一的格式來描述。
第一個AMF包封裝字符串類型數據,用來裝入一個“onMetaData”標志,這個標志與Adobe的一些API調用有,在此不細述。
第二個AMF包封裝一個數組類型,這個數組中包含了音視頻信息項的名稱和值。
具體說明如下,大家可以參照圖片上的數據進行理解
第1個字節(jié)表示AMF包類型,一般總是0x08,表示數組。
第2-5個字節(jié)為UI32類型值,表示數組元素的個數。
后面即為各數組元素的封裝,數組元素為元素名稱和值組成的對。表示方法如下:
第1-2個字節(jié)表示元素名稱的長度,假設為L。
后面跟著為長度為L的字符串。
第L+3個字節(jié)表示元素值的類型。
后面跟著為對應值,占用字節(jié)數取決于值的類型。
例如:
等等。。。
后面準備分析下mp4格式,這篇文章就這樣了,…………。