www.pudn.com > henclib263.rar > block.cxx


/* 
* block.cxx 
* 
* implementation for 8x8 block level functions. 
* 
* Copyright (c) 2002-2004 Li Chun-lin(li_chunlin@263.net) 
* 
* This program is free software; you can redistribute it and/or 
* modify it under the terms of the GNU General Public License 
* as published by the Free Software Foundation; either version 2 
* of the License, or (at your option) any later version. 
*  
* This program is distributed in the hope that it will be useful, 
* but WITHOUT ANY WARRANTY; without even the implied warranty of 
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
* GNU General Public License for more details. 
 
* You should have received a copy of the GNU General Public License 
* along with this program; if not, write to the Free Software 
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. 
*/ 
 
#include  
#include  
#include  
#include  
#include "../include/HEnc.h" 
 
#ifdef  __cplusplus 
extern "C" { 
#endif 
 
//! Zigzag Matrix 
static int MixZig[64] = {0, 1,  5,  6,  14, 15, 27, 28, 
                         2, 4,  7,  13, 16, 26, 29, 42, 
		                 3, 8,  12, 17, 25, 30, 41, 43, 
		                 9, 11, 18, 24, 31, 40, 44, 53, 
		                10, 19, 23, 32, 39, 45, 52, 54, 
		                20, 22, 33, 38, 46, 51, 55, 60,  
		                21, 34, 37, 47, 50, 56, 59, 61, 
		                35, 36, 48, 49, 57, 58, 62, 63}; 
 
//! Matrices for obmc prediction 
static  int Mc[8][8] =  
{ 
    {4,5,5,5,5,5,5,4}, 
    {5,5,5,5,5,5,5,5}, 
    {5,5,6,6,6,6,5,5}, 
    {5,5,6,6,6,6,5,5}, 
    {5,5,6,6,6,6,5,5}, 
    {5,5,6,6,6,6,5,5}, 
    {5,5,5,5,5,5,5,5}, 
    {4,5,5,5,5,5,5,4}, 
}; 
static  int Mt[8][8] = 
{ 
    {2,2,2,2,2,2,2,2}, 
    {1,1,2,2,2,2,1,1}, 
    {1,1,1,1,1,1,1,1}, 
    {1,1,1,1,1,1,1,1}, 
    {0,0,0,0,0,0,0,0}, 
    {0,0,0,0,0,0,0,0}, 
    {0,0,0,0,0,0,0,0}, 
    {0,0,0,0,0,0,0,0}, 
}; 
static  int Mb[8][8] =  
{ 
    {0,0,0,0,0,0,0,0}, 
    {0,0,0,0,0,0,0,0}, 
    {0,0,0,0,0,0,0,0}, 
    {0,0,0,0,0,0,0,0}, 
    {1,1,1,1,1,1,1,1}, 
    {1,1,1,1,1,1,1,1}, 
    {1,1,2,2,2,2,1,1}, 
    {2,2,2,2,2,2,2,2}, 
}; 
static  int Mr[8][8] =  
{ 
    {0,0,0,0,1,1,1,2}, 
    {0,0,0,0,1,1,2,2}, 
    {0,0,0,0,1,1,2,2}, 
    {0,0,0,0,1,1,2,2}, 
    {0,0,0,0,1,1,2,2}, 
    {0,0,0,0,1,1,2,2}, 
    {0,0,0,0,1,1,2,2}, 
    {0,0,0,0,1,1,1,2}, 
}; 
static  int Ml[8][8] = 
{ 
    {2,1,1,1,0,0,0,0}, 
    {2,2,1,1,0,0,0,0}, 
    {2,2,1,1,0,0,0,0}, 
    {2,2,1,1,0,0,0,0}, 
    {2,2,1,1,0,0,0,0}, 
    {2,2,1,1,0,0,0,0}, 
    {2,2,1,1,0,0,0,0}, 
    {2,1,1,1,0,0,0,0}, 
}; 
 
 
/*! 
******************************************************************************* 
* 
*   Name:          pred_lum 
*   Description:   lum prediction for the data of one 8x8 block 
*   Input:         interpolated lum image, the position of current block, MV 
*   Output:        prediction data 
*   Optimization:  no 
*   Last modified: 2002/12/21  
* 
*******************************************************************************/ 
void pred_lum(int pix_x, int pix_y, MotionVector *MV, unsigned char *ipol,  
			  int lx, unsigned char *pred_block) 
{ 
	int pred_x, pred_y; 
	int i, j, k, l; 
	int h_space = 2; 
	int v_space = lx * 2; 
	unsigned char *tmp1; 
	unsigned char *tmp2 = pred_block; 
 
	pred_x = 2*pix_x + 2*MV->x + MV->x_half; 
	pred_y = 2*pix_y + 2*MV->y + MV->y_half; 
	tmp1 = ipol + lx*pred_y + pred_x; 
 
	for (i = 0, k = 0; i < 8; i++, k+=v_space) 
	{ 
		for (j = 0, l = 0; j < 8; j++, l+=h_space) 
		{ 
			*tmp2 = *(tmp1 + k + l); 
			tmp2++; 
		} 
	} 
 
} 
 
/*! 
******************************************************************************* 
* 
*   Name:          pred_lum_bid 
*   Description:   bi-direction lum prediction for the data of one 8x8 block(B frames only) 
*   Input:         interpolated lum images, the position of current block, displacement 
*   Output:        prediction data 
*   Optimization:  no 
*   Last modified: 2003/1/9  
* 
*******************************************************************************/ 
void pred_lum_bid(int pix_x, int pix_y, int dxf, int dyf, int dxb, int dyb,  
					unsigned char *prev_ipol, unsigned char *next_ipol, int lx,  
					unsigned char *pred_block) 
{ 
	int fw_pred_x, fw_pred_y; 
	int bw_pred_x, bw_pred_y; 
	int i, j, k, l; 
	int h_space = 2; 
	int v_space = lx * 2; 
	unsigned char *tmp1; 
	unsigned char *tmp2; 
	unsigned char *tmp3 = pred_block; 
 
	fw_pred_x = 2*pix_x + dxf; 
	fw_pred_y = 2*pix_y + dyf; 
	bw_pred_x = 2*pix_x + dxb; 
	bw_pred_y = 2*pix_y + dyb; 
 
	tmp1 = prev_ipol + lx*fw_pred_y + fw_pred_x; 
	tmp2 = next_ipol + lx*bw_pred_y + bw_pred_x; 
 
	for (i = 0, k = 0; i < 8; i++, k+=v_space) 
	{ 
		for (j = 0, l = 0; j < 8; j++, l+=h_space) 
		{ 
			*tmp3 = (*(tmp1 + k + l) + *(tmp2 + k + l)) / 2; 
			tmp3++; 
		} 
	} 
} 
 
/*! 
******************************************************************************* 
* 
*   Name:          pred_obmc 
*   Description:   overlaped motion compensation prediction for lum 
*   Input:          
*   Output:         
*   Optimization:  no 
*   Last modified: 2002/12/25 
* 
*******************************************************************************/ 
void pred_obmc(int x, int y, MotionVector *MV[6][MBR+1][MBC+2], int pic_width,  
			   unsigned char *prev_ipol, int lx, int block, unsigned char *pred_block) 
{ 
	int r = y/16+1; 
	int c = x/16+1; 
	int use4mv_c = (MV[0][r][c]->Mode == MODE_INTER4V ? 1 : 0); 
	int	use4mv_t = (MV[0][r-1][c]->Mode == MODE_INTER4V ? 1 : 0); 
	int use4mv_l = (MV[0][r][c-1]->Mode == MODE_INTER4V ? 1 : 0); 
	int use4mv_r = (MV[0][r][c+1]->Mode == MODE_INTER4V ? 1 : 0); 
	int intra_t, intra_l, intra_r; 
	int vecc, vect, vecb, vecl, vecr; 
	int x_curr, y_curr, x_top, y_top, x_btm, y_btm, x_left, y_left, x_right, y_right; 
	int pred_x_c, pred_x_t, pred_x_b, pred_x_l, pred_x_r; 
	int pred_y_c, pred_y_t, pred_y_b, pred_y_l, pred_y_r; 
	int val_c, val_t, val_b, val_l, val_r; 
	int m, n; 
 
	intra_t = (MV[0][r-1][c]->Mode == MODE_INTRA ? 1 : 0); 
	intra_t = (MV[0][r-1][c]->Mode == MODE_INTRA_Q ? 1 : intra_t);  
	intra_l = (MV[0][r][c-1]->Mode == MODE_INTRA ? 1 : 0); 
	intra_l = (MV[0][r][c-1]->Mode == MODE_INTRA_Q ? 1 : intra_l);  
	intra_r = (MV[0][r][c+1]->Mode == MODE_INTRA ? 1 : 0); 
	intra_r = (MV[0][r][c+1]->Mode == MODE_INTRA_Q ? 1 : intra_r);  
 
	switch (block) 
	{ 
	case 1: 
		vecc = use4mv_c ? 1 : 0; 
		x_curr = c; 
		y_curr = r; 
 
		vect  = intra_t ? vecc : (use4mv_t ? 3 : 0); 
		x_top = c; 
		y_top = intra_t ? r : r-1; 
 
		vecb = use4mv_c ? 3 : 0; 
		x_btm = c; 
		y_btm = r; 
 
		vecl = intra_l ? vecc: (use4mv_l ? 2 : 0); 
		x_left = intra_l ? c : c-1; 
		y_left = r; 
 
		vecr = use4mv_c ? 2 : 0; 
		x_right = c; 
		y_right = r; 
 
		if (1 == c) 
		{ 
			vecl = vecc; 
			x_left = 1; 
		} 
		if (1 == r) 
		{ 
			vect = vecc; 
			y_top = 1; 
		} 
 
		break; 
	case 2: 
		vecc = use4mv_c ? 2 : 0; 
		x_curr = c; 
		y_curr = r; 
 
		vect = intra_t ? vecc : (use4mv_t ? 4 : 0); 
		x_top = c; 
		y_top = intra_t ? r : r-1; 
 
		vecb = use4mv_c ? 4 : 0; 
		x_btm = c; 
		y_btm = r; 
 
		vecl = use4mv_c ? 1 : 0; 
		x_left = c; 
		y_left = r; 
 
		vecr = intra_r ? vecc : (use4mv_r ? 1 : 0); 
		x_right = intra_r ? c : c+1; 
		y_right = r; 
 
		if (1 == r) 
		{ 
			vect = vecc; 
			y_top = 1; 
		} 
		if (c == pic_width/16) 
		{ 
			vecr = vecc; 
			x_right = c; 
		} 
		break; 
	case 3: 
		vecc = use4mv_c ? 3 : 0; 
		x_curr = c; 
		y_curr = r; 
 
		vect = use4mv_c ? 1 : 0; 
		x_top = c; 
		y_top = r; 
 
		vecb = vecc; 
		x_btm = c; 
		y_btm = r; 
 
		vecl = intra_l ? vecc : (use4mv_l ? 4 : 0); 
		x_left = intra_l ? c : c-1; 
		y_left = r; 
 
		vecr = use4mv_c ? 4 : 0; 
		x_right = c; 
		y_right = r; 
 
		if (1 == c) 
		{ 
			vecl = vecc; 
			x_left = 1; 
		} 
		break; 
	case 4: 
		vecc = use4mv_c ? 4 : 0; 
		x_curr = c; 
		y_curr = r; 
 
		vect = use4mv_c ? 2 : 0; 
		x_top = c; 
		y_top = r; 
 
		vecb = vecc; 
		x_btm = c; 
		y_btm = r; 
 
		vecl = use4mv_c ? 3 : 0; 
		x_left = c; 
		y_left = r; 
 
		vecr = intra_r ? vecc : (use4mv_r ? 3 : 0); 
		x_right = intra_r ? c : c+1; 
		y_right = r; 
 
		if (c == pic_width/16) 
		{ 
			vecr = vecc; 
			x_right = c; 
		} 
		break; 
	default: 
		printf("obmc error, block type not exist.\n"); 
		exit(-1); 
	} 
 
	pred_x_c = 2*x + (((block-1)&1)<<4) + MV[vecc][y_curr][x_curr]->x*2 + MV[vecc][y_curr][x_curr]->x_half; 
	pred_x_t = 2*x + (((block-1)&1)<<4) + MV[vect][y_top][x_top]->x*2 + MV[vect][y_top][x_top]->x_half; 
	pred_x_b = 2*x + (((block-1)&1)<<4) + MV[vecb][y_btm][x_btm]->x*2 + MV[vecb][y_btm][x_btm]->x_half; 
	pred_x_l = 2*x + (((block-1)&1)<<4) + MV[vecl][y_left][x_left]->x*2 + MV[vecl][y_left][x_left]->x_half; 
	pred_x_r = 2*x + (((block-1)&1)<<4) + MV[vecr][y_right][x_right]->x*2 + MV[vecr][y_right][x_right]->x_half; 
 
	pred_y_c = 2*y + (((block-1)&2)<<3) + MV[vecc][y_curr][x_curr]->y*2 + MV[vecc][y_curr][x_curr]->y_half; 
	pred_y_t = 2*y + (((block-1)&2)<<3) + MV[vect][y_top][x_top]->y*2 + MV[vect][y_top][x_top]->y_half; 
	pred_y_b = 2*y + (((block-1)&2)<<3) + MV[vecb][y_btm][x_btm]->y*2 + MV[vecb][y_btm][x_btm]->y_half; 
	pred_y_l = 2*y + (((block-1)&2)<<3) + MV[vecl][y_left][x_left]->y*2 + MV[vecl][y_left][x_left]->y_half; 
	pred_y_r = 2*y + (((block-1)&2)<<3) + MV[vecr][y_right][x_right]->y*2 + MV[vecr][y_right][x_right]->y_half; 
	for (n = 0; n < 8; n++) 
	{ 
		for (m = 0; m < 8; m++) 
		{ 
			val_c = *(prev_ipol + (pred_y_c + n*2)*lx + pred_x_c+m*2) * Mc[n][m]; 
			val_t = *(prev_ipol + (pred_y_t + n*2)*lx + pred_x_t+m*2) * Mt[n][m]; 
			val_b = *(prev_ipol + (pred_y_b + n*2)*lx + pred_x_b+m*2) * Mb[n][m]; 
			val_l = *(prev_ipol + (pred_y_l + n*2)*lx + pred_x_l+m*2) * Ml[n][m]; 
			val_r = *(prev_ipol + (pred_y_r + n*2)*lx + pred_x_r+m*2) * Mr[n][m]; 
 
			*(pred_block + n*8 +m) = (val_c + val_t + val_b + val_l + val_r + 4)>>3; 
		} 
	} 
} 
 
/*! 
******************************************************************************* 
* 
*   Name:          pred_chrom 
*   Description:   chrom prediction for the data of one 8x8 block 
*   Input:         reference picture, the position of current block. 
*   Output:        prediction data 
*   Optimization:  no 
*   Last modified: 2002/11/21  
*   Note:          the chrom data is interpolated online 
* 
*******************************************************************************/ 
void pred_chrom(int pix_x, int pix_y, unsigned char *prev, 	int lx,  
				int dx, int dy, unsigned char *pred_block) 
				 
{ 
	int xint, yint; 
	int xh, yh; 
	int i, j; 
	int x_off, y_off; 
	unsigned char *tmp = pred_block; 
 
    xint = dx>>1; 
    xh = dx & 1; 
    yint = dy>>1; 
    yh = dy & 1; 
 
	if (!xh && !yh)  //!< xh and yh are both zero 
	{ 
		x_off = pix_x + xint; 
		y_off = pix_y + yint; 
		for (i = 0; i < 8; i++) 
		{ 
			for (j = 0; j < 8; j++) 
			{ 
				*tmp = *(prev + (y_off+i)*lx + x_off+j); 
				tmp++; 
			} 
		} 
	} 
	else if (!xh && yh) //!< yh is not zero 
	{ 
		x_off = pix_x + xint; 
		y_off = pix_y + yint; 
		for (i = 0; i < 8; i++) 
		{ 
			for (j = 0; j < 8; j++) 
			{ 
				*tmp = (*(prev + (y_off+i)*lx + x_off+j) + 
					    *(prev + (y_off+i+yh)*lx + x_off+j) + 1)>>1; 
				tmp++; 
			} 
		} 
	} 
	else if (xh && !yh)  //!< xh is not zero 
	{ 
		x_off = pix_x + xint; 
		y_off = pix_y + yint; 
		for (i = 0; i < 8; i++) 
		{ 
			for (j = 0; j < 8; j++) 
			{ 
				*tmp = (*(prev + (y_off+i)*lx + x_off+j) + 
					    *(prev + (y_off+i)*lx + x_off+j+xh) + 1)>>1; 
				tmp++; 
			} 
		} 
	} 
	else   //! neither xh nor yh is zero 
	{ 
		x_off = pix_x + xint; 
		y_off = pix_y + yint; 
		for (i = 0; i < 8; i++) 
		{ 
			for (j = 0; j < 8; j++) 
			{ 
				*tmp = (*(prev + (y_off+i)*lx + x_off+j) + 
					   *(prev + (y_off+i)*lx + x_off+j+xh) + 
						*(prev + (y_off+i+yh)*lx + x_off+j) + 
						*(prev + (y_off+i+yh)*lx + x_off+j+xh) +  
						2)>>2; 
				tmp++; 
			} 
		} 
	} 
} 
 
/*! 
******************************************************************************* 
* 
*   Name:          pred_chrom_bid 
*   Description:   bi-direction chrom prediction for the data of one 8x8 block 
*                  (only used in B frames)  
*   Input:         the pointer to previous picture and next picture, 
*                  the position of current block, forward and backward displacement 
*   Output:        prediction data 
*   Optimization:  NO 
*   Last modified: 2002/11/21  
*   Note:          the chrom data is interpolated online 
* 
*******************************************************************************/ 
void pred_chrom_bid(int pix_x, int pix_y, unsigned char *prev, 	unsigned char *next, int lx,  
				int dxf, int dyf, int dxb, int dyb, unsigned char *pred_block) 
{ 
	int xint1, yint1, xint2, yint2; 
	int xh1, yh1, xh2, yh2; 
	int i, j; 
	int x_off, y_off; 
	unsigned char *tmp = pred_block; 
 
    xint1 = dxf>>1; 
    xh1 = dxf & 1; 
    yint1 = dyf>>1; 
    yh1 = dyf & 1; 
 
 
	if (!xh1 && !yh1)  //!< xh and yh are both zero 
	{ 
		x_off = pix_x + xint1; 
		y_off = pix_y + yint1; 
		for (i = 0; i < 8; i++) 
		{ 
			for (j = 0; j < 8; j++) 
			{ 
				*tmp = *(prev + (y_off+i)*lx + x_off+j); 
				tmp++; 
			} 
		} 
	} 
	else if (!xh1 && yh1) //!< yh is not zero 
	{ 
		x_off = pix_x + xint1; 
		y_off = pix_y + yint1; 
		for (i = 0; i < 8; i++) 
		{ 
			for (j = 0; j < 8; j++) 
			{ 
				*tmp = (*(prev + (y_off+i)*lx + x_off+j) + 
					    *(prev + (y_off+i+yh1)*lx + x_off+j) + 1)>>1; 
				tmp++; 
			} 
		} 
	} 
	else if (xh1 && !yh1)  //!< xh is not zero 
	{ 
		x_off = pix_x + xint1; 
		y_off = pix_y + yint1; 
		for (i = 0; i < 8; i++) 
		{ 
			for (j = 0; j < 8; j++) 
			{ 
				*tmp = (*(prev + (y_off+i)*lx + x_off+j) + 
					    *(prev + (y_off+i)*lx + x_off+j+xh1) + 1)>>1; 
				tmp++; 
			} 
		} 
	} 
	else   //! neither xh nor yh is zero 
	{ 
		x_off = pix_x + xint1; 
		y_off = pix_y + yint1; 
		for (i = 0; i < 8; i++) 
		{ 
			for (j = 0; j < 8; j++) 
			{ 
				*tmp = (*(prev + (y_off+i)*lx + x_off+j) + 
					   *(prev + (y_off+i)*lx + x_off+j+xh1) + 
						*(prev + (y_off+i+yh1)*lx + x_off+j) + 
						*(prev + (y_off+i+yh1)*lx + x_off+j+xh1) +  
						2)>>2; 
				tmp++; 
			} 
		} 
	} 
 
	tmp = pred_block; 
	xint2 = dxb>>1; 
	xh2 = dxb & 1; 
	yint2 = dyb>>1; 
	yh2 = dyb & 1; 
 
	if (!xh2 && !yh2)  //!< xh and yh are both zero 
	{ 
		x_off = pix_x + xint2; 
		y_off = pix_y + yint2; 
		for (i = 0; i < 8; i++) 
		{ 
			for (j = 0; j < 8; j++) 
			{ 
				*tmp = (*tmp)/2 + (*(next + (y_off+i)*lx + x_off+j))/2; 
				tmp++; 
			} 
		} 
	} 
	else if (!xh2 && yh2) //!< yh is not zero 
	{ 
		x_off = pix_x + xint2; 
		y_off = pix_y + yint2; 
		for (i = 0; i < 8; i++) 
		{ 
			for (j = 0; j < 8; j++) 
			{ 
				*tmp = (*tmp)/2 +  
					    (*(next + (y_off+i)*lx + x_off+j) + 
					     *(next + (y_off+i+yh2)*lx + x_off+j) + 1)/4;				       			 
				tmp++; 
			} 
		} 
	} 
	else if (xh2 && !yh2)  //!< xh is not zero 
	{ 
		x_off = pix_x + xint2; 
		y_off = pix_y + yint2; 
		for (i = 0; i < 8; i++) 
		{ 
			for (j = 0; j < 8; j++) 
			{ 
				*tmp = (*tmp)/2 +  
					   (*(next + (y_off+i)*lx + x_off+j) + 
					    *(next + (y_off+i)*lx + x_off+j+xh2) + 1)/4; 
				tmp++; 
			} 
		} 
	} 
	else   //! neither xh nor yh is zero 
	{ 
		x_off = pix_x + xint2; 
		y_off = pix_y + yint2; 
		for (i = 0; i < 8; i++) 
		{ 
			for (j = 0; j < 8; j++) 
			{ 
				*tmp = (*tmp)/2 + 
					   (*(next + (y_off+i)*lx + x_off+j) + 
					    *(next + (y_off+i)*lx + x_off+j+xh2) + 
					    *(next + (y_off+i+yh2)*lx + x_off+j) + 
						*(next + (y_off+i+yh2)*lx + x_off+j+xh2) +  
						2)/8; 
				tmp++; 
			} 
		} 
	} 
} 
 
/*! 
******************************************************************************* 
* 
*   Name:          make_diff 
*   Description:   compute difference value of one 8x8 block during inter-frame coding  
*   Input:         the pointer of current block, the pointer of predictive block 
*   Output:         
*   Effect:        Fill difference block 
*   Optimization:  NO 
*   Last modified: 2002/11/22 
* 
*******************************************************************************/ 
void make_diff(unsigned char* curr_block, int pic_width, unsigned char *pred_block, short *diff_block) 
{ 
	unsigned char *tmp1 = curr_block; 
	unsigned char *tmp2 = pred_block; 
	short       *tmp3 = diff_block; 
	int i, j, k; 
 
	for (i = 0, k = 0; i < 8; i++, k+=pic_width) 
	{ 
		for (j = 0; j < 8; j++) 
		{ 
			*tmp3 = (short)( *(tmp1 + k + j) - *tmp2 ); 
			tmp2++; 
			tmp3++; 
		} 
	} 
} 
 
/*! 
******************************************************************************* 
* 
*   Name:          recon_pic 
*   Description:   reconstruct one 8x8 block during inter-frame coding 
*   Input:         pred_block, diff_block 
*   Output:         
*   Effect:        Fill corresponding area of recon image 
*   Optimization:  NO 
*   Last modified: 2002/11/22 
* 
*******************************************************************************/ 
void recon_pic(unsigned char* recon_block, int pic_width, unsigned char *pred_block, short *diff_block) 
{ 
	unsigned char *tmp1 = recon_block; 
	unsigned char *tmp2 = pred_block; 
	short       *tmp3 = diff_block; 
	int           i, j, k; 
 
	for (i = 0, k = 0; i < 8; i++, k+=pic_width) 
	{ 
		for (j = 0; j < 8; j ++) 
		{ 
			*(tmp1 + k + j) = (unsigned char)mmin(255, mmax(0, (short)(*tmp3 + *tmp2))); 
			tmp2++; 
			tmp3++; 
		} 
	} 
 
} 
 
 
/***************************************************************************** 
//Name        : Quant_blk_I 
//Input       : a 8*8 16-bit block coefficients to be quanted pointed by curr_block 
//		        QUANT Parameter,QP 
//Output      : Quanted coefficients, qun_blk 
//              zero flag, return value 
//Description : quant and scan 
//              special quant function for INTRA block for the difference  
//              between INTRA & INTER in quant, so you can use this function  
//              for quant in I picture encode directly. 
//Optimization: NO 
//Last modified on 2002.11.22 by zj 
******************************************************************************/ 
int Quant_blk_I (short *curr_blk,short *qun_blk, int QP) 
{ 
  int i; 
  int level; 
  int nonezero = 0; 
   
  if (QP) 
  { 
      qun_blk[0] = mmax(1,mmin(254, (curr_blk[0]+4)/8)); 
 
      for (i = 1; i < 64; i++)  
	  { 
        level = (abs(curr_blk[i])) / (2*QP); 
		if (level == 0) 
		{ 
			qun_blk[MixZig[i]] = 0; 
 
		} 
		else 
		{ 
			qun_blk[MixZig[i]] =  mmin(127,mmax(-127,sign(curr_blk[i]) * level)); 
			nonezero = 1; 
		} 
      } 
  } 
 
  return nonezero; 
} 
 
 
/************************************************************************ 
//Name         : DeQuant_blk_I 
//Input        : a 8*8 16-bit block for dequant, curr_blk 
//               quant parameter,QP 
//Output       : Dequanted block for IDCT, curr_block 
//Dciscription : the inverse process of Quant_block_I  
//Optimization : NO 
//Last modifid on 2002.11.22 by zj 
*************************************************************************/ 
void DeQuant_blk_I (short *curr_blk, short *recn_blk, int QP) 
{ 
	int i; 
    for (i = 0; i < 64; i++)  
	{ 
      if (curr_blk[MixZig[i]])  
	  { 
        if ((QP % 2) == 1) 
          recn_blk[i] = QP * (2*abs(curr_blk[MixZig[i]]) + 1); 
        else 
          recn_blk[i] = QP * (2*abs(curr_blk[MixZig[i]]) + 1) - 1; 
        recn_blk[i] = sign(curr_blk[MixZig[i]]) * recn_blk[i]; 
      } 
      else 
        recn_blk[i] = 0; 
    } 
      recn_blk[0] = curr_blk[0]*8; 
} 
 
/*! 
******************************************************************************* 
* 
*   Name:          Quant_blk_P       
*   Description:   Quant and scan  
*   Input:         curr_blk 
*   Output:        qun_blk 
*   Optimization:  NO 
*   Last modified: 2003.2.27 
* 
*******************************************************************************/ 
int Quant_blk_P (short *curr_blk,short *qun_blk, int QP) 
{ 
  int i; 
  int level; 
  int nonezero = 0; 
  int qpp = QP/2; 
  float qp = (float) 1 / (2*QP); 
   
  if (QP) 
  { 
 
      for (i = 0; i < 64; i++)  
	  { 
        //level = (abs(curr_blk[i]) - QP/2) / (2*QP); 
		level = (int) ((abs(curr_blk[i]) - qpp) * qp);//level = (int) (abs(curr_blk[i]) - qpp) * qp; 
        if (!level) 
		{ 
			qun_blk[MixZig[i]] = 0;	 
 
		} 
		else 
		{ 
			qun_blk[MixZig[i]] =  mmin(127,mmax(-127,sign(curr_blk[i]) * level)); 
			nonezero = 1; 
		} 
	  } 
  } 
 
  return nonezero; 
} 
 
 
 
/*! 
******************************************************************************* 
* 
*   Name:          DeQuant_blk_P       
*   Description:   DeQuant and inverse scan  
*   Input:         curr_blk  
*   Output:        recn_blk  
*   Optimization:  NO 
*   Last modified: 2003.2.27 
* 
*******************************************************************************/ 
void DeQuant_blk_P (short *curr_blk, short *recn_blk, int QP) 
{ 
	int i; 
    for (i = 0; i < 64; i++)  
	{ 
      if (curr_blk[MixZig[i]])  
	  { 
        if ((QP % 2) == 1) 
          recn_blk[i] = QP * (2*abs(curr_blk[MixZig[i]]) + 1); 
        else 
          recn_blk[i] = QP * (2*abs(curr_blk[MixZig[i]]) + 1) - 1; 
        recn_blk[i] = sign(curr_blk[MixZig[i]]) * recn_blk[i]; 
      } 
      else 
        recn_blk[i] = 0; 
    } 
} 
 
/************************************************************************************** 
//Name        : fdct 
//Input       : 8*8 16-bit block data to be transformed: curr_blk. 
//Output      : transformed data for quant, rsltblk. 
//Description : DCT transform 
//Optimization: fdct_mmx.cpp(for IA) 
//Last modified on 2003.2.11 by lcl 
**************************************************************************************/ 
void fdct (short *curr_blk, short *rsltblk) 
{ 
  int j1, i, j, k; 
  float b[8]; 
  float b1[8]; 
  float d[8][8]; 
  float f0 = (float) .7071068; 
  float f1 = (float) .4903926; 
  float f2 = (float) .4619398; 
  float f3 = (float) .4157348; 
  float f4 = (float) .3535534; 
  float f5 = (float) .2777851; 
  float f6 = (float) .1913417; 
  float f7 = (float) .0975452; 
 
  for (i = 0, k = 0; i < 8; i++) 
  { 
	   
	  for (j = 0; j < 4; j++) 
	  { 
		  j1 = 7 - j; 
		  b1[j] = (float) curr_blk[j + k] + (float) curr_blk[j1 + k]; 
		  b1[j1] = (float) curr_blk[j + k] - (float) curr_blk[j1 + k]; 
	  } 
	  k += 8; 
	  b[0] = b1[0] + b1[3]; 
	  b[1] = b1[1] + b1[2]; 
	  b[2] = b1[1] - b1[2]; 
	  b[3] = b1[0] - b1[3]; 
	  b[4] = b1[4]; 
	  b[5] = (b1[6] - b1[5]) * f0; 
	  b[6] = (b1[6] + b1[5]) * f0; 
	  b[7] = b1[7]; 
	  d[i][0] = (b[0] + b[1]) * f4; 
	  d[i][4] = (b[0] - b[1]) * f4; 
	  d[i][2] = b[2] * f6 + b[3] * f2; 
	  d[i][6] = b[3] * f6 - b[2] * f2; 
	  b1[4] = b[4] + b[5]; 
	  b1[7] = b[7] + b[6]; 
	  b1[5] = b[4] - b[5]; 
	  b1[6] = b[7] - b[6]; 
	  d[i][1] = b1[4] * f7 + b1[7] * f1; 
	  d[i][5] = b1[5] * f3 + b1[6] * f5; 
	  d[i][7] = b1[7] * f7 - b1[4] * f1; 
	  d[i][3] = b1[6] * f3 - b1[5] * f5; 
  } 
  /* Vertical transform */ 
  for (i = 0; i < 8; i++) 
  { 
	  for (j = 0; j < 4; j++) 
	  { 
		  j1 = 7 - j; 
		  b1[j] = d[j][i] + d[j1][i]; 
		  b1[j1] = d[j][i] - d[j1][i]; 
	  } 
	  b[0] = b1[0] + b1[3]; 
	  b[1] = b1[1] + b1[2]; 
	  b[2] = b1[1] - b1[2]; 
	  b[3] = b1[0] - b1[3]; 
	  b[4] = b1[4]; 
	  b[5] = (b1[6] - b1[5]) * f0; 
	  b[6] = (b1[6] + b1[5]) * f0; 
	  b[7] = b1[7]; 
	  rsltblk[i] = (short) ((b[0] + b[1]) * f4); 
	  rsltblk[32 + i] = (short) ((b[0] - b[1]) * f4); 
	  rsltblk[16 + i] = (short) (b[2] * f6 + b[3] * f2); 
	  rsltblk[48 + i] = (short) (b[3] * f6 - b[2] * f2); 
	  b1[4] = b[4] + b[5]; 
	  b1[7] = b[7] + b[6]; 
	  b1[5] = b[4] - b[5]; 
	  b1[6] = b[7] - b[6]; 
	  rsltblk[8 + i] = (short) (b1[4] * f7 + b1[7] * f1); 
	  rsltblk[40 + i] = (short) (b1[5] * f3 + b1[6] * f5); 
	  rsltblk[56 + i] = (short) (b1[7] * f7 - b1[4] * f1); 
	  rsltblk[24 + i] = (short) (b1[6] * f3 - b1[5] * f5); 
  } 
   
} 
 
/****************************************************************************************** 
//Name        : idct 
//Input       : a 8*8 16-bit block dequanted: curr_blk; 
//Output      : 8*8 16-bit block: des_blk 
//Description : inverse DCT 
//Optimization: idctmmx.asm; idct_mmx.cpp. (for IA) 
//Last modified on 2002.11.22 by zj 
*******************************************************************************************/ 
void idct (short *curr_blk, short *des_blk) 
{ 
  int j1, i, j, k; 
  double b[8], b1[8], d[8][8]; 
  double f0 = .7071068; 
  double f1 = .4903926; 
  double f2 = .4619398; 
  double f3 = .4157348; 
  double f4 = .3535534; 
  double f5 = .2777851; 
  double f6 = .1913417; 
  double f7 = .0975452; 
  double e, f, g, h; 
 
  /* Horizontal */ 
 
  for (i = 0, k = 0; i < 8; i++, k += 8) 
  { 
    e = ((double) curr_blk[1 + k]) * f7 - ((double) curr_blk[7 + k]) * f1; 
    h = ((double) curr_blk[7 + k]) * f7 + ((double) curr_blk[1 + k]) * f1; 
    f = ((double) curr_blk[k + 5]) * f3 - ((double) curr_blk[k + 3]) * f5; 
    g = ((double) curr_blk[k + 3]) * f3 + ((double) curr_blk[k + 5]) * f5; 
 
    b1[0] = ((double) (curr_blk[k + 0] + curr_blk[k + 4])) * f4; 
    b1[1] = ((double) (curr_blk[k + 0] - curr_blk[k + 4])) * f4; 
    b1[2] = ((double) curr_blk[k + 2]) * f6 - ((double) curr_blk[k + 6]) * f2; 
    b1[3] = ((double) curr_blk[k + 6]) * f6 + ((double) curr_blk[k + 2]) * f2; 
    b[4] = e + f; 
    b1[5] = e - f; 
    b1[6] = h - g; 
    b[7] = h + g; 
 
    b[5] = (b1[6] - b1[5]) * f0; 
    b[6] = (b1[6] + b1[5]) * f0; 
    b[0] = b1[0] + b1[3]; 
    b[1] = b1[1] + b1[2]; 
    b[2] = b1[1] - b1[2]; 
    b[3] = b1[0] - b1[3]; 
 
    for (j = 0; j < 4; j++) 
    { 
      j1 = 7 - j; 
      d[i][j] = b[j] + b[j1]; 
      d[i][j1] = b[j] - b[j1]; 
    } 
  } 
 
 
  /* Vertical */ 
 
  for (i = 0; i < 8; i++) 
  { 
    e = d[1][i] * f7 - d[7][i] * f1; 
    h = d[7][i] * f7 + d[1][i] * f1; 
    f = d[5][i] * f3 - d[3][i] * f5; 
    g = d[3][i] * f3 + d[5][i] * f5; 
 
    b1[0] = (d[0][i] + d[4][i]) * f4; 
    b1[1] = (d[0][i] - d[4][i]) * f4; 
    b1[2] = d[2][i] * f6 - d[6][i] * f2; 
    b1[3] = d[6][i] * f6 + d[2][i] * f2; 
    b[4] = e + f; 
    b1[5] = e - f; 
    b1[6] = h - g; 
    b[7] = h + g; 
 
    b[5] = (b1[6] - b1[5]) * f0; 
    b[6] = (b1[6] + b1[5]) * f0; 
    b[0] = b1[0] + b1[3]; 
    b[1] = b1[1] + b1[2]; 
    b[2] = b1[1] - b1[2]; 
    b[3] = b1[0] - b1[3]; 
 
 
	for (j = 0, k = 0; j < 4; j++, k += 8) 
	{ 
		j1 = 7 - j; 
		des_blk[k + i] = (short) mnint(b[j] + b[j1]); 
		des_blk[56 - k + i] = (short) mnint(b[j] - b[j1]); 
	} 
 
  } 
} 
 
 
 
/*! 
******************************************************************************* 
* 
*   Name:          block_copy1 
*   Description:   copy a block(8x8) of data to somewhere in a image 
*   Input:         the pointer of source block, the pointer of destination, 
*                  width of image 
*   Output:        none 
*   Optimization:   
*   Last modified: 2002/11/20 
* 
*******************************************************************************/ 
void block_copy1( unsigned char *des_block, unsigned char *src_block, int lx_des) 
{ 
	unsigned char *tmp = src_block; 
	int i, j, k; 
 
	for (i = 0, k = 0; i < 8; i++, k+=lx_des) 
	{ 
		 
		for(j = 0; j < 8; j++) 
		{ 
			*(des_block + k + j) = *tmp; 
			tmp++; 
		} 
	 
	}	 
 
} 
/*! 
******************************************************************************* 
* 
*   Name:          block_copy2 
*   Description:   copy a block(8x8) of data in the picture to a 8x8 block 
*   Input:         the pointer of source block, the pointer of destination, 
*                  width of image 
*   Output:        none 
*   Optimization:    
*   Last modified: 2003/2/11 
* 
*******************************************************************************/ 
void block_copy2(short *des_block, unsigned char *src_block, int lx_src) 
{ 
	short *tmp = des_block; 
	int i, j, k; 
 
	for (i = 0, k = 0; i < 8; i++, k+=lx_src) 
	{ 
		for(j = 0; j < 8; j++) 
		{ 
			*tmp = (short) (*(src_block + k + j));  
			tmp++; 
		} 
	} 
 
} 
/*! 
******************************************************************************* 
* 
*   Name:          block_copy3 
*   Description:   copy a block(8x8) of data in 8x8 block to the picture 
*   Input:         the pointer of source block, the pointer of destination, 
*                  width of image 
*   Output:        none 
*   Optimizaiton:   
*   Last modified: 2003/2/25 
* 
*******************************************************************************/ 
void block_copy3(unsigned char *des_block, short *src_block, int lx_des) 
{ 
	short *tmp = src_block; 
	int i, j, k; 
 
	for (i = 0, k = 0; i < 8; i++, k+=lx_des) 
	{ 
		for(j = 0; j < 8; j++) 
		{ 
			*(des_block + k + j) =(unsigned char)mmin(255, mmax(0, mnint (*tmp)));  
			tmp++; 
		} 
	} 
 
} 
 
#ifdef  __cplusplus 
} 
#endif