flv头 FLV header
总体上看,FLV包括文件头(File Header)和文件体(File Body)两部分,其中文件体由一系列的Tag组成。
Signature: FLV 文件的前
3个字节
为固定的‘F’‘L’‘V’,用来标识这个文件是flv格式的.在做格式探测的时候,如果发现前3个字节为“FLV”,就认为它是flv文件.
Version:
第4个字节
表示flv版本号.
Flags: 第5个字节中的第0位和第2位,分别表示 video 与 audio 存在的情况.(1表示存在,0表示不存在)
如果都存在,值为5
DataOffset : 最后
4个字节
表示FLV header 长度.
综上,一共9个字节
unsigned char flvHeaderTag[9] = {
0x46, 0x4C, 0x56,
0x01, 0x05,
0x00, 0x00, 0x00, 0x09};
FLV头后面第一个prevTagSize始终为0
===========
File Body==========
FLV header之后,就是File Body.FLV File Body是由一连串的
PreviousTagSize + tags
构成. PreviousTagSize就是
4个字节
数据大小,表示前一个tag的size.
==========FLV Tag=====
FLV文件中的数据都是由一个个TAG组成,TAG里面的数据可能是video、audio、scripts.
TagType: TAG中第1个字节中的前5位表示这个TAG中包含数据的类型,
8 = audio,9 = video,18 = script data.
DataSize(3个字节)
:
StreamID之后
的
数据长度.(length of the tag – 11),其中UI24表示3个字节,11为整个Tag除去Data之外的大小。
Timestamp和TimestampExtended组成了这个TAG包数据的PTS信息,记得刚开始做FLV demux的时候,并没有考虑TimestampExtended的值,直接就把Timestamp默认为是PTS,后来发生的现象就是画面有跳帧的现象,后来才仔细看了一下文档发现真正数据的PTS是
PTS= Timestamp | TimestampExtended<<24.
StreamID之后就是数据
。每种格式都不一样,下面进行详细介绍.
即一直到StreamId一共有11个字节
===========Audio Tag==============
如果TAG包中的TagType==8时,就表示这个TAG是audio。
StreamID之后的数据是
AudioTagHeader
,AudioTagHeader结构如下:
AudioTagHeader的第
1个字节
,也就是紧跟着StreamID的1个字节包含着音频类型、采样率等基本信息.上述表里列的十分清楚.
AudioTagHeader之后跟着的就是AUDIODATA数据了
,也就是audio payload 但是这里有个特例,如果音频格式(SoundFormat)是10 = AAC,
AudioTagHeader中会多出1个字节的数据AACPacketType
,这个字段来表示AACAUDIODATA的类型:0 = AAC sequence header,1 = AAC raw。
图片双击可看大图:
- AAC sequence header也就是包含了AudioSpecificConfig,AudioSpecificConfig包含着一些更加详细的音频信息,AudioSpecificConfig的定义在ISO14496-3中1.6.2.1 AudioSpecificConfig。
在ffmpeg中有对AudioSpecificConfig解析的函数,ff_mpeg4audio_get_config()(我的ffmpeg版本中是avpriv_mpeg4audio_get_config())。
- AAC raw 这种包含的就是音频ES流了,也就是audio payload.
在FLV文件中,一般情况下 AAC sequence header 这种包只出现1次,而且是第一个audio tag,为什么要提到这种tag,因为当时在做FLV demux的时候,如果是AAC的音频,需要在每帧AAC ES流前边添加7个字节ADST头,ADST在音频的格式中会详细解读,这是解码器通用的格式,就是AAC的纯ES流要打包成ADST格式的AAC文件,解码器才能正常播放.就是在打包ADST的时候,需要samplingFrequencyIndex这个信息,samplingFrequencyIndex最准确的信息是在AudioSpecificConfig中,所以就对AudioSpecificConfig进行解析并得到了samplingFrequencyIndex。 到这步你就完全可以把FLV 文件中的音频信息及数据提取出来,送给音频解码器正常播放了。
==========Video Tag============
如果TAG包中的TagType==9时,就表示这个TAG是video. StreamID之后的数据就表示是
VideoTagHeader
,VideoTagHeader结构如下:
VideoTagHeader的头1个字节,也就是紧跟着StreamID的1个字节包含着视频
帧类型(比如关键帧,p帧)
及视频CodecID信息.
VideoTagHeader之后跟着的就是VIDEODATA数据了,也就是video payload.当然就像音频AAC一样,这里
也有特例
,即如果视频的格式是AVC(H.264)的话,VideoTagHeader会多出
4个字节
的信息:AVCPacketType 和 CompositionTime。
AVCPacketType 表示接下来 VIDEODATA (AVCVIDEOPACKET)的内容:
IF AVCPacketType == 0
AVCDecoderConfigurationRecord
(AVC sequence header)
IF AVCPacketType == 1 One or more NALUs (Full frames are required)
还有如果为2,表示是结束包,一般在flv文件结尾。
AVCDecoderConfigurationRecord
包含着H.264解码比较重要的
sps和pps
信息,在给AVC解码器送数据流之前一定要把sps和pps信息送出,否则解码器不能正常解码。而且在解码器stop之后再次start之前,
如seek、快进快退状态切换等,都需要重新送一遍sps和pps的信息
。AVCDecoderConfigurationRecord在FLV文件中一般情况也是出现1次,也就是第一个video tag. AVCDecoderConfigurationRecord的
定义
在ISO 14496-15, 5.2.4.1中。
CompositionTime:3个字节
===========AVCDecoderConfigurationRecord=========
FFmpeg中extradata_size
格式: 4B大小+SPS+4B大小+pps
AVCDecoderConfigurationRecord
结构的定义:
aligned(8) class AVCDecoderConfigurationRecord {
unsigned int(8) configurationVersion = 1;
unsigned int(8) AVCProfileIndication;
unsigned int(8) profile_compatibility;
unsigned int(8) AVCLevelIndication;
bit(6) reserved = ‘111111’b;
unsigned int(2)
lengthSizeMinusOne
;
bit(3) reserved = ‘111’b;
unsigned
int(5)
numOfSPS;
for (i=0; i< numOfSPS; i++) {
unsigned int(16)
SPSLength ;
bit(
8*sequenceParameterSetLength
) sequenceParameterSetNALUnit;
}
unsigned
int(8)
numOfPPS;
for (i=0; i< numOfPPSet; i++) {
unsigned
int(16)
PPSetLength;
bit(8*pictureParameterSetLength) pictureParameterSetNALUnit;
}
}
下面
蓝色的部分就是
FLV
文件中的
AVCDecoderConfigurationRecord
部分。
17 00 表示是参数包,然后00 00 00 是
:3个字节CompositionTime
00000130h: 00 00 00
17 00 00 00 00
01 4D 40 15
FF
E1 00 0A
; .........M@.?.
00000140h:
67 4D 40 15 96 53 01 00 4A 20
01
00 05 68 E9 23
; gM@.
朣
..J ...h?
00000150h:
88 00
00 00 00 2A 08 00 00 52 00 00 00 00 00 00 ; ?...*...R......
根据定义:
·
configurationVersion =
01
·
AVCProfileIndication =
4D
·
profile_compatibility =
40
·
AVCLevelIndication =
15
·
lengthSizeMinusOne =
FF
<-
非常重要,是
H.264
视频中
NALU
的长度,
计算方法
是
1 + (lengthSizeMinusOne & 3)
计算结果为
4
·
numOfSequenceParameterSets =
E1
<- SPS
的个数,计算方法是
numOfSequenceParameterSets
& 0x1F
计算结果为
1
·
sequenceParameterSetLength =
00 0A
<-
SPS
的长度
·
sequenceParameterSetNALUnits =
67 4D 40 15 96 53 01 00 4A 20
<- SPS数据
·
numOfPictureParameterSets =
01
<- PPS
的个数
·
pictureParameterSetLength =
00 05
<- PPS
的长度
·
pictureParameterSetNALUnits =
68 E9 23 88 00
<- PPS数据
资料:
FLV文件格式规范.pdf
解析工具:
FlvParse
SpecialFFLV