📄 motion.c
字号:
imint = it; jmint = jt; iminb = ib; jminb = jb; imindmv = delta_x; jmindmv = delta_y; vmc = local_dist; } } } /* end delta x loop */ } /* end delta y loop */ } } } /* Compute L1 error for decision purposes */ local_dist = bdist1( ref + (imins>>1) + (width<<1)*(jmins>>1), ref + width + (imint>>1) + (width<<1)*(jmint>>1), mb, width<<1, imins&1, jmins&1, imint&1, jmint&1, 8); local_dist += bdist1( ref + width + (imins>>1) + (width<<1)*(jmins>>1), ref + (iminb>>1) + (width<<1)*(jminb>>1), mb + width, width<<1, imins&1, jmins&1, iminb&1, jminb&1, 8); *dmcp = local_dist; *iminp = imins; *jminp = jmins; *imindmvp = imindmv; *jmindmvp = jmindmv; *vmcp = vmc;}static void dpfield_estimate(topref,botref,mb,i,j,imins,jmins, imindmvp, jmindmvp, dmcp, vmcp)unsigned char *topref, *botref, *mb;int i,j;int imins, jmins;int *imindmvp, *jmindmvp;int *dmcp,*vmcp;{ unsigned char *sameref, *oppref; int io0,jo0,io,jo,delta_x,delta_y,mvxs,mvys,mvxo0,mvyo0; int imino,jmino,imindmv,jmindmv,vmc_dp,local_dist; /* Assign opposite and same reference pointer */ if (pict_struct==TOP_FIELD) { sameref = topref; oppref = botref; } else { sameref = botref; oppref = topref; } mvxs = imins - (i<<1); mvys = jmins - (j<<1); /* vector for prediction from field of opposite 'parity' */ mvxo0 = (mvxs+(mvxs>0)) >> 1; /* mvxs // 2 */ mvyo0 = (mvys+(mvys>0)) >> 1; /* mvys // 2 */ /* vertical field shift correction */ if (pict_struct==TOP_FIELD) mvyo0--; else mvyo0++; /* convert back to absolute coordinates */ io0 = mvxo0 + (i<<1); jo0 = mvyo0 + (j<<1); /* initialize minimum dual prime distortion to large value */ vmc_dp = 1 << 30; for (delta_y = -1; delta_y <= 1; delta_y++) { for (delta_x = -1; delta_x <=1; delta_x++) { /* opposite field coordinates */ io = io0 + delta_x; jo = jo0 + delta_y; if (io >= 0 && io <= (width-16)<<1 && jo >= 0 && jo <= (height2-16)<<1) { /* compute prediction error */ local_dist = bdist2( sameref + (imins>>1) + width2*(jmins>>1), oppref + (io>>1) + width2*(jo>>1), mb, /* current mb location */ width2, /* adjacent line distance */ imins&1, jmins&1, io&1, jo&1, /* half-pel flags */ 16); /* block height */ /* update delta with least distortion vector */ if (local_dist < vmc_dp) { imino = io; jmino = jo; imindmv = delta_x; jmindmv = delta_y; vmc_dp = local_dist; } } } /* end delta x loop */ } /* end delta y loop */ /* Compute L1 error for decision purposes */ *dmcp = bdist1( sameref + (imins>>1) + width2*(jmins>>1), oppref + (imino>>1) + width2*(jmino>>1), mb, /* current mb location */ width2, /* adjacent line distance */ imins&1, jmins&1, imino&1, jmino&1, /* half-pel flags */ 16); /* block height */ *imindmvp = imindmv; *jmindmvp = jmindmv; *vmcp = vmc_dp;}/* 全搜索块匹配
blk:块的左上角像素坐标
h:块的高度
lx:在参考块中,垂直相邻的像素之间的距离(以字节为单位)
org:源参考图像的左上角像素的坐标
ref:重建参考图像的左上角像素的坐标
i0,j0:搜索窗口的中心点
sx,sy:搜索窗口的半长和半宽
xmax,ymax:搜索区域的右边界和下边界
iminp,jminp:指向存储结果的指针
*/
static int fullsearch(org,ref,blk,lx,i0,j0,sx,sy,h,xmax,ymax,iminp,jminp)unsigned char *org,*ref,*blk;int lx,i0,j0,sx,sy,h,xmax,ymax;int *iminp,*jminp;{ int i,j,imin,jmin,ilow,ihigh,jlow,jhigh; int d,dmin; int k,l,sxy; ilow = i0 - sx; ihigh = i0 + sx; if (ilow<0) ilow = 0; if (ihigh>xmax-16) ihigh = xmax-16; jlow = j0 - sy; jhigh = j0 + sy; if (jlow<0) jlow = 0; if (jhigh>ymax-h) jhigh = ymax-h; /* full pel search, spiraling outwards */ imin = i0; jmin = j0; dmin = dist1(org+imin+lx*jmin,blk,lx,0,0,h,65536); sxy = (sx>sy) ? sx : sy; for (l=1; l<=sxy; l++) { i = i0 - l; j = j0 - l; for (k=0; k<8*l; k++) { if (i>=ilow && i<=ihigh && j>=jlow && j<=jhigh) { d = dist1(org+i+lx*j,blk,lx,0,0,h,dmin); if (d<dmin) { dmin = d; imin = i; jmin = j; } } if (k<2*l) i++; else if (k<4*l) j++; else if (k<6*l) i--; else j--; } } /* half pel */ dmin = 65536; imin <<= 1; jmin <<= 1; ilow = imin - (imin>0); ihigh = imin + (imin<((xmax-16)<<1)); jlow = jmin - (jmin>0); jhigh = jmin + (jmin<((ymax-h)<<1)); for (j=jlow; j<=jhigh; j++) for (i=ilow; i<=ihigh; i++) { d = dist1(ref+(i>>1)+lx*(j>>1),blk,lx,i&1,j&1,h,dmin); if (d<dmin) { dmin = d; imin = i; jmin = j; } } *iminp = imin; *jminp = jmin; return dmin;}/*
* 求两个块之间绝对差值
* blk1,blk2:为两个块左上角像素坐标
*lx:垂直相邻的像素之间的距离(以字节为单位)
*hx,hy:水平和垂直插值的标志
*h:块的高度(通常为8或16)
*distlim:极值,如果结果超过该值则放弃之。
*/static int dist1(blk1,blk2,lx,hx,hy,h,distlim)unsigned char *blk1,*blk2;int lx,hx,hy,h;int distlim;{ unsigned char *p1,*p1a,*p2; int i,j; int s,v; s = 0; p1 = blk1; p2 = blk2; if (!hx && !hy) for (j=0; j<h; j++) { if ((v = p1[0] - p2[0])<0) v = -v; s+= v; if ((v = p1[1] - p2[1])<0) v = -v; s+= v; if ((v = p1[2] - p2[2])<0) v = -v; s+= v; if ((v = p1[3] - p2[3])<0) v = -v; s+= v; if ((v = p1[4] - p2[4])<0) v = -v; s+= v; if ((v = p1[5] - p2[5])<0) v = -v; s+= v; if ((v = p1[6] - p2[6])<0) v = -v; s+= v; if ((v = p1[7] - p2[7])<0) v = -v; s+= v; if ((v = p1[8] - p2[8])<0) v = -v; s+= v; if ((v = p1[9] - p2[9])<0) v = -v; s+= v; if ((v = p1[10] - p2[10])<0) v = -v; s+= v; if ((v = p1[11] - p2[11])<0) v = -v; s+= v; if ((v = p1[12] - p2[12])<0) v = -v; s+= v; if ((v = p1[13] - p2[13])<0) v = -v; s+= v; if ((v = p1[14] - p2[14])<0) v = -v; s+= v; if ((v = p1[15] - p2[15])<0) v = -v; s+= v; if (s >= distlim) break; p1+= lx; p2+= lx; } else if (hx && !hy) for (j=0; j<h; j++) { for (i=0; i<16; i++) { v = ((unsigned int)(p1[i]+p1[i+1]+1)>>1) - p2[i]; if (v>=0) s+= v; else s-= v; } p1+= lx; p2+= lx; } else if (!hx && hy) { p1a = p1 + lx; for (j=0; j<h; j++) { for (i=0; i<16; i++) { v = ((unsigned int)(p1[i]+p1a[i]+1)>>1) - p2[i]; if (v>=0) s+= v; else s-= v; } p1 = p1a; p1a+= lx; p2+= lx; } } else /* if (hx && hy) */ { p1a = p1 + lx; for (j=0; j<h; j++) { for (i=0; i<16; i++) { v = ((unsigned int)(p1[i]+p1[i+1]+p1a[i]+p1a[i+1]+2)>>2) - p2[i]; if (v>=0) s+= v; else s-= v; } p1 = p1a; p1a+= lx; p2+= lx; } } return s;}/*
* 两个块之间均方误差
*/static int dist2(blk1,blk2,lx,hx,hy,h)unsigned char *blk1,*blk2;int lx,hx,hy,h;{ unsigned char *p1,*p1a,*p2; int i,j; int s,v; s = 0; p1 = blk1; p2 = blk2; if (!hx && !hy) for (j=0; j<h; j++) { for (i=0; i<16; i++) { v = p1[i] - p2[i]; s+= v*v; } p1+= lx; p2+= lx; } else if (hx && !hy) for (j=0; j<h; j++) { for (i=0; i<16; i++) { v = ((unsigned int)(p1[i]+p1[i+1]+1)>>1) - p2[i]; s+= v*v; } p1+= lx; p2+= lx; } else if (!hx && hy) { p1a = p1 + lx; for (j=0; j<h; j++) { for (i=0; i<16; i++) { v = ((unsigned int)(p1[i]+p1a[i]+1)>>1) - p2[i]; s+= v*v; } p1 = p1a; p1a+= lx; p2+= lx; } } else /* if (hx && hy) */ { p1a = p1 + lx; for (j=0; j<h; j++) { for (i=0; i<16; i++) { v = ((unsigned int)(p1[i]+p1[i+1]+p1a[i]+p1a[i+1]+2)>>2) - p2[i]; s+= v*v; } p1 = p1a; p1a+= lx; p2+= lx; } } return s;}/*
*(16*h) 块和双向预测之间的绝对误差
*
*/static int bdist1(pf,pb,p2,lx,hxf,hyf,hxb,hyb,h)unsigned char *pf,*pb,*p2;int lx,hxf,hyf,hxb,hyb,h;{ unsigned char *pfa,*pfb,*pfc,*pba,*pbb,*pbc; int i,j; int s,v; pfa = pf + hxf; pfb = pf + lx*hyf; pfc = pfb + hxf; pba = pb + hxb; pbb = pb + lx*hyb; pbc = pbb + hxb; s = 0; for (j=0; j<h; j++) { for (i=0; i<16; i++) { v = ((((unsigned int)(*pf++ + *pfa++ + *pfb++ + *pfc++ + 2)>>2) + ((unsigned int)(*pb++ + *pba++ + *pbb++ + *pbc++ + 2)>>2) + 1)>>1) - *p2++; if (v>=0) s+= v; else s-= v; } p2+= lx-16; pf+= lx-16; pfa+= lx-16; pfb+= lx-16; pfc+= lx-16; pb+= lx-16; pba+= lx-16; pbb+= lx-16; pbc+= lx-16; } return s;}/*
* (16*h) 块和双向预测之间的均方误差
*/static int bdist2(pf,pb,p2,lx,hxf,hyf,hxb,hyb,h)unsigned char *pf,*pb,*p2;int lx,hxf,hyf,hxb,hyb,h;{ unsigned char *pfa,*pfb,*pfc,*pba,*pbb,*pbc; int i,j; int s,v; pfa = pf + hxf; pfb = pf + lx*hyf; pfc = pfb + hxf; pba = pb + hxb; pbb = pb + lx*hyb; pbc = pbb + hxb; s = 0; for (j=0; j<h; j++) { for (i=0; i<16; i++) { v = ((((unsigned int)(*pf++ + *pfa++ + *pfb++ + *pfc++ + 2)>>2) + ((unsigned int)(*pb++ + *pba++ + *pbb++ + *pbc++ + 2)>>2) + 1)>>1) - *p2++; s+=v*v; } p2+= lx-16; pf+= lx-16; pfa+= lx-16; pfb+= lx-16; pfc+= lx-16; pb+= lx-16; pba+= lx-16; pbb+= lx-16; pbc+= lx-16; } return s;}/*
* 计算一个(16*16) 块的方差,并乘以256
* p: 块左上角像素的地址
* lx: 相邻像素的垂直距离(以字节为单位)
*/static int variance(p,lx)unsigned char *p;int lx;{ int i,j; unsigned int v,s,s2; s = s2 = 0; for (j=0; j<16; j++) { for (i=0; i<16; i++) { v = *p++; s+= v; s2+= v*v; } p+= lx-16; } return s2 - (s*s)/256;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -