⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mvmv.c

📁 优化过的xvid1.1.2源代码
💻 C
字号:
#include "stdlib.h"
#include "MVBitstream.h"
#include "MVMv.h"

extern VLC const TMNMVtab0[];
extern VLC const TMNMVtab1[];
extern VLC const TMNMVtab2[];

static const VECTOR zeroMV = { 0, 0 };

__inline int get_mv_data(Bitstream * bs)
{

	 uint32_t index;

	if (BitstreamGetBit(bs))
		return 0;

	index = BitstreamShowBits(bs, 12);

	if (index >= 512) {
		index = (index >> 8) - 2;
		BitstreamSkip(bs, TMNMVtab0[index].len);
		return TMNMVtab0[index].code;
	}

	if (index >= 128) {
		index = (index >> 2) - 32;
		BitstreamSkip(bs, TMNMVtab1[index].len);
		return TMNMVtab1[index].code;
	}

	index -= 4;

	BitstreamSkip(bs, TMNMVtab2[index].len);
	return TMNMVtab2[index].code;

}

int get_mv(Bitstream * bs, int fcode)
{

	int data;
	int res;
	int mv;
	int scale_fac = 1 << (fcode - 1);

	data = get_mv_data(bs);

	if (scale_fac == 1 || data == 0)
		return data;

	res = BitstreamGetBits(bs, fcode - 1);
	mv = ((abs(data) - 1) * scale_fac) + res + 1;

	return data < 0 ? -mv : mv;

}

VECTOR get_pmv2_interlaced(const MACROBLOCK * const mbs,
												   const int mb_width,
												   const int bound,
												   const int x,
												   const int y,
												   const int block)
{
  int lx, ly, lz;   /* left */
  int tx, ty, tz;   /* top */
  int rx, ry, rz;   /* top-right */
  int lpos, tpos, rpos;
  int num_cand = 0, last_cand = 1;

  VECTOR pmv[4];  /* left neighbour, top neighbour, top-right neighbour */

  lx=x-1; ly=y;   lz=1;
  tx=x;   ty=y-1; tz=2;
  rx=x+1; ry=y-1; rz=2;

  lpos=lx+ly*mb_width;
  rpos=rx+ry*mb_width;
  tpos=tx+ty*mb_width;

  if(lx>=0 && lpos>=bound) 
  {
    num_cand++;
    if(mbs[lpos].field_pred)
     pmv[1] = mbs[lpos].mvs_avg;
    else 
     pmv[1] = mbs[lpos].mvs[lz];
  }
  else 
  {
    pmv[1] = zeroMV;
  }  

  if(tpos>=bound) 
  {
    num_cand++;
    last_cand=2;
    if(mbs[tpos].field_pred)
     pmv[2] = mbs[tpos].mvs_avg;
    else
     pmv[2] = mbs[tpos].mvs[tz];
  } 
  else
  { 
    pmv[2] = zeroMV;
  }
        
  if(rx<mb_width && rpos>=bound) 
  {
    num_cand++;
    last_cand = 3;
    if(mbs[rpos].field_pred)
     pmv[3] = mbs[rpos].mvs_avg;
    else
     pmv[3] = mbs[rpos].mvs[rz];
  } 
  else
  { 
    pmv[3] = zeroMV;
  }  

  /* If there're more than one candidate, we return the median vector */
  if(num_cand>1) 
  {
    /* set median */
    pmv[0].x = MIN(MAX(pmv[1].x, pmv[2].x),
               MIN(MAX(pmv[2].x, pmv[3].x), MAX(pmv[1].x, pmv[3].x)));
    pmv[0].y = MIN(MAX(pmv[1].y, pmv[2].y),
               MIN(MAX(pmv[2].y, pmv[3].y), MAX(pmv[1].y, pmv[3].y)));
          
    return pmv[0];
  }

  return pmv[last_cand];  /* no point calculating median mv */
}

VECTOR get_pmv2(const MACROBLOCK * const mbs,
								const int mb_width,
								const int bound,
								const int x,
								const int y,
								const int block)
{
	int lx, ly, lz;		/* left */
	int tx, ty, tz;		/* top */
	int rx, ry, rz;		/* top-right */
	int lpos, tpos, rpos;
	int num_cand = 0, last_cand = 1;

	VECTOR pmv[4];	/* left neighbour, top neighbour, top-right neighbour */

	switch (block) {
	case 0:
		lx = x - 1;	ly = y;		lz = 1;
		tx = x;		ty = y - 1;	tz = 2;
		rx = x + 1;	ry = y - 1;	rz = 2;
		break;
	case 1:
		lx = x;		ly = y;		lz = 0;
		tx = x;		ty = y - 1;	tz = 3;
		rx = x + 1;	ry = y - 1;	rz = 2;
		break;
	case 2:
		lx = x - 1;	ly = y;		lz = 3;
		tx = x;		ty = y;		tz = 0;
		rx = x;		ry = y;		rz = 1;
		break;
	default:
		lx = x;		ly = y;		lz = 2;
		tx = x;		ty = y;		tz = 0;
		rx = x;		ry = y;		rz = 1;
	}

	lpos = lx + ly * mb_width;
	rpos = rx + ry * mb_width;
	tpos = tx + ty * mb_width;

	if (lpos >= bound && lx >= 0) {
		num_cand++;
		pmv[1] = mbs[lpos].mvs[lz];
	} else pmv[1] = zeroMV;

	if (tpos >= bound) {
		num_cand++;
		last_cand = 2;
		pmv[2] = mbs[tpos].mvs[tz];
	} else pmv[2] = zeroMV;

	if (rpos >= bound && rx < mb_width) {
		num_cand++;
		last_cand = 3;
		pmv[3] = mbs[rpos].mvs[rz];
	} else pmv[3] = zeroMV;

	/* If there're more than one candidate, we return the median vector */

	if (num_cand > 1) {
		/* set median */
		pmv[0].x =
			MIN(MAX(pmv[1].x, pmv[2].x),
				MIN(MAX(pmv[2].x, pmv[3].x), MAX(pmv[1].x, pmv[3].x)));
		pmv[0].y =
			MIN(MAX(pmv[1].y, pmv[2].y),
				MIN(MAX(pmv[2].y, pmv[3].y), MAX(pmv[1].y, pmv[3].y)));
		return pmv[0];
	}

	return pmv[last_cand];	/* no point calculating median mv */
}

