flv格式学习

 FLV(Flash Video)是现在非常流行的流媒体格式,由于其视频文件体积轻巧、封装播放简单等特点,使其很适合在网络上进行应用,目前主流的视频网站无一例外地使用了FLV格式。另外由于当前浏览器与Flash Player紧密的结合,使得网页播放FLV视频轻而易举,也是FLV流行的原因之一。

    FLV视频格式是Adobe公司设计开发的,目前已经免费开放,现在的版本是v10。下面我们就了解一下FLV文件格式。

    FLV是流媒体封装格式,我们可以将其数据看为二进制字节流。总体上看,FLV包括文件头(File Header)和文件体(File Body)两部分,其中文件体由一系列的Tag及Tag Size对组成。因此一个FLV文件看上去是下面的结构:

flv格式学习_第1张图片

    其中,Previous Tag Size紧跟在每个Tag之后,占4个字节表示一个UI32类型的数值,表示前面一个Tag的大小。需要注意的是,Previous Tag Size #0的值总是为0Tag类型包括视频、音频和Script,且每个Tag只能包含一种类型的数据。下面我们看看File HeaderTag的具体结构,为了方便大家理解,我贴一个实际FLV文件的字节流图片,图片中把不同部分区分了颜色。

flv格式学习_第2张图片

 

一、File Header结构

    File Header在当前版本中总是由9个字节组成,如图中蓝色区域所示。

    第1-3字节为文件标识(Signature),总为“FLV”(0x46 0x4C 0x56),如图中紫色区域。

    第4字节为版本,目前为1(0x01)。

    第5个字节的前5位保留,必须为0。

    第5个字节的第6位表示是否存在音频Tag。

    第5个字节的第7位保留,必须为0。

    第5个字节的第8位表示是否存在视频Tag。

    第6-9个字节为UI32类型的值,表示从File Header开始到File Body开始的字节数,版本1中总为9。

 

二、Previous Tag Size结构

    如图中红色位置所示。

 

三、Tag结构

    Tag包括Tag Header和Tag Data两部分。不同类型的Tag的Header结构是相同的,但是Data结构各不相同。如图中绿色和黄色区域分别表示Tag Header数据和Tag Data数据。

    当前版本的Tag Header结构占用11个字节。

    第1个字节表示Tag类型,包括音频(0x08)、视频(0x09)和script data(0x12),其他类型值被保留。

    第2-4字节为UI24类型的值,表示该Tag Data部分的大小。

    第5-7字节为UI24类型的值,表示该Tag的时间戳(单位为ms),第一个Tag的时间戳总是0。

    第8个字节为时间戳的扩展字节,当24位数值不够时,该字节作为最高位将时间戳扩展为32位值。

    第9-11字节为UI24类型的值,表示stream id,总是0。

    后面的字节为Tag Data数据,Data的大小由第2-4字节的数值指示,根据第1个字节指示的Tag类型,按照不同的结构解析Tag Data。下面分别介绍。

 

