FLV協議5分鐘入門淺析

FLV協議簡介

FLV(Flash Video)是一種流媒體格式,因其體積小、協議相對簡單,很快便流行開來,並獲得普遍的支持。php

常見的HTTP-FLV直播協議,就是使用HTTP流式傳輸經過FLV封裝的音視頻數據。對想要了解HTTP-FLV的同窗來講,瞭解FLV協議頗有必要。ios

歸納地說,FLV 由 FLV header 跟 FLV file body 兩部分組成,而 FLV file body 又由多個 FLV tag組成。數組

FLV = FLV header + FLV file body FLV file body = PreviousTagSize0 + Tag1 + PreviousTagSize1 + Tag2 + ... + PreviousTagSizeN-1 + TagNbash

FLV tag又分爲3種類型:less

  • Video Tag:存放視頻相關數據;
  • Audio Tag:存放音頻相關數據;
  • Script Tag:存放音視頻元數據;

在實際講解FLV協議前,首先對單位進行約定:ide

類型 定義
0x... 16進制數據
SI8 有符號8位整數
SI16 有符號16位整數
SI24 有符號24位整數
SI32 有符號32位整數
STRING Sequence of Unicode 8-bit characters (UTF-8), terminated with 0x00 (unless otherwise specified)
UI8 無符號8位整數
UI16 無符號16位整數
UI24 無符號24位整數
UI32 無符號32位整數
xxx [ ] 類型爲xxx的數組
xxx [n] 類型爲xxx的數組,數組長度爲n

FLV header

FLV header由以下字段組成,其中:學習

  1. 前三個字節內容固定是FLV
  2. 最後4個字節內容固定是9(對FLV版本1來講)
字段 字段類型 字段含義
Signature UI8 簽名,固定爲'F' (0x46)
Signature UI8 簽名,固定爲'L' (0x4c)
Signature UI8 簽名,固定爲'V' (0x56)
Version UI8 版本,好比 0x01 表示 FLV 版本 1
TypeFlagsReserved UB[5] 全爲0
TypeFlagsAudio UB[1] 1表示有audio tag,0表示沒有
TypeFlagsReserved UB[1] 全爲0
TypeFlagsVideo UB[1] 1表示有video tag,0表示沒有
DataOffset UI32 FLV header的大小,單位是字節

FLV file body

FLV file body頗有規律,由一系列的TagSize和Tag組成,其中:ui

  1. PreviousTagSize0 老是爲0;
  2. tag 由tag header、tag body組成;
  3. 對FLV版本1,tag header固定爲11個字節,所以,PreviousTagSize(除第1個)的值爲 11 + 前一個tag 的 tag body的大小;
字段 字段類型 字段含義
PreviousTagSize0 UI32 老是0
Tag1 FLVTAG 第1個tag
PreviousTagSize1 UI32 前一個tag的大小,包括tag header
Tag2 FLVTAG 第2個tag
... ... ...
PreviousTagSizeN-1 UI32 第N-1個tag的大小
TagN FLVTAG 第N個tag
PreviousTagSizeN UI32 第N個tag的大小,包含tag header

FLV tags

FLV tag由 tag header + tag body組成。this

tag header以下,總共佔據11個字節:編碼

字段 字段類型 字段含義
TagType UI8 tag類型
8:audio
9:video
18:script data
其餘:保留
DataSize UI24 tag body的大小
Timestamp UI24 相對於第一個tag的時間戳(單位是毫秒)
第一個tag的Timestamp爲0
TimestampExtended UI8 時間戳的擴展字段,當 Timestamp 3個字節不夠時,會啓用這個字段,表明高8位
StreamID UI24 老是0
Data 取決於根據TagType TagType=8,則爲AUDIODATA
TagType=9,則爲VIDEODATA
TagType=18,則爲SCRIPTDATAOBJECT

In playback, the time sequencing of FLV tags depends on the FLV timestamps only. Any timing mechanisms built into the payload data format are ignored.

Audio tags

定義以下所示:

