Flash Video 简称FLV,目前国内大部分视频分析网站都是采用这种格式。
它的主要是由 File Header + File Body 构成。 如下图所示

FLV Video解析-编程知识网

FLV Header 构成

FLV Video解析-编程知识网

字段 字节数 描述
Signature 3 固定字节 0X46 4c 56 对应ASCII 的FLV
Version 1 版本号
TypeFlags 1 类型标识。 前5个bit是类型标志预留字段,必须是0; 第6个bit音频类型标志(TypeFlagsAudio); 第7个bit是类型标志预留字段,必须是0; 第8个bit视频类型标志(TypeFlagsVideo)。(0x05,也就是 00000101,表示既有音频也有视频。0x01 只有视频)
data offset 4 版本号为1,值固定为9

FLV Body 构成

FLV body 由PreviousTagSize + Tag 构成,而tag 又分为 3种类型,分别是
Script(脚本)、Video(视频)、Audio(音频)

PreviousTagSize 解析

PreviousTagSize 为固定的4个字节,表示前面一个tag 的值

FLV Tag 解析

FLV tag 由 TagHeader + tag Data 构成

Tag Header

Tag Header为固定的11 个字节,其内部由以下几个字段构成

字段 字节数 描述
TagType 1 0x12 : Scipt 0x09 :视频 0x08:音频
DataSize 3 数据长度
TimeStamp 3 相对于第一帧的时间戳,单位为毫秒,第一帧总为0
TimeStampExtender 1 时间戳的补充字段
StreamID 3 0

FLV Video解析-编程知识网

所以后面的一个 PreviousTagSize = 前一个dataSize + 11;

Tag Data

Script data

Script Tag,一般都是flv文件的开头才有一个。它包含两个AMF(Action Message Format)包,第一个AMF包封装了" onMetaData ",第二个AMF包封装了诸如视频图像长宽,文件长度,视频帧率,音频比特率,位深等等。
FLV Video解析-编程知识网
上图中0x08 字节,表示 Value 字段是数组类型

Video Data

Tag Data 是由 FrameTypeCodecID 以及VideoData 或者AVCVIDEOPACKET构成,AVCVIDEOPACKET只存在第一个video tag 中。
下图是视频的首个 Tag,它一定是由 11个字节的Header + frameType(0x17,0x27)+AVCVIDEOPACKET 组成
FLV Video解析-编程知识网
下面是Tag Data 3个字段的描述:

0x17 : 1个byte 对应8 bits, 0x17 转为0001 0111 ,分别对应的是截图中的frameTypeCodecID.
FrameType 数值对应的值意味着 (0001 = 1)
1– keyframe
2 – inner frame
3 – disposable inner frame (h.263 only)
4 – generated keyframe

CodecID 数值对应的值意味着 (0111 = 7)
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)

所以我们可以判断在传输非关键帧的时候 FrameType + CodeCID 组成的值为0x27

AVCVIDEOPACKET 解析

FLV Video解析-编程知识网

字段 字节 描述
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内容

组装的相关代码见下:

    const char *sps = videoFrame.sps.bytes;const char *pps = videoFrame.pps.bytes;NSInteger sps_len = videoFrame.sps.length;NSInteger pps_len = videoFrame.pps.length;body = (unsigned char *)malloc(rtmpLength);memset(body, 0, rtmpLength);body[iIndex++] = 0x17;body[iIndex++] = 0x00;body[iIndex++] = 0x00;body[iIndex++] = 0x00;body[iIndex++] = 0x00;body[iIndex++] = 0x01;body[iIndex++] = sps[1];body[iIndex++] = sps[2];body[iIndex++] = sps[3];body[iIndex++] = 0xff;/*sps*/body[iIndex++] = 0xe1;body[iIndex++] = (sps_len >> 8) & 0xff;body[iIndex++] = sps_len & 0xff;memcpy(&body[iIndex], sps, sps_len);iIndex += sps_len;/*pps*/body[iIndex++] = 0x01;body[iIndex++] = (pps_len >> 8) & 0xff;body[iIndex++] = (pps_len) & 0xff;memcpy(&body[iIndex], pps, pps_len);iIndex += pps_len;
普通Video Data 解析

讲完第一个特殊的VideoData, 其他所有的VideoData 都是由AVPACKETTYPE + CompsitionTime offset + Data(去除startCode 的有效图像数据)构成。
FLV Video解析-编程知识网

具体的iOS 侧代码组装可见:LFLIiveKit
FLV 分析工具需要使用Windows 下的 FLV Analyzer