格式介绍
概览
FLV是流媒体封装格式,我们可以将其数据看为二进制字节流。
总体上看,FLV包括文件头(File Header)和文件体(File Body)两部分,其中文件体由一系列的Tag及Tag Size对组成。
- 用UltraEdit打开FLV文件,如下图
1. 文件头File Header
46 4C 56 01 05 00 00 00 09
头部分由一下几部分组成
Signature(3 Byte)+Version(1 Byte)+Flags(1 Bypte)+DataOffset(4 Byte)
- signature :占3个字节,固定FLV三个字符作为标示。
一般发现前三个字符为FLV时就认为他是flv文件。
图中0x46 0x4C 0x56,代表FLV。 - Version:占1个字节 标示FLV的版本号。这里我们看到是1。
- Flags:占1个字节 内容标示。
第0位和第2位,分别表示 video 与 audio 存在的情况.(1表示存在,0表示不存在)。
截图看到是0x05,也就是00000101,代表既有视频,也有音频。 - DataOffset:
4个字节 表示FLV的header长度。这里可以看到固定是9。
2.文件体File Body
FLV的body部分是一系列的back-pointers+tag构成的
-
back-pointers
固定4个字节,表示前一个tag的size。第一个back-pointers数据为0。 -
tag
音视频数据,其中tag内部又分为flv_tag_header + video_header/audio_header+data,详见如下Tag详解部分。
3. Tag详解
Tag数据结构
Tag分为:
flv_tag_header + video_header/audio_header+data;
其中flv_tag_header占11个字节,video_header5个字节,audio_header2个字节,剩余为H264数据。
flv_tag_header如下:
长度11个字节,type+tag data size+Timestamp+TimestampExtended+stream id+ tag data
-
type 1个字节。
Tag分三种类型:
scripts0x12
18
audio0x08
8
video0x09
9 -
tag data size 3个字节。
表示tag data的长度。从streamd id 后算起。 -
Timestreamp 3个字节。
时间戳 -
TimestampExtended 1个字节。
时间戳扩展字段 -
stream id 3个字节。
总是0
video_header/audio_header
-
video_header,长度5个字节
4bit Frame Type,帧类型
4bit CodecID,视频编码类型
8 bit AVCPacketType,是sequence header(0)还是NALU(1)
24 bit CompositionTime,如果为NALU 则为时间间隔,否则为0 -
audio_header,长度为2个字节
4bit 表示音频格式
第5、6bit 表示采样率
第7bit 表示采用的长度
第8bit 表示音频类型
8 bit AVCPacketType,是AAC sequence header(0)还是 AAC raw(1)
data 数据部分
为H264编码后帧数据
脚本Tag,script tag,18,0x12
脚本Tag一般只有一个,是flv的第一个Tag,用于存放flv的信息,比如duration、audiodatarate、creator、width等。
-
一般来说,该Tag Data结构包含两个AMF包。
AMF(Action Message Format)是Adobe设计的一种通用数据封装格式,在Adobe的很多产品中应用,简单来说,AMF将不同类型的数据用统一的格式来描述。-
第一个AMF包封装字符串类型数据
第1个字节表示AMF包类型,一般总是0x02,表示字符串,其他值表示意义请查阅文档。
第2-3个字节为UI16类型值,表示字符串的长度,一般总是0x000A(“onMetaData”长度)。
后面字节为字符串数据,一般总为“onMetaData”。 -
第二个AMF包封装一个数组类型,这个数组中包含了音视频信息项的名称和值。
第1个字节表示AMF包类型,一般总是0x08,表示数组。
第2-5个字节为UI32类型值,表示数组元素的个数。
后面即为各数组元素的封装,数组元素为元素名称和值组成的对。表示方法如下:
第1-2个字节表示元素名称的长度,假设为L。
后面跟着为长度为L的字符串。
第L+3个字节表示元素值的类型。
后面跟着为对应值,占用字节数取决于值的类型。
-
-
脚本的数据类型。
所有数据都是以数据类型+(数据长度)+数据的格式出现的。
数据类型占1byte,数据长度看数据类型是否存在,后面才是数据。
视频Tag,FLV Video Tag,9,0x09
根据Tag Header读取VideoData数据后,videoData的部分分为 视频信息Video_Header+AVC_Video_Header+数据
-
视频信息,1字节
-
前4位表示帧类型Frame Type
-
后4位为编码ID (CodecID)
-
-
视频的格式(CodecID)是AVC(H.264)的话,VideoTagHeader会多出4个字节的信息,AVCPacketType和CompositionTime,所以是H264编码的情况下VideoHeader长度是5个字节。
-
AVCPacketType,1个字节
-
AVCDecoderConfigurationRecord
包含着是H.264解码相关比较重要的sps和pps信息,再给AVC解码器送数据流之前一定要把sps和pps信息送出,否则的话解码器不能正常解码。
而且在解码器stop之后再次start之前,如seek、快进快退状态切换等,都需要重新送一遍sps和pps的信息。
AVCDecoderConfigurationRecord在FLV文件中一般情况也是出现1次,也就是第一个video tag. -
CompositionTime,3个字节
-
-
sps pps
第一个video 一般存放的是sps和pps。
存储的格式:0x01+sps[1]+sps[2]+sps[3]+0xFF+0xE1+sps size+sps+01+pps size+pps
其中sps size和pps size各占两个字节,所以videoData部分长度是11个字节 + sps.length + pps.length;再加上videoHeader的5个字节。
音频Tag,FLV Audio Tag,8,0x08
根据Tag Header读取AudioData数据后,AudioData的部分分为 音频信息Audio_Header+AACPacketType+数据
-
音频信息,1字节
- 前4位表示音频格式
- 第5、6位表示采样率
- 第7位表示采用的长度
- 第8位表示音频类型
- 前4位表示音频格式
-
其中如果音频格式为10,即是AAC格式的,AudioTagHeader中会多出一个字节AACPacketType,这个字段来表示AACAUDIODATA的类型:0 = AAC sequence header,1 = AAC raw。
- AAC sequence header也就是包含了AudioSpecificConfig,AudioSpecificConfig包含着一些更加详细音频的信息,AudioSpecificConfig的定义在ISO14496-3中1.6.2.1 AudioSpecificConfig,这里就不详细贴了。而且在ffmpeg中有对AudioSpecificConfig解析的函数,ff_mpeg4audio_get_config(),可以对比的看一下,理解更深刻。
- AAC raw 这种包含的就是音频ES流了,也就是audio payload.
举个例子
拿个flv文件对照着看一看
FLV Header
-
46 4C 56 01 05 00 00 00 09
:
表示FLV Header ,音视频都有 -
0x 00 00 00 00
第一个back-pointers(表示前一个tag的size)。他前面没有tag,所以是0。
脚本Tag
12 00 00 B6 00 00 00 00 00 00 00
0x12
表示这是一个scripts tag,00 00 B6
三个字节表示tag data长度为182个字节,Timestreamp、TimestampExtended、stream id 均为0。
下一个back-pointers,表示该整个tag的size,即182 + 11(tag data前面的长度) = 193 = 0xc1,即 00 00 00 c1
,在工具中查找即可。
-
02 00 0A 6F 6E 4D 65 65 74 61 44 61 74 61
表示第一个AMF包。
02表示类型为string type,后面两个字节00 00A 表示长度是10,值onMetaData。 -
03 00 00 00 08
03表示ObjectType,此处应该一般是08才对,表示数组类型;表示有8个键值对。
接下来就是解析键值对了。 -
解析键值对
0005表示键长度,77 69 64 74 68
表示width,00
表示类型为Number,后面8字节表示值。
0006表示键长度,68 65 69 67 68 74
表示height,00
表示类型为Number,后面8字节表示值。
以此类推解析到最后end marker 00 00 09
,表示解析完毕。
第一个videoTag,一般包含sps和pps
09 00 00 25 00 00 00 00 00 00 00
09表示视频Tag;
00 00 25表示长度为0x25=37;加上头部长度11,为48,下一个back-pointers是00 00 00 30
Timestreamp、TimestampExtended、stream id均为0;
接下来是数据部分tag data。如下图所示:
-
0x17
,即0b00010111
前4位表示帧类型,1表示为关键帧; 后4位表示编码ID,7表示是AVC。
视频格式是AVC(H.264)类型的话,后面1个字节表示AVCPacketType,再后三个字节表示CompositionTime。 -
00
AVCPacketType为0,表示是AVCDecoderConfigurationRecord。就表示包含着sps和pps了。这个东西要第一个发给解码器,要不然不能正常解码。 -
00 00 00
CompositionTime为0。接下来就是sps和pps的信息了。 -
0x01+sps[1]+sps[2]+sps[3]+0xFF+0xE1+sps size+sps+01+pps size+pps
,对照着二进制看一下
sps[1] =42
sps[2] =80
sps[3] =20
sps size =00 11
,表示sps长度为17,17字节的sps数据读取完;读到01
pps size =00 04
,表示pps长度为4,
读取完后该tag结束。下一个back-pointers。
第一个audioTag,包含AAC sequence header
08 00 00 04 00 00 00 00 00 00 00
08表示音频;
00 00 04表示长度为4;加上头部长度11,为15,下一个back-pointers是00 00 00 0F
接下来是tag data。如下图所示:
AF
,即0b10101111
前4个字节为1010,十进制10,表示音频格式是AAC;10会多一个字节AACPacketType,表示该AACAUDIODATA的类型。
第5、6位为11,十进制3,表示采样率为44kHz;
第7位为1,表示16位采用;
第8位为1,表示stereo;
00
,表示AACPacketType,为0表示该Tag是AAC sequence header。
接下来两个字节表示AudioSpecificConfig,包含更加详细音频的信息。
读取完后该tag结束。下一个back-pointers。
之后的videoTag、videoTag
-
下一个video
长度为35525的视频数据,时间戳为23。
0x17
后一位AVCPacketType01
,表示NALU数据。三个CompositionTime字节过后,就是NALU数据了。
-
下一个audio
长度为1538的音频数据,时间戳为36;
0xAF
后一位AACPacketType为01
,表示ACC raw,即音频NALU数据。
总结
至此我们把FLV格式梳理了一遍,就能更好理解FLV部分代码了。
参考:
FLV视频封装格式详解
flv格式详解+实例剖析
将h.264视频流封装成flv格式文件
FLV(AAC/AVC)学习笔记