FFmpeg從入門到出家(FLV文件結構解析)

FLV(FLASH VIDEO),是一種常用的文件封裝格式,目前國內外大部分視頻分享網站都是採用的這種格式。其標準定義爲《Adobe Flash Video File Format Specification》。RTMP協議也是基於FLV視頻格式的。

FLV的文件格式在該規範中已闡述清楚,本章節不再重複描述,而是結合下面的示例具體闡述如何分析FLV文件。
FFmpeg從入門到出家(FLV文件結構解析)
圖3. FLV文件結構示例1
FFmpeg從入門到出家(FLV文件結構解析)
圖4. FLV文件結構示例2

FLV文件的分析工具有很多,這裏給大家推薦FLV Parser這個小軟件,通過它可以很容易的看到文件的組成結構。

3.1 文件結構

從整個文件上看,FLV是由Header和File Body組成,如下圖所示:
FFmpeg從入門到出家(FLV文件結構解析)
圖5. FLV文件總體結構

1.FLV Header - 長度爲9,其結構的標準定義參見標準定義見E.2 The FLV header;

  1. FLV File Body - 由一連串的PreviousTagSize + Tag構成。previousTagSize是4個字節的數據,表示前一個tag的size。標準定義參見E.3 The FLV File Body。

以圖3. FLV文件結構示例1爲例分析整體結構:

1.位置0x00000000 - 0x00000008, 共9個字節,爲FLV Header,其中:

◦0x00000000 - 0x00000002 : 0x46 0x4C 0x56分別表示字符'F''L''V',用來標識這個文件是FLV格式的。在做格式探測的時候,如果發現前3個字節爲“FLV”,就認爲它是FLV文件;

◦0x00000003 : 0x01, 表示FLV版本號;

◦0x00000004 : 0x05, 轉換爲2進制是0000 0101,其中第0位爲1,表示存在video,第2位爲1,表示存在audio;

◦0x00000005 - 0x00000008 : 0x00 0x00 0x00 0x09,轉十進制爲9,表示FLV header的長度,當FLV 版本號爲1時,該值通常爲9。

2.位置0x00000009 - ,爲FLV File Body:

◦0x00000009 - 0x0000000C : 0x00 0x00 0x00 0x00 PreviousTagSize0,轉十進制爲0,該值永遠爲0;

◦0x0000000D - 0x00000209 : 0x12 ... 0x09,共509個字節,爲Tag1的具體內容;

◦0x0000020A - 0x0000020D : 0x00 0x00 0x01 0xFD,轉十進制爲509,表示它前面的Tag,即Tag1的長度爲509;

◦0x0000020E - :按照Tag + PreviousTagSize的結構依次遞推,此處不再舉例說明。

3.2 Tag定義

FLV File Body是由一系列的PreviousTagSize + Tag組成,其中PreviousTagSize的長度爲4個字節,用來表示前一個Tag的長度;Tag裏面的數據可能是video、audio或者scripts,其定義參見E.4.1 FLV Tag,結構如下:
FFmpeg從入門到出家(FLV文件結構解析)
圖6. FLV Tag 結構

以圖3. FLV文件結構示例1爲例分析Tag結構:

1.位置0x0000020E : 0x08, 二進制爲0000 1000,第5位爲0, 表示爲非加擾文件;低5位01000爲8,說明這個Tag包含的數據類型爲Audio;

  1. 位置0x0000020F - 0x00000211 : 0x00 0x00 0x04,轉十進制爲4,說明Tag的內容長度爲4,與該tag後面的previousTagSize(15) - 11相同;

  2. 位置0x00000212 - 0x00000214 : 0x00 0x00 0x00,轉十進制爲0,說明當前Audio數據的時間戳爲0;

5.位置0x00000215 : 0x00,擴展時間戳爲0,如果擴展時間戳不爲0,那麼該Tag的時間戳應爲:Timestamp | TimestampExtended<<24;

  1. 位置0x00000216 - 0x00000218 : 0x00 0x00 0x00,StreamID,總是0;

  2. StreamID之後的數據每種格式的情況都不一樣,下面會依次進行詳細解讀。

3.3 Audio Tags

如果TAG包中的TagType等於8,表示該Tag中包含的數據類型爲Audio。StreamID之後的數據就是AudioTagHeader,其定義詳見E.4.2.1 AUDIODATA。結構如下:
FFmpeg從入門到出家(FLV文件結構解析)
圖7. FLV Audio Tag結構

需要說明的是,通常情況下AudioTagHeader之後跟着的就是AUDIODATA數據了,但有個特例,如果音頻編碼格式爲AAC,AudioTagHeader中會多出1個字節的數據AACPacketType,這個字段來表示AACAUDIODATA的類型:

•0 = AAC sequence header

•1 = AAC raw。

以圖3. FLV文件結構示例爲例分析AudioTag結構:

  1. 位置0x00000219 : 0xAF, 二進制表示爲1010 1111:

◦高4位爲1010,轉十進制爲10,表示Audio的編碼格式爲AAC;

◦第3、2位爲11,轉十進制爲3,表示該音頻的採樣率爲44KHZ;

◦第1位爲1,表示該音頻採樣點位寬爲16bits;

