注:参考自bilibili系列视频,从0开始做播放器-第6章-图像编码的基础概念(理论课)https://www.bilibili.com/video/BV1PK41157jz
常见编码格式
视频需要编码,是因为采集来的原始视频太大,一部720p的电影,存原始图像就需要大约1T。所以需要编码,把原始图像压缩,便于我们传输和存储。
- H264 诞生于2003年,是目前最常见的编码方式
- H265 是H264的继任者,相比H264,H265性能更好,压缩的更小,但是很耗硬件,很多硬件不支持;H265不能广泛使用的另一个原因是,H5浏览器还不支持H265,主要H265专利费比较贵。
- VP8 由 Google 发布,Youtube和google在用
- VP9 是VP8的继任者,由 Google 发布,Youtube和google在用
- AVS(Audio Video coding Standard)国产,常见于政府项目,安防领域
- AVS2 是AVS的继任者,国产,常见于政府项目,安防领域
H264
-
SPS 序列参数集
- profile,定义基础配置
- 视频长宽
-
PPS 图像参数集
- 码流中熵编码/解码选择的算法
一般来说,编码器编出的首帧数据为PPS和SPS,接着为I帧(注: 要想解码一路流,必须先把SPS和PPS传给解码器。)(https://zhuanlan.zhihu.com/p/27896239SPS和PPS详解)
I帧 关键帧,保存整个图像的信息,自身可以通过视频解压算法解压成一张单独的完整的图片。I帧图像用于阻止误差的累积和扩散。在闭合式GOP中,每个GOP的第一个帧一定是I帧,且当前GOP的数据不会参考前后GOP的数据。
P帧 前向预测帧,只记录本帧与前一帧的差别
B帧 双向预测帧,只记录本帧与前一帧和后一帧的差别;B帧具有更高的压缩率,但需要更多的缓冲时间以及更高的CPU占用率,因此B帧适合本地存储以及视频点播,而不适用对实时性要求较高的直播系统。
NALU,帧,slice,宏块之间的关系
H264原始码流(裸流)是由一个接一个NALU组成,H264分为两个层面,VCL(视频编码层)和 NAL(网络提取层)。
- VCL(video coding)视频编码层:负责有效表示视频数据的内容;
- NAL(network abstraction)网络抽象层:负责格式化数据并提供头信息,以保证数据适合各种信道和存储介质上的传播。
H264结构中,一个视频图像编码后的数据叫做一帧(frame),一帧由一个片(slice)或多个片组成,一个片由一个或多个宏块(MB)组成,一个宏块由16x16的yuv数据组成。宏块作为H264编码的基本单位。
NALU是一种封装的模组 ,一个Slice编码之后被打包进一个NALU,不过NALU除了容纳Slice编码的码流外,还可以容纳其他数据,比如序列参数集SPS。所以nalu不一定是slice。
拓展:
那么为什么要设置片(slice)呢?
设置片(slice)的目的是为了限制误码的扩散和传输,应使编码片相互间是独立的。某片的预测不能以其他片中的宏块为参考图像,这样某一片中的预测误差才不会传播到其他片中。
PTS和DTS
PTS:显示时间戳,表示解码后的帧显示的时间
DTS:解码时间戳,表示送入解码器的顺序
NALU (Network Abstract Layer Unit)
- nalu type 如下图,常用的是1,5,7,8。
- 1是非IDR帧 有可能是I帧,P帧,B帧
-
5是IDR帧,IDR帧一定是I帧,但I帧不一定是IDR帧。IDR帧前面通常会有SPS和PPS。
IDR帧常用于流媒体,因为存成文件的话,SPS、PPS信息会存在文件头,只存一次就可以,而流媒体,由于是网络流,
1.只发一次SPS我们无法保证服务器一定会接收到;
2.就算第一次发SPS就接收到了,那也需要一直在服务器缓存;
3.如果直播小姐姐切换了前后摄像头,SPS和PPS就会变化,如果还用第一次接收到的SPS,就会出错
所以就需要IDR帧的存在,隔一段时间,就传一下SPS和PPS。 - 7是SPS 序列参数集
-
8是PPS 图像参数集
- 获取nalu type
start code后面一个字节的低5位,获取方法:int naluType = nalu[4]0x1f,这里是常犯错误的地方。
H264的两种存储形态
Annex B
- startCode NALU 以0001或001开头
- 防竞争字节 编码时,slice数据里如果出现000,就插入0x3,这样,slice里所有的 0001 ,就被转换为 000 0x3 1;解码时,将slice数据中000后面的0x3去掉,就可以还原数据。
- 多用于网络流媒体中,rtp,rtmp等
AVCC
- 表示NALU长度的前缀,不定长,有时1字节,有时2字节,有时4字节
- 防竞争字节,同上,将000后面插入0x3,在AVCC中,由于没有startCode,这个操作对于AVCC格式是没有实际意义的,但是要遵从标准,所以也这样做了。遵从标准,有助于不同存储形态之间转换。
- 多用于文件存储中,如mp4
GOP
GOP是画面组,一个GOP是一组连续的画面。
GOP结构一般是:
I BBP BBP BBP BB I
增大图片组能有效的减少编码后的视频体积,但是也会降低视频质量。
常见误区
- 分辨率越大码率越大吗?
不一定。码率是单位时间内,传输的编码后的数据位数。码率约等于传输速率。
码率由什么决定:
- 分辨率,影响较小
- 画面混乱程度,单帧图像,混乱程度越高,同等质量下,编码后的数据量越大;图像越简单,编码后的数据越小。
- 画面之间的变化量越大,编码后的数据量越大。
- 编码(压缩)程度,画面混乱程度相等时,压缩的狠,画质可能不好,但编码后数据会小
- P帧一定比I帧小,B帧一定比P帧小
- P帧不一定比I帧小,当场景转换的时候,临界两帧,比如前一帧是室内简单场景,是I帧,后一帧是室外复杂场景,是P帧,P帧存的是与前一帧的变化量,场景转换时,前后两帧差距太大,P帧数据量就会很大。所以P帧不一定比I帧小。
- B帧不一定比P帧小,也是在场景转换的时候,B帧有可能跟前后某帧差别很大,无法参考数据,于是数据量很大。
- 所以说,每类帧类型的使用位置还是很重要的,每一帧给合适的帧类型,才能发挥好压缩效果