写点什么

FLV 格式解析

用户头像
轻口味
关注
发布于: 13 小时前

简介

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 组成
tag type+tag data size+Timestamp+TimestampExtended+stream id+ tag data
复制代码


  • 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 内容。先看下存储的格):


0x01+sps[1]+sps[2]+sps[3]+0xFF+0xE1+sps size+sps+01+pps size+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


引用:


flv格式详解+实例剖析


FLV视频封装格式详解


【总结】FLV(AAC/AVC)学习笔记


将h.264视频流封装成flv格式文件(一.flv格式)


将h.264视频流封装成flv格式文件(二.开始动手)


RTMP协议中的AMF数据


rtmp协议简单解析以及用其发送h264的flv文件


FLV 文件格式解析


(原)从mp4,flv文件中解析出h264和aac,送解码器解码失败:,avc1 与 H264 区别在这里其实有人遇到了和我一样的问题:http://stackoverflow.com/questions/11330764/ffmpeg-cant-decode-h264-stream-frame-data


simplest_mediadata_test


rtmp_relayRtmpMindmap


发布于: 13 小时前阅读数: 3
用户头像

轻口味

关注

100位签约计划优质创作者 2017.10.17 加入

Android音视频、AI相关领域从业者

评论

发布
暂无评论
FLV格式解析