FLV(Flash Video)是如今很是流行的流媒體格式,因爲其視頻文件體積輕巧、封裝播放簡單等特色,使其很適合在網絡上進行應用,目前主流的視頻網站無一例外地使用了FLV格式。另外因爲當前瀏覽器與Flash Player緊密的結合,使得網頁播放FLV視頻垂手可得,也是FLV流行的緣由之一。html
FLV是流媒體封裝格式,咱們能夠將其數據看爲二進制字節流。整體上看,FLV包括文件頭(File Header)和文件體(File Body)兩部分,其中文件體由一系列的Tag及Tag Size對組成。 git
用到資源文件:github
先來一張圖,這是《科比退役演講》下載)的一個FLV視頻。我使用的是UltraEdit的二進制查看工具。 數組
頭部分由一下幾部分組成 Signature(3 Byte)+Version(1 Byte)+Flags(1 Bypte)+DataOffset(4 Byte)瀏覽器
FLV的body部分是一系列的back-pointers+tag構成的bash
tag type+tag data size+Timestamp+TimestampExtended+stream id+ tag data 複製代碼
圖上第一個tag:markdown
圖中紅色部分是我標出"("與")"先後的的兩個back-pointers,都是4個字節。而括號中間就是第一個TAG。那是怎麼計算的呢?咱們就以這個作個示例。網絡
前面已經提到tag分3種。咱們一個個看ide
腳本Tag通常只有一個,是flv的第一個Tag,用於存放flv的信息,好比duration、audiodatarate、creator、width等。 首先介紹下腳本的數據類型。全部數據都是以數據類型+(數據長度)+數據的格式出現的,數據類型佔1byte,數據長度看數據類型是否存在,後面纔是數據。工具
通常來講,該Tag Data結構包含兩個AMF包。AMF(Action Message Format)是Adobe設計的一種通用數據封裝格式,在Adobe的不少產品中應用,簡單來講,AMF將不一樣類型的數據用統一的格式來描述。第一個AMF包封裝字符串類型數據,用來裝入一個「onMetaData」標誌,這個標誌與Adobe的一些API調用有,在此不細述。第二個AMF包封裝一個數組類型(srs返回爲object類型),這個數組中包含了音視頻信息項的名稱和值。具體說明以下
值 | 類型 | 說明 |
---|---|---|
0 | Number type | 8 Bypte Double |
1 | Boolean type | 1 Bypte bool |
2 | String type | 後面2個字節爲長度 |
3 | Object type | |
4 | MovieClip type | |
5 | Null type | |
6 | Undefined type | |
7 | Reference type | |
8 | ECMA array type | 數組,相似Map |
10 | Strict array type | |
11 | Date type | |
12 | Long string type | 後面4個字節爲長度 |
表示數組,相似Map。後面4個字節爲數組的個數。而後是鍵值對,第一個爲鍵,2個字節爲長度。後面跟具體的內容。接着3個字節表示值的類型,而後根據類型判斷長度。 上圖咱們能夠判斷,總共有13個鍵值對。 第一個長度爲8個字節是duration。值類型是0x004073,第一個字節是00,因此是double,8個字節。 第二個長度5個字節是width。值也是double類型,8個字節。 依次解析下去...
stream-id以後:
值 | 類型 |
---|---|
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 |
值 | 類型 |
---|---|
0 | 5.5-kHz |
1 | 11-kHz |
2 | 22-kHz |
3 | 44-kHz |
值 | 類型 |
---|---|
0 | snd8Bit |
1 | snd16Bit |
值 | 類型 |
---|---|
0 | sndMono |
1 | sndStereo |
因爲kobe視頻音頻編碼是pcm,查找視頻tag太難,使用<<東風破>> mv視頻
咱們看到數據部分: 視頻信息+數據 視頻信息,1個字節。
StreamId以後的數據就表示是VideoTagHeader,若是是avc,VideoTagHeader會多出4個字節的信息就是AVCPacketType和CompositionTime
值 | 類型 |
---|---|
1 | keyframe (for AVC, a seekable frame) 關鍵幀 |
2 | inter frame (for AVC, a non-seekable frame) |
3 | disposable inter frame (H.263 only) |
4 | generated keyframe (reserved for server use only) |
5 | video info/command frame |
值 | 類型 |
---|---|
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 |
特殊狀況 視頻的格式(CodecID)是AVC(H.264)的話,VideoTagHeader會多出4個字節的信息,AVCPacketType 和CompositionTime。
值 | 類型 |
---|---|
0 | AVCDecoderConfigurationRecord(AVC sequence header) |
1 | AVC NALU |
2 | AVC end of sequence (lower level NALU sequence ender is not required or supported) |
AVCDecoderConfigurationRecord.包含着是H.264解碼相關比較重要的sps和pps信息,再給AVC解碼器送數據流以前必定要把sps和pps信息送出,不然的話解碼器不能正常解碼。並且在解碼器stop以後再次start以前,如seek、快進快退狀態切換等,都須要從新送一遍sps和pps的信息.AVCDecoderConfigurationRecord在FLV文件中通常狀況也是出現1次,也就是第一個video tag.
條件 | 值 |
---|---|
AVCPacketType ==1 | Composition time offset |
AVCPacketType !=1 | 0 |
再看到第二個video tag
咱們看到 AVCPacketType =1,然後面三個字節爲000043。這是一個視頻幀數據。 解析到的數據徹底符合上面的理論。sps pps 前面咱們提到第一個video 通常存放的是sps和pps。這裏咱們具體解析下sps和pps內容。先看下存儲的格):
0x01+sps[1]+sps[2]+sps[3]+0xFF+0xE1+sps size+sps+01+pps size+pps
複製代碼
sps[1]=0x64 sps[2]=00 sps[3]=0D sps size=0x001B=27(佔兩個字節) 跳過27個字節後,是0x01 pps size=0x0005=118(佔兩個字節) 跳過5個字節,就到了back-pointers。
視頻幀數據 解析出sps和pps tag後,後面的video tag就是真正的視頻數據內容了
這是第二個video tag其實和以前圖同樣,只是我圈出來關鍵信息。先看下格式 frametype=0x17=00010111 AVCPacketType =1 Composition Time=0x000043 後面就是NALU DATA引用:
(原)從mp4,flv文件中解析出h264和aac,送解碼器解碼失敗:,avc1與H264區別在這裏其實有人遇到了和我同樣的問題:stackoverflow.com/questions/1…