📄 coder.c
字号:
* pel prediction
*
* Input: pointer to image structure
* Returns: pointer to interpolated image
* Side effects: allocates memory to interpolated image
*
*
*
***********************************************************************/
//====================================================================
//void InterpolateImage(unsigned char _huge *image,unsigned char _huge *ipol_image,
// int width, int height)
//{
// unsigned char _huge *ii, _huge *oo;
// int i,j;
// ii = ipol_image;
// oo = image;
/* main image */
// for (j = 0; j < height-1; j++) {
// for (i = 0; i < width-1; i++) {
// *(ii + (i<<1)) = *(oo + i);
// *(ii + (i<<1)+1) = (*(oo + i) + *(oo + i + 1) + 1)>>1;
// *(ii + (i<<1)+(width<<1)) = (*(oo + i) + *(oo + i + width) + 1)>>1;
// *(ii + (i<<1)+1+(width<<1)) = (*(oo+i) + *(oo+i+1) +
// *(oo+i+width) + *(oo+i+1+width) + 2)>>2;
// }
/* last pels on each line */
// *(ii+ (width<<1) - 2) = *(oo + width - 1);
// *(ii+ (width<<1) - 1) = *(oo + width - 1);
// *(ii+ (width<<1)+ (width<<1)-2) = (*(oo+width-1)+*(oo+width+width-1)+1)>>1;
// *(ii+ (width<<1)+ (width<<1)-1) = (*(oo+width-1)+*(oo+width+width-1)+1)>>1;
// ii += (width<<2);
// oo += width;
// }
/* last lines */
// for (i = 0; i < width-1; i++) {
// *(ii+ (i<<1)) = *(oo + i);
// *(ii+ (i<<1)+1) = (*(oo + i) + *(oo + i + 1) + 1)>>1;
// *(ii+ (width<<1)+ (i<<1)) = *(oo + i);
// *(ii+ (width<<1)+ (i<<1)+1) = (*(oo + i) + *(oo + i + 1) + 1)>>1;
// }
/* bottom right corner pels */
// *(ii + (width<<1) - 2) = *(oo + width -1);
// *(ii + (width<<1) - 1) = *(oo + width -1);
// *(ii + (width<<2) - 2) = *(oo + width -1);
// *(ii + (width<<2) - 1) = *(oo + width -1);
//}
//====================================================================
//==================================================================
_inline unsigned char InterpolatePel(unsigned char _huge *image,int xcurr , int ycurr)
{
unsigned char _huge *oo;
int i,j;
oo = image;
j = (ycurr >> 1);
i = (xcurr >> 1);
oo += j * widthA ;
if( (ycurr & 1 ) == 0 )
{
if( (xcurr & 1 ) == 0 )
{
return ( *(oo + i) ) ;
}else{
if( (i < widthA-1) && (j <= heightA -1) )
return ((*(oo + i) + *(oo + i + 1) + 1)>>1) ;
else
return (*(oo + widthA -1));
}
}else{
if( ( xcurr & 1 ) == 0 )
{
if( (i <= widthA-1) && (j < heightA -1) )
return ((*(oo + i) + *(oo + i + widthA) + 1)>>1) ;
else
return (*(oo + widthA -1));
}else{
if( (i < widthA-1) && (j < heightA -1) )
return ((*(oo+i) + *(oo+i+1) + *(oo+i+widthA) + *(oo+i+1+widthA) + 2)>>2 ) ;
else if (( i == widthA - 1 )&&(j != heightA -1 ) )
return ((*(oo+widthA-1)+ *(oo+widthA+widthA-1) + 1 )>>1);
else if ( (i != widthA -1 ) && (j == heightA - 1 ) )
return ((*(oo + i) + *(oo + i + 1) + 1)>>1);
else
return (*(oo + widthA -1));
}
}
}
//==================================================================
/**********************************************************************
*
* Name: MotionEstimatePicture
* Description: Finds integer and half pel motion estimation
* and chooses 8x8 or 16x16
*
* Input: current image, previous image, interpolated
* reconstructed previous image, seek_dist,
* motion vector array
* Returns:
* Side effects: allocates memory for MV structure
*
*
*
***********************************************************************/
void MotionEstimatePicture(unsigned char _huge *curr, unsigned char _huge *prev,
int seek_dist, MotionVector *MV[6][MBR+1][MBC+2])
{
char * ii , * jj , * pp , * kk ;
int m[5] ;
int i,j,k,h;
int pmv0,pmv1,xoff,yoff, sub_offx ,sub_offy;
unsigned char curr_mb[16][16];
int sad8 = INT_MAX, sad16, sad0;
MotionVector *f0,*f[4] ;
int offx=0,offy=0;
int lx = pels + 64;
// Do motion estimation and store result in array
for ( j = 0; j < mbr; j++)
{
offy = j*MB_SIZE;
for ( i = 0; i < mbc; i++)
{
offx = i*MB_SIZE;
FindMB(offx,offy ,curr, curr_mb);
sad0 = SAD_Macroblock(prev + offx + (long)offy*lx, &curr_mb[0][0],
lx, INT_MAX,0) - PREF_NULL_VEC;
if(sad0 < 900) //changable
{
for (k = 0; k < 5; k++)
ZeroVec(MV[k][j+1][i+1]);
MV[0][j+1][i+1]->Mode = MODE_INTER0;
}
// Integer pel search
else
{
f0 = MV[0][j+1][i+1];
f[0] = MV[1][j+1][i+1];
f[1] = MV[2][j+1][i+1];
f[2] = MV[3][j+1][i+1];
f[3] = MV[4][j+1][i+1];
/* integer pel search */
/* NBNB need to use newgob properly as last parameter */
FindPMV(MV,i+1,j+1,&pmv0,&pmv1,0,0,0);
/* Here the PMV's are found using integer motion vectors */
/* (NB should add explanation for this )*/
xoff = pmv0>>1; /* always divisable by two */
yoff = pmv1>>1;
//this function perform inter Mv estimation
MotionEstimation(&curr_mb[0][0], prev, offx, offy,
xoff, yoff, seek_dist, MV, &sad0 );
sad16 = f0->min_error;
m[0] = sad16 ;
// in order to reduce work
if( sad16 < 256 ) continue ;
//f0 --> f4 are all MotionVectors
f0->Mode = ChooseMode(&curr_mb[0][0],sad16);
/* Half pel search */
if (f0->Mode != MODE_INTRA)
{
sub_offx = offx + f0->x ;
sub_offy = offy + f0->y ;
ii = pp = prev + sub_offx + sub_offy * lx ;
jj = ii - lx ;
m[1] = SAD_Macroblock(jj, &curr_mb[0][0], lx, INT_MAX,0);
jj = ii + lx ;
m[2] = SAD_Macroblock(jj, &curr_mb[0][0], lx, INT_MAX,0);
jj = ii - 1 ;
m[3] = SAD_Macroblock(jj, &curr_mb[0][0], lx, INT_MAX,0);
jj = ii + 1 ;
m[4] = SAD_Macroblock(jj, &curr_mb[0][0], lx, INT_MAX,0);
newFindHalfPel(f0, m );
sad16 = f0->min_error;
if (advanced) // advance mode is used as default
{
for( h = 0; h < 4 ; h ++ )
{
if( h == 0 )
{
ii = pp ;
kk = &curr_mb[0][0] ;
}else if( h == 1 )
{
ii = pp + 8 ;
kk = &curr_mb[0][0] + 8 ;
}
else if( h == 2 )
{
ii = pp + 8 * lx ;
kk = &curr_mb[0][0] + 8 * 16 ;
}
else if( h == 3 )
{
ii = pp + 8 * lx + 8 ; //modified !!!!!org : + 8*lx+lx
kk = &curr_mb[0][0] + 8 * 16 + 8 ;
}
m[0] = SAD_Block(ii, kk, lx, INT_MAX);
jj = ii - lx ;
m[1] = SAD_Block(jj, kk, lx, INT_MAX);
jj = ii + lx ;
m[2] = SAD_Block(jj, kk, lx, INT_MAX);
jj = ii - 1 ;
m[3] = SAD_Block(jj, kk, lx, INT_MAX);
jj = ii + 1 ;
m[4] = SAD_Block(jj, kk, lx, INT_MAX);
newFindHalfPel(f[h], m );
}
sad8 = f[0]->min_error +f[1]->min_error +f[2]->min_error +f[3]->min_error;
sad8 += PREF_16_VEC;
//Choose Zero Vector, 8x8 or 16x16 vectors
if (sad0 < sad8 && sad0 < sad16)
{
f0->x = f0->y = 0;
f0->x_half = f0->y_half = 0;
}
else
{
if (sad8 < sad16)
f0->Mode = MODE_INTER4V;
}
}
else
{
//Choose Zero Vector or 16x16 vectors
if (sad0 < sad16)
{
f0->x = f0->y = 0;
f0->x_half = f0->y_half = 0;
}
}
}
else
for (k = 0; k < 5; k++)
ZeroVec(MV[k][j+1][i+1]);
}
}
}
return;
}
//=========================================================
_inline void newFindHalfPel(MotionVector *fr, int m[5])
{
int error = m[0] ;
if( ( (m[3] - m[0]) <<1 ) < (m[4] - m[0]) )
{
fr->x_half = -1 ;
error += m[3] ;
}else if( ( (m[4] - m[0])<<1 ) < (m[3] - m[0]) )
{
fr->x_half = +1 ;
error += m[4] ;
}else{
fr->x_half = 0 ;
error += m[0] ;
}
if( ( (m[1] - m[0])<<1 ) < (m[2] - m[0]) )
{
fr->y_half = -1 ;
error += m[1] ;
}else if( ( (m[2] - m[0])<<1 ) < (m[1] - m[0]) )
{
fr->y_half = +1 ;
error += m[2] ;
}else{
fr->y_half = 0 ;
error += m[0] ;
}
fr->min_error = error /3 ;
}
/**********************************************************************
*
* Name: MakeEdgeImage
* Description: Copies edge pels for use with unrestricted
* motion vector mode
*
* Input: pointer to source image, destination image
* width, height, edge
* Returns:
* Side effects:
*
*
*
***********************************************************************/
void MakeEdgeImage(unsigned char _huge *src, unsigned char _huge *dst, int width,
int height, int edge)
{
long i,j;
unsigned char _huge *p1,_huge *p2,_huge *p3,_huge *p4;
unsigned char _huge *o1,_huge *o2,_huge *o3,_huge *o4;
/* center image */
p1 = dst;
o1 = src;
for (j = 0; j < height;j++)
{
for(i = 0; i < width; i++)
p1[i] = o1[i];
p1 += width + (edge<<1);
o1 += width;
}
/* left and right edges */
p1 = dst-1;
o1 = src;
for (j = 0; j < height;j++) {
for (i = 0; i < edge; i++) {
*(p1 - i) = *o1;
*(p1 + width + i + 1) = *(o1 + width - 1);
}
p1 += width + (edge<<1);
o1 += width;
}
/* top and bottom edges */
p1 = dst;
p2 = dst + (long)(width + (edge<<1))*(height-1);
o1 = src;
o2 = src + (long)width*(height-1);
for (j = 0; j < edge;j++) {
p1 = p1 - (width + (edge<<1));
p2 = p2 + (width + (edge<<1));
for (i = 0; i < width; i++) {
*(p1 + i) = *(o1 + i);
*(p2 + i) = *(o2 + i);
}
}
/* corners */
p1 = dst - (width+(edge<<1)) - 1;
p2 = p1 + width + 1;
p3 = dst + (long)(width+(edge<<1))*(height)-1;
p4 = p3 + width + 1;
o1 = src;
o2 = o1 + width - 1;
o3 = src + (long)width*(height-1);
o4 = o3 + width - 1;
for (j = 0; j < edge; j++) {
for (i = 0; i < edge; i++) {
*(p1 - i) = *o1;
*(p2 + i) = *o2;
*(p3 - i) = *o3;
*(p4 + i) = *o4;
}
p1 = p1 - (width + (edge<<1));
p2 = p2 - (width + (edge<<1));
p3 = p3 + width + (edge<<1);
p4 = p4 + width + (edge<<1);
}
}
/**********************************************************************
*
* Name: Clip
* Description: clips recontructed data 0-255
*
* Input: pointer to recon. data structure
* Side effects: data structure clipped
*
*
*
***********************************************************************/
void Clip(MB_Structure *data)
{
int m;
int *lum = data->lum[0], *cr = data->Cr[0], *cb = data->Cb[0];
for (m = 0; m < 256; m++,lum++)
{
*lum = mmin(255,mmax(0,*lum));
}
for (m = 0; m < 64; m++,cr++,cb++)
{
*cr = mmin(255,mmax(0,*cr));
*cb = mmin(255,mmax(0,*cb));
}
}
_inline void MeanMB(MB_Structure *data, int mean[6])
{
int i;
int *kk;
kk = data->lum[0];
mean[0] = 0;
for(i = 0; i < 8; i++)
{
mean[0] += *kk + *(kk+1) + *(kk+2) + *(kk+3) +
*(kk+4) + *(kk+5) + *(kk+6) + *(kk+7);
kk += 16;
}
mean[0] = mean[0]>>6;
kk = data->lum[0] + 8;
mean[1] = 0;
for(i = 0; i < 8; i++)
{
mean[1] += *kk + *(kk+1) + *(kk+2) + *(kk+3) +
*(kk+4) + *(kk+5) + *(kk+6) + *(kk+7);
kk += 16;
}
mean[1] = mean[1]>>6;
kk = data->lum[0] + 128;
mean[2] = 0;
for(i = 0; i < 8; i++)
{
mean[2] += *kk + *(kk+1) + *(kk+2) + *(kk+3) +
*(kk+4) + *(kk+5) + *(kk+6) + *(kk+7);
kk += 16;
}
mean[2] = mean[2]>>6;
kk = data->lum[0] + 136;
mean[3] = 0;
for(i = 0; i < 8; i++)
{
mean[3] += *kk + *(kk+1) + *(kk+2) + *(kk+3) +
*(kk+4) + *(kk+5) + *(kk+6) + *(kk+7);
kk += 16;
}
mean[3] = mean[3]>>6;
kk = data->Cb[0];
mean[4] = 0;
for(i = 0; i < 8; i++)
{
mean[4] += *kk + *(kk+1) + *(kk+2) + *(kk+3) +
*(kk+4) + *(kk+5) + *(kk+6) + *(kk+7);
kk += 8;
}
mean[4] = mean[4]>>6;
kk = data->Cr[0];
mean[5] = 0;
for(i = 0; i < 8; i++)
{
mean[5] += *kk + *(kk+1) + *(kk+2) + *(kk+3) +
*(kk+4) + *(kk+5) + *(kk+6) + *(kk+7);
kk += 8;
}
mean[5] = mean[5]>>6;
}
_inline int VarMB(MB_Structure *data, int mean)
{
int sad = 0, i;
int *ii = data->lum[0];
for(i = 0; i< 16; i++)
{
ii += 16;
sad += (abs(*ii - mean) +abs(*(ii+1 ) - mean)
+ abs(*(ii+2) - mean) +abs(*(ii+3 ) - mean)
+ abs(*(ii+4) - mean) +abs(*(ii+5 ) - mean)
+ abs(*(ii+6) - mean) +abs(*(ii+7 ) - mean)
+ abs(*(ii+8) - mean) +abs(*(ii+9 ) - mean)
+ abs(*(ii+10)- mean) +abs(*(ii+11) - mean)
+ abs(*(ii+12)- mean) +abs(*(ii+13) - mean)
+ abs(*(ii+14)- mean) +abs(*(ii+15) - mean));
}
return sad>>8;
}
_inline void DiffMB(MB_Structure *diff, MB_Structure *orig, int symbol)
{
int i;
int *lum_in, *Cr_in, *Cb_in, *lum_out, *Cr_out, *Cb_out;
lum_in = orig->lum[0];
lum_out = diff->lum[0];
Cr_in = orig->Cr[0];
Cr_out = diff->Cr[0];
Cb_in = orig->Cb[0];
Cb_out = diff->Cb[0];
if(symbol == 0)
{
for(i=0; i<256; i++,lum_in++,lum_out++)
*lum_out = *lum_out - *lum_in;
for(i=0; i<64; i++,Cr_in++,Cr_out++,Cb_in++,Cb_out++)
{
*Cr_out = *Cr_out - *Cr_in;
*Cb_out = *Cb_out - *Cb_in;
}
}
else
{
for(i=0; i<256; i++,lum_in++,lum_out++)
*lum_out = *lum_out + *lum_in;
for(i=0; i<64; i++,Cr_in++,Cr_out++,Cb_in++,Cb_out++)
{
*Cr_out = *Cr_out + *Cr_in;
*Cb_out = *Cb_out + *Cb_in;
}
}
}
void error(text)
char *text;
{
MessageBox( NULL ,text,"Error",MB_OK);
exit(1);
}
/* compliance warning messages to user, but don't exit() */
void error_handler(char *error_info)
{
MessageBox( NULL ,error_info,"Error",MB_OK);
exit(0);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -