[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 78, Thu Mar 28 20:57:25 2002 UTC revision 115, Thu Apr 11 10:18:40 2002 UTC
# Line 2  Line 2 
2   *   *
3   *  Modifications:   *  Modifications:
4   *   *
5     *  02.04.2002 add EPZS(^2) as ME algorithm, use PMV_USESQUARES to choose between
6     *             EPZS and EPZS^2
7   *  08.02.2002 split up PMVfast into three routines: PMVFast, PMVFast_MainLoop   *  08.02.2002 split up PMVfast into three routines: PMVFast, PMVFast_MainLoop
8   *             PMVFast_Refine to support multiple searches with different start points   *             PMVFast_Refine to support multiple searches with different start points
9   *  07.01.2002 uv-block-based interpolation   *  07.01.2002 uv-block-based interpolation
# Line 31  Line 33 
33    
34  #include <assert.h>  #include <assert.h>
35  #include <stdio.h>  #include <stdio.h>
36    #include <stdlib.h>
37    
38  #include "../encoder.h"  #include "../encoder.h"
39  #include "../utils/mbfunctions.h"  #include "../utils/mbfunctions.h"
# Line 70  Line 73 
73  #define ABS(X)    (((X)>0)?(X):-(X))  #define ABS(X)    (((X)>0)?(X):-(X))
74  #define SIGN(X)   (((X)>0)?1:-1)  #define SIGN(X)   (((X)>0)?1:-1)
75    
76    int32_t PMVfastSearch16(
 int32_t PMVfastSearch8(  
77          const uint8_t * const pRef,          const uint8_t * const pRef,
78          const uint8_t * const pRefH,          const uint8_t * const pRefH,
79          const uint8_t * const pRefV,          const uint8_t * const pRefV,
80          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
81          const IMAGE * const pCur,          const IMAGE * const pCur,
82          const int x, const int y,          const int x, const int y,
83          const int start_x, int start_y,                                          const uint32_t MotionFlags,
84          const uint32_t iQuality,                                          const MBParam * const pParam,
         MBParam * const pParam,  
85          MACROBLOCK * const pMBs,          MACROBLOCK * const pMBs,
86          VECTOR * const currMV,          VECTOR * const currMV,
87          VECTOR * const currPMV);          VECTOR * const currPMV);
88    
89  int32_t PMVfastSearch16(  int32_t EPZSSearch16(
90          const uint8_t * const pRef,          const uint8_t * const pRef,
91          const uint8_t * const pRefH,          const uint8_t * const pRefH,
92          const uint8_t * const pRefV,          const uint8_t * const pRefV,
93          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
94          const IMAGE * const pCur,          const IMAGE * const pCur,
95          const int x, const int y,          const int x, const int y,
96          const uint32_t iQuality,                                          const uint32_t MotionFlags,
97          MBParam * const pParam,                                          const MBParam * const pParam,
98          MACROBLOCK * const pMBs,          MACROBLOCK * const pMBs,
99          VECTOR * const currMV,          VECTOR * const currMV,
100          VECTOR * const currPMV);          VECTOR * const currPMV);
101    
102    
103    int32_t PMVfastSearch8(
104                                            const uint8_t * const pRef,
105                                            const uint8_t * const pRefH,
106                                            const uint8_t * const pRefV,
107                                            const uint8_t * const pRefHV,
108                                            const IMAGE * const pCur,
109                                            const int x, const int y,
110                                            const int start_x, int start_y,
111                                            const uint32_t MotionFlags,
112                                            const MBParam * const pParam,
113                                            MACROBLOCK * const pMBs,
114                                            VECTOR * const currMV,
115                                            VECTOR * const currPMV);
116    
117  /*  int32_t EPZSSearch8(
118   * diamond search stuff                                          const uint8_t * const pRef,
119   * keep the the sequence in circular order (so optimization works)                                          const uint8_t * const pRefH,
120   */                                          const uint8_t * const pRefV,
121                                            const uint8_t * const pRefHV,
122                                            const IMAGE * const pCur,
123                                            const int x, const int y,
124                                            const int start_x, int start_y,
125                                            const uint32_t MotionFlags,
126                                            const MBParam * const pParam,
127                                            MACROBLOCK * const pMBs,
128                                            VECTOR * const currMV,
129                                            VECTOR * const currPMV);
130    
 typedef struct  
 {  
         int32_t dx;  
         int32_t dy;  
 }  
 DPOINT;  
