FLV = FLV Header + FLV File Boby
类型说明
UI8:1字节
UI24:2字节
UI32:4字节
UB:1bit
UI8[n]:n 字节
UB[n]:n bit
字段 | 类型 | 说明 |
---|---|---|
Signature | UI8[3] | 签名,总是’FLV’ |
Version | UI8 | 文件版本,0x01表示FLV1 |
TypeFlagsReserved | UB[5] | 保留,总是0 |
TypeFlagsAudio | UB[1] | 为1表示文件中存在Audio Tag |
TypeFlagsReserved | UB[1] | 保留,总是0 |
TypeFlagsVideo | UB[1] | 为1表示文件中存在Video Tag |
DataOffset | UI32 | FLV Header的长度,当FLV版本为FLV1时,DataOffset总是9 |
注:DataOffset将用来表示更大的FLV Header在之后版本中。
字段 | 类型 | 说明 |
---|---|---|
PreviousTagSize0 | UI32 | 总是0 |
Tag1 | FLVTAG | 第一个FLV Tag |
PreviousTagSize1 | UI32 | 前一个FLV Tag的长度,FLV1版本中,大小为FLV Tag Header(11字节) + FLV Tag Boby |
Tag2 | FLVTAG | 第二个FLV Tag |
… | ||
PreviousTagSizeN-1 | UI32 | 倒数第二个PreviousTagSize |
TagN | FLVTAG | 倒数第一个Tag |
PreviousTagSizeN | UI32 | 倒数第一个PreviousTagSize |
字段 | 类型 | 说明 |
---|---|---|
Reserved | UB[2] | 保留给FMS,应该为0 |
Filter | UB[1] | 一般用不到,未加密的文件应为0,加密的标签应为1 |
TagType | UB[5] | Tag类型 8为Audio Tag 9为Video Tag 18为Script Tag |
DataSize | UI24 | FLV Tag Body的长度,也就是FLV Tag Size - FLV Tag Header |
Timestamp | UI24 | Tag的毫秒时间戳,是相对于第一个Tag的相对时间戳,第一个Tag时间戳总为0 |
TimestampExtended | UI8 | TimestampExtended表示时间戳的高8位,而Timestamp表示时间戳的低24位,扩展时间戳为SI32类型。 |
StreamID | UI24 | 总为0 |
AudioTagHeader | if TagType=8 AudioTagHeader |
当TagType=8,包含AudioTagHeader |
VideoTagHeader | if TagType=9 VideoTagHeader |
当TagType=9,包含VideoTagHeader |
EncryptionTagHeader | if Filter=1 EncryptionTagHeader |
当Filter=1,包含EncryptionTagHeader,一般无用 |
FilterParams | if Filter=1 FilterParams |
当Filter=1,包含FilterParams,一般无用 |
Data | AudioData/VideoData/ScriptData | 当TagType=8,Data为AudioData。 当TagType=9,Data为VideoData。 当TagType=18,Data为ScriptData。 |
注:
数据的时间戳信息dts,dts = TimeStamp(3bytes) | TimeStampExtended(1bytes)<< 24 。
总结:
FLV File = FLV File Header(9字节) + FLV File Boby
FLV File Boby = PreTagSize0(4字节) + Tag1 + PreTagSize1 + … + PreTagSize(N-1) + TagN + PreTagSizeN
FLVTag = TagHeader(11字节) + TagBoby
TagBoby = VideoTag/AudioTag/ScriptTag = VideoTag/AudioTag/ScriptTag Header + VideoTag/AudioTag/ScriptTag Data
AudioTagHeader包含音频的元信息。
字段 | 类型 | 说明 |
---|---|---|
SoundFormat | UB[4] | 音频编码格式 2=MP3 3=Linear PCM, little endian 7=G711A 8=G711U 10=AAC 11=Speex 14=MP3(8KHZ) |
SoundRate | UB[2] | 音频采样率 0 = 5.5 kHz 1 = 11 kHz 2 = 22 kHz 3 = 44 kHz |
SoundSize | UB[1] | 采样深度 0 = 8-bit samples 1 = 16-bit samples |
SoundType | UB[1] | 声道数 0 = Mono sound 1 = Stereo sound |
AACPacketType | if SoundFormat=10 UI8 |
只有SoundFormat=10时,才有AACPakcetType。 0 = AAC sequence header 1 = AAC raw |
字段 | 类型 | 说明 |
---|---|---|
SoundData | 如果SoundFormat == 10,此字段为AACAUDIODATA 否则为Varies by format |
字段 | 类型 | 说明 |
---|---|---|
Data | 如果AACPacketType=0,此字段为AudioSpecificConfig 或者AACPacketType=1,此字段为Raw AAC Frame Data UI8[] |
AudioSpecificConfig 结构描述非常复杂,在标准文档中是用伪代码描述的,这里先假定要编码的音频格式,做一下简化。假定音频格式为AAC-LC,音频采样率为44100。
在 FLV 的文件中,一般情况下 AAC sequence header 这种包只出现1次,而且是第一个 audio tag。为什么需要这种 tag(AAC sequence header):因为在做 FLV demux 的时候,如果是 AAC 的音频,需要在每帧 AAC ES 流(ES流=裸流)前边添加 7 个字节 ADST 头,ADST 是解码器通用的格式,也就是说 AAC 的纯 ES 流要打包成 ADST 格式的 AAC 流,解码器才能正常播放。
注:
当SoundFormat等于10时,音频编码为AAC,需要给每帧音频帧加上关键信息头(>=7字节),因为FLV中AAC数据帧不包含关键信息,不能直接用于解码。
字段 | 类型 | 说明 |
---|---|---|
Frame Type | UB[4] | 视频帧的类型 1=关键帧 2=非关键帧 3~5不常用 |
CodecID | UB[4] | 视频编码格式 2 = Sorenson H.263 3 = Screen video 4 = On2 VP6 5 = On2 VP6 with alpha channel 6 = Screen video version 2 7 = AVC |
AVCPacketType | if CodecID=7 UI8 |
AVCPacket类型 0 = AVC sequence header 1 = AVC NALU 2 = AVC end of sequence |
CompostionTime | if CodecID=7 SI24 |
IF AVCPacketType == 1 Composition time offset ELSE 0 |
字段 | 类型 | 说明 |
---|---|---|
VideoTagBoby | IF FrameType == 5 UI8 ELSE ( IF CodecID == 2 H263VIDEOPACKET IF CodecID == 3 SCREENVIDEOPACKET IF CodecID == 4 VP6FLVVIDEOPACKET IF CodecID == 5 VP6FLVALPHAVIDEOPACKET IF CodecID == 6 SCREENV2VIDEOPACKET IF CodecID == 7 AVCVIDEOPACKET ) |
字段 | 类型 | 说明 |
---|---|---|
Data | IF AVCPacketType == 0 AVCDecoderConfigurationRecord IF AVCPacketType == 1 One or more NALUs (Full frames are required) |
AVCDecoderConfigurationRecord 包含着是 H.264 解码相关比较重要的 SPS 和 PPS 信息,在给 AVC 解码器送数据流之前一定要把 SPS 和 PPS 信息送出,否则的话,解码器不能正常解码。
AVCDecoderConfigurationRecord 长度为 sizeof(UI8) * (11 + sps_size + pps_size)。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NPpWrLmd-1646361402502)(v2-7d7050429cb47ebc7586cc630ed3bb97_720w.png)]
当Data为Nalu时, Data = NaluLength(指示NaluBoby的长度,4字节) + NaluBoby(不包含起始码00 00 00 01)。
当I帧包含了SPS, PPS等关键信息时,把关键信息和I帧当成一个整体进行解析。
ScriptTagBody 内容用 AMF 编码
SCRIPTDATA
由ScriptTagBody
组成, 主要包括Name
和Value
两部分:
一个string类型的SCRIPTDATAVALUE。
一个ECMA Array类型的SCRIPTDATAVALUE。
SCRIPTDATA:
FLV metadata object 保存在 SCRIPTDATA 中, 叫 onMetaData。
flv格式解析:
https://zhuanlan.zhihu.com/p/28722048