FLV文件結構解析

1. FLV文件格式相對於MP4,簡單很多。
   FLV Header(9Bytes) + FLV Body
   
                    a比特: 1:有音頻; 0:無音頻
                    v比特: 1:有視頻; 0:無視頻   如果音視頻都有這個字節爲0x05
   'F'|'L'|'V'|0x01|0b00000a0v| 0x00 00 00 09|
                    |                                         |
         版本字節一般爲0x01      頭長度 固定爲9
 
    FLV Body由一系列的Tag組成,每個tag的結構如下:
    { 0x00000000| tag_header0| tag_data0 } | {tag_size0| tag_header1 | tag_data1 } | {tag_size1| tag_header2 | tag_data2 } |...
       tag_size(n) = tag_data_size(n-1) + 11
       解析完一個tag後,讀取下4個字節,可以比較下看是不是前幀完全解碼完畢。

       除了可以驗證碼流外,還有什麼樣的好處促使FLV格式採用這種方式呢?不太清楚。

        0x00000000| { tag_header0| tag_data0  | tag_size0} | { tag_header1 | tag_data1 | tag_size1} |...

       Tag body也可以這樣看,編碼時按照: 數據頭 數據體 數據大小 三部分來劃分,更適合一些。下面各個tag都是按照這個結構來寫的。 


    Tag header 11Bytes

    |1Byte Tag類型                                |  只支持3類, 0x08音頻; 0x09視頻;0x12腳本
    |3Byte data_size數據區長度         |  純數據長度,不包括頭信息的15字節
    |3Byte timestamp 時間戳               |  最終的時間戳 = (timestamp_ex<< 24) | timestamp   
    |1Byte timestamp_ex擴展時間戳 |  最終時間戳的高8位。不知道爲什麼定義成這樣,可能是因爲標準擴展
    |3Byte StreamID                             |  總爲0

    Tag Data data_size字節
    |Tag數據段,長度爲data_size...  |  音視頻或者腳本數據。
    |4Byte PreviousTagSize               |  是前一個Tag數據長度,第一個Tag此數據段爲0.

2. 視頻Tag
   視頻數據的第一個字節定義視頻信息:
   高4比特定義幀格式:1 關鍵幀; 2 內部幀(非IDR幀);3可丟棄內部幀(僅對H.263有用)
   低4比特定義編碼器:2:H.263, 4: VP6, 7:H264; ...
   對於264的視頻FLV,這個字節一般爲 0x17或者0x27.
   
3. 音頻tag
   音頻數據的第一個字節定義視頻信息:
   高4比特定義音頻編碼格式:0 Linear PCM, 1: ADPCM, 2: MP3, 10:AAC ..
   第4,3兩比特定義採樣率: 0 5.5KHz, 1 11KHz, 2 22KHz, 3 44KHz. 對於AAC該值總爲3
   第2比特定義採樣大小: 0 8比特,1 16比特
   第1比特定義聲道數: 0 單聲道,1 立體聲

4. 腳本tag
   理論上不需要解析腳本Tag就可以解碼FLV文件,它只是提供了一些信息記錄。
   腳本Tag裏面的類型比較多,格式也不一樣。
   Number 類,記錄一個8字節double數據。|0x00|8字節data|.
   Boolean類,記錄一個1字節布爾型數據。|0x01|1字節data|.
   String類,記錄一個變長字符串數據。  |0x02|2字節 字符串長度 N| N字節字符串內容|.
             注意讀取完字符串後加一個'\0'字符串結束符號。因此字符串申請的時候,長度爲N+1.

   ECMA array type, 記錄一些數據對。

        |0x08| 4字節 數組長度 N|2字節 字符串長度 m1 | m1字節字符串內容|1字節 data1 type | X字節 data1 | ...

                                               |2字節 字符串長度 Nm| Nm字節字符串內容|1字節 dataN type| X字節 dataN|           
                      有N個數據對                  元素名    (長度|數據)                               元素值(類型|數據)

                一般用這個記錄一些音視頻信息,例如:

                                                                0x0008                         "duration"                   0x00      8字節double
                                                                0x0005                            "width"                     0x00      8字節double
                                                                0x0006                           "stereo"                    0x01      1字節boolean型  

   Strict array type類,記錄一組數據。
                               |0x0A|4字節 數組長度 N| 1字節 data1 type| X字節 data1 | ...
                                                                    |1字節 dataN type| X字節 dataN|
                                                 有N個數據,      每個數據的類型    數據值                                   
                     一般會用這個類記錄關鍵幀的偏移地址和對應的pts值。類型都是 Number類,即X=8字節double型
   Object type, 記錄對象數據。一般用它來做keyframes的數據存儲起始。

5.keyframes字段
   FLV沒有像mp4一樣定義stbl,FLV文件如果做快進,seek等操作會比較麻煩。

   業內通用做法是在腳本Tag裏面增加keyfrmes object類。一般定義爲:

   |00 09| 9字節 "keyframes"|00 0D| 13字節 "filepositions"|0A| 4字節關鍵字數目 N|00|8字節 關鍵幀1偏移地址| ...
                                                                                                                               |00|8字節 關鍵幀N偏移地址|

                                                 |00 05| 5字節 "times"               |0A| 4字節關鍵字數目 N|00|8字節 關鍵幀1時間| ...
                                                                                                                               |00|8字節 關鍵幀N時間|          
  有了各個關鍵幀的偏移地址和時間,做Seek操作的時候就方便的多。
 
6. 讀取8字節double型,這個牽扯浮點型的存儲結構問題,蠻羅嗦,沒看明白,但找到下面一段代碼可以實現轉換。
    uint64_t v = get_8bytes();
    if(v+v > 0xFFEULL<<52) return 0.0/0.0;
    double x = ldexp(((v&((1LL<<52)-1)) + (1LL<<52)) * (v>>63|1), (v>>52&0x7FF)-1075);

7. FLV結構裏面,數據長度有3字節和4字節限制,不會像Mp4一樣出現8字節長度。
   3字節最大表示16M數據,4字節最大是4G數據。
   一個Video Tag裏面的NALU長度不能超過16M字節。
   
發佈了40 篇原創文章 · 獲贊 7 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章