131    
132    typedef int32_t (MainSearch16Func)(
133            const uint8_t * const pRef,
134            const uint8_t * const pRefH,
135            const uint8_t * const pRefV,
136            const uint8_t * const pRefHV,
137            const uint8_t * const cur,
138            const int x, const int y,
139            int32_t startx, int32_t starty,
140            int32_t iMinSAD,
141            VECTOR * const currMV,
142            const VECTOR * const pmv,
143            const int32_t min_dx, const int32_t max_dx,
144            const int32_t min_dy, const int32_t max_dy,
145            const int32_t iEdgedWidth,
146            const int32_t iDiamondSize,
147            const int32_t iFcode,
148            const int32_t iQuant,
149            int iFound);
150    
151  static const DPOINT diamond_small[4] =  typedef MainSearch16Func* MainSearch16FuncPtr;
 {  
         {0, 1}, {1, 0}, {0, -1}, {-1, 0}  
 };  
152    
153    
154  static const DPOINT diamond_large[8] =  typedef int32_t (MainSearch8Func)(
155  {          const uint8_t * const pRef,
156          {0, 2}, {1, 1}, {2, 0}, {1, -1}, {0, -2}, {-1, -1}, {-2, 0}, {-1, 1}          const uint8_t * const pRefH,
157  };          const uint8_t * const pRefV,
158            const uint8_t * const pRefHV,
159            const uint8_t * const cur,
160            const int x, const int y,
161            int32_t startx, int32_t starty,
162            int32_t iMinSAD,
163            VECTOR * const currMV,
164            const VECTOR * const pmv,
165            const int32_t min_dx, const int32_t max_dx,
166            const int32_t min_dy, const int32_t max_dy,
167            const int32_t iEdgedWidth,
168            const int32_t iDiamondSize,
169            const int32_t iFcode,
170            const int32_t iQuant,
171            int iFound);
172    
173    typedef MainSearch8Func* MainSearch8FuncPtr;
174    
175  // mv.length table  // mv.length table
176  static const uint32_t mvtab[33] = {  static const uint32_t mvtab[33] = {
# Line 261  Line 308 
308    
309  #ifndef SEARCH16  #ifndef SEARCH16
310  #define SEARCH16        PMVfastSearch16  #define SEARCH16        PMVfastSearch16
311    //#define SEARCH16      FullSearch16
312    //#define SEARCH16      EPZSSearch16
313  #endif  #endif
314    
315  #ifndef SEARCH8  #ifndef SEARCH8
316  #define SEARCH8         PMVfastSearch8  #define SEARCH8         PMVfastSearch8
317    //#define SEARCH8       EPZSSearch8
318  #endif  #endif
319    
320  bool MotionEstimation(  bool MotionEstimation(
# Line 290  Line 340 
340          int32_t sad16;          int32_t sad16;
341          int32_t deviation;          int32_t deviation;
342    
343            if (sadInit);
344                    (*sadInit)();
345    
346          // note: i==horizontal, j==vertical          // note: i==horizontal, j==vertical
347          for (i = 0; i < iHcount; i++)          for (i = 0; i < iHcount; i++)
348                  for (j = 0; j < iWcount; j++)                  for (j = 0; j < iWcount; j++)
# Line 392  Line 445 
445      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \
446  }  }
447    
448    #define NOCHECK_MV16_CANDIDATE(X,Y) { \
449        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
450        iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\
451        if (iSAD < iMinSAD) \
452        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
453    }
454    
455  #define CHECK_MV16_CANDIDATE(X,Y) { \  #define CHECK_MV16_CANDIDATE(X,Y) { \
456    if ( ((X) <= max_dx) && ((X) >= min_dx) \    if ( ((X) <= max_dx) && ((X) >= min_dx) \
# Line 431  Line 490 
490    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \
491  }  }
492    
493    #define NOCHECK_MV8_CANDIDATE(X,Y) \
494      { \
495        iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
496        iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\
497        if (iSAD < iMinSAD) \
498        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
499    }
500    
501  #define CHECK_MV8_CANDIDATE(X,Y) { \  #define CHECK_MV8_CANDIDATE(X,Y) { \
502    if ( ((X) <= max_dx) && ((X) >= min_dx) \    if ( ((X) <= max_dx) && ((X) >= min_dx) \
# Line 501  Line 567 
567  }  }
568  */  */
569    
570  int32_t PMVfastSearch16_MainSearch(  int32_t Diamond16_MainSearch(
571          const uint8_t * const pRef,          const uint8_t * const pRef,
572          const uint8_t * const pRefH,          const uint8_t * const pRefH,
573          const uint8_t * const pRefV,          const uint8_t * const pRefV,
# Line 558  Line 624 
624          return iMinSAD;          return iMinSAD;
625  }  }
626    
627  int32_t PMVfastSearch16_Refine(  int32_t Square16_MainSearch(
628                                            const uint8_t * const pRef,
629                                            const uint8_t * const pRefH,
630                                            const uint8_t * const pRefV,
631                                            const uint8_t * const pRefHV,
632                                            const uint8_t * const cur,
633                                            const int x, const int y,
634                                            int32_t startx, int32_t starty,
635                                            int32_t iMinSAD,
636                                            VECTOR * const currMV,
637                                            const VECTOR * const pmv,
638                                            const int32_t min_dx, const int32_t max_dx,
639                                            const int32_t min_dy, const int32_t max_dy,
640                                            const int32_t iEdgedWidth,
641                                            const int32_t iDiamondSize,
642                                            const int32_t iFcode,
643                                            const int32_t iQuant,
644                                            int iFound)
645    {
646    /* Do a square search around given starting point, return SAD of best */
647    
648            int32_t iDirection=0;
649            int32_t iSAD;
650            VECTOR backupMV;
651            backupMV.x = startx;
652            backupMV.y = starty;
653    
654    /* It's one search with full square pattern, and new parts for all following diamonds */
655    
656    /*   new direction are extra, so 1-4 is normal diamond
657          537
658          1*2
659          648
660    */
661    
662            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
663            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
664            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
665            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
666    
667            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
668            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
669            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
670            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
671    
672    
673            if (iDirection)
674                    while (!iFound)
675                    {
676                            iFound = 1;
677                            backupMV=*currMV;
678    
679                            switch (iDirection)
680                            {
681                                    case 1:
682                                            CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);
683                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
684                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
685                                            break;
686                                    case 2:
687                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
688                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
689                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
690                                            break;
691    
692                                    case 3:
693                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
694                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
695                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
696                                            break;
697    
698                                    case 4:
699                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
700                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
701                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
702                                            break;
703    
704                                    case 5:
705                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
706                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
707                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
708                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
709                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
710                                            break;
711    
712                                    case 6:
713                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
714                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
715    
716                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
717                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
718                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
719    
720                                            break;
721    
722                                    case 7:
723                                            CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);
724                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
725                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
726                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
727                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
728                                            break;
729    
730                                    case 8:
731                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
732                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
733                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
734                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
735                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
736                                            break;
737                            default:
738                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
739                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
740                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
741                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
742    
743                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
744                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
745                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
746                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
747                                            break;
748                            }
749                    }
750            else
751                    {
752                            currMV->x = startx;
753                            currMV->y = starty;
754                    }
755            return iMinSAD;
756    }
757    
758    
759    int32_t Full16_MainSearch(
760                                            const uint8_t * const pRef,
761                                            const uint8_t * const pRefH,
762                                            const uint8_t * const pRefV,
763                                            const uint8_t * const pRefHV,
764                                            const uint8_t * const cur,
765                                            const int x, const int y,
766                                            int32_t startx, int32_t starty,
767                                            int32_t iMinSAD,
768                                            VECTOR * const currMV,
769                                            const VECTOR * const pmv,
770                                            const int32_t min_dx, const int32_t max_dx,
771                                            const int32_t min_dy, const int32_t max_dy,
772                                            const int32_t iEdgedWidth,
773                                            const int32_t iDiamondSize,
774                                            const int32_t iFcode,
775                                            const int32_t iQuant,
776                                            int iFound)
777    {
778            int32_t iSAD;
779            int32_t dx,dy;
780            VECTOR backupMV;
781            backupMV.x = startx;
782            backupMV.y = starty;
783    
784            for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
785                    for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
786                            NOCHECK_MV16_CANDIDATE(dx,dy);
787    
788            return iMinSAD;
789    }
790    
791    int32_t Full8_MainSearch(
792                                            const uint8_t * const pRef,
793                                            const uint8_t * const pRefH,
794                                            const uint8_t * const pRefV,
795                                            const uint8_t * const pRefHV,
796                                            const uint8_t * const cur,
797                                            const int x, const int y,
798                                            int32_t startx, int32_t starty,
799                                            int32_t iMinSAD,
800                                            VECTOR * const currMV,
801                                            const VECTOR * const pmv,
802                                            const int32_t min_dx, const int32_t max_dx,
803                                            const int32_t min_dy, const int32_t max_dy,
804                                            const int32_t iEdgedWidth,
805                                            const int32_t iDiamondSize,
806                                            const int32_t iFcode,
807                                            const int32_t iQuant,
808                                            int iFound)
809    {
810            int32_t iSAD;
811            int32_t dx,dy;
812            VECTOR backupMV;
813            backupMV.x = startx;
814            backupMV.y = starty;
815    
816            for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
817                    for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
818                            NOCHECK_MV8_CANDIDATE(dx,dy);
819    
820            return iMinSAD;
821    }
822    
823    
824    
825    int32_t Halfpel16_Refine(
826          const uint8_t * const pRef,          const uint8_t * const pRef,
827          const uint8_t * const pRefH,          const uint8_t * const pRefH,
828          const uint8_t * const pRefV,          const uint8_t * const pRefV,
# Line 593  Line 857 
857    
858  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)
859    
860    
861  int32_t PMVfastSearch16(  int32_t PMVfastSearch16(
862          const uint8_t * const pRef,          const uint8_t * const pRef,
863          const uint8_t * const pRefH,          const uint8_t * const pRefH,
# Line 601  Line 866 
866          const IMAGE * const pCur,          const IMAGE * const pCur,
867          const int x, const int y,          const int x, const int y,
868          const uint32_t MotionFlags,          const uint32_t MotionFlags,
869          MBParam * const pParam,                                          const MBParam * const pParam,
870          MACROBLOCK * const pMBs,          MACROBLOCK * const pMBs,
871          VECTOR * const currMV,          VECTOR * const currMV,
872          VECTOR * const currPMV)          VECTOR * const currPMV)
# Line 732  Line 997 
997          {          {
998    
999                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1000                          goto step10b;                          goto PMVfast16_Terminate_without_Refine;
1001                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
1002                          goto step10;                          goto PMVfast16_Terminate_with_Refine;
1003          }          }
1004    
1005  /*  /*
# Line 788  Line 1053 
1053          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[0]) && (iMinSAD < pMB->sad16) ) )          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[0]) && (iMinSAD < pMB->sad16) ) )
1054          {          {
1055                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1056                          goto step10b;                          goto PMVfast16_Terminate_without_Refine;
1057                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
1058                          goto step10;                          goto PMVfast16_Terminate_with_Refine;
1059          }          }
1060    
1061    
# Line 807  Line 1072 
1072          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1073    
1074  /* 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 */
1075          iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1076                                            x, y,                                            x, y,
1077                                            currMV->x, currMV->y, iMinSAD, &newMV,                                            currMV->x, currMV->y, iMinSAD, &newMV,
1078                                            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 823  Line 1088 
1088  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1089    
1090                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0],backupMV)) )
1091                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1092                                                            x, y,                                                            x, y,
1093                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1094                                                            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 836  Line 1101 
1101                  }                  }
1102    
1103                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1104                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1105                                                            x, y,                                                            x, y,
1106                                                            0, 0, iMinSAD, &newMV,                                                            0, 0, iMinSAD, &newMV,
1107                                                            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 853  Line 1118 
1118     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.
1119  */  */
1120    
1121   step10:  PMVfast16_Terminate_with_Refine:
1122          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
1123                  iMinSAD = PMVfastSearch16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,
1124                                                    x, y,                                                    x, y,
1125                                                    currMV, iMinSAD,                                                    currMV, iMinSAD,
1126                                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
1127    
1128   step10b:  PMVfast16_Terminate_without_Refine:
1129          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - pmv[0].x;
1130          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - pmv[0].y;
1131          return iMinSAD;          return iMinSAD;
# Line 871  Line 1136 
1136    
1137    
1138    
1139  int32_t PMVfastSearch8_MainSearch(  int32_t Diamond8_MainSearch(
1140          const uint8_t * const pRef,          const uint8_t * const pRef,
1141          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1142          const uint8_t * const pRefV,          const uint8_t * const pRefV,
# Line 928  Line 1193 
1193          return iMinSAD;          return iMinSAD;
1194  }  }
1195    
1196  int32_t PMVfastSearch8_Refine(  int32_t Halfpel8_Refine(
1197          const uint8_t * const pRef,          const uint8_t * const pRef,
1198          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1199          const uint8_t * const pRefV,          const uint8_t * const pRefV,
# Line 973  Line 1238 
1238          const int x, const int y,          const int x, const int y,
1239          const int start_x, int start_y,          const int start_x, int start_y,
1240          const uint32_t MotionFlags,          const uint32_t MotionFlags,
1241          MBParam * const pParam,                                          const MBParam * const pParam,
1242          MACROBLOCK * const pMBs,          MACROBLOCK * const pMBs,
1243          VECTOR * const currMV,          VECTOR * const currMV,
1244          VECTOR * const currPMV)          VECTOR * const currPMV)
# Line 1081  Line 1346 
1346    
1347          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]) ) )
1348          {          {
1349                  if (MotionFlags & PMV_QUICKSTOP8)                  if (MotionFlags & PMV_QUICKSTOP16)
1350                          goto step10_8b;                          goto PMVfast8_Terminate_without_Refine;
1351                  if (MotionFlags & PMV_EARLYSTOP8)                  if (MotionFlags & PMV_EARLYSTOP16)
1352                          goto step10_8;                          goto PMVfast8_Terminate_with_Refine;
1353          }          }
1354    
1355    
1356  /*  /*
1357     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.
1358     Also calculate (0,0) but do not subtract offset.     Also calculate (0,0) but do not subtract offset.
# Line 1139  Line 1405 
1405    
1406          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[iSubBlock]) && (iMinSAD < pMB->sad8[iSubBlock]) ) )          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[iSubBlock]) && (iMinSAD < pMB->sad8[iSubBlock]) ) )
1407          {          {
1408                  if (MotionFlags & PMV_QUICKSTOP8)                  if (MotionFlags & PMV_QUICKSTOP16)
1409                          goto step10_8b;                          goto PMVfast8_Terminate_without_Refine;
1410                  if (MotionFlags & PMV_EARLYSTOP8)                  if (MotionFlags & PMV_EARLYSTOP16)
1411                          goto step10_8;                          goto PMVfast8_Terminate_with_Refine;
1412          }          }
1413    
1414  /************ (Diamond Search)  **************/  /************ (Diamond Search)  **************/
# Line 1158  Line 1424 
1424          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1425    
1426  /* 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 */
1427          iSAD = PMVfastSearch8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD = Diamond8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1428                                           x, y,                                           x, y,
1429                                           currMV->x, currMV->y, iMinSAD, &newMV,                                           currMV->x, currMV->y, iMinSAD, &newMV,
1430                                           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 1174  Line 1440 
1440  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1441    
1442                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0],backupMV)) )
1443                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1444                                                            x, y,                                                            x, y,
1445                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1446                                                            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 1187  Line 1453 
1453                  }                  }
1454    
1455                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1456                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1457                                                            x, y,                                                            x, y,
1458                                                            0, 0, iMinSAD, &newMV,                                                            0, 0, iMinSAD, &newMV,
1459                                                            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 1204  Line 1470 
1470     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.
1471  */  */
1472    
1473   step10_8:  PMVfast8_Terminate_with_Refine:
1474          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
1475                  iMinSAD = PMVfastSearch8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,
1476                                                   x, y,                                                   x, y,
1477                                                   currMV, iMinSAD,                                                   currMV, iMinSAD,
1478                                                   pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                   pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
1479    
  step10_8b:  
1480    
1481    PMVfast8_Terminate_without_Refine:
1482          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - pmv[0].x;
1483          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - pmv[0].y;
1484    
1485          return iMinSAD;          return iMinSAD;
1486  }  }
1487    
1488    int32_t EPZSSearch16(
1489                                            const uint8_t * const pRef,
1490                                            const uint8_t * const pRefH,
1491                                            const uint8_t * const pRefV,
1492                                            const uint8_t * const pRefHV,
1493                                            const IMAGE * const pCur,
1494                                            const int x, const int y,
1495                                            const uint32_t MotionFlags,
1496                                            const MBParam * const pParam,
1497                                            MACROBLOCK * const pMBs,
1498                                            VECTOR * const currMV,
1499                                            VECTOR * const currPMV)
1500    {
1501            const uint32_t iWcount = pParam->mb_width;
1502            const uint32_t iHcount = pParam->mb_height;
1503            const int32_t iFcode = pParam->fixed_code;
1504            const int32_t iQuant = pParam->quant;
1505    
1506            const int32_t iWidth = pParam->width;
1507            const int32_t iHeight = pParam->height;
1508            const int32_t iEdgedWidth = pParam->edged_width;
1509    
1510            const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
1511    
1512            int32_t min_dx;
1513            int32_t max_dx;
1514            int32_t min_dy;
1515            int32_t max_dy;
1516    
1517            VECTOR newMV;
1518            VECTOR backupMV;
1519    
1520            VECTOR pmv[4];
1521            int32_t psad[8];
1522    
1523            static MACROBLOCK * oldMBs = NULL;
1524            MACROBLOCK * const pMB = pMBs + x + y * iWcount;
1525            MACROBLOCK * oldMB = NULL;
1526    
1527            static int32_t thresh2;
1528            int32_t bPredEq;
1529            int32_t iMinSAD,iSAD=9999;
1530    
1531            MainSearch16FuncPtr EPZSMainSearchPtr;
1532    
1533            if (oldMBs == NULL)
1534            {       oldMBs = (MACROBLOCK*) calloc(1,iWcount*iHcount*sizeof(MACROBLOCK));
1535                    fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));
1536            }
1537            oldMB = oldMBs + x + y * iWcount;
1538    
1539    /* Get maximum range */
1540            get_range(&min_dx, &max_dx, &min_dy, &max_dy,
1541                            x, y, 16, iWidth, iHeight, iFcode);
1542    
1543    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
1544    
1545            if (!(MotionFlags & PMV_HALFPEL16 ))
1546            { min_dx = EVEN(min_dx);
1547              max_dx = EVEN(max_dx);
1548              min_dy = EVEN(min_dy);
1549              max_dy = EVEN(max_dy);
1550            }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1551    
1552            bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
1553    
1554    /* Step 4: Calculate SAD around the Median prediction.
1555            MinSAD=SAD
1556            If Motion Vector equal to Previous frame motion vector
1557                    and MinSAD<PrevFrmSAD goto Step 10.
1558            If SAD<=256 goto Step 10.
1559    */
1560    
1561    // Prepare for main loop
1562    
1563            *currMV=pmv[0];         /* current best := median prediction */
1564            if (!(MotionFlags & PMV_HALFPEL16))
1565            {
1566                    currMV->x = EVEN(currMV->x);
1567                    currMV->y = EVEN(currMV->y);
1568            }
1569    
1570            if (currMV->x > max_dx)
1571                    currMV->x=max_dx;
1572            if (currMV->x < min_dx)
1573                    currMV->x=min_dx;
1574            if (currMV->y > max_dy)
1575                    currMV->y=max_dy;
1576            if (currMV->y < min_dy)
1577                    currMV->y=min_dy;
1578    
1579    /***************** This is predictor SET A: only median prediction ******************/
1580    
1581            iMinSAD = sad16( cur,
1582                    get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),
1583                    iEdgedWidth, MV_MAX_ERROR);
1584            iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;
1585    
1586    // thresh1 is fixed to 256
1587            if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,pMB->mvs[0])) && (iMinSAD < pMB->sad16) ) )
1588                    {
1589                            if (MotionFlags & PMV_QUICKSTOP16)
1590                                    goto EPZS16_Terminate_without_Refine;
1591                            if (MotionFlags & PMV_EARLYSTOP16)
1592                                    goto EPZS16_Terminate_with_Refine;
1593                    }
1594    
1595    /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
1596    
1597    // previous frame MV
1598            CHECK_MV16_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);
1599    
1600    // set threshhold based on Min of Prediction and SAD of collocated block
1601    // CHECK_MV16 always uses iSAD for the SAD of last vector to check, so now iSAD is what we want
1602    
1603            if ((x==0) && (y==0) )
1604            {
1605                    thresh2 =  512;
1606            }
1607            else
1608            {
1609    /* T_k = 1.2 * MIN(SAD_top,SAD_left,SAD_topleft,SAD_coll) +128;   [Tourapis, 2002] */
1610    
1611                    thresh2 = MIN(psad[0],iSAD)*6/5 + 128;
1612            }
1613    
1614    // MV=(0,0) is often a good choice
1615    
1616            CHECK_MV16_ZERO;
1617    
1618    
1619    // left neighbour, if allowed
1620            if (x != 0)
1621            {
1622                    if (!(MotionFlags & PMV_HALFPEL16 ))
1623                    {       pmv[1].x = EVEN(pmv[1].x);
1624                            pmv[1].y = EVEN(pmv[1].y);
1625                    }
1626                    CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1627            }
1628    
1629    // top neighbour, if allowed
1630            if (y != 0)
1631            {
1632                    if (!(MotionFlags & PMV_HALFPEL16 ))
1633                    {       pmv[2].x = EVEN(pmv[2].x);
1634                            pmv[2].y = EVEN(pmv[2].y);
1635                    }
1636                    CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1637    
1638    // top right neighbour, if allowed
1639                    if (x != (iWcount-1))
1640                    {
1641                            if (!(MotionFlags & PMV_HALFPEL16 ))
1642                            {       pmv[3].x = EVEN(pmv[3].x);
1643                                    pmv[3].y = EVEN(pmv[3].y);
1644                            }
1645                            CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);
1646                    }
1647            }
1648    
1649    /* Terminate if MinSAD <= T_2
1650       Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
1651    */
1652    
1653            if ( (iMinSAD <= thresh2)
1654                    || ( MVequal(*currMV,pMB->mvs[0]) && (iMinSAD <= pMB->sad16) ) )
1655                    {
1656                            if (MotionFlags & PMV_QUICKSTOP16)
1657                                    goto EPZS16_Terminate_without_Refine;
1658                            if (MotionFlags & PMV_EARLYSTOP16)
1659                                    goto EPZS16_Terminate_with_Refine;
1660                    }
1661    
1662    /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/
1663    
1664            backupMV = pMB->mvs[0];                 // last MV
1665            backupMV.x += (pMB->mvs[0].x - oldMB->mvs[0].x );       // acceleration X
1666            backupMV.y += (pMB->mvs[0].y - oldMB->mvs[0].y );       // acceleration Y
1667    
1668            CHECK_MV16_CANDIDATE(backupMV.x,backupMV.y);
1669    
1670    // left neighbour
1671            if (x != 0)
1672                    CHECK_MV16_CANDIDATE((oldMB-1)->mvs[0].x,oldMB->mvs[0].y);
1673    
1674    // top neighbour
1675            if (y != 0)
1676                    CHECK_MV16_CANDIDATE((oldMB-iWcount)->mvs[0].x,oldMB->mvs[0].y);
1677    
1678    // right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs
1679    
1680            if (x != iWcount-1)
1681                    CHECK_MV16_CANDIDATE((pMB+1)->mvs[0].x,oldMB->mvs[0].y);
1682    
1683    // bottom neighbour, dito
1684            if (y != iHcount-1)
1685                    CHECK_MV16_CANDIDATE((pMB+iWcount)->mvs[0].x,oldMB->mvs[0].y);
1686    
1687    /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */
1688            if (iMinSAD <= thresh2)
1689                    {
1690                            if (MotionFlags & PMV_QUICKSTOP16)
1691                                    goto EPZS16_Terminate_without_Refine;
1692                            if (MotionFlags & PMV_EARLYSTOP16)
1693                                    goto EPZS16_Terminate_with_Refine;
1694                    }
1695    
1696    /************ (if Diamond Search)  **************/
1697    
1698            backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1699    
1700    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
1701    
1702            if (MotionFlags & PMV_USESQUARES16)
1703                    EPZSMainSearchPtr = Square16_MainSearch;
1704            else
1705                    EPZSMainSearchPtr = Diamond16_MainSearch;
1706    
1707            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1708                            x, y,
1709                            currMV->x, currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1710                            2, iFcode, iQuant, 0);
1711    
1712            if (iSAD < iMinSAD)
1713            {
1714                    *currMV = newMV;
1715                    iMinSAD = iSAD;
1716            }
1717    
1718    
1719            if (MotionFlags & PMV_EXTSEARCH16)
1720            {
1721    /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
1722    
1723                    if (!(MVequal(pmv[0],backupMV)) )
1724                    {
1725                            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1726                                    x, y,
1727                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1728                                    pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
1729                    }
1730    
1731                    if (iSAD < iMinSAD)
1732                    {
1733                            *currMV = newMV;
1734                            iMinSAD = iSAD;
1735                    }
1736    
1737                    if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1738                    {
1739                            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1740                                    x, y,
1741                            0, 0, iMinSAD, &newMV,
1742                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, /*iDiamondSize*/ 2, iFcode, iQuant, 0);
1743    
1744                            if (iSAD < iMinSAD)
1745                            {
1746                                    *currMV = newMV;
1747                                    iMinSAD = iSAD;
1748                            }
1749                    }
1750            }
1751    
1752    /***************        Choose best MV found     **************/
1753    
1754    EPZS16_Terminate_with_Refine:
1755            if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
1756                    iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,
1757                                    x, y,
1758                                    currMV, iMinSAD,
1759                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
1760    
1761    EPZS16_Terminate_without_Refine:
1762    
1763            *oldMB = *pMB;
1764    
1765            currPMV->x = currMV->x - pmv[0].x;
1766            currPMV->y = currMV->y - pmv[0].y;
1767            return iMinSAD;
1768    }
1769    
1770    
1771    int32_t EPZSSearch8(
1772                                            const uint8_t * const pRef,
1773                                            const uint8_t * const pRefH,
1774                                            const uint8_t * const pRefV,
1775                                            const uint8_t * const pRefHV,
1776                                            const IMAGE * const pCur,
1777                                            const int x, const int y,
1778                                            const int start_x, const int start_y,
1779                                            const uint32_t MotionFlags,
1780                                            const MBParam * const pParam,
1781                                            MACROBLOCK * const pMBs,
1782                                            VECTOR * const currMV,
1783                                            VECTOR * const currPMV)
1784    {
1785            const uint32_t iWcount = pParam->mb_width;
1786            const int32_t iFcode = pParam->fixed_code;
1787            const int32_t iQuant = pParam->quant;
1788    
1789            const int32_t iWidth = pParam->width;
1790            const int32_t iHeight = pParam->height;
1791            const int32_t iEdgedWidth = pParam->edged_width;
1792    
1793            const uint8_t * cur = pCur->y + x*8 + y*8*iEdgedWidth;
1794    
1795            int32_t iDiamondSize=1;
1796    
1797            int32_t min_dx;
1798            int32_t max_dx;
1799            int32_t min_dy;
1800            int32_t max_dy;
1801    
1802            VECTOR newMV;
1803            VECTOR backupMV;
1804    
1805            VECTOR pmv[4];
1806            int32_t psad[8];
1807    
1808            const   int32_t iSubBlock = ((y&1)<<1) + (x&1);
1809    
1810            MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1811    
1812            int32_t bPredEq;
1813            int32_t iMinSAD,iSAD=9999;
1814    
1815            MainSearch8FuncPtr EPZSMainSearchPtr;
1816    
1817    /* Get maximum range */
1818            get_range(&min_dx, &max_dx, &min_dy, &max_dy,
1819                            x, y, 8, iWidth, iHeight, iFcode);
1820    
1821    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
1822    
1823            if (!(MotionFlags & PMV_HALFPEL8 ))
1824            { min_dx = EVEN(min_dx);
1825              max_dx = EVEN(max_dx);
1826              min_dy = EVEN(min_dy);
1827              max_dy = EVEN(max_dy);
1828            }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1829    
1830            bPredEq  = get_pmvdata(pMBs, x>>1, y>>1, iWcount, iSubBlock, pmv, psad);
1831    
1832    
1833    /* Step 4: Calculate SAD around the Median prediction.
1834            MinSAD=SAD
1835            If Motion Vector equal to Previous frame motion vector
1836                    and MinSAD<PrevFrmSAD goto Step 10.
1837            If SAD<=256 goto Step 10.
1838    */
1839    
1840    // Prepare for main loop
1841    
1842    
1843            if (!(MotionFlags & PMV_HALFPEL8))
1844            {
1845                    currMV->x = EVEN(currMV->x);
1846                    currMV->y = EVEN(currMV->y);
1847            }
1848    
1849            if (currMV->x > max_dx)
1850                    currMV->x=max_dx;
1851            if (currMV->x < min_dx)
1852                    currMV->x=min_dx;
1853            if (currMV->y > max_dy)
1854                    currMV->y=max_dy;
1855            if (currMV->y < min_dy)
1856                    currMV->y=min_dy;
1857    
1858    /***************** This is predictor SET A: only median prediction ******************/
1859    
1860    
1861            iMinSAD = sad8( cur,
1862                    get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),
1863                    iEdgedWidth);
1864            iMinSAD += calc_delta_8(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;
1865    
1866    
1867    // thresh1 is fixed to 256
1868            if (iMinSAD < 256/4 )
1869                    {
1870                            if (MotionFlags & PMV_QUICKSTOP8)
1871                                    goto EPZS8_Terminate_without_Refine;
1872                            if (MotionFlags & PMV_EARLYSTOP8)
1873                                    goto EPZS8_Terminate_with_Refine;
1874                    }
1875    
1876    /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
1877    
1878    // previous frame MV
1879            CHECK_MV8_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);
1880    
1881    // MV=(0,0) is often a good choice
1882    
1883            CHECK_MV8_ZERO;
1884    
1885    /* Terminate if MinSAD <= T_2
1886       Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
1887    */
1888    
1889            if (iMinSAD < 512/4)    /* T_2 == 512/4 hardcoded */
1890                    {
1891                            if (MotionFlags & PMV_QUICKSTOP8)
1892                                    goto EPZS8_Terminate_without_Refine;
1893                            if (MotionFlags & PMV_EARLYSTOP8)
1894                                    goto EPZS8_Terminate_with_Refine;
1895                    }
1896    
1897    /************ (if Diamond Search)  **************/
1898    
1899            backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1900    
1901            if (!(MotionFlags & PMV_HALFPELDIAMOND8))
1902                    iDiamondSize *= 2;
1903    
1904    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
1905    
1906    //      if (MotionFlags & PMV_USESQUARES8)
1907    //              EPZSMainSearchPtr = Square8_MainSearch;
1908    //      else
1909                    EPZSMainSearchPtr = Diamond8_MainSearch;
1910    
1911            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1912                    x, y,
1913                    currMV->x, currMV->y, iMinSAD, &newMV,
1914                    pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1915                    iDiamondSize, iFcode, iQuant, 00);
1916    
1917    
1918            if (iSAD < iMinSAD)
1919            {
1920                    *currMV = newMV;
1921                    iMinSAD = iSAD;
1922            }
1923    
1924            if (MotionFlags & PMV_EXTSEARCH8)
1925            {
1926    /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
1927    
1928                    if (!(MVequal(pmv[0],backupMV)) )
1929                    {
1930                            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1931                                    x, y,
1932                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1933                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);
1934    
1935                            if (iSAD < iMinSAD)
1936                            {
1937                                    *currMV = newMV;
1938                                    iMinSAD = iSAD;
1939                            }
1940                    }
1941    
1942                    if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1943                    {
1944                            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1945                                    x, y,
1946                            0, 0, iMinSAD, &newMV,
1947                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);
1948    
1949                            if (iSAD < iMinSAD)
1950                            {
1951                                    *currMV = newMV;
1952                                    iMinSAD = iSAD;
1953                            }
1954                    }
1955            }
1956    
1957    /***************        Choose best MV found     **************/
1958    
1959    EPZS8_Terminate_with_Refine:
1960            if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
1961                    iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,
1962                                    x, y,
1963                                    currMV, iMinSAD,
1964                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
1965    
1966    EPZS8_Terminate_without_Refine:
1967    
1968            currPMV->x = currMV->x - pmv[0].x;
1969            currPMV->y = currMV->y - pmv[0].y;
1970            return iMinSAD;
1971    }
1972    

Legend:
Removed from v.78  
changed lines
  Added in v.115

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