FLV文件分析
很久没看,做下关于FLV文件格式知识点回顾!
一、简单介绍
FLV(Flash Video)是Adobe公司推出的一种媒体封装格式。一个FLV文件,每个Tag类型都属于一个
流。也就是说一个FLV文件最多只有一路音频流、一个路视频流,不能定义单个类型的多个独立流在一个
文件中。
FLV数据以大端序存储,解析时需要注意。比如:0x12C,那么存储时就是0x01 0x2C。FLV封装格式
由一个FLV Header和FLV Body组成,其中FLV Body由很多个Tag组成。Tag一般可以分为三种类型:脚本
数据类型、音频数据类型、视频数据类型。
一个标准的FLV文件结构如下图所示:
二、FLV文件头
FLV Header 官方协议文档定义如下:
针对FLV Header相关字段,解释下其中的含义:
46 4c 56 01 05 00 00 00 09 //就代表该FLV文件包含音频、视频
二、FLV文件Body
FLV Body 官方协议文档定义如下:
针对FLV Body相关字段,解释下其中的含义:
2.1 FLV Tag
每一个tag其实是由两部分组成,Tag header(11 Byte)+Tag data(实际数据域)。Tag Header中存放着
TagType、DataSize等字段信息。而Tag data部分就是实际数据域信息,后面会分别讲述数据域(Tag data)。
其中FLV tag官方文档定义如下:
针对FLV Tag相关字段,解释下其中含义:
2.2 Tag data
2.2.1 Audio data tags(音频数据tag)
AUDIODATA官方协议文档定义如下:
针对AUDIODATA相关字段,解释下其中的含义:
AACAUDIODATA官方协议定义如下:
其中如果AACPacketType==0时,AudioSpecificConfig结构在ISO 14496-3文档中有定义该结构,部分结
构如下图:
AudioSpecificConfig() { audioObjectType = GetAudioObjectType(); samplingFrequencyIndex; // 4 bslbf if (samplingFrequencyIndex == 0xf) { samplingFrequency; // 24 uimsbf } channelConfiguration; // 4 bslbf sbrPresentFlag = -1; psPresentFlag = -1; if (audioObjectType == 5 || audioObjectType == 29) { // ... } else { extensionAudioObjectType = 0; } switch (audioObjectType) { case 1: case 2: case 3: case 4: //... GASpecificConfig(); break: case ...: //... } if (extensionAudioObjectType != 5 && bits_to_decode() >= 16) { //... } GetAudioObjectType() { audioObjectType; // 5 uimsbf if (audioObjectType == 31) { audioObjectType = 32 + audioObjectTypeExt; // 6 uimsbf } return audioObjectType; }
2.2.2 Video data tags(视频数据Tag)
VIDEODATA官方协议文档定义如下:
针对VIDEODATA相关字段,解释下其中的含义:
AVCVIDEOPACKET官方协议定义如下:
其中如果是AVCPacketType==0时,即AVC sequence header,AVCDecoderConfigurationRecord在
ISO 14496-15中定义如下:
aligned(8) class AVCDecoderConfigurationRecord { unsigned int(8) configurationVersion = 1; unsigned int(8) AVCProfileIndication; unsigned int(8) profile_compatibility; unsigned int(8) AVCLevelIndication; bit(6) reserved = '111111'b; unsigned int(2) lengthSizeMinusOne; bit(3) reserved = '111'b; unsigned int(5) numOfSequenceParameterSets; for (i = 0; i < numOfSequenceParameterSets; i++) { unsigned int(16) sequenceParameterSetLength ; bit(8*sequenceParameterSetLength) sequenceParameterSetNALUnit; } unsigned int(8) numOfPictureParameterSets; for (i = 0; i < numOfPictureParameterSets; i++) { unsigned int(16) pictureParameterSetLength; bit(8*pictureParameterSetLength) pictureParameterSetNALUnit; } if (profile_idc == 100 || profile_idc == 110 || profile_idc == 122 || profile_idc == 144) { bit(6) reserved = '111111'b; unsigned int(2) chroma_format; bit(5) reserved = '11111'b; unsigned int(3) bit_depth_luma_minus8; bit(5) reserved = '11111'b; unsigned int(3) bit_depth_chroma_minus8; unsigned int(8) numOfSequenceParameterSetExt; for (i = 0; i < numOfSequenceParameterSetExt; i++) { unsigned int(16) sequenceParameterSetExtLength; bit(8*sequenceParameterSetExtLength) sequenceParameterSetExtNALUnit; } } }
如果是H265,HEVCDecoderConfigurationRecord定义如下:
aligned(8) class HEVCDecoderConfigurationRecord { unsigned int(8) configurationVersion = 1; unsigned int(2) general_profile_space; unsigned int(1) general_tier_flag; unsigned int(5) general_profile_idc; unsigned int(32) general_profile_compatibility_flags; unsigned int(48) general_constraint_indicator_flags; unsigned int(8) general_level_idc; bit(4) reserved = ‘1111’b; unsigned int(12) min_spatial_segmentation_idc; bit(6) reserved = ‘111111’b; unsigned int(2) parallelismType; bit(6) reserved = ‘111111’b; unsigned int(2) chromaFormat; bit(5) reserved = ‘11111’b; unsigned int(3) bitDepthLumaMinus8; bit(5) reserved = ‘11111’b; unsigned int(3) bitDepthChromaMinus8; bit(16) avgFrameRate; bit(2) constantFrameRate; bit(3) numTemporalLayers; bit(1) temporalIdNested; unsigned int(2) lengthSizeMinusOne; unsigned int(8) numOfArrays; for (j=0; j < numOfArrays; j++) { bit(1) array_completeness; unsigned int(1) reserved = 0; unsigned int(6) NAL_unit_type; unsigned int(16) numNalus; for (i=0; i< numNalus; i++) { unsigned int(16) nalUnitLength; bit(8*nalUnitLength) nalUnit; } } }