关于ffmpeg这里插入一个章节-----关于flv格式的解析,因为在ffmpeg推流的过程中,最流行的就是将数据封装成flv格式,通过rtmp传输,所以搞明白flv的格式构成是十分有必要的,我可能会扣的比较细。
1.首先来看flv的最外层,FLVHeader + PreviousTagSize(前一个tag的大小)+ Tag + .... + PreviousTagN + TagN,这部分我相信很多文章都有讲过,我就不细说了。
表1:
Field | Size | Comment |
签名 | 1Byte | ’F’(0X46) |
签名 | 1Byte | ‘L’(0X4C) |
签名 | 1Byte | ‘V’(0x56) |
版本 | 1Byte | FLV的版本。0x01表示FLV 版本是1 |
保留字段 | 5bits | 前五位必须是0 |
是否有音频流 | 1bits | 音频流是否存在标志 |
保留字段 | 1bits | 必须是0 |
是否有视频流 | 1bits | 视频流是否存在标志 |
文件头大小 | 4Byte | FLV版本1时填写9,表明的是FLV头的大小,为后期的FLV版本扩展使用。包括这四个字节。 数据的起始位置就是从文件开头偏移这么多的大小。 |
TAG为视频,也就是TagType=0x09时的组成图示,配合表二食用效果更佳:
表2:
Field | type | Comment |
TAG类型 | 1Byte | 0x08: audio 0x09: video 0x12: script data——这里是一些描述信息。 all others: reserved其他所有值未使用。 |
数据大小 | 3Byte | 数据区的大小,不包括包头。包头总大小是11个字节。 |
时戳 | 3Byte | 当前帧时戳,单位是毫秒。相对于FLV文件的第一个TAG时戳。第一个tag的时戳总是0。——不是时戳增量,rtmp中是时戳增量。 |
时戳扩展字段 | 1Byte | 如果时戳大于0xFFFFFF,将会使用这个字节。这个字节是时戳的高8位,上面的三个字节是低24位。 |
流ID | 3Byte | 总是0 |
数据区Data | Byte[n] | 真正的数据 |
FrameType为数据类型,CodecID为包装类型,1为JPEG,2为H263,3为Screen video,4为On2 VP6,5为On2 VP6,6为Screen videoversion 2,7为AVC。
表3:
FrameType | Comment |
1 | 关键帧(I帧) |
2 | 非关键帧(P帧,B帧) |
3 | H263的非关键帧 |
4 | 服务器生成的关键帧 |
5 | 视频信息或命令帧 |
表4:
CodecID | Comment | VideoDataType |
1 | JPEG | |
2 | H263 | H263VideoPacket |
3 | Screen video | ScreenVideopacket |
4 | On2 VP6 | VP6FLVVideoPacket |
5 | On2 VP6 with alpha channel 6: Screen video version 2 | VP6FLVAlphaVideoPacket |
6 | Screen video version 2 | ScreenV2VideoPacket |
7 | AVC | AVCVideoPacket |
注明:在VideoHeader为0x17的情况下,为关键帧的AVCVideoPacket,在这种情况下VideoData包含FrameType和CompositionTime。
在这里我们对最常用的AVCVideoPacket进行解构:
AVCVideoPacketBody里面的内容是由AVCPacketType来决定的,其中0x02的AVCEndOfSequence并非必须的。
注:flv中的nalu并非标准的nalu数据格式,标准的nalu采用00 00 00 01或者 00 00 01分隔,在flv中是没有分割字节的。也即是说在CompostionTime之后直接就是NALU的数据。
至此flv的总体结构就分析完毕了,得益于flv结构简单明了,所以才会被广泛用于网络传输。
如果有什么分析错误的地方,希望能在评论告诉我,让我改正,还是那句话大家共同进步!!!!