简介
FLV(Flash Video)是Adobe公司推出的⼀种流媒体格式,由于其封装后的⾳视频⽂件体积⼩、封装简单等特点,⾮常适合于互联⽹上使⽤。⽬前主流的视频⽹站基本都⽀持FLV。采⽤FLV格式封装的⽂件后缀为.flv。
FLV封装格式是由⼀个⽂件头(file header)和 ⽂件体(file Body)组成。其中,FLV body由⼀对对的(Previous Tag Size字段 + tag)组成。Previous Tag Size字段 排列在Tag之前,占⽤4个字节。Previous Tag Size记录了前⾯⼀个Tag的⼤⼩,⽤于逆向读取处理。FLV header后的第⼀个Pervious Tag Size的值为0。
Tag⼀般可以分为3种类型:脚本(帧)数据类型、⾳频数据类型、视频数据。FLV数据以⼤端序进⾏存储,在解析时需要注意。⼀个标准FLV⽂件结构如下图:
数据结构
FLV⽂件的详细内容结构如下图:
FLV header
FLV头占9个字节,⽤来标识⽂件为FLV类型,以及后续存储的⾳视频流。⼀个FLV⽂件,每种类型的tag都属于⼀个流,也就是⼀个flv⽂件最多只有⼀个⾳频流,⼀个视频流,不存在多个独⽴的⾳视频流在⼀个⽂件的情况。
下面以实际的一个文件头为例,来看看FLV Header:
结构如下:
Field | size | pos | value | comment |
签名 | u8 | 0 | 0x46 | 'F' |
签名 | u8 | 1 | 0x4c | 'L' |
签名 | u8 | 2 | 0x56 | 'V' |
版本 | u8 | 3 | 0x01 | FLV版本:0x01表示版本1 |
保留字段 | 5 (bit) | 4 | 00000(0x05: 0000 0101) | 默认0 |
音频流标识 | 1 (bit) | 4 | 1(0x05: 0000 0101) | 是否存在音频流:1有音频流 |
保留字段 | 1 (bit) | 4 | 0(0x05: 0000 0101) | 默认0 |
视频流标识 | 1 (bit) | 4 | 1(0x05: 0000 0101) | 是否存在视频流:1有视频流 |
文件头大小 | u32 | 5 | 0x09 |
FLV版本1时填写9,表明的是FLV头的⼤⼩,为后期的 |
FLV Body
就是FLV File Body。FLV File Body是由⼀连串的back-pointers + tags构成。Back-pointer表示Previous Tag Size(前⼀个tag的字节数据⻓度),占4个字节。可以看到上图中第一个Previous Tag Size:00 00 00 00 表示0。
FLV Tag
每⼀个Tag也是由两部分组成:tag header和tag data。Tag Header⾥存放的是当前tag的类型、数据区(tag data)的⻓度等信息。
Tag header
tag header⼀般占11个字节的内存空间。我们以第一个和第二个Tag分析一下,FLV tag结构如下:
Field | Type | pos | Comment |
Tag 类型 Type | u8 | 0x0d |
0x08:audio 0x09:video 0x12:Script data(脚本数据) :表明第一个Tag是脚本数据 |
数据区大小 | u24 | 0x0e |
当前tag的数据区域的大小,不包含tag header。 :第二个Previous Tag Size: 0x174 + 0x17+1=0x18c 可以看到 0x017f = 0x174 (Tag)+ 11(Header) |
时间戳 | u24 | 0x11 | 当前帧时戳,单位是毫秒。相对值,第⼀个tag的时戳总是为0 |
时间戳扩展字段 | u8 | 0x14 |
如果时戳⼤于0xFFFFFF,将会使⽤这个字节。这个字节是时戳的⾼8位, 上⾯的三个字节是低24位。 |
StreamID | u24 | 0x15 | 总是0 |
数据区域 | u[8*n] | 0x16 | 数据域数据 |
注意:
1. flv⽂件中Timestamp和TimestampExtended拼出来的是dts。也就是解码时间。Timestamp和TimestampExtended拼出来dts单位为ms。(如果不存在B帧,当然dts等于pts)
2. CompositionTime 表示PTS相对于DTS的偏移值, 在每个视频tag的第14~16字节,
显示时间(pts) = 解码时间(tag的第5~8字节) + CompositionTime (CompositionTime的单位也是ms)
Script Tag Data
该类型Tag⼜被称为MetaData Tag,存放⼀些关于FLV视频和⾳频的元信息,⽐如:duration、width、height等。通常该类型Tag会作为FLV⽂件的第⼀个tag,并且只有⼀个,跟在File Header后。该类型Tag DaTa的结构如下所示(source.200kbps.768x320.flv⽂件为例):
Audio Tag Data
⾳频Tag Data区域开始的:
- 第⼀个字节包含了⾳频数据的参数信息,
- 第⼆个字节开始为⾳频流数据。
注意:(这两个字节属于tag的data部分,不是header部分)
Field | Type | Value | comment |
音频格式 | uB4 | 10 (0xaf) |
0 = Linear PCM, platform endian 11 = Speex 14 = MP3 8-Khz |
采样率 | uB2 | 3 (0xaf) |
0 = 5.5kHz 1 = 11kHz |
采样精度 | uB1 | 1 (0xaf) |
0 = snd8Bit |
音频声道 | uB1 | 1 (0xaf) |
0 = sndMono 单声道 |
第⼆个字节开始为⾳频数据(需要判断该数据是真正的⾳频数据,还是⾳频config信息)。
Filed | Type | Comment |
音频数据 | u[8*n] |
if SoundFormat == 10 (AAC类型) |
Video Tag Data
视频Tag Data开始的:
- 第⼀个字节包含视频数据的参数信息,
- 第⼆个字节开始为视频流数据。
第⼀个字节包含视频信息,格式如下:
Field | Type | Value | Comment |
帧类型 | uB4 | 1 (0x17) |
1: keyframe (for AVC, a seekable frame)——h264的IDR,关 |
编码ID | uB4 | 7 (0x17) |
使⽤哪种编码类型: |
第⼆个字节开始为视频数据
Field | Type | Comment |
视频数据 | u[8*n] |
If CodecID == 2 |