[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 3, Fri Mar 8 02:46:11 2002 UTC revision 132, Tue Apr 23 00:04:51 2002 UTC
# Line 2  Line 2 
2   *   *
3   *  Modifications:   *  Modifications:
4   *   *
5     *  22.04.2002 remove some compile warning by chenm001 <chenm001@163.com>
6     *  14.04.2002 added MotionEstimationBVOP()
7     *  02.04.2002 add EPZS(^2) as ME algorithm, use PMV_USESQUARES to choose between
8     *             EPZS and EPZS^2
9   *  08.02.2002 split up PMVfast into three routines: PMVFast, PMVFast_MainLoop   *  08.02.2002 split up PMVfast into three routines: PMVFast, PMVFast_MainLoop
10   *             PMVFast_Refine to support multiple searches with different start points   *             PMVFast_Refine to support multiple searches with different start points
11   *      07.01.2002 uv-block-based interpolation   *      07.01.2002 uv-block-based interpolation
# Line 31  Line 35 
35    
36  #include <assert.h>  #include <assert.h>
37  #include <stdio.h>  #include <stdio.h>
38    #include <stdlib.h>
39    
40  #include "../encoder.h"  #include "../encoder.h"
41  #include "../utils/mbfunctions.h"  #include "../utils/mbfunctions.h"
42  #include "../prediction/mbprediction.h"  #include "../prediction/mbprediction.h"
43  #include "../global.h"  #include "../global.h"
44  #include "../utils/timer.h"  #include "../utils/timer.h"
45    #include "motion.h"
46  #include "sad.h"  #include "sad.h"
47    
48  // very large value  // very large value
# Line 65  Line 71 
71  #define EVEN(A)         (((A)<0?(A)+1:(A)) & ~1)  #define EVEN(A)         (((A)<0?(A)+1:(A)) & ~1)
72    
73    
74  #define MIN(X, Y) ((X)<(Y)?(X):(Y))  int32_t PMVfastSearch16(
75  #define MAX(X, Y) ((X)>(Y)?(X):(Y))                                          const uint8_t * const pRef,
76  #define ABS(X) (((X)>0)?(X):-(X))                                          const uint8_t * const pRefH,
77  #define SIGN(X) (((X)>0)?1:-1)                                          const uint8_t * const pRefV,
78                                            const uint8_t * const pRefHV,
79                                            const IMAGE * const pCur,
80                                            const int x, const int y,
81                                            const uint32_t MotionFlags,
82                                            const MBParam * const pParam,
83                                            MACROBLOCK * const pMBs,
84                                            VECTOR * const currMV,
85                                            VECTOR * const currPMV);
86    
87    int32_t EPZSSearch16(
88                                            const uint8_t * const pRef,
89                                            const uint8_t * const pRefH,
90                                            const uint8_t * const pRefV,
91                                            const uint8_t * const pRefHV,
92                                            const IMAGE * const pCur,
93                                            const int x, const int y,
94                                            const uint32_t MotionFlags,
95                                            const MBParam * const pParam,
96                                            MACROBLOCK * const pMBs,
97                                            VECTOR * const currMV,
98                                            VECTOR * const currPMV);
99    
100    
101  int32_t PMVfastSearch8(  int32_t PMVfastSearch8(
# Line 79  Line 106 
106                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
107                                          const int x, const int y,                                          const int x, const int y,
108                                          const int start_x, int start_y,                                          const int start_x, int start_y,
109                                          const uint32_t iQuality,                                          const uint32_t MotionFlags,
110                                          MBParam * const pParam,                                          const MBParam * const pParam,
111                                          MACROBLOCK * const pMBs,                                          MACROBLOCK * const pMBs,
112                                          VECTOR * const currMV,                                          VECTOR * const currMV,
113                                          VECTOR * const currPMV);                                          VECTOR * const currPMV);
114    
115  int32_t PMVfastSearch16(  int32_t EPZSSearch8(
116                                          const uint8_t * const pRef,                                          const uint8_t * const pRef,
117                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
118                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
119                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
120                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
121                                          const int x, const int y,                                          const int x, const int y,
122                                          const uint32_t iQuality,                                          const int start_x, int start_y,
123                                          MBParam * const pParam,                                          const uint32_t MotionFlags,
124                                            const MBParam * const pParam,
125                                          MACROBLOCK * const pMBs,                                          MACROBLOCK * const pMBs,
126                                          VECTOR * const currMV,                                          VECTOR * const currMV,
127                                          VECTOR * const currPMV);                                          VECTOR * const currPMV);
128    
129    
130    typedef int32_t (MainSearch16Func)(
131            const uint8_t * const pRef,
132            const uint8_t * const pRefH,
133            const uint8_t * const pRefV,
134            const uint8_t * const pRefHV,
135            const uint8_t * const cur,
136            const int x, const int y,
137            int32_t startx, int32_t starty,
138            int32_t iMinSAD,
139            VECTOR * const currMV,
140            const VECTOR * const pmv,
141            const int32_t min_dx, const int32_t max_dx,
142            const int32_t min_dy, const int32_t max_dy,
143            const int32_t iEdgedWidth,
144            const int32_t iDiamondSize,
145            const int32_t iFcode,
146            const int32_t iQuant,
147            int iFound);
148    
149  /* diamond search stuff  typedef MainSearch16Func* MainSearch16FuncPtr;
    keep the the sequence in circular order (so optimization works)  
 */  
   
 typedef struct  
 {  
         int32_t dx;  
         int32_t dy;  
 }  
 DPOINT;  
   
   
 static const DPOINT diamond_small[4] =  
 {  
         {0, 1}, {1, 0}, {0, -1}, {-1, 0}  
 };  
