FLV的定義:
Flash Video(簡稱FLV),是一種流行的網(wǎng)絡(luò)格式怕品,是Adobe推出的妇垢。目前大部分視頻網(wǎng)站都支持這種格式。
FLV的文件結(jié)構(gòu)
FLV文件由FLV Header 和 FLV Body構(gòu)成肉康。
FLV Header 頭部信息
Header 部分記錄了FLV的類型闯估、版本、流信息吼和、Header 長度等涨薪。一般整個(gè)Header占用9個(gè)字節(jié),大于9個(gè)字節(jié)則表示頭部信息在這基礎(chǔ)之上還存在擴(kuò)展數(shù)據(jù)炫乓。Header 的頭部信息排布如下所示:
FLV Body 文件內(nèi)容部分
Body 是由一個(gè)個(gè)Tag組成的刚夺,每個(gè)Tag下面有一塊4個(gè)字節(jié)的空間,用來記錄這個(gè)Tag 的長度末捣。這個(gè)后置的PreviousTagSize用于逆向讀取處理侠姑,表示的是前面的Tag的大小,對(duì)于FLV版本0x01來說箩做,數(shù)值等于 11 + Tag的DataSize莽红。其結(jié)構(gòu)排布如下:
FLV Tag
每個(gè)Tag 也是由兩部分組成的:Tag Header 和 Tag Data。Tag Header 存放了當(dāng)前Tag的類型卒茬,數(shù)據(jù)長度船老、時(shí)間戳咖熟、時(shí)間戳擴(kuò)展、StreamsID等信息柳畔,然后再接著數(shù)據(jù)區(qū)Tag Data馍管。Tag的排布如下:
Tag Data
Tag Data分成 Audio,Video薪韩,Script 三種确沸。
Audio Tag Data
音頻的Tag Data又分為 AudioTagHeader 和 Data 數(shù)據(jù)區(qū),其排布結(jié)構(gòu)如下圖所示:
AudioTagHeader通常占用1個(gè)字節(jié)俘陷,AAC編碼則會(huì)多出一個(gè)AACPacketType的字節(jié)罗捎,用于表示AAC的序列頭還是裸數(shù)據(jù)。
其中拉盾,前4bits表示SoundFormat桨菜,其數(shù)值對(duì)應(yīng)聲音格式,如下:
0 - Linear PCM, platform endian
1 - ADPCM
2 - MP3
3 - LinearPCM捉偏,little endian
4 - Nellymoser 16-kHz mono
5 - Nellymoser 8-kHZ mono
6 - Nellymoser
7 - G.711 A-law logarithmic PCM
8 - G.711 U-law logarithmic PCM
9 - reserved
10 - AAC
11 - Speex
14 - MP3 8-kHz
15 - Device-specific sound
第5倒得、6bit 表示SoundRate,數(shù)值對(duì)應(yīng)采樣率夭禽,對(duì)于AAC來說霞掺,總是3:
0 - 5.5kHz
1 - 11kHz
2 - 22kHz
3 - 44kHz
第7bit 表示采樣大小:
0 - snd 8 bit
1 - snd 16 bit
第8bit 表示音頻聲道數(shù)讹躯,對(duì)于AAC來說菩彬,總是1:
0 - sndMono
1 - sndStereo
audio Data數(shù)據(jù)區(qū),根據(jù)SoundFormat的數(shù)值來確定潮梯,如果SoundFormat = 10骗灶,則Data數(shù)據(jù)區(qū)是AAC編碼部分,其他聲音類型酷麦,則根據(jù)具體格式進(jìn)行解析矿卑。
AAC編碼
針對(duì)AAC編碼喉恋,音頻Data數(shù)據(jù)區(qū)的定義如下:
AACPacketType = 0 時(shí)沃饶,表示AAC序列頭,也就是AudioSpecificConfig轻黑, AACPacketType = 1 時(shí)糊肤,表示AAC的裸流,也就是AAC Raw frame data氓鄙。
AudioSpecificConfig
AudioSpecificConfig 只出現(xiàn)在第一個(gè)Audio Tag中馆揉,結(jié)構(gòu)如下,
AudioSpecificConfig() {
audioObjectType; 5bits
samplingFrequencyIndex; 4bits
if ( samplingFrequencyIndex == 0xf ) {
samplingFrequency; 24bits
}
channelConfiguration; 4bits
sbrPresentFlag = -1;
if ( audioObjectType == 5 ) {
extensionAudioObjectType = audioObjectType;
sbrPresentFlag = 1;
extensionSamplingFrequencyIndex; 4bits
if ( extensionSamplingFrequencyIndex == 0xf ) {
extensionSamplingFrequency; 24bits
}
audioObjectType; 5bits
} else {
extensionAudioObjectType = 0;
}
if ( audioObjectType == 1 || audioObjectType == 2 ||
audioObjectType == 3 || audioObjectType == 4 ||
audioObjectType == 6 || audioObjectType == 7 ) {
GASpecificConfig();
}
if ( audioObjectType == 8 ) {
CelpSpecificConfig();
}
if ( audioObjectType == 9 ) {
HvxcSpecificConfig();
}
if ( audioObjectType == 12 ) {
TTSSpecificConfig();
}
if ( audioObjectType == 13 || audioObjectType == 14 ||
audioObjectType == 15 || audioObjectType == 16 ) {
StructureAudioSpecificConfig();
}
if ( audioObjectType == 17 || audioObjectType == 19 ||
audioObjectType == 20 || audioObjectType == 21 ||
audioObjectType == 22 || audioObjectType == 23 ) {
GASpecificConfig();
}
if ( audioObjectType == 24 ) {
ErrorResilientCelpSpecificConfig();
}
if ( audioObjectType == 25 ) {
ErrorResilientHvxcSpecificConfig();
}
if ( audioObjectType == 26 || audioObjectType == 27 ) {
ParametricSpecificConfig();
}
if ( audioObjectType == 17 || audioObjectType == 19 ||
audioObjectType == 20 || audioObjectType == 21 ||
audioObjectType == 22 || audioObjectType == 23 ||
audioObjectType == 24 || audioObjectType == 25 ||
audioObjectType == 26 || audioObjectType == 27 ) {
epConfig; 2bits
if ( epConfig == 2 || epConfig == 3 ) {
ErrorProtectionSpecificConfig();
}
if ( epConfig == 3 ) {
directMapping; 1bit
if ( ! directMapping ) {
/* tbd */
}
}
}
if ( audioObjectType == 28 ) {
SSCSpecificConfig();
}
if ( extensionAudioObjectType != 5 && bits_to_decode() >= 16 ) {
syncExtensionType; 11bits
if ( syncExtensionType == 0x2b7 ) {
extensionAudioObjectType; 5bits
if ( extensionAudioObjectType == 5 ) {
sbrPresentFlag; 1bit
if ( sbrPresentFlag == 1 ) {
extensionSamplingFrequencyIndex; 4bits
if ( extensionSamplingFrequencyIndex == 0xf ) {
extensionSamplingFrequency; 24bits
}
}
}
}
}
}
AudioSpecificConfig 簡化格式如下:
audioObjectType 5bits 編碼結(jié)構(gòu)類型抖拦,AAC-LC為2
samplingFreguencyIndex 4bits 音頻采樣率索引值
channelConfiguration 4bits 音頻聲道數(shù)
GASpecificConfig
frameLengthFlag 1bits 標(biāo)志位升酣,用于表明IMDCT窗口長度舷暮,為0
dependsOnCoreCoder 1bits 標(biāo)志位,用于表明是否依賴corecoder噩茄,為0
extensionFlag 1bits 擴(kuò)展標(biāo)志位下面,選擇了AAC-LC,這里必須為0
其中绩聘,samplingFreguencyIndex 對(duì)應(yīng)關(guān)系如下:
0 - 96000
1 - 88200
2 - 64000
3 - 48000
4 - 44100
5 - 32000
6 - 24000
7 - 22050
8 - 16000
9 - 12000
10 - 11025
11 - 8000
12 - 7350
13 - Reserved
14 - Reserved
15 - frequency is written explictly
AAC Raw frame data
AAC裸流AAC Raw frame data沥割,即AAC音頻原始數(shù)據(jù),不包括AAC頭數(shù)據(jù)ADTS凿菩。
AAC頭部數(shù)據(jù) ADTS
ADTS包括采樣頻率机杜、幀長度等信息,共7個(gè)字節(jié)衅谷,分為兩部分:
adts_fixed_header 椒拗、adts_variable_header
adts_fixed_header 排布如下:
adts_fixed_header() {
syncword 12bits always 0xFFF
ID 1bit 0--MPEG-4 1--MPEG-2
layer 2bits always '00'
protection_absent 1bit
profile 2bits 0--Main profile 1--Low Complexity profile(LC)
2--Scalable Sampling Rate profile(SSR) 3--reserved
sampling_frequency_index 4bits 音頻采樣率索引值
private_bit 1bit
channel_configuration 3bits 音頻聲道數(shù)
original_copy 1bit
home 1bit
}
channel_configuration 對(duì)應(yīng)關(guān)系如下:
0 bit : Defined in AOT Specific Config
1 bit : 1 channel:front-center
2 bit : 2 channels:front-left,front-right
3 bit : 3 channels:front-center获黔,front-left陡叠,front-right
4 bit : 4 channels:front-center,front-left肢执,front-right枉阵,back-center
5 bit : 5 channels:front-center,front-left预茄,front-right兴溜,back-left,back-right
6 bit : 6 channels:front-center耻陕,front-left拙徽,front-right,back-left诗宣,back-right膘怕,LFE-channel
7 bit : 8 channels:front-center,front-left召庞,front-right岛心,side-left,side-right篮灼,back-left忘古,back-right,LFE-channel
8-15 bit:Reserved
adts_variable_header排布如下:
adts_variable_header() {
copyright_identification_bit 1bit
copyright_identification_start 1bit
aac_frame_length 13bits ADTS頭 + AAC原始流
adts_buffer_fullness 11bits 0x7FF表示碼率可變的碼流
number_of_raw_data_blocks_in_frame 2bits
}
MP3編碼
如果是MP3 編碼部分诅诱,audio 數(shù)據(jù)區(qū)直接為 MP3 頭 + MP3 原始數(shù)據(jù)髓堪。
MP3 頭部格式如下:
MP3FrameHeader
{
sync 11bits 同步信息always 0xFFF
version 2bits 版本 00--MPEG 2.5 01--未定義 10--MPEG 2 11--MPEG 1
layer 2bits 層 00--未定義 01--Layer 3 10--Layer 2 11--Layer 1
error_protection 1bit CRC校驗(yàn)0--校驗(yàn) 1--不校驗(yàn)
bitrate_index 4bits 位率
sampling_frequency 2bits 采樣率索引值
padding 1bit 幀長調(diào)節(jié)
private 1bit 保留字
mode 2bits 聲道模式
mode_extension 2bits 擴(kuò)充模式
copyright 1bit 版權(quán)
original 1bit 原版標(biāo)志
emphasis 2bits 強(qiáng)調(diào)模式
}
sampling_frequency對(duì)應(yīng)關(guān)系如下:
version 00--MPEG 2.5 01--未定義 10--MPEG 2 11--MPEG 1
MPEG 1: 00--44.1kHz 01--48kHz 10--32kHz 11--未定義
MPEG 2: 00--22.05kHz 01--24kHz 10--16kHz 11--未定義
MPEG 2.5: 00--11.025kHz 01--12kHz 10--8kHz 11--未定義
mode對(duì)應(yīng)關(guān)系如下:
00--立體聲Stereo 01--Joint Stereo 10--雙聲道 11--單聲道
Video Tag Data
如果Tag 包中的TagType = 9時(shí),這個(gè)Tag就表示video數(shù)據(jù)。則StreamID之后緊跟著 VideoTagHeader 和 Video Data 數(shù)據(jù)區(qū)干旁。
Video Tag 有一個(gè)字節(jié)的VideoTagHeader 和 Video數(shù)據(jù)區(qū)部分組成
VideoTagHeader
VideoTagHeader 通常由一個(gè)字節(jié)構(gòu)成驶沼,前4bit表示類型,后4bit表示編碼器Id争群。
Video數(shù)據(jù)區(qū)
Video數(shù)據(jù)區(qū)部分格式不確定商乎。對(duì)于H264/AVC編碼部分,Video數(shù)據(jù)區(qū)排布如下:
其中祭阀,AVCsequenceheader只有出現(xiàn)在第一個(gè)Video Tag鹉戚,只有一個(gè)。為了能夠從FLV中獲取NALU专控,必須知道前面的NALU長度所占的字節(jié)數(shù)抹凳,通常是1、2伦腐、4個(gè)字節(jié)赢底,這個(gè)內(nèi)容則必須從AVCDecoderConfigurationRecord中獲取,這個(gè)遵從標(biāo)準(zhǔn)ISO/IEC 14496-15的5.2.4小節(jié)柏蘑。AVCDecoderConfigurationRecord 的結(jié)構(gòu)如下:
aligned(8) class AVCDecoderConfigurationRecord {
unsigned int(8) configurationVersion = 1; //版本號(hào)
unsigned int(8) AVCProfileIndication; //sps[1]幸冻,即0x67后面那個(gè)字節(jié)
unsigned int(8) profile_compatibility; //sps[2]
unsigned int(8) AVCLevelIndication; //sps[3]
bit(6) reserved = '111111'b;
unsigned int(2) lengthSizeMinusOne; //NALUnitLength的長度減1,一般為3
bit(3) reserved = '111'b;
unsigned int(5) numOfSequenceParameterSets; //sps個(gè)數(shù)咳焚,一般為1
for ( i=0; i<numOfSequenceParameterSets; i++ ) {
unsigned int(16) sequenceParameterSetLength; //sps的長度
bit(8*sequenceParameterSetLength) sequenceParameterSetNALUnit;
}
unsigned int(8) numOfPictureParameterSets; //pps個(gè)數(shù)洽损,一般為1
for ( i=0; i<numOfPictureParameterSets; i++) {
unsigned int(16) pictureParameterSetLength; //pps長度
bit(8*pictureParameterSetLength) pictureParameterSetNALUnit;
}
}
其中,lengthSizeMinusOne + 1 = NALU長度字段所占字節(jié)數(shù)
Script Tag
當(dāng)TagType = 0x12時(shí)革半, 這個(gè)Tag就是Script tag碑定。Script Tag一般只有一個(gè),是FLV文件的第一個(gè)Tag又官,用于存放FLV文件信息延刘,比如時(shí)長、分辨率六敬、音頻采樣率等碘赖。所有的數(shù)據(jù)都是以數(shù)據(jù)類型 + (數(shù)據(jù)長度) + 數(shù)據(jù)格式出現(xiàn),數(shù)據(jù)類型占1個(gè)字節(jié)外构,數(shù)據(jù)長度看數(shù)據(jù)類型是否存在普泡,后面才是數(shù)據(jù)。數(shù)據(jù)排布如下:
其中SCRIPTDATAOBJECTEND和SCRIPTDATAVARIABLEEND為0x000009典勇,用于標(biāo)記結(jié)尾
SCRIPTDATASTRING結(jié)構(gòu)為:
StringLength 2bytes
StringData String
SCRIPTDATALONGSTRING結(jié)構(gòu)為:
StringLength 4bytes
StringData String
ECMA array type結(jié)構(gòu)為:
ECMAArrayLength 4bytes
StringLength 2bytes
StringData String
DataType 1byte
Data 不定長
SCRIPTDATAVARIABLEEND
Object type結(jié)構(gòu)為:
StringLength 2bytes
StringData String
DataType 1byte
DataVale 不定長
SCRIPTDATAOBJECTEND
Strict array type結(jié)構(gòu)為:
ArrayNum 4bytes
DataType byte
DataValue 不定長
類型在FLV的官方文檔中有詳細(xì)的介紹劫哼。
onMeteData
onMeteData 是FLV文件中的第一個(gè)Tag,是ScriptData中對(duì)我們來說十分重要的信息割笙,結(jié)構(gòu)如下:
audiocodecid
音頻編碼類型id,跟AudioTagHeader中的SoundFormat是對(duì)應(yīng)的。
videocodecid
視頻編碼類型id伤溉,跟VideoTagHeader 的 CodecID是對(duì)應(yīng)的