www.pudn.com > motionE.zip.rar > Motion.cpp


// Motion.cpp: implementation of the CMotion class. 
// 
////////////////////////////////////////////////////////////////////// 
 
#include "stdafx.h" 
#include "Motion.h" 
 
#ifdef _DEBUG 
#undef THIS_FILE 
static char THIS_FILE[]=__FILE__; 
#define new DEBUG_NEW 
#endif 
 
extern  PICTINFO pictInform; 
extern int Pquant; 
extern  CFile Statisfile; 
////////////////////////////////////////////////////////////////////// 
// Construction/Destruction 
////////////////////////////////////////////////////////////////////// 
 
CMotion::CMotion() 
{ 
 
 
} 
 
CMotion::~CMotion() 
{ 
 
} 
//用原图像进行全象素搜索       /用重构图像进行半象素搜索 
/*                    
 * oldorg: 源帧 (for P and B frames) 
 * oldref: 重构帧 (P and B frames) 
 * cur:    当前帧:  预测形成帧 
 * sxf,syf: 前向搜索窗 (frame coordinates) 
 * mbi:     指向宏块结构的指针 
 * 返回结果: 确定宏块的信息结构 mbi 
 */ 
 
void CMotion::motion_estimation(unsigned char *oldorg, 
								unsigned char *oldref, 
								unsigned char *cur,  
								int sxf, int syf,mbinfo *mbi) 
{ 
  int i, j; 
  height=pictInform.height; 
  width =pictInform.width; 
  SearchRule=pictInform.SearchRule; 
  MPCThred  =pictInform.MPCThred; 
 
  //遍历picture中所有宏块  
  for (j=0; jMV[0]; 
		 y1=(mbi-1)->MV[1]; 
	 } 
	 if(i==0||i==(pictInform.mb_width-1)*16)//去掉边界的宏块 
	 { 
		 x1=0; 
		 y1=0; 
	 } 
	 if(j!=0)//确定y方向 
	 {		 
		 x2=(mbi-pictInform.mb_width)->MV[0]; 
		 y2=(mbi-pictInform.mb_width)->MV[1]; 
	 } 
	 if(j==0||j==(pictInform.mb_height-1)*16)//去掉边界的宏块 
	 { 
		 x2=0; 
		 y2=0; 
	 } 
	 x1=x1>>1; //仅取运动矢量的整像素的位置 
	 x2=x2>>1; 
	 y1=y1>>1; 
	 y2=y2>>1; 
	 int detx,dety;  //取两个运动矢量的平均作为参考矢量 
     detx=(x1+x2)/2; 
	 dety=(y1+y2)/2; 
     if(detx<=1&&dety<=1)//更新搜索范围 
	 { 
		 sxf=sxf-1; 
		 syf=syf-1; 
	 } 
 
 
   dmc = TSS(oldorg,oldref,mb, 
                       width,i+detx,j+dety,sxf,syf,16,width,height,&imin,&jmin);    
		 
    int sad; 
	sad=MAD(oldref+(imin>>1)+width*(jmin>>1),mb,width,0,0,16,65536); 
	if(((i-imin>>1)==0)&&((j-jmin>>1)==0))//0运动矢量 
		sad=sad-100; 
    mbi->mb_type=INTER; 
    mbi->MV[0] = imin - (i<<1); //附给运动矢量以半象素为单位 
    mbi->MV[1] = jmin - (j<<1); 
 
} 
 
 
 
 
/*绝对值差 
 * total absolute difference between two (16*h) blocks 
 * including optional half pel interpolation of blk1 (hx,hy) 
 * blk1,blk2: addresses of top left pels of both blocks 
 * lx:        distance (in bytes) of vertically adjacent pels 
 * hx,hy:     flags for horizontal and/or vertical interpolation 
 * h:         height of block (usually 8 or 16) 
 * distlim:   bail out if sum exceeds this value 
 */ 
int CMotion::MAD(unsigned char *blk1, unsigned char *blk2,  
				   int lx, int hx, int hy, int h, int distlim) 
{ 
  unsigned char *p1,*p2,*p1a;        //MAD 
  int i,j; 
  int s,v; 
 
  s = 0; 
  p1 = blk1; 
  p2 = blk2; 
 
  if (!hx && !hy) 
    for (j=0; j= distlim) 
         break; 
      p1+= lx; 
      p2+= lx; 
	  } 
  else if (hx && !hy) 
    for (j=0; j>1) - p2[i]; 
        s+=abs(v);          //插值(a+b+1)/2 
	  } 
      p1+= lx; 
      p2+= lx; 
    } 
  else if (!hx && hy)//y方向上插值 
  { 
    p1a = p1 + lx;//下一行 
    for (j=0; j>1) - p2[i]; 
        s+=abs(v); 
	  } 
      p1 = p1a; 
      p1a+= lx; 
      p2+= lx; 
    } 
  } 
  else //if (hx && hy) x y方向上都插值 
  { 
    p1a = p1 + lx; 
    for (j=0; j>2) - p2[i]; 
        s+=abs(v); 
	  } 
      p1 = p1a; 
      p1a+= lx; 
      p2+= lx; 
    } 
  } 
  return s; 
} 
 
int CMotion::TSS(unsigned char *org, unsigned char *ref, 
					   unsigned char *blk, int lx, int i0, int j0,  
					   int sx, int sy, int h, int xmax, int ymax,  
					   int *iminp, int *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; 
 
  //全象素搜索, spiraling outwards 
  //用原图像做全象素搜索, 
  imin = i0; 
  jmin = j0; 
 
   
  dmin = MAD(org+imin+lx*jmin,blk,lx,0,0,h,65536); 
 
 
  sxy = (sx>sy) ? sx : sy; 
 
  for (l=sxy; l>0; l>>=1)//减小搜索半径 
  { 
    i = imin - l; 
    j = jmin - l; 
    for (k=0; k<8; k++)    //搜索周围8个点 
    { 
      if (i>=ilow && i<=ihigh && j>=jlow && j<=jhigh) 
       
	    d = MAD(org+i+lx*j,blk,lx,0,0,h,dmin); 
		  
	 
 
        if (d0);  
  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 = MAD(ref+(i>>1)+lx*(j>>1),blk,lx,i&1,j&1,h,dmin);		 
 
      if (d