[svn] / branches / dev-api-4 / xvidcore / src / motion / motion_est.c Repository:
ViewVC logotype

Diff of /branches/dev-api-4/xvidcore/src/motion/motion_est.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1071, Thu Jun 19 09:59:37 2003 UTC revision 1081, Thu Jul 10 17:41:48 2003 UTC
# Line 21  Line 21 
21   *  along with this program ; if not, write to the Free Software   *  along with this program ; if not, write to the Free Software
22   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
23   *   *
24   * $Id: motion_est.c,v 1.58.2.18 2003-06-19 09:58:57 syskin Exp $   * $Id: motion_est.c,v 1.58.2.21 2003-07-10 17:41:48 edgomez Exp $
25   *   *
26   ****************************************************************************/   ****************************************************************************/
27    
# Line 40  Line 40 
40  #include "motion_est.h"  #include "motion_est.h"
41  #include "motion.h"  #include "motion.h"
42  #include "sad.h"  #include "sad.h"
43    #include "gmc.h"
44  #include "../utils/emms.h"  #include "../utils/emms.h"
45  #include "../dct/fdct.h"  #include "../dct/fdct.h"
46    
# Line 455  Line 456 
456  }  }
457    
458  static void  static void
459    CheckCandidate16I(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
460    {
461            int sad;
462    //      int xc, yc;
463            const uint8_t * Reference;
464    //      VECTOR * current;
465    
466            if ( (x > data->max_dx) || ( x < data->min_dx)
467                    || (y > data->max_dy) || (y < data->min_dy) ) return;
468    
469            Reference = GetReference(x, y, data);
470    //      xc = x; yc = y;
471    
472            sad = sad16(data->Cur, Reference, data->iEdgedWidth, 256*4096);
473    //      sad += d_mv_bits(x, y, data->predMV, data->iFcode, 0, 0);
474    
475    /*      if (data->chroma) sad += ChromaSAD((xc >> 1) + roundtab_79[xc & 0x3],
476                                                                                    (yc >> 1) + roundtab_79[yc & 0x3], data);
477    */
478    
479            if (sad < data->iMinSAD[0]) {
480                    data->iMinSAD[0] = sad;
481                    data->currentMV[0].x = x; data->currentMV[0].y = y;
482                    *dir = Direction;
483            }
484    }
485    
486    static void
487  CheckCandidate32I(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)  CheckCandidate32I(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
488  {  {
489          /* maximum speed - for P/B/I decision */          /* maximum speed - for P/B/I decision */
# Line 463  Line 492 
492          if ( (x > data->max_dx) || (x < data->min_dx)          if ( (x > data->max_dx) || (x < data->min_dx)
493                  || (y > data->max_dy) || (y < data->min_dy) ) return;                  || (y > data->max_dy) || (y < data->min_dy) ) return;
494    
495          sad = sad32v_c(data->Cur, data->RefP[0] + (x>>1) + (y>>1)*(data->iEdgedWidth),          sad = sad32v_c(data->Cur, data->RefP[0] + (int)((x>>1) + (y>>1)*(data->iEdgedWidth)),
496                                          data->iEdgedWidth, data->temp+1);                                          data->iEdgedWidth, data->temp+1);
497    
498          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
# Line 667  Line 696 
696          for(i = 0; i < 4; i++) {          for(i = 0; i < 4; i++) {
697                  int s = 8*((i&1) + (i>>1)*data->iEdgedWidth);                  int s = 8*((i&1) + (i>>1)*data->iEdgedWidth);
698                  transfer_8to16subro(in, data->Cur + s, ptr + s, data->iEdgedWidth);                  transfer_8to16subro(in, data->Cur + s, ptr + s, data->iEdgedWidth);
699                  bits += data->temp[i] = Block_CalcBits(coeff, in, data->iQuant, data->quant_type, &cbp, i);                  bits += data->temp[i] = Block_CalcBits(coeff, in, data->dctSpace + 128, data->iQuant, data->quant_type, &cbp, i);
700          }          }
701    
702          bits += t = BITS_MULT*d_mv_bits(x, y, data->predMV, data->iFcode, data->qpel^data->qpel_precision, 0);          bits += t = BITS_MULT*d_mv_bits(x, y, data->predMV, data->iFcode, data->qpel^data->qpel_precision, 0);
# Line 692  Line 721 
721          /* chroma U */          /* chroma U */
722          ptr = interpolate8x8_switch2(data->RefQ + 64, data->RefP[4], 0, 0, xc, yc,  data->iEdgedWidth/2, data->rounding);          ptr = interpolate8x8_switch2(data->RefQ + 64, data->RefP[4], 0, 0, xc, yc,  data->iEdgedWidth/2, data->rounding);
723          transfer_8to16subro(in, ptr, data->CurU, data->iEdgedWidth/2);          transfer_8to16subro(in, ptr, data->CurU, data->iEdgedWidth/2);
724          bits += Block_CalcBits(coeff, in, data->iQuant, data->quant_type, &cbp, 4);          bits += Block_CalcBits(coeff, in, data->dctSpace + 128, data->iQuant, data->quant_type, &cbp, 4);
725          if (bits >= data->iMinSAD[0]) return;          if (bits >= data->iMinSAD[0]) return;
726    
727          /* chroma V */          /* chroma V */
728          ptr = interpolate8x8_switch2(data->RefQ + 64, data->RefP[5], 0, 0, xc, yc,  data->iEdgedWidth/2, data->rounding);          ptr = interpolate8x8_switch2(data->RefQ + 64, data->RefP[5], 0, 0, xc, yc,  data->iEdgedWidth/2, data->rounding);
729          transfer_8to16subro(in, ptr, data->CurV, data->iEdgedWidth/2);          transfer_8to16subro(in, ptr, data->CurV, data->iEdgedWidth/2);
730          bits += Block_CalcBits(coeff, in, data->iQuant, data->quant_type, &cbp, 5);          bits += Block_CalcBits(coeff, in, data->dctSpace + 128, data->iQuant, data->quant_type, &cbp, 5);
731    
732          bits += BITS_MULT*mcbpc_inter_tab[(MODE_INTER & 7) | ((cbp & 3) << 3)].len;          bits += BITS_MULT*mcbpc_inter_tab[(MODE_INTER & 7) | ((cbp & 3) << 3)].len;
733    
# Line 731  Line 760 
760          }          }
761    
762          transfer_8to16subro(in, data->Cur, ptr, data->iEdgedWidth);          transfer_8to16subro(in, data->Cur, ptr, data->iEdgedWidth);
763          bits = Block_CalcBits(coeff, in, data->iQuant, data->quant_type, &cbp, 5);          bits = Block_CalcBits(coeff, in, data->dctSpace + 128, data->iQuant, data->quant_type, &cbp, 5);
764          bits += BITS_MULT*d_mv_bits(x, y, data->predMV, data->iFcode, data->qpel^data->qpel_precision, 0);          bits += BITS_MULT*d_mv_bits(x, y, data->predMV, data->iFcode, data->qpel^data->qpel_precision, 0);
765    
766          if (bits < data->iMinSAD[0]) {          if (bits < data->iMinSAD[0]) {
# Line 1065  Line 1094 
1094                                   const IMAGE * const pRefH,                                   const IMAGE * const pRefH,
1095                                   const IMAGE * const pRefV,                                   const IMAGE * const pRefV,
1096                                   const IMAGE * const pRefHV,                                   const IMAGE * const pRefHV,
1097                                    const IMAGE * const pGMC,
1098                                   const uint32_t iLimit)                                   const uint32_t iLimit)
1099  {  {
1100          MACROBLOCK *const pMBs = current->mbs;          MACROBLOCK *const pMBs = current->mbs;
# Line 1079  Line 1109 
1109          uint32_t x, y;          uint32_t x, y;
1110          uint32_t iIntra = 0;          uint32_t iIntra = 0;
1111          int32_t quant = current->quant, sad00;          int32_t quant = current->quant, sad00;
1112          int skip_thresh = \          int skip_thresh = INITIAL_SKIP_THRESH * \
                 INITIAL_SKIP_THRESH * \  
1113                  (current->vop_flags & XVID_VOP_REDUCED ? 4:1) * \                  (current->vop_flags & XVID_VOP_REDUCED ? 4:1) * \
1114                  (current->vop_flags & XVID_VOP_MODEDECISION_BITS ? 2:1);                  (current->vop_flags & XVID_VOP_MODEDECISION_BITS ? 2:1);
1115    
# Line 1089  Line 1118 
1118          VECTOR currentMV[5];          VECTOR currentMV[5];
1119          VECTOR currentQMV[5];          VECTOR currentQMV[5];
1120          int32_t iMinSAD[5];          int32_t iMinSAD[5];
1121          DECLARE_ALIGNED_MATRIX(dct_space, 2, 64, int16_t, CACHE_LINE);          DECLARE_ALIGNED_MATRIX(dct_space, 3, 64, int16_t, CACHE_LINE);
1122          SearchData Data;          SearchData Data;
1123          memset(&Data, 0, sizeof(SearchData));          memset(&Data, 0, sizeof(SearchData));
1124          Data.iEdgedWidth = iEdgedWidth;          Data.iEdgedWidth = iEdgedWidth;
# Line 1101  Line 1130 
1130          Data.rounding = pParam->m_rounding_type;          Data.rounding = pParam->m_rounding_type;
1131          Data.qpel = (current->vol_flags & XVID_VOL_QUARTERPEL ? 1:0);          Data.qpel = (current->vol_flags & XVID_VOL_QUARTERPEL ? 1:0);
1132          Data.chroma = MotionFlags & XVID_ME_CHROMA16;          Data.chroma = MotionFlags & XVID_ME_CHROMA16;
1133          Data.rrv = (current->vop_flags & XVID_VOP_REDUCED ? 1:0);          Data.rrv = (current->vop_flags & XVID_VOP_REDUCED) ? 1:0;
1134          Data.dctSpace = dct_space;          Data.dctSpace = dct_space;
1135          Data.quant_type = !(pParam->vol_flags & XVID_VOL_MPEGQUANT);          Data.quant_type = !(pParam->vol_flags & XVID_VOL_MPEGQUANT);
1136    
# Line 1168  Line 1197 
1197                  }                  }
1198          }          }
1199    
1200          if (current->vol_flags & XVID_VOL_GMC ) /* GMC only for S(GMC)-VOPs */  //      if (current->vol_flags & XVID_VOL_GMC ) /* GMC only for S(GMC)-VOPs */
1201          {  //      {
1202                  current->warp = GlobalMotionEst( pMBs, pParam, current, reference, pRefH, pRefV, pRefHV);  //              current->warp = GlobalMotionEst( pMBs, pParam, current, reference, pRefH, pRefV, pRefHV);
1203          }  //      }
1204          return 0;          return 0;
1205  }  }
1206    
# Line 2161  Line 2190 
2190          }          }
2191  }  }
2192    
2193  #define INTRA_THRESH    1700  #define INTRA_THRESH    2200
2194  #define INTER_THRESH    1200  #define INTER_THRESH    50
2195    #define INTRA_THRESH2   95
2196    
2197  int  int
2198  MEanalysis(     const IMAGE * const pRef,  MEanalysis(     const IMAGE * const pRef,
2199                          const FRAMEINFO * const Current,                          const FRAMEINFO * const Current,
2200                          const MBParam * const pParam,                          const MBParam * const pParam,
2201                          const int maxIntra, /* maximum number if non-I frames */                          const int maxIntra, //maximum number if non-I frames
2202                          const int intraCount, /* number of non-I frames after last I frame; 0 if we force P/B frame */                          const int intraCount, //number of non-I frames after last I frame; 0 if we force P/B frame
2203                          const int bCount,  /* number of B frames in a row */                          const int bCount,  // number of B frames in a row
2204                          const int b_thresh)                          const int b_thresh)
2205  {  {
2206          uint32_t x, y, intra = 0;          uint32_t x, y, intra = 0;
2207          int sSAD = 0;          int sSAD = 0;
2208          MACROBLOCK * const pMBs = Current->mbs;          MACROBLOCK * const pMBs = Current->mbs;
2209          const IMAGE * const pCurrent = &Current->image;          const IMAGE * const pCurrent = &Current->image;
2210          int IntraThresh = INTRA_THRESH, InterThresh = INTER_THRESH + 10*b_thresh;          int IntraThresh = INTRA_THRESH, InterThresh = INTER_THRESH + b_thresh;
2211          int s = 0, blocks = 0;          int blocks = 0;
2212            int complexity = 0;
2213    
2214          int32_t iMinSAD[5], temp[5];          int32_t iMinSAD[5], temp[5];
2215          VECTOR currentMV[5];          VECTOR currentMV[5];
# Line 2190  Line 2221 
2221          Data.temp = temp;          Data.temp = temp;
2222          CheckCandidate = CheckCandidate32I;          CheckCandidate = CheckCandidate32I;
2223    
2224    
2225          if (intraCount != 0) {          if (intraCount != 0) {
2226                  if (intraCount < 10) /* we're right after an I frame */                  if (intraCount < 10) // we're right after an I frame
2227                          IntraThresh += 15* (intraCount - 10) * (intraCount - 10);                          IntraThresh += 15* (intraCount - 10) * (intraCount - 10);
2228                  else                  else
2229                          if ( 5*(maxIntra - intraCount) < maxIntra) /* we're close to maximum. 2 sec when max is 10 sec */                          if ( 5*(maxIntra - intraCount) < maxIntra) // we're close to maximum. 2 sec when max is 10 sec
2230                                  IntraThresh -= (IntraThresh * (maxIntra - 8*(maxIntra - intraCount)))/maxIntra;                                  IntraThresh -= (IntraThresh * (maxIntra - 8*(maxIntra - intraCount)))/maxIntra;
2231          }          }
2232    
2233          InterThresh -= (350 - 8*b_thresh) * bCount;          InterThresh -= 12 * bCount;
2234          if (InterThresh < 300 + 5*b_thresh) InterThresh = 300 + 5*b_thresh;          if (InterThresh < 15 + b_thresh) InterThresh = 15 + b_thresh;
2235    
2236          if (sadInit) (*sadInit) ();          if (sadInit) (*sadInit) ();
2237    
2238          for (y = 1; y < pParam->mb_height-1; y += 2) {          for (y = 1; y < pParam->mb_height-1; y += 2) {
2239                  for (x = 1; x < pParam->mb_width-1; x += 2) {                  for (x = 1; x < pParam->mb_width-1; x += 2) {
2240                          int i;                          int i;
2241                          blocks += 4;                          blocks += 10;
2242    
2243                          if (bCount == 0) pMBs[x + y * pParam->mb_width].mvs[0] = zeroMV;                          if (bCount == 0) pMBs[x + y * pParam->mb_width].mvs[0] = zeroMV;
2244                          else { /* extrapolation of the vector found for last frame */                          else { //extrapolation of the vector found for last frame
2245                                  pMBs[x + y * pParam->mb_width].mvs[0].x =                                  pMBs[x + y * pParam->mb_width].mvs[0].x =
2246                                          (pMBs[x + y * pParam->mb_width].mvs[0].x * (bCount+1) ) / bCount;                                          (pMBs[x + y * pParam->mb_width].mvs[0].x * (bCount+1) ) / bCount;
2247                                  pMBs[x + y * pParam->mb_width].mvs[0].y =                                  pMBs[x + y * pParam->mb_width].mvs[0].y =
# Line 2221  Line 2253 
2253                          for (i = 0; i < 4; i++) {                          for (i = 0; i < 4; i++) {
2254                                  int dev;                                  int dev;
2255                                  MACROBLOCK *pMB = &pMBs[x+(i&1) + (y+(i>>1)) * pParam->mb_width];                                  MACROBLOCK *pMB = &pMBs[x+(i&1) + (y+(i>>1)) * pParam->mb_width];
                                 if (pMB->sad16 > IntraThresh) {  
2256                                          dev = dev16(pCurrent->y + (x + (i&1) + (y + (i>>1)) * pParam->edged_width) * 16,                                          dev = dev16(pCurrent->y + (x + (i&1) + (y + (i>>1)) * pParam->edged_width) * 16,
2257                                                                          pParam->edged_width);                                                                          pParam->edged_width);
2258    
2259                                    complexity += dev;
2260                                          if (dev + IntraThresh < pMB->sad16) {                                          if (dev + IntraThresh < pMB->sad16) {
2261                                                  pMB->mode = MODE_INTRA;                                                  pMB->mode = MODE_INTRA;
2262                                                  if (++intra > ((pParam->mb_height-2)*(pParam->mb_width-2))/2) return I_VOP;                                                  if (++intra > ((pParam->mb_height-2)*(pParam->mb_width-2))/2) return I_VOP;
2263                                          }                                          }
2264                                  }  
2265                                  if (pMB->mvs[0].x == 0 && pMB->mvs[0].y == 0) s++;                                  if (pMB->mvs[0].x == 0 && pMB->mvs[0].y == 0)
2266                                            if (dev > 500 && pMB->sad16 < 1000)
2267                                                    sSAD += 1000;
2268    
2269                                  sSAD += pMB->sad16;                                  sSAD += pMB->sad16;
2270                          }                          }
2271                  }                  }
2272          }          }
2273            complexity >>= 7;
2274    
2275          sSAD /= blocks;          sSAD /= complexity + 4*blocks;
   
         if (b_thresh < 20) {  
                 s = (10*s) / blocks;  
                 if (s > 4) sSAD += (s - 2) * (40 - 2*b_thresh); /* static block - looks bad when in bframe... */  
         }  
2276    
2277            if (intraCount > 12 && sSAD > INTRA_THRESH2 ) return I_VOP;
2278          if (sSAD > InterThresh ) return P_VOP;          if (sSAD > InterThresh ) return P_VOP;
2279          emms();          emms();
2280          return B_VOP;          return B_VOP;
2281  }  }
2282    
2283    
 static WARPPOINTS  
 GlobalMotionEst(const MACROBLOCK * const pMBs,  
                                 const MBParam * const pParam,  
                                 const FRAMEINFO * const current,  
                                 const FRAMEINFO * const reference,  
                                 const IMAGE * const pRefH,  
                                 const IMAGE * const pRefV,  
                                 const IMAGE * const pRefHV      )  
 {  
   
         const int deltax=8;             /* upper bound for difference between a MV and it's neighbour MVs */  
         const int deltay=8;  
         const int grad=512;             /* lower bound for deviation in MB */  
   
         WARPPOINTS gmc;  
   
         uint32_t mx, my;  
   
         int MBh = pParam->mb_height;  
         int MBw = pParam->mb_width;  
   
         int *MBmask= calloc(MBh*MBw,sizeof(int));  
         double DtimesF[4] = { 0.,0., 0., 0. };  
         double sol[4] = { 0., 0., 0., 0. };  
         double a,b,c,n,denom;  
         double meanx,meany;  
         int num,oldnum;  
   
         if (!MBmask) {  fprintf(stderr,"Mem error\n");  
                                         gmc.duv[0].x= gmc.duv[0].y =  
                                                 gmc.duv[1].x= gmc.duv[1].y =  
                                                 gmc.duv[2].x= gmc.duv[2].y = 0;  
                                         return gmc; }  
   
         /* filter mask of all blocks */  
   
         for (my = 1; my < (uint32_t)MBh-1; my++)  
         for (mx = 1; mx < (uint32_t)MBw-1; mx++)  
         {  
                 const int mbnum = mx + my * MBw;  
                 const MACROBLOCK *pMB = &pMBs[mbnum];  
                 const VECTOR mv = pMB->mvs[0];  
   
                 if (pMB->mode == MODE_INTRA || pMB->mode == MODE_NOT_CODED)  
                         continue;  
   
                 if ( ( (abs(mv.x -   (pMB-1)->mvs[0].x) < deltax) && (abs(mv.y -   (pMB-1)->mvs[0].y) < deltay) )  
                 &&   ( (abs(mv.x -   (pMB+1)->mvs[0].x) < deltax) && (abs(mv.y -   (pMB+1)->mvs[0].y) < deltay) )  
                 &&   ( (abs(mv.x - (pMB-MBw)->mvs[0].x) < deltax) && (abs(mv.y - (pMB-MBw)->mvs[0].y) < deltay) )  
                 &&   ( (abs(mv.x - (pMB+MBw)->mvs[0].x) < deltax) && (abs(mv.y - (pMB+MBw)->mvs[0].y) < deltay) ) )  
                         MBmask[mbnum]=1;  
         }  
   
         for (my = 1; my < (uint32_t)MBh-1; my++)  
         for (mx = 1; mx < (uint32_t)MBw-1; mx++)  
         {  
                 const uint8_t *const pCur = current->image.y + 16*my*pParam->edged_width + 16*mx;  
   
                 const int mbnum = mx + my * MBw;  
                 if (!MBmask[mbnum])  
                         continue;  
   
                 if (sad16 ( pCur, pCur+1 , pParam->edged_width, 65536) <= (uint32_t)grad )  
                         MBmask[mbnum] = 0;  
                 if (sad16 ( pCur, pCur+pParam->edged_width, pParam->edged_width, 65536) <= (uint32_t)grad )  
                         MBmask[mbnum] = 0;  
   
         }  
   
         emms();  
   
         do {            /* until convergence */  
   
         a = b = c = n = 0;  
         DtimesF[0] = DtimesF[1] = DtimesF[2] = DtimesF[3] = 0.;  
         for (my = 0; my < (uint32_t)MBh; my++)  
                 for (mx = 0; mx < (uint32_t)MBw; mx++)  
                 {  
                         const int mbnum = mx + my * MBw;  
                         const MACROBLOCK *pMB = &pMBs[mbnum];  
                         const VECTOR mv = pMB->mvs[0];  
   
                         if (!MBmask[mbnum])  
                                 continue;  
   
                         n++;  
                         a += 16*mx+8;  
                         b += 16*my+8;  
                         c += (16*mx+8)*(16*mx+8)+(16*my+8)*(16*my+8);  
   
                         DtimesF[0] += (double)mv.x;  
                         DtimesF[1] += (double)mv.x*(16*mx+8) + (double)mv.y*(16*my+8);  
                         DtimesF[2] += (double)mv.x*(16*my+8) - (double)mv.y*(16*mx+8);  
                         DtimesF[3] += (double)mv.y;  
                 }  
   
         denom = a*a+b*b-c*n;  
   
 /* Solve the system:    sol = (D'*E*D)^{-1} D'*E*F   */  
 /* D'*E*F has been calculated in the same loop as matrix */  
   
         sol[0] = -c*DtimesF[0] + a*DtimesF[1] + b*DtimesF[2];  
         sol[1] =  a*DtimesF[0] - n*DtimesF[1]                + b*DtimesF[3];  
         sol[2] =  b*DtimesF[0]                - n*DtimesF[2] - a*DtimesF[3];  
         sol[3] =                 b*DtimesF[1] - a*DtimesF[2] - c*DtimesF[3];  
   
         sol[0] /= denom;  
         sol[1] /= denom;  
         sol[2] /= denom;  
         sol[3] /= denom;  
   
         meanx = meany = 0.;  
         oldnum = 0;  
         for (my = 0; my < (uint32_t)MBh; my++)  
                 for (mx = 0; mx < (uint32_t)MBw; mx++)  
                 {  
                         const int mbnum = mx + my * MBw;  
                         const MACROBLOCK *pMB = &pMBs[mbnum];  
                         const VECTOR mv = pMB->mvs[0];  
   
                         if (!MBmask[mbnum])  
                                 continue;  
   
                         oldnum++;  
                         meanx += fabs(( sol[0] + (16*mx+8)*sol[1] + (16*my+8)*sol[2] ) - mv.x );  
                         meany += fabs(( sol[3] - (16*mx+8)*sol[2] + (16*my+8)*sol[1] ) - mv.y );  
                 }  
   
         if (4*meanx > oldnum)   /* better fit than 0.25 is useless */  
                 meanx /= oldnum;  
         else  
                 meanx = 0.25;  
   
         if (4*meany > oldnum)  
                 meany /= oldnum;  
         else  
                 meany = 0.25;  
   
 /*      fprintf(stderr,"sol = (%8.5f, %8.5f, %8.5f, %8.5f)\n",sol[0],sol[1],sol[2],sol[3]);  
         fprintf(stderr,"meanx = %8.5f  meany = %8.5f   %d\n",meanx,meany, oldnum);  
 */  
         num = 0;  
         for (my = 0; my < (uint32_t)MBh; my++)  
                 for (mx = 0; mx < (uint32_t)MBw; mx++)  
                 {  
                         const int mbnum = mx + my * MBw;  
                         const MACROBLOCK *pMB = &pMBs[mbnum];  
                         const VECTOR mv = pMB->mvs[0];  
   
                         if (!MBmask[mbnum])  
                                 continue;  
   
                         if  ( ( fabs(( sol[0] + (16*mx+8)*sol[1] + (16*my+8)*sol[2] ) - mv.x ) > meanx )  
                                 || ( fabs(( sol[3] - (16*mx+8)*sol[2] + (16*my+8)*sol[1] ) - mv.y ) > meany ) )  
                                 MBmask[mbnum]=0;  
                         else  
                                 num++;  
                 }  
   
         } while ( (oldnum != num) && (num>=4) );  
   
         if (num < 4)  
         {  
                 gmc.duv[0].x= gmc.duv[0].y= gmc.duv[1].x= gmc.duv[1].y= gmc.duv[2].x= gmc.duv[2].y=0;  
         } else {  
   
                 gmc.duv[0].x=(int)(sol[0]+0.5);  
                 gmc.duv[0].y=(int)(sol[3]+0.5);  
   
                 gmc.duv[1].x=(int)(sol[1]*pParam->width+0.5);  
                 gmc.duv[1].y=(int)(-sol[2]*pParam->width+0.5);  
   
                 gmc.duv[2].x=0;  
                 gmc.duv[2].y=0;  
         }  
 /*      fprintf(stderr,"wp1 = ( %4d, %4d)  wp2 = ( %4d, %4d) \n", gmc.duv[0].x, gmc.duv[0].y, gmc.duv[1].x, gmc.duv[1].y); */  
   
         free(MBmask);  
   
         return gmc;  
 }  
   
2284  /* functions which perform BITS-based search/bitcount */  /* functions which perform BITS-based search/bitcount */
2285    
2286  static int  static int
# Line 2621  Line 2471 
2471          /* chroma U */          /* chroma U */
2472          ptr = interpolate8x8_switch2(Data->RefQ + 64, Data->RefP[4], 0, 0, sumx, sumy, Data->iEdgedWidth/2, Data->rounding);          ptr = interpolate8x8_switch2(Data->RefQ + 64, Data->RefP[4], 0, 0, sumx, sumy, Data->iEdgedWidth/2, Data->rounding);
2473          transfer_8to16subro(in, Data->CurU, ptr, Data->iEdgedWidth/2);          transfer_8to16subro(in, Data->CurU, ptr, Data->iEdgedWidth/2);
2474          bits += Block_CalcBits(coeff, in, Data->iQuant, Data->quant_type, &cbp, 4);          bits += Block_CalcBits(coeff, in, Data->dctSpace + 128, Data->iQuant, Data->quant_type, &cbp, 4);
2475    
2476          if (bits >= *Data->iMinSAD) return bits;          if (bits >= *Data->iMinSAD) return bits;
2477    
2478          /* chroma V */          /* chroma V */
2479          ptr = interpolate8x8_switch2(Data->RefQ + 64, Data->RefP[5], 0, 0, sumx, sumy, Data->iEdgedWidth/2, Data->rounding);          ptr = interpolate8x8_switch2(Data->RefQ + 64, Data->RefP[5], 0, 0, sumx, sumy, Data->iEdgedWidth/2, Data->rounding);
2480          transfer_8to16subro(in, Data->CurV, ptr, Data->iEdgedWidth/2);          transfer_8to16subro(in, Data->CurV, ptr, Data->iEdgedWidth/2);
2481          bits += Block_CalcBits(coeff, in, Data->iQuant, Data->quant_type, &cbp, 5);          bits += Block_CalcBits(coeff, in, Data->dctSpace + 128, Data->iQuant, Data->quant_type, &cbp, 5);
2482    
2483          bits += BITS_MULT*mcbpc_inter_tab[(MODE_INTER4V & 7) | ((cbp & 3) << 3)].len;          bits += BITS_MULT*mcbpc_inter_tab[(MODE_INTER4V & 7) | ((cbp & 3) << 3)].len;
2484    
# Line 2645  Line 2495 
2495          for(i = 0; i < 4; i++) {          for(i = 0; i < 4; i++) {
2496                  int s = 8*((i&1) + (i>>1)*Data->iEdgedWidth);                  int s = 8*((i&1) + (i>>1)*Data->iEdgedWidth);
2497                  transfer_8to16copy(in, Data->Cur + s, Data->iEdgedWidth);                  transfer_8to16copy(in, Data->Cur + s, Data->iEdgedWidth);
2498                  bits += Block_CalcBitsIntra(coeff, in, Data->iQuant, Data->quant_type, &cbp, i, &dc);                  bits += Block_CalcBitsIntra(coeff, in, Data->dctSpace + 128, Data->iQuant, Data->quant_type, &cbp, i, &dc);
2499    
2500                  if (bits >= Data->iMinSAD[0]) return bits;                  if (bits >= Data->iMinSAD[0]) return bits;
2501          }          }
# Line 2654  Line 2504 
2504    
2505          /*chroma U */          /*chroma U */
2506          transfer_8to16copy(in, Data->CurU, Data->iEdgedWidth/2);          transfer_8to16copy(in, Data->CurU, Data->iEdgedWidth/2);
2507          bits += Block_CalcBitsIntra(coeff, in, Data->iQuant, Data->quant_type, &cbp, 4, &dc);          bits += Block_CalcBitsIntra(coeff, in, Data->dctSpace + 128, Data->iQuant, Data->quant_type, &cbp, 4, &dc);
2508    
2509          if (bits >= Data->iMinSAD[0]) return bits;          if (bits >= Data->iMinSAD[0]) return bits;
2510    
2511          /* chroma V */          /* chroma V */
2512          transfer_8to16copy(in, Data->CurV, Data->iEdgedWidth/2);          transfer_8to16copy(in, Data->CurV, Data->iEdgedWidth/2);
2513          bits += Block_CalcBitsIntra(coeff, in, Data->iQuant, Data->quant_type, &cbp, 5, &dc);          bits += Block_CalcBitsIntra(coeff, in, Data->dctSpace + 128, Data->iQuant, Data->quant_type, &cbp, 5, &dc);
2514    
2515          bits += BITS_MULT*mcbpc_inter_tab[(MODE_INTRA & 7) | ((cbp & 3) << 3)].len;          bits += BITS_MULT*mcbpc_inter_tab[(MODE_INTRA & 7) | ((cbp & 3) << 3)].len;
2516    
2517          return bits;          return bits;
2518  }  }
2519    
2520    
2521    
2522    
2523    
2524    static __inline void
2525    GMEanalyzeMB (  const uint8_t * const pCur,
2526                                    const uint8_t * const pRef,
2527                                    const uint8_t * const pRefH,
2528                                    const uint8_t * const pRefV,
2529                                    const uint8_t * const pRefHV,
2530                                    const int x,
2531                                    const int y,
2532                                    const MBParam * const pParam,
2533                                    MACROBLOCK * const pMBs,
2534                                    SearchData * const Data)
2535    {
2536    
2537            int i=0;
2538    //      VECTOR pmv[3];
2539            MACROBLOCK * const pMB = &pMBs[x + y * pParam->mb_width];
2540    
2541            Data->iMinSAD[0] = MV_MAX_ERROR;
2542    
2543            //median is only used as prediction. it doesn't have to be real
2544            if (x == 0 && y == 0)
2545                    Data->predMV.x = Data->predMV.y = 0;
2546            else
2547                    if (x == 0) //left macroblock does not have any vector now
2548                            Data->predMV = (pMB - pParam->mb_width)->mvs[0]; // top instead of median
2549                    else if (y == 0) // top macroblock doesn't have it's vector
2550                            Data->predMV = (pMB-1)->mvs[0]; // left instead of median
2551                            else Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0); //else median
2552    
2553            get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
2554                                    pParam->width, pParam->height, Data->iFcode - ((pParam->vol_flags & XVID_VOL_QUARTERPEL)?1:0), 0, 0);
2555    
2556            Data->Cur = pCur + 16*(x + y * pParam->edged_width);
2557            Data->RefP[0] = pRef + 16*(x + y * pParam->edged_width);
2558            Data->RefP[1] = pRefV + 16*(x + y * pParam->edged_width);
2559            Data->RefP[2] = pRefH + 16*(x + y * pParam->edged_width);
2560            Data->RefP[3] = pRefHV + 16*(x + y * pParam->edged_width);
2561    
2562            Data->currentMV[0].x = Data->currentMV[0].y = 0;
2563            CheckCandidate16I(0, 0, 255, &i, Data);
2564    
2565            if ( (Data->predMV.x !=0) || (Data->predMV.y != 0) )
2566                    CheckCandidate16I(Data->predMV.x, Data->predMV.y, 255, &i, Data);
2567    
2568            if (Data->iMinSAD[0] > 256 /*4 * MAX_SAD00_FOR_SKIP*/) // diamond only if needed
2569                    DiamondSearch(Data->currentMV[0].x, Data->currentMV[0].y, Data, 255);
2570    
2571            SubpelRefine(Data);
2572    
2573    
2574            /* for QPel halfpel positions are worse than in halfpel mode :( */
2575    /*      if (Data->qpel) {
2576                    Data->currentQMV->x = 2*Data->currentMV->x;
2577                    Data->currentQMV->y = 2*Data->currentMV->y;
2578                    Data->qpel_precision = 1;
2579                    get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
2580                                            pParam->width, pParam->height, iFcode, 1, 0);
2581                    SubpelRefine(Data);
2582            }
2583    */
2584    
2585            pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
2586            pMB->sad16 = Data->iMinSAD[0];
2587            pMB->sad16 += d_mv_bits(pMB->mvs[0].x, pMB->mvs[0].y, Data->predMV, Data->iFcode, 0, 0);
2588            return;
2589    }
2590    
2591    void
2592    GMEanalysis(const MBParam * const pParam,
2593                            const FRAMEINFO * const current,
2594                            const FRAMEINFO * const reference,
2595                            const IMAGE * const pRefH,
2596                            const IMAGE * const pRefV,
2597                            const IMAGE * const pRefHV)
2598    {
2599            uint32_t x, y;
2600            MACROBLOCK * const pMBs = current->mbs;
2601            const IMAGE * const pCurrent = &current->image;
2602            const IMAGE * const pReference = &reference->image;
2603    
2604            int32_t iMinSAD[5], temp[5];
2605            VECTOR currentMV[5];
2606            SearchData Data;
2607            memset(&Data, 0, sizeof(SearchData));
2608    
2609            Data.iEdgedWidth = pParam->edged_width;
2610            Data.qpel = ((pParam->vol_flags & XVID_VOL_QUARTERPEL)?1:0);
2611            Data.qpel_precision = 0;
2612            Data.rounding = pParam->m_rounding_type;
2613            Data.chroma = current->motion_flags & XVID_ME_CHROMA16;
2614            Data.rrv = current->vop_flags & XVID_VOL_REDUCED_ENABLE;
2615    
2616            Data.currentMV = &currentMV[0];
2617            Data.iMinSAD = &iMinSAD[0];
2618            Data.iFcode = current->fcode;
2619            Data.temp = temp;
2620            Data.RefP[0] = pReference->y;
2621            Data.RefP[1] = pRefV->y;
2622            Data.RefP[2] = pRefH->y;
2623            Data.RefP[3] = pRefHV->y;
2624    
2625            CheckCandidate = CheckCandidate16I;
2626    
2627            if (sadInit) (*sadInit) ();
2628    
2629            for (y = 0; y < pParam->mb_height; y ++) {
2630                    for (x = 0; x < pParam->mb_width; x ++) {
2631    
2632                            GMEanalyzeMB(pCurrent->y, pReference->y, pRefH->y, pRefV->y, pRefHV->y, x, y, pParam, pMBs, &Data);
2633                    }
2634            }
2635            return;
2636    }
2637    
2638    
2639    WARPPOINTS
2640    GlobalMotionEst(MACROBLOCK * const pMBs,
2641                                    const MBParam * const pParam,
2642                                    const FRAMEINFO * const current,
2643                                    const FRAMEINFO * const reference,
2644                                    const IMAGE * const pRefH,
2645                                    const IMAGE * const pRefV,
2646                                    const IMAGE * const pRefHV)
2647    {
2648    
2649            const unsigned int deltax=8;            // upper bound for difference between a MV and it's neighbour MVs
2650            const unsigned int deltay=8;
2651            const unsigned int gradx=512;           // lower bound for gradient in MB (ignore "flat" blocks)
2652            const unsigned int grady=512;
2653    
2654            double sol[4] = { 0., 0., 0., 0. };
2655    
2656            WARPPOINTS gmc;
2657    
2658            uint32_t mx, my;
2659    
2660            int MBh = pParam->mb_height;
2661            int MBw = pParam->mb_width;
2662            const int minblocks = 9; //MBh*MBw/32+3;                /* just some reasonable number 3% + 3 */
2663            const int maxblocks = MBh*MBw/4;                /* just some reasonable number 3% + 3 */
2664    
2665            int num=0;
2666            int oldnum;
2667    
2668            gmc.duv[0].x = gmc.duv[0].y = gmc.duv[1].x = gmc.duv[1].y = gmc.duv[2].x = gmc.duv[2].y = 0;
2669    
2670            GMEanalysis(pParam,current, reference, pRefH, pRefV, pRefHV);
2671    
2672            /* block based ME isn't done, yet, so do a quick presearch */
2673    
2674    // filter mask of all blocks
2675    
2676            for (my = 0; my < (uint32_t)MBh; my++)
2677            for (mx = 0; mx < (uint32_t)MBw; mx++)
2678            {
2679                    const int mbnum = mx + my * MBw;
2680                            pMBs[mbnum].mcsel = 0;
2681            }
2682    
2683    
2684            for (my = 1; my < (uint32_t)MBh-1; my++) /* ignore boundary blocks */
2685            for (mx = 1; mx < (uint32_t)MBw-1; mx++) /* theirs MVs are often wrong */
2686            {
2687                    const int mbnum = mx + my * MBw;
2688                    MACROBLOCK *const pMB = &pMBs[mbnum];
2689                    const VECTOR mv = pMB->mvs[0];
2690    
2691                    /* don't use object boundaries */
2692                    if   ( (abs(mv.x -   (pMB-1)->mvs[0].x) < deltax)
2693                            && (abs(mv.y -   (pMB-1)->mvs[0].y) < deltay)
2694                            && (abs(mv.x -   (pMB+1)->mvs[0].x) < deltax)
2695                            && (abs(mv.y -   (pMB+1)->mvs[0].y) < deltay)
2696                            && (abs(mv.x - (pMB-MBw)->mvs[0].x) < deltax)
2697                            && (abs(mv.y - (pMB-MBw)->mvs[0].y) < deltay)
2698                            && (abs(mv.x - (pMB+MBw)->mvs[0].x) < deltax)
2699                            && (abs(mv.y - (pMB+MBw)->mvs[0].y) < deltay) )
2700                    {       const int iEdgedWidth = pParam->edged_width;
2701                            const uint8_t *const pCur = current->image.y + 16*(my*iEdgedWidth + mx);
2702                            if ( (sad16 ( pCur, pCur+1 , iEdgedWidth, 65536) >= gradx )
2703                             &&  (sad16 ( pCur, pCur+iEdgedWidth, iEdgedWidth, 65536) >= grady ) )
2704                             {      pMB->mcsel = 1;
2705                                    num++;
2706                             }
2707    
2708                    /* only use "structured" blocks */
2709                    }
2710            }
2711            emms();
2712    
2713            /*      further filtering would be possible, but during iteration, remaining
2714                    outliers usually are removed, too */
2715    
2716            if (num>= minblocks)
2717            do {            /* until convergence */
2718                    double DtimesF[4];
2719                    double a,b,c,n,invdenom;
2720                    double meanx,meany;
2721    
2722                    a = b = c = n = 0;
2723                    DtimesF[0] = DtimesF[1] = DtimesF[2] = DtimesF[3] = 0.;
2724                    for (my = 1; my < (uint32_t)MBh-1; my++)
2725                    for (mx = 1; mx < (uint32_t)MBw-1; mx++)
2726                    {
2727                            const int mbnum = mx + my * MBw;
2728                            const VECTOR mv = pMBs[mbnum].mvs[0];
2729    
2730                            if (!pMBs[mbnum].mcsel)
2731                                    continue;
2732    
2733                            n++;
2734                            a += 16*mx+8;
2735                            b += 16*my+8;
2736                            c += (16*mx+8)*(16*mx+8)+(16*my+8)*(16*my+8);
2737    
2738                            DtimesF[0] += (double)mv.x;
2739                            DtimesF[1] += (double)mv.x*(16*mx+8) + (double)mv.y*(16*my+8);
2740                            DtimesF[2] += (double)mv.x*(16*my+8) - (double)mv.y*(16*mx+8);
2741                            DtimesF[3] += (double)mv.y;
2742                    }
2743    
2744            invdenom = a*a+b*b-c*n;
2745    
2746    /* Solve the system:    sol = (D'*E*D)^{-1} D'*E*F   */
2747    /* D'*E*F has been calculated in the same loop as matrix */
2748    
2749            sol[0] = -c*DtimesF[0] + a*DtimesF[1] + b*DtimesF[2];
2750            sol[1] =  a*DtimesF[0] - n*DtimesF[1]                           + b*DtimesF[3];
2751            sol[2] =  b*DtimesF[0]                          - n*DtimesF[2] - a*DtimesF[3];
2752            sol[3] =                                 b*DtimesF[1] - a*DtimesF[2] - c*DtimesF[3];
2753    
2754            sol[0] /= invdenom;
2755            sol[1] /= invdenom;
2756            sol[2] /= invdenom;
2757            sol[3] /= invdenom;
2758    
2759            meanx = meany = 0.;
2760            oldnum = 0;
2761            for (my = 1; my < (uint32_t)MBh-1; my++)
2762                    for (mx = 1; mx < (uint32_t)MBw-1; mx++)
2763                    {
2764                            const int mbnum = mx + my * MBw;
2765                            const VECTOR mv = pMBs[mbnum].mvs[0];
2766    
2767                            if (!pMBs[mbnum].mcsel)
2768                                    continue;
2769    
2770                            oldnum++;
2771                            meanx += fabs(( sol[0] + (16*mx+8)*sol[1] + (16*my+8)*sol[2] ) - (double)mv.x );
2772                            meany += fabs(( sol[3] - (16*mx+8)*sol[2] + (16*my+8)*sol[1] ) - (double)mv.y );
2773                    }
2774    
2775            if (4*meanx > oldnum)   /* better fit than 0.25 (=1/4pel) is useless */
2776                    meanx /= oldnum;
2777            else
2778                    meanx = 0.25;
2779    
2780            if (4*meany > oldnum)
2781                    meany /= oldnum;
2782            else
2783                    meany = 0.25;
2784    
2785            num = 0;
2786            for (my = 0; my < (uint32_t)MBh; my++)
2787                    for (mx = 0; mx < (uint32_t)MBw; mx++)
2788                    {
2789                            const int mbnum = mx + my * MBw;
2790                            const VECTOR mv = pMBs[mbnum].mvs[0];
2791    
2792                            if (!pMBs[mbnum].mcsel)
2793                                    continue;
2794    
2795                            if  ( ( fabs(( sol[0] + (16*mx+8)*sol[1] + (16*my+8)*sol[2] ) - (double)mv.x ) > meanx )
2796                                    || ( fabs(( sol[3] - (16*mx+8)*sol[2] + (16*my+8)*sol[1] ) - (double)mv.y ) > meany ) )
2797                                    pMBs[mbnum].mcsel=0;
2798                            else
2799                                    num++;
2800                    }
2801    
2802            } while ( (oldnum != num) && (num>= minblocks) );
2803    
2804            if (num < minblocks)
2805            {
2806                    const int iEdgedWidth = pParam->edged_width;
2807                    num = 0;
2808    
2809    /*              fprintf(stderr,"Warning! Unreliable GME (%d/%d blocks), falling back to translation.\n",num,MBh*MBw);
2810    */
2811                    gmc.duv[0].x= gmc.duv[0].y= gmc.duv[1].x= gmc.duv[1].y= gmc.duv[2].x= gmc.duv[2].y=0;
2812    
2813                    if (!(current->motion_flags & XVID_GME_REFINE))
2814                            return gmc;
2815    
2816                    for (my = 1; my < (uint32_t)MBh-1; my++) /* ignore boundary blocks */
2817                    for (mx = 1; mx < (uint32_t)MBw-1; mx++) /* theirs MVs are often wrong */
2818                    {
2819                            const int mbnum = mx + my * MBw;
2820                            MACROBLOCK *const pMB = &pMBs[mbnum];
2821                            const uint8_t *const pCur = current->image.y + 16*(my*iEdgedWidth + mx);
2822                            if ( (sad16 ( pCur, pCur+1 , iEdgedWidth, 65536) >= gradx )
2823                             &&  (sad16 ( pCur, pCur+iEdgedWidth, iEdgedWidth, 65536) >= grady ) )
2824                             {      pMB->mcsel = 1;
2825                                    gmc.duv[0].x += pMB->mvs[0].x;
2826                                    gmc.duv[0].y += pMB->mvs[0].y;
2827                                    num++;
2828                             }
2829                    }
2830    
2831                    if (gmc.duv[0].x)
2832                            gmc.duv[0].x /= num;
2833                    if (gmc.duv[0].y)
2834                            gmc.duv[0].y /= num;
2835            } else {
2836    
2837                    gmc.duv[0].x=(int)(sol[0]+0.5);
2838                    gmc.duv[0].y=(int)(sol[3]+0.5);
2839    
2840                    gmc.duv[1].x=(int)(sol[1]*pParam->width+0.5);
2841                    gmc.duv[1].y=(int)(-sol[2]*pParam->width+0.5);
2842    
2843                    gmc.duv[2].x=-gmc.duv[1].y;             /* two warp points only */
2844                    gmc.duv[2].y=gmc.duv[1].x;
2845            }
2846            if (num>maxblocks)
2847            {       for (my = 1; my < (uint32_t)MBh-1; my++)
2848                    for (mx = 1; mx < (uint32_t)MBw-1; mx++)
2849                    {
2850                            const int mbnum = mx + my * MBw;
2851                            if (pMBs[mbnum-1].mcsel)
2852                                    pMBs[mbnum].mcsel=0;
2853                            else
2854                                    if (pMBs[mbnum-MBw].mcsel)
2855                                            pMBs[mbnum].mcsel=0;
2856                    }
2857            }
2858            return gmc;
2859    }
2860    
2861    int
2862    GlobalMotionEstRefine(
2863                                    WARPPOINTS *const startwp,
2864                                    MACROBLOCK * const pMBs,
2865                                    const MBParam * const pParam,
2866                                    const FRAMEINFO * const current,
2867                                    const FRAMEINFO * const reference,
2868                                    const IMAGE * const pCurr,
2869                                    const IMAGE * const pRef,
2870                                    const IMAGE * const pRefH,
2871                                    const IMAGE * const pRefV,
2872                                    const IMAGE * const pRefHV)
2873    {
2874            uint8_t* GMCblock = (uint8_t*)malloc(16*pParam->edged_width);
2875            WARPPOINTS bestwp=*startwp;
2876            WARPPOINTS centerwp,currwp;
2877            int gmcminSAD=0;
2878            int gmcSAD=0;
2879            int direction;
2880    //      int mx,my;
2881    
2882    /* use many blocks... */
2883    /*              for (my = 0; my < (uint32_t)pParam->mb_height; my++)
2884                    for (mx = 0; mx < (uint32_t)pParam->mb_width; mx++)
2885                    {
2886                            const int mbnum = mx + my * pParam->mb_width;
2887                            pMBs[mbnum].mcsel=1;
2888                    }
2889    */
2890    
2891    /* or rather don't use too many blocks... */
2892    /*
2893                    for (my = 1; my < (uint32_t)MBh-1; my++)
2894                    for (mx = 1; mx < (uint32_t)MBw-1; mx++)
2895                    {
2896                            const int mbnum = mx + my * MBw;
2897                            if (MBmask[mbnum-1])
2898                                    MBmask[mbnum-1]=0;
2899                            else
2900                                    if (MBmask[mbnum-MBw])
2901                                            MBmask[mbnum-1]=0;
2902    
2903                    }
2904    */
2905                    gmcminSAD = globalSAD(&bestwp, pParam, pMBs, current, pRef, pCurr, GMCblock);
2906    
2907                    if ( (reference->coding_type == S_VOP)
2908                            && ( (reference->warp.duv[1].x != bestwp.duv[1].x)
2909                              || (reference->warp.duv[1].y != bestwp.duv[1].y)
2910                              || (reference->warp.duv[0].x != bestwp.duv[0].x)
2911                              || (reference->warp.duv[0].y != bestwp.duv[0].y)
2912                              || (reference->warp.duv[2].x != bestwp.duv[2].x)
2913                              || (reference->warp.duv[2].y != bestwp.duv[2].y) ) )
2914                    {
2915                            gmcSAD = globalSAD(&reference->warp, pParam, pMBs,
2916                                                                    current, pRef, pCurr, GMCblock);
2917    
2918                            if (gmcSAD < gmcminSAD)
2919                            {       bestwp = reference->warp;
2920                                    gmcminSAD = gmcSAD;
2921                            }
2922                    }
2923    
2924            do {
2925                    direction = 0;
2926                    centerwp = bestwp;
2927    
2928                    currwp = centerwp;
2929    
2930                    currwp.duv[0].x--;
2931                    gmcSAD = globalSAD(&currwp, pParam, pMBs, current, pRef, pCurr, GMCblock);
2932                    if (gmcSAD < gmcminSAD)
2933                    {       bestwp = currwp;
2934                            gmcminSAD = gmcSAD;
2935                            direction = 1;
2936                    }
2937                    else
2938                    {
2939                    currwp = centerwp; currwp.duv[0].x++;
2940                    gmcSAD = globalSAD(&currwp, pParam, pMBs, current, pRef, pCurr, GMCblock);
2941                    if (gmcSAD < gmcminSAD)
2942                    {       bestwp = currwp;
2943                            gmcminSAD = gmcSAD;
2944                            direction = 2;
2945                    }
2946                    }
2947                    if (direction) continue;
2948    
2949                    currwp = centerwp; currwp.duv[0].y--;
2950                    gmcSAD = globalSAD(&currwp, pParam, pMBs, current, pRef, pCurr, GMCblock);
2951                    if (gmcSAD < gmcminSAD)
2952                    {       bestwp = currwp;
2953                            gmcminSAD = gmcSAD;
2954                            direction = 4;
2955                    }
2956                    else
2957                    {
2958                    currwp = centerwp; currwp.duv[0].y++;
2959                    gmcSAD = globalSAD(&currwp, pParam, pMBs, current, pRef, pCurr, GMCblock);
2960                    if (gmcSAD < gmcminSAD)
2961                    {       bestwp = currwp;
2962                            gmcminSAD = gmcSAD;
2963                            direction = 8;
2964                    }
2965                    }
2966                    if (direction) continue;
2967    
2968                    currwp = centerwp; currwp.duv[1].x++;
2969                    gmcSAD = globalSAD(&currwp, pParam, pMBs, current, pRef, pCurr, GMCblock);
2970                    if (gmcSAD < gmcminSAD)
2971                    {       bestwp = currwp;
2972                            gmcminSAD = gmcSAD;
2973                            direction = 32;
2974                    }
2975                    currwp.duv[2].y++;
2976                    gmcSAD = globalSAD(&currwp, pParam, pMBs, current, pRef, pCurr, GMCblock);
2977                    if (gmcSAD < gmcminSAD)
2978                    {       bestwp = currwp;
2979                            gmcminSAD = gmcSAD;
2980                            direction = 1024;
2981                    }
2982    
2983                    currwp = centerwp; currwp.duv[1].x--;
2984                    gmcSAD = globalSAD(&currwp, pParam, pMBs, current, pRef, pCurr, GMCblock);
2985                    if (gmcSAD < gmcminSAD)
2986                    {       bestwp = currwp;
2987                            gmcminSAD = gmcSAD;
2988                            direction = 16;
2989                    }
2990                    else
2991                    {
2992                    currwp = centerwp; currwp.duv[1].x++;
2993                    gmcSAD = globalSAD(&currwp, pParam, pMBs, current, pRef, pCurr, GMCblock);
2994                    if (gmcSAD < gmcminSAD)
2995                    {       bestwp = currwp;
2996                            gmcminSAD = gmcSAD;
2997                            direction = 32;
2998                    }
2999                    }
3000                    if (direction) continue;
3001    
3002    
3003                    currwp = centerwp; currwp.duv[1].y--;
3004                    gmcSAD = globalSAD(&currwp, pParam, pMBs, current, pRef, pCurr, GMCblock);
3005                    if (gmcSAD < gmcminSAD)
3006                    {       bestwp = currwp;
3007                            gmcminSAD = gmcSAD;
3008                            direction = 64;
3009                    }
3010                    else
3011                    {
3012                    currwp = centerwp; currwp.duv[1].y++;
3013                    gmcSAD = globalSAD(&currwp, pParam, pMBs, current, pRef, pCurr, GMCblock);
3014                    if (gmcSAD < gmcminSAD)
3015                    {       bestwp = currwp;
3016                            gmcminSAD = gmcSAD;
3017                            direction = 128;
3018                    }
3019                    }
3020                    if (direction) continue;
3021    
3022                    currwp = centerwp; currwp.duv[2].x--;
3023                    gmcSAD = globalSAD(&currwp, pParam, pMBs, current, pRef, pCurr, GMCblock);
3024                    if (gmcSAD < gmcminSAD)
3025                    {       bestwp = currwp;
3026                            gmcminSAD = gmcSAD;
3027                            direction = 256;
3028                    }
3029                    else
3030                    {
3031                    currwp = centerwp; currwp.duv[2].x++;
3032                    gmcSAD = globalSAD(&currwp, pParam, pMBs, current, pRef, pCurr, GMCblock);
3033                    if (gmcSAD < gmcminSAD)
3034                    {       bestwp = currwp;
3035                            gmcminSAD = gmcSAD;
3036                            direction = 512;
3037                    }
3038                    }
3039                    if (direction) continue;
3040    
3041                    currwp = centerwp; currwp.duv[2].y--;
3042                    gmcSAD = globalSAD(&currwp, pParam, pMBs, current, pRef, pCurr, GMCblock);
3043                    if (gmcSAD < gmcminSAD)
3044                    {       bestwp = currwp;
3045                            gmcminSAD = gmcSAD;
3046                            direction = 1024;
3047                    }
3048                    else
3049                    {
3050                    currwp = centerwp; currwp.duv[2].y++;
3051                    gmcSAD = globalSAD(&currwp, pParam, pMBs, current, pRef, pCurr, GMCblock);
3052                    if (gmcSAD < gmcminSAD)
3053                    {       bestwp = currwp;
3054                            gmcminSAD = gmcSAD;
3055                            direction = 2048;
3056                    }
3057                    }
3058            } while (direction);
3059            free(GMCblock);
3060    
3061            *startwp = bestwp;
3062    
3063            return gmcminSAD;
3064    }
3065    
3066    int
3067    globalSAD(const WARPPOINTS *const wp,
3068                      const MBParam * const pParam,
3069                      const MACROBLOCK * const pMBs,
3070                      const FRAMEINFO * const current,
3071                      const IMAGE * const pRef,
3072                      const IMAGE * const pCurr,
3073                      uint8_t *const GMCblock)
3074    {
3075            NEW_GMC_DATA gmc_data;
3076            int iSAD, gmcSAD=0;
3077            int num=0;
3078            unsigned int mx, my;
3079    
3080            generate_GMCparameters( 3, 3, wp, pParam->width, pParam->height, &gmc_data);
3081    
3082            for (my = 0; my < (uint32_t)pParam->mb_height; my++)
3083                    for (mx = 0; mx < (uint32_t)pParam->mb_width; mx++) {
3084    
3085                    const int mbnum = mx + my * pParam->mb_width;
3086                    const int iEdgedWidth = pParam->edged_width;
3087    
3088                    if (!pMBs[mbnum].mcsel)
3089                            continue;
3090    
3091                    gmc_data.predict_16x16(&gmc_data, GMCblock,
3092                                                    pRef->y,
3093                                                    iEdgedWidth,
3094                                                    iEdgedWidth,
3095                                                    mx, my,
3096                                                    pParam->m_rounding_type);
3097    
3098                    iSAD = sad16 ( pCurr->y + 16*(my*iEdgedWidth + mx),
3099                                                      GMCblock , iEdgedWidth, 65536);
3100                    iSAD -= pMBs[mbnum].sad16;
3101    
3102                    if (iSAD<0)
3103                            gmcSAD += iSAD;
3104                    num++;
3105            }
3106            return gmcSAD;
3107    }
3108    

Legend:
Removed from v.1071  
changed lines
  Added in v.1081

No admin address has been configured
ViewVC Help
Powered by ViewVC 1.0.4