◦第0位爲1,表示該音頻爲立體聲。

  1. 位置0x0000021A : 0x00,十進制爲0,並且Audio的編碼格式爲AAC,說明AACAUDIODATA中存放的是AAC sequence header;

  2. 位置0x0000021B - 0x0000021C : AUDIODATA數據,即AAC sequence header。

3.3.1 AudioSpecificConfig

AAC sequence header中存放的是AudioSpecificConfig,該結構包含了更加詳細的音頻信息,《ISO-14496-3 Audio》中的1.6.2.1 章節對此作了詳細定義。

通常情況下,AAC sequence header這種Tag在FLV文件中只出現1次,並且是第一個Audio Tag,它存放了解碼AAC音頻所需要的詳細信息。

有關AudioSpecificConfig結構的代碼解析,可以參考ffmpeg/libavcodec/mpeg4audio.c中的avpriv_mpeg4audio_get_config方法。

爲什麼AudioTagHeader中定義了音頻的相關參數,我們還需要傳遞AudioSpecificConfig呢?

因爲當SoundFormat爲AAC時,SoundType須設置爲1(立體聲),SoundRate須設置爲3(44KHZ),但這並不意味着FLV文件中AAC編碼的音頻必須是44KHZ的立體聲。播放器在播放AAC音頻時,應忽略AudioTagHeader中的參數,並根據AudioSpecificConfig來配置正確的解碼參數。

3.4 Video Tag

如果TAG包中的TagType等於9,表示該Tag中包含的數據類型爲Video。StreamID之後的數據就是VideoTagHeader,其定義詳見E.4.3.1 VIDEODATA,結構如下:
FFmpeg從入門到出家(FLV文件結構解析)
圖8. FLV Video Tag結構

VideoTagHeader之後跟着的就是VIDEODATA數據了,但是和AAC音頻一樣,它也存在一個特例,就是當視頻編碼格式爲H.264的時候,VideoTagHeader會多出4個字節的信息,AVCPacketType和CompositionTime。

•AVCPacketType用來表示VIDEODATA的內容

•CompositonTime相對時間戳,如果AVCPacketType=0x01,爲相對時間戳,其它均爲0;

以圖4. FLV文件結構示例2爲例分析VideoTagHeader結構:

  1. 位置0x0000022C : 0x17, 二進制表示爲0001 0111:

◦高4位爲0001,轉十進制爲1,表示當前幀爲關鍵幀;

◦低4位爲0111,轉十進制爲7,說明當前視頻的編碼格式爲AVC。

  1. 位置0x0000022D : 0x00,十進制爲0,並且Video的編碼格式爲AVC,說明VideoTagBody中存放的是AVC sequence header;

  2. 位置0x0000022E - 0x00000230 : 轉十進制爲0,表示相對時間戳爲0;

  3. 位置0x00000231 - 0x0000021C : VIDEODATA數據,即AVC sequence header。

3.4.1 AVCDecoderConfigurationRecord

AVC sequence header中存放的是AVCDecoderConfigurationRecord,《ISO-14496-15 AVC file format》對此作了詳細定義。它存放的是AVC的編碼參數,解碼時需設置給解碼器後方可正確解碼。

通常情況下,AVC sequence header這種Tag在FLV文件中只出現1次,並且第一個Video Tag。

有關AVCDecoderConfigurationRecord結構的代碼解析,可以參考中的ff_isom_write_avcc方法。

3.4.2 CompositionTime(相對時間戳)

相對時間戳的概念需要和PTS、DTS一起理解:

DTS : Decode Time Stamp,解碼時間戳,用於告知解碼器該視頻幀的解碼時間;

PTS : Presentation Time Stamp,顯示時間戳,用於告知播放器該視頻幀的顯示時間;

CTS : Composition Time Stamp,相對時間戳,用來表示PTS與DTS的差值。

如果視頻裏各幀的編碼是按輸入順序依次進行的,則解碼和顯示時間相同,應該是一致的。但在編碼後的視頻類型中,如果存在B幀,輸入順序和編碼順序並不一致,所以才需要PTS和DTS這兩種時間戳。視頻幀的解碼一定是發生在顯示前,所以視頻幀的PTS,一定是大於等於DTS的,因此CTS=PTS-DTS。

FLV Video Tag中的TimeStamp,不是PTS,而是DTS,視頻幀的PTS需要我們通過DTS + CTS計算得到。

爲什麼Audio Tag不需要CompositionTime呢?

因爲Audio的編碼順序和輸入順序一致,即PTS=DTS,所以它沒有CompositionTime的概念。

3.5 Script Data Tags

如果TAG包中的TagType等於18,表示該Tag中包含的數據類型爲SCRIPT。

SCRIPTDATA 結構十分複雜,定義了很多格式類型,每個類型對應一種結構,詳細可參考E.4.4 Data Tags

onMetaData是SCRIPTDATA中一個非常重要的信息,其結構定義可參考E.5 onMetaData。它通常是FLV文件中的第一個Tag,用來表示當前文件的一些基本信息: 比如視音頻的編碼類型id、視頻的寬和高、文件大小、視頻長度、創建日期等。

來自:金山雲視頻雲團隊

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