www.pudn.com > henclib263.rar > macroblock.cxx
/* * macroblock.cxx * * implementation for the macroblock 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/macroblock.h" #include "../include/block.h" #include#ifdef __cplusplus extern "C" { #endif //! find MV for chroma block according to MV(s) of luma block void findchromMV(H263VencStatus *encoder, MCParam *MC, int x, int y, int *dx, int *dy, int BACKWARD); //! find both forward and backward MV for chroma block in direct prediction mode of B pictures void findchromMV_dir(H263VencStatus *encoder, MCParam *MC, int x, int y, int *dx1, int *dy1, int *dx2, int *dy2); /*! ******************************************************************************* * * Name: MB_Encode_P * Description: Encode one Macroblock in P mode(make diff,dct,Q,IQ,IDct,data-recon) * Input: position of curr-MB, encoder structure, MV * Output: qcoeff_p * Side effect: write reconstructive data to recon_pic in corresponding position * Return: cbp * Last modified: 2002/12/17 * *******************************************************************************/ int MB_Encode_P(H263VencStatus *encoder, int pix_x, int pix_y, MCParam *MC, short *qcoeff_p) { int i, j; int flag = 32; unsigned char *curr_block; unsigned char *recon_block; unsigned char pred_block[64]; short diff_block[64]; MB_structure curr_mb; MB_structure recon_mb; MotionVector *MV; int dx, dy; int cbp = 0; int pic_width = encoder->pels; int rec_width = encoder->mv_outside_frame ? encoder->pels + 32 : encoder->pels; int lx_ipol = encoder->mv_outside_frame ? pic_width*2+64 : pic_width*2; int lx_ref_c = encoder->mv_outside_frame ? pic_width/2+16 : pic_width/2; int QP = encoder->total_Q; unsigned char *prev_ipol = encoder->prev_ipol; Image *ref_img = &(encoder->frame_buf[encoder->ref_index]); Image *curr_img = &(encoder->frameToEncode); Image *recon_img = &(encoder->frame_buf[encoder->zero_index]); //! Find MB in the image curr_mb.pLum = curr_img->pLum + pix_y * pic_width + pix_x; curr_mb.pCb = curr_img->pCb + pix_y * pic_width/4 + pix_x/2; curr_mb.pCr = curr_img->pCr + pix_y * pic_width/4 + pix_x/2; recon_mb.pLum = recon_img->pLum + pix_y * rec_width + pix_x; recon_mb.pCb = recon_img->pCb + pix_y * rec_width/4 + pix_x/2; recon_mb.pCr = recon_img->pCr + pix_y * rec_width/4 + pix_x/2; //! Encode each block in the MB //!4 lum blocks for (i = 0; i < 16; i+=8) { for (j = 0; j < 16; j+=8) { curr_block = curr_mb.pLum + i*pic_width + j; recon_block = recon_mb.pLum + i*rec_width + j; if (!encoder->obmc) { if (encoder->use4mv && (MC->mv_frame[0][pix_y/16+1][pix_x/16+1]->Mode == MODE_INTER4V)) { MV = MC->mv_frame[(j>>3)+(i>>2)+1][pix_y/16+1][pix_x/16+1]; } else { MV = MC->mv_frame[0][pix_y/16+1][pix_x/16+1]; } pred_lum(pix_x+j, pix_y+i, MV, prev_ipol, lx_ipol, pred_block); } else { pred_obmc(pix_x, pix_y, MC->mv_frame, pic_width, prev_ipol, lx_ipol, (j>>3)+(i>>2)+1, pred_block); } make_diff(curr_block, pic_width, pred_block, diff_block); fdct(diff_block, diff_block); if (Quant_blk_P(diff_block, qcoeff_p, QP)) { cbp|=flag; DeQuant_blk_P(qcoeff_p, diff_block, QP); idct(diff_block, diff_block); recon_pic(recon_block, rec_width, pred_block, diff_block); } else { block_copy1(recon_block, pred_block, rec_width); } flag = flag >> 1; qcoeff_p+=64; } } findchromMV(encoder, MC, pix_x, pix_y, &dx, &dy, 0); //!< find MV for 2 chrom blocks //! Cb block curr_block = curr_mb.pCb; recon_block = recon_mb.pCb; pred_chrom(pix_x/2, pix_y/2, ref_img->pCb, lx_ref_c, dx, dy, pred_block); make_diff(curr_block, pic_width/2, pred_block, diff_block); fdct(diff_block, diff_block); if (Quant_blk_P(diff_block, qcoeff_p, QP)) { cbp|=flag; DeQuant_blk_P (qcoeff_p, diff_block, QP); idct(diff_block, diff_block); recon_pic(recon_block, rec_width/2, pred_block, diff_block); } else { block_copy1(recon_block, pred_block, rec_width/2); } flag = flag >> 1; qcoeff_p+=64; //! Cr block curr_block = curr_mb.pCr; recon_block = recon_mb.pCr; pred_chrom(pix_x/2, pix_y/2, ref_img->pCr, lx_ref_c, dx, dy, pred_block); make_diff(curr_block, pic_width/2, pred_block, diff_block); fdct(diff_block, diff_block); if (Quant_blk_P(diff_block, qcoeff_p, QP)) { cbp|=flag; DeQuant_blk_P (qcoeff_p, diff_block, QP); idct(diff_block, diff_block); recon_pic(recon_block, rec_width/2, pred_block, diff_block); } else { block_copy1(recon_block, pred_block, rec_width/2); } return cbp; } /*! ******************************************************************************* * * Name: MB_Encode_I * Description: Encode one Macroblock in I mode(dct, Q, IQ, Idct, data-recon) * Input: position of curr-MB, encoder structure * Output: qcoeff_p * Side effect: write reconstructive data to recon_pic in corresponding position * Last modified: 2002/12/5 by zj * *******************************************************************************/ int MB_Encode_I(H263VencStatus *encoder, int pix_x, int pix_y, short *qcoeff_i) { int i, j; int flag = 32; unsigned char *curr_block; unsigned char *recon_block; MB_structure curr_mb; MB_structure recon_mb; int cbp = 0; int pic_width = encoder->pels; int rec_width = encoder->mv_outside_frame? encoder->pels+32 : encoder->pels; int QI = encoder->total_Q; Image *curr_img = &(encoder->frameToEncode); Image *recon_img = &(encoder->frame_buf[encoder->zero_index]); short tmpblk[64]; if (encoder->PTYPE == B_IMG) { curr_img = &(encoder->BPicture[encoder->B_count]); recon_img = &(encoder->BPicture[0]); rec_width = encoder->pels; } //! Find MB in the image curr_mb.pLum = curr_img->pLum + pix_y * pic_width + pix_x; curr_mb.pCb = curr_img->pCb + pix_y * pic_width/4 + pix_x/2; curr_mb.pCr = curr_img->pCr + pix_y * pic_width/4 + pix_x/2; recon_mb.pLum = recon_img->pLum + pix_y * rec_width + pix_x; recon_mb.pCb = recon_img->pCb + pix_y * rec_width/4 + pix_x/2; recon_mb.pCr = recon_img->pCr + pix_y * rec_width/4 + pix_x/2; //! Encode each block in the MB //! 4 lum blocks for (i = 0; i < 16; i+=8) { for (j = 0; j < 16; j+=8) { curr_block = curr_mb.pLum + i*pic_width + j; recon_block = recon_mb.pLum + i*rec_width + j; block_copy2(tmpblk, curr_block, pic_width); // 2/11/2003 lcl fdct (tmpblk, tmpblk); // 2/11/2003 lcl if (Quant_blk_I (tmpblk, qcoeff_i, QI)) // 2/12/2003 lcl // if(rsden (curr_block, 0, pic_width, QI, INTRA, qcoeff_i)) { cbp|=flag; } DeQuant_blk_I (qcoeff_i, tmpblk, QI); // 2/12/2003 lcl idct (tmpblk, tmpblk); // 2/25/2003 lcl block_copy3(recon_block, tmpblk, rec_width); flag = flag >> 1; qcoeff_i+=64; } } //! Cb block curr_block = curr_mb.pCb; recon_block = recon_mb.pCb; block_copy2(tmpblk, curr_block, pic_width/2); fdct (tmpblk, tmpblk); // 2/12/2003 lcl if (Quant_blk_I (tmpblk, qcoeff_i, QI)) // 2/12/2003 lcl { cbp|=flag; } DeQuant_blk_I (qcoeff_i, tmpblk, QI); // 2/12/2003 lcl idct (tmpblk, tmpblk); // 2/26/2003 lcl block_copy3(recon_block, tmpblk, rec_width/2); flag = flag >> 1; qcoeff_i+=64; //! Cr block curr_block = curr_mb.pCr; recon_block = recon_mb.pCr; block_copy2(tmpblk, curr_block, pic_width/2); fdct (tmpblk, tmpblk); // 2/12/2003 lcl if (Quant_blk_I (tmpblk, qcoeff_i, QI)) // 2/12/2003 lcl { cbp|=flag; } DeQuant_blk_I (qcoeff_i, tmpblk, QI); // 2/12/2003 lcl idct (tmpblk, tmpblk); // 2/25/2003 lcl block_copy3(recon_block, tmpblk, rec_width/2); return cbp; } /*! ******************************************************************************* * * Name: MB_Encode_B * Description: Encode one Macroblock in for B frame(make diff,dct,Q,IQ,IDct,data-recon) * Input: position of curr-MB, encoder structure, MV * Output: qcoeff_p * Side effect: write reconstructive data to recon_pic in corresponding position * Return: cbp * Last modified: 2003/1/8 * *******************************************************************************/ int MB_Encode_B(H263VencStatus *encoder, int pix_x, int pix_y, MCParam *MC, short *qcoeff_p) { int i, j; int flag = 32; unsigned char *curr_block; unsigned char *recon_block; unsigned char pred_block[64]; short diff_block[64]; MB_structure curr_mb; MB_structure recon_mb; int trb; int trd; int dxf, dyf, dxb, dyb; MotionVector *MV; //!< pointer to MV of last P frame int mb_x = pix_x/16; int mb_y = pix_y/16; int pred_mode = MC->mv_frame[0][mb_y+1][mb_x+1]->Mode; int cbp = 0; int pic_width = encoder->pels; int rec_width = encoder->pels; int lx_ipol = encoder->mv_outside_frame ? pic_width*2+64 : pic_width*2; int lx_ref_c = encoder->mv_outside_frame ? pic_width/2+16 : pic_width/2; int QP = encoder->total_Q; unsigned char *prev_ipol = encoder->prev_ipol; unsigned char *next_ipol = encoder->next_ipol; Image *ref_img = &(encoder->frame_buf[encoder->ref_index]); Image *next_img = &(encoder->frame_buf[encoder->zero_index]); Image *curr_img = &(encoder->BPicture[encoder->B_count]); Image *recon_img = &(encoder->BPicture[0]); trb = encoder->TRB - encoder->TRP[encoder->ref_index]; if (trb < 0) { trb += 256; } trd = encoder->TRP[encoder->zero_index] - encoder->TRP[encoder->ref_index]; if (trd < 0) { trd += 256; } //! Find MB in the image curr_mb.pLum = curr_img->pLum + pix_y * pic_width + pix_x; curr_mb.pCb = curr_img->pCb + pix_y * pic_width/4 + pix_x/2; curr_mb.pCr = curr_img->pCr + pix_y * pic_width/4 + pix_x/2; recon_mb.pLum = recon_img->pLum + pix_y * rec_width + pix_x; recon_mb.pCb = recon_img->pCb + pix_y * rec_width/4 + pix_x/2; recon_mb.pCr = recon_img->pCr + pix_y * rec_width/4 + pix_x/2; /* direct mode */ if (B_DIRECT == pred_mode) { //! Encode each block in the MB //!4 lum blocks for (i = 0; i < 16; i+=8) { for (j = 0; j < 16; j+=8) { curr_block = curr_mb.pLum + i*pic_width + j; recon_block = recon_mb.pLum + i*rec_width + j; MV = MC->mv_lastframe[0][mb_y][mb_x]; if (MV->Mode == MODE_INTER4V || MV->Mode == MODE_INTER4V_Q) { MV = MC->mv_lastframe[(j>>3)+(i>>2)+1][mb_y][mb_x]; } dxf = (MV->x*2 + MV->x_half) * trb / trd; dyf = (MV->y*2 + MV->y_half) * trb / trd; dxb = (MV->x*2 + MV->x_half) * (trb-trd) / trd; dyb = (MV->y*2 + MV->y_half) * (trb-trd) / trd; pred_lum_bid(pix_x+j, pix_y+i, dxf, dyf, dxb, dyb, prev_ipol, next_ipol, lx_ipol, pred_block); make_diff(curr_block, pic_width, pred_block, diff_block); fdct(diff_block, diff_block); if (Quant_blk_P(diff_block, qcoeff_p, QP)) { cbp|=flag; DeQuant_blk_P(qcoeff_p, diff_block, QP); idct(diff_block, diff_block); recon_pic(recon_block, rec_width, pred_block, diff_block); } else { block_copy1(recon_block, pred_block, rec_width); } flag = flag >> 1; qcoeff_p+=64; } } /* find both forward MV and backward MV for chrom blocks in direct mode */ findchromMV_dir(encoder, MC, pix_x, pix_y, &dxf, &dyf, &dxb, &dyb); //! Cb block curr_block = curr_mb.pCb; recon_block = recon_mb.pCb; pred_chrom_bid(pix_x/2, pix_y/2, ref_img->pCb, next_img->pCb, lx_ref_c, dxf, dyf, dxb, dyb, pred_block); make_diff(curr_block, pic_width/2, pred_block, diff_block); fdct(diff_block, diff_block); if (Quant_blk_P(diff_block, qcoeff_p, QP)) { cbp|=flag; DeQuant_blk_P (qcoeff_p, diff_block, QP); idct(diff_block, diff_block); recon_pic(recon_block, rec_width/2, pred_block, diff_block); } else { block_copy1(recon_block, pred_block, rec_width/2); } flag = flag >> 1; qcoeff_p+=64; //! Cr block curr_block = curr_mb.pCr; recon_block = recon_mb.pCr; pred_chrom_bid(pix_x/2, pix_y/2, ref_img->pCr, next_img->pCr, lx_ref_c, dxf, dyf, dxb, dyb, pred_block); make_diff(curr_block, pic_width/2, pred_block, diff_block); fdct(diff_block, diff_block); if (Quant_blk_P(diff_block, qcoeff_p, QP)) { cbp|=flag; DeQuant_blk_P (qcoeff_p, diff_block, QP); idct(diff_block, diff_block); recon_pic(recon_block, rec_width/2, pred_block, diff_block); } else { block_copy1(recon_block, pred_block, rec_width/2); } } /* forward mode */ else if (B_FORWARD == pred_mode) { //! Encode each block in the MB //!4 lum blocks for (i = 0; i < 16; i+=8) { for (j = 0; j < 16; j+=8) { curr_block = curr_mb.pLum + i*pic_width + j; recon_block = recon_mb.pLum + i*rec_width + j; MV = MC->mv_frame[0][mb_y+1][mb_x+1]; pred_lum(pix_x+j, pix_y+i, MV, prev_ipol, lx_ipol, pred_block); make_diff(curr_block, pic_width, pred_block, diff_block); fdct( diff_block, diff_block); if (Quant_blk_P(diff_block, qcoeff_p, QP)) { cbp|=flag; DeQuant_blk_P(qcoeff_p, diff_block, QP); idct(diff_block, diff_block); recon_pic(recon_block, rec_width, pred_block, diff_block); } else { block_copy1(recon_block, pred_block, rec_width); } flag = flag >> 1; qcoeff_p+=64; } } /* only find forward MV for chrom blocks in forward mode */ findchromMV(encoder, MC, pix_x, pix_y, &dxf, &dyf, 0); //! Cb block curr_block = curr_mb.pCb; recon_block = recon_mb.pCb; pred_chrom(pix_x/2, pix_y/2, ref_img->pCb, lx_ref_c, dxf, dyf, pred_block); make_diff(curr_block, pic_width/2, pred_block, diff_block); fdct(diff_block, diff_block); if (Quant_blk_P(diff_block, qcoeff_p, QP)) { cbp|=flag; DeQuant_blk_P (qcoeff_p, diff_block, QP); idct(diff_block, diff_block); recon_pic(recon_block, rec_width/2, pred_block, diff_block); } else { block_copy1(recon_block, pred_block, rec_width/2); } flag = flag >> 1; qcoeff_p+=64; //! Cr block curr_block = curr_mb.pCr; recon_block = recon_mb.pCr; pred_chrom(pix_x/2, pix_y/2, ref_img->pCr, lx_ref_c, dxf, dyf, pred_block); make_diff(curr_block, pic_width/2, pred_block, diff_block); fdct(diff_block, diff_block); if (Quant_blk_P(diff_block, qcoeff_p, QP)) { cbp|=flag; DeQuant_blk_P (qcoeff_p, diff_block, QP); idct(diff_block, diff_block); recon_pic(recon_block, rec_width/2, pred_block, diff_block); } else { block_copy1(recon_block, pred_block, rec_width/2); } } /* backward mode */ else if (B_BACKWARD == pred_mode) { //! Encode each block in the MB //!4 lum blocks for (i = 0; i < 16; i+=8) { for (j = 0; j < 16; j+=8) { curr_block = curr_mb.pLum + i*pic_width + j; recon_block = recon_mb.pLum + i*rec_width + j; MV = MC->mv_frame[5][mb_y+1][mb_x+1]; pred_lum(pix_x+j, pix_y+i, MV, next_ipol, lx_ipol, pred_block); make_diff(curr_block, pic_width, pred_block, diff_block); fdct(diff_block, diff_block); if (Quant_blk_P(diff_block, qcoeff_p, QP)) { cbp|=flag; DeQuant_blk_P(qcoeff_p, diff_block, QP); idct(diff_block, diff_block); recon_pic(recon_block, rec_width, pred_block, diff_block); } else { block_copy1(recon_block, pred_block, rec_width); } flag = flag >> 1; qcoeff_p+=64; } } /* only find backward MV for chrom blocks in backward mode */ findchromMV(encoder, MC, pix_x, pix_y, &dxb, &dyb, 1); //! Cb block curr_block = curr_mb.pCb; recon_block = recon_mb.pCb; pred_chrom(pix_x/2, pix_y/2, next_img->pCb, lx_ref_c, dxb, dyb, pred_block); make_diff(curr_block, pic_width/2, pred_block, diff_block); fdct(diff_block, diff_block); if (Quant_blk_P(diff_block, qcoeff_p, QP)) { cbp|=flag; DeQuant_blk_P (qcoeff_p, diff_block, QP); idct(diff_block, diff_block); recon_pic(recon_block, rec_width/2, pred_block, diff_block); } else { block_copy1(recon_block, pred_block, rec_width/2); } flag = flag >> 1; qcoeff_p+=64; //! Cr block curr_block = curr_mb.pCr; recon_block = recon_mb.pCr; pred_chrom(pix_x/2, pix_y/2, next_img->pCr, lx_ref_c, dxb, dyb, pred_block); make_diff(curr_block, pic_width/2, pred_block, diff_block); fdct(diff_block, diff_block); if (Quant_blk_P(diff_block, qcoeff_p, QP)) { cbp|=flag; DeQuant_blk_P (qcoeff_p, diff_block, QP); idct(diff_block, diff_block); recon_pic(recon_block, rec_width/2, pred_block, diff_block); } else { block_copy1(recon_block, pred_block, rec_width/2); } } /* bi-direction mode */ else if (B_BIDIRECTIONAL == pred_mode) { //! Encode each block in the MB //!4 lum blocks for (i = 0; i < 16; i+=8) { for (j = 0; j < 16; j+=8) { curr_block = curr_mb.pLum + i*pic_width + j; recon_block = recon_mb.pLum + i*rec_width + j; dxf = MC->mv_frame[0][mb_y+1][mb_x+1]->x*2 + MC->mv_frame[0][mb_y+1][mb_x+1]->x_half; dyf = MC->mv_frame[0][mb_y+1][mb_x+1]->y*2 + MC->mv_frame[0][mb_y+1][mb_x+1]->y_half; dxb = MC->mv_frame[5][mb_y+1][mb_x+1]->x*2 + MC->mv_frame[5][mb_y+1][mb_x+1]->x_half; dyb = MC->mv_frame[5][mb_y+1][mb_x+1]->y*2 + MC->mv_frame[5][mb_y+1][mb_x+1]->y_half; pred_lum_bid(pix_x+j, pix_y+i, dxf, dyf, dxb, dyb, prev_ipol, next_ipol, lx_ipol, pred_block); make_diff(curr_block, pic_width, pred_block, diff_block); fdct(diff_block, diff_block); if (Quant_blk_P(diff_block, qcoeff_p, QP)) { cbp|=flag; DeQuant_blk_P(qcoeff_p, diff_block, QP); idct(diff_block, diff_block); recon_pic(recon_block, rec_width, pred_block, diff_block); } else { block_copy1(recon_block, pred_block, rec_width); } flag = flag >> 1; qcoeff_p+=64; } } /* find forward MV and backward MV for chrom blocks respectivly in bi-direction mode */ findchromMV(encoder, MC, pix_x, pix_y, &dxf, &dyf, 0); findchromMV(encoder, MC, pix_x, pix_y, &dxb, &dyb, 1); //! Cb block curr_block = curr_mb.pCb; recon_block = recon_mb.pCb; pred_chrom_bid(pix_x/2, pix_y/2, ref_img->pCb, next_img->pCb, lx_ref_c, dxf, dyf, dxb, dyb, pred_block); make_diff(curr_block, pic_width/2, pred_block, diff_block); fdct(diff_block, diff_block); if (Quant_blk_P(diff_block, qcoeff_p, QP)) { cbp|=flag; DeQuant_blk_P (qcoeff_p, diff_block, QP); idct(diff_block, diff_block); recon_pic(recon_block, rec_width/2, pred_block, diff_block); } else { block_copy1(recon_block, pred_block, rec_width/2); } flag = flag >> 1; qcoeff_p+=64; //! Cr block curr_block = curr_mb.pCr; recon_block = recon_mb.pCr; pred_chrom_bid(pix_x/2, pix_y/2, ref_img->pCr, next_img->pCr, lx_ref_c, dxf, dyf, dxb, dyb, pred_block); make_diff(curr_block, pic_width/2, pred_block, diff_block); fdct(diff_block, diff_block); if (Quant_blk_P(diff_block, qcoeff_p, QP)) { cbp|=flag; DeQuant_blk_P (qcoeff_p, diff_block, QP); idct(diff_block, diff_block); recon_pic(recon_block, rec_width/2, pred_block, diff_block); } else { block_copy1(recon_block, pred_block, rec_width/2); } } else { return -1; } return cbp; } /*! findbiSAD calculate the sum of the absolute difference between one MB and its bi-direction predicted value */ int findbiSAD(unsigned char *prev, unsigned char *next, unsigned char *curr, int lx_ipol, int lx_curr, int blocksize) { int i, j; unsigned char *p0 = curr; unsigned char *p1 = prev; unsigned char *p2 = next; int sad = 0; for (j = 0; j < blocksize; j++) { for (i = 0; i < blocksize; i++) { sad += absm(p0[i] - (p1[i<<1]+p2[i<<1])/2); } p0 += lx_curr; p1 += lx_ipol<<1; p2 += lx_ipol<<1; } return sad; } /*! ******************************************************************************* * * Name: findchromMV * Description: * Input: * Output: * Last modified: 2002/12/21 * *******************************************************************************/ void findchromMV(H263VencStatus *encoder, MCParam *MC, int x, int y, int *dx, int *dy, int BACKWARD) { int r = y/16+1; int c = x/16+1; int vec = BACKWARD ? 5 : 0; int roundtab[] = {0,0,0,1,1,1,1,1,1,1,1,1,1,1,2,2}; int sum; if (((MC->mv_frame[0][r][c]->Mode == MODE_INTER4V)||(MC->mv_frame[0][r][c]->Mode == MODE_INTER4V_Q)) && encoder->use4mv && (encoder->PTYPE != B_IMG)) { sum = MC->mv_frame[1][r][c]->x*2+MC->mv_frame[1][r][c]->x_half+ MC->mv_frame[2][r][c]->x*2+MC->mv_frame[2][r][c]->x_half+ MC->mv_frame[3][r][c]->x*2+MC->mv_frame[3][r][c]->x_half+ MC->mv_frame[4][r][c]->x*2+MC->mv_frame[4][r][c]->x_half; *dx = sign(sum)*(roundtab[absm(sum)%16] + (absm(sum)/16)*2); sum = MC->mv_frame[1][r][c]->y*2+MC->mv_frame[1][r][c]->y_half+ MC->mv_frame[2][r][c]->y*2+MC->mv_frame[2][r][c]->y_half+ MC->mv_frame[3][r][c]->y*2+MC->mv_frame[3][r][c]->y_half+ MC->mv_frame[4][r][c]->y*2+MC->mv_frame[4][r][c]->y_half; *dy = sign(sum)*(roundtab[absm(sum)%16] + (absm(sum)/16)*2); } else { *dx = 2*MC->mv_frame[vec][r][c]->x + MC->mv_frame[vec][r][c]->x_half; *dy = 2*MC->mv_frame[vec][r][c]->y + MC->mv_frame[vec][r][c]->y_half; *dx = ( *dx % 4 == 0 ? *dx >> 1 : (*dx>>1)|1 ); *dy = ( *dy % 4 == 0 ? *dy >> 1 : (*dy>>1)|1 ); } } /*! ******************************************************************************* * * Name: findchromMV_dir * Description: * Input: * Output: * Last modified: 2003/1/9 * *******************************************************************************/ void findchromMV_dir(H263VencStatus *encoder, MCParam *MC, int x, int y, int *dx1, int *dy1, int *dx2, int *dy2) { int r = y/16; int c = x/16; int trb; int trd; int dxf, dyf, dxb, dyb; int roundtab[] = {0,0,0,1,1,1,1,1,1,1,1,1,1,1,2,2}; int sum1, sum2, sum3, sum4; int i; trb = encoder->TRB - encoder->TRP[encoder->ref_index]; if (trb < 0) { trb += 256; } trd = encoder->TRP[encoder->zero_index] - encoder->TRP[encoder->ref_index]; if (trd < 0) { trd += 256; } if (((MC->mv_lastframe[0][r][c]->Mode == MODE_INTER4V)||(MC->mv_lastframe[0][r][c]->Mode == MODE_INTER4V_Q)) && encoder->use4mv ) { sum1 = sum2 = sum3 = sum4 = 0; for (i = 1; i < 5; i++) { dxf = (MC->mv_lastframe[i][r][c]->x*2 + MC->mv_lastframe[i][r][c]->x_half) * trb / trd; dyf = (MC->mv_lastframe[i][r][c]->y*2 + MC->mv_lastframe[i][r][c]->y_half) * trb / trd; dxb = (MC->mv_lastframe[i][r][c]->x*2 + MC->mv_lastframe[i][r][c]->x_half) * (trb - trd) / trd; dyb = (MC->mv_lastframe[i][r][c]->y*2 + MC->mv_lastframe[i][r][c]->y_half) * (trb - trd) / trd; sum1 += dxf; sum2 += dyf; sum3 += dxb; sum4 += dyb; } *dx1 = sign(sum1)*(roundtab[absm(sum1)%16] + (absm(sum1)/16)*2); *dy1 = sign(sum2)*(roundtab[absm(sum2)%16] + (absm(sum2)/16)*2); *dx2 = sign(sum3)*(roundtab[absm(sum3)%16] + (absm(sum3)/16)*2); *dy2 = sign(sum4)*(roundtab[absm(sum4)%16] + (absm(sum4)/16)*2); } else { dxf = (MC->mv_lastframe[0][r][c]->x*2 + MC->mv_lastframe[0][r][c]->x_half) * trb / trd; dyf = (MC->mv_lastframe[0][r][c]->y*2 + MC->mv_lastframe[0][r][c]->y_half) * trb / trd; dxb = (MC->mv_lastframe[0][r][c]->x*2 + MC->mv_lastframe[0][r][c]->x_half) * (trb - trd) / trd; dyb = (MC->mv_lastframe[0][r][c]->y*2 + MC->mv_lastframe[0][r][c]->y_half) * (trb - trd) / trd; *dx1 = (dxf % 4 == 0 ? dxf >> 1 : (dxf>>1)|1); *dy1 = (dyf % 4 == 0 ? dyf >> 1 : (dyf>>1)|1); *dx2 = (dxb % 4 == 0 ? dxb >> 1 : (dxb>>1)|1); *dy2 = (dyb % 4 == 0 ? dyb >> 1 : (dyb>>1)|1); } } #ifdef __cplusplus } #endif