@ltlovezh
2019-07-15T21:17:55.000000Z
字数 5989
阅读 2745
视频封装格式
Flv
FLV(Flash Video)是Adobe公司设计开发的一种流行的流媒体格式,由于其视频文件体积轻巧、封装简单等特点,使其很适合在互联网上进行应用。此外,FLV可以使用Flash Player进行播放,而Flash Player插件已经安装在绝大部分浏览器上,这使得通过网页播放FLV视频十分容易。FLV封装格式的文件后缀通常为“.flv”。
整体来看,FLV包括文件头(File Header)和文件体(File Body)两部分,其中文件体由一系列的Tag组成。因此一个FLV文件结构如下图所示:
其中,每个Tag前面包含一个Previous Tag Size字段,表示前面一个Tag的大小。Tag的类型可以是视频、音频和Script,每个Tag有且只能是三种类型中的一种。FLV的详细结构如下所示:
Field | Type | Comment |
---|---|---|
Signature | UI8 | Signature byte always 'F' (0x46) |
Signature | UI8 | Signature byte always 'L' (0x4C) |
Signature | UI8 | Signature byte always 'V' (0x56) |
Version | UI8 | File version (for example, 0x01 for FLV version 1) |
TypeFlagsReserved | UB[5] | 0 |
TypeFlagsAudio | UB[1] | 1 : Audio Tags are present |
TypeFlagsReserved | UB[1] | 0 |
TypeFlagsVideo | UB[1] | 1 : Video Tags are present |
DataOffset | UI32 | The length of this flv file header in bytes |
F
、L
、V
,用来标识当前文件是flv格式。若发现前3个字节为“FLV”,就认为它是flv文件。00 00 00 09
。所以一般情况下,同时包含音频和视频的Flv File Header的16进制(大端模式)为46 4C 56 01 05 00 00 00 09
Flv的主体是Tag序列,Flv Tag的前11
字节是固定的Tag Header
,详细结构如下所示:
Field | Type | Comment |
---|---|---|
Reserved | UB[2] | Reserved for FMS, should be 0 |
Filter | UB[1] | Indicates if packets are filtered. 0 : No pre-processing required. 1 : Pre-processing (such as decryption) of the packet is required before it can be rendered. Shall be 0 in unencrypted files, and 1 for encrypted tags. |
TagType | UB[5] | Tag Type , 8 : audio , 9 : video , 18 : script data |
DataSize | UI24 | Length of the Tag Body. Number of bytes after StreamID to end of Tag (length of tag – 11) |
Timestamp | UI24 | Time in milliseconds at which the data in this tag applies. This value is relative to the first tag in the FLV file, which always has a timestamp of 0. |
TimestampExtended | UI8 | Extension of the Timestamp field to form a SI32 value. This field represents the upper 8 bits, while the previous Timestamp field represents the lower 24 bits of the time in milliseconds. |
StreamID | UI24 | Always 0 |
XXTagHeader | AudioTagHeader (TagType == 8) VideoTagHeader (TagType == 9) |
音频Header or 视频Header |
Data | AudioData(TagType == 8) VideoData(TagType == 9) ScriptData(TagType == 18) |
Data specific for each media type |
Flv File Header之后紧跟的第一个Tag一般是Script Tag
,有且只有一个。该类型Tag又通常被称为Metadata Tag
,存储一些关于Flv音频和视频的元数据信息,如:duration、width、height等,其结构如下所示:
第一个AMF包:
第1个字节表示AMF类型,一般总是0x02,表示字符串。第2-3个字节为UI16类型值,标识字符串的长度,一般总是0x000A(onMetaData长度)。后续字节则为具体字符串,一般总为“onMetaData”(
6F 6E 4D 65 74 61 44 61 74 61
)。
第二个AMF包:
第1个字节表示AMF类型,一般总是0x08,表示数组。第2-5个字节为UI32类型值,表示数组元素的个数。后面即为各数组元素的封装,数组元素为名称和值组成的Key-Value。常见的数组元素如下所示:
Key | Type | Value |
---|---|---|
duration | Number | 时长 |
filesize | Number | 文件大小 |
width | Number | 视频帧宽度 |
height | Number | 视频帧高度 |
videodatarate | Number | 视频码率 |
framerate | Number | 视频帧率 |
videocodecid | Number | 视频编码方式,如:Avc、Hevc |
audiocodecid | Number | 音频编码方式 |
audiodatarate | Number | 音频码率 |
audiosamplerate | Number | 音频采样率 |
audiosamplesize | Number | 音频采样位数 |
audiochannels | Number | 音频单通道 or 双通道 |
stereo | Boolean | 是否为立体声,1:立体声(双声道) |
有一点特别重要:Script Tag
的两个AMF数据是紧跟在Script Tag
11字节的Tag Header后面的。
参考之前Flv Tag的结构,若TagType等于8,则表示当前是音频Tag,StreamID之后的数据就是AudioTagHeader,AudioTagHeader结构如下:
Field | Type | Comment |
---|---|---|
SoundFormat | UB[4] | Format of SoundData. The following values are defined: 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 Formats 7, 8, 14 and 15 are reserved. AAC is supported in Flash Player 9.0 and higher. Speex is supported in Flash Player 10 and higher. |
SoundRate | UB[2] | Sampling rate. The following values are defined: 0 : 5.5 kHz 1 : 11 kHz 2 : 22 kHz 3 : 44 kHz |
SoundSize | UB[1] | Size of each audio sample. This parameter only pertains to uncompressed formats. 0 : 8-bit samples 1 : 16-bit samples |
SoundType | UB[1] | Mono or stereo sound 0 : Mono sound 1 : Stereo sound |
AACPacketType | UI8 (if SoundFormat == 10) | What the following values are ? 0 : AAC sequence header 1 : AAC raw |
AudioTagHeader的第1个字节,也就是紧跟在StreamID后面的1个字节包含着音频类型、采样率、采样位数、声道等基本信息。
AudioTagHeader之后就是AudioData数据了。但是这里有个特例,如果音频格式(SoundFormat)是10(AAC),AudioTagHeader中会多出1字节的AACPacketType结构,这个字段表示AACAudioData的类型:
如果AACPacketType
等于0,那么紧跟在AudioTagHeader后面的Data就是AAC sequence header,AAC sequence header包含了AudioSpecificConfig,AudioSpecificConfig包含着一些更加详细的音频信息。
一般情况下,AAC sequence header只会出现1次,而且是第一个Audio Tag。为什么需要这种Tag,因为如果是AAC音频,需要在每帧AAC ES流前面添加7字节的ADST头,这是解码器通用的格式,就是要把AAC的纯ES流打包成ADST格式的AAC文件,解码器才能正常播放。在打包ADST的时候,需要samplingFrequencyIndex信息,而samplingFrequencyIndex最准确的信息就在AudioSpecificConfig中,所以就需要对AudioSpecificConfig进行解析得到samplingFrequencyIndex。
如果AACPacketType
等于1,那么紧跟在AudioTagHeader后面的Data就是AAC raw,即音频ES流。
有一点特别重要:Audio Tag
的数据是紧跟在Audio Tag
11字节的Tag Header后面的。
参考之前Flv Tag的结构,若TagType等于9,则表示当前是视频Tag,StreamID之后的数据就是VideoTagHeader,VideoTagHeader结构如下:
Field | Type | Comment |
---|---|---|
Frame Type | UB[4] | Type of video frame. The following values are defined: 1 : key frame (for AVC, a seekable frame) 2 : inter frame (for AVC, a non-seekable frame) 3 : disposable inter frame (H.263 only) 4 : generated key frame (reserved for server use only) 5 : video info/command frame |
CodecID | UB[4] | Codec Identifier. The following values are defined: 2 : Sorenson H.263 3 : Screen video 4 : On2 VP6 5 : On2 VP6 with alpha channel 6 : Screen video version 2 7 : AVC |
AVCPacketType | UI8(if CodecID == 7) | The following values are defined: 0 : AVC sequence header 1 : AVC NALU 2 : AVC end of sequence (lower level NALU sequence ender is not required or supported) |
CompositionTime | SI24(if CodecID == 7) | IF AVCPacketType == 1 Composition time offset else 0 |
VideoTagHeader的第1个字节,也就是紧跟在StreamID后面的1个字节包含着视频帧类型及视频编码信息。
VideoTagHeader之后就是VideoData数据了,当然就像音频AAC一样,这里也有特例:如果视频格式是AVC(H.264),VideoTagHeader中会多出4个字节信息:AVCPacketType和CompositionTime。其中,AVCPacketType表示AVCVideoData的类型:
如果AVCPacketType
等于0,那么紧跟在VideoTagHeader后面的Data就是AVCDecoderConfigurationRecord,它包含着解码H264至关重要的sps和pps信息,再给AVC解码器送数据流之前一定要把sps和pps信息送出,否则解码器就不能正常解码。AVCDecoderConfigurationRecord在FLV文件中一般情况也只出现1次,也就是第一个Video Tag。
如果AVCPacketType
等于1,那么紧跟在VideoTagHeader后面的Data就是NALU了(可能包含多个NALU),NALU存储的是Slice,多个Slice构成一帧图像,一个Video Tag必须至少包含一个完整的帧图像。
有一点特别重要:Video Tag
的数据是紧跟在Video Tag
11字节的Tag Header后面的。