一、flv文件结构
flv文件由flv header 和flv body组成。
二、flv header
Header 部分记录了FLV的类型、版本、流信息、Header 长度等。一般整个Header占用9个字节,大于9个字节则表示头部信息在这基础之上还存在扩展数据。Header 的头部信息排布如下所示:
三、flv body
Body 是由一个个Tag组成的,每个Tag下面有一块4个字节的空间,用来记录这个Tag 的长度。这个后置的PreviousTagSize用于逆向读取处理,表示的是前面的Tag的大小,对于FLV版本0x01来说,数值等于 11 + Tag的DataSize(tag header总是11个字节)。其结构排布如下:
1.tag
每个Tag 也是由两部分组成的:Tag Header 和 Tag Data。Tag Header 存放了当前Tag的类型,数据长度、时间戳、时间戳扩展、StreamsID等信息,然后再接着数据区Tag Data。
2.tag header
tag header的排布如下:
3.tag data
Tag Data分成 Audio,Video,Script 三种。
1)Audio Tag Data
音频的Tag Data又分为 Audio Tag Header 和 Data 数据区,其排布结构如下图所示:
AudioTagHeader通常占用1个字节,AAC编码则会多出一个AACPacketType的字节,用于表示AAC的序列头还是裸数据。
其中,前4bits表示SoundFormat,其数值对应声音格式,如下:
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,数值对应采样率,对于AAC来说,总是3:
0 - 5.5kHz
1 - 11kHz
2 - 22kHz
3 - 44kHz
第7bit 表示采样大小:
0 - snd 8 bit
1 - snd 16 bit
第8bit 表示音频声道数,对于AAC来说,总是1:
0 - sndMono
1 - sndStereo
audio Data数据区,根据SoundFormat的数值来确定,如果SoundFormat = 10,则Data数据区是AAC编码部分,其他声音类型,则根据具体格式进行解析。
针对AAC编码,音频Data数据区的定义如下:
AACPacketType = 0 时,表示AAC序列头,也就是AudioSpecificConfig, AACPacketType = 1 时,表示AAC的裸流,也就是AAC Raw frame data。
AudioSpecificConfig 只出现在第一个Audio Tag中,结构如下:
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 编码结构类型,AAC-LC为2
samplingFreguencyIndex 4bits 音频采样率索引值
channelConfiguration 4bits 音频声道数
GASpecificConfig
frameLengthFlag 1bits 标志位,用于表明IMDCT窗口长度,为0
dependsOnCoreCoder 1bits 标志位,用于表明是否依赖corecoder,为0
extensionFlag 1bits 扩展标志位,选择了AAC-LC,这里必须为0
其中,samplingFreguencyIndex 对应关系如下:
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裸流AAC Raw frame data,即AAC音频原始数据,不包括AAC头数据ADTS。
如果是MP3 编码部分,audio 数据区直接为 MP3 头 + MP3 原始数据。
2)Video Tag Data
Video Tag 由一个字节的Video Tag Header 和 Video数据区部分组成。
Video Tag Header
Video Tag Header通常由一个字节构成,前4bit表示类型,后4bit表示编码器Id。
Video Tag Data
Video数据区部分格式不确定。对于H264/AVC编码部分,Video数据区排布如下:
其中,AVCsequenceheader只有出现在第一个Video Tag,只有一个。为了能够从FLV中获取NALU,必须知道前面的NALU长度所占的字节数,通常是1、2、4个字节,这个内容则必须从AVCDecoderConfigurationRecord中获取,这个遵从标准ISO/IEC 14496-15的5.2.4小节。AVCDecoderConfigurationRecord 的结构如下:
aligned(8) class AVCDecoderConfigurationRecord {
unsigned int(8) configurationVersion = 1; //版本号
unsigned int(8) AVCProfileIndication; //sps[1],即0x67后面那个字节
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个数,一般为1
for ( i=0; i<numOfSequenceParameterSets; i++ ) {
unsigned int(16) sequenceParameterSetLength; //sps的长度
bit(8*sequenceParameterSetLength) sequenceParameterSetNALUnit;
}
unsigned int(8) numOfPictureParameterSets; //pps个数,一般为1
for ( i=0; i<numOfPictureParameterSets; i++) {
unsigned int(16) pictureParameterSetLength; //pps长度
bit(8*pictureParameterSetLength) pictureParameterSetNALUnit;
}
}
其中,lengthSizeMinusOne + 1 = NALU长度字段所占字节数。
3)Script Tag Data
当TagType = 0x12时, 这个Tag就是Script tag。Script Tag一般只有一个,是FLV文件的第一个Tag,用于存放FLV文件信息,比如时长、分辨率、音频采样率等。所有的数据都是以数据类型 + (数据长度) + 数据格式出现,数据类型占1个字节,数据长度看数据类型是否存在,后面才是数据。数据排布如下:
其中SCRIPTDATAOBJECTEND和SCRIPTDATAVARIABLEEND为0x000009,用于标记对象和数组类型的结尾。
SCRIPTDATASTRING结构为:
StringLength 2bytes
StringData String
SCRIPTDATALONGSTRING结构为:
StringLength 4bytes
StringData String
ECMA array type结构为:
ECMAArrayLength 4bytes
StringLength 2bytes
StringData String
DataType 1byte
Data 不定长
SCRIPTDATAVARIABLEEND
Object type结构为:
StringLength 2bytes
StringData String
DataType 1byte
DataVale 不定长
SCRIPTDATAOBJECTEND
Strict array type结构为:
ArrayNum 4bytes
DataType byte
DataValue 不定长
如果类型为String,后面的2bytes为字符串的长度(Long String是4bytes),再后面才是字符串数据;如果是Number类型,后面的8bytes为Double类型的数据;Boolean类型,后面1byte为Bool类型。
知道了这些后再来看看flv中的脚本,一般开头是0x02,表示String类型,后面的2bytes为字符串长度,一般是0x000a(“onMetaData”的长度),再后面就是字符串“onMetaData”。好像flv格式的文件都有onMetaData标记,在运行ActionScript的时候会用到它。后面跟的是0x08,表示ECMA Array类型,这个和Map比较相似,一个键跟着一个值。键都是String类型的,所以开头的0x02被省略了,直接跟着的是字符串的长度,然后是字符串,再是值的类型,也就是上面介绍的那些了。
onMetaData标签中包含的是流的信息,一般的信息包括: