视频压缩技术详解
H264压缩技术
H264 编码器采用的是变换和预测的混合编码法。由上图所示,输入的帧或场 Fn 以宏块为单位被编码器处理。首先,按帧内或帧间预测编码的方法进行处理。
如果采用帧内预测编码,其预测值 PRED(图中用 P 表示)是由当前片中前面已编码的参考图像经运动补偿( MC)后得出,其中参考图像用 F’n-1 表示。为了提高预测精度,从而提高压缩比,实际的参考图像可在过去或未来(指显示次序上)已编码解码重建和滤波的帧中进行选择。
预测值 PRED 和当前块相减后,产生一个残差块 Dn,经块变换、量化后产生一组量化后的变换系数 X,再经熵编码,与解码所需的一些边信息(如预测模式量化参数、运动矢量等)一起组成一个压缩后的码流,经 NAL(网络自适应层)供传输和存储用。
H264 视频格式是经过有损压缩的,但在技术上尽可能做的降低存储体积下获得较好图像质量和低带宽图像快速传输。
H264压缩技术主要采用了以下几种方法对视频数据进行压缩。包括:
- 帧内预测压缩,解决的是空域数据冗余问题。
- 帧间预测压缩(运动估计与补偿),解决的是时域数据冗余问题。
- 整数离散余弦变换(DCT),将空间上的相关性变为频域上无关的数据然后进行量化。
- CABAC压缩。
H264结构中,一个视频图像编码后的数据叫做一帧,一帧由一个片(slice)或多个片组成,一个片由一个或多个宏块(MB)组成,一个宏块由16x16的yuv数据组成。宏块作为H264编码的基本单位。
在H264协议内定义了三种帧,分别是I帧、B帧与P帧。I帧就是之前所说的一个完整的图像帧,而B、帧与P帧所对应的就是之前说的不编码全部图像的帧。P帧与B帧的差别就是P帧是参考之前的I帧而生成的,而B帧是参考前后图像帧编码生成的。
经过压缩后的帧分为:I帧,P帧和B帧:
- I帧:关键帧,采用帧内压缩技术。你可以理解为这一帧画面的完整保留;解码时只需要本帧数据就可以完成(因为包含完整画面)
- P帧:向前参考帧,在压缩时,只参考前面已经处理的帧。采用帧间压缩技术。P帧表示的是这一帧跟之前的一个关键帧(或P帧)的差别,解码时需要用之前缓存的画面叠加上本帧定义的差别,生成最终画面。(也就是差别帧,P帧没有完整画面数据,只有与前一帧的画面差别的数据)
- B帧:双向参考帧,在压缩时,它既参考前而的帧,又参考它后面的帧。采用帧间压缩技术。B帧记录的是本帧与前后帧的差别(具体比较复杂,有4种情况),换言之,要解码B帧,不仅要取得之前的缓存画面,还要解码之后的画面,通过前后画面的与本帧数据的叠加取得最终的画面。B帧压缩率高,但是解码时CPU会比较累~。
还有一个概念是,IDR帧:
一个序列的第一个图像叫做 IDR 图像(立即刷新图像),IDR 图像都是 I 帧图像。H.264 引入 IDR 图像是为了解码的重同步,当解码器解码到 IDR 图像时,立即将参考帧队列清空,将已解码的数据全部输出或抛弃,重新查找参数集,开始一个新的序列。这样,如果前一个序列出现重大错误,在这里可以获得重新同步的机会。IDR图像之后的图像永远不会使用IDR之前的图像的数据来解码。IDR 图像一定是 I 图像,但I图像不一定是 IDR 图像。一个序列中可以有很多的I图像,I 图像之后的图像可以引用 I 图像之间的图像做运动参考。
还有一点注意的,对于 IDR 帧来说,在 IDR 帧之后的所有帧都不能引用任何 IDR 帧之前的帧的内容,与此相反,对于普通的 I 帧来说,位于其之后的 B- 和 P- 帧可以引用位于普通 I- 帧之前的 I- 帧。从随机存取的视频流中,播放器永远可以从一个 IDR 帧播放,因为在它之后没有任何帧引用之前的帧。但是,不能在一个没有 IDR 帧的视频中从任意点开始播放,因为后面的帧总是会引用前面的帧。
继续再多补充一个概念,图像组(GOP):
一个序列就是一段内容差异不太大的图像编码后生成的一串数据流。当运动变化比较少时,一个序列可以很长,因为运动变化少就代表图像画面的内容变动很小,所以就可以编一个 I 帧,然后一直 P 帧、B 帧了。当运动变化多时,可能一个序列就比较短了,比如就包含一个 I 帧和 3、4个P帧。
GOP是画面组,一个GOP是一组连续的画面。
GOP一般有两个数字,如M=3,N=12。M指定I帧与P帧之间的距离,N指定两个I帧之间的距离。那么现在的GOP结构是:
H.264 编码器会按顺序,每次取出两幅相邻的帧进行宏块比较,计算两帧的相似度。通过宏块扫描与宏块搜索可以发现这两个帧的关联度是非常高的。进而发现这一组帧的关联度都是非常高的,这些帧就可以划分到一个图像群组,我们简称 GOP(Group Of Pictures)。
I 帧、B帧、P帧还有一些特点,如下:
I帧特点:
1)它是一个全帧压缩编码帧。它将全帧图像信息进行JPEG压缩编码及传输;
2)解码时仅用I帧的数据就可重构完整图像;
3)I帧描述了图像背景和运动主体的详情;
4)I帧不需要参考其他画面而生成;
5)I帧是P帧和B帧的参考帧(其质量直接影响到同组中以后各帧的质量);
6)I帧是帧组GOP的基础帧(第一帧),在一组中只有一个I帧;
7)I帧不需要考虑运动矢量;
8)I帧所占数据的信息量比较大。
I 帧
(I Picture、I Frame、Intra Coded Picture),译为:帧内编码图像,也叫做关键帧(Keyframe),是视频的第一帧,也是 GOP 的第一帧,一个 GOP 只有一个I 帧
。I 帧
是一种自带全部信息的完整独立帧,不会依赖其他帧的信息,也就是自我进行参考的帧,可以简单理解为一张静态图像。在编码时对整帧图像数据进行编码。在解码时仅用当前I 帧
的编码数据就可以解码出完整的图像。
P帧特点:
1)P帧是I帧后面相隔1~2帧的编码帧;
2)P帧采用运动补偿的方法传送它与前面的I或P帧的差值及运动矢量(预测误差);
3)解码时必须将I帧中的预测值与预测误差求和后才能重构完整的P帧图像;
4)P帧属于前向预测的帧间编码。它只参考前面最靠近它的I帧或P帧;
5)P帧可以是其后面P帧的参考帧,也可以是其前后的B帧的参考帧;
6)由于P帧是参考帧,它可能造成解码错误的扩散;
7)由于是差值传送,P帧的压缩比较高。
P 帧
(P Picture、P Frame、Predictive Coded Picture),译为:预测编码图像。编码时并不会对整帧图像数据进行编码,以前面的 I 帧
或 P 帧
作为参考帧,只编码当前 P 帧
与参考帧的差异数据。解码时需要先解码出前面的参考帧,再结合差异数据解码出当前 P 帧
完整的图像。在较早的视频编码标准(例如MPEG-2)中,P 帧
只能使用一个参考帧,而一些现代视频编码标准(比如 H.264),允许使用多个参考帧。
B帧特点:
1)B帧是由前面的I或P帧和后面的P帧来进行预测的;
2)B帧传送的是它与前面的I或P帧和后面的P帧之间的预测误差及运动矢量;
3)B帧是双向预测编码帧;
4)B帧压缩比最高,因为它只反映并参考帧间运动主体的变化情况,预测比较准确;加大B帧的数量可以有效地提高视频数据的压缩比,但是在实时互动的环境下,过多的B帧会引起延时,因为B帧会过分的依赖于前后帧,在网络好的环境下,可以正常的传输帧,这样没有什么问题,但是在网络不好的时候,B帧会等待其他帧到来,会引起延时。
5)B帧不是参考帧,不会造成解码错误的扩散。
B 帧
(B Picture、B Frame、Bipredictive Coded Picture),译为:前后预测编码图像。
编码时并不会对整帧图像数据进行编码,同时以前面、后面的 I 帧
或 P 帧
作为参考帧,只编码当前 B 帧
与前后参考帧的差异数据,因为可参考的帧变多了,所以只需要存储更少的差异数据。解码时需要先解码出前后的参考帧,再结合差异数据解码出当前 B 帧
完整的图像。
不难看出,编码后的数据大小:I 帧
> P 帧
> B 帧
。
注:I、B、P各帧是根据压缩算法的需要,是人为定义的,它们都是实实在在的物理帧。一般来说,I帧的压缩率是7(跟JPG差不多),P帧是20,B帧可以达到50。可见使用B帧能节省大量空间,节省出来的空间可以用来保存多一些I帧,这样在相同码率下,可以提供更好的画质。
备注:
视频传输中会出现连个比较常见的现象,花屏 和 卡顿
(1)如果在GOP分组中的P帧丢失,会造成解码端的图像发生错误。这就是花屏。GOP一组帧呈现出的连贯效果,由于P帧丢失,它需要更新的部分就没有,所以无法正常呈现。故出现花屏现象。
(2)为了解决花屏的问题发生,我们可以将丢失 P帧 或是 I帧 的 GOP 丢掉(包含其中的所有帧),直到下一个I帧再重新刷新图像。但是由于这一帧丢掉了,所以会出现卡顿。
帧的编解码顺序
以下图为例,在播放时站在用户角度看到的帧的顺序是 I0->B2->B3->P1->B5->B6->P4->B8->B9->I7->B11->B12->P10
。编码时同样首先编码 I0
帧,按照显示顺序接下来应该编码 B2
帧,但是由于 B2
帧需要参考后面的 P1
帧,所以要优先编码 P1
帧,接下来才能编码 B2
帧,然后是 B3
帧,再后面就是 P4
帧、B5
帧、B6
帧,紧接着由于 B8
帧和 B9
帧需要参考 GOP #1 的 I7
帧,在 B8
帧和 B9
帧编码之前要先编码 I7
帧,总结下来编码的顺序是 I0->P1->B2->B3->P4->B5->B6->I7->B8->B9->P10->B11->B12
。解码顺序和编码顺序是一样的。
1.2、GOP 长度
GOP 的长度表示 GOP 的帧数。GOP 的长度需要控制在合理范围,以平衡视频质量、视频大小(网络带宽)和seek 效果(拖动、快进的响应速度)等。加大 GOP 长度有利于减小视频文件大小,但也不宜设置过大,太大则会导致 GOP 后部帧的画面失真,影响视频质量。由于 P 帧
、B 帧
的复杂度大于 I 帧
,GOP 值过大,过多的P 帧
、B 帧
会影响编码效率,使编码效率降低。如果设置过小的 GOP 值,视频文件会比较大,则需要提高视频的输出码率,以确保画面质量不会降低,故会增加网络带宽。GOP 长度也是影响视频 seek 响应速度的关键因素,seek 时播放器需要定位到离指定位置最近的前一个I 帧
,如果 GOP 太大意味着距离指定位置可能越远(需要解码的参考帧就越多)、seek 响应的时间(缓冲时间)也越长。
1.3、GOP 类型
GOP 又可以分为 Open(开放)、Closed(封闭)两种。Open 类型:前一个 GOP 的 B 帧
可以参考下一个 GOP 的 I 帧
。Closed 类型:前一个 GOP 的 B 帧
不能参考下一个 GOP 的 I 帧
,并且 GOP 不能以 B 帧
结尾。
需要注意的是,由于 P 帧
、B 帧
都对前面的参考帧(P 帧
、I 帧
)有依赖性,因此,一旦前面的参考帧出现数据错误,就会导致后面的 P 帧
、B 帧
也出现数据错误,而且这种错误还会继续向后传播。对于普通的 I 帧
,其后的P 帧
和B 帧
可以参考该普通 I 帧
之前的其他 I 帧
。
在 Closed GOP 中,有一种特殊的 I 帧
,叫做 IDR 帧
(Instantaneous Decoder Refresh,译为:即时解码刷新)。在编码解码中为了方便,将 GOP 中首个 I 帧
要和其他I帧区别开,把第一个 I 帧
叫 IDR 帧
,这样方便控制编码和解码流程,所以 IDR 帧
一定是 I 帧
,但 I 帧
不一定是 IDR 帧
。当遇到 IDR 帧
时,会清空参考帧队列。如果前一个序列出现重大错误,在这里可以获得重新同步的机会,使错误不会继续往下传播。一个 IDR 帧
之后的所有帧,永远都不会参考该 IDR 帧之前的帧。视频播放时,播放器一般都支持随机 seek(拖动)到指定位置,而播放器直接选择到指定位置附近的 IDR 帧
进行播放最为便捷,因为可以明确知道该 IDR 帧
之后的所有帧都不会参考其之前的其他 I 帧
,从而避免较为复杂的反向解析。
2、帧内/帧间编码
I 帧
采用的是帧内(Intra Frame)编码,处理的是空间冗余。P 帧
、B 帧
采用的是帧间(Inter Frame)编码,处理的是时间冗余。
2.1、划分宏块
在进行编码之前,编码器会通过算法将一张完整的帧切割成多个宏块(Macroblock),然后逐块进行后续的压缩处理。H.264 中的宏块大小通常是 16x16
,宏块是 H.264 中最大的块。宏块可以进一步拆分为多个更小的变换块(Transform blocks)、预测块(Prediction blocks)。变换块的尺寸有:16x16
、8x8
、4x4
。预测块的尺寸有:16×16
、16×8
、8×16
、8×8
、8×4
、4×8
、4×4
。
H.264 - 预测块
2.2、帧内编码
帧内编码,也称帧内预测。 假设当前的块不在图像边缘,我们可以用上方相邻块边界邻近值作为基础值,也就是上面一行中的每一个值,都垂直向下做拷贝,构建出和源 YUV 块一样大小的预测块,这种构建预测块的方式,我们叫做垂直预测模式,属于帧内预测模式的一种。紧接着,以 4x4
的预测块为例,用源 YUV 的数据和预测 YUV 的数据做差值,得到残差块,这样我们在码流中,就直接传输当前 4x4
块的预测模式的标志位和残差数据就行,这样极大地节省了码流。编码器会选取最佳预测模式,使预测帧更加接近原始帧,减少相互间的差异,提高编码的压缩效率。
与垂直预测模式相似的,还有水平预测模式、均值预测模式(也就是 4x4
的均值填充整个 4x4
)等 9 种可选的预测模式,:
3.帧间编码
帧间编码,也称帧间预测,用到了运动补偿(Motion compensation)技术。编码器利用块匹配算法,尝试在先前已编码的帧(称为参考帧)上搜索与正在编码的块相似的块。如果编码器搜索成功,则可以使用称为运动矢量的向量对块进行编码,该向量指向匹配块在参考帧处的位置。在大多数情况下,编码器将成功执行,但是找到的块可能与它正在编码的块不完全匹配,这时编码器将计算它们之间残差值。这些残差值称为预测误差,需要进行变换并将其发送给编码器。综上所述,如果编码器在参考帧上成功找到匹配块,它将获得指向匹配块的运动矢量和预测误差。使用这两个元素以及帧间预测模式标志位,解码器将能够恢复该块的原始像素。如果一切顺利,该算法将能够找到一个几乎没有预测误差的匹配块,因此,一旦进行变换,运动矢量加上预测误差的总大小将小于原始编码的大小。如果块匹配算法未能找到合适的匹配,则预测误差将是可观的。因此,运动矢量的总大小加上预测误差将大于原始编码。在这种情况下,编码器将产生异常,并为该特定块发送原始编码。
4.变换 + 量化
把经过预测后得到的残差值经过 DCT 变换(Discrete Cosine Transform,译为离散余弦变换),目的是把直流和低频(相对平坦,图像或块中大部分占比)能量集中在左上,高频(细节,图像或块中少部分占比)能量集中在右下。DCT 本身虽然没有压缩作用,仅仅是去掉了数据的相关性,却为后面进一步压缩数据时的取舍,奠定了必不可少的基础。
变换后直流分量 DC 都集中在左上角,是整块像素的求和的均值。由于人眼对高频信号不敏感,我们可以定义这样一个变量 QP = 5,将变换块中所有的值都除以 QP,这样做进一步节省传输码流位宽,同时主要去掉了高频分量的值,在解码端只需要将变换块中所有的值在乘 QP 就可以基本还原低频分量。
我们将 QP 运算的过程称为量化,可见量化值越大,丢掉的高频信息就越多,再加上编码器中都是用整形变量代表像素值,所以量化值最大还原的低频信息也会越不准确,即造成的失真就越大,块效应也会越大,视频编码的质量损失主要来源于此。
5.滤波
---- 后续更新 ----
6.熵编码
熵的大小与信源的概率模型有着密切的关系,各个符号出现的概率不同,信源的熵也不同。当信源中各事件是等概率分布时,熵具有极大值。信源的熵与其可能达到的最大值之间的差值反映了该信源所含有的冗余度。信源的冗余度越小,即每个符号所独立携带的信息量越大,那么传送相同的信息量所需要的序列长度越短,符号位越少。因此,数据压缩的一个基本的途径是去除信源的符号之间的相关性,尽可能地使序列成为无记忆的,即前一符号的出现不影响以后任何一个符号出现的概率。
利用信源的统计特性进行码率压缩的编码就称为熵编码,也叫统计编码。熵编码是无损压缩编码方法,它生成的码流可以经解码无失真地恢复出原数据。熵编码是建立在随机过程的统计特性基础上的。
视频编码常用的有两种:变长编码(哈夫曼编码)、算术编码。
H.264 最后将结果进行熵编码,分为上下文自适应的变长编码(Context-based Adaptive Variable-Length Coding,CAVLC)与上下文自适应的二进制算术编码(Context-based Adaptive Binary Arithmetic Coding,CABAC)。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效