--- trunk/xvidcore/src/motion/motion_est.c 2002/05/07 20:03:18 167 +++ trunk/xvidcore/src/motion/motion_est.c 2002/05/11 23:54:30 174 @@ -54,13 +54,17 @@ #define MV16_THRESHOLD 192 #define MV8_THRESHOLD 56 +#define NEIGH_MOVE_THRESH 8 +// how much a block's MV must differ from his neighbour +// to be search for INTER4V. The more, the faster... + /* sad16(0,0) bias; mpeg4 spec suggests nb/2+1 */ /* nb = vop pixels * 2^(bpp-8) */ #define MV16_00_BIAS (128+1) #define MV8_00_BIAS (0) /* INTER bias for INTER/INTRA decision; mpeg4 spec suggests 2*nb */ -#define INTER_BIAS 512 +#define MV16_INTER_BIAS 512 /* Parameters which control inter/inter4v decision */ #define IMV16X16 5 @@ -69,10 +73,11 @@ #define NEIGH_TEND_16X16 2 #define NEIGH_TEND_8X8 2 - // fast ((A)/2)*2 #define EVEN(A) (((A)<0?(A)+1:(A)) & ~1) +#define MVzero(A) ( ((A).x)==(0) && ((A).y)==(0) ) +#define MVequal(A,B) ( ((A).x)==((B).x) && ((A).y)==((B).y) ) int32_t PMVfastSearch16( const uint8_t * const pRef, @@ -271,133 +276,144 @@ { const uint32_t iWcount = pParam->mb_width; const uint32_t iHcount = pParam->mb_height; - MACROBLOCK * pMBs = current->mbs; - IMAGE * pCurrent = ¤t->image; + MACROBLOCK * const pMBs = current->mbs; + MACROBLOCK * const prevMBs = reference->mbs; // previous frame - MACROBLOCK * prevMBs = reference->mbs; // previous frame - IMAGE * pRef = &reference->image; + const IMAGE * const pCurrent = ¤t->image; + const IMAGE * const pRef = &reference->image; + const VECTOR zeroMV = {0,0}; - uint32_t i, j, iIntra = 0; - - VECTOR mv16; - VECTOR pmv16; - - int32_t sad8 = 0; - int32_t sad16; - int32_t deviation; - + int32_t x, y; + int32_t iIntra = 0; + VECTOR pmv; + if (sadInit) (*sadInit)(); - // note: i==horizontal, j==vertical - for (i = 0; i < iHcount; i++) - for (j = 0; j < iWcount; j++) + for (y = 0; y < iHcount; y++) + for (x = 0; x < iWcount; x++) { - MACROBLOCK *pMB = &pMBs[j + i * iWcount]; - MACROBLOCK *prevMB = &prevMBs[j + i * iWcount]; - - sad16 = SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, - j, i, current->motion_flags, current->quant, current->fcode, - pParam, pMBs, prevMBs, &mv16, &pmv16); - pMB->sad16=sad16; + MACROBLOCK* const pMB = &pMBs[x + y * iWcount]; + pMB->sad16 = SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, + x, y, current->motion_flags, current->quant, current->fcode, + pParam, pMBs, prevMBs, &pMB->mv16, &pMB->pmvs[0]); + } - /* decide: MODE_INTER or MODE_INTRA - if (dev_intra < sad_inter - 2 * nb) use_intra - */ + for (y = 0; y < iHcount; y++) + for (x = 0; x < iWcount; x++) + { + MACROBLOCK* const pMB = &pMBs[x + y * iWcount]; - deviation = dev16(pCurrent->y + j*16 + i*16*pParam->edged_width, pParam->edged_width); - - if (deviation < (sad16 - INTER_BIAS)) + if (0 < (pMB->sad16 - MV16_INTER_BIAS)) { - pMB->mode = MODE_INTRA; - pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = 0; - pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = 0; - - pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = 0; - - iIntra++; - if(iIntra >= iLimit) - return 1; + int32_t deviation; + deviation = dev16(pCurrent->y + x*16 + y*16*pParam->edged_width, + pParam->edged_width); + + if (deviation < (pMB->sad16 - MV16_INTER_BIAS)) + { + pMB->mode = MODE_INTRA; + pMB->mv16 = pMB->mvs[0] = pMB->mvs[1] + = pMB->mvs[2] = pMB->mvs[3] = zeroMV; + pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] + = pMB->sad8[2] = pMB->sad8[3] = 0; + + iIntra++; + if (iIntra >= iLimit) + return 1; - continue; + continue; + } } - if (current->global_flags & XVID_INTER4V) + if ( (current->global_flags & XVID_INTER4V) + && (!(current->global_flags & XVID_LUMIMASKING) + || pMB->dquant == NO_CHANGE) ) { - pMB->sad8[0] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, - 2 * j, 2 * i, mv16.x, mv16.y, - current->motion_flags, current->quant, current->fcode, - pParam, pMBs, prevMBs, &pMB->mvs[0], &pMB->pmvs[0]); + int32_t neigh=0; - pMB->sad8[1] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, - 2 * j + 1, 2 * i, mv16.x, mv16.y, + if (x>0) + { neigh += abs((pMB->mv16.x)-((pMB-1)->mv16.x)); + neigh += abs((pMB->mv16.y)-((pMB-1)->mv16.y)); + } + if (y>0) + { neigh += abs((pMB->mv16.x)-((pMB-iWcount)->mv16.x)); + neigh += abs((pMB->mv16.y)-((pMB-iWcount)->mv16.y)); + } + if (x<(iWcount-1)) + { neigh += abs((pMB->mv16.x)-((pMB+1)->mv16.x)); + neigh += abs((pMB->mv16.y)-((pMB+1)->mv16.y)); + } + if (y<(iHcount-1)) + { neigh += abs((pMB->mv16.x)-((pMB+iHcount)->mv16.x)); + neigh += abs((pMB->mv16.y)-((pMB+iHcount)->mv16.y)); + } + + if (neigh > NEIGH_MOVE_THRESH) + { + int32_t sad8 = 129; //IMV16X16 * current->quant; + + if (sad8 < pMB->sad16) + sad8 += pMB->sad8[0] + = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, + 2*x, 2*y, pMB->mv16.x, pMB->mv16.y, current->motion_flags, current->quant, current->fcode, - pParam, pMBs, prevMBs, &pMB->mvs[1], &pMB->pmvs[1]); + pParam, pMBs, prevMBs, &pMB->mvs[0], &pMB->pmvs[0]); - pMB->sad8[2] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, - 2 * j, 2 * i + 1, mv16.x, mv16.y, - current->motion_flags, current->quant, current->fcode, - pParam, pMBs, prevMBs, &pMB->mvs[2], &pMB->pmvs[2]); + if (sad8 < pMB->sad16) + sad8 += pMB->sad8[1] + = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, + 2*x+1, 2*y, pMB->mv16.x, pMB->mv16.y, + current->motion_flags, current->quant, current->fcode, + pParam, pMBs, prevMBs, &pMB->mvs[1], &pMB->pmvs[1]); + + if (sad8 < pMB->sad16) + sad8 += pMB->sad8[2] + = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, + 2*x, 2*y+1, pMB->mv16.x, pMB->mv16.y, + current->motion_flags, current->quant, current->fcode, + pParam, pMBs, prevMBs, &pMB->mvs[2], &pMB->pmvs[2]); - pMB->sad8[3] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, - 2 * j + 1, 2 * i + 1, mv16.x, mv16.y, - current->motion_flags, current->quant, current->fcode, - pParam, pMBs, prevMBs, &pMB->mvs[3], &pMB->pmvs[3]); - - sad8 = pMB->sad8[0] + pMB->sad8[1] + pMB->sad8[2] + pMB->sad8[3]; - } - + if (sad8 < pMB->sad16) + sad8 += pMB->sad8[3] + = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, + 2*x+1, 2*y+1, pMB->mv16.x, pMB->mv16.y, + current->motion_flags, current->quant, current->fcode, + pParam, pMBs, prevMBs, &pMB->mvs[3], &pMB->pmvs[3]); /* decide: MODE_INTER or MODE_INTER4V - mpeg4: if (sad8 < sad16 - nb/2+1) use_inter4v + mpeg4: if (sad8 < pMB->sad16 - nb/2+1) use_inter4v */ - if (!(current->global_flags & XVID_LUMIMASKING) || pMB->dquant == NO_CHANGE) - { - if (((current->global_flags & XVID_INTER4V)==0) || - (sad16 < (sad8 + (int32_t)(IMV16X16 * current->quant)))) - { - - sad8 = sad16; - pMB->mode = MODE_INTER; - pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = mv16.x; - pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = mv16.y; - pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = sad16; - pMB->pmvs[0].x = pmv16.x; - pMB->pmvs[0].y = pmv16.y; - } - else + if (sad8 < pMB->sad16) { pMB->mode = MODE_INTER4V; - pMB->sad8[0] *= 4; + pMB->sad8[0] *= 4; pMB->sad8[1] *= 4; pMB->sad8[2] *= 4; pMB->sad8[3] *= 4; + continue; + } } } - else - { - sad8 = sad16; - pMB->mode = MODE_INTER; - pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = mv16.x; - pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = mv16.y; - pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = sad16; - pMB->pmvs[0].x = pmv16.x; - pMB->pmvs[0].y = pmv16.y; - } + pMB->mode = MODE_INTER; + pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mv16; + pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = pMB->sad16; + + pmv = get_pmv(pMBs, x, y, pParam->mb_width, 0); + // get_pmv has to be called again. + // intra-decision and inter4v change predictors + + pMB->pmvs[0].x = pMB->mv16.x - pmv.x; + pMB->pmvs[0].y = pMB->mv16.y - pmv.y; } return 0; } -#define MVzero(A) ( ((A).x)==(0) && ((A).y)==(0) ) - -#define MVequal(A,B) ( ((A).x)==((B).x) && ((A).y)==((B).y) ) - - #define CHECK_MV16_ZERO {\ if ( (0 <= max_dx) && (0 >= min_dx) \ && (0 <= max_dy) && (0 >= min_dy) ) \ @@ -861,7 +877,7 @@ VECTOR pmv[4]; int32_t psad[4]; - const MACROBLOCK * const pMB = pMBs + x + y * iWcount; +// const MACROBLOCK * const pMB = pMBs + x + y * iWcount; const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount; static int32_t threshA,threshB; @@ -901,26 +917,6 @@ iFound=0; -/* Step 2: Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion - vector of the median. - If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2 -*/ - - if ((bPredEq) && (MVequal(pmv[0],prevMB->mvs[0]) ) ) - iFound=2; - -/* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search. - Otherwise select large Diamond Search. -*/ - - if ( (pmv[0].x != 0) || (pmv[0].y != 0) || (threshB<1536) || (bPredEq) ) - iDiamondSize=1; // halfpel! - else - iDiamondSize=2; // halfpel! - - if (!(MotionFlags & PMV_HALFPELDIAMOND16) ) - iDiamondSize*=2; - /* Step 4: Calculate SAD around the Median prediction. MinSAD=SAD If Motion Vector equal to Previous frame motion vector @@ -928,9 +924,6 @@ If SAD<=256 goto Step 10. */ - -// Prepare for main loop - *currMV=pmv[0]; /* current best := prediction */ if (!(MotionFlags & PMV_HALFPEL16 )) { /* This should NOT be necessary! */ @@ -962,13 +955,43 @@ if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) ) { - + if (iMinSAD < 2*iQuant) // high chances for SKIP-mode + { + if (!MVzero(*currMV)) + { + iMinSAD += MV16_00_BIAS; + CHECK_MV16_ZERO; // (0,0) saves space for letterboxed pictures + iMinSAD -= MV16_00_BIAS; + } + } + if (MotionFlags & PMV_QUICKSTOP16) goto PMVfast16_Terminate_without_Refine; if (MotionFlags & PMV_EARLYSTOP16) goto PMVfast16_Terminate_with_Refine; } + +/* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion + vector of the median. + If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2 +*/ + + if ((bPredEq) && (MVequal(pmv[0],prevMB->mvs[0]) ) ) + iFound=2; + +/* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search. + Otherwise select large Diamond Search. +*/ + + if ( (!MVzero(pmv[0])) || (threshB<1536) || (bPredEq) ) + iDiamondSize=1; // halfpel! + else + iDiamondSize=2; // halfpel! + + if (!(MotionFlags & PMV_HALFPELDIAMOND16) ) + iDiamondSize*=2; + /* Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block. Also calculate (0,0) but do not subtract offset. @@ -978,36 +1001,51 @@ // (0,0) is always possible - CHECK_MV16_ZERO; + if (!MVzero(pmv[0])) + CHECK_MV16_ZERO; // previous frame MV is always possible - CHECK_MV16_CANDIDATE(prevMB->mvs[0].x,prevMB->mvs[0].y); + + if (!MVzero(prevMB->mvs[0])) + if (!MVequal(prevMB->mvs[0],pmv[0])) + CHECK_MV16_CANDIDATE(prevMB->mvs[0].x,prevMB->mvs[0].y); // left neighbour, if allowed - if (x != 0) + + if (!MVzero(pmv[1])) + if (!MVequal(pmv[1],prevMB->mvs[0])) + if (!MVequal(pmv[1],pmv[0])) { if (!(MotionFlags & PMV_HALFPEL16 )) { pmv[1].x = EVEN(pmv[1].x); - pmv[1].y = EVEN(pmv[1].y); + pmv[1].y = EVEN(pmv[1].y); } + CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y); } // top neighbour, if allowed - if (y != 0) + if (!MVzero(pmv[2])) + if (!MVequal(pmv[2],prevMB->mvs[0])) + if (!MVequal(pmv[2],pmv[0])) + if (!MVequal(pmv[2],pmv[1])) { if (!(MotionFlags & PMV_HALFPEL16 )) { pmv[2].x = EVEN(pmv[2].x); - pmv[2].y = EVEN(pmv[2].y); + pmv[2].y = EVEN(pmv[2].y); } CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y); // top right neighbour, if allowed - if ((uint32_t)x != (iWcount-1)) + if (!MVzero(pmv[3])) + if (!MVequal(pmv[3],prevMB->mvs[0])) + if (!MVequal(pmv[3],pmv[0])) + if (!MVequal(pmv[3],pmv[1])) + if (!MVequal(pmv[3],pmv[2])) { if (!(MotionFlags & PMV_HALFPEL16 )) { pmv[3].x = EVEN(pmv[3].x); - pmv[3].y = EVEN(pmv[3].y); + pmv[3].y = EVEN(pmv[3].y); } CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y); } @@ -1235,25 +1273,30 @@ int32_t psad[4]; VECTOR newMV; VECTOR backupMV; + VECTOR startMV; - const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount; +// const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount; const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount; static int32_t threshA,threshB; int32_t iFound,bPredEq; int32_t iMinSAD,iSAD; - int32_t iSubBlock = ((y&1)<<1) + (x&1); + int32_t iSubBlock = (y&1)+(y&1) + (x&1); -/* Get maximum range */ + /* Init variables */ + startMV.x = start_x; + startMV.y = start_y; + + /* Get maximum range */ get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 8, iWidth, iHeight, iFcode); if (!(MotionFlags & PMV_HALFPELDIAMOND8 )) { min_dx = EVEN(min_dx); - max_dx = EVEN(max_dx); - min_dy = EVEN(min_dy); - max_dy = EVEN(max_dy); + max_dx = EVEN(max_dx); + min_dy = EVEN(min_dy); + max_dy = EVEN(max_dy); } /* because we might use IF (dx>max_dx) THEN dx=max_dx; */ @@ -1276,26 +1319,6 @@ iFound=0; -/* Step 2: Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion - vector of the median. - If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2 -*/ - - if ((bPredEq) && (MVequal(pmv[0],prevMB->mvs[iSubBlock]) ) ) - iFound=2; - -/* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search. - Otherwise select large Diamond Search. -*/ - - if ( (pmv[0].x != 0) || (pmv[0].y != 0) || (threshB<1536/4) || (bPredEq) ) - iDiamondSize=1; // 1 halfpel! - else - iDiamondSize=2; // 2 halfpel = 1 full pixel! - - if (!(MotionFlags & PMV_HALFPELDIAMOND8) ) - iDiamondSize*=2; - /* Step 4: Calculate SAD around the Median prediction. MinSAD=SAD If Motion Vector equal to Previous frame motion vector @@ -1306,15 +1329,15 @@ // Prepare for main loop - currMV->x=start_x; /* start with mv16 */ - currMV->y=start_y; + *currMV = startMV; iMinSAD = sad8( cur, get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth), iEdgedWidth); iMinSAD += calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y, (uint8_t)iFcode, iQuant); - if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,prevMB->mvs[iSubBlock])) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) ) + if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,prevMB->mvs[iSubBlock])) + && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) ) { if (MotionFlags & PMV_QUICKSTOP16) goto PMVfast8_Terminate_without_Refine; @@ -1322,6 +1345,26 @@ goto PMVfast8_Terminate_with_Refine; } +/* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion + vector of the median. + If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2 +*/ + + if ((bPredEq) && (MVequal(pmv[0],prevMB->mvs[iSubBlock]) ) ) + iFound=2; + +/* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search. + Otherwise select large Diamond Search. +*/ + + if ( (!MVzero(pmv[0])) || (threshB<1536/4) || (bPredEq) ) + iDiamondSize=1; // 1 halfpel! + else + iDiamondSize=2; // 2 halfpel = 1 full pixel! + + if (!(MotionFlags & PMV_HALFPELDIAMOND8) ) + iDiamondSize*=2; + /* Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block. @@ -1330,40 +1373,68 @@ If MV is (0,0) subtract offset. */ -// the prediction might be even better than mv16 - CHECK_MV8_CANDIDATE(pmv[0].x,pmv[0].y); +// the median prediction might be even better than mv16 -// (0,0) is always possible + if (!MVequal(pmv[0],startMV)) + CHECK_MV8_CANDIDATE(pmv[0].x,pmv[0].y); + +// (0,0) if needed + if (!MVzero(pmv[0])) + if (!MVzero(startMV)) CHECK_MV8_ZERO; -// previous frame MV is always possible +// previous frame MV if needed + if (!MVzero(prevMB->mvs[iSubBlock])) + if (!MVequal(prevMB->mvs[iSubBlock],startMV)) + if (!MVequal(prevMB->mvs[iSubBlock],pmv[0])) CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y); - -// left neighbour, if allowed - if (psad[1] != MV_MAX_ERROR) + + if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[iSubBlock]) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) ) + { + if (MotionFlags & PMV_QUICKSTOP16) + goto PMVfast8_Terminate_without_Refine; + if (MotionFlags & PMV_EARLYSTOP16) + goto PMVfast8_Terminate_with_Refine; + } + + +// left neighbour, if allowed and needed + if (!MVzero(pmv[1])) + if (!MVequal(pmv[1],startMV)) + if (!MVequal(pmv[1],prevMB->mvs[iSubBlock])) + if (!MVequal(pmv[1],pmv[0])) { if (!(MotionFlags & PMV_HALFPEL8 )) { pmv[1].x = EVEN(pmv[1].x); - pmv[1].y = EVEN(pmv[1].y); + pmv[1].y = EVEN(pmv[1].y); } CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y); } -// top neighbour, if allowed - if (psad[2] != MV_MAX_ERROR) +// top neighbour, if allowed and needed + if (!MVzero(pmv[2])) + if (!MVequal(pmv[2],startMV)) + if (!MVequal(pmv[2],prevMB->mvs[iSubBlock])) + if (!MVequal(pmv[2],pmv[0])) + if (!MVequal(pmv[2],pmv[1])) { if (!(MotionFlags & PMV_HALFPEL8 )) { pmv[2].x = EVEN(pmv[2].x); - pmv[2].y = EVEN(pmv[2].y); + pmv[2].y = EVEN(pmv[2].y); } CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y); -// top right neighbour, if allowed - if (psad[3] != MV_MAX_ERROR) +// top right neighbour, if allowed and needed + if (!MVzero(pmv[3])) + if (!MVequal(pmv[3],startMV)) + if (!MVequal(pmv[3],prevMB->mvs[iSubBlock])) + if (!MVequal(pmv[3],pmv[0])) + if (!MVequal(pmv[3],pmv[1])) + if (!MVequal(pmv[3],pmv[2])) { if (!(MotionFlags & PMV_HALFPEL8 )) { pmv[3].x = EVEN(pmv[3].x); - pmv[3].y = EVEN(pmv[3].y); + pmv[3].y = EVEN(pmv[3].y); } CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y); } @@ -1496,7 +1567,7 @@ int32_t psad[8]; static MACROBLOCK * oldMBs = NULL; - const MACROBLOCK * const pMB = pMBs + x + y * iWcount; +// const MACROBLOCK * const pMB = pMBs + x + y * iWcount; const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount; MACROBLOCK * oldMB = NULL; @@ -1783,7 +1854,7 @@ const int32_t iSubBlock = ((y&1)<<1) + (x&1); - const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount; +// const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount; const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount; int32_t bPredEq;