JM95 与 JM85 中的编码代码详解(张新发)
介绍函数 void encode_one_macroblock () (主要是在运动估计部分)
先判断 intra 的值,若是 I 帧或 P 帧的强制帧内编码宏块,则 intra 的值为 1,否则
intra 的值为 0。
假设现在我们取 intra 的值为 0(编码帧间编码的 P 帧或 B 帧宏块)
init_enc_mb_params(currMB, &enc_mb, intra, bslice)
这个函数用来初始化一些编码宏块参数,最重要的是根据 intra 的值和配置参数判
断哪些宏块模式有效,注意不管是帧内还是帧间
根据假设前提,现在有效的模式是 Skip(0) ,
16*16(1),16*8(2),8*16(3),8*8(4),8*4(5),4*8(6),4*4(7),(4|5|6|7)(8),I4MB(9),I16MB(10
)。
这个函数还用来计算3个拉格朗日参数值。
先不考虑B帧情况。
运动估计部分总体思路:
在宏块模式中循环,对于某种分割宏块模式,在参考帧中循环,用率失真函数确
定最佳的参考帧和运动矢量,得到最小的cost,
对已经确定最佳参考帧和运动矢量的宏块模式用率失真函数比较,具有最小值的
那个宏块模式即为最佳宏块分割模式,其对应的参考帧和运动矢量都是最佳的。
for (min_cost=INT_MAX, mode=1; mode<4; mode++)
在 16*16(1),16*8(2),8*16(3)三种宏块模式中循环
for (cost=0, block=0; block<(mode==1?1:2); block++)
在 16*16(1),16*8(2),8*16(3)模式的分割块中循环,例如是 16*8(2),8*16(3)则循环两
次。
PartitionMotionSearch (mode, block, enc_mb.lambda_mf); //某种分割块中的运动
搜索
进入这个函数分析:
这里要注意的是几个变量,step_h0,step_v0,step_h,step_v,by,bx,他们的取
值是根据 input->part_size,bx0,by0 数组来取的
后面出现这些变量的循环时会详细介绍这个值
for (list=0; list<numlists;list++),在前向与后向中循环
for (ref=0; ref < listXsize[list+list_offset]; ref++),在参考帧中循环
m_cost = &motion_cost[blocktype][list][ref][block8x8];用 m_cost 纪录本分割块的
cost
for (v=by; v<by + step_v0; v += step_v)
for (h=bx; h<bx+
step_h0; h+=step_h)
这个循环,对于 16*16(1),16*8(2),8*16(3)三种方式 step_h0=step_h,step_v0=
step_v,他们只循环一次,其实这个二重循环主要是子宏块分割
进行循环的,即 8*8(4)以下的一些分割,在后面讨论 8*8(4)的方式时我们会看到
by,bx 标示分割块在宏块中的位置,以 4*4 的block为单位,例如 16*8 的
下面的分割块,则by=2,bx=0;
pic_block_y,pic_block_x就标示了本分割块在图像中的block坐标
mcost = BlockMotionSearch (ref, list, h<<2, v<<2, blocktype, search_range,
lambda_factor);