四、Audio Tag Data结构

    音频Tag开始的第1个字节包含了音频数据的参数信息,从第2个字节开始为音频流数据。

    第1个字节的前4位的数值表示了音频数据格式,各值代表的意义大家可以查阅Adobe公司发布的FLV格式说明文档(可以到我的磁盘空间的“资料”目录去下载 http://e.ys168.com/?tinyfun)。

    第1个字节的第5-6位的数值表示采样率,0 = 5.5 kHz,1 = 11 kHz,2 = 22 kHz,3 = 44 kHz。

    第1个字节的第7位表示采样精度,0 = 8bits,1 = 16bits。

    第1个字节的第8位表示音频类型,0 = mono,1 = stereo。

 

五、Video Tag Data结构

    视频Tag也用开始的第1个字节包含视频数据的参数信息,从第2个字节开始为视频流数据。

    第1个字节的前4位的数值表示帧类型。

    第1个字节的后4位的数值表示视频编码ID,1 = JPEG(现已不用),2 = Sorenson H.263,3 = Screen video,4 = On2 VP6,5 = On2 VP6 with alpha channel,6 = Screen video version 2。

 

六、Script Tag Data结构

    该类型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个字节表示元素值的类型。

       后面跟着为对应值,占用字节数取决于值的类型。

 

    OK,到此FLV文件结构讲完了,希望我已经讲清楚了:)另外我自己写了一个小工具,用它可以查看一个FLV文件的结构,并且能够分析各个字段对应字节的具体值,截图如下。目前还有一些小问题需要完善,后面我会加一个使用说明。想用的朋友可以到我磁盘空间的“工具”目录去下载。(http://tinyfun.ys168.com/)

flv格式学习_第3张图片




flv文件的格式其实网上资料还是不少,但是怎么封装成flv却不多。看了不少资料,找到了一个觉得还比较靠谱的:http://www.cnblogs.com/chef/archive/2012/07/18/2597279.html

其实flv还是挺简单的一个视频格式,下面就来先谈一谈FLV的格式吧。

 

FLV是一个二进制文件,简单来说,其是由一个文件头(FLV header)和很多tag组成(FLV body)。tag又可以分成三类:audio,video,script,分别代表音频流,视频流,脚本流,而每个tag又由tag header和tag data组成。

文件头由9bytes组成

 

前3个bytes是文件类型,总是“FLV”,也就是(0x46 0x4C 0x56)。第4btye是版本号,目前一般是0x01。第5byte是流的信息,倒数第一bit是1表示有视频(0x01),倒数第三bit是1表示有音频(0x4),有视频又有音频就是0x01 | 0x04(0x05),其他都应该是0。最后4bytes表示FLV 头的长度,3+1+1+4 = 9

flv格式学习_第4张图片

 

FLV header后面就是FLV body,FLV body由若干个tag 组成。每一个tag第一部分是tag header,tag header长度为11bytes,但是每个tag header前面有4bytes记录着上一个tag的长度,此待会儿再说。tag header的第1个byte为记录着tag的类型,音频(0x8),视频(0x9),脚本(0x12);第2到4bytes是数据区的长度,也就是tag data的长度;再后面3个bytes是时间戳,单位是毫秒,类型为0x12则时间戳为0,时间戳控制着文件播放的速度,可以根据音视频的帧率类设置;时间戳后面一个byte是扩展时间戳,时间戳不够长的时候用;最后3bytes是streamID,但是总为0,再后面就是数据区了(tag data),也即是h264的裸流,tag header 长度为1+3+3+1+3=11。

flv格式学习_第5张图片

0x12前面的00 00 00 00 就是刚刚说的记录着上一个tag的长度的4bytes,这里因为前面没有tag,所以为0。

 

tag data如果是音频数据,第一个byte记录audio信息:

前4bits表示音频格式(全部格式请看官方文档):

·0 -- 未压缩

·1 -- ADPCM

·2 -- MP3

·4 -- Nellymoser 16-kHz mono

·5 -- Nellymoser 8-kHz mono

·10 -- AAC

下面两个bits表示samplerate:

·0 -- 5.5KHz

·1 -- 11kHz

·2 -- 22kHz

·3 -- 44kHz

下面1bit表示采样长度:

·0 -- snd8Bit

·1 -- snd16Bit

下面1bit表示类型:

·0 -- sndMomo

·1 -- sndStereo

之后是数据。

如果是视频数据,第一个byte记录video信息:

前4bits表示类型:

·1-- keyframe

·2 -- inner frame

·3 -- disposable inner frame (h.263 only)

·4 -- generated keyframe

后4bits表示解码器ID:

·2 -- seronson h.263

·3 -- screen video

·4 -- On2 VP6

·5 -- On2 VP6 with alpha channel

·6 -- Screen video version 2

·7 -- AVC (h.264)

之后是数据。

flv格式学习_第6张图片

 

 

 

如果是AAC和AVC的音视频,则在放入数据前有一个音频和视频的配置信息需要写入前两个tag,等会再说。之前说每个tag前面会有一个记录上个tag长度的4个bytes(previous tag size),整个的flv文件其实是:FLV header + previous tag size0 + tag1 + previous tag size1 + tag2 + previous tag size2 + ... +tagN + previous tag sizeN。第一个previous tag size因为前面没有tag,所以为0,其他的总是记录着前面一个tag 长度(tag data size + tag header size)。

flv格式学习_第7张图片

 

 

如果tag data是脚本数据,Script Tag Data,该类型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个字节表示元素值的类型。

   后面跟着为对应值,占用字节数取决于值的类型

flv格式学习_第8张图片

 

 

到此flv格式的解析就差不多了,如有写错的地方请指出。

 

附上一个网友写的flv的查看工具:http://download.csdn.net/detail/yeyumin89/4534822 

flv文件的格式其实网上资料还是不少,但是怎么封装成flv却不多。看了不少资料,找到了一个觉得还比较靠谱

前面写了flv文件的解析,有h264裸流的话就开始封装吧。网上大多数都是用ffmeg库来做这个工作的,哎,学习资料少学不会,还是自己动手吧。

封装前要先了解下h.264格式,只需要知道一点点就可以了,我看了h.264官方文档,我靠,3百多页,还全是中文,什么,是中文?既然是中文的我就勉强看下吧,我靠,看起来还很复杂的,果断不看了,不需要,也没时间,我又不做解码,这东西具体步骤资料又少,基本都是那一两篇转来转去,这还要感谢我上一篇提到的那个连接的兄弟,记录下过程,不然以后就忘干净了。
 
h264是一个个NALU单元组成的,每个单元以00 00 01 或者 00 00 00 01分隔开来,每2个00 00 00 01之间就是一个NALU单元。我们实际上就是将一个个NALU单元封装进FLV文件
flv格式学习_第9张图片
 
每个NALU单元开头第一个byte的低5bits表示着该单元的类型,即 NAL nal_unit_type:
#define NALU_TYPE_SLICE 1
#define NALU_TYPE_DPA 2
#define NALU_TYPE_DPB 3
#define NALU_TYPE_DPC 4
#define NALU_TYPE_IDR 5
#define NALU_TYPE_SEI 6          
#define NALU_TYPE_SPS 7
#define NALU_TYPE_PPS 8
#define NALU_TYPE_AUD 9
#define NALU_TYPE_EOSEQ 10
#define NALU_TYPE_EOSTREAM 11
#define NALU_TYPE_FILL 12
每个NALU第一个byte & 0x1f 就可以得出它的类型,比如上图第一个NALU:67 & 0x1f = 7,则此单元是SPS,第三个:68 & 0x1f = 8,则此单元是PPS。
 
前一章说到如果数据是AAC或者AVC的话,则有一个音频和视频的配置信息需要写入前两个tag(metadata之后),AAC音频就不说了,在ISO-14496-3 Audio 中有描述,给一张图。
flv格式学习_第10张图片
 
说下AVC视频流的configuretion,ISO-14496-15 AVC file format 有详细描述,先给两张图,一张是说明,一张是实际截图。
flv格式学习_第11张图片
 
flv格式学习_第12张图片
这个例子是对应我第一个截图来的,一般h264数据最开始的两个NALU就是PSP和PPS,但是我现在还没有明白为什么我的那个h264裸流在开始的时候会有两个SPS、PPS,而且之后数据还会不时的出现,但是我没有管这个,依然只各弄了一个进去,其他的忽略掉了,反正多余的我都忽略了,也没发现有什么错。反正首先把音视频的配置信息封进metadata之后的tag,然后就可以封数据了。再说下元数据,flv header之后就是它了,再之后就是音视频配置信息,再后面就是音视频数据,元数据前一章说了是amf格式的,安格式封就行了,测试其实没有元数据视频也可以正常播放,等会再简单说下amf吧。
 
 
现在开始封装h264数据吧,前一章提到了flv关于AVC的格式,除开元数据,其他数据是:一个byte的video信息+一个byte的AVCPacket type+3个bytes的无用数据(composition time,当AVC时无用,全是0)+ 4个bytes的NALU单元长度 + N个bytes的NALU数据,所以包头数据长度信息是刚才提到的信息的总和长度。要强调下,当音视频配置信息tag的时候,是没有4个bytes的NALU单元长度的
AVC的配置信息时,先上一个图,
flv格式学习_第13张图片
17 -- 高4bits:1,keyframe。 低4bits:7,代表AVC。 后面一个byte 0x00,AVCPacket type,代表AVC sequence header。后3个bytes无意义,之后就是decoder configuration record的内容了。 图中绿色后面 00 00 00 28就是前面tag的总长度
 
当NALU第一个byte xx & 0x1f == 5的时候,说明该单元是一个I frame,关键帧
flv格式学习_第14张图片
17 -- 和上面的一样。 01 -- AVC NALU。蓝色框内的4个bytes记录后面NALU数据的长度。65 & 0x1f == 5.
 
如果NALU第一个byte xx & 0x1f != 5的时候,就不是一个I frame
27 -- 高4bits:2,inter frame ,P frame。 低4bits:7,AVC NALU。其他都一样。图中绿色后面 00 00 00 28就是前面tag的总长度。
 
 
整个的flv文件其实是:FLV header + previous tag size0 + tag1 + previous tag size1 + tag2 + previous tag size2 + ... +tagN + previous tag sizeN。
tag1是metadata,记录视频的一些信息;tag2是视频配置信息(AVC decoder configuration record),tag3是音频配置信息(如果没有音频则去掉此项),tag4以及之后的tag就是音视频数据了。
每一个结构怎么封都说清楚了,安上面的步骤一个一个NALU封就行了。
 
 
 
 
封包的时候要特别注意一下包头里面的时间戳,因为这个控制着播放的速度,如果不填,全是0的话,播放会相当快,一般按视频帧率来设置。我这个h264流是8帧的,所以我每个tag的时间间隔是125ms左右。
注意了,flv里面的数据都是大端模式,放数据进去要转换一下,如果你是通常的小端的机器的话。
 
 
 
 
到这里应该差不多了吧,我是一个NALU单元封装成一个tag,我也是刚接触,不知道上述还有哪些地方不合理,不过测试没有发现问题。我也才接触这东西,如果有知情人,望解释一下为什么有多个PPS SPS,谢谢可怜
 
至于rtmp协议发送flv,之后再写吧。


flv文件的格式其实网上资料还是不少, 但是怎么封 装成flv却不多。看了不少资料,找到了一个觉得还比较靠谱

你可能感兴趣的:(flv格式学习)