字段 字段類型 字段含義
SoundFormat UB[4] 音頻格式,重點關注 **10 = AAC **
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
SoundRate UB[2] 採樣率,對AAC來講,永遠等於3
0 = 5.5-kHz
1 = 11-kHz
2 = 22-kHz
3 = 44-kHz
SoundSize UB[1] 採樣精度,對於壓縮過的音頻,永遠是16位
0 = snd8Bit
1 = snd16Bit
SoundType UB[1] 聲道類型,對Nellymoser來講,永遠是單聲道;對AAC來講,永遠是雙聲道;
0 = sndMono 單聲道
1 = sndStereo 雙聲道
SoundData UI8[size of sound data] 若是是AAC,則爲 AACAUDIODATA;
其餘請參考規範;

備註:

If the SoundFormat indicates AAC, the SoundType should be set to 1 (stereo) and the SoundRate should be set to 3 (44 kHz). However, this does not mean that AAC audio in FLV is always stereo, 44 kHz data. Instead, the Flash Player ignores these values and extracts the channel and sample rate data is encoded in the AAC bitstream.

AACAUDIODATA

當 SoundFormat 爲10時,表示音頻採AAC進行編碼,此時,SoundData的定義以下:

字段 字段類型 字段含義
AACPacketType UI8 0: AAC sequence header
1: AAC raw
Data UI8[n] 若是AACPacketType爲0,則爲AudioSpecificConfig
若是AACPacketType爲1,則爲AAC幀數據

The AudioSpecificConfig is explained in ISO 14496-3. Note that it is not the same as the contents of the esds box from an MP4/F4V file. This structure is more deeply embedded.

關於AudioSpecificConfig

僞代碼以下:參考這裏

5 bits: object type
if (object type == 31)
    6 bits + 32: object type
4 bits: frequency index
if (frequency index == 15)
    24 bits: frequency
4 bits: channel configuration
var bits: AOT Specific Config
複製代碼

定義以下:

字段 字段類型 字段含義
AudioObjectType UB[5] 編碼器類型,好比2表示AAC-LC
SamplingFrequencyIndex UB[4] 採樣率索引值,好比4表示44100
SamplingFrequencyIndex UB[4] 採樣率索引值,好比4表示44100
ChannelConfiguration UB[4] 聲道配置,好比2表明雙聲道,front-left, front-right

Video tags

定義以下:

字段 字段類型 字段含義
FrameType UB[4] 重點關注一、2:
1: keyframe (for AVC, a seekable frame) —— 即H.264的IDR幀;
2: inter frame (for AVC, a non- seekable frame) —— H.264的普通I幀;
3: disposable inter frame (H.263 only)
4: generated keyframe (reserved for server use only)
5: video info/command frame
CodecID UB[4] 編解碼器,主要關注 7(AVC)
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
VideoData 取決於CodecID 實際的媒體類型,主要關注 7:AVCVIDEOPACKE
2: H263VIDEOPACKET
3: SCREENVIDEOPACKET
4: VP6FLVVIDEOPACKET
5: VP6FLVALPHAVIDEOPACKET
6: SCREENV2VIDEOPACKET
7: AVCVIDEOPACKE

AVCVIDEOPACKE

當 CodecID 爲 7 時,VideoData 爲 AVCVIDEOPACKE,也即 H.264媒體數據。

AVCVIDEOPACKE 的定義以下:

字段 字段類型 字段含義
AVCPacketType UI8 0: AVC sequence header
1: AVC NALU
2: AVC end of sequence
CompositionTime SI24 若是AVCPacketType=1,則爲時間cts偏移量;不然,爲0
Data UI8[n] 一、若是若是AVCPacketType=1,則爲AVCDecoderConfigurationRecord
二、若是AVCPacketType=1=2,則爲NALU(一個或多個)
三、若是AVCPacketType=2,則爲空

這裏有幾點稍微解釋下:

  1. NALU:H.264中,將數據按照特定規則格式化後獲得的抽象邏輯單元,稱爲NALU。這裏的數據既包括了編碼後的視頻數據,也包括視頻解碼須要用到的參數集(PPS、SPS)。
  2. AVCDecoderConfigurationRecord:H.264 視頻解碼所須要的參數集(SPS、PPS)
  3. CTS:當B幀的存在時,視頻解碼呈現過程當中,dts、pts可能不一樣,cts的計算公式爲 pts - dts/90,單位爲毫秒;若是B幀不存在,則cts固定爲0;

