[svn] / trunk / xvidcore / src / motion / motion_est.c Repository:
ViewVC logotype

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

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

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