void get_motion_vector_interlaced(DECODER * dec,
								Bitstream * bs,
								int x,
								int y,
								int k,
								MACROBLOCK *pMB,
								int fcode,
								const int bound)
{
  const int scale_fac = 1 << (fcode - 1);
  const int high = (32 * scale_fac) - 1;
  const int low = ((-32) * scale_fac);
  const int range = (64 * scale_fac);
  
  /* Get interlaced prediction */
  const VECTOR pmv=get_pmv2_interlaced(dec->mbs,dec->mb_width,bound,x,y,k);
  VECTOR mv,mvf1,mvf2;

  if(!pMB->field_pred)
  {
    mv.x = get_mv(bs,fcode);
    mv.y = get_mv(bs,fcode);
    
    mv.x += pmv.x;
    mv.y += pmv.y;

    if(mv.x<low)
    {
      mv.x += range;
    }
    else
      if(mv.x>high)
      {
         mv.x-=range;
      }

    if(mv.y < low)
    {
      mv.y += range;
    }
    else
      if (mv.y > high)
      {
        mv.y -= range;
      }
    
      pMB->mvs[0]=pMB->mvs[1]=pMB->mvs[2]=pMB->mvs[3]=mv;
  }
  else
  {
     mvf1.x = get_mv(bs, fcode);
     mvf1.y = get_mv(bs, fcode);

     mvf1.x += pmv.x;
     mvf1.y = 2*(mvf1.y+pmv.y/2); /* It's multiple of 2 */

     if (mvf1.x < low)
     {
       mvf1.x += range;
     }
     else 
       if (mvf1.x > high) 
       {
         mvf1.x -= range;
       }

     if (mvf1.y < low) 
     {
      mvf1.y += range;
     }
     else
      if (mvf1.y > high)
       {
         mvf1.y -= range;
       }

	    mvf2.x = get_mv(bs, fcode);
	    mvf2.y = get_mv(bs, fcode);
	
	    mvf2.x += pmv.x;
	    mvf2.y = 2*(mvf2.y+pmv.y/2); /* It's multiple of 2 */
	
	    if (mvf2.x < low) 
	    {
      	mvf2.x += range;
    	}
    	else
    	 if (mvf2.x > high) 
    	 {
      		mvf2.x -= range;
    		}

    	if (mvf2.y < low) 
    	{
      	mvf2.y += range;
    	}
    	 else 
    	 		if (mvf2.y > high) 
    	 		{
    	       mvf2.y -= range;
    			}

    pMB->mvs[0]=mvf1;
    pMB->mvs[1]=mvf2;
    pMB->mvs[2].x=pMB->mvs[3].x=0;
    pMB->mvs[2].y=pMB->mvs[3].y=0;
  
    /* Calculate average for as it is field predicted */
    pMB->mvs_avg.x=DIV2ROUND(pMB->mvs[0].x+pMB->mvs[1].x);
    pMB->mvs_avg.y=DIV2ROUND(pMB->mvs[0].y+pMB->mvs[1].y);
  }
}

void  get_b_motion_vector(Bitstream * bs,
						  VECTOR * mv,
						  int fcode,
						  const VECTOR pmv,
						  const DECODER * const dec,
						  const int x, const int y)
{
  const int scale_fac = 1 << (fcode - 1);
  const int high = (32 * scale_fac) - 1;
  const int low = ((-32) * scale_fac);
  const int range = (64 * scale_fac);

  int mv_x = get_mv(bs, fcode);
  int mv_y = get_mv(bs, fcode);

  mv_x += pmv.x;
  mv_y += pmv.y;

  if (mv_x < low)
    mv_x += range;
  else if (mv_x > high)
    mv_x -= range;

  if (mv_y < low)
    mv_y += range;
  else if (mv_y > high)
    mv_y -= range;

  mv->x = mv_x;
  mv->y = mv_y;
}

void get_motion_vector(DECODER * dec,
						Bitstream * bs,
						int x,
						int y,
						int k,
						VECTOR * ret_mv,
						int fcode,
						const int bound)
{

	  const int scale_fac = 1 << (fcode - 1);
	  const int high = (32 * scale_fac) - 1;
	  const int low = ((-32) * scale_fac);
	  const int range = (64 * scale_fac);

	  const VECTOR pmv = get_pmv2(dec->mbs, dec->mb_width, bound, x, y, k);
	  VECTOR mv;

	  mv.x = get_mv(bs, fcode);
	  mv.y = get_mv(bs, fcode);

	  mv.x += pmv.x;
	  mv.y += pmv.y;

	  if (mv.x < low) 
	  {
		mv.x += range;
	  }
	  else
		  if (mv.x > high) 
		  {
		    mv.x -= range;
		  }

	  if (mv.y < low)
	  {
		mv.y += range;
	  } 
	  else
		  if (mv.y > high) 
		  {
			mv.y -= range;
		  }

	  ret_mv->x = mv.x;
	  ret_mv->y = mv.y;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -