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

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

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

revision 78, Thu Mar 28 20:57:25 2002 UTC revision 96, Mon Apr 1 22:47:58 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 392  Line 442 
442      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \
443  }  }
444    
445    #define NOCHECK_MV16_CANDIDATE(X,Y) { \
446        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
447        iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\
448        if (iSAD < iMinSAD) \
449        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
450    }
451    
452  #define CHECK_MV16_CANDIDATE(X,Y) { \  #define CHECK_MV16_CANDIDATE(X,Y) { \
453    if ( ((X) <= max_dx) && ((X) >= min_dx) \    if ( ((X) <= max_dx) && ((X) >= min_dx) \
# Line 431  Line 487 
487    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \
488  }  }
489    
490    #define NOCHECK_MV8_CANDIDATE(X,Y) \
491      { \
492        iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
493        iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\
494        if (iSAD < iMinSAD) \
495        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
496    }
497    
498  #define CHECK_MV8_CANDIDATE(X,Y) { \  #define CHECK_MV8_CANDIDATE(X,Y) { \
499    if ( ((X) <= max_dx) && ((X) >= min_dx) \    if ( ((X) <= max_dx) && ((X) >= min_dx) \
# Line 501  Line 564 
564  }  }
565  */  */
566    
567  int32_t PMVfastSearch16_MainSearch(  int32_t Diamond16_MainSearch(
568          const uint8_t * const pRef,          const uint8_t * const pRef,
569          const uint8_t * const pRefH,          const uint8_t * const pRefH,
570          const uint8_t * const pRefV,          const uint8_t * const pRefV,
# Line 558  Line 621 
621          return iMinSAD;          return iMinSAD;
622  }  }
623    
624  int32_t PMVfastSearch16_Refine(  int32_t Square16_MainSearch(
625                                            const uint8_t * const pRef,
626                                            const uint8_t * const pRefH,
627                                            const uint8_t * const pRefV,
628                                            const uint8_t * const pRefHV,
629                                            const uint8_t * const cur,
630                                            const int x, const int y,
631                                            int32_t startx, int32_t starty,
632                                            int32_t iMinSAD,
633                                            VECTOR * const currMV,
634                                            const VECTOR * const pmv,
635                                            const int32_t min_dx, const int32_t max_dx,
636                                            const int32_t min_dy, const int32_t max_dy,
637                                            const int32_t iEdgedWidth,
638                                            const int32_t iDiamondSize,
639                                            const int32_t iFcode,
640                                            const int32_t iQuant,
641                                            int iFound)
642    {
643    /* Do a square search around given starting point, return SAD of best */
644    
645            int32_t iDirection=0;
646            int32_t iSAD;
647            VECTOR backupMV;
648            backupMV.x = startx;
649            backupMV.y = starty;
650    
651    /* It's one search with full square pattern, and new parts for all following diamonds */
652    
653    /*   new direction are extra, so 1-4 is normal diamond
654          537
655          1*2
656          648
657    */
658    
659            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
660            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
661            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
662            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
663    
664            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
665            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
666            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
667            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
668    
669    
670            if (iDirection)
671                    while (!iFound)
672                    {
673                            iFound = 1;
674                            backupMV=*currMV;
675    
676                            switch (iDirection)
677                            {
678                                    case 1:
679                                            CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);
680                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
681                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
682                                            break;
683                                    case 2:
684                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
685                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
686                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
687                                            break;
688    
689                                    case 3:
690                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
691                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
692                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
693                                            break;
694    
695                                    case 4:
696                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
697                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
698                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
699                                            break;
700    
701                                    case 5:
702                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
703                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
704                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
705                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
706                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
707                                            break;
708    
709                                    case 6:
710                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
711                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
712    
713                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
714                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
715                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
716    
717                                            break;
718    
719                                    case 7:
720                                            CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);
721                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
722                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
723                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
724                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
725                                            break;
726    
727                                    case 8:
728                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
729                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
730                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
731                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
732                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
733                                            break;
734                            default:
735                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
736                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
737                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
738                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
739    
740                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
741                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
742                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
743                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
744                                            break;
745                            }
746                    }
747            else
748                    {
749                            currMV->x = startx;
750                            currMV->y = starty;
751                    }
752            return iMinSAD;
753    }
754    
755    
756    int32_t Full16_MainSearch(
757                                            const uint8_t * const pRef,
758                                            const uint8_t * const pRefH,
759                                            const uint8_t * const pRefV,
760                                            const uint8_t * const pRefHV,
761                                            const uint8_t * const cur,
762                                            const int x, const int y,
763                                            int32_t startx, int32_t starty,
764                                            int32_t iMinSAD,
765                                            VECTOR * const currMV,
766                                            const VECTOR * const pmv,
767                                            const int32_t min_dx, const int32_t max_dx,
768                                            const int32_t min_dy, const int32_t max_dy,
769                                            const int32_t iEdgedWidth,
770                                            const int32_t iDiamondSize,
771                                            const int32_t iFcode,
772                                            const int32_t iQuant,
773                                            int iFound)
774    {
775            int32_t iSAD;
776            int32_t dx,dy;
777            VECTOR backupMV;
778            backupMV.x = startx;
779            backupMV.y = starty;
780    
781            for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
782                    for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
783                            NOCHECK_MV16_CANDIDATE(dx,dy);
784    
785            return iMinSAD;
786    }
787    
788    int32_t Full8_MainSearch(
789                                            const uint8_t * const pRef,
790                                            const uint8_t * const pRefH,
791                                            const uint8_t * const pRefV,
792                                            const uint8_t * const pRefHV,
793                                            const uint8_t * const cur,
794                                            const int x, const int y,
795                                            int32_t startx, int32_t starty,
796                                            int32_t iMinSAD,
797                                            VECTOR * const currMV,
798                                            const VECTOR * const pmv,
799                                            const int32_t min_dx, const int32_t max_dx,
800                                            const int32_t min_dy, const int32_t max_dy,
801                                            const int32_t iEdgedWidth,
802                                            const int32_t iDiamondSize,
803                                            const int32_t iFcode,
804                                            const int32_t iQuant,
805                                            int iFound)
806    {
807            int32_t iSAD;
808            int32_t dx,dy;
809            VECTOR backupMV;
810            backupMV.x = startx;
811            backupMV.y = starty;
812    
813            for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
814                    for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
815                            NOCHECK_MV8_CANDIDATE(dx,dy);
816    
817            return iMinSAD;
818    }
819    
820    
821    
822    int32_t Halfpel16_Refine(
823          const uint8_t * const pRef,          const uint8_t * const pRef,
824          const uint8_t * const pRefH,          const uint8_t * const pRefH,
825          const uint8_t * const pRefV,          const uint8_t * const pRefV,
# Line 593  Line 854 
854    
855  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)
856    
857    
858  int32_t PMVfastSearch16(  int32_t PMVfastSearch16(
859          const uint8_t * const pRef,          const uint8_t * const pRef,
860          const uint8_t * const pRefH,          const uint8_t * const pRefH,
# Line 601  Line 863 
863          const IMAGE * const pCur,          const IMAGE * const pCur,
864          const int x, const int y,          const int x, const int y,
865          const uint32_t MotionFlags,          const uint32_t MotionFlags,
866          MBParam * const pParam,                                          const MBParam * const pParam,
867          MACROBLOCK * const pMBs,          MACROBLOCK * const pMBs,
868          VECTOR * const currMV,          VECTOR * const currMV,
869          VECTOR * const currPMV)          VECTOR * const currPMV)
# Line 732  Line 994 
994          {          {
995    
996                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
997                          goto step10b;                          goto PMVfast16_Terminate_without_Refine;
998                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
999                          goto step10;                          goto PMVfast16_Terminate_with_Refine;
1000          }          }
1001    
1002  /*  /*
# Line 788  Line 1050 
1050          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[0]) && (iMinSAD < pMB->sad16) ) )          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[0]) && (iMinSAD < pMB->sad16) ) )
1051          {          {
1052                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1053                          goto step10b;                          goto PMVfast16_Terminate_without_Refine;
1054                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
1055                          goto step10;                          goto PMVfast16_Terminate_with_Refine;
1056          }          }
1057    
1058    
# Line 807  Line 1069 
1069          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1070    
1071  /* 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 */
1072          iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1073                                            x, y,                                            x, y,
1074                                            currMV->x, currMV->y, iMinSAD, &newMV,                                            currMV->x, currMV->y, iMinSAD, &newMV,
1075                                            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 1085 
1085  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1086    
1087                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0],backupMV)) )
1088                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1089                                                            x, y,                                                            x, y,
1090                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1091                                                            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 1098 
1098                  }                  }
1099    
1100                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1101                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1102                                                            x, y,                                                            x, y,
1103                                                            0, 0, iMinSAD, &newMV,                                                            0, 0, iMinSAD, &newMV,
1104                                                            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 1115 
1115     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.
1116  */  */
1117    
1118   step10:  PMVfast16_Terminate_with_Refine:
1119          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
1120                  iMinSAD = PMVfastSearch16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,
1121                                                    x, y,                                                    x, y,
1122                                                    currMV, iMinSAD,                                                    currMV, iMinSAD,
1123                                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
1124    
1125   step10b:  PMVfast16_Terminate_without_Refine:
1126          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - pmv[0].x;
1127          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - pmv[0].y;
1128          return iMinSAD;          return iMinSAD;
# Line 871  Line 1133 
1133    
1134    
1135    
1136  int32_t PMVfastSearch8_MainSearch(  int32_t Diamond8_MainSearch(
1137          const uint8_t * const pRef,          const uint8_t * const pRef,
1138          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1139          const uint8_t * const pRefV,          const uint8_t * const pRefV,
# Line 928  Line 1190 
1190          return iMinSAD;          return iMinSAD;
1191  }  }
1192    
1193  int32_t PMVfastSearch8_Refine(  int32_t Halfpel8_Refine(
1194          const uint8_t * const pRef,          const uint8_t * const pRef,
1195          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1196          const uint8_t * const pRefV,          const uint8_t * const pRefV,
# Line 973  Line 1235 
1235          const int x, const int y,          const int x, const int y,
1236          const int start_x, int start_y,          const int start_x, int start_y,
1237          const uint32_t MotionFlags,          const uint32_t MotionFlags,
1238          MBParam * const pParam,                                          const MBParam * const pParam,
1239          MACROBLOCK * const pMBs,          MACROBLOCK * const pMBs,
1240          VECTOR * const currMV,          VECTOR * const currMV,
1241          VECTOR * const currPMV)          VECTOR * const currPMV)
# Line 1081  Line 1343 
1343    
1344          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]) ) )
1345          {          {
1346                  if (MotionFlags & PMV_QUICKSTOP8)                  if (MotionFlags & PMV_QUICKSTOP16)
1347                          goto step10_8b;                          goto PMVfast8_Terminate_without_Refine;
1348                  if (MotionFlags & PMV_EARLYSTOP8)                  if (MotionFlags & PMV_EARLYSTOP16)
1349                          goto step10_8;                          goto PMVfast8_Terminate_with_Refine;
1350          }          }
1351    
1352    
1353  /*  /*
1354     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.
1355     Also calculate (0,0) but do not subtract offset.     Also calculate (0,0) but do not subtract offset.
# Line 1139  Line 1402 
1402    
1403          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[iSubBlock]) && (iMinSAD < pMB->sad8[iSubBlock]) ) )          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[iSubBlock]) && (iMinSAD < pMB->sad8[iSubBlock]) ) )
1404          {          {
1405                  if (MotionFlags & PMV_QUICKSTOP8)                  if (MotionFlags & PMV_QUICKSTOP16)
1406                          goto step10_8b;                          goto PMVfast8_Terminate_without_Refine;
1407                  if (MotionFlags & PMV_EARLYSTOP8)                  if (MotionFlags & PMV_EARLYSTOP16)
1408                          goto step10_8;                          goto PMVfast8_Terminate_with_Refine;
1409          }          }
1410    
1411  /************ (Diamond Search)  **************/  /************ (Diamond Search)  **************/
# Line 1158  Line 1421 
1421          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1422    
1423  /* 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 */
1424          iSAD = PMVfastSearch8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD = Diamond8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1425                                           x, y,                                           x, y,
1426                                           currMV->x, currMV->y, iMinSAD, &newMV,                                           currMV->x, currMV->y, iMinSAD, &newMV,
1427                                           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 1437 
1437  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1438    
1439                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0],backupMV)) )
1440                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1441                                                            x, y,                                                            x, y,
1442                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1443                                                            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 1450 
1450                  }                  }
1451    
1452                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1453                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1454                                                            x, y,                                                            x, y,
1455                                                            0, 0, iMinSAD, &newMV,                                                            0, 0, iMinSAD, &newMV,
1456                                                            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 1467 
1467     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.
1468  */  */
1469    
1470   step10_8:  PMVfast8_Terminate_with_Refine:
1471          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
1472                  iMinSAD = PMVfastSearch8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,
1473                                                   x, y,                                                   x, y,
1474                                                   currMV, iMinSAD,                                                   currMV, iMinSAD,
1475                                                   pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                   pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
1476    
  step10_8b:  
