音视频技术以及FLV封装格式详解
Contents
音视频技术及解析FLV封装格式
1.播放网络视频的流程
要从网络上播放一个视频,大致流程如下:
可见,一个网络视频从网络传输和播放这个过程,经过了如下一些过程:
首先最上面的数据,是从互联网上接受的流媒体数据,所以:
解协议: stream media data --> 封装格式数据 (eg. FLV)
常见的封装的流式数据格式有以下:
FLV
MP4
MKV
AVI 等等
解封装,将音频和视频数据分开
解封装 封装格式数据(eg FLV) -——> 音频压缩编码数据(ACC) + 视频压缩编码数据 (eg H.264)
解码 这一环是非常重要的,原生的图像和声音数据,如果不经过压缩编码,数据量会非常庞大,所以,解码就是从压缩的数据中,还原声音和图像的原始数据。
解码: 压缩格式数据(eg H.264) --> 非压缩颜色数据 (eg.YUV420P)
最后根据封装模块的参数信息,同步解码出来的视频和音频数据,分别送到显卡和声卡播放出来
2.FLV 详解
首先,FLV作为一种流媒体数据格式,非常适合在网络上传输,它内部结构大致如下:
即: FLV = Header + Body Body= PreviousTagSize (4bytes) + Tag
2.1header
Signature(3 Byte)+Version(1 Byte)+Flags(1 Bypte)+DataOffset(4 Byte)
- signature 占3个字节 固定FLV三个字符作为标示。一般发现前三个字符为FLV时就认为他是flv文件。
- Version 占1个字节 标示FLV的版本号。这里我们看到是1
- Flags 占1个字节 内容标示。第0位和第2位,分别表示 video 与 audio 存在的情况.(1表示存在,0表示不存在)
- DataOffset 4个字节 表示FLV的header长度。这里可以看到固定是9
2.2 body
FLV的body部分是由一系列的back-pointers + tag构成 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 数据部分
script tag
脚本Tag一般只有一个,是flv的第一个Tag,用于存放flv的信息,比如duration、audiodatarate、creator、width等 一般包含了两个amf包,数据的格式都是:
数据类型+(数据长度)+数据
第一个AMF包: 第1个字节表示AMF包类型,一般总是0x02,表示字符串。第2-3个字节为UI16类型值,标识字符串的长度,一般总是0x000A(“onMetaData”长度)。后面字节为具体的字符串,一般总为“onMetaData”(6F,6E,4D,65,74,61,44,61,74,61)
第二个AMF包:
第1个字节表示AMF包类型,一般总是0x08,表示数组。第2-5个字节为UI32类型值,表示数组元素的个数。后面即为各数组元素的封装,数组元素为元素名称和值
组成的对。常见的数组元素如下表所示:
audio tag
音频Tag Data区域开始的第一个字节包含了音频数据的参数信息,从第二个字节开始为音频流数据。结构如下:
第一个字节包含参数信息,前4位是音频格式,5-8位分别表示了采样率、采样精度、音频声道信息,各个位表示情况如下:
第二个字节开始为音频数据。
video tag
视频Tag Data开始的第一个字节包含视频数据的参数信息,从第二个字节开始为视频流数据。结构如下:
参数信息对应如下:
后面接着的就是视频数据。
是一段以字节对齐的流数据,具体怎么构成要看第一个字节中的编码格式,这里着重介绍下 AVC VIDEO PACKET:
- 关于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是一种结构清晰的流媒体格式,在接收到数据后,总是可以根据每一段的最前面(header) 部分,得知后面紧跟的数据如何展开,例如,对每一个TAG,可以知道它是音频视频还是脚本,再根据其长度,可以找到数据结尾的偏置值。然后再对tag data展开时,又可以根据第一个字节找到其类型,根据该类型的指定格式进行解码等操作。
Author 秋酱
LastMod 2020-08-31