FLV文件格式分析
参考地址:
https://zhuanlan.zhihu.com/p/83346973
https://www.cnblogs.com/leisure_chn/p/10662941.html
https://blog.csdn.net/abe_liu/article/details/107445565 (video解析)
https://www.cnblogs.com/chgaowei/p/5445597.html (FLV文件格式官方规范详解)
前言
flv 是 flash video 的缩写,是 Adobe Flash payler 支持的一种流媒体播放格式。flv 是一种层级格式,除了一个 flv header 外,剩下全是由 一个个 tag 组成。tag 是由 tag 头和 tag 数据组成。tag 类型分为音频、视频、脚本,一共三种类型。每一种数据类型又有自己的 tag 头。
FLV 文件头格式

FLV 文件有 9 个字节的文件头,文件以 3 字节签名 0x46、0x4C、0x 56 开始,分别是 ‘F’、’L’、’V’ 三个字母的 ascii 编码。版本号是 1。文件头中还有 flag 标记,表面是否有音频、视频 tag。
| 字段 | 类型 | 说明 | 
|---|---|---|
| Signature | UI8 | 'F' (0x46) | 
| Signature | UI8 | 'L' (0x4C) | 
| Signature | UI8 | 'V' (0x56) | 
| Version | UI8 | 类型标识。 前5个bit是类型标志预留字段,必须是0; 第6个bit音频类型标志(TypeFlagsAudio); 第7个bit是类型标志预留字段,必须是0; 第8个bit视频类型标志(TypeFlagsVideo)。(0x05,也就是 00000101,表示既有音频也有视频。0x01 只有视频) FLV 版本。例如,0x01 表示 FLV 版本 1 | 
| TypeFlags | UI8 | b[0] 是否存在视频流 b[2] 是否存在音频流 其他字段保留,值为0 | 
| DataOffset | UI32 | FLV Header 长度(字节) | 
下来以音频、视频为例,分析一下 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
| 字段 | 字节数 | 描述 | 
|---|---|---|
| TagType | 1 | 0x12 : Scipt 0x09 :视频 0x08:音频 | 
| DataSize | 3 | 数据长度 | 
| TimeStamp | 3 | 相对于第一帧的时间戳,单位为毫秒,第一帧总为0 | 
| TimeStampExtender | 1 | 时间戳的补充字段 | 
| StreamID | 3 | 0 | 
flv tag 的 body 部分其实就是音频的 tag 部分了,图中每一个字段都有简单说明。具体每一个参数都有很多取值,取值的详细说明参考 [1] 中标明的 flv 规范音频 tag 部分。
对于 AACPacketType = 0 的情况,音频数据是 AudioSpecificConfig 格式,此格式在 ISO/IEC 14496-3 2009 中第一,可惜下载不到此文档。
如果是 AACPacketType = 1 的情况,那么后续数据都是 AAC 格式了(data里面的数据不包含Acc 的头7个字节)。
音频数据
| Field | type | Comment | 
| 音频格式 | UB4 | 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 7, 8, 14, and 15:内部保留使用。 flv是不支持g711a的,如果要用,可能要用线性音频。 | 
| 采样率 | UB2 | For AAC: always 3   (AAC总是3) 0 = 5.5-kHz 1 = 11-kHz 2 = 22-kHz 3 = 44-kHz | 
| 采样大小 | UB1 | 0 = snd8Bit 1 = snd16Bit | 
| 声道 | UB1 | 0=单声道 1=立体声,双声道。AAC永远是1 | 
| 声音数据 | UI8[N] | 如果是PCM线性数据,存储的时候每个16bit小端存储,有符号。 如果音频格式是AAC,则存储的数据是AAC AUDIO DATA,否则为线性数组。 | 
视频 tag 格式

视频 tag 格式和音频格式 flv 文件头、flv tag 头都相同。
这里需要说明一下的是,当 flv 包含的是 h264 的时候,CodecID 值是 7。在 H264 视频流开始的第一个 NALU 数据,需要发送 SPS、PPS 类型的数据。此时,AVCPacketType 会填 0,SPS/PPS 是包含在 AVCDecoderConfigurationRecord 结构中。
视频Tag Data 是由 FrameType 和CodecID 以及VideoData 或者AVCVIDEOPACKET构成,AVCVIDEOPACKET只存在第一个video tag 中。
1、AVCVIDEOPACKET 解析
| 字段 | 字节 | 描述 | 
|---|---|---|
| AVCPACKETType | 1 | 0:AVC sequence header 1:AVC NALU 2:AVC end of sequence | 
| Composition Offset | 3 | 合成时间。 AVCPacketType==1,表示 合成时间(单位毫秒); 否则为0 | 
| VideoData | 2 | 如果AVCPacketType=0数据部分为AVCDecoderConfigurationRecord; 如果AVCPacketType=1,数据部分为1个或多个NALU; 如果AVCPacketType==2,数据部分为空 | 
关键的AVCDecoderConfigurationRecord 数据构成
| 字段 | 字节 | 描述 | 
|---|---|---|
| 版本 | 1 | 0x01版本号为1 | 
| 编码规格 | 3 | sps[1]+sps[2]+sps[3] | 
| NALU 的长度 | 1 | 0xff | 
| SPS个数 | 1 | 0xE1 | 
| SPS长度 | 2 | 整个sps长度 | 
| SPS的内容 | n | 整个sps | 
| PPS个数 | 1 | 0x01 | 
| PPS长度 | 2 | 整个pps长度 | 
| PPS内容 | n | 整个pps内容 | 
2、普通Video Data 解析
讲完第一个特殊的VideoData, 其他所有的VideoData 都是由AVPACKETTYPE + CompsitionTime offset + Data(去除startCode 的有效图像数据)构成。
 
                    
                
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号