FLV格式解析

2017-03-11

版权声明:本文为作者原创文章,可以随意转载,但必须在明确位置表明出处!!!

FLV介绍

FLV(Flash Video)是Adobe公司设计开发的一种流行的流媒体格式,由于其视频文件体积轻巧、封装简单等特点,使其很适合在互联网上进行应用。此外,FLV可以使用Flash Player进行播放,而Flash Player插件已经安装在全世界绝大部分浏览器上,这使得通过网页播放FLV视频十分容易。目前主流的视频网站如优酷网,土豆网,乐视网等网站无一例外地使用了FLV格式。FLV封装格式的文件后缀通常为“.flv”

FLV封装格式

总体来将FLV格式分为两大部分,分别是FLV文件头(FLV HEADER)和FLV BODY,FLV BODY里包涵多个Tag标签。我将结合一个FLV视频文件来辅助讲解FLV封装格式,以便能做到理论和实践的结合加深对FLV格式的理解,在开始之前以一张图来呈现FLV的封装格式:

从上图可以看出FLV BODY包涵了多个Tag标签,每个Tag标签的开始都是上一个Tag标签的大小+11个字节,这11个字节就是Tag Header的大小,每个Tag标签里同样包涵了两部分内容,分别是Tag Header, Tag Data,这里我们需要特别注释的是Tag Header里的第一个字节Type,如果这个字节是0x08表示该Tag是一个视频数据帧,如果是0x09表示该Tag是一个音频数据帧,如果是0x12则表示该Tag是一个控制帧, 控制帧一般是FLV HEADER后第一个出现的Tag标签,而且只出现一次。改Tag包涵了一些视频文件的信息,如像素宽高,视频时长等等信息。既然type有三种类型那么它们所对应的Tag Data结果也会有所不同。下面介绍一下三种不通类型的Tag Data结构

Script Data结构

  • AFM1:AFM1包第一个字节总是0x02表示字符串,紧跟着的两个字节表示该字符串的长度,一般为0x000A,表示向后10个字节的字符串一般为“onMetaData”,这里的0x02表示字符串和后面两个字节表示字符串长度是根据官方文档video_file_format_spec_v10_1.pdf所规定的,如下图:

    从上图可以看到2表示String类型,而String类型表示如下图的结构:

    我们可以看到SCRIPTDATASTRING结构包涵两个字段,一个是StringLength,一个是StringData,StringLength是一个UI16表示一个16位无符号的整形也就是两个字节,所以ox000A就代表了字符串的长度,如果你想要了解更多的细节可以仔细阅读官方文档。

  • AFM2:AFM2包第一个字节一班为0x08表示ECMA array是一个数组类型,ECMA array的结构如下:

    从上图我们可以知道ECMA array结构包涵了三个字段,

  • ECMAArrayLength: 数组长度,4个字节
  • Variables: 变量,它的类型是一个数组,数组里面包涵列属性名和属性值
  • List Terminator: 列表结束字段,改类型是一个SCRIPTDATAOBJECTEND类型,这个类型结构是固定的三个字节,内容是0x00, 0x00, 0x09,如下图:

好了讲到这里我们队Script Data结构有了一些认识, 下面就通过一个flv格式文件来验证一下是否个上面所说的一致。如下图:

我们先看上图中第一行的前9个字节,这9个字节就表示FLV HEADER,0x46,0x4C,0x56(FLV)这三个字节表示文件标识符,我们这里主要看一下Flags字节,在上图中这个字节的值为0x05 = 0000 0101从这里可以看出第6个字节和第8个字节都是1则表示该文件既包含音频也包含视频。从第9个字节往后就是我们的FLV BODY部分了, BODY部分上面已经介绍了是由多个Tag组成的,从第9个字节向后数4个字节(0x00,0x00,0x00,0x00)就是我们的Previous Tag Size大小了,这里的大小是0是因为它是第一个Tag在它的前面没有其它Tag,所以自然为0了。接下来就是最关键的地方了,Tag中的Type字段值表明了该Tag是什么类型的Tag,从下图中我们可以看到该Tag的type值尾0x12,那么它表示该Tag是一个Scrip Tag。

紧跟0x12的三个字段就是DataSize了。

  • DataSize: 0x00,0x02,0xA9 = 681表示该Tag的Tag Data大小为681个字节
  • TimeStamp: 0x00,0x00,0x00 = 0时间戳
  • TimeStampEx: 0x00 = 0
  • StreamId: 0x00,0x00,0x00 = 0

