音视频技术及解析FLV封装格式

1.播放网络视频的流程

要从网络上播放一个视频,大致流程如下:

可见,一个网络视频从网络传输和播放这个过程,经过了如下一些过程:

  1. 首先最上面的数据,是从互联网上接受的流媒体数据,所以:

    解协议:
    stream media data  --> 封装格式数据 (eg. FLV) 
    

    常见的封装的流式数据格式有以下:

  2. FLV

  3. MP4

  4. MKV

  5. AVI 等等

  6. 解封装,将音频和视频数据分开

    解封装
    封装格式数据(eg FLV) -——>  音频压缩编码数据(ACC) + 视频压缩编码数据 (eg H.264)
    
    
  7. 解码 这一环是非常重要的,原生的图像和声音数据,如果不经过压缩编码,数据量会非常庞大,所以,解码就是从压缩的数据中,还原声音和图像的原始数据。

    解码:
    压缩格式数据(eg H.264) -->  非压缩颜色数据 (eg.YUV420P)
    
  8. 最后根据封装模块的参数信息,同步解码出来的视频和音频数据,分别送到显卡和声卡播放出来

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展开时,又可以根据第一个字节找到其类型,根据该类型的指定格式进行解码等操作。