FLV(Flash Video)是一种流媒体格式,因其体积小、协议相对简单,很快便流行开来,并得到广泛的支持。常见的HTTP-FLV直播协议,就是使用HTTP流式传输通过FLV封装的音视频数据。对想要了解HTTP-FLV的同学来说,了解FLV协议很有必要。
FLV协议简介
FLV(Flash Video)是一种流媒体格式,因其体积小、协议相对简单,很快便流行开来,并得到广泛的支持。
常见的HTTP-FLV直播协议,就是使用HTTP流式传输通过FLV封装的音视频数据。对想要了解HTTP-FLV的同学来说,了解FLV协议很有必要。
概括地说,FLV 由 FLV header 跟 FLV file body 两部分组成,而 FLV file body 又由多个 FLV tag组成。
FLV = FLV header + FLV file body
FLV file body = PreviousTagSize0 + Tag1 + PreviousTagSize1 + Tag2 + ... + PreviousTagSizeN-1 + TagN
FLV tag又分为3种类型:
Video Tag:存放视频相关数据;
Audio Tag:存放音频相关数据;
Script Tag:存放音视频元数据;
在实际讲解FLV协议前,首先对单位进行约定:
STRING
Sequence of Unicode 8-bit characters (UTF-8), terminated with 0x00 (unless otherwise specified)
无符号8位整数
无符号16位整数
无符号24位整数
无符号32位整数
xxx [ ]
类型为xxx的数组
xxx [n]
类型为xxx的数组,数组长度为n
FLV header由如下字段组成,其中:
前三个字节内容固定是
FLV
最后4个字节内容固定是9(对FLV版本1来说)
In playback, the time sequencing of FLV tags depends on the FLV timestamps only. Any timing mechanisms built into the payload data format are ignored.
定义如下所示:
SoundFormat
UB[4]
音频格式,重点关注 **10 = AAC **
0 = Linear PCM, platform endian
1 = ADPCM
2 = MP3
3 = Linear PCM, little endian
4 = Nellymoser 16-kHz mono
5 = Nellymoser 8-kHz mono
6 = Nellymoser
7 = G.711 A-law logarithmic PCM 8 = G.711 mu-law logarithmic PCM 9 = reserved
10 = AAC
11 = Speex
14 = MP3 8-Khz
15 = Device-specific sound
SoundRate
UB[2]
采样率,对AAC来说,永远等于3
0 = 5.5-kHz
1 = 11-kHz
2 = 22-kHz
3 = 44-kHz
SoundSize
UB[1]
采样精度,对于压缩过的音频,永远是16位
0 = snd8Bit
1 = snd16Bit
SoundType
UB[1]
声道类型,对Nellymoser来说,永远是单声道;对AAC来说,永远是双声道;
0 = sndMono 单声道
1 = sndStereo 双声道
SoundData
UI8[size of sound data]
如果是AAC,则为 AACAUDIODATA;
其他请参考规范;
If the SoundFormat indicates AAC, the SoundType should be set to 1 (stereo) and the SoundRate should be set to 3 (44 kHz). However, this does not mean that AAC audio in FLV is always stereo, 44 kHz data. Instead, the Flash Player ignores these values and extracts the channel and sample rate data is encoded in the AAC bitstream.
AACAUDIODATA
当 SoundFormat 为10时,表示音频采AAC进行编码,此时,SoundData的定义如下:
The AudioSpecificConfig is explained in ISO 14496-3. Note that it is not the same as the contents of the esds box from an MP4/F4V file. This structure is more deeply embedded.
关于AudioSpecificConfig
伪代码如下:参考
这里
5 bits: object type
if (object type == 31)
6 bits + 32: object type
4 bits: frequency index
if (frequency index == 15)
24 bits: frequency
4 bits: channel configuration
var bits: AOT Specific Config
定义如下:
FrameType
UB[4]
重点关注1、2:
1: keyframe (for AVC, a seekable frame) —— 即H.264的IDR帧;
2: inter frame (for AVC, a non- seekable frame) —— H.264的普通I帧;
3: disposable inter frame (H.263 only)
4: generated keyframe (reserved for server use only)
5: video info/command frame
CodecID
UB[4]
编解码器,主要关注 7(AVC)
1: JPEG (currently unused)
2: Sorenson H.263
3: Screen video
4: On2 VP6
5: On2 VP6 with alpha channel 6: Screen video version 2
7: AVC
VideoData
取决于CodecID
实际的媒体类型,主要关注 7:AVCVIDEOPACKE
2: H263VIDEOPACKET
3: SCREENVIDEOPACKET
4: VP6FLVVIDEOPACKET
5: VP6FLVALPHAVIDEOPACKET
6: SCREENV2VIDEOPACKET
7: AVCVIDEOPACKE
AVCVIDEOPACKE
当 CodecID 为 7 时,VideoData 为 AVCVIDEOPACKE,也即 H.264媒体数据。
AVCVIDEOPACKE 的定义如下:
这里有几点稍微解释下:
NALU:H.264中,将数据按照特定规则格式化后得到的抽象逻辑单元,称为NALU。这里的数据既包括了编码后的视频数据,也包括视频解码需要用到的参数集(PPS、SPS)。
AVCDecoderConfigurationRecord:H.264 视频解码所需要的参数集(SPS、PPS)
CTS:当B帧的存在时,视频解码呈现过程中,dts、pts可能不同,cts的计算公式为 pts - dts/90,单位为毫秒;如果B帧不存在,则cts固定为0;
PPS、SPS这里先不展开。
Script Data Tags通常用来存放跟FLV中音视频相关的元数据信息(onMetaData),比如时长、长度、宽度等。它的定义相对复杂些,采用AMF(Action Message Format)封装了一系列数据类型,比如字符串、数值、数组等。
SCRIPTDATASTRING
变量类型:
0 = Number type
1 = Boolean type
2 = String type
3 = Object type
4 = MovieClip type
5 = Null type
6 = Undefined type
7 = Reference type 8 = ECMA array type 10 = Strict array type 11 = Date type
12 = Long string type
ECMAArrayLength
如果Type为8(数组),则为UI32
ScriptDataValue
If Type == 0 DOUBLE
If Type == 1 UI8
If Type == 2 SCRIPTDATASTRING
...(有点长,可以参考规范)
ScriptDataValueTerminator
如果Type3,则为SCRIPTDATAOBJECTEND
如果 Type8,则为SCRIPTDATAVARIABLEEND
Object、Array的结束符
可以看到,Script Data Tag 的定义相对复杂,下面通过onMetaData进行进一步讲解。
onMetaData中包含了音视频相关的元数据,封装在Script Data Tag中,它包含了两个AMF。
第一个AMF:
第1个字节:0x02,表示字符串类型
第2-3个字节:UI16类型,值为0x000A,表示字符串的长度为10(onMetaData的长度);
第4-13个字节:字符串onMetaData对应的16进制数字(0x6F 0x6E 0x4D 0x65 0x74 0x61 0x44 0x61 0x74 0x61);
第二个AMF:
第1个字节:0x08,表示数组类型;
第2-5个字节:UI32类型,表示数组的长度,onMetaData中具体包含哪些属性是不固定的。
第6个字节+:比如duration,则:
第6-9个字节:0x0008,表示长度为8个字节;
第10-17个字节:0x6475 7261 7469,表示 duration 这个字符串;
第18个字节:0x00,表示为数值类型;
第19-26个字节:0x...,表示具体的时长;
更多onMetaData字段的定义:
FLV协议本身不算复杂,理解上的困难,更多时候来自音视频编解码相关的知识,比如H.264、AAC相关知识,建议不懂的时候自行查下。此外,FLV的字节序为大端序,在做协议解析的时候一定要注意。
本文为讲解方便,部分内容可能不够严谨,如有错漏敬请指出。
video_file_format_spec_v10.pdf
https://www.adobe.com/content/dam/acom/en/devnet/flv/video_file_format_spec_v10.pdf
MPEG-4 Part 3
https://en.wikipedia.org/wiki/MPEG-4_Part_3#Audio_Profiles
flv文件分析
https://www.jianshu.com/p/e290dca02979
H.264再学习 -- 详解 H.264 NALU语法结构
https://blog.csdn.net/qq_29350001/article/details/78226286