1. FLV文件格式
FLV (Flash Vedio ) 是一种视频流媒体格式,FLV是被众多新一代视频分享网站所采用,是目前增长最快、最为广泛的视频传播格式。是在sorenson公司的压缩算法的基础上开发出来的。FLV格式不仅可以轻松的导入Flash中,速度极快,并且能起到保护版权的作用,并且可以不通过本地的微软或者REAL播放器播放视频。
2. FLV文件介绍
FLV是一个二进制文件,由文件头(FLV header)和很多tag组成。tag又可以分成三类:audio,video,script,分别代表音频流,视频流,脚本流(关键字或者文件信息之类)。
FLV文件=FLV头文件+ tag1+tag内容1 + tag2+tag内容2 + ...+... + tagN+tag内容N。
2.1 FLV Header
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] |
Shall be 0 |
TypeFlagsAudio |
UB [1] |
1 = Audio tags are present |
TypeFlagsReserved |
UB [1] |
Shall be 0 |
TypeFlagsVideo |
UB [1] |
1 = Video tags are present |
DataOffset |
UI32 |
The length of this header in bytes |
Signature: FLV 文件的前3个字节为固定的‘F’‘L’‘V’,用来标识这个文件是flv格式的.在做格式探测的时候,
如果发现前3个字节为“FLV”,就认为它是flv文件。
Version: 第4个字节表示flv版本号。
Flags: 第5个字节中的第0位和第2位,分别表示 video 与 audio 存在的情况.(1表示存在,0表示不存在)
DataOffset : 最后4个字节表示FLV header 长度。
2.2 FLV Body
Field |
Type |
Comment |
PreviousTagSize0 |
UI32 |
Always 0 |
Tag1 |
FLVTAG |
First tag |
PreviousTagSize1 |
UI32 |
Size of previous tag, including its header, in bytes. For FLV version1, this value is 11 plus the DataSize of the previous tag. |
Tag2 |
FLVTAG |
Second tag |
... |
... |
... |
PreviousTagSizeN-1 |
UI32 |
Size of second-to-last tag, including its header, in bytes. |
TagN |
FLVTAG |
Last tag |
PreviousTagSizeN |
UI32 |
Size of last tag, including its header, in bytes |
FLV header之后,就是 FLV File Body。
FLV File Body是由一连串的back-pointers + tags构成.back-pointers就是4个字节数据,表示前一个tag的size。
3. Tag 标签
FLV文件中的数据都是由一个个TAG组成,TAG里面的数据可能是video、audio、scripts。
3.1 FLV Tag
Field |
Type |
Comment |
Reserved |
UB [2] |
Reserved for FMS, should be 0 |
Filter |
UB [1] |
Indicates if packets are filtered. |
TagType |
UB [5] |
Type of contents in this tag. The following types are |
DataSize |
UI24 |
Length of the message. Number of bytes after StreamID to |
Timestamp |
UI24 |
Time in milliseconds at which the data in this tag applies. |
TimestampExtended |
UI8 |
Extension of the Timestamp field to form a SI32 value. This |
StreamID |
UI24 |
Always 0. |
AudioTagHeader |
IF TagType == 8 |
|
VideoTagHeader |
IF TagType == 9 |
|
EncryptionHeader |
IF Filter == 1 |
|
FilterParams |
IF Filter == 1 |
|
Data |
IF TagType == 8 |
Data specific for each media type. |
TagType: TAG中第1个字节中的前5位表示这个TAG中包含数据的类型,8 = audio,9 = video,18 = script data
DataSize:StreamID之后的数据长度。
Timestamp和TimestampExtended组成了这个TAG包数据的PTS信息,记得刚开始做FVL demux的时候,并没有考虑TimestampExtended的值,直接就把Timestamp默认为是PTS,后来发生的现 象就是画面有跳帧的现象,后来才仔细看了一下文档发现真正数据的PTS是PTS= Timestamp | TimestampExtended<<24。
StreamID之后的数据就是每种格式的情况不一样了,接下来对格式进行详细的介绍。
3.1.1 Script Tag
如果TAG包中的TagType==18时,就表示这个TAG是SCRIPT。
SCRIPTDATA 结构十分复杂,定义了很多格式类型,每个类型对应一种结构。
Field |
Type |
Comment |
Type |
UI8 |
Type of the ScriptDataValue. |
ScriptDataValue |
IF Type == 0 |
Script data value. |
类型在FLV的官方文档中都有详细介绍.
OnMetadata
onMetaData 是SCRIPTDATA中对我们来说十分重要的信息,结构如下表:
Property Name |
Type |
Comment |
audiocodecid |
Number |
Audio codec ID used in the file (see E.4.2.1 for available SoundFormat values) |
audiodatarate |
Number |
Audio bit rate in kilobits per second |
audiodelay |
Number |
Delay introduced by the audio codec in seconds |
audiosamplerate |
Number |
Frequency at which the audio stream is replayed |
audiosamplesize |
Number |
Resolution of a single audio sample |
canSeekToEnd |
Boolean |
Indicating the last video frame is a key frame |
creationdate |
String |
Creation date and time |
duration |
Number |
Total duration of the file in seconds |
filesize |
Number |
Total size of the file in bytes |
framerate |
Number |
Number of frames per second |
height |
Number |
Height of the video in pixels |
stereo |
Boolean |
Indicating stereo audio |
videocodecid |
Number |
Video codec ID used in the file (see E.4.3.1 for available CodecID values) |
videodatarate |
Number |
Video bit rate in kilobits per second |
width |
Number |
Width of the video in pixels |
这里面的duration、filesize、视频的width、height等这些信息对我们来说很有用.
该类型Tag又通常被称为Metadata Tag,会放一些关于FLV视频和音频的参数信息,如duration、width、height等。通常该类型Tag会跟在File Header后面作为第一个Tag出现,而且只有一个。
一般来说,该Tag Data结构包含两个AMF包。AMF(Action Message Format)是Adobe设计的一种通用数据封装格式,在Adobe的很多产品中应用,简单来说,AMF将不同类型的数据用统一的格式来描述。第一个AMF包封装字符串类型数据,用来装入一个“onMetaData”标志,这个标志与Adobe的一些API调用有,在此不细述。第二个AMF包封装一个数组类型,这个数组中包含了音视频信息项的名称和值。具体说明如下,大家可以参照图片上的数据进行理解。
第一个AMF包:
第1个字节表示AMF包类型,一般总是0x02,表示字符串,其他值表示意义请查阅文档。
第2-3个字节为UI16类型值,表示字符串的长度,一般总是0x000A(“onMetaData”长度)。
后面字节为字符串数据,一般总为“onMetaData”。
第二个AMF包:
第1个字节表示AMF包类型,一般总是0x08,表示数组。
第2-5个字节为UI32类型值,表示数组元素的个数。
后面即为各数组元素的封装,数组元素为元素名称和值组成的对。表示方法如下:
第1-2个字节表示元素名称的长度,假设为L。
后面跟着为长度为L的字符串。
第L+3个字节表示元素值的类型。
后面跟着为对应值,占用字节数取决于值的类型。
keyframes
当时在做flv demux的时候,发现官方的文档中并没有对keyframes index做描述,但是flv的这种结构每个tag又不像TS有同步头,如果没有keyframes index 的话,seek及快进快退的效果会非常差,因为需要一个tag一个tag的顺序读取。后来通过网络查一些资料,发现了一个keyframes的信息藏在SCRIPTDATA中。
keyframes几乎是一个非官方的标准,也就是民间标准.在网上已经很难看到flv文件格式,但是metadata里面不包含 keyframes项目的视频 . 两个常用的操作metadata的工具是flvtool2和FLVMDI,都是把keyframes作为一个默认的元信息项目.在FLVMDI的主页(http://www.buraks.com/flvmdi/)上有描述:
keyframes: (Object) This object is added only if you specify the /k switch. 'keyframes' is known to FLVMDI and if /k switch is not specified, 'keyframes' object will be deleted.
'keyframes' object has 2 arrays: 'filepositions' and 'times'. Both arrays have the same number of elements, which is equal to the number of key frames in the FLV. Values in times array are in 'seconds'. Each correspond to the timestamp of the n'th key frame. Values in filepositions array are in 'bytes'. Each correspond to the fileposition of the nth key frame video tag (which starts with byte tag type 9).
也就是说keyframes中包含着2个内容 'filepositions' and 'times'分别指的是关键帧的文件位置和关键帧的PTS.通过keyframes可以建立起自己的Index,然后再seek和快进快退的操作中,快速有效的跳转到你想要找的关键帧的位置进行处理。
参考内容:
http://blog.csdn.net/leixiaohua1020/article/details/17934487