参考软件JM95,ldecode
macroblock.c中的 SetMotionVectorPredictor()
pmv:将要获得的预测向量.
ref_frame:当前参考帧序号,refIdxLX
rFrameL:相邻块A的参考帧序号,即标准中的refIdxLXA
rFrameU:refIdxLXB
rFrameUR:refIdxLXC
refPic:当前编码帧每个4X4子块的参考帧索引.
tmp_mv:当前编码帧每个4X4子块的运动MV包括X,Y两个方向.
(已经运动估计过的的子块,当前编码块相邻的A,B,C,D子块都是已经运动估计了,所以refPic,tmp_mv可以用来参考)
ref_frame:参考帧索引号,不是frame_num,也不是POC号,是位于list中的序号.
block_x:X方向的坐标
block_y:Y方向的坐标
blockshape_x:该子块X方向的尺寸,MbPartWidth,
blockshape_y:该子块Y方向的尺寸 MbPartHeight
mb_x,mb_y=4*block_x(block_y)=标准中的x+xS.
mb_nr=currMbAddr
rel_x=xD
block_x=标准中的(x+xS)/4?
blockshape_x=标准中的predPartWidth
getluma4x4Neighbour()的输出都等于GetNeighbour输出的1/4,xW/4,yW/4
先调用getluma4x4neighbour来算出block_a,block_b,block_c,block_d的参数(包括有效性、地址、xW、yW、pos_x、pos_y)
判断block_c在哪几种情况下无效:(mb_x,mb_y是xN点宏块内的坐标?)
1.16×8时,如果xN,yN在no.1宏块,那么block_c无效(16*8时下面的那个宏块,那么没有C块)
2.mb_x=0,blcokshape_x=8,mb_y!=8,mb_y>0(不是0宏块)时,c也无效。(即8×8的第2宏块?)
3.mb_x=8,blockshape_x=8,mb_y!=0,(即8×8的3号宏块),C无效。
如果C无效,用D的数据替代C。
mvPredType=0;(0:mvp,1:只用A,2只用B,3只用C)
1.如果不是mbaff:rFrameL(左)=refPic中a宏块的pos_x,pos_y指向点值,rFrameU(上)取出b宏块点的值,rFrameUR(右上)取出c宏块点的值。
2.如果是mbaff:
a)currMb是场:那么rFrameL在A为场时取block_x,block_y指向的值,为帧时为refIdx值乘以2,rFrameU,UR类似
b)currMb是帧,在A为场时refIdx除以2,为帧时取block_x,block_y指向的值。
只有一个相邻块的参考帧序号和当前参考帧序号相同的情况下:
rFrameL == ref_frame(表示A参考帧序号 = 当前参考帧序号)
如果当前参考帧只参考的和A相同的参考帧,那么mvPredType=1,如果只同B的,那么=2,如果只同C的,那么=3;
以下同标准P121
1)8×16,第0个宏块,且A参考的同currMb参考的,那么mvPredType=1
2)8×16,第1个宏块,且C参考的同currMb参考的,那么mvPredType=3;
3)16×8,第0个宏块,且B参考同currMb参考的,那么mvPredType=2
4)16×8,第1个宏块,且A参考同currMb参考的,那么mvPredType=1;
hv为参数做0、1(两次循环)(是否0为x,1为y)
1)hv=0:mv_a,mv_b, mv_c都取temp_mv[0]
2)hv=1:
a)如果不是mbaff:mv_a,mv_b, mv_c都取temp_mv[1]。
b)如果是mbaff:
i.currMb是场:A为场,mv_a=tmp_mv[1],A为帧,mv_a=tmp_mv[1]/2,B,C类似。
ii.currMb是帧:A为场,mv_a=tmp_mv[1]×2,A为帧,mv_a=tmp_mv[1]
根据mvPredType不同采取不同的预测方法:
1)mvpred_median模式:如果b和c都无效,那么pred_vec=mv_a;否则pred_vec=mv_a,mv_b,mv_c的中间的值。
2)mvpred_L模式:pred_vec=mv_a
3)mvpred_U模式:pred_vec=mv_b;
4)mvpred_UR模式:pred_vec=mv_c;
hv=0,pmv_x=pred_vec;
hv=1,pmv_y=pred_vec;
macroblock.c中的 SetMotionVectorPredictor()
pmv:将要获得的预测向量.
ref_frame:当前参考帧序号,refIdxLX
rFrameL:相邻块A的参考帧序号,即标准中的refIdxLXA
rFrameU:refIdxLXB
rFrameUR:refIdxLXC
refPic:当前编码帧每个4X4子块的参考帧索引.
tmp_mv:当前编码帧每个4X4子块的运动MV包括X,Y两个方向.
(已经运动估计过的的子块,当前编码块相邻的A,B,C,D子块都是已经运动估计了,所以refPic,tmp_mv可以用来参考)
ref_frame:参考帧索引号,不是frame_num,也不是POC号,是位于list中的序号.
block_x:X方向的坐标
block_y:Y方向的坐标
blockshape_x:该子块X方向的尺寸,MbPartWidth,
blockshape_y:该子块Y方向的尺寸 MbPartHeight
mb_x,mb_y=4*block_x(block_y)=标准中的x+xS.
mb_nr=currMbAddr
rel_x=xD
block_x=标准中的(x+xS)/4?
blockshape_x=标准中的predPartWidth
getluma4x4Neighbour()的输出都等于GetNeighbour输出的1/4,xW/4,yW/4
先调用getluma4x4neighbour来算出block_a,block_b,block_c,block_d的参数(包括有效性、地址、xW、yW、pos_x、pos_y)
判断block_c在哪几种情况下无效:(mb_x,mb_y是xN点宏块内的坐标?)
1.16×8时,如果xN,yN在no.1宏块,那么block_c无效(16*8时下面的那个宏块,那么没有C块)
2.mb_x=0,blcokshape_x=8,mb_y!=8,mb_y>0(不是0宏块)时,c也无效。(即8×8的第2宏块?)
3.mb_x=8,blockshape_x=8,mb_y!=0,(即8×8的3号宏块),C无效。
如果C无效,用D的数据替代C。
mvPredType=0;(0:mvp,1:只用A,2只用B,3只用C)
1.如果不是mbaff:rFrameL(左)=refPic中a宏块的pos_x,pos_y指向点值,rFrameU(上)取出b宏块点的值,rFrameUR(右上)取出c宏块点的值。
2.如果是mbaff:
a)currMb是场:那么rFrameL在A为场时取block_x,block_y指向的值,为帧时为refIdx值乘以2,rFrameU,UR类似
b)currMb是帧,在A为场时refIdx除以2,为帧时取block_x,block_y指向的值。
只有一个相邻块的参考帧序号和当前参考帧序号相同的情况下:
rFrameL == ref_frame(表示A参考帧序号 = 当前参考帧序号)
如果当前参考帧只参考的和A相同的参考帧,那么mvPredType=1,如果只同B的,那么=2,如果只同C的,那么=3;
以下同标准P121
1)8×16,第0个宏块,且A参考的同currMb参考的,那么mvPredType=1
2)8×16,第1个宏块,且C参考的同currMb参考的,那么mvPredType=3;
3)16×8,第0个宏块,且B参考同currMb参考的,那么mvPredType=2
4)16×8,第1个宏块,且A参考同currMb参考的,那么mvPredType=1;
hv为参数做0、1(两次循环)(是否0为x,1为y)
1)hv=0:mv_a,mv_b, mv_c都取temp_mv[0]
2)hv=1:
a)如果不是mbaff:mv_a,mv_b, mv_c都取temp_mv[1]。
b)如果是mbaff:
i.currMb是场:A为场,mv_a=tmp_mv[1],A为帧,mv_a=tmp_mv[1]/2,B,C类似。
ii.currMb是帧:A为场,mv_a=tmp_mv[1]×2,A为帧,mv_a=tmp_mv[1]
根据mvPredType不同采取不同的预测方法:
1)mvpred_median模式:如果b和c都无效,那么pred_vec=mv_a;否则pred_vec=mv_a,mv_b,mv_c的中间的值。
2)mvpred_L模式:pred_vec=mv_a
3)mvpred_U模式:pred_vec=mv_b;
4)mvpred_UR模式:pred_vec=mv_c;
hv=0,pmv_x=pred_vec;
hv=1,pmv_y=pred_vec;