FLV 格式解析
简介
FLV(Flash Video)是现在非常流行的流媒体格式,由于其视频文件体积轻巧、封装播放简单等特点,使其很适合在网络上进行应用,目前主流的视频网站无一例外地使用了 FLV 格式。另外由于当前浏览器与 Flash Player 紧密的结合,使得网页播放 FLV 视频轻而易举,也是 FLV 流行的原因之一。
FLV 是流媒体封装格式,我们可以将其数据看为二进制字节流。总体上看,FLV 包括文件头(File Header)和文件体(File Body)两部分,其中文件体由一系列的 Tag 及 Tag Size 对组成。
用到资源文件:
东风破.flv:https://pan.baidu.com/s/1gWewApMWwdGlS-dcquSlrg 提取码: ndpy
科比退役演讲.flv: https://pan.baidu.com/s/1OwosXhKZGQWt8f8GUVFg1w 提取码: afh3
FLV 格式解析
先来一张图,这是《科比退役演讲》下载)的一个 FLV 视频。我使用的是 UltraEdit 的二进制查看工具。
header
头部分由一下几部分组成 Signature(3 Byte)+Version(1 Byte)+Flags(1 Bypte)+DataOffset(4 Byte)
signature 占 3 个字节 固定 FLV 三个字符作为标示。一般发现前三个字符为 FLV 时就认为他是 flv 文件。图中 0x46 0x4C 0x56,代表 FLV
Version 占 1 个字节 标示 FLV 的版本号。这里我们看到是 1
Flags 占 1 个字节 内容标示。第 0 位和第 2 位,分别表示 video 与 audio 存在的情况.(1 表示存在,0 表示不存在)。截图看到是 0x05,也就是 00000101,代表既有视频,也有音频。
DataOffset 4 个字节 表示 FLV 的 header 长度。这里可以看到固定是 9
Body
FLV 的 body 部分是一系列的 back-pointers+tag 构成的
back-pointers 固定 4 个字节,表示前一个 tag 的 size
tag 分三种类型:video,audio,scripts.
tag 组成
type 1 个字节。8 为 Audio,9 为 Video,18 为 scripts
tag data size 3 个字节。表示 tag data 的长度。从 streamd id 后算起。
Timestreamp 3 个字节。时间戳
TimestampExtended 1 个字节。时间戳扩展字段
stream id 3 个字节。总是 0
tag data 数据部分
图上第一个 tag:
type=0x12=18,表示是一个 scripts,FLV 中,header 后的第一个 tag 是 script tag,script tag 内容是 amf 格式数据,包含两个 amf.
size=0x00 0x01 0x74 = 372
timpestreamp = 0x00 0x00 0x00
TimestampExtended=0x00
streamid=0x00 0x00 0x00
tag data 部分:
tag 的划分
图中红色部分是我标出"("与")"前后的的两个 back-pointers,都是 4 个字节。而括号中间就是第一个 TAG。那是怎么计算的呢?我们就以这个做个示例。
首先第一个 back-pointers 是 0x00000000,那是因为后面是第一个 TAG。所以他为 0。
然后根据我们我们前面格式获取到 size 是 0x00 0x01 0x74 = 372。也就是说从 stream id 后面再加上 372 个字节就到了第一个 TAG 的末尾,我们数一下。tag header 有 11 个字节。那么到第一个 TAG,总共有 372+11=383=0x17f。
接下来我们找到 0x17f 的地址,从工具上很容易找到,正好就是后括号")"的前面。红 0x00 0x00 0x01 0x7F=372,这代表的是上一个 TAG 的大小。
最后我们计算一下,上一个 TAG 数据部分是 372 个字节,前面 type、stream id 等字段占了 11 个字节。正好是匹配的。上面我们已经知道了怎么取划分每个 TAG。接下来我们就看 TAG 的具体内容:
tag 的内容
前面已经提到 tag 分 3 种。我们一个个看
script
脚本 Tag 一般只有一个,是 flv 的第一个 Tag,用于存放 flv 的信息,比如 duration、audiodatarate、creator、width 等。首先介绍下脚本的数据类型。所有数据都是以数据类型+(数据长度)+数据的格式出现的,数据类型占 1byte,数据长度看数据类型是否存在,后面才是数据。
一般来说,该 Tag Data 结构包含两个 AMF 包。AMF(Action Message Format)是 Adobe 设计的一种通用数据封装格式,在 Adobe 的很多产品中应用,简单来说,AMF 将不同类型的数据用统一的格式来描述。第一个 AMF 包封装字符串类型数据,用来装入一个“onMetaData”标志,这个标志与 Adobe 的一些 API 调用有,在此不细述。第二个 AMF 包封装一个数组类型(srs 返回为 object 类型),这个数组中包含了音视频信息项的名称和值。具体说明如下
上图为第一个 AMF 包
type=0x02 对应 String
size=0A=10
value=onMetaData 正好是 10 个字节。
上图为第二个 AMF
type=0x08 对应 ECMA array type。
表示数组,类似 Map。后面 4 个字节为数组的个数。然后是键值对,第一个为键,2 个字节为长度。后面跟具体的内容。接着 3 个字节表示值的类型,然后根据类型判断长度。上图我们可以判断,总共有 13 个键值对。第一个长度为 8 个字节是 duration。值类型是 0x004073,第一个字节是 00,所以是 double,8 个字节。第二个长度 5 个字节是 width。值也是 double 类型,8 个字节。依次解析下去...
Audio
视频中第二个 tag 为音频 tag
stream-id 之后:
前 4 位为音频格式
接着 2 位为采样率(对于 AAC 总是 3)
接着 1 位为采样的长度(压缩过的音视频都是 16bit)
接着 1 位为音频类型(对于 AAC 总是 1)
video
由于 kobe 视频音频编码是 pcm,查找视频 tag 太难,使用<<东风破>> mv 视频
type=0x09=9。这里应该是一个 video。
size=0x000030=48。长度为 48。
timestreamp=0x000000。
TimestampExtended =0x00。
stream id =0x000000
我们看到数据部分:视频信息+数据视频信息,1 个字节。
StreamId 之后的数据就表示是 VideoTagHeader,如果是 avc,VideoTagHeader 会多出 4 个字节的信息就是 AVCPacketType 和 CompositionTime
前 4 位为帧类型 Frame Type
后 4 位为编码 ID (CodecID)
特殊情况视频的格式(CodecID)是 AVC(H.264)的话,VideoTagHeader 会多出 4 个字节的信息,AVCPacketType 和 CompositionTime。
AVCPacketType 占 1 个字节
AVCDecoderConfigurationRecord.包含着是 H.264 解码相关比较重要的 sps 和 pps 信息,再给 AVC 解码器送数据流之前一定要把 sps 和 pps 信息送出,否则的话解码器不能正常解码。而且在解码器 stop 之后再次 start 之前,如 seek、快进快退状态切换等,都需要重新送一遍 sps 和 pps 的信息.AVCDecoderConfigurationRecord 在 FLV 文件中一般情况也是出现 1 次,也就是第一个 video tag.
CompositionTime 占 3 个字节
再看到第二个 video tag
我们看到 AVCPacketType =1,而后面三个字节为 000043。这是一个视频帧数据。解析到的数据完全符合上面的理论。
sps pps 前面我们提到第一个 video 一般存放的是 sps 和 pps。这里我们具体解析下 sps 和 pps 内容。先看下存储的格):
sps[1]=0x64sps[2]=00sps[3]=0Dsps size=0x001B=27(占两个字节)跳过 27 个字节后,是 0x01pps size=0x0005=118(占两个字节)跳过 5 个字节,就到了 back-pointers。
视频帧数据解析出 sps 和 pps tag 后,后面的 video tag 就是真正的视频数据内容了
这是第二个 video tag 其实和之前图一样,只是我圈出来关键信息。先看下格式 frametype=0x17=00010111AVCPacketType =1Composition Time=0x000043 后面就是 NALU DATA
引用:
(原)从mp4,flv文件中解析出h264和aac,送解码器解码失败:,avc1 与 H264 区别在这里其实有人遇到了和我一样的问题:http://stackoverflow.com/questions/11330764/ffmpeg-cant-decode-h264-stream-frame-data
版权声明: 本文为 InfoQ 作者【轻口味】的原创文章。
原文链接:【http://xie.infoq.cn/article/ee5b8c4fdab1017abfe12f8e3】。文章转载请联系作者。
评论