H264 + AAC封装FLV
H264 + AAC封装FLV
FLV格式解析
FLV文件格式
FLV包含一个File Header以及File Body组成,其中File Body由无数个tag组成,结构如图
FLV Header
FLV Header 由9个字节组成结构如下:
- 第1-3字节:1-3字节为文件标识,标识"FLV"0x46 0x4C 0x56
- 第4字节:第4个字节位版本,总为1
- 第5字节:第5个字节的前5位保留,必须为0,第6位标识是否有音频,第7位保留为0,第8位标识是否有视频
- 第6-9字节:第6-9个字节为UI32类型的值,表示从File Header开始到File Body开始的字节数,版本1中总为9
对应数据结构如下:
struct FlVHeader
{
unsigned char tag_f;
unsigned char tag_l;
unsigned char tag_v;
unsigned char version;
unsigned char streamInfo;
unsigned char DataOffset[4];
FlVHeader()
{
tag_f = 'F';
tag_l = 'L';
tag_v = 'V';
version = 0x01;
streamInfo = 0x05; //有音频也有视频
memset(DataOffset, 0, 4);
DataOffset[3] = 0x09;
}
};
FLV Body
Tag Header
FLV tag 包含Tag 头(Tag Header)以及Tag 数据(Tag Body)两个部分,Tag Header由11个字节组成结构如图:
- type : 音频(0x08)、视频(0x09)和script data(0x12)
- tag size : 3个字节标识该tag data部分size
- time : 3个字节标识时间戳字段(毫秒)
- timeEx : 如果时间戳超过3个字节标识的范围,可以用timeEX标识时间戳的高位
Audio Tag Data
音频Tag Data 第一个字节标识音频数据的格式,之后就是编码完成之后的AAC音频数据,每个AAC音频数据采样数为1024:
- 第1个字节的前4位的数值表示了音频数据格式
- 第1个字节的第5-6位的数值表示采样率
- 第1个字节的第7位表示采样精度
- 第1个字节的第8位表示音频类型
生成音频格式函数如下:
uint8_t createFLVTagAudioInfo(int audioCodec, int sampleRate, int channels, int sampleSize)
{
uint8_t soundRate = 0;
if (sampleRate <= 8 * 1000)
soundRate = FLV_SAMPLERATE_SPECIAL;
else if (sampleRate > 8 * 1000 && sampleRate <= 20 * 1000)
soundRate = FLV_SAMPLERATE_11025HZ;
else if (sampleRate > 20 * 1000 && sampleRate <= 30 * 1000)
soundRate = FLV_SAMPLERATE_22050HZ;
else if (sampleRate > 30 * 1000)
soundRate = FLV_SAMPLERATE_44100HZ;
uint8_t soundType = (1 == channels) ? 0 : 1;
uint8_t soundBitsPerSample;
if(sampleSize == 8)
soundBitsPerSample = FLV_SAMPLESSIZE_8BIT;
else if(sampleSize == 16)
soundBitsPerSample = FLV_SAMPLESSIZE_16BIT;
else if(sampleSize == 24)
soundBitsPerSample = FLV_SAMPLESSIZE_24BIT;
uint8_t audioInfo = (audioCodec << FLV_AUDIO_CODECID_OFFSET) | (soundRate << FLV_AUDIO_SAMPLERATE_OFFSET) \
| (soundBitsPerSample << FLV_AUDIO_SAMPLESSIZE_OFFSET) | soundType;
return audioInfo;
}
Video Tag Data
和音频数据类似,也是第一个字节标识视频编码信息,第二个字节开始为视频数据:
- 第1个字节的前4位的数值标识AVC帧类型
- 第1个字节的后4位的数值表示视频编码类型id
数据打包
写FLV文件的时候先写入FLV Header,然后写入Script Tag(可以不用写),之后交叉写入VideoTag以及AudioTag,写入Video Tag以及Audio Tag的时机在于判断每个Tag的时间戳大小,优先写入时间戳小的Tag。