1477    
1478    PMVfast8_Terminate_without_Refine:
1479          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - pmv[0].x;
1480          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - pmv[0].y;
1481    
1482          return iMinSAD;          return iMinSAD;
1483  }  }
1484    
1485    int32_t EPZSSearch16(
1486                                            const uint8_t * const pRef,
1487                                            const uint8_t * const pRefH,
1488                                            const uint8_t * const pRefV,
1489                                            const uint8_t * const pRefHV,
1490                                            const IMAGE * const pCur,
1491                                            const int x, const int y,
1492                                            const uint32_t MotionFlags,
1493                                            const MBParam * const pParam,
1494                                            MACROBLOCK * const pMBs,
1495                                            VECTOR * const currMV,
1496                                            VECTOR * const currPMV)
1497    {
1498            const uint32_t iWcount = pParam->mb_width;
1499            const uint32_t iHcount = pParam->mb_height;
1500            const int32_t iFcode = pParam->fixed_code;
1501            const int32_t iQuant = pParam->quant;
1502    
1503            const int32_t iWidth = pParam->width;
1504            const int32_t iHeight = pParam->height;
1505            const int32_t iEdgedWidth = pParam->edged_width;
1506    
1507            const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
1508    
1509            int32_t min_dx;
1510            int32_t max_dx;
1511            int32_t min_dy;
1512            int32_t max_dy;
1513    
1514            VECTOR newMV;
1515            VECTOR backupMV;
1516    
1517            VECTOR pmv[4];
1518            int32_t psad[8];
1519    
1520            static MACROBLOCK * oldMBs = NULL;
1521            MACROBLOCK * const pMB = pMBs + x + y * iWcount;
1522            MACROBLOCK * oldMB = NULL;
1523    
1524            static int32_t thresh2;
1525            int32_t bPredEq;
1526            int32_t iMinSAD,iSAD=9999;
1527    
1528            MainSearch16FuncPtr EPZSMainSearchPtr;
1529    
1530            if (oldMBs == NULL)
1531            {       oldMBs = (MACROBLOCK*) calloc(1,iWcount*iHcount*sizeof(MACROBLOCK));
1532                    fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));
1533            }
1534            oldMB = oldMBs + x + y * iWcount;
1535    
1536    /* Get maximum range */
1537            get_range(&min_dx, &max_dx, &min_dy, &max_dy,
1538                            x, y, 16, iWidth, iHeight, iFcode);
1539    
1540    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
1541    
1542            if (!(MotionFlags & PMV_HALFPEL16 ))
1543            { min_dx = EVEN(min_dx);
1544              max_dx = EVEN(max_dx);
1545              min_dy = EVEN(min_dy);
1546              max_dy = EVEN(max_dy);
1547            }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1548    
1549            bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
1550    
1551    /* Step 4: Calculate SAD around the Median prediction.
1552            MinSAD=SAD
1553            If Motion Vector equal to Previous frame motion vector
1554                    and MinSAD<PrevFrmSAD goto Step 10.
1555            If SAD<=256 goto Step 10.
1556    */
1557    
1558    // Prepare for main loop
1559    
1560            *currMV=pmv[0];         /* current best := median prediction */
1561            if (!(MotionFlags & PMV_HALFPEL16))
1562            {
1563                    currMV->x = EVEN(currMV->x);
1564                    currMV->y = EVEN(currMV->y);
1565            }
1566    
1567            if (currMV->x > max_dx)
1568                    currMV->x=max_dx;
1569            if (currMV->x < min_dx)
1570                    currMV->x=min_dx;
1571            if (currMV->y > max_dy)
1572                    currMV->y=max_dy;
1573            if (currMV->y < min_dy)
1574                    currMV->y=min_dy;
1575    
1576    /***************** This is predictor SET A: only median prediction ******************/
1577    
1578            iMinSAD = sad16( cur,
1579                    get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),
1580                    iEdgedWidth, MV_MAX_ERROR);
1581            iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;
1582    
1583    // thresh1 is fixed to 256
1584            if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,pMB->mvs[0])) && (iMinSAD < pMB->sad16) ) )
1585                    {
1586                            if (MotionFlags & PMV_QUICKSTOP16)
1587                                    goto EPZS16_Terminate_without_Refine;
1588                            if (MotionFlags & PMV_EARLYSTOP16)
1589                                    goto EPZS16_Terminate_with_Refine;
1590                    }
1591    
1592    /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
1593    
1594    // previous frame MV
1595            CHECK_MV16_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);
1596    
1597    // set threshhold based on Min of Prediction and SAD of collocated block
1598    // CHECK_MV16 always uses iSAD for the SAD of last vector to check, so now iSAD is what we want
1599    
1600            if ((x==0) && (y==0) )
1601            {
1602                    thresh2 =  512;
1603            }
1604            else
1605            {
1606    /* T_k = 1.2 * MIN(SAD_top,SAD_left,SAD_topleft,SAD_coll) +128;   [Tourapis, 2002] */
1607    
1608                    thresh2 = MIN(psad[0],iSAD)*6/5 + 128;
1609            }
1610    
1611    // MV=(0,0) is often a good choice
1612    
1613            CHECK_MV16_ZERO;
1614    
1615    
1616    // left neighbour, if allowed
1617            if (x != 0)
1618            {
1619                    if (!(MotionFlags & PMV_HALFPEL16 ))
1620                    {       pmv[1].x = EVEN(pmv[1].x);
1621                            pmv[1].y = EVEN(pmv[1].y);
1622                    }
1623                    CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1624            }
1625    
1626    // top neighbour, if allowed
1627            if (y != 0)
1628            {
1629                    if (!(MotionFlags & PMV_HALFPEL16 ))
1630                    {       pmv[2].x = EVEN(pmv[2].x);
1631                            pmv[2].y = EVEN(pmv[2].y);
1632                    }
1633                    CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1634    
1635    // top right neighbour, if allowed
1636                    if (x != (iWcount-1))
1637                    {
1638                            if (!(MotionFlags & PMV_HALFPEL16 ))
1639                            {       pmv[3].x = EVEN(pmv[3].x);
1640                                    pmv[3].y = EVEN(pmv[3].y);
1641                            }
1642                            CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);
1643                    }
1644            }
1645    
1646    /* Terminate if MinSAD <= T_2
1647       Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
1648    */
1649    
1650            if ( (iMinSAD <= thresh2)
1651                    || ( MVequal(*currMV,pMB->mvs[0]) && (iMinSAD <= pMB->sad16) ) )
1652                    {
1653                            if (MotionFlags & PMV_QUICKSTOP16)
1654                                    goto EPZS16_Terminate_without_Refine;
1655                            if (MotionFlags & PMV_EARLYSTOP16)
1656                                    goto EPZS16_Terminate_with_Refine;
1657                    }
1658    
1659    /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/
1660    
1661            backupMV = pMB->mvs[0];                 // last MV
1662            backupMV.x += (pMB->mvs[0].x - oldMB->mvs[0].x );       // acceleration X
1663            backupMV.y += (pMB->mvs[0].y - oldMB->mvs[0].y );       // acceleration Y
1664    
1665            CHECK_MV16_CANDIDATE(backupMV.x,backupMV.y);
1666    
1667    // left neighbour
1668            if (x != 0)
1669                    CHECK_MV16_CANDIDATE((oldMB-1)->mvs[0].x,oldMB->mvs[0].y);
1670    
1671    // top neighbour
1672            if (y != 0)
1673                    CHECK_MV16_CANDIDATE((oldMB-iWcount)->mvs[0].x,oldMB->mvs[0].y);
1674    
1675    // right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs
1676    
1677            if (x != iWcount-1)
1678                    CHECK_MV16_CANDIDATE((pMB+1)->mvs[0].x,oldMB->mvs[0].y);
1679    
1680    // bottom neighbour, dito
1681            if (y != iHcount-1)
1682                    CHECK_MV16_CANDIDATE((pMB+iWcount)->mvs[0].x,oldMB->mvs[0].y);
1683    
1684    /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */
1685            if (iMinSAD <= thresh2)
1686                    {
1687                            if (MotionFlags & PMV_QUICKSTOP16)
1688                                    goto EPZS16_Terminate_without_Refine;
1689                            if (MotionFlags & PMV_EARLYSTOP16)
1690                                    goto EPZS16_Terminate_with_Refine;
1691                    }
1692    
1693    /************ (if Diamond Search)  **************/
1694    
1695            backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1696    
1697    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
1698    
1699            if (MotionFlags & PMV_USESQUARES16)
1700                    EPZSMainSearchPtr = Square16_MainSearch;
1701            else
1702                    EPZSMainSearchPtr = Diamond16_MainSearch;
1703    
1704            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1705                            x, y,
1706                            currMV->x, currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1707                            2, iFcode, iQuant, 0);
1708    
1709            if (iSAD < iMinSAD)
1710            {
1711                    *currMV = newMV;
1712                    iMinSAD = iSAD;
1713            }
1714    
1715    
1716            if (MotionFlags & PMV_EXTSEARCH16)
1717            {
1718    /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
1719    
1720                    if (!(MVequal(pmv[0],backupMV)) )
1721                    {
1722                            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1723                                    x, y,
1724                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1725                                    pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
1726                    }
1727    
1728                    if (iSAD < iMinSAD)
1729                    {
1730                            *currMV = newMV;
1731                            iMinSAD = iSAD;
1732                    }
1733    
1734                    if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1735                    {
1736                            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1737                                    x, y,
1738                            0, 0, iMinSAD, &newMV,
1739                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, /*iDiamondSize*/ 2, iFcode, iQuant, 0);
1740    
1741                            if (iSAD < iMinSAD)
1742                            {
1743                                    *currMV = newMV;
1744                                    iMinSAD = iSAD;
1745                            }
1746                    }
1747            }
1748    
1749    /***************        Choose best MV found     **************/
1750    
1751    EPZS16_Terminate_with_Refine:
1752            if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
1753                    iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,
1754                                    x, y,
1755                                    currMV, iMinSAD,
1756                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
1757    
1758    EPZS16_Terminate_without_Refine:
1759    
1760            *oldMB = *pMB;
1761    
1762            currPMV->x = currMV->x - pmv[0].x;
1763            currPMV->y = currMV->y - pmv[0].y;
1764            return iMinSAD;
1765    }
1766    
1767    
1768    int32_t EPZSSearch8(
1769                                            const uint8_t * const pRef,
1770                                            const uint8_t * const pRefH,
1771                                            const uint8_t * const pRefV,
1772                                            const uint8_t * const pRefHV,
1773                                            const IMAGE * const pCur,
1774                                            const int x, const int y,
1775                                            const int start_x, const int start_y,
1776                                            const uint32_t MotionFlags,
1777                                            const MBParam * const pParam,
1778                                            MACROBLOCK * const pMBs,
1779                                            VECTOR * const currMV,
1780                                            VECTOR * const currPMV)
1781    {
1782            const uint32_t iWcount = pParam->mb_width;
1783            const int32_t iFcode = pParam->fixed_code;
1784            const int32_t iQuant = pParam->quant;
1785    
1786            const int32_t iWidth = pParam->width;
1787            const int32_t iHeight = pParam->height;
1788            const int32_t iEdgedWidth = pParam->edged_width;
1789    
1790            const uint8_t * cur = pCur->y + x*8 + y*8*iEdgedWidth;
1791    
1792            int32_t iDiamondSize=1;
1793    
1794            int32_t min_dx;
1795            int32_t max_dx;
1796            int32_t min_dy;
1797            int32_t max_dy;
1798    
1799            VECTOR newMV;
1800            VECTOR backupMV;
1801    
1802            VECTOR pmv[4];
1803            int32_t psad[8];
1804    
1805            const   int32_t iSubBlock = ((y&1)<<1) + (x&1);
1806    
1807            MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1808    
1809            int32_t bPredEq;
1810            int32_t iMinSAD,iSAD=9999;
1811    
1812            MainSearch8FuncPtr EPZSMainSearchPtr;
1813    
1814    /* Get maximum range */
1815            get_range(&min_dx, &max_dx, &min_dy, &max_dy,
1816                            x, y, 8, iWidth, iHeight, iFcode);
1817    
1818    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
1819    
1820            if (!(MotionFlags & PMV_HALFPEL8 ))
1821            { min_dx = EVEN(min_dx);
1822              max_dx = EVEN(max_dx);
1823              min_dy = EVEN(min_dy);
1824              max_dy = EVEN(max_dy);
1825            }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1826    
1827            bPredEq  = get_pmvdata(pMBs, x>>1, y>>1, iWcount, iSubBlock, pmv, psad);
1828    
1829    
1830    /* Step 4: Calculate SAD around the Median prediction.
1831            MinSAD=SAD
1832            If Motion Vector equal to Previous frame motion vector
1833                    and MinSAD<PrevFrmSAD goto Step 10.
1834            If SAD<=256 goto Step 10.
1835    */
1836    
1837    // Prepare for main loop
1838    
1839    
1840            if (!(MotionFlags & PMV_HALFPEL8))
1841            {
1842                    currMV->x = EVEN(currMV->x);
1843                    currMV->y = EVEN(currMV->y);
1844            }
1845    
1846            if (currMV->x > max_dx)
1847                    currMV->x=max_dx;
1848            if (currMV->x < min_dx)
1849                    currMV->x=min_dx;
1850            if (currMV->y > max_dy)
1851                    currMV->y=max_dy;
1852            if (currMV->y < min_dy)
1853                    currMV->y=min_dy;
1854    
1855    /***************** This is predictor SET A: only median prediction ******************/
1856    
1857    
1858            iMinSAD = sad8( cur,
1859                    get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),
1860                    iEdgedWidth);
1861            iMinSAD += calc_delta_8(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;
1862    
1863    
1864    // thresh1 is fixed to 256
1865            if (iMinSAD < 256/4 )
1866                    {
1867                            if (MotionFlags & PMV_QUICKSTOP8)
1868                                    goto EPZS8_Terminate_without_Refine;
1869                            if (MotionFlags & PMV_EARLYSTOP8)
1870                                    goto EPZS8_Terminate_with_Refine;
1871                    }
1872    
1873    /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
1874    
1875    // previous frame MV
1876            CHECK_MV8_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);
1877    
1878    // MV=(0,0) is often a good choice
1879    
1880            CHECK_MV8_ZERO;
1881    
1882    /* Terminate if MinSAD <= T_2
1883       Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
1884    */
1885    
1886            if (iMinSAD < 512/4)    /* T_2 == 512/4 hardcoded */
1887                    {
1888                            if (MotionFlags & PMV_QUICKSTOP8)
1889                                    goto EPZS8_Terminate_without_Refine;
1890                            if (MotionFlags & PMV_EARLYSTOP8)
1891                                    goto EPZS8_Terminate_with_Refine;
1892                    }
1893    
1894    /************ (if Diamond Search)  **************/
1895    
1896            backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1897    
1898            if (!(MotionFlags & PMV_HALFPELDIAMOND8))
1899                    iDiamondSize *= 2;
1900    
1901    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
1902    
1903    //      if (MotionFlags & PMV_USESQUARES8)
1904    //              EPZSMainSearchPtr = Square8_MainSearch;
1905    //      else
1906                    EPZSMainSearchPtr = Diamond8_MainSearch;
1907    
1908            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1909                    x, y,
1910                    currMV->x, currMV->y, iMinSAD, &newMV,
1911                    pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1912                    iDiamondSize, iFcode, iQuant, 00);
1913    
1914    
1915            if (iSAD < iMinSAD)
1916            {
1917                    *currMV = newMV;
1918                    iMinSAD = iSAD;
1919            }
1920    
1921            if (MotionFlags & PMV_EXTSEARCH8)
1922            {
1923    /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
1924    
1925                    if (!(MVequal(pmv[0],backupMV)) )
1926                    {
1927                            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1928                                    x, y,
1929                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1930                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);
1931    
1932                            if (iSAD < iMinSAD)
1933                            {
1934                                    *currMV = newMV;
1935                                    iMinSAD = iSAD;
1936                            }
1937                    }
1938    
1939                    if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1940                    {
1941                            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1942                                    x, y,
1943                            0, 0, iMinSAD, &newMV,
1944                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);
1945    
1946                            if (iSAD < iMinSAD)
1947                            {
1948                                    *currMV = newMV;
1949                                    iMinSAD = iSAD;
1950                            }
1951                    }
1952            }
1953    
1954    /***************        Choose best MV found     **************/
1955    
1956    EPZS8_Terminate_with_Refine:
1957            if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
1958                    iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,
1959                                    x, y,
1960                                    currMV, iMinSAD,
1961                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
1962    
1963    EPZS8_Terminate_without_Refine:
1964    
1965            currPMV->x = currMV->x - pmv[0].x;
1966            currPMV->y = currMV->y - pmv[0].y;
1967            return iMinSAD;
1968    }
1969    

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

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