今天翻看日历,发现距离上一次的I帧编码的博客已经搁了一个月了…,今天把这个坑填上。
另外注意:这里的子目录,代表进入了函数中。例如:3.main(),那么3.1就是main{ code }
前文回顾:强烈建议回顾一下Overview部分。
H.264压缩技术之总览(Overview)——Matlab源码解析.
H.264压缩技术之视频基础(foundation of learning video)——Matlab源码解析.
H.264压缩技术之帧内预测(I Frame)——Matlab源码解析.
这里主要是做了四件事:
Seq(:,:,2)=double(VideoSeq_input(:,:,k)) %%k代表是第几帧
X(:,:,2)=Seq(:,:,2);%%注意X(:,:,1)中保留的就是参考帧!!!I帧编码部分已经保存过了
[Seq_r(:,:,2),bits] = encode_p_frame(X,Quant(q),ext,block_size);
%%开始对这一帧进行P帧编码,其实X中包含了要编码的帧和前一个参考帧
%%ext不用管就是一个标志
%Quant代表量化因子
%%当然在前面已经gobal了全局变量 mvm mr bs
进入encode_p_frame函数——>开始模式决定(mode_decision)
mode_decision(bs,mr,i,j);
%%这里出现了i,j就代表已经进行分块处理了
从我们需要操作的帧中,按bs大小开始取块,并进行如下四种预测。
注: 每个块都得经理如下四种模式,但是这里只介绍第一种完全预测,其他的都是类似的,由读者自行探索。
上述四种模式在源码中的函数分别为:
我们从mode_decision函数进入后,里面进入完全预测模式。
你可以看到输入的变量和上面的模式决定所输入的变量是一样的。
这里调用了一个窗函数swr,需要我们知道的是,这个swr操作之后生成的变量中,包含了参考帧的像素信息(可以理解为卷积操作,但不是卷积)。
并且获取需要操作的块的位置curr.
多说一嘴:程序如何判断这个块是完全模式,还是对角模式呢?
其实我们前面有一个标记,来表示这个块当前的模式:
switch mvp_mode
case 'm' %%这里的m就代表的是我要进行完全模式的向量预测
[mvxp,mvyp] = find_median_mv_pred(i,j,bsx);
case 'a'
[mvxp,mvyp] = find_mv_pred_a(i,j,bsx);
case 'b'
[mvxp,mvyp] = find_mv_pred_b(i,j,bsx);
case 'c'
[mvxp,mvyp] = find_mv_pred_c(i,j,bsx);
end
好我们进入find_median_mv_pred.
初始化的mvm容器中因为没有运动向量,所以里面一开始全部都是inf.
这个函数的核心就是计算出mvp 用来更新mvm和后续的运动向量mvpx,mvpy的计算。
mvxp = mvp(1);
%%简单粗暴的将算出来的mvp赋值给mvxp,代表这个块的完全模式下的x方向的运动向量为mvxp
mvyp = mvp(2);
注:区别于2.1.1的块运动补偿,这里是具体的运动补偿的操作部分。上面只是这个主函数名字。
这一步的工作其实还挺多的,我们一步一步的来细细分析:
既然我们确定了要找到J尽可能小的预测模式,但是对于完整的大分块下,这种J就是最小的吗?是不是要进行更微观的搜索呢?
答案是:Yes,进行亚像素搜索!
这个思想类似显微镜调节时,先调粗准焦,再调细准焦一样。
重点看右下角的图,假设我们一开始确定J最小的块是蓝色的块,通过亚像素搜索看看其他四色的块是不是J更小呢。
当我们完成上述的亚像素搜索后,已经基本确定了当前模式(完全模式)下的最佳预测块pred和其运动向量x’,y’.那么我们就可以来开始计算代价了。
如下图,好不容易motion_comp_block返回了结果就是上面的pred,x’,y’。
现在我们拿着这些东西来算代价。
具体计算规则和I帧编码一致请读者参考I帧编码。
其实和完全模式类似,但没有完全模式复杂。剩下预测模式请读者自行探索。
这里多提一嘴,如何来评判这个块适合哪种模式呢?见下图!(很重要)
首先,并不是所有的预测模式中都有子块预测,针对对角预测模式才有子块预测。
这里多了个大块变小块的过程。其他具体操作和大块预测一致。
本章主要介绍了Matlab源码的帧间编码流程。流程相对复杂,但总体来说就是做了五件事:
其中预测部分和比较部分是帧间编码的精髓所在,这也是帧间预测的难点!!