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

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

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

revision 768, Thu Jan 9 11:36:33 2003 UTC revision 769, Sat Jan 11 14:59:24 2003 UTC
# Line 32  Line 32 
32  #include <stdio.h>  #include <stdio.h>
33  #include <stdlib.h>  #include <stdlib.h>
34  #include <string.h>     // memcpy  #include <string.h>     // memcpy
35    #include <math.h>       // lrint
36    
37  #include "../encoder.h"  #include "../encoder.h"
38  #include "../utils/mbfunctions.h"  #include "../utils/mbfunctions.h"
# Line 752  Line 753 
753          Data.iFcode = current->fcode;          Data.iFcode = current->fcode;
754          Data.rounding = pParam->m_rounding_type;          Data.rounding = pParam->m_rounding_type;
755          Data.qpel = pParam->m_quarterpel;          Data.qpel = pParam->m_quarterpel;
756          Data.chroma = current->global_flags & XVID_ME_COLOUR;          Data.chroma = current->global_flags & ( PMV_CHROMA16 | PMV_CHROMA8 );
757          Data.rrv = current->global_flags & XVID_REDUCED;          Data.rrv = current->global_flags & XVID_REDUCED;
758    
759          if ((current->global_flags & XVID_REDUCED)) {          if ((current->global_flags & XVID_REDUCED)) {
# Line 801  Line 802 
802    
803  //initial skip decision  //initial skip decision
804  /* no early skip for GMC (global vector = skip vector is unknown!)      */  /* no early skip for GMC (global vector = skip vector is unknown!)      */
805                          if (current->coding_type == P_VOP)      { /* no fast SKIP for S(GMC)-VOPs */                          if (!(current->global_flags & XVID_GMC))        { /* no fast SKIP for S(GMC)-VOPs */
806                                  if (pMB->dquant == NO_CHANGE && sad00 < pMB->quant * INITIAL_SKIP_THRESH * (Data.rrv ? 4:1) )                                  if (pMB->dquant == NO_CHANGE && sad00 < pMB->quant * INITIAL_SKIP_THRESH * (Data.rrv ? 4:1) )
807                                          if (Data.chroma || SkipDecisionP(pCurrent, pRef, x, y, iEdgedWidth/2, pMB->quant, Data.rrv)) {                                          if (Data.chroma || SkipDecisionP(pCurrent, pRef, x, y, iEdgedWidth/2, pMB->quant, Data.rrv)) {
808                                                  SkipMacroblockP(pMB, sad00);                                                  SkipMacroblockP(pMB, sad00);
# Line 815  Line 816 
816                                                  current->global_flags & XVID_INTER4V, pMB);                                                  current->global_flags & XVID_INTER4V, pMB);
817    
818  /* final skip decision, a.k.a. "the vector you found, really that good?" */  /* final skip decision, a.k.a. "the vector you found, really that good?" */
819                          if (current->coding_type == P_VOP)      {                          if (!(current->global_flags & XVID_GMC))        {
820                                  if ( (pMB->dquant == NO_CHANGE) && (sad00 < pMB->quant * MAX_SAD00_FOR_SKIP)                                  if ( (pMB->dquant == NO_CHANGE) && (sad00 < pMB->quant * MAX_SAD00_FOR_SKIP)
821                                          && ((100*pMB->sad16)/(sad00+1) > FINAL_SKIP_THRESH * (Data.rrv ? 4:1)) )                                          && ((100*pMB->sad16)/(sad00+1) > FINAL_SKIP_THRESH * (Data.rrv ? 4:1)) )
822                                          if (Data.chroma || SkipDecisionP(pCurrent, pRef, x, y, iEdgedWidth/2, pMB->quant, Data.rrv)) {                                          if (Data.chroma || SkipDecisionP(pCurrent, pRef, x, y, iEdgedWidth/2, pMB->quant, Data.rrv)) {
# Line 855  Line 856 
856                  }                  }
857          }          }
858    
859          if (current->coding_type == S_VOP)      /* first GMC step only for S(GMC)-VOPs */          if (current->global_flags & XVID_GMC )  /* first GMC step only for S(GMC)-VOPs */
860                  current->GMC_MV = GlobalMotionEst( pMBs, pParam, current->fcode );          {
861          else                  current->warp = GlobalMotionEst( pMBs, pParam, current, reference, pRefH, pRefV, pRefHV);
862                  current->GMC_MV = zeroMV;          }
863    
864          return 0;          return 0;
865  }  }
# Line 1913  Line 1914 
1914    
1915  }  }
1916    
1917  static void  
1918  CheckGMC(int x, int y, const int dir, int * iDirection,  static WARPPOINTS
1919                  const MACROBLOCK * const pMBs, uint32_t * bestcount, VECTOR * GMC,  GlobalMotionEst(const MACROBLOCK * const pMBs,
1920                  const MBParam * const pParam)                                  const MBParam * const pParam,
1921                                    const FRAMEINFO * const current,
1922                                    const FRAMEINFO * const reference,
1923                                    const IMAGE * const pRefH,
1924                                    const IMAGE * const pRefV,
1925                                    const IMAGE * const pRefHV      )
1926  {  {
         uint32_t mx, my, a, count = 0;  
1927    
1928          for (my = 1; my < pParam->mb_height-1; my++)          const int deltax=8;             // upper bound for difference between a MV and it's neighbour MVs
1929                  for (mx = 1; mx < pParam->mb_width-1; mx++) {          const int deltay=8;
1930                          VECTOR mv;          const int grad=512;             // lower bound for deviation in MB
1931                          const MACROBLOCK *pMB = &pMBs[mx + my * pParam->mb_width];  
1932                          if (pMB->mode == MODE_INTRA || pMB->mode == MODE_NOT_CODED) continue;          WARPPOINTS gmc;
1933                          mv = pMB->mvs[0];  
1934                          a = ABS(mv.x - x) + ABS(mv.y - y);          uint32_t mx, my;
                         if (a < 6) count += 6 - a;  
                 }  
1935    
1936          if (count > *bestcount) {          int MBh = pParam->mb_height;
1937                  *bestcount = count;          int MBw = pParam->mb_width;
1938                  *iDirection = dir;  
1939                  GMC->x = x; GMC->y = y;          int *MBmask= calloc(MBh*MBw,sizeof(int));
1940            double DtimesF[4] = { 0.,0., 0., 0. };
1941            double sol[4] = { 0., 0., 0., 0. };
1942            double a,b,c,n,denom;
1943            double meanx,meany;
1944            int num,oldnum;
1945    
1946            if (!MBmask) { fprintf(stderr,"Mem error\n"); return gmc;}
1947    
1948    // filter mask of all blocks
1949    
1950            for (my = 1; my < MBh-1; my++)
1951            for (mx = 1; mx < MBw-1; mx++)
1952            {
1953                    const int mbnum = mx + my * MBw;
1954                    const MACROBLOCK *pMB = &pMBs[mbnum];
1955                    const VECTOR mv = pMB->mvs[0];
1956    
1957                    if (pMB->mode == MODE_INTRA || pMB->mode == MODE_NOT_CODED)
1958                            continue;
1959    
1960                    if ( ( (ABS(mv.x -   (pMB-1)->mvs[0].x) < deltax) && (ABS(mv.y -   (pMB-1)->mvs[0].y) < deltay) )
1961                    &&   ( (ABS(mv.x -   (pMB+1)->mvs[0].x) < deltax) && (ABS(mv.y -   (pMB+1)->mvs[0].y) < deltay) )
1962                    &&   ( (ABS(mv.x - (pMB-MBw)->mvs[0].x) < deltax) && (ABS(mv.y - (pMB-MBw)->mvs[0].y) < deltay) )
1963                    &&   ( (ABS(mv.x - (pMB+MBw)->mvs[0].x) < deltax) && (ABS(mv.y - (pMB+MBw)->mvs[0].y) < deltay) ) )
1964                            MBmask[mbnum]=1;
1965          }          }
1966    
1967            for (my = 1; my < MBh-1; my++)
1968            for (mx = 1; mx < MBw-1; mx++)
1969            {
1970                    const uint8_t *const pCur = current->image.y + 16*my*pParam->edged_width + 16*mx;
1971    
1972                    const int mbnum = mx + my * MBw;
1973                    if (!MBmask[mbnum])
1974                            continue;
1975    
1976                    if (sad16 ( pCur, pCur+1 , pParam->edged_width, 65536) <= grad )
1977                            MBmask[mbnum] = 0;
1978                    if (sad16 ( pCur, pCur+pParam->edged_width, pParam->edged_width, 65536) <= grad )
1979                            MBmask[mbnum] = 0;
1980    
1981  }  }
1982    
1983            emms();
1984    
1985  static VECTOR          do {            /* until convergence */
 GlobalMotionEst(const MACROBLOCK * const pMBs, const MBParam * const pParam, const uint32_t iFcode)  
 {  
1986    
1987          uint32_t count, bestcount = 0;          a = b = c = n = 0;
1988          int x, y;          DtimesF[0] = DtimesF[1] = DtimesF[2] = DtimesF[3] = 0.;
1989          VECTOR gmc = {0,0};          for (my = 0; my < MBh; my++)
1990          int step, min_x, max_x, min_y, max_y;                  for (mx = 0; mx < MBw; mx++)
1991          uint32_t mx, my;                  {
1992          int iDirection, bDirection;                          const int mbnum = mx + my * MBw;
1993                            const MACROBLOCK *pMB = &pMBs[mbnum];
1994                            const VECTOR mv = pMB->mvs[0];
1995    
1996          min_x = min_y = -32<<iFcode;                          if (!MBmask[mbnum])
1997          max_x = max_y = 32<<iFcode;                                  continue;
1998    
1999  //step1: let's find a rough camera panning                          n++;
2000          for (step = 32; step >= 2; step /= 2) {                          a += 16*mx+8;
2001                  bestcount = 0;                          b += 16*my+8;
2002                  for (y = min_y; y <= max_y; y += step)                          c += (16*mx+8)*(16*mx+8)+(16*my+8)*(16*my+8);
2003                          for (x = min_x ; x <= max_x; x += step) {  
2004                                  count = 0;                          DtimesF[0] += (double)mv.x;
2005                                  //for all macroblocks                          DtimesF[1] += (double)mv.x*(16*mx+8) + (double)mv.y*(16*my+8);
2006                                  for (my = 1; my < pParam->mb_height-1; my++)                          DtimesF[2] += (double)mv.x*(16*my+8) - (double)mv.y*(16*mx+8);
2007                                          for (mx = 1; mx < pParam->mb_width-1; mx++) {                          DtimesF[3] += (double)mv.y;
2008                                                  const MACROBLOCK *pMB = &pMBs[mx + my * pParam->mb_width];                  }
2009                                                  VECTOR mv;  
2010            denom = a*a+b*b-c*n;
2011    
2012    /* Solve the system:     sol = (D'*E*D)^{-1} D'*E*F   */
2013    /* D'*E*F has been calculated in the same loop as matrix */
2014    
2015            sol[0] = -c*DtimesF[0] + a*DtimesF[1] + b*DtimesF[2];
2016            sol[1] =  a*DtimesF[0] - n*DtimesF[1]                + b*DtimesF[3];
2017            sol[2] =  b*DtimesF[0]                - n*DtimesF[2] - a*DtimesF[3];
2018            sol[3] =                 b*DtimesF[1] - a*DtimesF[2] - c*DtimesF[3];
2019    
2020            sol[0] /= denom;
2021            sol[1] /= denom;
2022            sol[2] /= denom;
2023            sol[3] /= denom;
2024    
2025            meanx = meany = 0.;
2026            oldnum = 0;
2027            for (my = 0; my < MBh; my++)
2028                    for (mx = 0; mx < MBw; mx++)
2029                    {
2030                            const int mbnum = mx + my * MBw;
2031                            const MACROBLOCK *pMB = &pMBs[mbnum];
2032                            const VECTOR mv = pMB->mvs[0];
2033    
2034                                                  if (pMB->mode == MODE_INTRA || pMB->mode == MODE_NOT_CODED)                          if (!MBmask[mbnum])
2035                                                          continue;                                                          continue;
2036    
2037                                                  mv = pMB->mvs[0];                          oldnum++;
2038                                                  if ( ABS(mv.x - x) <= step && ABS(mv.y - y) <= step )   /* GMC translation is always halfpel-res */                          meanx += ABS(( sol[0] + (16*mx+8)*sol[1] + (16*my+8)*sol[2] ) - mv.x );
2039                                                          count++;                          meany += ABS(( sol[3] + (16*my+8)*sol[1] - (16*mx+8)*sol[2] ) - mv.y );
2040                                          }  
                                 if (count >= bestcount) { bestcount = count; gmc.x = x; gmc.y = y; }  
2041                          }                          }
2042                  min_x = gmc.x - step;  
2043                  max_x = gmc.x + step;          if (2*meanx > oldnum)   /* mittlere Abweichung von Ebene */
2044                  min_y = gmc.y - step;                  meanx /= oldnum;
2045                  max_y = gmc.y + step;          else
2046                    meanx = 0.5;
2047            if (2*meany > oldnum)
2048                    meany /= oldnum;
2049            else
2050                    meanx = 0.5;
2051    
2052    //      fprintf(stderr,"meanx = %8.5f  meany = %8.5f   %d\n",meanx,meany, oldnum);
2053    
2054            num = 0;
2055            for (my = 0; my < MBh; my++)
2056                    for (mx = 0; mx < MBw; mx++)
2057                    {
2058                            const int mbnum = mx + my * MBw;
2059                            const MACROBLOCK *pMB = &pMBs[mbnum];
2060                            const VECTOR mv = pMB->mvs[0];
2061    
2062                            if (!MBmask[mbnum])
2063                                    continue;
2064    
2065                            if  ( ( ABS(( sol[0] + (16*mx+8)*sol[1] + (16*my+8)*sol[2] ) - mv.x ) > meanx )
2066                               || ( ABS(( sol[3] + (16*my+8)*sol[1] - (16*mx+8)*sol[2] ) - mv.y ) > meany ) )
2067                                    MBmask[mbnum]=0;
2068                            else
2069                                    num++;
2070          }          }
2071    
2072          if (bestcount < (pParam->mb_height-2)*(pParam->mb_width-2)/10)          } while ( (oldnum != num) && (num>=4) );
                 gmc.x = gmc.y = 0; //no camara pan, no GMC  
2073    
2074  // step2: let's refine camera panning using gradiend-descent approach          if (num < 4)
2075  // TODO: more warping points may be evaluated here (like in interpolate mode search - two vectors in one diamond)          {
2076          bestcount = 0;                  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;
2077          CheckGMC(gmc.x, gmc.y, 255, &iDirection, pMBs, &bestcount, &gmc, pParam);          } else {
         do {  
                 x = gmc.x; y = gmc.y;  
                 bDirection = iDirection; iDirection = 0;  
                 if (bDirection & 1) CheckGMC(x - 1, y, 1+4+8, &iDirection, pMBs, &bestcount, &gmc, pParam);  
                 if (bDirection & 2) CheckGMC(x + 1, y, 2+4+8, &iDirection, pMBs, &bestcount, &gmc, pParam);  
                 if (bDirection & 4) CheckGMC(x, y - 1, 1+2+4, &iDirection, pMBs, &bestcount, &gmc, pParam);  
                 if (bDirection & 8) CheckGMC(x, y + 1, 1+2+8, &iDirection, pMBs, &bestcount, &gmc, pParam);  
2078    
2079          } while (iDirection);                  gmc.duv[0].x=(int)(sol[0]+0.5);
2080                    gmc.duv[0].y=(int)(sol[3]+0.5);
2081    
2082          if (pParam->m_quarterpel) {                  gmc.duv[1].x=(int)(sol[1]*pParam->width+0.5);
2083                  gmc.x *= 2;                  gmc.duv[1].y=(int)(-sol[2]*pParam->width+0.5);
2084                  gmc.y *= 2;     /* we store the halfpel value as pseudo-qpel to make comparison easier */  
2085                    gmc.duv[2].x=0;
2086                    gmc.duv[2].y=0;
2087          }          }
2088    //      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);
2089    
2090            free(MBmask);
2091    
2092          return gmc;          return gmc;
2093  }  }

Legend:
Removed from v.768  
changed lines
  Added in v.769

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