FLV文件格式官方規範詳解

——若是要學習一個新的知識點,官方手冊多是最快的途徑。查看網上其餘人的總結也許入門更快,可是要準確,深刻,完整,仍是要看官方手冊。
 
如下內容來自對官方文檔Video File Format Specification Version 10的分析總結。過程當中藉助ffmpeg實際轉換了一個flv文件用例研究。
 
一個FLV文件,每種類型的tag都屬於一個流,也就是一個flv文件最多隻有一個音頻流,一個視頻流,不存在多個獨立的音視頻流在一個文件的狀況。(mp4好像是能夠的)
 
另外,FLV文件格式所用的是大端序。
 
注:下面的數據type中,UI表示無符號整形,後面跟的數字表示其長度是多少位。好比UI8,表示沒法整形,長度一個字節。UI24是三個字節。UB表示位域,UB5表示一個字節的5位。能夠參考c中的位域結構體。
 
FLV頭

 
Field
type
Comment
簽名
UI8
’F’(0X46)
簽名
UI8
‘L’(0X4C)
簽名
UI8
‘V’(0x56)
版本
UI8
FLV的版本。0x01表示FLV 版本是1
保留字段
UB5
前五位必須是0
是否有音頻流
UB1
音頻流是否存在標誌
保留字段
UB1
必須是0
是否有視頻流
UB1
視頻流是否存在標誌
文件頭大小
UI32
FLV版本1時填寫9,代表的是FLV頭的大小,爲後期的FLV版本擴展使用。包括這四個字節。
數據的起始位置就是從文件開頭偏移這麼多的大小。
 
 
FLV文件體

 
body部分由一個個Tag組成,每一個Tag的下面有一塊 4bytes的空間,用來記錄這個tag的長度,這個後置用於逆向讀取處理,他們的關係以下圖:
flv
注意:頭下面四個本身就是PreviousTagSize,由於前一個沒有Tag,因此,值填寫0。
 
FLV tags 結構

 
Field
type
Comment
TAG類型
UI8
 
8: audio
9: video
18: script data——這裏是一些描述信息。
all others: reserved其餘全部值未使用。
數據大小
UI24
數據區的大小,不包括包頭。包頭總大小是11個字節。
時戳
UI24
當前幀時戳,單位是毫秒。相對於FLV文件的第一個TAG時戳。第一個tag的時戳老是0。——不是時戳增量,rtmp中是時戳增量。
時戳擴展字段
UI8
若是時戳大於0xFFFFFF,將會使用這個字節。這個字節是時戳的高8位,上面的三個字節是低24位。
流ID
U24
老是0
數據區
UI8[n]
 
 
 
音頻數據

 
Field
type
Comment
音頻格式
UB4
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
8 = G.711 mu-law logarithmic PCM 9 = reserved
10 = AAC
11 = Speex
14 = MP3 8-Khz
15 = Device-specific sound
 
7, 8, 14, and 15:內部保留使用。
flv是不支持g711a的,若是要用,可能要用線性音頻。
採樣率
UB2
For AAC: always 3
0 = 5.5-kHz
1 = 11-kHz
2 = 22-kHz
3 = 44-kHz
採樣大小
UB1
0 = snd8Bit
1 = snd16Bit
聲道
UB1
0=單聲道
1=立體聲,雙聲道。AAC永遠是1
聲音數據
UI8[N]
若是是PCM線性數據,存儲的時候每一個16bit小端存儲,有符號。
若是音頻格式是AAC,則存儲的數據是AAC AUDIO DATA,不然爲線性數組。
 
 
AAC AUDIO DATA

 
視頻數據

 
 
Field
type
Comment
幀類型
UB4
 
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 keyframe (reserved for server use only)
5: video info/command frame
編碼ID
UB4
使用哪一種編碼類型:
 
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
視頻數據
UI[N]
若是是avc,則參考下面的介紹:
 
AVCVIDEOPACKET
 
AVCVIDEOPACKET

 
 