接下来就是Tag Data部分了,记住了这个Tag Data部分的大小是681个字节,接下来的0x02表示字符串,0x00 0x0A表示字符串长度为10,接下来的10个字节就是具体的字符串“onMetaData”正好10个字符如下图:

这就是AFM1这个包的内容了,跟上面所讲是一致的。再来看看AFM2如下图:

可以看到AFM2的第一个字节确实是0x08,数组的长度是0x00,0x00,0x00,0x19 = 25,这个时候我们看看数组里是如何存储的,从上文AFM2的介绍和结构图我们知道Variables是一个数组结构,该结构如下图:

该结构包涵了两个字段:

  • PropertyName: 属性名,类型是SCRIPTDATASTRING类型,从文章的前半部我们知道SCRIPTDATASTRING也包涵了两个字段分别是2个字节的StringLength,和一个StringData
  • PropertyValue: 属性值,类型是SCRIPTDATAVALUE类型。SCRIPTDATAVALUE结构如下:

所以从这里我们可以知道0x00,0x0F = 15表示字符串长度,也就是属性名metadatacreator如下图:

接下来就是SCRIPTDATAVALUE类型,该类型占一个字节,也就是0x02,而0x02表示String类型,所以又会到SCRIPTDATASTRING结构了,0x00, 0x03 = 3表示器字符串长度,所以接下来的三个字节表示属性值0x69,0x6B,0x75 = “iku”,所以数组的第一个属性信息是metadatacreator = iku,后面就都是依据此规则解析出属性名和属性值。直到最后为0x00,0x00,0x09则表示到达数组结尾了。到这里Script Tag结构就介绍完了,和我们文章开始讲的是一致的。

okay, 上文提到了Script Tag 的Tag Data大小是681个个字节,然后我们跳到Script Tag结尾,如下图:

从这个图中我们可以看到Script Tag的结尾部份的确是0x00,0x00,0x09,到这里就表示Script Tag结束了,那么接下来就是下一个Tag的开始了,0x00,0x00,0x02,0xB4表示的是上一个Tag的长度 + 11个Tag Header的长度,0x00,0x00,0x02,0xB4 = 692 = 681 + 11正好是上一个Tag Data的大小加上11个Tag Header长度。接下来就看该Tag是什么类型的Tag了,这里的type = 0x09则表示该Tag是个视频数据帧,视频帧的长度是0x00,0x00,0x2D = 45就是该视频帧Tag Data的长度如下图红线所标示出来的就是Tag Data的长度:

下面我看来看看Video Tag结构

Video Tag结构


第一个字节的前4位表示帧类型,后4位表示视频编码类型,下图中是目前所支持的帧类型,和视频编码类型。

上图红线表示出来的是Video Tag Data部分, 它的第一个字节是0x17 = 0001 0111,所有前4为的值为1,着表示该视频帧的类型是key frame (for AVC, a seekable frame)关键帧,后四为的值是7则表示它的视频编码类型是AVC类型。接下来的数据就是该视频帧的数据了,直到红线标识结尾都是该视频帧的数据。紧跟着红线结尾的数据这表示下一个Tag帧数据了,0x00,0x00,0x00,0x38 = 56 = 45 + 11正好是上一个Video Tag的大小,这里我们看看该Tag是什么类型的Tag, 该Tag的type = 0x08者表示该Tag帧是一个音频帧,音频帧的结构如下。

Audio Tag结构


音频帧的第一个字节的前4位表示音频编码类型,后四位分别表示采样率,精度,类型,下面的表格中是目前为止所支持的音频编码类型:

音频采样率:

从上表可以看出FLV视频封装格式不支持48kHz的采样率

音频采样精度:

音频类型:

下图红线标出的地方就是Audio Tag Data的大小为9个字节,它的第一个字节是0xAF = 1010 1111,那么它的音频编码类型就是1010 = 10这表示音频编码类型是AAC, 采样率11 = 3表示它的采样率为44kHz,采样精度是1表示使用的是16bit的采样精度,音频类型的值为1表示音频类型为sndStereo;到此我们就介绍完了FLV的封装格式了,有兴趣的朋友可以自己动手试试,下面是我用MFC写的一个FLV格式解析工具。

格式分析工具

格式分析工具是用VS 2010MFC开发的,开发工具主要是对格式协议的进一步理解

项目地址:https://github.com/Gavinxyj/AVAnalysisTools


推荐我的微信公众号:爱做饭的老谢


上一篇:视频YUV/RGB格式解析
下一篇:H.264码流协议解析