📄 mv_est.c
字号:
#include"sim.h"
static long mv_time = 0;
void MotionEstimation(unsigned char *act_block, unsigned char _huge *prev, int x_curr,
int y_curr, int xoff, int yoff, int seek_dist,
MotionVector *MV[6][MBR+1][MBC+2], int *SAD_0 )
{
int step;
int Min_FRAME;
MotionVector MV_FRAME;
unsigned char *ii;
unsigned char *pp, *search_area, *adv_search_area = NULL,*zero_area = NULL;
int sxy,i,k,j, off;
int ihigh,ilow,jhigh,jlow,h_length,v_length;
int xmax,ymax,sad,lx;
int FirstStep = 8 ;
xmax = pels;
ymax = lines;
sxy = seek_dist;
xoff = mmin(16,mmax(-16,xoff));
yoff = mmin(16,mmax(-16,yoff));
lx = pels + 64;
ilow = x_curr + xoff - sxy;
ihigh = x_curr + xoff + sxy;
jlow = y_curr + yoff - sxy;
jhigh = y_curr + yoff + sxy;
h_length = ihigh - ilow + 16;
v_length = jhigh - jlow + 16;
search_area = LoadArea(prev, ilow, jlow, h_length, v_length, lx);
Min_FRAME = INT_MAX;
MV_FRAME.x = 0;
MV_FRAME.y = 0;
MV_FRAME.x_half = 0;
MV_FRAME.y_half = 0;
if (xoff == 0 && yoff == 0)
{
Min_FRAME = *SAD_0;
MV_FRAME.x = 0;
MV_FRAME.y = 0;
}
else
{
ii = search_area + (x_curr+xoff-ilow) + (y_curr+yoff-jlow)*h_length;
Min_FRAME = SAD_Macroblock(ii, act_block, h_length, Min_FRAME, 0);
MV_FRAME.x = xoff;
MV_FRAME.y = yoff;
}
/* NB: if xoff or yoff != 0, the Extended MV Range is used. If we
allow the zero vector to be chosen prior to the half pel search
in this case, the half pel search might lead to a
non-transmittable vector (on the wrong side of zero). If SAD_0
turns out to be the best SAD, the zero-vector will be chosen
after half pel search instead. The zero-vector can be
transmitted in all modes, no matter what the MV predictor is */
/* 3-step search */
if( (Min_FRAME /256 ) <= 4 ) FirstStep = 4 ;
if( (Min_FRAME /256 ) <= 3 ) FirstStep = 2 ;
if( (Min_FRAME /256 ) <= 2 ) FirstStep = 1 ;
if( (Min_FRAME /256 ) <= 1 ) FirstStep = 0 ;
pp = search_area + x_curr + xoff - ilow + (y_curr + yoff - jlow)*h_length;
for(step = FirstStep; step >= 1; step = step>>1)
{
i = 0; j = 0;
off = h_length*step;
ii = pp - step - off; /*(-step,-step)*/
sad = SAD_Macroblock(ii, act_block, h_length, Min_FRAME, (step%2));
if (sad < Min_FRAME)
{
i = -step; j = -step;
Min_FRAME = sad;
}
ii = pp - off; /*(0, -step)*/
sad = SAD_Macroblock(ii, act_block, h_length, Min_FRAME,(step%2));
if (sad < Min_FRAME)
{
i = 0; j = -step;
Min_FRAME = sad;
}
ii = pp + step - off; /*(step, -step)*/
sad = SAD_Macroblock(ii, act_block, h_length, Min_FRAME,(step%2));
if (sad < Min_FRAME)
{
i = step; j = -step;
Min_FRAME = sad;
}
ii = pp - step; /*(-step, 0)*/
sad = SAD_Macroblock(ii, act_block, h_length, Min_FRAME,(step%2));
if (sad < Min_FRAME)
{
i = -step; j = 0;
Min_FRAME= sad;
}
ii = pp + step; /*(step, 0)*/
sad = SAD_Macroblock(ii, act_block, h_length, Min_FRAME,(step%2));
if (sad < Min_FRAME)
{
i = step; j = 0;
Min_FRAME = sad;
}
ii = pp + off - step; /*(-step,step)*/
sad = SAD_Macroblock(ii, act_block, h_length, Min_FRAME,(step%2));
if (sad < Min_FRAME)
{
i = -step; j = step;
Min_FRAME = sad;
}
ii = pp + off; /*(0,step)*/
sad = SAD_Macroblock(ii, act_block, h_length, Min_FRAME,(step%2));
if (sad < Min_FRAME)
{
i = 0 ; j = step;
Min_FRAME = sad;
}
ii = pp + off + step; /*(step,step)*/
sad = SAD_Macroblock(ii, act_block, h_length, Min_FRAME,(step%2));
if (sad < Min_FRAME)
{
i = step; j = step;
Min_FRAME = sad;
}
MV_FRAME.x += i;
MV_FRAME.y += j;
pp += i + j*h_length;
}
//finally MV_FRAME[0] stores the proper MV
i = x_curr/MB_SIZE+1;
j = y_curr/MB_SIZE+1;
if(MV_FRAME.x > MAX_MVx )
{
MAX_MVx = MV_FRAME.x ;
}
if(MV_FRAME.y > MAX_MVy )
{
MAX_MVy = MV_FRAME.y ;
}
if (!advanced)
{
MV[0][j][i]->x = MV_FRAME.x;
MV[0][j][i]->y = MV_FRAME.y;
MV[0][j][i]->min_error = Min_FRAME;
}
else
{
for( k = 0; k < 5; k++ )
{
MV[k][j][i]->x = MV_FRAME.x;
MV[k][j][i]->y = MV_FRAME.y;
}
}
free(search_area);
if (advanced)
free(adv_search_area);
return;
}
/**********************************************************************
*
* Name: LoadArea
* Description: fills array with a square of image-data
*
* Input: pointer to image and position, x and y size
* Returns: pointer to area
* Side effects: memory allocated to array
*
*
***********************************************************************/
unsigned char *LoadArea(unsigned char _huge *im, int x, int y,
int x_size, int y_size, int lx)
{
unsigned char *res = (unsigned char *)malloc(sizeof(char)*x_size*y_size);
unsigned char _huge *in;
unsigned char *out;
int i = x_size;
int j = y_size;
in = im + (long)y*lx + x;
out = res;
while (j--) {
while (i--)
*out++ = *in++;
i = x_size;
in += lx - x_size;
};
return res;
}
/**********************************************************************
*
* Name: SAD_Macroblock
* Description: fast way to find the SAD of one vector
*
* Input: pointers to search_area and current block,
* Min_F1/F2/FR
* Returns: sad_f1/f2
* Side effects:
*
*
***********************************************************************/
int SAD_Macroblock( unsigned char *pp, unsigned char *act_block,
int h_length, int Min_FRAME , int type )
{
// if type =0 ; then use pixels labeled 1
// else use pixels labeled 2
// |----------------------|
// | 1 2 1 2 1 2 1 2 1 2 |
// |----------------------|
int i;
int sub_Min_FRAME = Min_FRAME ;
int sad = 0;
unsigned char *kk;
unsigned char *ii;
ii = pp ;
kk = act_block ;
i = 16;
while (i>0) {
sad += (abs(*ii - *kk ) +abs(*(ii+1) - *(kk+1) )
+abs(*(ii+2) - *(kk+2) ) +abs(*(ii+3) - *(kk+3) )
+abs(*(ii+4) - *(kk+4) ) +abs(*(ii+5) - *(kk+5) )
+abs(*(ii+6) - *(kk+6) ) +abs(*(ii+7) - *(kk+7) )
+abs(*(ii+8) - *(kk+8) ) +abs(*(ii+9) - *(kk+9) )
+abs(*(ii+10)- *(kk+10)) +abs(*(ii+11) - *(kk+11) )
+abs(*(ii+12)- *(kk+12)) +abs(*(ii+13) - *(kk+13) )
+abs(*(ii+14)- *(kk+14)) +abs(*(ii+15) - *(kk+15) )
);
ii += h_length;
kk += 16;
i -- ;
if ( sad > sub_Min_FRAME)
return INT_MAX;
}
//sad = sad << 1 ;
return sad;
}
int SAD_Block(unsigned char *ii, unsigned char *act_block,
int h_length, int min_sofar)
{
int i;
int sad = 0;
int sub_min_sofar = min_sofar ;
unsigned char *kk;
kk = act_block;
i = 8;
while (i>0) {
sad += (abs(*ii - *kk ) +abs(*(ii+1 ) - *(kk+1) )
+abs(*(ii+2) - *(kk+2) ) +abs(*(ii+3 ) - *(kk+3) )
+abs(*(ii+4) - *(kk+4) ) +abs(*(ii+5 ) - *(kk+5) )
+abs(*(ii+6) - *(kk+6) ) +abs(*(ii+7 ) - *(kk+7) )
);
ii += h_length;
kk += 16;
i -- ;
if (sad > sub_min_sofar)
return INT_MAX;
}
//sad = sad << 1 ;
return sad;
}
/**********************************************************************
*
* Name: FindMB
* Description: Picks out one MB from picture
*
* Input: position of MB to pick out,
* pointer to frame data, empty 16x16 array
* Returns:
* Side effects: fills array with MB data
*
*
***********************************************************************/
void FindMB(int x, int y, unsigned char _huge *image, unsigned char MB[16][16])
{
int n;
register int m;
long start = x + (long)y*pels;
for (n = 0; n < MB_SIZE; n++)
{
for (m = 0; m < MB_SIZE; m++)
MB[n][m] = *(image + m + start);
start += pels;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -