FLV文件格式解析

 flv文件主要由两部分组成:header和body。

1.header

header部分记录了flv的类型、版本等信息,是flv的开头,一般都差不多,占9bytes。具体格式如下:
文件类型 3 bytes “FLV”
版本 1 byte 一般为0x01
流信息 1 byte 倒数第一位是1表示有视频,倒数第三位是1表示有音频,倒数第二、四位必须为0
header长度 4 bytes 整个header的长度,一般为9;大于9表示下面还有扩展信息

2.body

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


2.1.Tag

每个Tag由也是由两部分组成的:Tag Header和Tag Data。Tag Header里存放的是当前Tag的类型、数据区(Tag Data)长度等信息,具体如下:
名称 长度 介绍
Tag类型 1 bytes 8:音频
9:视频
18:脚本
其他:保留
数据区长度 3 bytes 在数据区的长度
时间戳 3 bytes 整数,单位是毫秒。对于脚本型的tag总是0
时间戳扩展 1 bytes 将时间戳扩展为4bytes,代表高8位。很少用到
StreamsID 3 bytes 总是0
数据区(data) 由数据区长度决定 数据实体

2.2.Tag Data

数据区根据Tag类型的不同可分为三种,音频数据、视频数据和脚本数据。

2.2.1.音频数据
第一个byte是音频的信息,格式如下。
名称 长度 介绍
音频格式 4 bits 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
采样率 2 bits 0 = 5.5-kHz
1 = 11-kHz
2 = 22-kHz
3 = 44-kHz
对于AAC总是3
采样的长度 1 bit 0 = snd8Bit
1 = snd16Bit
压缩过的音频都是16bit
音频类型 1 bit 0 = sndMono
1 = sndStereo
对于AAC总是1
第2byte开始就是音频流数据了。
2.2.2.视频数据


Field

type

Comment

帧类型

UB4

1: keyframe (for AVC, a seekable frame)——h264的IDR,关键帧,可重入帧。

2: inter frame (for AVC, a non- seekable frame)——h264的普通帧

3: disposable inter frame (H.263 only)
4: generated keyframe (reserved for server use only)

5: video info/command frame

编码ID

UB4

使用哪种编码类型:

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

视频数据

UI[N]

如果是avc,则参考下面的介绍:

AVCVIDEOPACKET

AVCVIDEOPACKET


Field

type

Comment

AVC packet类型

UI8

0:AVC序列头

1:AVC NALU单元

2:AVC序列结束。低级别avc不需要。

CTS

SI24

如果AVC packet类型是1,则为cts偏移(见下面的解释),为0则为0

数据

UI8[n]

如果AVC packet类型是0,则是解码器配置,sps,pps。

如果是1,则是nalu单元,可以是多个,具体格式:将下面

关于CTS:这是一个比较难以理解的概念,需要和pts,dts配合一起理解。

首先,pts(presentation time stamps),dts(decoder timestamps),cts(CompositionTime)的概念:

pts:显示时间,也就是接收方在显示器显示这帧的时间。单位为1/90000 秒。

dts:解码时间,也就是rtp包中传输的时间戳,表明解码的顺序。单位单位为1/90000 秒。——根据后面的理解,pts就是标准中的CompositionTime

cts偏移:cts = (pts - dts) / 90 。cts的单位是毫秒。

pts和dts的时间不一样,应该只出现在含有B帧的情况下,也就是profile main以上。baseline是没有这个问题的,baseline的pts和dts一直想吐,所以cts一直为0。

在flv tag中的时戳就是DTS。

研究 一下文档,  ISO/IEC 14496-12:2005(E)      8.15   Time to Sample Boxes,发现CompositionTime就是presentation time stamps,只是叫法不同。——需要再进一步确认。

在上图中,cp就是pts,显示时间。DT是解码时间,rtp的时戳。

I1是第一个帧,B2是第二个,后面的序号就是摄像头输出的顺序。决定了显示的顺序。

DT,是编码的顺序,特别是在有B帧的情况,P4要在第二个解,因为B2和B3依赖于P4,但是P4的显示要在B3之后,因为他的顺序靠后。这样就存在显示时间CT(PTS)和解码时间DT的差,就有了CT偏移。

P4解码时间是10,但是显示时间是40,

AVCVIDEOPACKET中data格式:

Field

type

Comment

长度

UI32

nalu单元的长度,不包括长度字段。

nalu数据

UI8[N]

NALU数据,没有四个字节的nalu单元头,直接从h264头开始,比如:65 ** ** **,41 **  ** ** 

长度

UI32

nalu单元的长度,不包括长度字段。

nalu数据

UI8[N]

NALU数据,没有四个字节的nalu单元头,直接从h264头开始,比如:65 ** ** **,41 **  ** ** 

...

...

...

Data tags


主要是onMeta信息需要关注。

AVCDecoderConfigurationRecord


AVCVIDEOPACKET的数据格式,保存控制信息。

记录sps,pps信息。一般出现在第二个tag中,紧跟在onMeta之后。

一个典型的序列:

0000190: 0900 0033 0000 0000 0000 0017 0000 0000  ...3............
00001a0:0164 002a ffe1 001e 6764 002a acd9 4078  .d.*....gd.*..@x
00001b0:0227 e5ff c389 4388 0400 0003 0028 0000  .'....C......(..
00001c0:0978 3c60 c658 0100 0568 ebec b22c 0000  .x<`.X...h...,..
17:表示h264IDR data
00:表示是AVC序列头
00 00 00 :cts为0
//从此往下就是AVCDecoderConfigurationRecord
01 :版本号
64 00 2a:profile level id,sps的三个字节,64表示是h264 high profile,2a表示level。
FF:NALU长度,为3?不知道这个长度用在哪里。
E1:表示下面紧跟SPS有一个。
//sps[N]:sps数组。
00 1e:    前面是两个字节的sps长度,表示后面的sps的长度是1e大小。
6764 002a acd9 4078 0227 e5ff c389 4388 0400 0003 0028 0000 0978 3c60 c658:sps的数据。
//因为只有一个sps,跳过这些长度,然后就是pps的个数信息:
01 :pps个数,1
//pps[n] pps 的个数
00 05:表示pps的大小是5个字节。
68 eb ec b2 2c:pps的数据
00 00 …….这是下一个tag 的内容了

2.2.3脚本数据

脚本Tag一般只有一个,是flv的第一个Tag,用于存放flv的信息,比如duration、audiodatarate、creator、width等。

首先介绍下脚本的数据类型。所有数据都是以数据类型+(数据长度)+数据的格式出现的,数据类型占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被省略了,直接跟着的是字符串的长度,然后是字符串,再是值的类型,也就是上面介绍的那些了。

参考链接

https://wuyuans.com/2012/08/flv-format/
http://blog.csdn.net/chgaowei/article/details/51243345



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值