Field
type
Comment
AVC packet類型
UI8
0:AVC序列頭
1:AVC NALU單元
2:AVC序列結束。低級別avc不須要。
CTS
SI24
若是AVC packet類型是1,則爲cts偏移(見下面的解釋),爲0則爲0
數據
UI8[n]
若是AVC packet類型是0,則是解碼器配置,sps,pps。
若是是1,則是nalu單元,能夠是多個,具體格式:將下面
 
關於CTS:這是一個比較難以理解的概念,須要和pts,dts配合一塊兒理解。
首先,pts(presentation time stamps),dts(decoder timestamps),cts(CompositionTime)的概念:
pts:顯示時間,也就是接收方在顯示器顯示這幀的時間。單位爲1/90000 秒。
dts:解碼時間,也就是rtp包中傳輸的時間戳,代表解碼的順序。單位單位爲1/90000 秒。——根據後面的理解,pts就是標準中的CompositionTime
cts偏移:cts = (pts - dts) / 90 。cts的單位是毫秒。
 
pts和dts的時間不同,應該只出如今含有B幀的狀況下,也就是profile main以上。baseline是沒有這個問題的,baseline的pts和dts一直想吐,因此cts一直爲0。
 
在flv tag中的時戳就是DTS。
 
研究 一下文檔,  ISO/IEC 14496-12:2005(E)      8.15   Time to Sample Boxes,發現CompositionTime就是presentation time stamps,只是叫法不一樣。——須要再進一步確認。
 
在上圖中,cp就是pts,顯示時間。DT是解碼時間,rtp的時戳。
I1是第一個幀,B2是第二個,後面的序號就是攝像頭輸出的順序。決定了顯示的順序。
DT,是編碼的順序,特別是在有B幀的狀況,P4要在第二個解,由於B2和B3依賴於P4,可是P4的顯示要在B3以後,由於他的順序靠後。這樣就存在顯示時間CT(PTS)和解碼時間DT的差,就有了CT偏移。
 
 
P4解碼時間是10,可是顯示時間是40,
 
AVCVIDEOPACKET中data格式:
 
 
Field
type
Comment
長度
UI32
nalu單元的長度,不包括長度字段。
nalu數據
UI8[N]
NALU數據,沒有四個字節的nalu單元頭,直接從h264頭開始,好比:65 ** ** **,41 **  ** ** 
長度
UI32
nalu單元的長度,不包括長度字段。
nalu數據
UI8[N]
NALU數據,沒有四個字節的nalu單元頭,直接從h264頭開始,好比:65 ** ** **,41 **  ** ** 
...
...
...
     
 
 
Data tags

主要是onMeta信息須要關注。
 
 
 
 
AVCDecoderConfigurationRecord

AVCVIDEOPACKET的數據格式,保存控制信息。
記錄sps,pps信息。通常出如今第二個tag中,緊跟在onMeta以後。
 
一個典型的序列:
 
0000190: 0900 0033 0000 0000 0000 00 17 0000 0000  ...3............
00001a0: 0164 002a ffe1 001e 6764 002a acd9 4078  .d.*....gd.*..@x
00001b0: 0227 e5ff c389 4388 0400 0003 0028 0000  .'....C......(..
00001c0: 0978 3c60 c658 0100 0568 ebec b22c 0000  .x<`.X...h...,..
 
17:表示h264IDR data
00:表示是AVC序列頭
00 00 00 :cts爲0
//今後往下就是 AVCDecoderConfigurationRecord
01 :版本號
64 00 2a:profile level id,sps的三個字節,64表示是h264 high profile,2a表示level。
FF:NALU長度,爲3?不知道這個長度用在哪裏。
E1:表示下面緊跟SPS有一個。
//sps[N]:sps數組。
00 1e:    前面是兩個字節的sps長度,表示後面的sps的長度是1e大小。
6764 002a acd9 4078  0227 e5ff c389 4388 0400 0003 0028 0000  0978 3c60 c658:sps的數據。
//由於只有一個sps,跳過這些長度,而後就是pps的個數信息:
01 :pps個數,1
//pps[n] pps 的個數
00 05:表示pps的大小是5個字節。
68 eb ec b2 2c:pps的數據
00 00 …….這是下一個tag 的內容了
 

我 的微信公衆號數組

相關文章
相關標籤/搜索