150    
151    
152  static const DPOINT diamond_large[8] =  typedef int32_t (MainSearch8Func)(
153  {          const uint8_t * const pRef,
154          {0, 2}, {1, 1}, {2, 0}, {1, -1}, {0, -2}, {-1, -1}, {-2, 0}, {-1, 1}          const uint8_t * const pRefH,
155  };          const uint8_t * const pRefV,
156            const uint8_t * const pRefHV,
157            const uint8_t * const cur,
158            const int x, const int y,
159            int32_t startx, int32_t starty,
160            int32_t iMinSAD,
161            VECTOR * const currMV,
162            const VECTOR * const pmv,
163            const int32_t min_dx, const int32_t max_dx,
164            const int32_t min_dy, const int32_t max_dy,
165            const int32_t iEdgedWidth,
166            const int32_t iDiamondSize,
167            const int32_t iFcode,
168            const int32_t iQuant,
169            int iFound);
170    
171    typedef MainSearch8Func* MainSearch8FuncPtr;
172    
173  // mv.length table  // mv.length table
174  static const uint32_t mvtab[33] = {  static const uint32_t mvtab[33] = {
# Line 173  Line 219 
219    
220    
221    
 /* calculate the min/max range (in halfpixels)  
         relative to the _MACROBLOCK_ position  
 */  
   
 static void __inline get_range(  
                         int32_t * const min_dx, int32_t * const max_dx,  
                         int32_t * const min_dy, int32_t * const max_dy,  
                         const uint32_t x, const uint32_t y,  
                         const uint32_t block_sz,                                        // block dimension, 8 or 16  
                         const uint32_t width, const uint32_t height,  
                         const uint32_t fcode)  
 {  
         const int search_range = 32 << (fcode - 1);  
     const int high = search_range - 1;  
     const int low = -search_range;  
   
         // convert full-pixel measurements to half pixel  
         const int hp_width = 2 * width;  
         const int hp_height = 2 * height;  
         const int hp_edge = 2 * block_sz;  
         const int hp_x = 2 * (x) * block_sz;            // we need _right end_ of block, not x-coordinate  
         const int hp_y = 2 * (y) * block_sz;            // same for _bottom end_  
   
     *max_dx = MIN(high, hp_width - hp_x);  
     *max_dy = MIN(high, hp_height - hp_y);  
     *min_dx = MAX(low,  -(hp_edge + hp_x));  
     *min_dy = MAX(low,  -(hp_edge + hp_y));  
 }  
   
   
 /* getref: calculate reference image pointer  
 the decision to use interpolation h/v/hv or the normal image is  
 based on dx & dy.  
 */  
   
 static __inline const uint8_t * get_ref(  
                                 const uint8_t * const refn,  
                                 const uint8_t * const refh,  
                                 const uint8_t * const refv,  
                                 const uint8_t * const refhv,  
                                 const uint32_t x, const uint32_t y,  
                                 const uint32_t block,                                   // block dimension, 8 or 16  
                                 const int32_t dx, const int32_t dy,  
                                 const uint32_t stride)  
 {  
         switch ( ((dx&1)<<1) + (dy&1) )         // ((dx%2)?2:0)+((dy%2)?1:0)  
     {  
         case 0 : return refn + (x*block+dx/2) + (y*block+dy/2)*stride;  
     case 1 : return refv + (x*block+dx/2) + (y*block+(dy-1)/2)*stride;  
         case 2 : return refh + (x*block+(dx-1)/2) + (y*block+dy/2)*stride;  
         default :  
         case 3 : return refhv + (x*block+(dx-1)/2) + (y*block+(dy-1)/2)*stride;  
         }  
 }  
   
   
 /* This is somehow a copy of get_ref, but with MV instead of X,Y */  
   
 static __inline const uint8_t * get_ref_mv(  
                                 const uint8_t * const refn,  
                                 const uint8_t * const refh,  
                                 const uint8_t * const refv,  
                                 const uint8_t * const refhv,  
                                 const uint32_t x, const uint32_t y,  
                                 const uint32_t block,                   // block dimension, 8 or 16  
                                 const VECTOR* mv,       // measured in half-pel!  
                                 const uint32_t stride)  
 {  
         switch ( (((mv->x)&1)<<1) + ((mv->y)&1) )  
     {  
         case 0 : return refn + (x*block+(mv->x)/2) + (y*block+(mv->y)/2)*stride;  
         case 1 : return refv + (x*block+(mv->x)/2) + (y*block+((mv->y)-1)/2)*stride;  
         case 2 : return refh + (x*block+((mv->x)-1)/2) + (y*block+(mv->y)/2)*stride;  
         default :  
         case 3 : return refhv + (x*block+((mv->x)-1)/2) + (y*block+((mv->y)-1)/2)*stride;  
         }  
 }  
222    
223  #ifndef SEARCH16  #ifndef SEARCH16
224  #define SEARCH16        PMVfastSearch16  #define SEARCH16        PMVfastSearch16
225    //#define SEARCH16      FullSearch16
226    //#define SEARCH16      EPZSSearch16
227  #endif  #endif
228    
229  #ifndef SEARCH8  #ifndef SEARCH8
230  #define SEARCH8         PMVfastSearch8  #define SEARCH8         PMVfastSearch8
231    //#define SEARCH8       EPZSSearch8
232  #endif  #endif
233    
234  bool MotionEstimation(  bool MotionEstimation(
# Line 282  Line 254 
254      int32_t sad16;      int32_t sad16;
255      int32_t deviation;      int32_t deviation;
256    
257            if (sadInit)
258                    (*sadInit)();
259    
260          // note: i==horizontal, j==vertical          // note: i==horizontal, j==vertical
261      for (i = 0; i < iHcount; i++)      for (i = 0; i < iHcount; i++)
262                  for (j = 0; j < iWcount; j++)                  for (j = 0; j < iWcount; j++)
# Line 384  Line 359 
359      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \
360  }  }
361    
362    #define NOCHECK_MV16_CANDIDATE(X,Y) { \
363        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
364        iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\
365        if (iSAD < iMinSAD) \
366        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
367    }
368    
369  #define CHECK_MV16_CANDIDATE(X,Y) { \  #define CHECK_MV16_CANDIDATE(X,Y) { \
370    if ( ((X) <= max_dx) && ((X) >= min_dx) \    if ( ((X) <= max_dx) && ((X) >= min_dx) \
# Line 423  Line 404 
404    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \
405  }  }
406    
407    #define NOCHECK_MV8_CANDIDATE(X,Y) \
408      { \
409        iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
410        iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\
411        if (iSAD < iMinSAD) \
412        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
413    }
414    
415  #define CHECK_MV8_CANDIDATE(X,Y) { \  #define CHECK_MV8_CANDIDATE(X,Y) { \
416    if ( ((X) <= max_dx) && ((X) >= min_dx) \    if ( ((X) <= max_dx) && ((X) >= min_dx) \
# Line 493  Line 481 
481  }  }
482  */  */
483    
484  int32_t PMVfastSearch16_MainSearch(  int32_t Diamond16_MainSearch(
485                                          const uint8_t * const pRef,                                          const uint8_t * const pRef,
486                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
487                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
# Line 550  Line 538 
538          return iMinSAD;          return iMinSAD;
539  }  }
540    
541  int32_t PMVfastSearch16_Refine(  int32_t Square16_MainSearch(
542                                            const uint8_t * const pRef,
543                                            const uint8_t * const pRefH,
544                                            const uint8_t * const pRefV,
545                                            const uint8_t * const pRefHV,
546                                            const uint8_t * const cur,
547                                            const int x, const int y,
548                                            int32_t startx, int32_t starty,
549                                            int32_t iMinSAD,
550                                            VECTOR * const currMV,
551                                            const VECTOR * const pmv,
552                                            const int32_t min_dx, const int32_t max_dx,
553                                            const int32_t min_dy, const int32_t max_dy,
554                                            const int32_t iEdgedWidth,
555                                            const int32_t iDiamondSize,
556                                            const int32_t iFcode,
557                                            const int32_t iQuant,
558                                            int iFound)
559    {
560    /* Do a square search around given starting point, return SAD of best */
561    
562            int32_t iDirection=0;
563            int32_t iSAD;
564            VECTOR backupMV;
565            backupMV.x = startx;
566            backupMV.y = starty;
567    
568    /* It's one search with full square pattern, and new parts for all following diamonds */
569    
570    /*   new direction are extra, so 1-4 is normal diamond
571          537
572          1*2
573          648
574    */
575    
576            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
577            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
578            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
579            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
580    
581            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
582            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
583            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
584            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
585    
586    
587            if (iDirection)
588                    while (!iFound)
589                    {
590                            iFound = 1;
591                            backupMV=*currMV;
592    
593                            switch (iDirection)
594                            {
595                                    case 1:
596                                            CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);
597                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
598                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
599                                            break;
600                                    case 2:
601                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
602                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
603                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
604                                            break;
605    
606                                    case 3:
607                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
608                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
609                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
610                                            break;
611    
612                                    case 4:
613                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
614                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
615                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
616                                            break;
617    
618                                    case 5:
619                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
620                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
621                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
622                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
623                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
624                                            break;
625    
626                                    case 6:
627                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
628                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
629    
630                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
631                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
632                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
633    
634                                            break;
635    
636                                    case 7:
637                                            CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);
638                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
639                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
640                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
641                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
642                                            break;
643    
644                                    case 8:
645                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
646                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
647                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
648                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
649                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
650                                            break;
651                            default:
652                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
653                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
654                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
655                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
656    
657                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
658                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
659                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
660                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
661                                            break;
662                            }
663                    }
664            else
665                    {
666                            currMV->x = startx;
667                            currMV->y = starty;
668                    }
669            return iMinSAD;
670    }
671    
672    
673    int32_t Full16_MainSearch(
674                                            const uint8_t * const pRef,
675                                            const uint8_t * const pRefH,
676                                            const uint8_t * const pRefV,
677                                            const uint8_t * const pRefHV,
678                                            const uint8_t * const cur,
679                                            const int x, const int y,
680                                            int32_t startx, int32_t starty,
681                                            int32_t iMinSAD,
682                                            VECTOR * const currMV,
683                                            const VECTOR * const pmv,
684                                            const int32_t min_dx, const int32_t max_dx,
685                                            const int32_t min_dy, const int32_t max_dy,
686                                            const int32_t iEdgedWidth,
687                                            const int32_t iDiamondSize,
688                                            const int32_t iFcode,
689                                            const int32_t iQuant,
690                                            int iFound)
691    {
692            int32_t iSAD;
693            int32_t dx,dy;
694            VECTOR backupMV;
695            backupMV.x = startx;
696            backupMV.y = starty;
697    
698            for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
699                    for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
700                            NOCHECK_MV16_CANDIDATE(dx,dy);
701    
702            return iMinSAD;
703    }
704    
705    int32_t Full8_MainSearch(
706                                            const uint8_t * const pRef,
707                                            const uint8_t * const pRefH,
708                                            const uint8_t * const pRefV,
709                                            const uint8_t * const pRefHV,
710                                            const uint8_t * const cur,
711                                            const int x, const int y,
712                                            int32_t startx, int32_t starty,
713                                            int32_t iMinSAD,
714                                            VECTOR * const currMV,
715                                            const VECTOR * const pmv,
716                                            const int32_t min_dx, const int32_t max_dx,
717                                            const int32_t min_dy, const int32_t max_dy,
718                                            const int32_t iEdgedWidth,
719                                            const int32_t iDiamondSize,
720                                            const int32_t iFcode,
721                                            const int32_t iQuant,
722                                            int iFound)
723    {
724            int32_t iSAD;
725            int32_t dx,dy;
726            VECTOR backupMV;
727            backupMV.x = startx;
728            backupMV.y = starty;
729    
730            for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
731                    for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
732                            NOCHECK_MV8_CANDIDATE(dx,dy);
733    
734            return iMinSAD;
735    }
736    
737    
738    
739    int32_t Halfpel16_Refine(
740                                          const uint8_t * const pRef,                                          const uint8_t * const pRef,
741                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
742                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
# Line 585  Line 771 
771    
772  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)
773    
774    
775  int32_t PMVfastSearch16(  int32_t PMVfastSearch16(
776                                          const uint8_t * const pRef,                                          const uint8_t * const pRef,
777                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
# Line 593  Line 780 
780                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
781                                          const int x, const int y,                                          const int x, const int y,
782                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
783                                          MBParam * const pParam,                                          const MBParam * const pParam,
784                                          MACROBLOCK * const pMBs,                                          MACROBLOCK * const pMBs,
785                                          VECTOR * const currMV,                                          VECTOR * const currMV,
786                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
# Line 720  Line 907 
907                  iEdgedWidth, MV_MAX_ERROR);                  iEdgedWidth, MV_MAX_ERROR);
908          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;
909    
910          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,pMB->mvs[0])) && (iMinSAD < pMB->sad16) ) )          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,pMB->mvs[0])) && ((uint32_t)iMinSAD < pMB->sad16) ) )
911                  {                  {
912    
913                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
914                                  goto step10b;                          goto PMVfast16_Terminate_without_Refine;
915                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
916                                  goto step10;                          goto PMVfast16_Terminate_with_Refine;
917                  }                  }
918    
919  /*  /*
# Line 763  Line 950 
950                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
951    
952  // top right neighbour, if allowed  // top right neighbour, if allowed
953                  if (x != (iWcount-1))                  if ((uint32_t)x != (iWcount-1))
954                  {                  {
955                          if (!(MotionFlags & PMV_HALFPEL16 ))                          if (!(MotionFlags & PMV_HALFPEL16 ))
956                          {       pmv[3].x = EVEN(pmv[3].x);                          {       pmv[3].x = EVEN(pmv[3].x);
# Line 777  Line 964 
964     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.
965  */  */
966    
967          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[0]) && (iMinSAD < pMB->sad16) ) )          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[0]) && ((uint32_t)iMinSAD < pMB->sad16) ) )
968                  {                  {
969                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
970                                  goto step10b;                          goto PMVfast16_Terminate_without_Refine;
971                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
972                                  goto step10;                          goto PMVfast16_Terminate_with_Refine;
973                  }                  }
974    
975    
# Line 799  Line 986 
986          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
987    
988  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
989          iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
990                  x, y,                  x, y,
991                  currMV->x, currMV->y, iMinSAD, &newMV,                  currMV->x, currMV->y, iMinSAD, &newMV,
992                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
# Line 815  Line 1002 
1002  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1003    
1004                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0],backupMV)) )
1005                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1006                                  x, y,                                  x, y,
1007                          pmv[0].x, pmv[0].y, iMinSAD, &newMV,                          pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1008                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
# Line 828  Line 1015 
1015                  }                  }
1016    
1017                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1018                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1019                                  x, y,                                  x, y,
1020                          0, 0, iMinSAD, &newMV,                          0, 0, iMinSAD, &newMV,
1021                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
# Line 845  Line 1032 
1032          Step 10:  The motion vector is chosen according to the block corresponding to MinSAD.          Step 10:  The motion vector is chosen according to the block corresponding to MinSAD.
1033  */  */
1034    
1035  step10:  PMVfast16_Terminate_with_Refine:
1036          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
1037                  iMinSAD = PMVfastSearch16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,
1038                                  x, y,                                  x, y,
1039                                  currMV, iMinSAD,                                  currMV, iMinSAD,
1040                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
1041    
1042  step10b:  PMVfast16_Terminate_without_Refine:
1043          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - pmv[0].x;
1044          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - pmv[0].y;
1045          return iMinSAD;          return iMinSAD;
# Line 863  Line 1050 
1050    
1051    
1052    
1053  int32_t PMVfastSearch8_MainSearch(  int32_t Diamond8_MainSearch(
1054                                          const uint8_t * const pRef,                                          const uint8_t * const pRef,
1055                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1056                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
# Line 920  Line 1107 
1107          return iMinSAD;          return iMinSAD;
1108  }  }
1109    
1110  int32_t PMVfastSearch8_Refine(  int32_t Halfpel8_Refine(
1111                                          const uint8_t * const pRef,                                          const uint8_t * const pRef,
1112                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1113                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
# Line 965  Line 1152 
1152                                          const int x, const int y,                                          const int x, const int y,
1153                                          const int start_x, int start_y,                                          const int start_x, int start_y,
1154                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
1155                                          MBParam * const pParam,                                          const MBParam * const pParam,
1156                                          MACROBLOCK * const pMBs,                                          MACROBLOCK * const pMBs,
1157                                          VECTOR * const currMV,                                          VECTOR * const currMV,
1158                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
# Line 1071  Line 1258 
1258                  iEdgedWidth);                  iEdgedWidth);
1259          iMinSAD += calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y, (uint8_t)iFcode) * iQuant;          iMinSAD += calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y, (uint8_t)iFcode) * iQuant;
1260    
1261          if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,pMB->mvs[iSubBlock])) && (iMinSAD < pMB->sad8[iSubBlock]) ) )          if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,pMB->mvs[iSubBlock])) && ((uint32_t)iMinSAD < pMB->sad8[iSubBlock]) ) )
1262                  {                  {
1263                          if (MotionFlags & PMV_QUICKSTOP8)                  if (MotionFlags & PMV_QUICKSTOP16)
1264                                  goto step10_8b;                          goto PMVfast8_Terminate_without_Refine;
1265                          if (MotionFlags & PMV_EARLYSTOP8)                  if (MotionFlags & PMV_EARLYSTOP16)
1266                                  goto step10_8;                          goto PMVfast8_Terminate_with_Refine;
1267                  }                  }
1268    
1269    
1270  /*  /*
1271  Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.  Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.
1272          Also calculate (0,0) but do not subtract offset.          Also calculate (0,0) but do not subtract offset.
# Line 1129  Line 1317 
1317     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.
1318  */  */
1319    
1320          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[iSubBlock]) && (iMinSAD < pMB->sad8[iSubBlock]) ) )          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[iSubBlock]) && ((uint32_t)iMinSAD < pMB->sad8[iSubBlock]) ) )
1321                  {                  {
1322                          if (MotionFlags & PMV_QUICKSTOP8)                  if (MotionFlags & PMV_QUICKSTOP16)
1323                                  goto step10_8b;                          goto PMVfast8_Terminate_without_Refine;
1324                          if (MotionFlags & PMV_EARLYSTOP8)                  if (MotionFlags & PMV_EARLYSTOP16)
1325                                  goto step10_8;                          goto PMVfast8_Terminate_with_Refine;
1326                  }                  }
1327    
1328  /************ (Diamond Search)  **************/  /************ (Diamond Search)  **************/
# Line 1150  Line 1338 
1338          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1339    
1340  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
1341          iSAD = PMVfastSearch8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD = Diamond8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1342                  x, y,                  x, y,
1343                  currMV->x, currMV->y, iMinSAD, &newMV,                  currMV->x, currMV->y, iMinSAD, &newMV,
1344                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
# Line 1166  Line 1354 
1354  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1355    
1356                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0],backupMV)) )
1357                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1358                                  x, y,                                  x, y,
1359                          pmv[0].x, pmv[0].y, iMinSAD, &newMV,                          pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1360                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
# Line 1179  Line 1367 
1367                  }                  }
1368    
1369                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1370                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1371                                  x, y,                                  x, y,
1372                          0, 0, iMinSAD, &newMV,                          0, 0, iMinSAD, &newMV,
1373                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
# Line 1196  Line 1384 
1384           By performing an optional local half-pixel search, we can refine this result even further.           By performing an optional local half-pixel search, we can refine this result even further.
1385  */  */
1386    
1387  step10_8:  PMVfast8_Terminate_with_Refine:
1388          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
1389                  iMinSAD = PMVfastSearch8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,
1390                                  x, y,                                  x, y,
1391                                  currMV, iMinSAD,                                  currMV, iMinSAD,
1392                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
1393    
 step10_8b:  
