前言
flv 是 flash video 的缩写,是 Adobe Flash payler 支持的一种流媒体播放格式。flv 是一种层级格式,除了一个 flv header 外,剩下全是由 一个个 tag 组成。tag 是由 tag 头和 tag 数据组成。tag 类型分为音频、视频、脚本,一共三种类型。每一种数据类型又有自己的 tag 头。本文下来就简单分析一下 flv 文件格式。
FLV 文件头格式
FLV 文件有 9 个字节的文件头,文件以 3 字节签名 0x46、0x4C、0x 56 开始,分别是 ‘F’、’L’、’V’ 三个字母的 ascii 编码。版本号是 1。文件头中还有 flag 标记,表面是否有音频、视频 tag。
下来以音频、视频为例,分析一下 FLV 格式的 header、tag。
音频 tag 格式
如上图,除了 9 字节的公共文件头外,body 部分就是一个个 tag 组成的。每一个 tag 都有 15 字节的 tag 头。字段说明如下:
- PreviousTagSize,是 4 字节长度,表面之前的 Tag 的长度,包含了 tag 头和 tag 数据。第一个 tag ,此值是 0。
- TagType,是 1 字节长度。音频:8, 视频:9
- DataSize , 是 3 字节长。flv tag 的数据长度,其实如图里 audio tag 头及其数据长度。
- Timestamp,是 3 字节长。时间戳,貌似 flv 播放需要。
- TimestampExtended, 是对 Timestamp 长度的扩展,当时间长度 3 字节不能表示的时候,启用扩展字段。
- StreamID ,3 字节长,都填 0.
flv tag 的 body 部分其实就是音频的 tag 部分了,图中每一个字段都有简单说明。具体每一个参数都有很多取值,取值的详细说明参考 [1] 中标明的 flv 规范音频 tag 部分。
对于 AACPacketType = 0 的情况,音频数据是 AudioSpecificConfig 格式,此格式在 ISO/IEC 14496-3 2009 中第一,可惜下载不到此文档。可以参考 wiki 给的格式:
Audio Specific Config:
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
如果是 AACPacketType = 1 的情况,那么后续数据都是 AAC 格式了。
视频 tag 格式
视频 tag 格式和音频格式 flv 文件头、flv tag 头都相同,不再说明。video tag 也不再详细说明,可以参考 [1] 中标明的 flv 规范视频 tag 部分。
这里需要说明一下的是,当 flv 包含的是 h264 的时候,CodecID 值是 7。在 H264 视频流开始的第一个 NALU 数据,需要发送 SPS、PPS 类型的数据。此时,AVCPacketType 会填 0,SPS/PPS 是包含在 AVCDecoderConfigurationRecord 结构中,格式如下:
aligned(8) class AVCDecoderConfigurationRecord {
unsigned int(8) configurationVersion = 1;
unsigned int(8) AVCProfileIndication;
unsigned int(8) profile_compatibility;
unsigned int(8) AVCLevelIndication;
bit(6) reserved = ‘111111’b;
unsigned int(2) lengthSizeMinusOne;
bit(3) reserved = ‘111’b;
unsigned int(5) numOfSequenceParameterSets;// SPS 个数
for (i=0; i< numOfSequenceParameterSets; i++) {
unsigned int(16) sequenceParameterSetLength ;// SPS 字节长度
bit(8*sequenceParameterSetLength) sequenceParameterSetNALUnit;
}
unsigned int(8) numOfPictureParameterSets;
for (i=0; i< numOfPictureParameterSets; i++) {
unsigned int(16) pictureParameterSetLength;// PPS 自己长度
bit(8*pictureParameterSetLength) pictureParameterSetNALUnit; // PPS bit 流
}
if( profile_idc == 100 || profile_idc == 110 ||
profile_idc == 122 || profile_idc == 144 )
{
bit(6) reserved = ‘111111’b;
unsigned int(2) chroma_format;
bit(5) reserved = ‘11111’b;
unsigned int(3) bit_depth_luma_minus8;
bit(5) reserved = ‘11111’b;
unsigned int(3) bit_depth_chroma_minus8;
unsigned int(8) numOfSequenceParameterSetExt;
for (i=0; i< numOfSequenceParameterSetExt; i++) {
unsigned int(16) sequenceParameterSetExtLength;
bit(8*sequenceParameterSetExtLength) sequenceParameterSetExtNALUnit;
}
}
}
关于此格式,详细参考 H.264-AVC-ISO_IEC_14496-15 5.2.4.1 节。
如果是后续的视频图像 slice ,那么 AVCPacketType 都会设置为 1。
总结
本文我们描述了 flv 文件头格式,AAC 和 AVC 的 flv tag。如果以 flv 格式推送 rtmp 流,AAC 和 AVC 都要加上 audio tag 和 video tag,但是图中标明的FLV TAG 头没有包含。
本文算是 flv 格式学习的笔记、总结吧。flv 格式虽然结构简单,但是也有很多字段,每一个字段取值也有很多,这些细节需要参考具体的规范。