本文将介绍如何将H.264封装成flv格式。
在看本文之间,建议先看一看下面两篇文章:
首先说一说构建一个FLV文件需要什么?
FLV Header + FLv script tag + FLV Video tag + FLV Audio tag
由于这里只是封装H.264,所以不包括Audio tag。
下面将通过分析示例来说明FLV Header + FLv script tag + FLV Video tag这三部分如何构建。
1、FLV Header
通过阅读上面的文章《FLV格式详解》应该就很清楚FLV Header的内容了。
下面来分析一个实例:
Signature:0x46('F')
Signature:0x4c('L')
Signature:0x56('V')
Version:01
Flags:01
TypeFlagsReserved [Bit 3-7]:0
TypeFlagsAudio [Bit 2]:0
TypeFlagsReserved [Bit 1]:0
TypeFlagsVideo [Bit 0]:1
DataOffset:00 00 00 09
preTagSize:00 00 00 00 // 第一个tag默认为0
2、FLv script tag
又称Metadata Tag,位于flv header后的第一个tag
下面来分析一个实例
Tag Header:
TagType:12(表示这是一个script tag)
Datasize:00 00 9f(Tag Data 部分的大小)
Timestamp:00 00 00(该Tag的时间戳)
Timestamp_ex:00(时间戳的扩展部分)
StreamID::00 00 00(总是0)
Tag data:
因为TagType为0x12,所以这部分的数据为两个AMF包
第一个AMF包:
type:02(表示字符串)
stringLen:00 0a(字符串长度为10)
string:6f 6e 4d 65 74 61 44 61 74 61(onMetaData)
第二个AMF包:
type:08(表示数组)
arrayNum:00 00 00 07(数组元素个数)
stringLen:00 08(第一个数组元素字符串长度)
string:64 75 72 61 74 69 6f 6e(duration)
valType:00(数据类型,double型)
val:40 03 70 a3 d7 0a 3d 71(double型)
stringLen:00 05
string:77 69 64 74 68(width)
...
end:00 00 09
preTagSize:00 00 00 aa
3、FLV Video Tag
这部分封装着图像数据,也就是H.264的数据封装在这里。
H.264是由一个一个NALU组成,NALU的类型有(SPS、PPS、I帧的SLICE、非I帧的SLICE)
封装H.264就是将这些NALU一个一个取出来,然后封装成Tag。
需要注意的是,SPS与PPS必须封装在一个Tag中。
下面分别通过实例来分析各种NALU(SPS、PPS、I帧的SLICE、SEI、非I帧的SLICE)是怎么封装的。
1、SPS与PPS
Tag Header:
TagType:09(Tag的类型,包括音频(0x08)、视频(0x09)、script data(0x12))
Datasize:00 00 2e(Tag Data 部分的大小)
Timestamp:00 00 00(时间戳,19ms)
Timestamp_ex:00(时间戳的扩展部分)
StreamID:00 00 00(总是0)
Tag data:
FrameType | CodecID:17(keyframe | AVC)(视频tag的参数)
AVCVideoPaket:(因为CodecID==7,所以VideoData为AVCVideoPaket)
AVCPaketType:00(ACVPacket的类型,0: AVC sequence header;1: AVC NALU;2: AVC end of sequence)
CompositionTime:00 00 00
(因为ACVPaketType==0,所以Data=AVCDecoderConfigurationRecord)
AVCDecoderConfigurationRecord:
configurationVersion:01
AVCProfileIndication:64
profile_compatibility:00
AVCLevelIndication:1e
lengthSizeMinusOne:ff
numOfSequenceParameterSets:e1(低五位为SPS的个数,计算方法为:numOfSequenceParameterSets & 0x1F=1)
sequenceParameterSetLength:00 18(SPS的长度,24)
sequenceParameterSetNALUnits:67 64 00 1e ac d9 40 a0 33 b0 11 00 00 03 02 47 00 00 6d 34 0f 16 2d 96(SPS)
numOfPictureParameterSets:01(PPS的个数)
pictureParameterSetLength:00 06(PPS的长度)
pictureParameterSetNALUnits:68 eb e3 cb 22 c0(PPS)
previousTagSize:00 00 00 39
2、I帧的SLICE
Tag Header:
TagType:09(Tag的类型,包括音频(0x08)、视频(0x09)、script data(0x12))
Datasize:00 35 78(Tag Data 部分的大小)
Timestamp:00 00 0a(时间戳,19ms)
Timestamp_ex:00(时间戳的扩展部分)
StreamID:00 00 00(总是0)
Tag data:
FrameType | CodecID:17(key frame | AVC)(视频tag的参数)
因为CodecID==7,所以VideoData为AVCVideoPaket
AVCVideoPaket:
AVCPaketType:01(ACVPacket的类型,0: AVC sequence header;1: AVC NALU;2: AVC end of sequence)
CompositionTime:00 00 0a
NaluLen:00 00 35 6f
NaluData:...
preTagSize:00 00 35 83
对于SEI的封装跟I帧是一样的。
3、非I帧的SLICE
非I帧的封装格式和I帧的封装格式基本一样,唯一不同的是FrameType | CodecID:部分,应该设置为:
FrameType | CodecID:27(inter frame | AVC)(视频tag的参数)
总结:以上通过实例讲解了FLV的头部信息,script tag,以及H.264不同类型的NALU如何封装成tag,下面放出源码。