FLV 是 FLASH VIDEO 的简称,FLV 流媒体是随着Flash MX 的推出发展而来的视频格式。FLV 一般由文件头(FLV header) 和文件体(FLV body) 组成。其中文件体(FLV body)由一些列tag组成,tag又可分成三类:audio/video/script,分别代表音频流、视频流、脚本流(关键字或文件信息之类)。 在 FLV 文件中,每种 tag 类型都由一个单独的流组成,即在 FLV 文件中最多有一个视频流和一个音频流,对同一种类型的流,FLV 中不能够定义多个独立的流。 与 SWF 文件不同,FLV 文件以大字节序存储多字节。比如,0x300(0x12C) 在 SWF 文件中的字节序为 0x2C 0x01,在FLV 文件中则为 0x01 0x2C。
FLV 文件的整体结构如下图所示:
FLV 视频标准格式标准
FLV Header
以 FLV Header 46 4C 56 01 05 00 00 00 09
为例:
Field | Type | Comment |
---|---|---|
Signature | 1 byte | 必须为’F’(0x46) |
Signature | 1 byte | 必须为’L’(0x4C) |
Signature | 1 byte | 必须为’V’(0x56) |
(版本)Version | 1 byte | 通常为0x01 |
TypeFlagsReserved | 5 bits | 必须为0 |
TypeFlagsAudio | 1 bit | 表示是否含有音频 |
TypeFlagsReserved | 1 bit | 必须为0 |
TypeFlagsVideo | 1 bit | 表示是否含有视频 |
DataOffset | 4 bytes | 文件头部的大小(从文件开始位置到body的偏移量),通常为9 |
FLV Header 的前三个字节是固定的FLV
的 ASCII 码的值0x46 0x4C 0x56
; 接下来的一个字节表示 FLV 的版本号,例如 0x01 代表 FLV 版本号为 1。第 5 个字节中的第0位和第2位分别表示video和audio的存在情况(1表示存在,0表示不存在),其余6位必须为0.最后的4字节表示FLV Header的长度,对于version 1,此处为9.
FLV File Body
FLV Header 之后,FLV 文件的剩余部分称为 Body,它是由tag组成,它们交替如下:
Field | Type | Comment |
---|---|---|
PreviousTagSize0 | 4 bytes | 总是0 |
Tag1 | FLVTAG结构 | 第一个tag |
PreviousTagSize0 | 4 bytes | 上一个tag的大小,包含了tag的头部。对FLV版本1来讲,它的值等于上一个tag的数据大小+11 |
Tag2 | FLVTAG结构 | 第二个tag |
… | … | … |
PreviousTagSizeN - 1 | 4 bytes | 倒数第二个tag的大小 |
TagN | FLVTAG结构 | 最后一个tag |
PreviousTagSizeN | 4 bytes | 最后一个tag的大小 |
FLV tags
FLV tag格式如下:
Field | Type | Comment |
---|---|---|
Tag类型(TagType) | 1 bytes | 8:音频、9:视频、18:script数据 |
数据大小(DataSize) | 3 bytes | 数据字段的长度 |
时间戳(Timestamp) | 3 bytes | 毫秒为单位,第一个tag时,该值总是0 |
时间戳扩展(TimeStampExtended) | 1 bytes | 时间戳扩展为4bytes,代表高8位,很少用到 |
流ID | 3bytes | 总是0 |
数据(Data) | 音频、视频或script | 数据实体 |
以 Tag 12 00 12 A9 00 00 00 00 00 00 00 02 00 0A……
为例,0x12
代表该 tag 为script data,00 12 A9
代表该 tag 的 DataSize 为 681 byte,00 00 00
代表该 tag 的 TimeStamp 为 0,00
代表该 tag 的 TimeStampExtended 为 0,StreamID 总是 0,接下来的 681 byte 为script data 的内容。
播放过程中,FLV tag的时间信息完全依赖于 FLV 时间戳,内置的其他时间信息都被忽略掉。
Audio tags
Audio Tag 与 SWF 文件格式中的 DefineSound Tag 类似。它们的 Payload 数据除了额外的Nellymoser 8-kHz
格式外是相同的,该格式在 SWF 格式中不被允许。关于 SWF 文件格式的介绍,请看SWF(File Format Sepecification).
Audio Data
数据大小 | 名称 | 备注 |
---|---|---|
bit[4] | Sound Format | 2(0x2)-MP3;3(0x3)-PCM;10(0xA)-AAC |
bit[2] | Sample Rate | 0(0x0)-5500Hz;1(0x1)-11025Hz;2(0x2)-22050Hz;3(0x3)-44100Hz |
bit[1] | Sample Size | 0(0x0)-8bit;1(0x1)-16bit |
bit[1] | Channel Count | 0(0x0)-Mono;1(0x1)-Stereo |
byte[Payload Size -1] | Sound Data | 音频数据,随 Sound Format 不同,格式也不同 |
如果 Sound Format 为 0xA(AAC),Sound Data 为:
数据大小 | 名称 | 备注 |
---|---|---|
byte | Type | 0(0x0)-Sequence Header;1(0x1)-Raw;一般 Sequence Header 为第一个 Audio Tag,并且全文件只出现一次 |
bit[5] | Object Type | 1(0x1)-AAC Main;2(0x2)-AAC LC;31(0xFE)-Escape |
bit[6] | Extend Object Type | 如果 Object Type 为 0xFE |
bit[4] | Sample Frequency Index | 0~12分别为96000,88200,64000,48000,44100,32000,24000,22050,16000,12000,11025,8000,7350 |
uint24 | Sample Frequeny | 如果 Sample Frequency Index 为 15,此处为 Sample Frequency |
bit[4] | Channel Count | 声道数,4 为 Stereo |
AACAUDIODATA
AAC
格式在Flash Player
中被支持。
Field | Type | Comment |
---|---|---|
AACPacketType | UI8 | 0:AAC sequence header;1:AAC raw |
Data | UI8[n] | if AACPacketType == 0 AudioSpecificConfig else if AACPacketType == 1 Raw AAC frame data |
Video tags
Video Tag 与 SWF 文件格式中的 VideoFrame Tag 类似,它们的 Payload 数据是同一的。关于 SWF 文件格式的介绍,请看SWF(File Format Specification)。
以09 00 00 2D 00 00 00 00 00 00 00 17 00 00 00 00 01 4D 40 1F FF E1 00 19 67 4D 40 ……
为例,09
表示 Tag Type 为 Video Tag;00 00 2D
表示 DataSize 为 45;00 00 00
表示 Timestamp 为 0;00
表示 TimestampExtended 为 0;00 00 00
表示 StreamID 为 0;17
中的 8 bit,其中前 4 bit1
表示 FrameType 为 keyframe,后 4 bit7
表示 CodecID 为 AVC;之后的 45 byte 为 VideoData;
Video Data
Field | Type | Comment |
---|---|---|
帧类型(FrameType) | 4bits | 1.关键帧 2.inter frame(for AVC, a non-seekable frame) 3.disposable inter frame(H.263 only) 4.generated keyframe(reserved for serve use only) 5.video info/command frame |
CodeID | 4bits | 1:JPEG 2:H.263 3:Screen video 4:VP6 5:VP6 6:Screen video version 2 7:AVC |
视频数据(VideoData) | if CodecID == 7 AVCVIDEOPACKET | Video frame payload or UI8(see note following table) |
如果 FrameType = 5,此时的 VideoData 含义如下:
- 0 = Start of client-side seeking video frame sequence
- 1 = End of client-side seeking video frame sequence
AVCVIDEOPACKET
AVCVIDEOPACKET 携带一个AVC video data。
Field | Type | Comment |
---|---|---|
AVCPacketType | 1 byte | 0:AVC sequence header 1:AVC NALU 2:AVC end of sequence |
CompositionTime | SI24 | if AVCPacketType == 1 CompositionTime offset else 0 |
Data | UI8[n] | if AVCPacketType == 0 AVCDecoderConfigurationRecord else if AVCPacketType == 1 one or more NALUs |
Data tags
onMetaData
- duration : 一个 DOUBLE 指定了整个文件的总时长,单位 seconds
- width : 一个 DOUBLE 指定了视频的宽,单位 pixel
- height : 一个 DOUBLE 指定了视频的高,danwei pixel
- videodatarate : 一个DOUBLE 指定了 video bit rate,单位 kilobits per second
- framerate : 一个DOUBLE 指定了每秒的 frame 数
- videocodeid : 一个DOUBLE 指定了 video codec ID
- audiosamplerate : 一个 DOUBLE 指定了音频采样的分辨率
- stereo : 一个 BOOL 指定了data 是否是stereo
- filesize : 一个 DOUBLE 指定了文件的总大小,单位 byte.
FFmpeg FLV Demuxer源码分析
FFmpeg 中关于flv demuxer的定义如下:
1 2 3 4 5 6 7 8 9 10 11 12 |
|
其中的flv_read_header
是分析 FLV 的header函数,分析代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
|
FLV中关于tag的处理使用flv_read_packet
,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
|