概述
-
问:音视频处理主要以解码、特效、音视频合成等为主,为什么先介绍编码?
答:只有对编码原理和码流理解得足够彻底,才能做好开发工作,视频的开发不是简单地调用api,理解不透彻的话,遇到问题可能会毫无头绪,很可能连api都不知道怎么用,编码可以直接理解为压缩,将原始的yuv数据压缩为体积更小的数据 -
问:什么是H264?
答:提到视频编码,不得不提到大名鼎鼎的H.264。目前常见的编码标准有H264、H265、VP8、VP9 和 AV1,而其中用的最普遍的视频编码就是H.264(所以本文主要就来详细介绍一下它)。H264和H265都是国际标准化组织(ISO)和国际电信联盟(ITU)开发的编码标准,而VP8、VP9 和 AV1是谷歌开发的编码标准
编码的思路
大家都知道编码的目的是压缩原始数据,方便保存和传输,如何压缩?大体可以从一下3个方面来着手
- 帧内预测压缩,一张图像相邻的两个像素颜色可能很相似,那么它们的数据也就很相似,那么就产生了冗余数据,帧内压缩主要解决这部分冗余问题
- 帧间预测压缩,相邻的两帧图像往往很相似,同理,这里也产生了冗余数据,帧间压缩主要解决这部分冗余问题
- 整数离散余弦变换(DCT),将空间上的相关性变为频域上无关的数据然后进行量化,图像中人眼不敏感的信息会产生一些视觉上的冗余数据,DCT主要解决视觉冗余问题
- 熵编码,真正的编码开始了,将上面三部分得到的数据,进行编码算法的到最终的码流
预测编码
预测编码(Predictive Coding)是统计冗余数据压缩理论三个重要分支之一,它的理论基础是现代统计学和控制论,用预测编码可以减少数据时间和空间的相关性,它广泛地用于时间序列图像数据和语音数据的压缩编码。预测编码的方法是从相邻象素之间有较强的相关性特点考虑,比如当前象素的灰度或颜色信号,数值上与其相邻象素总是比较接近,除非处于边界状态,那么,当前象素的灰度或颜色信号的数值,可用前面已出现的象素的值进行预测(估计),得到一个预测值(估计值),将实际值与预测值求差,对这个差值信号进行编码、传送,这种编码方法称为预测编码方法。预测编码方分线性预测和非线性预测编码两种。
帧内预测
一帧图像中相邻像素的亮度和色度信息是比较接近的,并且亮度和色度信息也是逐渐变化的,不太会出现突变。也就是说,图像具有空间相关性。 利用这种相关性,视频压缩就可以去除空间冗余信息。 帧内预测,通过已编码的像素来预测待编码的像素值,最后达到减少空间冗余的目的,具体思路详看上述预测编码
章节,具体步骤如下:
- 划分
宏块
为了通过已编码的像素来预测尚未编码的像素,需要将一帧图像划分为若干个区域, 每个区域叫做宏块,宏块是编码标准的基本处理单元,通常它的大小为 16x16 像素(H264 默认是使用 16X16 大小的区域作为一个宏块,也可以划分成 8X8 大小的宏块)
- 划分
- 划分子块(图像中细节复杂的地方)
16X16 的宏块上可以划分出更小的子块。子块的大小可以是 8X16、 16X8、 8X8、 4X8、 8X4、 4X4。
- 划分子块(图像中细节复杂的地方)
- 对每个宏块进行预测
预测模式多达九种,预测模式就不在本文详解了,预测后找出与原图最接近的一种模式,然后计算差值(残差值),将差值和预测模式一起保存下来,就可以还原原始图像了
- 对每个宏块进行预测
帧间预测
- 帧分组
对于视频数据主要有两类数据冗余,一类是时间上的数据冗余,另一类是空间上的数据冗余。.其中时间上的数据冗余是最大的。下面我们就先来说说视频数据时间上的冗余问题。
为什么说时间上的冗余是最大的呢?假设摄像头每秒抓取30帧,这30帧的数据大部分情况下都是相关联的。也有可能不止30帧的的数据,可能几十帧,上百帧的数据都是关联特别密切的。
对于这些关联特别密切的帧,其实我们只需要保存一帧的数据,其它帧都可以通过这一帧再按某种规则预测出来,所以说视频数据在时间上的冗余是最多的。
为了达到相关帧通过预测的方法来压缩数据,就需要将视频帧进行分组。那么如何判定某些帧关系密切,可以划为一组呢?
分组即 H264 中的 序列(GOP
)。其算法是:在相邻几幅图像画面中,一般有差别的像素只有 10% 以内的点,亮度差值变化不超过 2%,而色度差值的变化只有 1% 以内,我们认为这样的图可以分到一组,在这样一组帧中,经过编码后,我们只保留第一帖的完整数据,其它帧都通过参考上一帧计算出来。我们称第一帧为 IDR/I帧,其它帧我们称为 P/B帧,这样编码后的数据帧组我们称为 GOP。
所以如果场景一直没什么变化,则一系列视频帧中 I 帧的数量会很少。如果场景变换很复杂,一直在场景变换大的场景切换时就会有 I 帧出现。
- 帧分组
- 帧间预测(运动估计与运动补偿)
H264 编码器先按顺序从编码缓冲区取出两帧图像数据,然后进行宏块扫描。当发现其中一帧图像中有物体时,就在另一帧的邻近位置进行匹配。如果此时在另一帧图像中匹配了该物体,那么就可以计算出物体的运动矢量了,运动矢量计算出来以后,将两帧图像相同部分的数据减掉,就得到了补偿数据,通过补偿数据即可还原图像了
我们把运动矢量与补偿称为帧间压缩技术,它解决的是视频帧在时间上的数据冗余。在这一步我们获取了 P/B 帧
- 帧间预测(运动估计与运动补偿)
DCT(离散余弦变换)
- 首先说说图像频率是什么。图像可以看做是一个定义为二维平面上的信号,该信号的幅值对应于像素的灰度值(对于彩色图像则是RGB三个分量),如果我们仅仅考虑图像上某一行像素,则可以将之视为一个定义在一维空间上的信号,这个信号在形式上与传统的信号处理领域的时变信号是相似的,时变信号是有一定频率成分的,图像的频率又称为空间频率,它反映了图像的像素灰度在空间中变化的情况。
- 一般图片的高频信息多但是幅值比较小。高频信息主要描述图片的边缘或者细节信息,对于快速空间变化的图像来说,比如充满沟壑的山脉,其高频成分会相对较强,低频则较弱。而低频主要是图像的整体轮廓信息。由于人眼的视觉敏感度是有限的,有的时候我们去除了一部分高频信息之后,人眼看上去感觉区别并不大。这就是去除视觉冗余。
- 因此,我们可以先将图片通过 DCT(离散余弦变换) 变换到频域,然后再去除一些高频信息。这样我们就可以减少信息量,从而达到压缩的目的
熵编码
- 主要去除信息熵冗余。而前面说的去除空间、时间、视觉冗余,其实都是为这一步做准备的。
- 前面的帧内帧间预测得到的残差以及后面的变换量化,都是将数据尽量转换为连续的0更多的表现形式,然后再利用合理的编码算法去编码形成最终的码流。
- 视频内容部分使用的是内容自适应的(CABAC或CAVLC)算术编码。具体编码算法这里就不深入了,不过核心思想都是利用了连续的‘0’尽可能去进行压缩
不喜勿喷
视频编解码技术太过复杂,本人也在学习中,本文写的很浅显,内容也大部分参考网上内容,有错误的地方还请指正,不喜勿喷,谢谢!
网友评论