本文轉自:http://blog.csdn.net/yeyumin89/article/details/7932368 對其文章的格式稍作調整,並修改了部分 type error.
flv 文件的格式其實網上資料仍是很多,可是怎麼封裝成 flv 卻很少。看了很多資料,找到了一個以爲還比較靠譜的: html
http://www.cnblogs.com/chef/archive/2012/07/18/2597279.html 數組
其實 flv 仍是挺簡單的一個視頻格式,下面就來先談一談 FLV 的格式吧。 ide
FLV 是一個二進制文件,簡單來講,其是由一個文件頭(FLV header)和不少 tag 組成(FLV body)。tag 又能夠分紅三類: audio, video, script,分別表明音頻流,視頻流,腳本流,而每一個 tag 又由 tag header 和 tag data 組成。 工具
文件頭由 9 bytes 組成 學習
前3個 bytes 是文件類型,老是「FLV」,也就是(0x46 0x4C 0x56)。第4 btye 是版本號,目前通常是 0x01。第5 byte 是流的信息,倒數第一 bit 是1表示有視頻(0x01),倒數第三 bit 是1表示有音頻(0x4),有視頻又有音頻就是 0x01 | 0x04(0x05),其餘都應該是 0。最後 4 bytes 表示 FLV 頭的長度,3+1+1+4 = 9。 測試
FLV header 後面就是 FLV body,FLV body 由若干個 tag 組成。每個 tag 第一部分是 tag header,tag header 長度爲 11 bytes,可是每一個 tag header 前面有 4 bytes 記錄着上一個 tag 的長度,此待會兒再說。tag header 的第1個 byte 爲記錄着 tag 的類型,音頻(0x8),視頻(0x9),腳本(0x12);第2到4 bytes 是數據區的長度,也就是 tag data 的長度;再後面3個 bytes 是時間戳,單位是毫秒,類型爲0x12則時間戳爲0,時間戳控制着文件播放的速度,能夠根據音視頻的幀率類設置;時間戳後面一個 byte 是擴展時間戳,時間戳不夠長的時候用;最後3 bytes 是 streamID,可是總爲0,再後面就是數據區了(tag data),也便是h264的裸流,tag header 長度爲1+3+3+1+3=11。 spa
0x12 前面的 00 00 00 00 就是剛剛說的記錄着上一個 tag 的長度的4 bytes,這裏由於前面沒有tag,因此爲0。 .net
tag data 若是是音頻數據,第一個 byte 記錄 audio 信息: 設計
前 4 bits 表示音頻格式(所有格式請看官方文檔): code
·0 -- 未壓縮
·1 -- ADPCM
·2 -- MP3
·4 -- Nellymoser 16-kHz mono
·5 -- Nellymoser 8-kHz mono
·10 -- AAC
下面兩個 bits 表示 samplerate:
·0 -- 5.5KHz
·1 -- 11kHz
·2 -- 22kHz
·3 -- 44kHz
下面1 bit 表示採樣長度:
·0 -- snd8Bit
·1 -- snd16Bit
下面1 bit 表示類型:
·0 -- sndMomo
·1 -- sndStereo
以後是數據。
若是是視頻數據,第一個 byte 記錄 video 信息:
前4 bits 表示類型:
·1-- keyframe
·2 -- inner frame
·3 -- disposable inner frame (h.263 only)
·4 -- generated keyframe
後4 bits 表示解碼器 ID:
·2 -- seronson h.263
·3 -- screen video
·4 -- On2 VP6
·5 -- On2 VP6 with alpha channel
·6 -- Screen video version 2
·7 -- AVC (h.264)
以後是數據。
若是是 AAC 和 AVC 的音視頻,則在放入數據前有一個音頻和視頻的配置信息須要寫入前兩個 tag,等會再說。以前說每一個 tag 前面會有一個記錄上個 tag 長度的4個bytes(previous tag size),整個的 flv 文件實際上是:FLV header + previous tag size0 + tag1 + previous tag size1 + tag2 + previous tag size2 + ... +tagN + previous tag sizeN。第一個 previous tag size 由於前面沒有 tag,因此爲0,其餘的老是記錄着前面一個 tag 長度(tag data size + tag header size)。
若是 tag data 是腳本數據,Script Tag Data,該類型 Tag 又一般被稱爲Metadata(元數據) Tag,會放一些關於 FLV 視頻和音頻的參數信息,如duration、width、height等。一般該類型 Tag 會跟在 File Header 後面做爲第一個 Tag 出現,並且只有一個。通常來講,該 Tag Data 結構包含兩個 AMF 包。AMF(Action Message Format)是 Adobe 設計的一種通用數據封裝格式,在Adobe 的不少產品中應用,簡單來講,AMF 將不一樣類型的數據用統一的格式來描述。第一個 AMF 包封裝字符串類型數據,用來裝入一個「onMetaData」標誌,這個標誌與 Adobe 的一些 API 調用有,在此不細述。第二個 AMF 包封裝一個數組類型,這個數組中包含了音視頻信息項的名稱和值。具體說明以下,你們能夠參照圖片上的數據進行理解。
第一個 AMF 包:
第1個字節表示 AMF 包類型,通常老是0x02,表示字符串,其餘值表示意義請查閱文檔。
第2-3個字節爲 UI16 類型值,表示字符串的長度,通常老是 0x000A(「onMetaData」長度)。
後面字節爲字符串數據,通常總爲「onMetaData」。
第二個AMF包:
第1個字節表示 AMF 包類型,通常老是 0x08,表示數組。
第2-5個字節爲 UI32 類型值,表示數組元素的個數。
後面即爲各數組元素的封裝,數組元素爲元素名稱和值組成的對。表示方法以下:
第1-2個字節表示元素名稱的長度,假設爲L。
後面跟着爲長度爲L的字符串。
第L+3個字節表示元素值的類型。
後面跟着爲對應值,佔用字節數取決於值的類型。
到此flv格式的解析就差很少了,若有寫錯的地方請指出。
附上一個網友寫的flv的查看工具:
http://download.csdn.net/detail/yeyumin89/4534822
前面寫了 flv 文件的解析,有 h264 裸流的話就開始封裝吧。網上大多數都是用ffmeg 庫來作這個工做的,哎,學習資料少學不會,仍是本身動手吧。
#define NALU_TYPE_EOSEQ 10
#define NALU_TYPE_EOSTREAM 11
#define NALU_TYPE_FILL 12
這個例子是對應我第一個截圖來的,通常 h264 數據最開始的兩個 NALU 就是 SPS 和 PPS,可是我如今尚未明白爲何個人那個 h264 裸流在開始的時候會有兩個 SPS、PPS,並且以後數據還會不時的出現,可是我沒有管這個,依然只各弄了一個進去,其餘的忽略掉了,反正多餘的我都忽略了,也沒發現有什麼錯。反正首先把音視頻的配置信息封進 metadata 以後的 tag,而後就能夠封數據了。再說下元數據,flv header 以後就是它了,再以後就是音視頻配置信息,再後面就是音視頻數據,元數據前一章說了是 AMF 格式的,按格式封就好了,測試其實沒有元數據視頻也能夠正常播放,等會再簡單說下 AMF吧。
如今開始封裝 h264 數據吧,前一章提到了 flv 關於 AVC 的格式,除開元數據,其餘數據是:一個 byte 的 video 信息 + 一個 byte 的 AVCPacket type + 3 個 bytes 的無用數據(composition time,當 AVC 時無用,全是 0)+ 4 個bytes 的 NALU 單元長度 + N 個bytes 的 NALU 數據,因此包頭數據長度信息是剛纔提到的信息的總和長度。要強調下,當音視頻配置信息 tag 的時候,是沒有 4 個 bytes 的 NALU 單元長度的。
17 -- 高4 bits:1,keyframe。 低4 bits:7,表明 AVC。 後面一個 byte 0x00,AVCPacket type,表明 AVC sequence header。後 3 個 bytes 無心義,以後就是 decoder configuration record 的內容了。 圖中綠色後面 00 00 00 28 就是前面 tag 的總長度。
封包的時候要特別注意一下包頭裏面的時間戳,由於這個控制着播放的速度,若是不填,全是 0 的話,播放會至關快,通常按視頻幀率來設置。我這個 h264 流是 8 幀的,因此我每一個 tag 的時間間隔是 125ms 左右。