PPS、SPS這裏先不展開。

Script Data Tags

Script Data Tags一般用來存放跟FLV中音視頻相關的元數據信息(onMetaData),好比時長、長度、寬度等。它的定義相對複雜些,採用AMF(Action Message Format)封裝了一系列數據類型,好比字符串、數值、數組等。

字段 字段類型 字段含義
Objects SCRIPTDATAOBJECT[] 任意數目的 SCRIPTDATAOBJECT
SCRIPTDATAOBJECTEND UI24 永遠是9,標識着Script Data的結束

SCRIPTDATAOBJECT 定義以下:

字段 字段類型 字段含義
ObjectName SCRIPTDATASTRING 對象的名字
ObjectData SCRIPTDATAVALUE 對象的值

SCRIPTDATAVALUE 的定義以下:

字段 字段類型 字段含義
Type SCRIPTDATASTRING 變量類型:
0 = Number type
1 = Boolean type
2 = String type
3 = Object type
4 = MovieClip type
5 = Null type
6 = Undefined type
7 = Reference type 8 = ECMA array type 10 = Strict array type 11 = Date type
12 = Long string type
ECMAArrayLength 若是Type爲8(數組),則爲UI32 數組長度
ScriptDataValue If Type == 0 DOUBLE
If Type == 1 UI8
If Type == 2 SCRIPTDATASTRING
...(有點長,能夠參考規範)
變量的值
ScriptDataValueTerminator 若是Type==3,則爲SCRIPTDATAOBJECTEND
若是 Type==8,則爲SCRIPTDATAVARIABLEEND
Object、Array的結束符

能夠看到,Script Data Tag 的定義相對複雜,下面經過onMetaData進行進一步講解。

onMetaData

onMetaData中包含了音視頻相關的元數據,封裝在Script Data Tag中,它包含了兩個AMF。

第一個AMF:

  • 第1個字節:0x02,表示字符串類型
  • 第2-3個字節:UI16類型,值爲0x000A,表示字符串的長度爲10(onMetaData的長度);
  • 第4-13個字節:字符串onMetaData對應的16進制數字(0x6F 0x6E 0x4D 0x65 0x74 0x61 0x44 0x61 0x74 0x61);

第二個AMF:

  • 第1個字節:0x08,表示數組類型;
  • 第2-5個字節:UI32類型,表示數組的長度,onMetaData中具體包含哪些屬性是不固定的。
  • 第6個字節+:好比duration,則:
    • 第6-9個字節:0x0008,表示長度爲8個字節;
    • 第10-17個字節:0x6475 7261 7469,表示 duration 這個字符串;
    • 第18個字節:0x00,表示爲數值類型;
    • 第19-26個字節:0x...,表示具體的時長;

更多onMetaData字段的定義:

字段 字段類型 字段含義
duration DOUBLE 文件的時長
width DOUBLE 視頻寬度(px)
height DOUBLE 視頻高度(px)
videodatarate DOUBLE 視頻比特率(kb/s)
framerate DOUBLE 視頻幀率(幀/s)
videocodecid DOUBLE 視頻編解碼器ID(參考Video Tag)
audiosamplerate DOUBLE 音頻採樣率
audiosamplesize DOUBLE 音頻採樣精度(參考Audio Tag)
stereo BOOL 是否立體聲
audiocodecid DOUBLE 音頻編解碼器ID(參考Audio Tag)
filesize DOUBLE 文件總得大小(字節)

寫在後面

FLV協議自己不算複雜,理解上的困難,更多時候來自音視頻編解碼相關的知識,好比H.26四、AAC相關知識,建議不懂的時候自行查下。此外,FLV的字節序爲大端序,在作協議解析的時候必定要注意。

本文爲講解方便,部份內容可能不夠嚴謹,若有錯漏敬請指出。

相關連接

video_file_format_spec_v10.pdf www.adobe.com/content/dam…

MPEG-4 Part 3 en.wikipedia.org/wiki/MPEG-4…

flv文件分析 www.jianshu.com/p/e290dca02…

H.264再學習 -- 詳解 H.264 NALU語法結構 blog.csdn.net/qq_29350001…

相關文章
相關標籤/搜索