flv 格式分析2

来源:互联网 发布:伺服电机编程实例 编辑:程序博客网 时间:2024/05/22 15:11

flv文件格式解析

date: 2014.12.10; modification:2014.12.10

目录:

  • 1 概述
  • 2 File header文件头
  • 3 Body
  • 4 Tag
    • 4.1 Tag Header
    • 4.2 Tag Data
    • 4.3 脚本Tag Data
    • 4.4 音频Tag data
    • 4.5 视频Tag data
      • 4.5.1 AVC视频封装
  • 5 参考文献

1 概述

flv文件总体分为两部分: header和body.

其中body部分又是由一个个数据段组成, 这数据段称为Tag. 其中tag又分为Tag header和Tag data. 详见后文.

它们的关系如下图

flv文件结构概览图

flv文件结构概览图

2 File header文件头

File header部分记录了flv的类型, 版本等信息, 是flv的开头, 一般都差不多, 占9bytes. 具体格式如下:

字段长度说明文件类型3 bytes字符: "FLV"版本1 byte一般为0x01流信息1 byte倒数第一位是1表示有视频, 倒数第三位是1表示有音频, 倒数第二, 四位必须为0header长度4 bytes整个header的长度, 一般为9; 大于9表示下面还有扩展信息

3 Body

body部分由一个个Tag组成, 每个Tag的下面有一块4bytes的空间, 用来记录这个tag的长度, 这个后置用于逆向读取处理.

4 Tag

每个Tag由也是由两部分组成的: Tag Header和Tag Data. Tag Header里存放的是当前Tag的类型, 数据区(Tag Data)长度等信息, 具体如下:

4.1 Tag Header

名称长度介绍Tag类型1 bytes见下文数据区长度3 bytes在数据区的长度时间戳3 bytes整数, 单位是毫秒. 对于脚本型的tag总是0时间戳扩展1 bytes将时间戳扩展为4bytes, 代表高8位. 很少用到StreamsID3 bytes总是0

Tag类型取值:

  • 8: 音频
  • 9: 视频
  • 18: 脚本
  • 其他: 保留

4.2 Tag Data

Tag header之后紧接着就是数据区(Tag data), 其长度由Tag header中的"数据区长度"字段表明. 数据区根据Tag类型的不同可分为三种, 音频数据, 视频数据和脚本数据.

4.3 脚本Tag Data

脚本Tag一般至少有一个, 用于存放flv的MetaData信息, 比如duration, audiodatarate, creator, width等. 一般这是FLV文件的第一个Tag, 因为知道了这些基本信息之后, 才好继续进行后面的解码的工作.

首先介绍下脚本的数据类型. 所有数据都是以 数据类型+(数据长度)+数据 的格式出现的, 也就是amf封装, 数据类型占1byte, 数据长度看数据类型是否存在, 后面才是数据.

其中数据类型的种类有:

  • 0 = Number type
  • 1 = Boolean type
  • 2 = String type
  • 3 = Object type
  • 4 = MovieClip type
  • 5 = Null type
  • 6 = Undefined type
  • 7 = Reference type
  • 8 = ECMA array type
  • 10 = Strict array type
  • 11 = Date type
  • 12 = Long string type

如果类型为String, 后面的2bytes为字符串的长度(Long String是4bytes), 再后面才是字符串数据; 如果是Number类型, 后面的8bytes为Double类型的数据; Boolean类型, 后面1byte为Bool类型.

知道了这些后再来看看flv中的脚本, 一般开头是0x02, 表示String类型, 后面的2bytes为字符串长度, 一般是0x000a("onMetaData"的长度), 再后面就是字符串"onMetaData". 好像flv格式的文件都有onMetaData标记, 在运行ActionScript的时候会用到它. 后面跟的是0x08, 表示ECMA Array类型, 这个和Map比较相似, 一个键跟着一个值. 键都是String类型的, 所以开头的0x02被省略了, 直接跟着的是字符串的长度, 然后是字符串, 再是值的类型, 也就是上面介绍的那些了.

