flv文件结构解析

  1. FLV文件格式相对于MP4,简单很多。
    FLV Header(9Bytes) + FLV Body

                 a比特: 1:有音频; 0:无音频
                 v比特: 1:有视频; 0:无视频   如果音视频都有这个字节为0x05
    

    ‘F’|‘L’|‘V’|0x01|0b00000a0v| 0x00 00 00 09|
    | |
    版本字节一般为0x01 头长度 固定为9

    FLV Body由一系列的Tag组成,每个tag的结构如下:
    { 0x00000000| tag_header0| tag_data0 } | {tag_size0| tag_header1 | tag_data1 } | {tag_size1| tag_header2 | tag_data2 } |…
    tag_size(n) = tag_data_size(n-1) + 11
    解析完一个tag后,读取下4个字节,可以比较下看是不是前帧完全解码完毕。
    除了可以验证码流外,还有什么样的好处促使FLV格式采用这种方式呢?不太清楚。

     0x00000000| { tag_header0| tag_data0  | tag_size0} | { tag_header1 | tag_data1 | tag_size1} |...
    
    Tag body也可以这样看,编码时按照: 数据头 数据体 数据大小 三部分来划分,更适合一些。下面各个tag都是按照这个结构来写的。 
    

    Tag header 11Bytes

    |1Byte Tag类型 | 只支持3类, 0x08音频; 0x09视频;0x12脚本
    |3Byte data_size数据区长度 | 纯数据长度,不包括头信息的15字节
    |3Byte timestamp 时间戳 | 最终的时间戳 = (timestamp_ex<< 24) | timestamp
    |1Byte timestamp_ex扩展时间戳 | 最终时间戳的高8位。不知道为什么定义成这样,可能是因为标准扩展
    |3Byte StreamID | 总为0

    Tag Data data_size字节
    |Tag数据段,长度为data_size… | 音视频或者脚本数据。
    |4Byte PreviousTagSize | 是前一个Tag数据长度,第一个Tag此数据段为0.

  2. 视频Tag
    视频数据的第一个字节定义视频信息:
    高4比特定义帧格式:1 关键帧; 2 内部帧(非IDR帧);3可丢弃内部帧(仅对H.263有用)
    低4比特定义编码器:2:H.263, 4: VP6, 7:H264; …
    对于264的视频FLV,这个字节一般为 0x17或者0x27.

  3. 音频tag
    音频数据的第一个字节定义视频信息:
    高4比特定义音频编码格式:0 Linear PCM, 1: ADPCM, 2: MP3, 10:AAC …
    第4,3两比特定义采样率: 0 5.5KHz, 1 11KHz, 2 22KHz, 3 44KHz. 对于AAC该值总为3
    第2比特定义采样大小: 0 8比特,1 16比特
    第1比特定义声道数: 0 单声道,1 立体声

  4. 脚本tag
    理论上不需要解析脚本Tag就可以解码FLV文件,它只是提供了一些信息记录。
    脚本Tag里面的类型比较多,格式也不一样。
    Number 类,记录一个8字节double数据。|0x00|8字节data|.
    Boolean类,记录一个1字节布尔型数据。|0x01|1字节data|.
    String类,记录一个变长字符串数据。 |0x02|2字节 字符串长度 N| N字节字符串内容|.
    注意读取完字符串后加一个’\0’字符串结束符号。因此字符串申请的时候,长度为N+1.
    ECMA array type, 记录一些数据对。

     |0x08| 4字节 数组长度 N|2字节 字符串长度 m1 | m1字节字符串内容|1字节 data1 type | X字节 data1 | ...
    
                                            |2字节 字符串长度 Nm| Nm字节字符串内容|1字节 dataN type| X字节 dataN|           
                   有N个数据对                  元素名    (长度|数据)                               元素值(类型|数据)
    
             一般用这个记录一些音视频信息,例如:
    
                                                             0x0008                         "duration"                   0x00      8字节double
                                                             0x0005                            "width"                     0x00      8字节double
                                                             0x0006                           "stereo"                    0x01      1字节boolean型  
    

    Strict array type类,记录一组数据。
    |0x0A|4字节 数组长度 N| 1字节 data1 type| X字节 data1 | …
    |1字节 dataN type| X字节 dataN|
    有N个数据, 每个数据的类型 数据值
    一般会用这个类记录关键帧的偏移地址和对应的pts值。类型都是 Number类,即X=8字节double型
    Object type, 记录对象数据。一般用它来做keyframes的数据存储起始。

5.keyframes字段
FLV没有像mp4一样定义stbl,FLV文件如果做快进,seek等操作会比较麻烦。
业内通用做法是在脚本Tag里面增加keyfrmes object类。一般定义为:

|00 09| 9字节 “keyframes”|00 0D| 13字节 “filepositions”|0A| 4字节关键字数目 N|00|8字节 关键帧1偏移地址| …
|00|8字节 关键帧N偏移地址|
|00 05| 5字节 “times” |0A| 4字节关键字数目 N|00|8字节 关键帧1时间| …
|00|8字节 关键帧N时间|
有了各个关键帧的偏移地址和时间,做Seek操作的时候就方便的多。

  1. 读取8字节double型,这个牵扯浮点型的存储结构问题,蛮罗嗦,没看明白,但找到下面一段代码可以实现转换。
    uint64_t v = get_8bytes();
    if(v+v > 0xFFEULL<<52) return 0.0/0.0;
    double x = ldexp(((v&((1LL<<52)-1)) + (1LL<<52)) * (v>>63|1), (v>>52&0x7FF)-1075);

  2. FLV结构里面,数据长度有3字节和4字节限制,不会像Mp4一样出现8字节长度。
    3字节最大表示16M数据,4字节最大是4G数据。
    一个Video Tag里面的NALU长度不能超过16M字节。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值