mot_est.cpp
上传用户:panstart
上传日期:2022-04-12
资源大小:199k
文件大小:12k
- ////////////////////////////////////////////////////////////////////////////
- //
- //
- // Project : VideoNet version 1.1.
- // Description : Peer to Peer Video Conferencing over the LAN.
- // Author : Nagareshwar Y Talekar ( nsry2002@yahoo.co.in)
- // Date : 15-6-2004.
- //
- // I have converted origional fast h.263 encoder library from C to C++
- // so that it can be integrated into any windows application easily.
- // I have removed some of unnecessary codes/files from the
- // fast h263 library.Also moved definitions and declarations
- // in their proper .h and .cpp files.
- //
- // File description :
- // Name : mot_est.cpp
- //
- //
- /////////////////////////////////////////////////////////////////////////////
- /*************************************************
* libr263: fast H.263 encoder library
*
* Copyright (C) 1996, Roalt Aalmoes, Twente University
* SPA multimedia group
*
* Based on Telenor TMN 1.6 encoder (Copyright (C) 1995, Telenor R&D)
* created by Karl Lillevold
*
* Author encoder: Roalt Aalmoes, <aalmoes@huygens.nl>
*
* Date: 31-07-96
**************************************************/
#include "Global.h"
-
/* Efficient macroblock comparison op. */
/* The comparison is between a non-interpolated lowres block of pixel
and a interpolated hires block of pixel. This might be confusing:
Example: compare 3x3 block with 3x3 block, then the 1s of block 1 are
compared with the 2s of block 2.
Block 1: Block 2:
1.1.1. 222
...... 222
1.1.1. 222
......
1.1.1.
You see, for block one (ii), you have 4 times more data!
*/
//inline int SAD_HalfPixelMacroblock(unsigned int *ii,
// unsigned int *curr,
// int pixels_on_line, int Min_SAD)
int SAD_HalfPixelMacroblock(unsigned int *ii,
- unsigned int *curr,
- int pixels_on_line, int Min_SAD)
- {
int j = 16;
int sad = 0;
while(j--) {
sad += abs(*ii-(*curr++));
ii += 2;
sad += abs(*ii-(*curr++));
ii += 2;
sad += abs(*ii-(*curr++));
ii += 2;
sad += abs(*ii- (*curr++));
ii += 2;
sad += abs(*ii-(*curr++));
ii += 2;
sad += abs(*ii-(*curr++));
ii += 2;
sad += abs(*ii-(*curr++));
ii += 2;
sad += abs(*ii-(*curr++));
ii += 2;
sad += abs(*ii-(*curr++));
ii += 2;
sad += abs(*ii-(*curr++));
ii += 2;
sad += abs(*ii-(*curr++));
ii += 2;
sad += abs(*ii-(*curr++));
ii += 2;
sad += abs(*ii-(*curr++));
ii += 2;
sad += abs(*ii-(*curr++));
ii += 2;
sad += abs(*ii-(*curr++));
ii += 2;
sad += abs(*ii-*curr);
if(sad > Min_SAD)
return INT_MAX;
ii += pixels_on_line*4 - 30;
/* Interpolated image, that means two times */
/* We also take only one of the two pixels */
/* This means another two times ... */
curr += pixels_on_line - 15;
} /* end while */
return sad;
}
/* This implementation contains two mayor algorithms: exhaustive and
logarithmic. The exhaustive algorithm was adapted to be applied on
half-pixel luminance, and the logarithmic algorithm was implemented
by Roalt Aalmoes and is functional equivalent to the one in berkeley's
MPEG encoder. */
void FullMotionEstimation(unsigned int *curr, unsigned int *prev_ipol,
int seek_dist, MotionVector *current_MV, int x_curr,
int y_curr)
/* x_curr and y_curr are whole-pixel
values to indicate upperleft (0,0)
pixel of this MB in whole frame curr */
{
int Min_FRAME;
MotionVector MV_FRAME;
unsigned int *curr_image_MB;
int sxy,xblock,k,yblock,l;
int RightXBorder,LeftXBorder,RightYBorder,LeftYBorder;
int xmax,ymax,sad;
int CenterX, CenterY, origCenterX, origCenterY, newCenterX, newCenterY;
int StepSizeX, StepSizeY;
curr_image_MB = curr + Global::pels*y_curr + x_curr;
/* from now on, all pixel related operations are based on prev_ipol */
/* way: thus resolution is enhanced by 2 for halfpixel search */
CenterX = 2*x_curr;
CenterY = 2*y_curr;
xmax = 2*Global::pels;
ymax = 2*Global::lines;
sxy = mmin(31, seek_dist);
LeftXBorder = CenterX - sxy;
RightXBorder = CenterX + sxy;
LeftYBorder = CenterY - sxy;
RightYBorder = CenterY + sxy;
if (LeftXBorder<0) LeftXBorder = 0;
if (RightXBorder>xmax-32) RightXBorder = xmax-32;
/* Comparison is still on 16x16 blocks */
if (LeftYBorder<0) LeftYBorder = 0;
/* but this is interleaved by 1 pixel! */
if (RightYBorder>ymax-32) RightYBorder = ymax-32;
/* e.g. comp. pixno.1 3 5 7 or 2 4 6 8 */
/*but never 1 2 3 4 as this is halfres.*/
Min_FRAME = INT_MAX;
MV_FRAME.x = 0;
MV_FRAME.y = 0;
MV_FRAME.x_half = 0;
MV_FRAME.y_half = 0;
if(Global::search_p_frames == CPARAM_EXHAUSTIVE) {
/* This is the spriral search variant of exhaustive seach */
/* First determine zero MV value SAD */
xblock = CenterX; yblock = CenterY;
sad = SAD_HalfPixelMacroblock(prev_ipol + xblock + yblock*Global::pels*2,
curr_image_MB,
Global::pels, Min_FRAME) - PREF_NULL_VEC;
/* I assume sad < INT_MAX */
Min_FRAME = sad;
/* Then do the surrounding MV SADs */
for (l = 1; l <= sxy; l++) {
/* For every loop from inside to outside do */
xblock = CenterX - l;
yblock = CenterY - l;
for (k = 0; k < 8*l; k++) {
if (xblock>=LeftXBorder && xblock<=RightXBorder
&& yblock>=LeftYBorder && yblock<=RightYBorder) {
/* 16x16 integer pel MV */
sad = SAD_HalfPixelMacroblock(prev_ipol + xblock + yblock*Global::pels*2,
curr_image_MB,
Global::pels, Min_FRAME);
if (sad < Min_FRAME) {
MV_FRAME.x = xblock - CenterX;
MV_FRAME.y = yblock - CenterY;
Min_FRAME = sad;
}
}
if (k<2*l) xblock++;
else if (k<4*l) yblock++;
else if (k<6*l) xblock--;
else yblock--;
}
} /* end for */
} else { /* Global::search_p_frames == DEF_LOGARITHMIC_SEARCH */
/* origCenter* is necessary because Center* changes */
origCenterX = CenterX; origCenterY = CenterY;
StepSizeX = ((2*sxy + 1) + 1)/3; /* round(Size of Xinterval / 3),
this is maximum size of between two
probes */
StepSizeY = ((2*sxy + 1) + 1)/3; /* round(Size of Yinterval / 3) */
sad = SAD_HalfPixelMacroblock(prev_ipol + CenterX + CenterY*Global::pels*2,
curr_image_MB,Global::pels,
Min_FRAME) - PREF_NULL_VEC;
/* I assume sad < INT_MAX */
Min_FRAME = sad;
while (StepSizeX >= 1 || StepSizeY >= 1) {
newCenterX = CenterX;
newCenterY = CenterY;
/* Do this loop three times */
for(xblock = CenterX - StepSizeX; xblock <= CenterX + StepSizeX &&
(StepSizeX != 0); xblock += StepSizeX) {
if(xblock < LeftXBorder || xblock > RightXBorder)
continue;
/* Do this loop three times */
for(yblock = CenterY - StepSizeY; yblock <= CenterY + StepSizeY &&
(StepSizeY != 0); yblock+= StepSizeY) {
if(yblock < LeftYBorder || yblock > RightYBorder)
continue;
/* In fact, the middlest comparison is only required
the first time, as the last time it is calculated
on the previous while-loop, remember:
NewCenterZ = zblock */
sad = SAD_HalfPixelMacroblock(prev_ipol + xblock + yblock*Global::pels*2,
curr_image_MB,Global::pels, Min_FRAME);
if (sad < Min_FRAME) {
MV_FRAME.x = xblock - origCenterX;
MV_FRAME.y = yblock - origCenterY;
Min_FRAME = sad;
newCenterX = xblock; newCenterY = yblock;
}
} /* end for yblock */
} /* end for xblock */
if(newCenterX < CenterX) {
RightXBorder = LeftXBorder + StepSizeX - 1;
} else if(newCenterX == CenterX) {
LeftXBorder = LeftXBorder + StepSizeX;
RightXBorder = RightXBorder - StepSizeX;
} else {
LeftXBorder = RightXBorder - StepSizeX + 1;
}
if(newCenterY < CenterY) {
RightYBorder = LeftYBorder + StepSizeY - 1;
} else if(newCenterY == CenterY) {
LeftYBorder = LeftYBorder + StepSizeY;
RightYBorder = RightYBorder - StepSizeY;
} else {
LeftYBorder = RightYBorder - StepSizeY + 1;
}
CenterX = newCenterX;
CenterY = newCenterY;
/* Stepsizes are 0 when RightZBorder == LeftZBorder */
StepSizeX = ((RightXBorder - LeftXBorder + 1) + 1)/3;
/* round(Size of Xinterval / 3), this is maximum size of between two
probes */
StepSizeY = ((RightYBorder - LeftYBorder + 1) + 1)/3;
/* round(Size of Yinterval / 3) */
} /* End while stepsize */
} /* end logarithmic search algorithm */
current_MV->x = MV_FRAME.x / 2;
current_MV->x_half = MV_FRAME.x % 2; /*This might not work for neg. values!*/
current_MV->y = MV_FRAME.y / 2;
current_MV->y_half = MV_FRAME.y % 2; /* This might not work! */
current_MV->min_error = Min_FRAME;
return;
}
int SAD_HalfPixelMacroblock2(unsigned int *ii,
unsigned int *curr,
int pixels_on_line, int Min_SAD)
{
int j = 16;
int sad = 0;
while(j--) {
sad += abs(*ii-(*curr));
sad += abs(*(ii + 2)-(*(curr+1)));
sad += abs(*(ii + 4)-(*(curr+2)));
sad += abs(*(ii + 6)-(*(curr+3)));
sad += abs(*(ii + 8)-(*(curr+4)));
sad += abs(*(ii + 10)-(*(curr+5)));
sad += abs(*(ii + 12)-(*(curr+6)));
sad += abs(*(ii + 14)-(*(curr+7)));
sad += abs(*(ii + 16)-(*(curr+8)));
sad += abs(*(ii + 18)-(*(curr+9)));
sad += abs(*(ii + 20)-(*(curr+10)));
sad += abs(*(ii + 22)-(*(curr+11)));
sad += abs(*(ii + 24)-(*(curr+12)));
sad += abs(*(ii + 26)-(*(curr+13)));
sad += abs(*(ii + 28)-(*(curr+14)));
sad += abs(*(ii + 30)-(*(curr+15)));
if(sad > Min_SAD)
return INT_MAX;
ii += pixels_on_line*2*2;
/* Interpolated image, that means two times */
/* We also take only one of the two pixels */
/* This means another two times ... */
curr += pixels_on_line;
} /* end while */
return sad;
}
unsigned int *LoadArea(unsigned int *im, int x, int y,
int x_size, int y_size, int lx)
{
unsigned int *res = (unsigned int *)malloc(sizeof(int)*x_size*y_size);
unsigned int *in;
unsigned int *out;
int i = x_size;
int j = y_size;
in = im + (y*lx) + x;
out = res;
while (j--) {
while (i--)
*out++ = *in++;
i = x_size;
in += lx - x_size;
};
return res;
}
void FindMB(int x, int y, unsigned int *image, unsigned int MB[16][16])
{
int n;
unsigned int *MB_ptr = &MB[0][0];
unsigned int *image_ptr;
MB_ptr = &MB[0][0];
image_ptr = image + x + y*Global::pels;
#ifdef LONGISDOUBLEINT
for(n = 0; n < 16; n++) {
* (unsigned long *) MB_ptr = * (unsigned long *) image_ptr;
MB_ptr += 2; image_ptr += 2;
* (unsigned long *) MB_ptr = * (unsigned long *) image_ptr;
MB_ptr += 2; image_ptr += 2;
* (unsigned long *) MB_ptr = * (unsigned long *) image_ptr;
MB_ptr += 2; image_ptr += 2;
* (unsigned long *) MB_ptr = * (unsigned long *) image_ptr;
MB_ptr += 2; image_ptr += 2;
* (unsigned long *) MB_ptr = * (unsigned long *) image_ptr;
MB_ptr += 2; image_ptr += 2;
* (unsigned long *) MB_ptr = * (unsigned long *) image_ptr;
MB_ptr += 2; image_ptr += 2;
* (unsigned long *) MB_ptr = * (unsigned long *) image_ptr;
MB_ptr += 2; image_ptr += 2;
* (unsigned long *) MB_ptr = * (unsigned long *) image_ptr;
MB_ptr += 2; image_ptr += 2;
image_ptr += Global::pels - 16;
}
#else
for (n = 0; n < 16; n++) {
*(unsigned int *) MB_ptr++ = *(unsigned int *) image_ptr++;
*(unsigned int *) MB_ptr++ = *(unsigned int *) image_ptr++;
*(unsigned int *) MB_ptr++ = *(unsigned int *) image_ptr++;
*(unsigned int *) MB_ptr++ = *(unsigned int *) image_ptr++;
*(unsigned int *) MB_ptr++ = *(unsigned int *) image_ptr++;
*(unsigned int *) MB_ptr++ = *(unsigned int *) image_ptr++;
*(unsigned int *) MB_ptr++ = *(unsigned int *) image_ptr++;
*(unsigned int *) MB_ptr++ = *(unsigned int *) image_ptr++;
*(unsigned int *) MB_ptr++ = *(unsigned int *) image_ptr++;
*(unsigned int *) MB_ptr++ = *(unsigned int *) image_ptr++;
*(unsigned int *) MB_ptr++ = *(unsigned int *) image_ptr++;
*(unsigned int *) MB_ptr++ = *(unsigned int *) image_ptr++;
*(unsigned int *) MB_ptr++ = *(unsigned int *) image_ptr++;
*(unsigned int *) MB_ptr++ = *(unsigned int *) image_ptr++;
*(unsigned int *) MB_ptr++ = *(unsigned int *) image_ptr++;
*(unsigned int *) MB_ptr++ = *(unsigned int *) image_ptr++;
image_ptr += Global::pels - 16;
}
#endif
}