www.pudn.com > henclib263.rar > mot_est.cxx
/* * mot_est.cxx * * implementation for functions which is used for motion estimation. * * 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/mot_est.h" #ifdef __cplusplus extern "C" { #endif #define MAX_SAD 99999 //!< MAX_SAD #define PREF_NULL_VEC 100 //!< according to tmn #define PREF_16_VEC 200 //!< according to tmn //#define PRINTMV extern int SpiralX[6561]; extern int SpiralY[6561]; //!MVFAST STRUCTURE typedef struct { int x; int y; int iStartNmbr; } DPOINT; //!MVFAST STRUCTURE typedef struct { int no_check_pts; DPOINT dpoint[8]; } DIAMOND; //!MVFAST DATA USED static DIAMOND diamond[3]={ {4,{{0,1,3},{1,0,0},{0,-1,1},{-1,0,2}}}, {8,{{0,2,6},{1,1,0},{2,0,0},{1,-1,2},{0,-2,2},{-1,-1,4},{-2,0,4},{-1,1,6}}}, {3,{{0,0,0},{0,0,0,},{0,0,0}}} }; //!MVFAST STRUCTURE enum {SDiamond, LDiamond, MotAdaptPat} dType; /*! ******************************************************************************* * * Name: interpolate_lum * Description: make interpolated lum image for 1/2 pel mv search * Input: * Output: * Side effect: fill the buffer for interpolated image(encoder->prev_ipol) * Optimization: NO * Last modified: 2002/11/21 * *******************************************************************************/ void interpolate_lum(H263VencStatus *encoder) { int width = encoder->mv_outside_frame ? encoder->pels+32 : encoder->pels; int height = encoder->mv_outside_frame ? encoder->lines+32: encoder->lines; unsigned char *oo = encoder->mv_outside_frame ? (encoder->frame_buf[encoder->ref_index]).pLum-width*16-16 : (encoder->frame_buf[encoder->ref_index]).pLum; unsigned char *ii = encoder->mv_outside_frame ? encoder->prev_ipol-width*64-32 : encoder->prev_ipol; int i, j; if (encoder->PTYPE == INTER) { /* for forward mv search */ oo = encoder->mv_outside_frame ? (encoder->frame_buf[encoder->ref_index]).pLum-width*16-16 : (encoder->frame_buf[encoder->ref_index]).pLum; ii = encoder->mv_outside_frame ? encoder->prev_ipol-width*64-32 : encoder->prev_ipol; } else if (encoder->PTYPE == B_IMG) { /* for backward mv search */ // it is always permitted that MVs be across the picture boundary oo = encoder->frame_buf[encoder->zero_index].pLum - width*16 - 16; ii = encoder->next_ipol - width*64 - 32; } else { printf("error in interplating picture"); exit(-1); } /* 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); } /*! ******************************************************************************* * * Name: grabVec * Description: refine best motion vectors and choose best mode for all mbs * of one picture * Input: the pointer of encoder strcture and MC structure * Output: MV(in MC structure) * Last modified: 2002/11/21 * *******************************************************************************/ void grabVec(H263VencStatus *encoder, MCParam *MC, int BACKWARD) { int i, j; int pix_x, pix_y; int pix_x_8, pix_y_8; int block; int x_center, y_center; int sad_gate = 512; void (*mv_search) (H263VencStatus*, MCParam*, int, int, int, int); //!< search functions // added by lcl on 2003/2/26, parameter for calculation of SAD int lx1 = encoder->pels; int lx2 = encoder->mv_outside_frame ? encoder->pels+32 : encoder->pels; unsigned char *p1 = (encoder->frameToEncode).pLum ; if (encoder->PTYPE == B_IMG) { p1 = (encoder->BPicture[encoder->B_count]).pLum; } //! choose search method if (0 == MC->method) { mv_search = mv_search_fs; } else if(1 == MC->method) { mv_search = mv_search_dmd; } else { printf("Invalid MV search method"); exit(-1); } /*! main loop */ for (pix_y = 0, i = 0; pix_y < encoder->lines; pix_y+=16, i++) { for (pix_x = 0, j = 0; pix_x < encoder->pels; pix_x+=16, j++) { if (!BACKWARD) { /* Forward MV search(for both P frames and B frames). */ MC->mv = MC->mv_frame[0][i+1][j+1]; //!< assign a pointer for current mv //! check zero point ahead of searching (MC->mv)->x = 0; (MC->mv)->y = 0; (MC->mv)->min_sad = me_sad_a(lx1, lx2, pix_x, pix_y, pix_x, pix_y, p1, encoder->frame_buf[encoder->ref_index].pLum, MAX_SAD, 16) - PREF_NULL_VEC; // (MC->mv)->min_sad = me_sad_a(encoder, pix_x, pix_y, pix_x, pix_y, MAX_SAD, 16, 0) - PREF_NULL_VEC; if ((MC->mv)->min_sad > sad_gate) { mv_search(encoder, MC, pix_x, pix_y, 16, BACKWARD); //!< search integer mv (predictor of mv not used) } findhalfpel(encoder, MC, pix_x, pix_y, 16, BACKWARD); //! 8x8 block Search(only for P frames). if (encoder->use4mv && (encoder->PTYPE!=B_IMG)) { for (block = 0; block < 4; block++) { pix_x_8 = pix_x+((block&1)<<3); pix_y_8 = pix_y+((block&2)<<2); MC->mv = MC->mv_frame[block+1][i+1][j+1]; //!< assign a pointer // decide searching center x_center = MC->mv_frame[0][i+1][j+1]->x; y_center = MC->mv_frame[0][i+1][j+1]->y; if (x_center > 15 - MC->search_range_8x8) { x_center = 15 - MC->search_range_8x8; } if (y_center > 15 - MC->search_range_8x8) { y_center = 15 - MC->search_range_8x8; } if (x_center < -15 + MC->search_range_8x8) { x_center = -15 + MC->search_range_8x8; } if (y_center < -15 + MC->search_range_8x8) { y_center = -15 + MC->search_range_8x8; } // do pre-search check (MC->mv)->x = x_center; (MC->mv)->y = y_center; (MC->mv)->min_sad = me_sad_a(lx1, lx2, pix_x_8, pix_y_8, pix_x_8+x_center, pix_y_8+y_center, p1, encoder->frame_buf[encoder->ref_index].pLum, MAX_SAD, 8); // (MC->mv)->min_sad = me_sad_a(encoder, pix_x_8, pix_y_8, pix_x_8+x_center, pix_y_8+y_center, MAX_SAD, 8, 0); if((MC->mv)->min_sad > sad_gate/4) { mv_search(encoder, MC, pix_x_8, pix_y_8, 8, BACKWARD); } findhalfpel(encoder, MC, pix_x_8, pix_y_8, 8, BACKWARD); } } } else { /*! Backward MV Search(only for B frames). */ if (encoder->PTYPE == B_IMG) { MC->mv = MC->mv_frame[5][i+1][j+1]; //!< assign a pointer // check zero point ahead of searching (MC->mv)->x = 0; (MC->mv)->y = 0; (MC->mv)->min_sad = me_sad_a(lx1, lx2, pix_x, pix_y, pix_x, pix_y, p1, encoder->frame_buf[encoder->zero_index].pLum, MAX_SAD, 16) - PREF_NULL_VEC; // (MC->mv)->min_sad = me_sad_a(encoder, pix_x, pix_y, pix_x, pix_y, MAX_SAD, 16, 1) - PREF_NULL_VEC; if ((MC->mv)->min_sad > sad_gate) { mv_search(encoder, MC, pix_x, pix_y, 16, BACKWARD); //!< search integer mv (predictor of mv not used) } findhalfpel(encoder, MC, pix_x, pix_y, 16, BACKWARD); } } /* Choose mode(only for P frames, prediction mode of B frames will be decided outside). */ if (encoder->PTYPE != B_IMG) { choose_mode(encoder, MC, pix_x, pix_y); } #ifdef PRINTMV printmv(encoder, MC, i, j, BACKWARD); #endif } #ifdef PRINTMV printf("\n"); #endif } } /*! ******************************************************************************* * * Name: mv_search_fs * Description: find best integer motion vector for a block(Full Search) * Input: position of current block * current lum image and reference lum image * Output: integer MV value * Last modified: 2002/12/17 by lcl * *******************************************************************************/ void mv_search_fs(H263VencStatus *encoder, MCParam *MC, int curr_x, int curr_y, int blocksize, int BACKWARD) { int iMinSAD = (MC->mv)->min_sad; int iCurrSAD; int i; int iXCheckPt; int iYCheckPt; int iCenterX = curr_x + (MC->mv)->x; int iCenterY = curr_y + (MC->mv)->y; int iXDest = iCenterX; int iYDest = iCenterY; int search_range = (8 == blocksize ? MC->search_range_8x8 : MC->search_range); int iNbr = (2*search_range + 1) * (2*search_range + 1); int mv_out; // added by lcl on 2003/2/22, parameter for calculation of SAD int lx1 = encoder->pels; int lx2 = encoder->mv_outside_frame ? encoder->pels+32 : encoder->pels; int index = BACKWARD ? encoder->zero_index : encoder->ref_index; unsigned char *p1 = (encoder->frameToEncode).pLum ; unsigned char *p2 = (encoder->frame_buf[index]).pLum ; if (encoder->PTYPE == B_IMG) { mv_out = 1; p1 = (encoder->BPicture[encoder->B_count]).pLum; } else { mv_out = encoder->annex.Advanced_Prediction || encoder->annex.Deblocking_Filter; } for (i = 1; i < iNbr; i++) { iXCheckPt = iCenterX + SpiralX[i]; iYCheckPt = iCenterY + SpiralY[i]; if ( (iXCheckPt<0||iYCheckPt<0|| iXCheckPt>encoder->pels - blocksize || iYCheckPt>encoder->lines - blocksize) && !mv_out) continue; //iCurrSAD = me_sad_a(encoder, curr_x, curr_y, iXCheckPt, iYCheckPt, iMinSAD, blocksize, BACKWARD); iCurrSAD = me_sad_a(lx1, lx2, curr_x, curr_y, iXCheckPt, iYCheckPt, p1, p2, iMinSAD, blocksize); if (iCurrSAD >= iMinSAD) continue; iMinSAD= iCurrSAD; iXDest = iXCheckPt; iYDest = iYCheckPt; } (MC->mv)->x = iXDest-curr_x; (MC->mv)->y = iYDest-curr_y; (MC->mv)->min_sad = iMinSAD; } /*! ******************************************************************************* * * Name: mv_search_dmd * Description: find best integer motion vector for a block(Noval Diomand Search) * Input: position of current block * current lum image and reference lum image * Output: integer MV value * Last modified: 2002/12/17 by lcl * *******************************************************************************/ void mv_search_dmd(H263VencStatus *encoder, MCParam *MC, int curr_x, int curr_y, int blocksize, int BACKWARD) { int iMinSAD=(MC->mv)->min_sad; int mbDiff; int iTotalCheckPts, iCheckPts, iMotDirn=0, iPtNmbr=0; int MOTION_ACTIVITY; int stopFlag=0, stopDiamondMotion=0; int dXCentre=curr_x + (MC->mv)->x; int dYCentre=curr_y + (MC->mv)->y; int iXDest=dXCentre; int iYDest=dYCentre; int iXCheckPt, iYCheckPt; int dType; int L1=1, L2=2, L3=4; int LMotion = 0; int block = 0; int mb_x = curr_x/16; int mb_y = curr_y/16; int vec_x; int vec_y; int search_range = (8 == blocksize) ? MC->search_range_8x8 : MC->search_range; int mv_out; // added by lcl on 2003/2/22, parameter for calculation of SAD int lx1 = encoder->pels; int lx2 = encoder->mv_outside_frame ? encoder->pels+32 : encoder->pels; int index = BACKWARD ? encoder->zero_index : encoder->ref_index; unsigned char *p1 = (encoder->frameToEncode).pLum ; unsigned char *p2 = (encoder->frame_buf[index]).pLum ; if (encoder->PTYPE == B_IMG) { mv_out = 1; p1 = (encoder->BPicture[encoder->B_count]).pLum; } else { mv_out = encoder->annex.Advanced_Prediction || encoder->annex.Deblocking_Filter; } //! assign neighborhood MVs as points of diamond[2], which is MotAdaptPat FindNbrMV(MC->mv_frame, block, 0, mb_x, mb_y, &vec_x, &vec_y, BACKWARD); //!< left diamond[2].dpoint[0].x = vec_x - (MC->mv)->x; diamond[2].dpoint[0].y = vec_y - (MC->mv)->y; FindNbrMV(MC->mv_frame, block, 1, mb_x, mb_y, &vec_x, &vec_y, BACKWARD); //!< up diamond[2].dpoint[1].x = vec_x - (MC->mv)->x; diamond[2].dpoint[1].y = vec_y - (MC->mv)->y; FindNbrMV(MC->mv_frame, block, 2, mb_x, mb_y, &vec_x, &vec_y, BACKWARD); //!< up-right diamond[2].dpoint[2].x = vec_x - (MC->mv)->x; diamond[2].dpoint[2].y = vec_y - (MC->mv)->y; //! compute motion activity MOTION_ACTIVITY = max(abs(diamond[2].dpoint[0].x)+abs(diamond[2].dpoint[0].y) , max( abs(diamond[2].dpoint[1].x)+abs(diamond[2].dpoint[1].y) , abs(diamond[2].dpoint[2].x)+abs(diamond[2].dpoint[2].y)) ); if (MOTION_ACTIVITY > L3) LMotion = 1; //!> detect large motion dType=(MOTION_ACTIVITY > L2) ? MotAdaptPat : ((MOTION_ACTIVITY > L1) ? LDiamond : SDiamond); iTotalCheckPts=diamond[dType].no_check_pts; while(stopFlag!=1) { iCheckPts=iTotalCheckPts; do { iXCheckPt=diamond[dType].dpoint[iPtNmbr].x+dXCentre; iYCheckPt=diamond[dType].dpoint[iPtNmbr].y+dYCentre; if ( (iXCheckPt < 0||iYCheckPt < 0|| iXCheckPt > (encoder->pels - blocksize)|| iYCheckPt > (encoder->lines - blocksize)) && !mv_out) goto NEXT_POSITION; if ( (iXCheckPt-curr_x) < -search_range|| (iXCheckPt-curr_x) > search_range|| (iYCheckPt-curr_y) < -search_range|| (iYCheckPt-curr_y) > search_range) goto NEXT_POSITION; //!< skip this check point else { mbDiff = me_sad_a(lx1, lx2, curr_x, curr_y, iXCheckPt, iYCheckPt, p1, p2, iMinSAD, blocksize); if (mbDiff < iMinSAD) { iMinSAD= mbDiff; iXDest = iXCheckPt; iYDest = iYCheckPt; iMotDirn=iPtNmbr; } } NEXT_POSITION: iPtNmbr+=1; iPtNmbr=(dType==LDiamond) ? iPtNmbr % diamond[LDiamond].no_check_pts : iPtNmbr % diamond[SDiamond].no_check_pts; iCheckPts-=1; }while(iCheckPts>0); if(dType==MotAdaptPat) { dType = LMotion?LDiamond:SDiamond; //!> if large motion, Large Diamond used iPtNmbr=0; iTotalCheckPts=diamond[dType].no_check_pts; } else { if((iXDest==dXCentre)&&(iYDest==dYCentre)) stopDiamondMotion=1; else { iTotalCheckPts=(((iXDest==dXCentre) || (iYDest==dYCentre))&&(dType==LDiamond)) ? 5 :3; iPtNmbr=diamond[dType].dpoint[iMotDirn].iStartNmbr; } } if(stopDiamondMotion) { if(dType==LDiamond) { dType = SDiamond; iPtNmbr = 0; iTotalCheckPts = diamond[dType].no_check_pts; } else stopFlag=1; } dXCentre=iXDest; dYCentre=iYDest; } (MC->mv)->x = iXDest - curr_x; (MC->mv)->y = iYDest - curr_y; (MC->mv)->min_sad = iMinSAD; } /*! ******************************************************************************* * * Name: findhalfpel * Description: find best motion vectors in half resolution * Input: position of current block * current lum image and interpolated reference lum image * Output: half MV value * Last modified: 2002/11/23 by lcl * *******************************************************************************/ void findhalfpel(H263VencStatus *encoder, MCParam *MC, int x, int y, int blocksize, int BACKWARD) { int iXPos[9] = {0, -1, 0, 1, -1, 1, -1, 0, 1}; int iYPos[9] = {0, -1, -1, -1, 0, 0, 1, 1, 1}; int iMinSAD, iCurrSAD; int iCenterX; int iCenterY; int iCheckPtX; int iCheckPtY; int iPoint, iBestPt; int mv_out; // added by lcl on 2003/2/22, parameter for calculation of SAD int lx1 = encoder->pels; int lx2 = encoder->mv_outside_frame ? encoder->pels*2+64 : encoder->pels*2; unsigned char *ipol = BACKWARD ? encoder->next_ipol : encoder->prev_ipol; unsigned char *p1 = (encoder->frameToEncode).pLum; unsigned char *p2 = ipol; if (encoder->PTYPE == B_IMG) { mv_out = 1; p1 = (encoder->BPicture[encoder->B_count]).pLum; } else { mv_out = encoder->annex.Advanced_Prediction || encoder->annex.Deblocking_Filter; } iBestPt = 0; iMinSAD = (MC->mv)->min_sad; iCenterX = (x + (MC->mv)->x)<<1; iCenterY = (y + (MC->mv)->y)<<1; for (iPoint = 1; iPoint < 9; iPoint++) { iCheckPtX = iCenterX + iXPos[iPoint]; //!< Current absolute X position in the reference pic iCheckPtY = iCenterY + iYPos[iPoint]; //!< Current absolute Y position in the reference pic if ( (iCheckPtX<0 || iCheckPtY<0 || iCheckPtX>(encoder->pels - blocksize)*2 || //!< keep in agreement with h.263 coder iCheckPtY>(encoder->lines - blocksize)*2) //!< should be considered later && !mv_out) continue; iCurrSAD = me_sad_b(lx1, lx2, x, y, iCheckPtX, iCheckPtY, p1, p2, iMinSAD, blocksize); if (iCurrSAD >= iMinSAD) continue; iMinSAD = iCurrSAD; iBestPt = iPoint; } (MC->mv)->x_half = iXPos[iBestPt]; (MC->mv)->y_half = iYPos[iBestPt]; (MC->mv)->min_sad = iMinSAD; } /*! ******************************************************************************* * * Name: zeroVec * Description: * Input: * Output: * Last modified: 2002/11/23 by lcl * *******************************************************************************/ void zeroVec(MotionVector *MV) { MV->x = 0; MV->y = 0; MV->x_half = 0; MV->y_half = 0; } /*! ******************************************************************************* * * Name: me_sad_a16 * Description: compute sad for integer pel motion search * Input: current lum image and reference lum image * position of current block in current image * position of reference block in reference image * Output: sad returned * Optimization: sadmmx.cpp * Last modified: 2003/02/20 by lcl * *******************************************************************************/ int me_sad_a(int lx1, int lx2, int x1, int y1, int x2, int y2, unsigned char *P1, unsigned char *P2, int sad_last, int blocksize) { int i, j; int sad = 0; unsigned char *p1 = P1 + y1*lx1 + x1; unsigned char *p2 = P2 + y2*lx2 +x2 ; for(i = 0; i < blocksize; i++) { for(j = 0; j < blocksize; j+=4) { sad+=absm(p1[j] - p2[j]); sad+=absm(p1[j+1] - p2[j+1]); sad+=absm(p1[j+2] - p2[j+2]); sad+=absm(p1[j+3] - p2[j+3]); if (sad > sad_last) return MAX_SAD; } p1+=lx1; p2+=lx2; } return sad; } /*! ******************************************************************************* * * Name: me_sad_b * Description: compute sad for half pel motion search * Input: current lum image, interpolated image derived from reference frame * position of current block in current lum image, * position of reference block in interpolated reference image * Output: sad returned * Optimization: sadmmx.cpp * Last modified: 2002/12/17 by lcl * *******************************************************************************/ int me_sad_b(int lx1, int lx2, int x1, int y1, int x2, int y2, unsigned char *P1, unsigned char *P2, int sad_last, int blocksize) { int i, j, k; int sad = 0; unsigned char *p1 = P1 + y1*lx1 + x1; unsigned char *p2 = P2 + y2*lx2 + x2 ; for(i = 0; i < blocksize; i++) { for(j = 0, k = 0; j < blocksize; j+=4, k+=8) { sad+=absm(p1[j] - p2[k]); sad+=absm(p1[j+1] - p2[k+2]); sad+=absm(p1[j+2] - p2[k+4]); sad+=absm(p1[j+3] - p2[k+6]); if (sad > sad_last) return MAX_SAD; } p1+=lx1; p2+=lx2*2; } return sad; } /*! ******************************************************************************* * * Name: Choose_mode * Description: Choose INTRA or INTER * Input: Position of current MB, sad value derived from motion estimation * Output: * Side effect: If the mode is INTRA, set current mv zero * Author: Modified from tmn1.7 by lcl * Last modified: 2002/11/23 by lcl * *******************************************************************************/ void choose_mode(H263VencStatus *encoder, MCParam *MC, int x_pos, int y_pos) { int i,j; int MB_mean = 0, A = 0; int y_off; unsigned char *curr = encoder->frameToEncode.pLum; int mb_size = 16; int lines = y_pos/mb_size; int pels = x_pos/mb_size; int sad16, sad8; int min_sad; sad16 = MC->mv_frame[0][lines+1][pels+1]->min_sad; sad8 = !encoder->use4mv ? MAX_SAD : MC->mv_frame[1][lines+1][pels+1]->min_sad+ MC->mv_frame[2][lines+1][pels+1]->min_sad+ MC->mv_frame[3][lines+1][pels+1]->min_sad+ MC->mv_frame[4][lines+1][pels+1]->min_sad+ PREF_16_VEC; if (sad8 < sad16) { MC->mv_frame[0][lines+1][pels+1]->Mode = MODE_INTER4V; } else { MC->mv_frame[0][lines+1][pels+1]->Mode = MODE_INTER; } min_sad = sad8 < sad16 ? sad8 : sad16; for (j = 0; j < mb_size; j++) { y_off = (y_pos + j) * encoder->pels; for (i = 0; i < mb_size; i++) { MB_mean += *(curr + x_pos + i + y_off); } } MB_mean /= (mb_size * mb_size); for (j = 0; j < mb_size; j++) { y_off = (y_pos + j) * encoder->pels; for (i = 0; i < mb_size; i++) { A += abs( *(curr + x_pos + i + y_off) - MB_mean ); } } if (A < (min_sad - 500)) { zeroVec(MC->mv_frame[0][lines+1][pels+1]); (MC->mv_frame[0][lines+1][pels+1])->Mode = MODE_INTRA; } } /*! ******************************************************************************* * * Name: * Description: * Input: * Output: * Last modified: * *******************************************************************************/ int ZeroVector(MotionVector *mv) { if(0 == mv->x && 0 == mv->y && 0 == mv->x_half && 0 == mv->y_half) { return 1; } else { return 0; } } /*! ******************************************************************************* * * Name: * Description: * Input: * Output: * Last modified: * *******************************************************************************/ void FindNbrMV(MotionVector *MV[6][MBR+1][MBC+2], int block, int index, int mb_x, int mb_y, int *vec_x, int *vec_y, int BACKWARD) { int p[3]; int xin1, xin2, xin3; int yin1, yin2, yin3; int vec1, vec2, vec3; int l8, o8, or8; if (!BACKWARD) { l8 = o8 = or8 = 0; if (MV[0][mb_y+1][mb_x]->Mode == MODE_INTER4V) { l8 = 1; } if (MV[0][mb_y][mb_x+1]->Mode == MODE_INTER4V) { o8 = 1; } if (MV[0][mb_y][mb_x+2]->Mode == MODE_INTER4V) { or8 = 1; } switch (block) { case 0: vec1 = (l8 ? 2 : 0) ; yin1 = mb_y ; xin1 = mb_x-1; vec2 = (o8 ? 3 : 0) ; yin2 = mb_y-1; xin2 = mb_x; vec3 = (or8? 3 : 0) ; yin3 = mb_y-1; xin3 = mb_x+1; break; case 1: vec1 = (l8 ? 2 : 0) ; yin1 = mb_y ; xin1 = mb_x-1; vec2 = (o8 ? 3 : 0) ; yin2 = mb_y-1; xin2 = mb_x; vec3 = (or8? 3 : 0) ; yin3 = mb_y-1; xin3 = mb_x+1; break; case 2: vec1 = 1 ; yin1 = mb_y ; xin1 = mb_x; vec2 = (o8 ? 4 : 0) ; yin2 = mb_y-1; xin2 = mb_x; vec3 = (or8? 3 : 0) ; yin3 = mb_y-1; xin3 = mb_x+1; break; case 3: vec1 = (l8 ? 4 : 0) ; yin1 = mb_y ; xin1 = mb_x-1; vec2 = 1 ; yin2 = mb_y ; xin2 = mb_x; vec3 = 2 ; yin3 = mb_y ; xin3 = mb_x; break; case 4: vec1 = 3 ; yin1 = mb_y ; xin1 = mb_x; vec2 = 1 ; yin2 = mb_y ; xin2 = mb_x; vec3 = 2 ; yin3 = mb_y ; xin3 = mb_x; break; } } else { vec1 = vec2 = vec3 = 5; yin1 = mb_y ; xin1 = mb_x-1; yin2 = mb_y-1; xin2 = mb_x; yin3 = mb_y-1; xin3 = mb_x+1; } p[0] = MV[vec1][yin1+1][xin1+1]->x; p[1] = mb_y > 0 ? MV[vec2][yin2+1][xin2+1]->x : 0; p[2] = mb_y > 0 ? MV[vec3][yin3+1][xin3+1]->x : 0; *vec_x = p[index]; p[0] = MV[vec1][yin1+1][xin1+1]->y; p[1] = mb_y > 0 ? MV[vec2][yin2+1][xin2+1]->y : 0; p[2] = mb_y > 0 ? MV[vec3][yin3+1][xin3+1]->y : 0; *vec_y = p[index]; } /*! ******************************************************************************* * * Name: * Description: * Input: * Output: * Last modified: * *******************************************************************************/ void printmv(H263VencStatus *encoder, MCParam *MC, int r, int c, int BACKWARD) { if (!BACKWARD) { printf("(%d, %d)", MC->mv_frame[0][r+1][c+1]->x, MC->mv_frame[0][r+1][c+1]->y); printf("(%d, %d)", MC->mv_frame[0][r+1][c+1]->x_half, MC->mv_frame[0][r+1][c+1]->y_half); printf("%d", MC->mv_frame[0][r+1][c+1]->min_sad); if(encoder->use4mv) { printf("-"); printf("(%d, %d)", MC->mv_frame[1][r+1][c+1]->x, MC->mv_frame[1][r+1][c+1]->y); printf("(%d, %d)", MC->mv_frame[1][r+1][c+1]->x_half, MC->mv_frame[1][r+1][c+1]->y_half); printf("&"); printf("(%d, %d)", MC->mv_frame[2][r+1][c+1]->x, MC->mv_frame[2][r+1][c+1]->y); printf("(%d, %d)", MC->mv_frame[2][r+1][c+1]->x_half, MC->mv_frame[2][r+1][c+1]->y_half); printf("&"); printf("(%d, %d)", MC->mv_frame[3][r+1][c+1]->x, MC->mv_frame[3][r+1][c+1]->y); printf("(%d, %d)", MC->mv_frame[3][r+1][c+1]->x_half, MC->mv_frame[3][r+1][c+1]->y_half); printf("&"); printf("(%d, %d)", MC->mv_frame[4][r+1][c+1]->x, MC->mv_frame[4][r+1][c+1]->y); printf("(%d, %d)", MC->mv_frame[4][r+1][c+1]->x_half, MC->mv_frame[4][r+1][c+1]->y_half); printf("%d", MC->mv_frame[1][r+1][c+1]->min_sad+MC->mv_frame[2][r+1][c+1]->min_sad+ MC->mv_frame[3][r+1][c+1]->min_sad+MC->mv_frame[4][r+1][c+1]->min_sad); } printf("\n"); } else { printf("Backward MV: "); printf("(%d, %d)", MC->mv_frame[5][r+1][c+1]->x, MC->mv_frame[5][r+1][c+1]->y); printf("(%d, %d)", MC->mv_frame[5][r+1][c+1]->x_half, MC->mv_frame[5][r+1][c+1]->y_half); printf("%d", MC->mv_frame[5][r+1][c+1]->min_sad); printf("\n"); } } /*! ******************************************************************************* * * Name: saveVec * Description: Save vectors for B frames to compute MVs in direct mode * Input: * Output: * Last modified: 2003/1/8 * *******************************************************************************/ void saveVec(MCParam *MC, int lines, int pels) { int i, j, k; for (i = 0; i < lines; i++) { for (j = 0; j < pels; j++) { if (MC->mv_frame[0][i+1][j+1]->Mode == MODE_INTER4V) { MC->mv_lastframe[0][i][j]->Mode = MC->mv_frame[0][i+1][j+1]->Mode; for (k = 0; k < 5; k++) { MC->mv_lastframe[k][i][j]->x = MC->mv_frame[k][i+1][j+1]->x; MC->mv_lastframe[k][i][j]->y = MC->mv_frame[k][i+1][j+1]->y; MC->mv_lastframe[k][i][j]->x_half = MC->mv_frame[k][i+1][j+1]->x_half; MC->mv_lastframe[k][i][j]->y_half = MC->mv_frame[k][i+1][j+1]->y_half; MC->mv_lastframe[k][i][j]->Mode = MC->mv_frame[k][i+1][j+1]->Mode; MC->mv_lastframe[k][i][j]->min_sad = MC->mv_frame[k][i+1][j+1]->min_sad; } } else { MC->mv_lastframe[0][i][j]->x = MC->mv_frame[0][i+1][j+1]->x; MC->mv_lastframe[0][i][j]->y = MC->mv_frame[0][i+1][j+1]->y; MC->mv_lastframe[0][i][j]->x_half = MC->mv_frame[0][i+1][j+1]->x_half; MC->mv_lastframe[0][i][j]->y_half = MC->mv_frame[0][i+1][j+1]->y_half; MC->mv_lastframe[0][i][j]->Mode = MC->mv_frame[0][i+1][j+1]->Mode; MC->mv_lastframe[0][i][j]->min_sad = MC->mv_frame[0][i+1][j+1]->min_sad; } } } } #ifdef __cplusplus } #endif