天天看點

FLV協定5分鐘入門淺析

FLV協定簡介

FLV(Flash Video)是一種流媒體格式,因其體積小、協定相對簡單,很快便流行開來,并得到廣泛的支援。

常見的HTTP-FLV直播協定,就是使用HTTP流式傳輸通過FLV封裝的音視訊資料。對想要了解HTTP-FLV的同學來說,了解FLV協定很有必要。

概括地說,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 + TagN

FLV tag又分為3種類型:

  • Video Tag:存放視訊相關資料;
  • Audio Tag:存放音頻相關資料;
  • Script Tag:存放音視訊中繼資料;

在實際講解FLV協定前,首先對機關進行約定:

| 類型 | 定義 |

| :-------- | :--------|

| 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)
簽名,固定為'L' (0x4c)
簽名,固定為'V' (0x56)
Version 版本,比如 0x01 表示 FLV 版本 1
TypeFlagsReserved UB[5] 全為0
TypeFlagsAudio UB[1] 1表示有audio tag,0表示沒有
TypeFlagsVideo 1表示有video tag,0表示沒有
DataOffset UI32 FLV header的大小,機關是位元組

FLV file body

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

  1. PreviousTagSize0 總是為0;
  2. tag 由tag header、tag body組成;
  3. 對FLV版本1,tag header固定為11個位元組,是以,PreviousTagSize(除第1個)的值為 11 + 前一個tag 的 tag body的大小;
PreviousTagSize0 總是0
Tag1 FLVTAG 第1個tag
PreviousTagSize1 前一個tag的大小,包括tag header
Tag2 第2個tag
...
PreviousTagSizeN-1 第N-1個tag的大小
TagN 第N個tag
PreviousTagSizeN 第N個tag的大小,包含tag header

FLV tags

FLV tag由 tag header + tag body組成。

tag header如下,總共占據11個位元組:

TagType

tag類型

8:audio

9:video

18:script data

其他:保留

DataSize UI24 tag body的大小
Timestamp

相對于第一個tag的時間戳(機關是毫秒)

第一個tag的Timestamp為0

TimestampExtended 時間戳的擴充字段,當 Timestamp 3個位元組不夠時,會啟用這個字段,代表高8位
StreamID
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

采樣精度,對于壓縮過的音頻,永遠是16位

0 = snd8Bit

1 = snd16Bit

SoundType

聲道類型,對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

0: AAC sequence header

1: AAC raw

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 編碼器類型,比如2表示AAC-LC
SamplingFrequencyIndex 采樣率索引值,比如4表示44100
ChannelConfiguration 聲道配置,比如2代表雙聲道,front-left, front-right

Video tags

FrameType

重點關注1、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

編解碼器,主要關注 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

0: AVC sequence header

1: AVC NALU

2: AVC end of sequence

CompositionTime SI24 如果AVCPacketType=1,則為時間cts偏移量;否則,為0

1、如果如果AVCPacketType=1,則為AVCDecoderConfigurationRecord

2、如果AVCPacketType=1=2,則為NALU(一個或多個)

3、如果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 永遠是9,辨別着Script Data的結束

SCRIPTDATAOBJECT 定義如下:

ObjectName SCRIPTDATASTRING 對象的名字
ObjectData SCRIPTDATAVALUE 對象的值

SCRIPTDATAVALUE 的定義如下:

Type

變量類型:

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 視訊寬度(px)
height 視訊高度(px)
videodatarate 視訊比特率(kb/s)
framerate 視訊幀率(幀/s)
videocodecid 視訊編解碼器ID(參考Video Tag)
audiosamplerate 音頻采樣率
audiosamplesize 音頻采樣精度(參考Audio Tag)
stereo BOOL 是否立體聲
audiocodecid 音頻編解碼器ID(參考Audio Tag)
filesize 檔案總得大小(位元組)

寫在後面

FLV協定本身不算複雜,了解上的困難,更多時候來自音視訊編解碼相關的知識,比如H.264、AAC相關知識,建議不懂的時候自行查下。此外,FLV的位元組序為大端序,在做協定解析的時候一定要注意。

本文為講解友善,部分内容可能不夠嚴謹,如有錯漏敬請指出。

相關連結

video_file_format_spec_v10.pdf

https://www.adobe.com/content/dam/acom/en/devnet/flv/video_file_format_spec_v10.pdf

MPEG-4 Part 3

https://en.wikipedia.org/wiki/MPEG-4_Part_3#Audio_Profiles

flv檔案分析

https://www.jianshu.com/p/e290dca02979

H.264再學習 -- 詳解 H.264 NALU文法結構

https://blog.csdn.net/qq_29350001/article/details/78226286

繼續閱讀