美文网首页
FLV文件(H264,AAC)格式分析

FLV文件(H264,AAC)格式分析

作者: Coder_Sven | 来源:发表于2020-06-21 16:13 被阅读0次

    FLV 文件 = File Header(FLV 文件头)+ File Body(FLV 文件体)。其中文件体又由一系列的 Tag 和 Tag Size 组成。

    19978008-0014afa7b9cfa4a1.webp.jpg

    使用16进制查看器打开一个FLV文件,查看数据的格式

    image-20200620144713398.png

    FLV File Header

    image-20200620145234822.png
    字段 字节 描述
    signature 3 文件格式标识。('F‘ : 0x46,'L' : 0x4C,'V' : 0x56)
    version 1 版本号。(0x01:版本号为1)
    type flags 1 类型标识。 前5个bit是类型标志预留字段,必须是0; 第6个bit音频类型标志(TypeFlagsAudio); 第7个bit是类型标志预留字段,必须是0; 第8个bit视频类型标志(TypeFlagsVideo)。(0x05,也就是 00000101,表示既有音频也有视频)
    data offset 4 文件头的长度。(对于版本号为1的FLV文件来说,文件头长度固定是9,大于9表示下面还有扩展信息)

    FLV File Body

    Body部分是由一系列的 PreviousTagSize + Tag 构成。

    PreviousTagSize 固定为4字节,表示前一个Tag的size
    
    Tag分为3种类型:Script(脚本)、Video(视频)、Audio(音频)
    
    image-20200620150117227.png

    FLV Tag

    FLV中的Tag又分为 tag header(tag头部分)和 tag data(tag数据部分)。
    

    FLV Tag Header(Tag头1+3+3+1+3=11个字节)

    字段 字节 描述
    TagType 1 当前tag的类型,值有: 0x08:audio 0x09:video 0x12:script 其他:未使用的预留值
    DataSize 3 数据部分的数据长度(Data字段的数据长度)。
    Timestamp 3 当前帧的时间戳,单位是毫秒。相对于第一个TAG的时间戳(第一个的时间戳总是0)
    TimestampExtended 1 时间戳扩展字段。 如果时间戳大于0xFFFFFF,将会使用这个字节。这个字节是时间戳的高8位,上面的三个字节是低24位。
    StreamID 3 流ID,总是0
    Data n 数据部分
    image-20200620151816034.png
    00 01 6A代表数据长度有362个字节,所以蓝色区域都是data数据区域。
    

    FLV Script Tag

    Script Tag一般只有一个,且是FLV中第一个Tag,用来存放一些描述信息,如:duration、width、height等。Script Tag 中Data部分的数据都是以 【数据类型 + 数据长度 + 数据】的格式出现的。一般来说,该Tag Data结构包含两个AMF包。AMF(Action Message Format)是Adobe设计的一种通用数据封装格式,在Adobe的很多产品中应用,简单来说,AMF将不同类型的数据用统一的格式来描述。第一个AMF包封装字符串类型数据,用来装入一个“onMetaData”标志,这个标志与Adobe的一些API调用有关。第二个AMF包封装一个数组类型,这个数组中包含了音视频信息项的名称和值。
    

    类型值意义

    类型 说明
    0 Number type double类型,后8字节为数据长度
    1 Boolean type bool类型,后1字节为数据长度
    2 String type string类型,后两字节为数据长度
    3 Object type
    4 MovieClip type
    5 Null type
    6 Undefined type
    7 Reference type
    8 ECMA array type 数组类型(类似Map),后4字节为数组长度。(key:前两字节为长度;value部分第1字节为类型)
    10 Strict array type
    11 Date type
    12 Long string type

    第一个AMF(1+2+10=13个字节)

    image-20200620153530511.png
    02:String类型
    
    0A:String长度为10
    
    后面10字节为数据的值
    

    第二个AMF包(头5个字节)

    image-20200620160959809.png
    08:数组
    00 00 00 10 :数组长度为16
    

    数组中元素封装形式为:前两个字节为元素名称的长度,后面跟着长度为L的字符串。紧跟着的一个字节表示元素值的类型,后面跟着是对应值,占用的字节数取决于值的类型。

    元素“duration”(19字节)

    image-20200620161756106.png
    00 08 代表后面8个字节长度为元素名称 
    名称:duration
    00 代表double类型,后8字节为数据长度
    

    元素“width”(16个字节)

    image-20200620162134609.png
    00 05 长度
    元素名称:width
    00:代表double类型,后8字节为数据长度
    

    元素"height"(17个字节)

    image-20200620162544994.png
    00 06 
    68 65 69 67 68 74 height
    00 代表double类型,后8字节为数据长度
    
    

    元素“videodatarate”(24个字节)

    image-20200620163146947.png
    00 0D :长度
    76 69 64 65 6F 64 61 74 61 72 61 74 65 字符串“videodatarate”
    00 :代表double类型,后8字节为数据长度
    

    元素“framerate”(20个字节)

    image-20200620163652002.png
    00 09 长度
    66 72 61 6D 65 72 61 74 65:字符串“framerate”
    00 代表double类型,后8字节为数据长度
    

    元素“videocodecid”(23个字符)

    image-20200620164044030.png
    00 0c :长度
    76 69 64 65 6F 63 6F 64 65 63 69 64 字符串videocodecid
    00 代表double类型,后8字节为数据长度
    

    以下就不再截图了,对比数据自己慢慢往下找

    元素“audiodatarate”(24个字节)

    00 0D:长度
    

    元素“audiosamplerate”(26个字节)

    00 0F:长度
    

    元素“audiosamplesize”(26个字节)

    00 0F
    

    元素“stereo”(10个字节)

    image-20200620165448830.png
    00 06 长度
    73 74 65 72 65 6F 字符串“stereo”
    01:bool类型,后1字节为数据长度
    

    元素“audiocodecid”(23个字节)

    00 0C:长度
    

    元素“major_brand”(20个字节)

    image-20200620171222221.png
    00 0B :长度
    02:看上面的类型文档,string,,后两个字节代表长度
    00 04 :长度为4
    

    元素“minor_version”(19个字节)

    image-20200620171639885.png
    00 0D:长度为13
    02:string 后两位表示长度
    00 01 长度为1
    

    元素“compatible_brands”(30个字节)

    image-20200620172257155.png
    00 11 :长度为17
    02 :string 后两位代表长度
    00 08 长度为8
    

    元素“encoder”(字节数25)

    image-20200620172617573.png
    00 07 :长度为7
    02 :string
    00 0D:长度为13
    

    元素“filesize”(22个字节)

    image-20200620174628862.png
    00 08 长度为8
    00:后8位表示长度
    00 00 :空字符串
    09 :结束标志
    

    16个元素长度相加19+16+17+24+20+23+...+22 = 344

    第一个AMF包(13)+第二个AMF包头(5)+16个元素数组数据长度(344)=362个字节。

    至此,,362个data数据全部分析完毕。

    那么下一个PreviousTagSize就是362+tag头(11)=373个字节

    PreviousTagSize是固定长度4

    image-20200620181245785.png
    00 00 01 75 = 373
    

    上面分析的是Script Tag,一般都是flv文件的开头才有一个,中间是一个TagSize,再接下来就是第一个VideoTag,TagHaeder(11个字节)

    image-20200620181921356.png
    Tag头分析,按照上面的文档一个个对照
    09:video
    00 00 2E :data 长度
    00 00 00 00 时间戳
    00 00 00 流id
    

    接下来分析VideoTagBody

    image-20200620183004009.png

    1700000000这五个字节为VideoTag数据部分的固定头五个字节

    字段 比特位 描述
    FrameType 高四位 帧类型。 1: keyframe(for AVC, a seekable frame) 2: inter frame(for AVC, a non-seekable frame) 3: disposable inter frame(H.263 only) 4: generated keyframe(reserved for server use only) 5: video info/command frame
    CodecId 低四位 编码类型。 1: JPEG(目前未用到) 2: Sorenson H.263 3: Screen video 4: On2 VP6 5: On2 VP6 with alpha channel 6: Screen video version 2 7: AVC(高级视频编码)

    比如上面的17就代表着是keyframe关键帧,并且是AVC(高级视频编码)

    字段 字节数 描述
    AVCPacketType 1 0:AVC sequence header 1:AVC NALU 2:AVC end of sequence
    CompositionTime 3 合成时间。 AVCPacketType==1,表示 合成时间(单位毫秒); 否则为0

    比如上面的00 00 00 00 就表示AVC sequence header和合成时间为0

    Data数据

    字段 字节 描述
    data n 如果AVCPacketType==0,数据部分为AVCDecoderConfigurationRecord; 如果AVCPacketType==1,数据部分为1个或多个NALU; 如果AVCPacketType==2,数据部分为空
    AVCDecoderConfigurationRecord

    AVCDecoderConfigurationRecord 包含了H.264解码相关比较重要的SPSPPS信息,再给AVC解码器送数据流之前一定要把SPSPPS信息送出,否则的话解码器不能正常解码。而且在解码器stop之后再次start之前,如seek、快进快退状态切换等,都需要重新送一遍SPSPPS的信息。AVCDecoderConfigurationRecord在FLV文件中一般情况也是出现1次,也就是第一个video tag。

    字段 字节 描述
    版本 1 0x01,版本号为1
    编码规格 3 sps[1]+sps[2]+sps[3]
    NALU 的长度 1 0xFF,包长为 (0xFF& 3) + 1,也就是4字节表示
    SPS个数 1 0xE1,个数为0xE1 & 0x1F 也就是1
    SPS长度 2 整个sps长度
    SPS的内容 n 整个sps
    PPS个数 1 0x01,1个
    PPS长度 2 整个pps长度
    PPS内容 n 整个pps内容
    image-20200620185347197.png
    00 19 :sps长度为25
    00 05 :pps长度为5
    

    上面的头数据(11)+(固定长度17 00 00 00 00)5+(1+3+1+1+2)+25(sps长度)+(1+2)+5(pps长度)= 57

    所以下一个PreviousTagSize为0x39

    image-20200620190610879.png

    第一个VideoTag过了之后,接下来是第一个AudioTag(Tag头11个字节)

    image-20200620190851965.png

    AudioTagBody与VideoTag类似

    字段 比特位 描述
    SoundFormat 4 音频数据格式。值: 0 = Linear PCM, platform endian 1 = ADPCM 2 = MP3 3 = Linear PCM, little endian 4 = Nellymoser 16-kHz mono 5 = Nellymoser 8-kHz mono 6 = Nellymoser 7 = G.711 A-law logarithmic PCM 8 = G.711 mu-law logarithmic PCM 9 = reserved 10 = AAC 11 = Speex 14 = MP3 8-kHz 15 = Device-specific sound (7,8,14,15是内部预留)
    SoundRate 2 音频采样率。值:
    0 = 5.5-kHz
    1 = 11-kHz
    2 = 22-kHz
    3 = 44-kHz
    (对于AAC来说,该字段总是3)
    SoundSize 1 采样长度。值:
    0 = snd9Bit
    1 = snd16Bit
    (对于压缩过的音频来说,一般都是16bit)
    SoundType 1 音频类型(单声道还是双声道)。值:
    0 = sndMono
    1 = sndStereo
    (对于AAC,总是1)
    SoundData n 音频数据部分(AAC则需要参考下面AACAUDIODATA部分)
    AACAUDIODATA
    字段 字节 描述
    AACPacketType 1 0:AAC 序列头<br />1:AAC 数据
    Data n 如果AACPacketType==0,参考下面的 AudioSpecificConfig 如果AACPacketType==1,即AAC原始音频数据
    AudioSpecificConfig(5个字节)
    字段 占位
    audioObjectType 5
    samplingFrequencyIndex 4
    channelConfiguration 4
    frameLengthFlag 1
    dependsOnCoreCoder 1
    extensionFlag 1
    Sync Extension Type() 11
    Extension Audio Object Type 5
    SBR Present Flag 1
    audioObjectType:2-AAC-LC,5-SBR,29-PS
    
    samplingFrequencyIndex:0-96000,1-88200,3-64000,4-44100,5-32000,6-24000,7-22050,8-16000
    
    channelConfiguration:1-单声道,2-双声道,依次类推....
    
    Frame Length Flag:0-1024 samples
    
    dependsOnCoreCoder:0-不依赖 1-依赖
    
    extensionFlag:0-Is not extention 1-Is extention
    
    Sync Extension Type():0x2b7表示HE-AAC的扩展
    
    Extension Audio Object Type:
    
    SBR Present Flag:
    
    image-20200621134531212.png
    AF:10101111  1010代表AAC  11代表44khz 1代表16Bit 1代表Stereo
    00:序列头
    12-10-56-E5-00:00010010-00010000-01010110-11100101-00000000
    00010:表示2-AAC-LC
    0100:表示4—44100
    0010:表示2-双声道
    0:表示0-1024samples
    0:表示不依赖
    0:表示is not extention
    01010110111:表示0x2b7-HE-AAC的扩展
    00101:表示5
    0:SBR Present Flag为0
    后面不足的地方全部补0
    

    所以当前Audio Tag的body Sized为2+5=7;整个Tag的size为body+header = 7+11=18

    Previous Tag Size(4个字节)

    image-20200621143858604.png

    接下来就是一个个普通的VideoTag和Audio Tag按照时间戳交替存放。记住每个Tag之后都有4个字节的Previous Tag Size.下面只列出一个Video Tag和一个Audio Tag的格式,其他的类似

    image-20200621145623930.png
    BodySize = 5+4+NALU_LENGTH;
    
    VideoTag数据部分固定的头5个字节,4个字节表示NALU长度,最后就是NALU数据部分
    
    image-20200621150831231.png
    image-20200621151256258.png
    BodySize = AAC_Data_Length+2
    
    image-20200621151801812.png

    到此为止已经介绍完FLV文件格式,flv格式还是比较简单的,header部分很简洁,body部分都是由一个个tag组成,tag的话也就三种,脚本tag一般只有一个。

    相关文章

      网友评论

          本文标题:FLV文件(H264,AAC)格式分析

          本文链接:https://www.haomeiwen.com/subject/utraxktx.html