4.4 音频Tag data

第一个byte是音频的信息, 格式如下.

  • 音频格式 (4bits) 取值:
    • 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
  • 采样率 (2bits) 取值:
    • 0 = 5.5-kHz
    • 1 = 11-kHz
    • 2 = 22-kHz
    • 3 = 44-kHz; 对于AAC总是3
  • 采样长度 (1bit) 取值:
    • 0 = snd8Bit
    • 1 = snd16Bit; 压缩过的音频都是16bit
  • 音频类型 (1bit) 取值:
    • 0 = sndMono
    • 1 = sndStereo; 对于AAC总是1

4.5 视频Tag data

和音频数据一样, 第一个byte是视频信息, 格式如下:

  • 帧类型 (4bits) 取值:
    • 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
  • 编码ID (4 bits) 取值:
    • 1: JPEG (currently unused)
    • 2: Sorenson H.263
    • 3: Screen video
    • 4: On2 VP6
    • 5: On2 VP6 with alpha channel
    • 6: Screen video version 2
    • 7: AVC

接下来就是具体Video的流数据的封装了.

4.5.1 AVC视频封装

对于AVC格式的video, 除了第一个字节的'帧类型'和'编码ID'之外, 从第二个字节开始分别为:

  • AVC包类型:AVCPacketType (8Bits) 取值:
    • 0: AVC sequence header
    • 1: AVC NALU
    • 2: AVC end of sequence
  • CompositionTime (24Bits) 取值:
    • 如果上面的AVCPacketType=0x01, 为相对时间戳;
    • 其它: 均为0;
  • Data (n Bytes) 为负载数据 取值:
    • 如果AVCPacketType=0x00, 为AVCDecorderConfigurationRecord;
    • 如果AVCPacketType=0x01, 为NALUs;
    • 如果AVCPacketType=0x02, 为空.

AVCDecoderConfigurationRecord详细说明:

一般第一个视频Tag会封装视频编码的总体描述信息(AVC sequence header), 就是AVCDecoderConfigurationRecord结构(ISO/IEC 14496-15 AVC file format中规定). 其结构如下:

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;    }} 

例如:

下面高亮的部分就是 FLV 文件中的 AVCDecoderConfigurationRecord 部分.

00000130h: 00 00 00 17 00 00 00 00 01 4D 40 15 FF E1 00 0A ; .........M@.?.

00000140h: 67 4D 40 15 96 53 01 00 4A 20 01 00 05 68 E9 23 ; gM@.朣..J ...h?

00000150h: 88 00 00 00 00 2A 08 00 00 52 00 00 00 00 00 00 ; ?...*...R......

根据 AVCDecoderConfigurationRecord 结构的定义:

  • configurationVersion = 01
  • AVCProfileIndication = 4D
  • profile_compatibility = 40
  • AVCLevelIndication = 15
  • lengthSizeMinusOne = FF : 非常重要, 是 H.264 视频中 NALU 的长度, 计算方法是 1 + (lengthSizeMinusOne & 3), NALU的长度怎么会一直都是4呢? 其实这不是NALU的长度, 而是NALU中, 表示长度的那个字段的长度是4字节(真绕啊).
  • numOfSequenceParameterSets = E1 : SPS 的个数, 计算方法是 numOfSequenceParameterSets & 0x1F, 结果为1
  • sequenceParameterSetLength = 00 0A : SPS 的长度
  • sequenceParameterSetNALUnits = 67 4D 40 15 96 53 01 00 4A 20 : SPS内容
  • numOfPictureParameterSets = 01 : PPS 的个数, 结果为1
  • pictureParameterSetLength = 00 05 : PPS 的长度
  • pictureParameterSetNALUnits = 68 E9 23 88 00 : PPS内容

5 参考文献

http://wuyuans.com/2012/08/flv-format/

http://blog.csdn.net/k1988/article/details/5654631

0 0
原创粉丝点击