FLV封装格式介绍及解析
FLV(Flash Video)是Adobe公司推出的一種流媒體格式,由于其封裝后的音視頻文件體積小、封裝簡單等特點,非常適合于互聯網上使用。目前主流的視頻網站基本都支持FLV。采用FLV格式封裝的文件后綴為.flv。
FLV封裝格式是由一個文件頭(flie header)和 文件體(file Body)組成。其中,FLV body由一對對的(Previous Tag Size字段 + tag)組成。Previous Tag Size字段 排列在Tag之前,占用4個字節。Previous Tag Size記錄了前面一個Tag的大小,用于逆向讀取處理。FLV header后的第一個Pervious Tag Size的值為0。Tag一般可以分為3種類型:腳本(幀)數據類型、音頻數據類型、視頻數據。FLV數據以大端序進行存儲,在解析時需要注意。一個標準FLV文件結構如下圖:
?
FLV文件結構
FLV文件的詳細內容結構如下圖:
FLV文件詳細內容結構
FLV header
注:在下面的數據type中,UI表示無符號整形,后面跟的數字表示其長度是多少位。比如UI8,表示無法整形,長度一個字節。UI24是三個字節,UI[8*n]表示多個字節。UB表示位域,UB5表示一個字節的5位??梢詤⒖糲中的位域結構體。
FLV頭占9個字節,用來標識文件為FLV類型,以及后續存儲的音視頻流。一個FLV文件,每種類型的tag都屬于一個流,也就是一個flv文件最多只有一個音頻流,一個視頻流,不存在多個獨立的音視頻流在一個文件的情況。FLV頭的結構如下:
| 簽名 | 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
FLV Header之后,就是FLV File Body.FLV File Body是由一連串的back-pointers + tags構成。Back-pointer表示Previous Tag Size(前一個tag的字節數據長度),占4個字節。
FLV Body結構
FLV Tag
每一個Tag也是由兩部分組成:tag header 和 tag data。Tag Header里存放的是當前tag的類型、數據區(tag data)的長度等信息。tag header一般占11個字節的內存空間。FLV tag結構如下:
| Tag類型 | UI8 | 8:audeo? 9:video? 18:Script data(腳本數據)? all Others:reserved 其他所有值未使用 |
| 數據區大小 | UI24 | 當前tag的數據區的大小,不包含包頭 |
| 時戳 | UI24 | 當前幀時戳,單位是毫秒。相對值,第一個tag的時戳總是為0 |
| 時戳擴展字段 | UI8 | 如果時戳大于0xFFFFFF,將會使用這個字節。這個字節是時戳的高8位,上面的三個字節是低24位。 |
| StreamID | UI24 | 總是為0 |
| 數據區 | UI[8*n] | 數據區數據 |
FLV Tag的類型可以是視頻、音頻和Script(腳本類型),下面分別介紹這三種Tag類型
Script Tag Data結構(腳本類型、幀類型)
該類型Tag又被稱為MetaData Tag,存放一些關于FLV視頻和音頻的元信息,比如:duration、width、height等。通常該類型Tag會作為FLV文件的第一個tag,并且只有一個,跟在File Header后。該類型Tag DaTa的結構如下所示:
?
幀類型 Tag Data結構
第一個AMF包:
第1個字節表示AMF包類型,一般總是0x02,表示字符串。第2-3個字節為UI16類型值,標識字符串的長度,一般總是0x000A(“onMetaData”長度)。后面字節為具體的字符串,一般總為“onMetaData”(6F,6E,4D,65,74,61,44,61,74,61)。
?
第二個AMF包:
第1個字節表示AMF包類型,一般總是0x08,表示數組。第2-5個字節為UI32類型值,表示數組元素的個數。后面即為各數組元素的封裝,數組元素為元素名稱和值組成的對。常見的數組元素如下表所示。
| duration | 時長 |
| width | 視頻寬度 |
| heiht | 視頻高度 |
| video data rate | 視頻碼率 |
| frame rate | 視頻幀率 |
| video codec id | 視頻編碼方式 |
| audio sample rate | 音頻采樣率 |
| audio sample size | 音頻采樣精度 |
| stereo | 是否為立體聲 |
| audio codec id | 音頻編碼方式 |
| filesize | 文件大小 |
| ... | ... |
Audio Tag Data結構(音頻類型)
音頻Tag Data區域開始的第一個字節包含了音頻數據的參數信息,從第二個字節開始為音頻流數據。結構如下:
Audio Tag Data結構
第一個字節為音頻的信息,格式如下:
| 音頻格式 | 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 flv是不支持g711a的,如果要用,可能要用線性音頻。 |
| 采樣率 | UB2 | 0 = 5.5-kHz 1 = 11-kHz 2 = 22-kHz 3 = 44-kHz 對于AAC總是3。由此可以看出FLV封裝格式并不支持48KHz的采樣率 |
| 采樣精度 | UB1 | 0 = snd8Bit 1 = snd16Bit 壓縮過的音頻都是16bit |
| 音頻聲道 | UB1 | 0 = sndMono 單聲道 1 = sndStereo 立體聲,雙聲道 對于AAC總是1 |
第二個字節開始為音頻數據。
| 音頻數據 | UI[8*n] | 如果是PCM線性數據,存儲的時候每個16bit小端存儲,有符號。 如果音頻格式是AAC,則存儲的數據是AAC AUDIO DATA,否則為線性數組。 |
video Tag Data結構(視頻類型)
視頻Tag Data開始的第一個字節包含視頻數據的參數信息,從第二個字節開始為視頻流數據。結構如下:
?
video Tag Data結構
第一個字節包含視頻信息,格式如下:
| 幀類型 | 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[8*n] | 如果是avc,則參考下面的介紹:AVC VIDEO PACKET |
AVC VIDEO PACKET
關于下面這塊內容有興趣的話可以結合h264結構來看,不感興趣的話可以直接跳過。
AVC VIDEO PACKET的結構:
| AVC packet類型 | UI8 | 0:AVC序列頭 1:AVC NALU單元 2:AVC序列結束。低級別avc不需要。 |
| CTS | UI24 | 如果AVC packet類型是1,則為cts偏移(見下面的解釋)。 如果AVC packet類型是0,則為0 |
| 數據 | UI[8*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 秒?!鶕竺娴睦斫?#xff0c;pts就是標準中的CompositionTime
cts偏移:cts = (pts - dts) / 90 。cts的單位是毫秒。
pts和dts的時間不一樣,應該只出現在含有B幀的情況下,也就是profile main以上。baseline是沒有這個問題的,baseline的pts和dts一直相同,所以cts一直為0。
AVC VIDEO PACKET中Data的結構:
| 長度 | UI32 | nalu單元的長度,不包括長度字段。 |
| nalu數據 | UI[8*n] | NALU數據,沒有四個字節的nalu單元頭,直接從h264頭開始,比如:65 ** ** **,41 ** ** ** |
| 長度 | UI32 | nalu單元的長度,不包括長度字段。 |
| nalu數據 | UI[8*n] | NALU數據,沒有四個字節的nalu單元頭,直接從h264頭開始,比如:65 ** ** **,41 ** ** ** |
| ... | ... | ... |
解析FLV
在理解了FLV結構的基礎上,就可以嘗試去解析一個FLV文件了。在閱讀代碼的過程中,遇到不懂的地方可以返回去看FLV結構,加深理解。
總結
以上是生活随笔為你收集整理的FLV封装格式介绍及解析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Flv的结构分析
- 下一篇: 32位CPU和64位CPU 区别