1394    
1395    PMVfast8_Terminate_without_Refine:
1396          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - pmv[0].x;
1397          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - pmv[0].y;
1398    
1399          return iMinSAD;          return iMinSAD;
1400  }  }
1401    
1402    int32_t EPZSSearch16(
1403                                            const uint8_t * const pRef,
1404                                            const uint8_t * const pRefH,
1405                                            const uint8_t * const pRefV,
1406                                            const uint8_t * const pRefHV,
1407                                            const IMAGE * const pCur,
1408                                            const int x, const int y,
1409                                            const uint32_t MotionFlags,
1410                                            const MBParam * const pParam,
1411                                            MACROBLOCK * const pMBs,
1412                                            VECTOR * const currMV,
1413                                            VECTOR * const currPMV)
1414    {
1415        const uint32_t iWcount = pParam->mb_width;
1416        const uint32_t iHcount = pParam->mb_height;
1417            const int32_t iFcode = pParam->fixed_code;
1418            const int32_t iQuant = pParam->quant;
1419    
1420            const int32_t iWidth = pParam->width;
1421            const int32_t iHeight = pParam->height;
1422            const int32_t iEdgedWidth = pParam->edged_width;
1423    
1424            const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
1425    
1426            int32_t min_dx;
1427            int32_t max_dx;
1428            int32_t min_dy;
1429            int32_t max_dy;
1430    
1431            VECTOR newMV;
1432            VECTOR backupMV;
1433    
1434            VECTOR pmv[4];
1435            int32_t psad[8];
1436    
1437            static MACROBLOCK * oldMBs = NULL;
1438            MACROBLOCK * const pMB = pMBs + x + y * iWcount;
1439            MACROBLOCK * oldMB = NULL;
1440    
1441            static int32_t thresh2;
1442            int32_t bPredEq;
1443            int32_t iMinSAD,iSAD=9999;
1444    
1445            MainSearch16FuncPtr EPZSMainSearchPtr;
1446    
1447            if (oldMBs == NULL)
1448            {       oldMBs = (MACROBLOCK*) calloc(1,iWcount*iHcount*sizeof(MACROBLOCK));
1449                    fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));
1450            }
1451            oldMB = oldMBs + x + y * iWcount;
1452    
1453    /* Get maximum range */
1454            get_range(&min_dx, &max_dx, &min_dy, &max_dy,
1455                            x, y, 16, iWidth, iHeight, iFcode);
1456    
1457    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
1458    
1459            if (!(MotionFlags & PMV_HALFPEL16 ))
1460            { min_dx = EVEN(min_dx);
1461              max_dx = EVEN(max_dx);
1462              min_dy = EVEN(min_dy);
1463              max_dy = EVEN(max_dy);
1464            }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1465    
1466            bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
1467    
1468    /* Step 4: Calculate SAD around the Median prediction.
1469            MinSAD=SAD
1470            If Motion Vector equal to Previous frame motion vector
1471                    and MinSAD<PrevFrmSAD goto Step 10.
1472            If SAD<=256 goto Step 10.
1473    */
1474    
1475    // Prepare for main loop
1476    
1477            *currMV=pmv[0];         /* current best := median prediction */
1478            if (!(MotionFlags & PMV_HALFPEL16))
1479            {
1480                    currMV->x = EVEN(currMV->x);
1481                    currMV->y = EVEN(currMV->y);
1482            }
1483    
1484            if (currMV->x > max_dx)
1485                    currMV->x=max_dx;
1486            if (currMV->x < min_dx)
1487                    currMV->x=min_dx;
1488            if (currMV->y > max_dy)
1489                    currMV->y=max_dy;
1490            if (currMV->y < min_dy)
1491                    currMV->y=min_dy;
1492    
1493    /***************** This is predictor SET A: only median prediction ******************/
1494    
1495            iMinSAD = sad16( cur,
1496                    get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),
1497                    iEdgedWidth, MV_MAX_ERROR);
1498            iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;
1499    
1500    // thresh1 is fixed to 256
1501            if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,pMB->mvs[0])) && ((uint32_t)iMinSAD < pMB->sad16) ) )
1502                    {
1503                            if (MotionFlags & PMV_QUICKSTOP16)
1504                                    goto EPZS16_Terminate_without_Refine;
1505                            if (MotionFlags & PMV_EARLYSTOP16)
1506                                    goto EPZS16_Terminate_with_Refine;
1507                    }
1508    
1509    /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
1510    
1511    // previous frame MV
1512            CHECK_MV16_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);
1513    
1514    // set threshhold based on Min of Prediction and SAD of collocated block
1515    // CHECK_MV16 always uses iSAD for the SAD of last vector to check, so now iSAD is what we want
1516    
1517            if ((x==0) && (y==0) )
1518            {
1519                    thresh2 =  512;
1520            }
1521            else
1522            {
1523    /* T_k = 1.2 * MIN(SAD_top,SAD_left,SAD_topleft,SAD_coll) +128;   [Tourapis, 2002] */
1524    
1525                    thresh2 = MIN(psad[0],iSAD)*6/5 + 128;
1526            }
1527    
1528    // MV=(0,0) is often a good choice
1529    
1530            CHECK_MV16_ZERO;
1531    
1532    
1533    // left neighbour, if allowed
1534            if (x != 0)
1535            {
1536                    if (!(MotionFlags & PMV_HALFPEL16 ))
1537                    {       pmv[1].x = EVEN(pmv[1].x);
1538                            pmv[1].y = EVEN(pmv[1].y);
1539                    }
1540                    CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1541            }
1542    
1543    // top neighbour, if allowed
1544            if (y != 0)
1545            {
1546                    if (!(MotionFlags & PMV_HALFPEL16 ))
1547                    {       pmv[2].x = EVEN(pmv[2].x);
1548                            pmv[2].y = EVEN(pmv[2].y);
1549                    }
1550                    CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1551    
1552    // top right neighbour, if allowed
1553                    if ((uint32_t)x != (iWcount-1))
1554                    {
1555                            if (!(MotionFlags & PMV_HALFPEL16 ))
1556                            {       pmv[3].x = EVEN(pmv[3].x);
1557                                    pmv[3].y = EVEN(pmv[3].y);
1558                            }
1559                            CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);
1560                    }
1561            }
1562    
1563    /* Terminate if MinSAD <= T_2
1564       Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
1565    */
1566    
1567            if ( (iMinSAD <= thresh2)
1568                    || ( MVequal(*currMV,pMB->mvs[0]) && ((uint32_t)iMinSAD <= pMB->sad16) ) )
1569                    {
1570                            if (MotionFlags & PMV_QUICKSTOP16)
1571                                    goto EPZS16_Terminate_without_Refine;
1572                            if (MotionFlags & PMV_EARLYSTOP16)
1573                                    goto EPZS16_Terminate_with_Refine;
1574                    }
1575    
1576    /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/
1577    
1578            backupMV = pMB->mvs[0];                 // last MV
1579            backupMV.x += (pMB->mvs[0].x - oldMB->mvs[0].x );       // acceleration X
1580            backupMV.y += (pMB->mvs[0].y - oldMB->mvs[0].y );       // acceleration Y
1581    
1582            CHECK_MV16_CANDIDATE(backupMV.x,backupMV.y);
1583    
1584    // left neighbour
1585            if (x != 0)
1586                    CHECK_MV16_CANDIDATE((oldMB-1)->mvs[0].x,oldMB->mvs[0].y);
1587    
1588    // top neighbour
1589            if (y != 0)
1590                    CHECK_MV16_CANDIDATE((oldMB-iWcount)->mvs[0].x,oldMB->mvs[0].y);
1591    
1592    // right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs
1593    
1594            if ((uint32_t)x != iWcount-1)
1595                    CHECK_MV16_CANDIDATE((pMB+1)->mvs[0].x,oldMB->mvs[0].y);
1596    
1597    // bottom neighbour, dito
1598            if ((uint32_t)y != iHcount-1)
1599                    CHECK_MV16_CANDIDATE((pMB+iWcount)->mvs[0].x,oldMB->mvs[0].y);
1600    
1601    /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */
1602            if (iMinSAD <= thresh2)
1603                    {
1604                            if (MotionFlags & PMV_QUICKSTOP16)
1605                                    goto EPZS16_Terminate_without_Refine;
1606                            if (MotionFlags & PMV_EARLYSTOP16)
1607                                    goto EPZS16_Terminate_with_Refine;
1608                    }
1609    
1610    /************ (if Diamond Search)  **************/
1611    
1612            backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1613    
1614    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
1615    
1616            if (MotionFlags & PMV_USESQUARES16)
1617                    EPZSMainSearchPtr = Square16_MainSearch;
1618            else
1619                    EPZSMainSearchPtr = Diamond16_MainSearch;
1620    
1621            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1622                            x, y,
1623                            currMV->x, currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1624                            2, iFcode, iQuant, 0);
1625    
1626            if (iSAD < iMinSAD)
1627            {
1628                    *currMV = newMV;
1629                    iMinSAD = iSAD;
1630            }
1631    
1632    
1633            if (MotionFlags & PMV_EXTSEARCH16)
1634            {
1635    /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
1636    
1637                    if (!(MVequal(pmv[0],backupMV)) )
1638                    {
1639                            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1640                                    x, y,
1641                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1642                                    pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
1643                    }
1644    
1645                    if (iSAD < iMinSAD)
1646                    {
1647                            *currMV = newMV;
1648                            iMinSAD = iSAD;
1649                    }
1650    
1651                    if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1652                    {
1653                            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1654                                    x, y,
1655                            0, 0, iMinSAD, &newMV,
1656                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, /*iDiamondSize*/ 2, iFcode, iQuant, 0);
1657    
1658                            if (iSAD < iMinSAD)
1659                            {
1660                                    *currMV = newMV;
1661                                    iMinSAD = iSAD;
1662                            }
1663                    }
1664            }
1665    
1666    /***************        Choose best MV found     **************/
1667    
1668    EPZS16_Terminate_with_Refine:
1669            if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
1670                    iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,
1671                                    x, y,
1672                                    currMV, iMinSAD,
1673                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
1674    
1675    EPZS16_Terminate_without_Refine:
1676    
1677            *oldMB = *pMB;
1678    
1679            currPMV->x = currMV->x - pmv[0].x;
1680            currPMV->y = currMV->y - pmv[0].y;
1681            return iMinSAD;
1682    }
1683    
1684    
1685    int32_t EPZSSearch8(
1686                                            const uint8_t * const pRef,
1687                                            const uint8_t * const pRefH,
1688                                            const uint8_t * const pRefV,
1689                                            const uint8_t * const pRefHV,
1690                                            const IMAGE * const pCur,
1691                                            const int x, const int y,
1692                                            const int start_x, const int start_y,
1693                                            const uint32_t MotionFlags,
1694                                            const MBParam * const pParam,
1695                                            MACROBLOCK * const pMBs,
1696                                            VECTOR * const currMV,
1697                                            VECTOR * const currPMV)
1698    {
1699        const uint32_t iWcount = pParam->mb_width;
1700            const int32_t iFcode = pParam->fixed_code;
1701            const int32_t iQuant = pParam->quant;
1702    
1703            const int32_t iWidth = pParam->width;
1704            const int32_t iHeight = pParam->height;
1705            const int32_t iEdgedWidth = pParam->edged_width;
1706    
1707            const uint8_t * cur = pCur->y + x*8 + y*8*iEdgedWidth;
1708    
1709            int32_t iDiamondSize=1;
1710    
1711            int32_t min_dx;
1712            int32_t max_dx;
1713            int32_t min_dy;
1714            int32_t max_dy;
1715    
1716            VECTOR newMV;
1717            VECTOR backupMV;
1718    
1719            VECTOR pmv[4];
1720            int32_t psad[8];
1721    
1722            const   int32_t iSubBlock = ((y&1)<<1) + (x&1);
1723    
1724            MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1725    
1726            int32_t bPredEq;
1727            int32_t iMinSAD,iSAD=9999;
1728    
1729            MainSearch8FuncPtr EPZSMainSearchPtr;
1730    
1731    /* Get maximum range */
1732            get_range(&min_dx, &max_dx, &min_dy, &max_dy,
1733                            x, y, 8, iWidth, iHeight, iFcode);
1734    
1735    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
1736    
1737            if (!(MotionFlags & PMV_HALFPEL8 ))
1738            { min_dx = EVEN(min_dx);
1739              max_dx = EVEN(max_dx);
1740              min_dy = EVEN(min_dy);
1741              max_dy = EVEN(max_dy);
1742            }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1743    
1744            bPredEq  = get_pmvdata(pMBs, x>>1, y>>1, iWcount, iSubBlock, pmv, psad);
1745    
1746    
1747    /* Step 4: Calculate SAD around the Median prediction.
1748            MinSAD=SAD
1749            If Motion Vector equal to Previous frame motion vector
1750                    and MinSAD<PrevFrmSAD goto Step 10.
1751            If SAD<=256 goto Step 10.
1752    */
1753    
1754    // Prepare for main loop
1755    
1756    
1757            if (!(MotionFlags & PMV_HALFPEL8))
1758            {
1759                    currMV->x = EVEN(currMV->x);
1760                    currMV->y = EVEN(currMV->y);
1761            }
1762    
1763            if (currMV->x > max_dx)
1764                    currMV->x=max_dx;
1765            if (currMV->x < min_dx)
1766                    currMV->x=min_dx;
1767            if (currMV->y > max_dy)
1768                    currMV->y=max_dy;
1769            if (currMV->y < min_dy)
1770                    currMV->y=min_dy;
1771    
1772    /***************** This is predictor SET A: only median prediction ******************/
1773    
1774    
1775            iMinSAD = sad8( cur,
1776                    get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),
1777                    iEdgedWidth);
1778            iMinSAD += calc_delta_8(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;
1779    
1780    
1781    // thresh1 is fixed to 256
1782            if (iMinSAD < 256/4 )
1783                    {
1784                            if (MotionFlags & PMV_QUICKSTOP8)
1785                                    goto EPZS8_Terminate_without_Refine;
1786                            if (MotionFlags & PMV_EARLYSTOP8)
1787                                    goto EPZS8_Terminate_with_Refine;
1788                    }
1789    
1790    /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
1791    
1792    // previous frame MV
1793            CHECK_MV8_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);
1794    
1795    // MV=(0,0) is often a good choice
1796    
1797            CHECK_MV8_ZERO;
1798    
1799    /* Terminate if MinSAD <= T_2
1800       Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
1801    */
1802    
1803            if (iMinSAD < 512/4)    /* T_2 == 512/4 hardcoded */
1804                    {
1805                            if (MotionFlags & PMV_QUICKSTOP8)
1806                                    goto EPZS8_Terminate_without_Refine;
1807                            if (MotionFlags & PMV_EARLYSTOP8)
1808                                    goto EPZS8_Terminate_with_Refine;
1809                    }
1810    
1811    /************ (if Diamond Search)  **************/
1812    
1813            backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1814    
1815            if (!(MotionFlags & PMV_HALFPELDIAMOND8))
1816                    iDiamondSize *= 2;
1817    
1818    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
1819    
1820    //      if (MotionFlags & PMV_USESQUARES8)
1821    //              EPZSMainSearchPtr = Square8_MainSearch;
1822    //      else
1823                    EPZSMainSearchPtr = Diamond8_MainSearch;
1824    
1825            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1826                    x, y,
1827                    currMV->x, currMV->y, iMinSAD, &newMV,
1828                    pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1829                    iDiamondSize, iFcode, iQuant, 00);
1830    
1831    
1832            if (iSAD < iMinSAD)
1833            {
1834                    *currMV = newMV;
1835                    iMinSAD = iSAD;
1836            }
1837    
1838            if (MotionFlags & PMV_EXTSEARCH8)
1839            {
1840    /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
1841    
1842                    if (!(MVequal(pmv[0],backupMV)) )
1843                    {
1844                            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1845                                    x, y,
1846                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1847                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);
1848    
1849                            if (iSAD < iMinSAD)
1850                            {
1851                                    *currMV = newMV;
1852                                    iMinSAD = iSAD;
1853                            }
1854                    }
1855    
1856                    if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1857                    {
1858                            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1859                                    x, y,
1860                            0, 0, iMinSAD, &newMV,
1861                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);
1862    
1863                            if (iSAD < iMinSAD)
1864                            {
1865                                    *currMV = newMV;
1866                                    iMinSAD = iSAD;
1867                            }
1868                    }
1869            }
1870    
1871    /***************        Choose best MV found     **************/
1872    
1873    EPZS8_Terminate_with_Refine:
1874            if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
1875                    iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,
1876                                    x, y,
1877                                    currMV, iMinSAD,
1878                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
1879    
1880    EPZS8_Terminate_without_Refine:
1881    
1882            currPMV->x = currMV->x - pmv[0].x;
1883            currPMV->y = currMV->y - pmv[0].y;
1884            return iMinSAD;
1885    }
1886    
1887    
1888    
1889    
1890    
1891    /* ***********************************************************
1892            bvop motion estimation
1893    // TODO: need to incorporate prediction here (eg. sad += calc_delta_16)
1894    ***************************************************************/
1895    
1896    /*
1897    void MotionEstimationBVOP(
1898                            MBParam * const pParam,
1899                            FRAMEINFO * const frame,
1900    
1901                            // forward (past) reference
1902                            const MACROBLOCK * const f_mbs,
1903                        const IMAGE * const f_ref,
1904                            const IMAGE * const f_refH,
1905                        const IMAGE * const f_refV,
1906                            const IMAGE * const f_refHV,
1907                            // backward (future) reference
1908                            const MACROBLOCK * const b_mbs,
1909                        const IMAGE * const b_ref,
1910                            const IMAGE * const b_refH,
1911                        const IMAGE * const b_refV,
1912                            const IMAGE * const b_refHV)
1913    {
1914        const uint32_t mb_width = pParam->mb_width;
1915        const uint32_t mb_height = pParam->mb_height;
1916            const int32_t edged_width = pParam->edged_width;
1917    
1918            int32_t i,j;
1919    
1920            int32_t f_sad16;
1921            int32_t b_sad16;
1922            int32_t i_sad16;
1923            int32_t d_sad16;
1924            int32_t best_sad;
1925    
1926            VECTOR pmv_dontcare;
1927    
1928            // note: i==horizontal, j==vertical
1929        for (j = 0; j < mb_height; j++)
1930            {
1931                    for (i = 0; i < mb_width; i++)
1932                    {
1933                            MACROBLOCK *mb = &frame->mbs[i + j*mb_width];
1934                            const MACROBLOCK *f_mb = &f_mbs[i + j*mb_width];
1935                            const MACROBLOCK *b_mb = &b_mbs[i + j*mb_width];
1936    
1937                            if (b_mb->mode == MODE_INTER
1938                                    && b_mb->cbp == 0
1939                                    && b_mb->mvs[0].x == 0
1940                                    && b_mb->mvs[0].y == 0)
1941                            {
1942                                    mb->mode = MB_IGNORE;
1943                                    mb->mvs[0].x = 0;
1944                                    mb->mvs[0].y = 0;
1945                                    mb->b_mvs[0].x = 0;
1946                                    mb->b_mvs[0].y = 0;
1947                                    continue;
1948                            }
1949    
1950    
1951                            // forward search
1952                            f_sad16 = SEARCH16(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
1953                                                    &frame->image,
1954                                                    i, j,
1955                                                    frame->motion_flags,  frame->quant, frame->fcode,
1956                                                    pParam,
1957                                                    f_mbs,
1958                                                    &mb->mvs[0], &pmv_dontcare);    // ignore pmv
1959    
1960                            // backward search
1961                            b_sad16 = SEARCH16(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
1962                                                    &frame->image,
1963                                                    i, j,
1964                                                    frame->motion_flags,  frame->quant, frame->bcode,
1965                                                    pParam,
1966                                                    b_mbs,
1967                                                    &mb->b_mvs[0], &pmv_dontcare);  // ignore pmv
1968    
1969                            // interpolate search (simple, but effective)
1970                            i_sad16 = sad16bi_c(
1971                                            frame->image.y + i*16 + j*16*edged_width,
1972                                            get_ref(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
1973                                                    i, j, 16, mb->mvs[0].x, mb->mvs[0].y, edged_width),
1974                                            get_ref(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
1975                                                    i, j, 16, mb->b_mvs[0].x, mb->b_mvs[0].x, edged_width),
1976                                            edged_width);
1977    
1978                            // TODO: direct search
1979                            // predictor + range of [-32,32]
1980                            d_sad16 = 65535;
1981    
1982    
1983                            if (f_sad16 < b_sad16)
1984                            {
1985                                    best_sad = f_sad16;
1986                                    mb->mode = MB_FORWARD;
1987                            }
1988                            else
1989                            {
1990                                    best_sad = b_sad16;
1991                                    mb->mode = MB_BACKWARD;
1992                            }
1993    
1994                            if (i_sad16 < best_sad)
1995                            {
1996                                    best_sad = i_sad16;
1997                                    mb->mode = MB_INTERPOLATE;
1998                            }
1999    
2000                            if (d_sad16 < best_sad)
2001                            {
2002                                    best_sad = d_sad16;
2003                                    mb->mode = MB_DIRECT;
2004                            }
2005    
2006                    }
2007            }
2008    }
2009    
2010    */

Legend:
Removed from v.3  
changed lines
  Added in v.132

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