前言
这篇博客开始就将介绍H.264视频编码中的,帧内编码,也就是I帧编码。章节展开将严格按照Matlab源码的逻辑进行书写。如果你手头有代码,建议配合代码一起食用。(开源代码overview部分有介绍)
另外注意:这里的子目录,代表进入了函数中。例如:3.main(),那么3.1就是main{ code }.
前文回顾:强烈建议回顾一下Overview部分。
H.264压缩技术之总览(Overview)——Matlab源码解析.
H.264压缩技术之视频基础(foundation of learning video)——Matlab源码解析.
帧内预测
1.设置参考帧+I帧编码
由于进行编码的帧格式为 IPPP格式,也就是说第一个帧是I帧,后续的都是P帧。
所以设置第一帧参考帧X为自身:
X(:,:,1)=Seq(:,:,1) %解释一下Seq为啥是3维数组,前两位代表每个帧的像素值,最后一位代表是第几帧
进行I帧编码
[Seq_r(:,:,1),bits] = encode_i_frame(Seq(:,:,1),QP); % Encoding
%encode_i_frame函数是编码I帧的函数,
%函数内主要操作为:熵编码,残差块,预测等
%QP为质量因子
%返回的结果Seq_r为重构帧,bits为进行编码后的比特流
2.Seq序列分块
这里的Seq可以理解为最左边的建筑工。现在将建筑工进行16-16分块。对每个16-16的大块,再进行4-4的小分块。这里用不同的颜色标记出不同的小分块。
3.开始对每块进行预测
这里的预测分为3种情况。分别是:
- 无需预测:针对左上角的块
- 仅仅需要水平或垂直预测
- 9个方向都得预测
如下图:右上角那一块蓝色块,就是属于不需要进行预测操作的块。对于右下角的橙色部分的块(4*4,不包含蓝色部分)仅仅需要进行水平预测。对于其他的普通情况,那么就需要进行9大方向的预测。
这里笔者仅仅介绍一种水平预测模式。其他的8种模式十分的类似,读者可以自行进行实验或查阅相关资料。
4.水平预测(pred_horz_4)
先看水平预测的主函数。pred_horz_4。
pred_horz_4(Seq,Seq_r,i,j)
%Seq:目前操作的序列块
%Seq_r前一个重构的序列块
%块的i,g位序
我们需要三个玩意,如上文注释部分解释。
你可以会问,如果这是第一块,那么,这个Seq_r哪来的?
其实在前面对第一块属于比较特殊的块,认为第一块为非预测块,不需要进行预测。只需要进行后续的编码即可。
4.1进行水平预测
其实水平预测没什么大不了,只是将参考块Seq_r的特定采样点(像素)照抄了一篇,赋值给预测矩阵pred而已。
4.2计算残差块 icp
如下图所示。我们按照步骤2.2 ——> 2.4操作结束后。得到残差块icp,和sae,并且记录当前块的预测模式mode。
最后通过比较每种预测模式mode的sae,取sae最小的模式作为当前块的预测模式。
多说一句:sae越小代表什么?
sae越小代表你进行预测时用对应模式所需要记录的变化信息越少(其实也相当于预测的最为准确)。
举例:如果sae=0,那么就说明预测块=参考块,说明完全没有运动变化,那么不改变是最好的“预测”。
最后返回4个值:icp,pred,sae,mode
[icp,pred,sae,mode]=pred_horz_4(Seq,Seq_r,i,j)
5.块编码(code_block)
针对第一块,非预测块,仅仅需要进行块编码。
块编码需要注意几点问题(非预测块):
- 进行编码的是残差块-icp
- 最后生成新的Seq_r作为下一块的参考
- 注意非预测块Seq_r的生成方式。Seq_r=icp_r+pred
- 最后生成了两样东西,一个是比特流,一个是重构块
补充一点:一般代码中带_r的都代表重构的意思。也就是经过反量化反熵编码所得的信息。
6.比特流拼接,残差积累,准备编码P帧
这里其实做了好几件事,但是由于非常的简单,所以放在一块说了。
- 对生成的比特流进行拼接:如Step4所示
- 保存原始帧,并且设置重构帧作为新的参考帧
- 准备P帧预测
7.小结
本章主要介绍了Matlab源码的帧内编码流程。总体来说就是做了三件事:
- 预测
- 块编码
- 比特流拼接
其中预测部分是帧内编码的精髓所在。通过9大方向的预测,找到最适合当前块的运动方法匹配的模式。大大减少了需要编码的比特数。
后续将介绍比较复杂的帧间预测(P Frame),敬请期待!