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