[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 96, Mon Apr 1 22:47:58 2002 UTC revision 259, Sat Jul 6 17:04:57 2002 UTC
# Line 1  Line 1 
1  /**************************************************************************  /**************************************************************************
2   *   *
3     *      XVID MPEG-4 VIDEO CODEC
4     *      motion estimation
5     *
6     *      This program is an implementation of a part of one or more MPEG-4
7     *      Video tools as specified in ISO/IEC 14496-2 standard.  Those intending
8     *      to use this software module in hardware or software products are
9     *      advised that its use may infringe existing patents or copyrights, and
10     *      any such use would be at such party's own risk.  The original
11     *      developer of this software module and his/her company, and subsequent
12     *      editors and their companies, will have no liability for use of this
13     *      software or modifications or derivatives thereof.
14     *
15     *      This program is free software; you can redistribute it and/or modify
16     *      it under the terms of the GNU General Public License as published by
17     *      the Free Software Foundation; either version 2 of the License, or
18     *      (at your option) any later version.
19     *
20     *      This program is distributed in the hope that it will be useful,
21     *      but WITHOUT ANY WARRANTY; without even the implied warranty of
22     *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23     *      GNU General Public License for more details.
24     *
25     *      You should have received a copy of the GNU General Public License
26     *      along with this program; if not, write to the Free Software
27     *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28     *
29     *************************************************************************/
30    
31    /**************************************************************************
32     *
33   *  Modifications:   *  Modifications:
34   *   *
35     *      01.05.2002      updated MotionEstimationBVOP
36     *      25.04.2002 partial prevMB conversion
37     *  22.04.2002 remove some compile warning by chenm001 <chenm001@163.com>
38     *  14.04.2002 added MotionEstimationBVOP()
39   *  02.04.2002 add EPZS(^2) as ME algorithm, use PMV_USESQUARES to choose between   *  02.04.2002 add EPZS(^2) as ME algorithm, use PMV_USESQUARES to choose between
40   *             EPZS and EPZS^2   *             EPZS and EPZS^2
41   *  08.02.2002 split up PMVfast into three routines: PMVFast, PMVFast_MainLoop   *  08.02.2002 split up PMVfast into three routines: PMVFast, PMVFast_MainLoop
# Line 40  Line 74 
74  #include "../prediction/mbprediction.h"  #include "../prediction/mbprediction.h"
75  #include "../global.h"  #include "../global.h"
76  #include "../utils/timer.h"  #include "../utils/timer.h"
77    #include "motion.h"
78  #include "sad.h"  #include "sad.h"
79    
 // very large value  
 #define MV_MAX_ERROR    (4096 * 256)  
   
 // stop search if sdelta < THRESHOLD  
 #define MV16_THRESHOLD  192  
 #define MV8_THRESHOLD   56  
   
 /* sad16(0,0) bias; mpeg4 spec suggests nb/2+1 */  
 /* nb  = vop pixels * 2^(bpp-8) */  
 #define MV16_00_BIAS    (128+1)  
   
 /* INTER bias for INTER/INTRA decision; mpeg4 spec suggests 2*nb */  
 #define INTER_BIAS      512  
   
 /* Parameters which control inter/inter4v decision */  
 #define IMV16X16                        5  
   
 /* vector map (vlc delta size) smoother parameters */  
 #define NEIGH_TEND_16X16        2  
 #define NEIGH_TEND_8X8          2  
   
   
 // fast ((A)/2)*2  
 #define EVEN(A)         (((A)<0?(A)+1:(A)) & ~1)  
   
   
 #define MIN(X, Y) ((X)<(Y)?(X):(Y))  
 #define MAX(X, Y) ((X)>(Y)?(X):(Y))  
 #define ABS(X)    (((X)>0)?(X):-(X))  
 #define SIGN(X)   (((X)>0)?1:-1)  
   
 int32_t PMVfastSearch16(  
                                         const uint8_t * const pRef,  
                                         const uint8_t * const pRefH,  
                                         const uint8_t * const pRefV,  
                                         const uint8_t * const pRefHV,  
                                         const IMAGE * const pCur,  
                                         const int x, const int y,  
                                         const uint32_t MotionFlags,  
                                         const MBParam * const pParam,  
                                         MACROBLOCK * const pMBs,  
                                         VECTOR * const currMV,  
                                         VECTOR * const currPMV);  
   
 int32_t EPZSSearch16(  
                                         const uint8_t * const pRef,  
                                         const uint8_t * const pRefH,  
                                         const uint8_t * const pRefV,  
                                         const uint8_t * const pRefHV,  
                                         const IMAGE * const pCur,  
                                         const int x, const int y,  
                                         const uint32_t MotionFlags,  
                                         const MBParam * const pParam,  
                                         MACROBLOCK * const pMBs,  
                                         VECTOR * const currMV,  
                                         VECTOR * const currPMV);  
   
   
 int32_t PMVfastSearch8(  
                                         const uint8_t * const pRef,  
                                         const uint8_t * const pRefH,  
                                         const uint8_t * const pRefV,  
                                         const uint8_t * const pRefHV,  
                                         const IMAGE * const pCur,  
                                         const int x, const int y,  
                                         const int start_x, int start_y,  
                                         const uint32_t MotionFlags,  
                                         const MBParam * const pParam,  
                                         MACROBLOCK * const pMBs,  
                                         VECTOR * const currMV,  
                                         VECTOR * const currPMV);  
80    
 int32_t EPZSSearch8(  
                                         const uint8_t * const pRef,  
                                         const uint8_t * const pRefH,  
                                         const uint8_t * const pRefV,  
                                         const uint8_t * const pRefHV,  
                                         const IMAGE * const pCur,  
                                         const int x, const int y,  
                                         const int start_x, int start_y,  
                                         const uint32_t MotionFlags,  
                                         const MBParam * const pParam,  
                                         MACROBLOCK * const pMBs,  
                                         VECTOR * const currMV,  
                                         VECTOR * const currPMV);  
81    
82    static int32_t lambda_vec16[32] =       /* rounded values for lambda param for weight of motion bits as in modified H.26L */
83    { 0, (int) (1.00235 + 0.5), (int) (1.15582 + 0.5), (int) (1.31976 + 0.5),
84                    (int) (1.49591 + 0.5), (int) (1.68601 + 0.5),
85            (int) (1.89187 + 0.5), (int) (2.11542 + 0.5), (int) (2.35878 + 0.5),
86                    (int) (2.62429 + 0.5), (int) (2.91455 + 0.5),
87            (int) (3.23253 + 0.5), (int) (3.58158 + 0.5), (int) (3.96555 + 0.5),
88                    (int) (4.38887 + 0.5), (int) (4.85673 + 0.5),
89            (int) (5.37519 + 0.5), (int) (5.95144 + 0.5), (int) (6.59408 + 0.5),
90                    (int) (7.31349 + 0.5), (int) (8.12242 + 0.5),
91            (int) (9.03669 + 0.5), (int) (10.0763 + 0.5), (int) (11.2669 + 0.5),
92                    (int) (12.6426 + 0.5), (int) (14.2493 + 0.5),
93            (int) (16.1512 + 0.5), (int) (18.442 + 0.5), (int) (21.2656 + 0.5),
94                    (int) (24.8580 + 0.5), (int) (29.6436 + 0.5),
95            (int) (36.4949 + 0.5)
96    };
97    
98  typedef int32_t (MainSearch16Func)(  static int32_t *lambda_vec8 = lambda_vec16;     /* same table for INTER and INTER4V for now */
         const uint8_t * const pRef,  
         const uint8_t * const pRefH,  
         const uint8_t * const pRefV,  
         const uint8_t * const pRefHV,  
         const uint8_t * const cur,  
         const int x, const int y,  
         int32_t startx, int32_t starty,  
         int32_t iMinSAD,  
         VECTOR * const currMV,  
         const VECTOR * const pmv,  
         const int32_t min_dx, const int32_t max_dx,  
         const int32_t min_dy, const int32_t max_dy,  
         const int32_t iEdgedWidth,  
         const int32_t iDiamondSize,  
         const int32_t iFcode,  
         const int32_t iQuant,  
         int iFound);  
99    
 typedef MainSearch16Func* MainSearch16FuncPtr;  
100    
101    
 typedef int32_t (MainSearch8Func)(  
         const uint8_t * const pRef,  
         const uint8_t * const pRefH,  
         const uint8_t * const pRefV,  
         const uint8_t * const pRefHV,  
         const uint8_t * const cur,  
         const int x, const int y,  
         int32_t startx, int32_t starty,  
         int32_t iMinSAD,  
         VECTOR * const currMV,  
         const VECTOR * const pmv,  
         const int32_t min_dx, const int32_t max_dx,  
         const int32_t min_dy, const int32_t max_dy,  
         const int32_t iEdgedWidth,  
         const int32_t iDiamondSize,  
         const int32_t iFcode,  
         const int32_t iQuant,  
         int iFound);  
   
 typedef MainSearch8Func* MainSearch8FuncPtr;  
   
102  // mv.length table  // mv.length table
103  static const uint32_t mvtab[33] = {  static const uint32_t mvtab[33] = {
104      1,  2,  3,  4,  6,  7,  7,  7,      1,  2,  3,  4,  6,  7,  7,  7,
# Line 181  Line 108 
108  };  };
109    
110    
111  static __inline uint32_t mv_bits(int32_t component, const uint32_t iFcode)  static __inline uint32_t
112    mv_bits(int32_t component,
113                    const uint32_t iFcode)
114  {  {
115      if (component == 0)      if (component == 0)
116                  return 1;                  return 1;
# Line 189  Line 118 
118      if (component < 0)      if (component < 0)
119                  component = -component;                  component = -component;
120    
121      if (iFcode == 1)          if (iFcode == 1) {
     {  
122                  if (component > 32)                  if (component > 32)
123                      component = 32;                      component = 32;
124    
# Line 207  Line 135 
135  }  }
136    
137    
138  static __inline uint32_t calc_delta_16(const int32_t dx, const int32_t dy, const uint32_t iFcode)  static __inline uint32_t
139  {  calc_delta_16(const int32_t dx,
140          return NEIGH_TEND_16X16 * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));                            const int32_t dy,
141  }                            const uint32_t iFcode,
142                              const uint32_t iQuant)
143  static __inline uint32_t calc_delta_8(const int32_t dx, const int32_t dy, const uint32_t iFcode)  {
144            return NEIGH_TEND_16X16 * lambda_vec16[iQuant] * (mv_bits(dx, iFcode) +
145  {                                                                                                            mv_bits(dy, iFcode));
146      return NEIGH_TEND_8X8 * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));  }
147  }  
148    static __inline uint32_t
149    calc_delta_8(const int32_t dx,
150                             const int32_t dy,
151                             const uint32_t iFcode,
152  /* calculate the min/max range (in halfpixels)                           const uint32_t iQuant)
153          relative to the _MACROBLOCK_ position  {
154  */          return NEIGH_TEND_8X8 * lambda_vec8[iQuant] * (mv_bits(dx, iFcode) +
155                                                                                                       mv_bits(dy, iFcode));
156  static void __inline get_range(  }
157          int32_t * const min_dx, int32_t * const max_dx,  
158          int32_t * const min_dy, int32_t * const max_dy,  bool
159          const uint32_t x, const uint32_t y,  MotionEstimation(MBParam * const pParam,
160          const uint32_t block_sz,                                        // block dimension, 8 or 16                                   FRAMEINFO * const current,
161          const uint32_t width, const uint32_t height,                                   FRAMEINFO * const reference,
         const uint32_t fcode)  
 {  
   
         const int search_range = 32 << (fcode - 1);  
         const int high = search_range - 1;  
         const int low = -search_range;  
   
         // convert full-pixel measurements to half pixel  
         const int hp_width = 2 * width;  
         const int hp_height = 2 * height;  
         const int hp_edge = 2 * block_sz;  
         const int hp_x = 2 * (x) * block_sz;            // we need _right end_ of block, not x-coordinate  
         const int hp_y = 2 * (y) * block_sz;            // same for _bottom end_  
   
         *max_dx = MIN(high,     hp_width - hp_x);  
         *max_dy = MIN(high,     hp_height - hp_y);  
         *min_dx = MAX(low,      -(hp_edge + hp_x));  
         *min_dy = MAX(low,      -(hp_edge + hp_y));  
   
 }  
   
   
 /*  
  * getref: calculate reference image pointer  
  * the decision to use interpolation h/v/hv or the normal image is  
  * based on dx & dy.  
  */  
   
 static __inline const uint8_t * get_ref(  
         const uint8_t * const refn,  
         const uint8_t * const refh,  
         const uint8_t * const refv,  
         const uint8_t * const refhv,  
         const uint32_t x, const uint32_t y,  
         const uint32_t block,                                   // block dimension, 8 or 16  
         const int32_t dx, const int32_t dy,  
         const uint32_t stride)  
 {  
   
         switch ( ((dx&1)<<1) + (dy&1) )         // ((dx%2)?2:0)+((dy%2)?1:0)  
         {  
         case 0  : return refn + (x*block+dx/2) + (y*block+dy/2)*stride;  
         case 1  : return refv + (x*block+dx/2) + (y*block+(dy-1)/2)*stride;  
         case 2  : return refh + (x*block+(dx-1)/2) + (y*block+dy/2)*stride;  
         default :  
         case 3  : return refhv + (x*block+(dx-1)/2) + (y*block+(dy-1)/2)*stride;  
         }  
   
 }  
   
   
 /* This is somehow a copy of get_ref, but with MV instead of X,Y */  
   
 static __inline const uint8_t * get_ref_mv(  
         const uint8_t * const refn,  
         const uint8_t * const refh,  
         const uint8_t * const refv,  
         const uint8_t * const refhv,  
         const uint32_t x, const uint32_t y,  
         const uint32_t block,                   // block dimension, 8 or 16  
         const VECTOR* mv,       // measured in half-pel!  
         const uint32_t stride)  
 {  
   
         switch ( (((mv->x)&1)<<1) + ((mv->y)&1) )  
         {  
         case 0  : return refn + (x*block+(mv->x)/2) + (y*block+(mv->y)/2)*stride;  
         case 1  : return refv + (x*block+(mv->x)/2) + (y*block+((mv->y)-1)/2)*stride;  
         case 2  : return refh + (x*block+((mv->x)-1)/2) + (y*block+(mv->y)/2)*stride;  
         default :  
         case 3  : return refhv + (x*block+((mv->x)-1)/2) + (y*block+((mv->y)-1)/2)*stride;  
         }  
   
 }  
   
 #ifndef SEARCH16  
 #define SEARCH16        PMVfastSearch16  
 //#define SEARCH16      FullSearch16  
 //#define SEARCH16      EPZSSearch16  
 #endif  
   
 #ifndef SEARCH8  
 #define SEARCH8         PMVfastSearch8  
 //#define SEARCH8       EPZSSearch8  
 #endif  
   
 bool MotionEstimation(  
         MACROBLOCK * const pMBs,  
         MBParam * const pParam,  
         const IMAGE * const pRef,  
162          const IMAGE * const pRefH,          const IMAGE * const pRefH,
163          const IMAGE * const pRefV,          const IMAGE * const pRefV,
164          const IMAGE * const pRefHV,          const IMAGE * const pRefHV,
         IMAGE * const pCurrent,  
165          const uint32_t iLimit)          const uint32_t iLimit)
   
166  {  {
167          const uint32_t iWcount = pParam->mb_width;          const uint32_t iWcount = pParam->mb_width;
168          const uint32_t iHcount = pParam->mb_height;          const uint32_t iHcount = pParam->mb_height;
169            MACROBLOCK *const pMBs = current->mbs;
170            MACROBLOCK *const prevMBs = reference->mbs;
171            const IMAGE *const pCurrent = &current->image;
172            const IMAGE *const pRef = &reference->image;
173    
174          uint32_t i, j, iIntra = 0;          const VECTOR zeroMV = { 0, 0 };
175    
176          VECTOR mv16;          long long time;
177          VECTOR pmv16;          int32_t x, y;
178            int32_t iIntra = 0;
179            VECTOR pmv;
180    
181          int32_t sad8 = 0;          if (sadInit)
182          int32_t sad16;                  (*sadInit) ();
         int32_t deviation;  
183    
184          // note: i==horizontal, j==vertical          for (y = 0; y < iHcount; y++)   {
185          for (i = 0; i < iHcount; i++)                  for (x = 0; x < iWcount; x ++)  {
                 for (j = 0; j < iWcount; j++)  
                 {  
                         MACROBLOCK *pMB = &pMBs[j + i * iWcount];  
186    
187                          sad16 = SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                          MACROBLOCK *const pMB = &pMBs[x + y * iWcount];
                                          j, i, pParam->motion_flags,  
                                          pParam, pMBs, &mv16, &pmv16);  
                         pMB->sad16=sad16;  
188    
189                            pMB->sad16 =
190                                    SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,
191                                                     y, current->motion_flags, current->quant,
192                                                     current->fcode, pParam, pMBs, prevMBs, &pMB->mv16,
193                                                     &pMB->pmvs[0]);
194    
195                          /* decide: MODE_INTER or MODE_INTRA                          if (0 < (pMB->sad16 - MV16_INTER_BIAS)) {
196                             if (dev_intra < sad_inter - 2 * nb) use_intra                                  int32_t deviation;
                         */  
197    
198                          deviation = dev16(pCurrent->y + j*16 + i*16*pParam->edged_width, pParam->edged_width);                                  deviation =
199                                            dev16(pCurrent->y + x * 16 + y * 16 * pParam->edged_width,
200                                                      pParam->edged_width);
201    
202                          if (deviation < (sad16 - INTER_BIAS))                                  if (deviation < (pMB->sad16 - MV16_INTER_BIAS)) {
                         {  
203                                  pMB->mode = MODE_INTRA;                                  pMB->mode = MODE_INTRA;
204                                  pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = 0;                                          pMB->mv16 = pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =
205                                  pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = 0;                                                  pMB->mvs[3] = zeroMV;
206                                            pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =
207                                                    pMB->sad8[3] = 0;
208    
209                                  iIntra++;                                  iIntra++;
210                                  if(iIntra >= iLimit)                                  if(iIntra >= iLimit)
# Line 370  Line 212 
212    
213                                  continue;                                  continue;
214                          }                          }
   
                         if (pParam->global_flags & XVID_INTER4V)  
                         {  
                                 pMB->sad8[0] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,  
                                                        2 * j, 2 * i, mv16.x, mv16.y, pParam->motion_flags,  
                                                        pParam, pMBs, &pMB->mvs[0], &pMB->pmvs[0]);  
   
                                 pMB->sad8[1] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,  
                                                        2 * j + 1, 2 * i, mv16.x, mv16.y, pParam->motion_flags,  
                                                        pParam, pMBs, &pMB->mvs[1], &pMB->pmvs[1]);  
   
                                 pMB->sad8[2] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,  
                                                        2 * j, 2 * i + 1, mv16.x, mv16.y, pParam->motion_flags,  
                                                        pParam, pMBs, &pMB->mvs[2], &pMB->pmvs[2]);  
   
                                 pMB->sad8[3] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,  
                                                        2 * j + 1, 2 * i + 1, mv16.x, mv16.y, pParam->motion_flags,  
                                                        pParam, pMBs, &pMB->mvs[3], &pMB->pmvs[3]);  
   
                                 sad8 = pMB->sad8[0] + pMB->sad8[1] + pMB->sad8[2] + pMB->sad8[3];  
215                          }                          }
216    
217                            pmv = pMB->pmvs[0];
218                            if (current->global_flags & XVID_INTER4V)
219                                    if ((!(current->global_flags & XVID_LUMIMASKING) ||
220                                             pMB->dquant == NO_CHANGE)) {
221                                            int32_t sad8 = IMV16X16 * current->quant;
222    
223                                            if (sad8 < pMB->sad16)
224    
225                                                    sad8 += pMB->sad8[0] =
226                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
227                                                                            pCurrent, 2 * x, 2 * y, pMB->mv16.x,
228                                                                            pMB->mv16.y, current->motion_flags,
229                                                                            current->quant, current->fcode, pParam,
230                                                                            pMBs, prevMBs, &pMB->mvs[0],
231                                                                            &pMB->pmvs[0]);
232    
233                                            if (sad8 < pMB->sad16)
234                                                    sad8 += pMB->sad8[1] =
235                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
236                                                                            pCurrent, 2 * x + 1, 2 * y, pMB->mv16.x,
237                                                                            pMB->mv16.y, current->motion_flags,
238                                                                            current->quant, current->fcode, pParam,
239                                                                            pMBs, prevMBs, &pMB->mvs[1],
240                                                                            &pMB->pmvs[1]);
241    
242                                            if (sad8 < pMB->sad16)
243                                                    sad8 += pMB->sad8[2] =
244                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
245                                                                            pCurrent, 2 * x, 2 * y + 1, pMB->mv16.x,
246                                                                            pMB->mv16.y, current->motion_flags,
247                                                                            current->quant, current->fcode, pParam,
248                                                                            pMBs, prevMBs, &pMB->mvs[2],
249                                                                            &pMB->pmvs[2]);
250    
251                                            if (sad8 < pMB->sad16)
252                                                    sad8 += pMB->sad8[3] =
253                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
254                                                                            pCurrent, 2 * x + 1, 2 * y + 1,
255                                                                            pMB->mv16.x, pMB->mv16.y,
256                                                                            current->motion_flags, current->quant,
257                                                                            current->fcode, pParam, pMBs, prevMBs,
258                                                                            &pMB->mvs[3], &pMB->pmvs[3]);
259    
260                          /* decide: MODE_INTER or MODE_INTER4V                          /* decide: MODE_INTER or MODE_INTER4V
261                             mpeg4:   if (sad8 < sad16 - nb/2+1) use_inter4v                                             mpeg4:   if (sad8 < pMB->sad16 - nb/2+1) use_inter4v
262                          */                          */
263    
264                          if (pMB->dquant == NO_CHANGE) {                                          if (sad8 < pMB->sad16) {
                                 if (((pParam->global_flags & XVID_INTER4V)==0) ||  
                                     (sad16 < (sad8 + (int32_t)(IMV16X16 * pParam->quant)))) {  
   
                                         sad8 = sad16;  
                                         pMB->mode = MODE_INTER;  
                                         pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = mv16.x;  
                                         pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = mv16.y;  
                                         pMB->pmvs[0].x = pmv16.x;  
                                         pMB->pmvs[0].y = pmv16.y;  
                                 }  
                                 else  
265                                          pMB->mode = MODE_INTER4V;                                          pMB->mode = MODE_INTER4V;
266                                                    pMB->sad8[0] *= 4;
267                                                    pMB->sad8[1] *= 4;
268                                                    pMB->sad8[2] *= 4;
269                                                    pMB->sad8[3] *= 4;
270                                                    continue;
271                          }                          }
272                          else  
273                          {                                  }
274                                  sad8 = sad16;  
275                                  pMB->mode = MODE_INTER;                                  pMB->mode = MODE_INTER;
276                                  pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = mv16.x;                          pMB->pmvs[0] = pmv;     /* pMB->pmvs[1] = pMB->pmvs[2] = pMB->pmvs[3]  are not needed for INTER */
277                                  pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = mv16.y;                          pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mv16;
278                                  pMB->pmvs[0].x = pmv16.x;                          pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] =
279                                  pMB->pmvs[0].y = pmv16.y;                                  pMB->sad16;
280                          }                          }
281                  }                  }
282    
283          return 0;          return 0;
284  }  }
285    
 #define MVzero(A) ( ((A).x)==(0) && ((A).y)==(0) )  
   
 #define MVequal(A,B) ( ((A).x)==((B).x) && ((A).y)==((B).y) )  
   
   
286  #define CHECK_MV16_ZERO {\  #define CHECK_MV16_ZERO {\
287    if ( (0 <= max_dx) && (0 >= min_dx) \    if ( (0 <= max_dx) && (0 >= min_dx) \
288      && (0 <= max_dy) && (0 >= min_dy) ) \      && (0 <= max_dy) && (0 >= min_dy) ) \
289    { \    { \
290      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0, 0 , iEdgedWidth), iEdgedWidth, MV_MAX_ERROR); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0, 0 , iEdgedWidth), iEdgedWidth, MV_MAX_ERROR); \
291      iSAD += calc_delta_16(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode, iQuant);\
     if (iSAD <= iQuant * 96)    \  
         iSAD -= MV16_00_BIAS; \  
292      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
293      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \
294  }  }
295    
296  #define NOCHECK_MV16_CANDIDATE(X,Y) { \  #define NOCHECK_MV16_CANDIDATE(X,Y) { \
297      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
298      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\
299      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
300      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
301  }  }
# Line 454  Line 305 
305      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
306    { \    { \
307      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
308      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\
309      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
310      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
311  }  }
# Line 464  Line 315 
315      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
316    { \    { \
317      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
318      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\
319      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
320      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
321  }  }
# Line 474  Line 325 
325      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
326    { \    { \
327      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
328      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\
329      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
330      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
331  }  }
# Line 482  Line 333 
333    
334  #define CHECK_MV8_ZERO {\  #define CHECK_MV8_ZERO {\
335    iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, 0, 0 , iEdgedWidth), iEdgedWidth); \    iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, 0, 0 , iEdgedWidth), iEdgedWidth); \
336    iSAD += calc_delta_8(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode) * iQuant;\    iSAD += calc_delta_8(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode, iQuant);\
337    if (iSAD < iMinSAD) \    if (iSAD < iMinSAD) \
338    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \
339  }  }
# Line 490  Line 341 
341  #define NOCHECK_MV8_CANDIDATE(X,Y) \  #define NOCHECK_MV8_CANDIDATE(X,Y) \
342    { \    { \
343      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
344      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\
345      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
346      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
347  }  }
# Line 500  Line 351 
351      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
352    { \    { \
353      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
354      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\
355      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
356      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
357  }  }
# Line 510  Line 361 
361      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
362    { \    { \
363      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
364      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\
365      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
366      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
367  }  }
# Line 520  Line 371 
371      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
372    { \    { \
373      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
374      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\
375      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
376      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
377  }  }
# Line 535  Line 386 
386                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
387                                          const int x, const int y,                                          const int x, const int y,
388                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
389                                            const uint32_t iQuant,
390                                            const uint32_t iFcode,
391                                          MBParam * const pParam,                                          MBParam * const pParam,
392                                          MACROBLOCK * const pMBs,                                          const MACROBLOCK * const pMBs,
393                                            const MACROBLOCK * const prevMBs,
394                                          VECTOR * const currMV,                                          VECTOR * const currMV,
395                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
396  {  {
397          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
         const int32_t iQuant = pParam->quant;  
398          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
399          int32_t iSAD;          int32_t iSAD;
400          int32_t pred_x,pred_y;          VECTOR pred;
401    
402    
403          get_pmv(pMBs, x, y, pParam->mb_width, 0, &pred_x, &pred_y);          pred = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
404    
405          iSAD = sad16( cur,          iSAD = sad16( cur,
406                  get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0,0, iEdgedWidth),                  get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0,0, iEdgedWidth),
# Line 556  Line 410 
410    
411          currMV->x = 0;          currMV->x = 0;
412          currMV->y = 0;          currMV->y = 0;
413          currPMV->x = -pred_x;          currPMV->x = -pred.x;
414          currPMV->y = -pred_y;          currPMV->y = -pred.y;
415    
416          return iSAD;          return iSAD;
417    
418  }  }
419  */  */
420    
421  int32_t Diamond16_MainSearch(  int32_t
422          const uint8_t * const pRef,  Diamond16_MainSearch(const uint8_t * const pRef,
423          const uint8_t * const pRefH,          const uint8_t * const pRefH,
424          const uint8_t * const pRefV,          const uint8_t * const pRefV,
425          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
426          const uint8_t * const cur,          const uint8_t * const cur,
427          const int x, const int y,                                           const int x,
428          int32_t startx, int32_t starty,                                           const int y,
429                                             int32_t startx,
430                                             int32_t starty,
431          int32_t iMinSAD,          int32_t iMinSAD,
432          VECTOR * const currMV,          VECTOR * const currMV,
433          const VECTOR * const pmv,          const VECTOR * const pmv,
434          const int32_t min_dx, const int32_t max_dx,                                           const int32_t min_dx,
435          const int32_t min_dy, const int32_t max_dy,                                           const int32_t max_dx,
436                                             const int32_t min_dy,
437                                             const int32_t max_dy,
438          const int32_t iEdgedWidth,          const int32_t iEdgedWidth,
439          const int32_t iDiamondSize,          const int32_t iDiamondSize,
440          const int32_t iFcode,          const int32_t iFcode,
# Line 588  Line 446 
446          int32_t iDirection=0;          int32_t iDirection=0;
447          int32_t iSAD;          int32_t iSAD;
448          VECTOR backupMV;          VECTOR backupMV;
449    
450          backupMV.x = startx;          backupMV.x = startx;
451          backupMV.y = starty;          backupMV.y = starty;
452    
# Line 599  Line 458 
458          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
459    
460          if (iDirection)          if (iDirection)
461                  while (!iFound)                  while (!iFound) {
                 {  
462                          iFound = 1;                          iFound = 1;
463                          backupMV=*currMV;                          backupMV=*currMV;
464    
465                          if ( iDirection != 2)                          if ( iDirection != 2)
466                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
467                                                                                       backupMV.y, 1);
468                          if ( iDirection != 1)                          if ( iDirection != 1)
469                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
470                                                                                       backupMV.y, 2);
471                          if ( iDirection != 4)                          if ( iDirection != 4)
472                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
473                                                                                       backupMV.y - iDiamondSize, 3);
474                          if ( iDirection != 3)                          if ( iDirection != 3)
475                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
476                  }                                                                                     backupMV.y + iDiamondSize, 4);
477          else          } else {
         {  
478                  currMV->x = startx;                  currMV->x = startx;
479                  currMV->y = starty;                  currMV->y = starty;
480          }          }
481          return iMinSAD;          return iMinSAD;
482  }  }
483    
484  int32_t Square16_MainSearch(  int32_t
485                                          const uint8_t * const pRef,  Square16_MainSearch(const uint8_t * const pRef,
486                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
487                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
488                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
489                                          const uint8_t * const cur,                                          const uint8_t * const cur,
490                                          const int x, const int y,                                          const int x,
491                                          int32_t startx, int32_t starty,                                          const int y,
492                                            int32_t startx,
493                                            int32_t starty,
494                                          int32_t iMinSAD,                                          int32_t iMinSAD,
495                                          VECTOR * const currMV,                                          VECTOR * const currMV,
496                                          const VECTOR * const pmv,                                          const VECTOR * const pmv,
497                                          const int32_t min_dx, const int32_t max_dx,                                          const int32_t min_dx,
498                                          const int32_t min_dy, const int32_t max_dy,                                          const int32_t max_dx,
499                                            const int32_t min_dy,
500                                            const int32_t max_dy,
501                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
502                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
503                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 645  Line 509 
509          int32_t iDirection=0;          int32_t iDirection=0;
510          int32_t iSAD;          int32_t iSAD;
511          VECTOR backupMV;          VECTOR backupMV;
512    
513          backupMV.x = startx;          backupMV.x = startx;
514          backupMV.y = starty;          backupMV.y = starty;
515    
# Line 661  Line 526 
526          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
527          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
528    
529          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);          CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
530          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                           backupMV.y - iDiamondSize, 5);
531          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);          CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
532          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                                           backupMV.y + iDiamondSize, 6);
533            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
534                                                             backupMV.y - iDiamondSize, 7);
535            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
536                                                             backupMV.y + iDiamondSize, 8);
537    
538    
539          if (iDirection)          if (iDirection)
540                  while (!iFound)                  while (!iFound) {
                 {  
541                          iFound = 1;                          iFound = 1;
542                          backupMV=*currMV;                          backupMV=*currMV;
543    
544                          switch (iDirection)                          switch (iDirection) {
                         {  
545                                  case 1:                                  case 1:
546                                          CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
547                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                     backupMV.y, 1);
548                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
549                                                                                     backupMV.y - iDiamondSize, 5);
550                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
551                                                                                     backupMV.y - iDiamondSize, 7);
552                                          break;                                          break;
553                                  case 2:                                  case 2:
554                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y,
555                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                                                   2);
556                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
557                                                                                     backupMV.y + iDiamondSize, 6);
558                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
559                                                                                     backupMV.y + iDiamondSize, 8);
560                                          break;                                          break;
561    
562                                  case 3:                                  case 3:
563                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize,
564                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
565                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
566                                                                                     backupMV.y - iDiamondSize, 7);
567                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
568                                                                                     backupMV.y + iDiamondSize, 8);
569                                          break;                                          break;
570    
571                                  case 4:                                  case 4:
572                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize,
573                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
574                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
575                                                                                     backupMV.y - iDiamondSize, 5);
576                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
577                                                                                     backupMV.y + iDiamondSize, 6);
578                                          break;                                          break;
579    
580                                  case 5:                                  case 5:
581                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y,
582                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                   1);
583                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize,
584                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                                                   3);
585                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
586                                                                                     backupMV.y - iDiamondSize, 5);
587                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
588                                                                                     backupMV.y + iDiamondSize, 6);
589                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
590                                                                                     backupMV.y - iDiamondSize, 7);
591                                          break;                                          break;
592    
593                                  case 6:                                  case 6:
594                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y,
595                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                   2);
596                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize,
597                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
598                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);  
599                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
600                                                                                     backupMV.y - iDiamondSize, 5);
601                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
602                                                                                     backupMV.y + iDiamondSize, 6);
603                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
604                                                                                     backupMV.y + iDiamondSize, 8);
605    
606                                          break;                                          break;
607    
608                                  case 7:                                  case 7:
609                                          CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
610                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                     backupMV.y, 1);
611                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize,
612                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
613                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
614                                                                                     backupMV.y - iDiamondSize, 5);
615                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
616                                                                                     backupMV.y - iDiamondSize, 7);
617                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
618                                                                                     backupMV.y + iDiamondSize, 8);
619                                          break;                                          break;
620    
621                                  case 8:                                  case 8:
622                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y,
623                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                   2);
624                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize,
625                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
626                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
627                                                                                     backupMV.y + iDiamondSize, 6);
628                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
629                                                                                     backupMV.y - iDiamondSize, 7);
630                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
631                                                                                     backupMV.y + iDiamondSize, 8);
632                                          break;                                          break;
633                          default:                          default:
634                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y,
635                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                                                                   1);
636                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y,
637                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                   2);
638                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize,
639                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
640                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize,
641                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
642                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);  
643                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
644                                                                                     backupMV.y - iDiamondSize, 5);
645                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
646                                                                                     backupMV.y + iDiamondSize, 6);
647                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
648                                                                                     backupMV.y - iDiamondSize, 7);
649                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
650                                                                                     backupMV.y + iDiamondSize, 8);
651                                          break;                                          break;
652                          }                          }
653                  }          } else {
         else  
                 {  
654                          currMV->x = startx;                          currMV->x = startx;
655                          currMV->y = starty;                          currMV->y = starty;
656                  }                  }
# Line 753  Line 658 
658  }  }
659    
660    
661  int32_t Full16_MainSearch(  int32_t
662                                          const uint8_t * const pRef,  Full16_MainSearch(const uint8_t * const pRef,
663                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
664                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
665                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
666                                          const uint8_t * const cur,                                          const uint8_t * const cur,
667                                          const int x, const int y,                                    const int x,
668                                          int32_t startx, int32_t starty,                                    const int y,
669                                      int32_t startx,
670                                      int32_t starty,
671                                          int32_t iMinSAD,                                          int32_t iMinSAD,
672                                          VECTOR * const currMV,                                          VECTOR * const currMV,
673                                          const VECTOR * const pmv,                                          const VECTOR * const pmv,
674                                          const int32_t min_dx, const int32_t max_dx,                                    const int32_t min_dx,
675                                          const int32_t min_dy, const int32_t max_dy,                                    const int32_t max_dx,
676                                      const int32_t min_dy,
677                                      const int32_t max_dy,
678                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
679                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
680                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 775  Line 684 
684          int32_t iSAD;          int32_t iSAD;
685          int32_t dx,dy;          int32_t dx,dy;
686          VECTOR backupMV;          VECTOR backupMV;
687    
688          backupMV.x = startx;          backupMV.x = startx;
689          backupMV.y = starty;          backupMV.y = starty;
690    
# Line 785  Line 695 
695          return iMinSAD;          return iMinSAD;
696  }  }
697    
698  int32_t Full8_MainSearch(  int32_t
699                                          const uint8_t * const pRef,  AdvDiamond16_MainSearch(const uint8_t * const pRef,
700                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
701                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
702                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
703                                          const uint8_t * const cur,                                          const uint8_t * const cur,
704                                          const int x, const int y,                                                  const int x,
705                                          int32_t startx, int32_t starty,                                                  const int y,
706                                                    int32_t startx,
707                                                    int32_t starty,
708                                                    int32_t iMinSAD,
709                                                    VECTOR * const currMV,
710                                                    const VECTOR * const pmv,
711                                                    const int32_t min_dx,
712                                                    const int32_t max_dx,
713                                                    const int32_t min_dy,
714                                                    const int32_t max_dy,
715                                                    const int32_t iEdgedWidth,
716                                                    const int32_t iDiamondSize,
717                                                    const int32_t iFcode,
718                                                    const int32_t iQuant,
719                                                    int iDirection)
720    {
721    
722            int32_t iSAD;
723    
724    /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
725    
726            if (iDirection) {
727                    CHECK_MV16_CANDIDATE(startx - iDiamondSize, starty);
728                    CHECK_MV16_CANDIDATE(startx + iDiamondSize, starty);
729                    CHECK_MV16_CANDIDATE(startx, starty - iDiamondSize);
730                    CHECK_MV16_CANDIDATE(startx, starty + iDiamondSize);
731            } else {
732                    int bDirection = 1 + 2 + 4 + 8;
733    
734                    do {
735                            iDirection = 0;
736                            if (bDirection & 1)     //we only want to check left if we came from the right (our last motion was to the left, up-left or down-left)
737                                    CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize, starty, 1);
738    
739                            if (bDirection & 2)
740                                    CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize, starty, 2);
741    
742                            if (bDirection & 4)
743                                    CHECK_MV16_CANDIDATE_DIR(startx, starty - iDiamondSize, 4);
744    
745                            if (bDirection & 8)
746                                    CHECK_MV16_CANDIDATE_DIR(startx, starty + iDiamondSize, 8);
747    
748                            /* now we're doing diagonal checks near our candidate */
749    
750                            if (iDirection)         //checking if anything found
751                            {
752                                    bDirection = iDirection;
753                                    iDirection = 0;
754                                    startx = currMV->x;
755                                    starty = currMV->y;
756                                    if (bDirection & 3)     //our candidate is left or right
757                                    {
758                                            CHECK_MV16_CANDIDATE_DIR(startx, starty + iDiamondSize, 8);
759                                            CHECK_MV16_CANDIDATE_DIR(startx, starty - iDiamondSize, 4);
760                                    } else                  // what remains here is up or down
761                                    {
762                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize, starty, 2);
763                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize, starty, 1);
764                                    }
765    
766                                    if (iDirection) {
767                                            bDirection += iDirection;
768                                            startx = currMV->x;
769                                            starty = currMV->y;
770                                    }
771                            } else                          //about to quit, eh? not so fast....
772                            {
773                                    switch (bDirection) {
774                                    case 2:
775                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
776                                                                                             starty - iDiamondSize, 2 + 4);
777                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
778                                                                                             starty + iDiamondSize, 2 + 8);
779                                            break;
780                                    case 1:
781                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
782                                                                                             starty - iDiamondSize, 1 + 4);
783                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
784                                                                                             starty + iDiamondSize, 1 + 8);
785                                            break;
786                                    case 2 + 4:
787                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
788                                                                                             starty - iDiamondSize, 1 + 4);
789                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
790                                                                                             starty - iDiamondSize, 2 + 4);
791                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
792                                                                                             starty + iDiamondSize, 2 + 8);
793                                            break;
794                                    case 4:
795                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
796                                                                                             starty - iDiamondSize, 2 + 4);
797                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
798                                                                                             starty - iDiamondSize, 1 + 4);
799                                            break;
800                                    case 8:
801                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
802                                                                                             starty + iDiamondSize, 2 + 8);
803                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
804                                                                                             starty + iDiamondSize, 1 + 8);
805                                            break;
806                                    case 1 + 4:
807                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
808                                                                                             starty + iDiamondSize, 1 + 8);
809                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
810                                                                                             starty - iDiamondSize, 1 + 4);
811                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
812                                                                                             starty - iDiamondSize, 2 + 4);
813                                            break;
814                                    case 2 + 8:
815                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
816                                                                                             starty - iDiamondSize, 1 + 4);
817                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
818                                                                                             starty + iDiamondSize, 1 + 8);
819                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
820                                                                                             starty + iDiamondSize, 2 + 8);
821                                            break;
822                                    case 1 + 8:
823                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
824                                                                                             starty - iDiamondSize, 2 + 4);
825                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
826                                                                                             starty + iDiamondSize, 2 + 8);
827                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
828                                                                                             starty + iDiamondSize, 1 + 8);
829                                            break;
830                                    default:                //1+2+4+8 == we didn't find anything at all
831                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
832                                                                                             starty - iDiamondSize, 1 + 4);
833                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
834                                                                                             starty + iDiamondSize, 1 + 8);
835                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
836                                                                                             starty - iDiamondSize, 2 + 4);
837                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
838                                                                                             starty + iDiamondSize, 2 + 8);
839                                            break;
840                                    }
841                                    if (!iDirection)
842                                            break;          //ok, the end. really
843                                    else {
844                                            bDirection = iDirection;
845                                            startx = currMV->x;
846                                            starty = currMV->y;
847                                    }
848                            }
849                    }
850                    while (1);                              //forever
851            }
852            return iMinSAD;
853    }
854    
855    int32_t
856    AdvDiamond8_MainSearch(const uint8_t * const pRef,
857                                               const uint8_t * const pRefH,
858                                               const uint8_t * const pRefV,
859                                               const uint8_t * const pRefHV,
860                                               const uint8_t * const cur,
861                                               const int x,
862                                               const int y,
863                                               int32_t startx,
864                                               int32_t starty,
865                                          int32_t iMinSAD,                                          int32_t iMinSAD,
866                                          VECTOR * const currMV,                                          VECTOR * const currMV,
867                                          const VECTOR * const pmv,                                          const VECTOR * const pmv,
868                                          const int32_t min_dx, const int32_t max_dx,                                             const int32_t min_dx,
869                                          const int32_t min_dy, const int32_t max_dy,                                             const int32_t max_dx,
870                                               const int32_t min_dy,
871                                               const int32_t max_dy,
872                                               const int32_t iEdgedWidth,
873                                               const int32_t iDiamondSize,
874                                               const int32_t iFcode,
875                                               const int32_t iQuant,
876                                               int iDirection)
877    {
878    
879            int32_t iSAD;
880    
881    /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
882    
883            if (iDirection) {
884                    CHECK_MV8_CANDIDATE(startx - iDiamondSize, starty);
885                    CHECK_MV8_CANDIDATE(startx + iDiamondSize, starty);
886                    CHECK_MV8_CANDIDATE(startx, starty - iDiamondSize);
887                    CHECK_MV8_CANDIDATE(startx, starty + iDiamondSize);
888            } else {
889                    int bDirection = 1 + 2 + 4 + 8;
890    
891                    do {
892                            iDirection = 0;
893                            if (bDirection & 1)     //we only want to check left if we came from the right (our last motion was to the left, up-left or down-left)
894                                    CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize, starty, 1);
895    
896                            if (bDirection & 2)
897                                    CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize, starty, 2);
898    
899                            if (bDirection & 4)
900                                    CHECK_MV8_CANDIDATE_DIR(startx, starty - iDiamondSize, 4);
901    
902                            if (bDirection & 8)
903                                    CHECK_MV8_CANDIDATE_DIR(startx, starty + iDiamondSize, 8);
904    
905                            /* now we're doing diagonal checks near our candidate */
906    
907                            if (iDirection)         //checking if anything found
908                            {
909                                    bDirection = iDirection;
910                                    iDirection = 0;
911                                    startx = currMV->x;
912                                    starty = currMV->y;
913                                    if (bDirection & 3)     //our candidate is left or right
914                                    {
915                                            CHECK_MV8_CANDIDATE_DIR(startx, starty + iDiamondSize, 8);
916                                            CHECK_MV8_CANDIDATE_DIR(startx, starty - iDiamondSize, 4);
917                                    } else                  // what remains here is up or down
918                                    {
919                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize, starty, 2);
920                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize, starty, 1);
921                                    }
922    
923                                    if (iDirection) {
924                                            bDirection += iDirection;
925                                            startx = currMV->x;
926                                            starty = currMV->y;
927                                    }
928                            } else                          //about to quit, eh? not so fast....
929                            {
930                                    switch (bDirection) {
931                                    case 2:
932                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
933                                                                                            starty - iDiamondSize, 2 + 4);
934                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
935                                                                                            starty + iDiamondSize, 2 + 8);
936                                            break;
937                                    case 1:
938                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
939                                                                                            starty - iDiamondSize, 1 + 4);
940                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
941                                                                                            starty + iDiamondSize, 1 + 8);
942                                            break;
943                                    case 2 + 4:
944                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
945                                                                                            starty - iDiamondSize, 1 + 4);
946                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
947                                                                                            starty - iDiamondSize, 2 + 4);
948                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
949                                                                                            starty + iDiamondSize, 2 + 8);
950                                            break;
951                                    case 4:
952                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
953                                                                                            starty - iDiamondSize, 2 + 4);
954                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
955                                                                                            starty - iDiamondSize, 1 + 4);
956                                            break;
957                                    case 8:
958                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
959                                                                                            starty + iDiamondSize, 2 + 8);
960                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
961                                                                                            starty + iDiamondSize, 1 + 8);
962                                            break;
963                                    case 1 + 4:
964                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
965                                                                                            starty + iDiamondSize, 1 + 8);
966                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
967                                                                                            starty - iDiamondSize, 1 + 4);
968                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
969                                                                                            starty - iDiamondSize, 2 + 4);
970                                            break;
971                                    case 2 + 8:
972                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
973                                                                                            starty - iDiamondSize, 1 + 4);
974                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
975                                                                                            starty + iDiamondSize, 1 + 8);
976                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
977                                                                                            starty + iDiamondSize, 2 + 8);
978                                            break;
979                                    case 1 + 8:
980                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
981                                                                                            starty - iDiamondSize, 2 + 4);
982                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
983                                                                                            starty + iDiamondSize, 2 + 8);
984                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
985                                                                                            starty + iDiamondSize, 1 + 8);
986                                            break;
987                                    default:                //1+2+4+8 == we didn't find anything at all
988                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
989                                                                                            starty - iDiamondSize, 1 + 4);
990                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
991                                                                                            starty + iDiamondSize, 1 + 8);
992                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
993                                                                                            starty - iDiamondSize, 2 + 4);
994                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
995                                                                                            starty + iDiamondSize, 2 + 8);
996                                            break;
997                                    }
998                                    if (!(iDirection))
999                                            break;          //ok, the end. really
1000                                    else {
1001                                            bDirection = iDirection;
1002                                            startx = currMV->x;
1003                                            starty = currMV->y;
1004                                    }
1005                            }
1006                    }
1007                    while (1);                              //forever
1008            }
1009            return iMinSAD;
1010    }
1011    
1012    
1013    int32_t
1014    Full8_MainSearch(const uint8_t * const pRef,
1015                                     const uint8_t * const pRefH,
1016                                     const uint8_t * const pRefV,
1017                                     const uint8_t * const pRefHV,
1018                                     const uint8_t * const cur,
1019                                     const int x,
1020                                     const int y,
1021                                     int32_t startx,
1022                                     int32_t starty,
1023                                     int32_t iMinSAD,
1024                                     VECTOR * const currMV,
1025                                     const VECTOR * const pmv,
1026                                     const int32_t min_dx,
1027                                     const int32_t max_dx,
1028                                     const int32_t min_dy,
1029                                     const int32_t max_dy,
1030                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
1031                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
1032                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 807  Line 1036 
1036          int32_t iSAD;          int32_t iSAD;
1037          int32_t dx,dy;          int32_t dx,dy;
1038          VECTOR backupMV;          VECTOR backupMV;
1039    
1040          backupMV.x = startx;          backupMV.x = startx;
1041          backupMV.y = starty;          backupMV.y = starty;
1042    
# Line 819  Line 1049 
1049    
1050    
1051    
1052  int32_t Halfpel16_Refine(  int32_t
1053          const uint8_t * const pRef,  Halfpel16_Refine(const uint8_t * const pRef,
1054          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1055          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1056          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1057          const uint8_t * const cur,          const uint8_t * const cur,
1058          const int x, const int y,                                   const int x,
1059                                     const int y,
1060          VECTOR * const currMV,          VECTOR * const currMV,
1061          int32_t iMinSAD,          int32_t iMinSAD,
1062          const VECTOR * const pmv,          const VECTOR * const pmv,
1063          const int32_t min_dx, const int32_t max_dx,                                   const int32_t min_dx,
1064          const int32_t min_dy, const int32_t max_dy,                                   const int32_t max_dx,
1065                                     const int32_t min_dy,
1066                                     const int32_t max_dy,
1067          const int32_t iFcode,          const int32_t iFcode,
1068          const int32_t iQuant,          const int32_t iQuant,
1069          const int32_t iEdgedWidth)          const int32_t iEdgedWidth)
# Line 855  Line 1088 
1088  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)
1089    
1090    
1091  int32_t PMVfastSearch16(  int32_t
1092                                          const uint8_t * const pRef,  PMVfastSearch16(const uint8_t * const pRef,
1093                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1094                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1095                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1096                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1097                                          const int x, const int y,                                  const int x,
1098                                    const int y,
1099                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
1100                                    const uint32_t iQuant,
1101                                    const uint32_t iFcode,
1102                                          const MBParam * const pParam,                                          const MBParam * const pParam,
1103                                          MACROBLOCK * const pMBs,                                  const MACROBLOCK * const pMBs,
1104                                    const MACROBLOCK * const prevMBs,
1105                                          VECTOR * const currMV,                                          VECTOR * const currMV,
1106                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
1107  {  {
1108          const uint32_t iWcount = pParam->mb_width;          const uint32_t iWcount = pParam->mb_width;
         const int32_t iFcode = pParam->fixed_code;  
         const int32_t iQuant = pParam->quant;  
1109          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
1110          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
1111          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
# Line 892  Line 1127 
1127          VECTOR pmv[4];          VECTOR pmv[4];
1128          int32_t psad[4];          int32_t psad[4];
1129    
1130          MACROBLOCK * const pMB = pMBs + x + y * iWcount;          MainSearch16FuncPtr MainSearchPtr;
1131    
1132            const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
1133    
1134          static int32_t threshA,threshB;          int32_t threshA, threshB;
1135          int32_t bPredEq;          int32_t bPredEq;
1136          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
1137    
1138  /* Get maximum range */  /* Get maximum range */
1139          get_range(&min_dx, &max_dx, &min_dy, &max_dy,          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight,
1140                    x, y, 16, iWidth, iHeight, iFcode);                            iFcode);
1141    
1142  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
1143    
1144          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16)) {
1145          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
1146          max_dx = EVEN(max_dx);          max_dx = EVEN(max_dx);
1147          min_dy = EVEN(min_dy);          min_dy = EVEN(min_dy);
1148          max_dy = EVEN(max_dy);          max_dy = EVEN(max_dy);
         }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */  
   
   
         bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);  
   
         if ((x==0) && (y==0) )  
         {  
                 threshA =  512;  
                 threshB = 1024;  
   
1149          }          }
         else  
         {  
                 threshA = psad[0];  
                 threshB = threshA+256;  
                 if (threshA< 512) threshA =  512;  
                 if (threshA>1024) threshA = 1024;  
                 if (threshB>1792) threshB = 1792;  
         }  
   
         iFound=0;  
1150    
1151  /* Step 2: Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion          /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1152     vector of the median.          bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
1153     If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2          // bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
 */  
   
         if ((bPredEq) && (MVequal(pmv[0],pMB->mvs[0]) ) )  
                 iFound=2;  
1154    
1155  /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.  /*      fprintf(stderr,"pmv: %d %d / %d --- %d %d   %d %d   %d %d - %d %d %d\n",
1156     Otherwise select large Diamond Search.                  pmv[0].x,pmv[0].y,psad[0],
1157                    pmv[1].x,pmv[1].y,pmv[2].x,pmv[2].y,pmv[3].x,pmv[3].y,
1158                    psad[1],psad[2],psad[3]);
1159  */  */
1160            if ((x == 0) && (y == 0)) {
1161                    threshA = 512;
1162                    threshB = 1024;
1163            } else {
1164                    threshA = psad[0];
1165                    threshB = threshA + 256;
1166                    if (threshA < 512)
1167                            threshA = 512;
1168                    if (threshA > 1024)
1169                            threshA = 1024;
1170                    if (threshB > 1792)
1171                            threshB = 1792;
1172            }
1173    
1174          if ( (pmv[0].x != 0) || (pmv[0].y != 0) || (threshB<1536) || (bPredEq) )          iFound = 0;
                 iDiamondSize=1; // halfpel!  
         else  
                 iDiamondSize=2; // halfpel!  
   
         if (!(MotionFlags & PMV_HALFPELDIAMOND16) )  
                 iDiamondSize*=2;  
1175    
1176  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
1177     MinSAD=SAD     MinSAD=SAD
# Line 958  Line 1180 
1180     If SAD<=256 goto Step 10.     If SAD<=256 goto Step 10.
1181  */  */
1182    
   
 // Prepare for main loop  
   
1183          *currMV=pmv[0];         /* current best := prediction */          *currMV=pmv[0];         /* current best := prediction */
1184          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16)) {   /* This should NOT be necessary! */
         {       /* This should NOT be necessary! */  
1185                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
1186                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
1187          }          }
1188    
1189          if (currMV->x > max_dx)          if (currMV->x > max_dx) {
         {  
1190                  currMV->x=max_dx;                  currMV->x=max_dx;
1191          }          }
1192          if (currMV->x < min_dx)          if (currMV->x < min_dx) {
         {  
1193                  currMV->x=min_dx;                  currMV->x=min_dx;
1194          }          }
1195          if (currMV->y > max_dy)          if (currMV->y > max_dy) {
         {  
1196                  currMV->y=max_dy;                  currMV->y=max_dy;
1197          }          }
1198          if (currMV->y < min_dy)          if (currMV->y < min_dy) {
         {  
1199                  currMV->y=min_dy;                  currMV->y=min_dy;
1200          }          }
1201    
1202          iMinSAD = sad16( cur,          iMinSAD =
1203                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  sad16(cur,
1204                           iEdgedWidth, MV_MAX_ERROR);                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
1205          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
1206            iMinSAD +=
1207          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,pMB->mvs[0])) && (iMinSAD < pMB->sad16) ) )                  calc_delta_16(currMV->x - pmv[0].x, currMV->y - pmv[0].y,
1208          {                                            (uint8_t) iFcode, iQuant);
1209    
1210            if ((iMinSAD < 256) ||
1211                    ((MVequal(*currMV, prevMB->mvs[0])) &&
1212                     ((uint32_t) iMinSAD < prevMB->sad16))) {
1213                    if (iMinSAD < 2 * iQuant)       // high chances for SKIP-mode
1214                    {
1215                            if (!MVzero(*currMV)) {
1216                                    iMinSAD += MV16_00_BIAS;
1217                                    CHECK_MV16_ZERO;        // (0,0) saves space for letterboxed pictures
1218                                    iMinSAD -= MV16_00_BIAS;
1219                            }
1220                    }
1221    
1222                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1223                          goto PMVfast16_Terminate_without_Refine;                          goto PMVfast16_Terminate_without_Refine;
# Line 999  Line 1225 
1225                          goto PMVfast16_Terminate_with_Refine;                          goto PMVfast16_Terminate_with_Refine;
1226          }          }
1227    
1228    
1229    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
1230       vector of the median.
1231       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
1232    */
1233    
1234            if ((bPredEq) && (MVequal(pmv[0], prevMB->mvs[0])))
1235                    iFound = 2;
1236    
1237    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
1238       Otherwise select large Diamond Search.
1239    */
1240    
1241            if ((!MVzero(pmv[0])) || (threshB < 1536) || (bPredEq))
1242                    iDiamondSize = 1;               // halfpel!
1243            else
1244                    iDiamondSize = 2;               // halfpel!
1245    
1246            if (!(MotionFlags & PMV_HALFPELDIAMOND16))
1247                    iDiamondSize *= 2;
1248    
1249  /*  /*
1250     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.
1251     Also calculate (0,0) but do not subtract offset.     Also calculate (0,0) but do not subtract offset.
1252     Let MinSAD be the smallest SAD up to this point.     Let MinSAD be the smallest SAD up to this point.
1253     If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
1254  */  */
1255    
1256  // (0,0) is always possible  // (0,0) is always possible
1257    
1258            if (!MVzero(pmv[0]))
1259          CHECK_MV16_ZERO;          CHECK_MV16_ZERO;
1260    
1261  // previous frame MV is always possible  // previous frame MV is always possible
1262          CHECK_MV16_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);  
1263            if (!MVzero(prevMB->mvs[0]))
1264                    if (!MVequal(prevMB->mvs[0], pmv[0]))
1265                            CHECK_MV16_CANDIDATE(prevMB->mvs[0].x, prevMB->mvs[0].y);
1266    
1267  // left neighbour, if allowed  // left neighbour, if allowed
1268          if (x != 0)  
1269          {          if (!MVzero(pmv[1]))
1270                  if (!(MotionFlags & PMV_HALFPEL16 ))                  if (!MVequal(pmv[1], prevMB->mvs[0]))
1271                  {       pmv[1].x = EVEN(pmv[1].x);                          if (!MVequal(pmv[1], pmv[0])) {
1272                                    if (!(MotionFlags & PMV_HALFPEL16)) {
1273                                            pmv[1].x = EVEN(pmv[1].x);
1274                  pmv[1].y = EVEN(pmv[1].y);                  pmv[1].y = EVEN(pmv[1].y);
1275                  }                  }
1276    
1277                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1278          }          }
   
1279  // top neighbour, if allowed  // top neighbour, if allowed
1280          if (y != 0)          if (!MVzero(pmv[2]))
1281          {                  if (!MVequal(pmv[2], prevMB->mvs[0]))
1282                  if (!(MotionFlags & PMV_HALFPEL16 ))                          if (!MVequal(pmv[2], pmv[0]))
1283                  {       pmv[2].x = EVEN(pmv[2].x);                                  if (!MVequal(pmv[2], pmv[1])) {
1284                                            if (!(MotionFlags & PMV_HALFPEL16)) {
1285                                                    pmv[2].x = EVEN(pmv[2].x);
1286                  pmv[2].y = EVEN(pmv[2].y);                  pmv[2].y = EVEN(pmv[2].y);
1287                  }                  }
1288                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1289    
1290  // top right neighbour, if allowed  // top right neighbour, if allowed
1291                  if (x != (iWcount-1))                                          if (!MVzero(pmv[3]))
1292                  {                                                  if (!MVequal(pmv[3], prevMB->mvs[0]))
1293                          if (!(MotionFlags & PMV_HALFPEL16 ))                                                          if (!MVequal(pmv[3], pmv[0]))
1294                          {       pmv[3].x = EVEN(pmv[3].x);                                                                  if (!MVequal(pmv[3], pmv[1]))
1295                                                                            if (!MVequal(pmv[3], pmv[2])) {
1296                                                                                    if (!(MotionFlags & PMV_HALFPEL16)) {
1297                                                                                            pmv[3].x = EVEN(pmv[3].x);
1298                          pmv[3].y = EVEN(pmv[3].y);                          pmv[3].y = EVEN(pmv[3].y);
1299                          }                          }
1300                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                  CHECK_MV16_CANDIDATE(pmv[3].x,
1301                                                                                                                             pmv[3].y);
1302                  }                  }
1303          }          }
1304    
1305            if ((MVzero(*currMV)) &&
1306                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
1307                    iMinSAD -= MV16_00_BIAS;
1308    
1309    
1310  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
1311     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.
1312  */  */
1313    
1314          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[0]) && (iMinSAD < pMB->sad16) ) )          if ((iMinSAD <= threshA) ||
1315          {                  (MVequal(*currMV, prevMB->mvs[0]) &&
1316                     ((uint32_t) iMinSAD < prevMB->sad16))) {
1317                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1318                          goto PMVfast16_Terminate_without_Refine;                          goto PMVfast16_Terminate_without_Refine;
1319                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1066  Line 1331 
1331     Refine by using small diamond and goto step 10.     Refine by using small diamond and goto step 10.
1332  */  */
1333    
1334            if (MotionFlags & PMV_USESQUARES16)
1335                    MainSearchPtr = Square16_MainSearch;
1336            else if (MotionFlags & PMV_ADVANCEDDIAMOND16)
1337                    MainSearchPtr = AdvDiamond16_MainSearch;
1338            else
1339                    MainSearchPtr = Diamond16_MainSearch;
1340    
1341          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1342    
1343    
1344    //      fprintf(stderr,"Entering Diamond %d %d (%d):\n",x,y,iMinSAD);
1345    
1346  /* 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 */
1347          iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
1348                                            x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
1349                                            currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx,
1350                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
1351                                                      iQuant, iFound);
1352    
1353          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
1354                  *currMV = newMV;                  *currMV = newMV;
1355                  iMinSAD = iSAD;                  iMinSAD = iSAD;
1356          }          }
1357    
1358          if (MotionFlags & PMV_EXTSEARCH16)          if (MotionFlags & PMV_EXTSEARCH16) {
         {  
1359  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1360    
1361                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
1362                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1363                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1364                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, pmv,
1365                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1366                                                                      iDiamondSize, iFcode, iQuant, iFound);
1367    
1368                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1369                          *currMV = newMV;                          *currMV = newMV;
1370                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1371                  }                  }
1372                  }                  }
1373    
1374                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
1375                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1376                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
1377                                                            0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy,
1378                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
1379                                                                      iQuant, iFound);
1380    
1381                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1382                          *currMV = newMV;                          *currMV = newMV;
1383                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1384                  }                  }
# Line 1117  Line 1391 
1391    
1392  PMVfast16_Terminate_with_Refine:  PMVfast16_Terminate_with_Refine:
1393          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
1394                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
1395                                    x, y,                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
1396                                    currMV, iMinSAD,                                                           iMinSAD, pmv, min_dx, max_dx, min_dy, max_dy,
1397                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                           iFcode, iQuant, iEdgedWidth);
1398    
1399    /*fprintf(stderr,"Chosen for %d %d: %d %d - %d %d\n",x,y,currMV->x,currMV->y,pmv[0].x,pmv[0].y);
1400    */
1401  PMVfast16_Terminate_without_Refine:  PMVfast16_Terminate_without_Refine:
1402          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - pmv[0].x;
1403          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - pmv[0].y;
# Line 1133  Line 1409 
1409    
1410    
1411    
1412  int32_t Diamond8_MainSearch(  int32_t
1413          const uint8_t * const pRef,  Diamond8_MainSearch(const uint8_t * const pRef,
1414          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1415          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1416          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1417          const uint8_t * const cur,          const uint8_t * const cur,
1418          const int x, const int y,                                          const int x,
1419          int32_t startx, int32_t starty,                                          const int y,
1420                                            int32_t startx,
1421                                            int32_t starty,
1422          int32_t iMinSAD,          int32_t iMinSAD,
1423          VECTOR * const currMV,          VECTOR * const currMV,
1424          const VECTOR * const pmv,          const VECTOR * const pmv,
1425          const int32_t min_dx, const int32_t max_dx,                                          const int32_t min_dx,
1426          const int32_t min_dy, const int32_t max_dy,                                          const int32_t max_dx,
1427                                            const int32_t min_dy,
1428                                            const int32_t max_dy,
1429          const int32_t iEdgedWidth,          const int32_t iEdgedWidth,
1430          const int32_t iDiamondSize,          const int32_t iDiamondSize,
1431          const int32_t iFcode,          const int32_t iFcode,
# Line 1157  Line 1437 
1437          int32_t iDirection=0;          int32_t iDirection=0;
1438          int32_t iSAD;          int32_t iSAD;
1439          VECTOR backupMV;          VECTOR backupMV;
1440    
1441          backupMV.x = startx;          backupMV.x = startx;
1442          backupMV.y = starty;          backupMV.y = starty;
1443    
# Line 1168  Line 1449 
1449          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
1450    
1451          if (iDirection)          if (iDirection)
1452                  while (!iFound)                  while (!iFound) {
                 {  
1453                          iFound = 1;                          iFound = 1;
1454                          backupMV=*currMV;       // since iDirection!=0, this is well defined!                          backupMV=*currMV;       // since iDirection!=0, this is well defined!
1455    
1456                          if ( iDirection != 2)                          if ( iDirection != 2)
1457                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1458                                                                                      backupMV.y, 1);
1459                          if ( iDirection != 1)                          if ( iDirection != 1)
1460                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1461                                                                                      backupMV.y, 2);
1462                          if ( iDirection != 4)                          if ( iDirection != 4)
1463                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1464                                                                                      backupMV.y - iDiamondSize, 3);
1465                          if ( iDirection != 3)                          if ( iDirection != 3)
1466                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1467                  }                                                                                    backupMV.y + iDiamondSize, 4);
1468          else          } else {
         {  
1469                  currMV->x = startx;                  currMV->x = startx;
1470                  currMV->y = starty;                  currMV->y = starty;
1471          }          }
1472          return iMinSAD;          return iMinSAD;
1473  }  }
1474    
1475  int32_t Halfpel8_Refine(  int32_t
1476          const uint8_t * const pRef,  Halfpel8_Refine(const uint8_t * const pRef,
1477          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1478          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1479          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1480          const uint8_t * const cur,          const uint8_t * const cur,
1481          const int x, const int y,                                  const int x,
1482                                    const int y,
1483          VECTOR * const currMV,          VECTOR * const currMV,
1484          int32_t iMinSAD,          int32_t iMinSAD,
1485          const VECTOR * const pmv,          const VECTOR * const pmv,
1486          const int32_t min_dx, const int32_t max_dx,                                  const int32_t min_dx,
1487          const int32_t min_dy, const int32_t max_dy,                                  const int32_t max_dx,
1488                                    const int32_t min_dy,
1489                                    const int32_t max_dy,
1490          const int32_t iFcode,          const int32_t iFcode,
1491          const int32_t iQuant,          const int32_t iQuant,
1492          const int32_t iEdgedWidth)          const int32_t iEdgedWidth)
# Line 1226  Line 1511 
1511    
1512  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)
1513    
1514  int32_t PMVfastSearch8(  int32_t
1515                                          const uint8_t * const pRef,  PMVfastSearch8(const uint8_t * const pRef,
1516                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1517                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1518                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1519                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1520                                          const int x, const int y,                             const int x,
1521                                          const int start_x, int start_y,                             const int y,
1522                               const int start_x,
1523                               const int start_y,
1524                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
1525                               const uint32_t iQuant,
1526                               const uint32_t iFcode,
1527                                          const MBParam * const pParam,                                          const MBParam * const pParam,
1528                                          MACROBLOCK * const pMBs,                             const MACROBLOCK * const pMBs,
1529                               const MACROBLOCK * const prevMBs,
1530                                          VECTOR * const currMV,                                          VECTOR * const currMV,
1531                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
1532  {  {
1533          const uint32_t iWcount = pParam->mb_width;          const uint32_t iWcount = pParam->mb_width;
   
         const int32_t iFcode = pParam->fixed_code;  
         const int32_t iQuant = pParam->quant;  
1534          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
1535          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
1536          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
# Line 1261  Line 1548 
1548          int32_t psad[4];          int32_t psad[4];
1549          VECTOR newMV;          VECTOR newMV;
1550          VECTOR backupMV;          VECTOR backupMV;
1551            VECTOR startMV;
1552    
1553          MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;  //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1554            const MACROBLOCK *const prevMB = prevMBs + (x >> 1) + (y >> 1) * iWcount;
1555    
1556          static int32_t threshA,threshB;           int32_t threshA, threshB;
1557          int32_t iFound,bPredEq;          int32_t iFound,bPredEq;
1558          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
1559    
1560          int32_t iSubBlock = ((y&1)<<1) + (x&1);          int32_t iSubBlock = (y & 1) + (y & 1) + (x & 1);
1561    
1562  /* Get maximum range */          MainSearch8FuncPtr MainSearchPtr;
         get_range(&min_dx, &max_dx, &min_dy, &max_dy,  
                   x, y, 8, iWidth, iHeight, iFcode);  
1563    
1564  /* we work with abs. MVs, not relative to prediction, so range is relative to 0,0 */          /* Init variables */
1565            startMV.x = start_x;
1566            startMV.y = start_y;
1567    
1568          if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))          /* Get maximum range */
1569          { min_dx = EVEN(min_dx);          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 8, iWidth, iHeight,
1570                              iFcode);
1571    
1572            if (!(MotionFlags & PMV_HALFPELDIAMOND8)) {
1573                    min_dx = EVEN(min_dx);
1574          max_dx = EVEN(max_dx);          max_dx = EVEN(max_dx);
1575          min_dy = EVEN(min_dy);          min_dy = EVEN(min_dy);
1576          max_dy = EVEN(max_dy);          max_dy = EVEN(max_dy);
1577          }               /* because we might use IF (dx>max_dx) THEN dx=max_dx; */          }
   
1578    
1579            /* because we might use IF (dx>max_dx) THEN dx=max_dx; */
1580          bPredEq  = get_pmvdata(pMBs, (x>>1), (y>>1), iWcount, iSubBlock, pmv, psad);          bPredEq  = get_pmvdata(pMBs, (x>>1), (y>>1), iWcount, iSubBlock, pmv, psad);
1581            // bPredEq = get_pmvdata2(pMBs, iWcount, 0, (x >> 1), (y >> 1), iSubBlock, pmv, psad);
1582    
1583          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
1584                  threshA =  512/4;                  threshA =  512/4;
1585                  threshB = 1024/4;                  threshB = 1024/4;
1586    
1587          }          } else {
         else  
         {  
1588                  threshA = psad[0]/4;                    /* good estimate */                  threshA = psad[0]/4;                    /* good estimate */
1589                  threshB = threshA+256/4;                  threshB = threshA+256/4;
1590                  if (threshA< 512/4) threshA =  512/4;                  if (threshA < 512 / 4)
1591                  if (threshA>1024/4) threshA = 1024/4;                          threshA = 512 / 4;
1592                  if (threshB>1792/4) threshB = 1792/4;                  if (threshA > 1024 / 4)
1593                            threshA = 1024 / 4;
1594                    if (threshB > 1792 / 4)
1595                            threshB = 1792 / 4;
1596          }          }
1597    
1598          iFound=0;          iFound=0;
1599    
 /* Step 2: Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion  
    vector of the median.  
    If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2  
 */  
   
         if ((bPredEq) && (MVequal(pmv[0],pMB->mvs[iSubBlock]) ) )  
                 iFound=2;  
   
 /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.  
    Otherwise select large Diamond Search.  
 */  
   
         if ( (pmv[0].x != 0) || (pmv[0].y != 0) || (threshB<1536/4) || (bPredEq) )  
                 iDiamondSize=1; // 1 halfpel!  
         else  
                 iDiamondSize=2; // 2 halfpel = 1 full pixel!  
   
         if (!(MotionFlags & PMV_HALFPELDIAMOND8) )  
                 iDiamondSize*=2;  
   
1600  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
1601     MinSAD=SAD     MinSAD=SAD
1602     If Motion Vector equal to Previous frame motion vector     If Motion Vector equal to Previous frame motion vector
# Line 1333  Line 1607 
1607    
1608  // Prepare for main loop  // Prepare for main loop
1609    
1610          currMV->x=start_x;              /* start with mv16 */  //  if (MotionFlags & PMV_USESQUARES8)
1611          currMV->y=start_y;  //      MainSearchPtr = Square8_MainSearch;
1612    //  else
1613    
1614            if (MotionFlags & PMV_ADVANCEDDIAMOND8)
1615                    MainSearchPtr = AdvDiamond8_MainSearch;
1616            else
1617                    MainSearchPtr = Diamond8_MainSearch;
1618    
         iMinSAD = sad8( cur,  
                         get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),  
                         iEdgedWidth);  
         iMinSAD += calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y, (uint8_t)iFcode) * iQuant;  
1619    
1620          if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,pMB->mvs[iSubBlock])) && (iMinSAD < pMB->sad8[iSubBlock]) ) )          *currMV = startMV;
1621          {  
1622            iMinSAD =
1623                    sad8(cur,
1624                             get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
1625                                                    iEdgedWidth), iEdgedWidth);
1626            iMinSAD +=
1627                    calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y,
1628                                             (uint8_t) iFcode, iQuant);
1629    
1630            if ((iMinSAD < 256 / 4) || ((MVequal(*currMV, prevMB->mvs[iSubBlock]))
1631                                                                    && ((uint32_t) iMinSAD <
1632                                                                            prevMB->sad8[iSubBlock]))) {
1633                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1634                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
1635                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
1636                          goto PMVfast8_Terminate_with_Refine;                          goto PMVfast8_Terminate_with_Refine;
1637          }          }
1638    
1639    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
1640       vector of the median.
1641       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
1642    */
1643    
1644            if ((bPredEq) && (MVequal(pmv[0], prevMB->mvs[iSubBlock])))
1645                    iFound = 2;
1646    
1647    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
1648       Otherwise select large Diamond Search.
1649    */
1650    
1651            if ((!MVzero(pmv[0])) || (threshB < 1536 / 4) || (bPredEq))
1652                    iDiamondSize = 1;               // 1 halfpel!
1653            else
1654                    iDiamondSize = 2;               // 2 halfpel = 1 full pixel!
1655    
1656            if (!(MotionFlags & PMV_HALFPELDIAMOND8))
1657                    iDiamondSize *= 2;
1658    
1659    
1660  /*  /*
1661     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.
1662     Also calculate (0,0) but do not subtract offset.     Also calculate (0,0) but do not subtract offset.
1663     Let MinSAD be the smallest SAD up to this point.     Let MinSAD be the smallest SAD up to this point.
1664     If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
1665  */  */
1666    
1667  // the prediction might be even better than mv16  // the median prediction might be even better than mv16
1668    
1669            if (!MVequal(pmv[0], startMV))
1670          CHECK_MV8_CANDIDATE(pmv[0].x,pmv[0].y);          CHECK_MV8_CANDIDATE(pmv[0].x,pmv[0].y);
1671    
1672  // (0,0) is always possible  // (0,0) if needed
1673            if (!MVzero(pmv[0]))
1674                    if (!MVzero(startMV))
1675          CHECK_MV8_ZERO;          CHECK_MV8_ZERO;
1676    
1677  // previous frame MV is always possible  // previous frame MV if needed
1678          CHECK_MV8_CANDIDATE(pMB->mvs[iSubBlock].x,pMB->mvs[iSubBlock].y);          if (!MVzero(prevMB->mvs[iSubBlock]))
1679                    if (!MVequal(prevMB->mvs[iSubBlock], startMV))
1680                            if (!MVequal(prevMB->mvs[iSubBlock], pmv[0]))
1681                                    CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,
1682                                                                            prevMB->mvs[iSubBlock].y);
1683    
1684            if ((iMinSAD <= threshA) ||
1685                    (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
1686                     ((uint32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
1687                    if (MotionFlags & PMV_QUICKSTOP16)
1688                            goto PMVfast8_Terminate_without_Refine;
1689                    if (MotionFlags & PMV_EARLYSTOP16)
1690                            goto PMVfast8_Terminate_with_Refine;
1691            }
1692    
1693  // left neighbour, if allowed  // left neighbour, if allowed and needed
1694          if (psad[1] != MV_MAX_ERROR)          if (!MVzero(pmv[1]))
1695          {                  if (!MVequal(pmv[1], startMV))
1696                  if (!(MotionFlags & PMV_HALFPEL8 ))                          if (!MVequal(pmv[1], prevMB->mvs[iSubBlock]))
1697                  {       pmv[1].x = EVEN(pmv[1].x);                                  if (!MVequal(pmv[1], pmv[0])) {
1698                                            if (!(MotionFlags & PMV_HALFPEL8)) {
1699                                                    pmv[1].x = EVEN(pmv[1].x);
1700                  pmv[1].y = EVEN(pmv[1].y);                  pmv[1].y = EVEN(pmv[1].y);
1701                  }                  }
1702                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
1703          }          }
1704    // top neighbour, if allowed and needed
1705  // top neighbour, if allowed          if (!MVzero(pmv[2]))
1706          if (psad[2] != MV_MAX_ERROR)                  if (!MVequal(pmv[2], startMV))
1707          {                          if (!MVequal(pmv[2], prevMB->mvs[iSubBlock]))
1708                  if (!(MotionFlags & PMV_HALFPEL8 ))                                  if (!MVequal(pmv[2], pmv[0]))
1709                  {       pmv[2].x = EVEN(pmv[2].x);                                          if (!MVequal(pmv[2], pmv[1])) {
1710                                                    if (!(MotionFlags & PMV_HALFPEL8)) {
1711                                                            pmv[2].x = EVEN(pmv[2].x);
1712                  pmv[2].y = EVEN(pmv[2].y);                  pmv[2].y = EVEN(pmv[2].y);
1713                  }                  }
1714                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
1715    
1716  // top right neighbour, if allowed  // top right neighbour, if allowed and needed
1717                  if (psad[3] != MV_MAX_ERROR)                                                  if (!MVzero(pmv[3]))
1718                  {                                                          if (!MVequal(pmv[3], startMV))
1719                          if (!(MotionFlags & PMV_HALFPEL8 ))                                                                  if (!MVequal(pmv[3], prevMB->mvs[iSubBlock]))
1720                          {       pmv[3].x = EVEN(pmv[3].x);                                                                          if (!MVequal(pmv[3], pmv[0]))
1721                                                                                    if (!MVequal(pmv[3], pmv[1]))
1722                                                                                            if (!MVequal(pmv[3], pmv[2])) {
1723                                                                                                    if (!
1724                                                                                                            (MotionFlags &
1725                                                                                                             PMV_HALFPEL8)) {
1726                                                                                                            pmv[3].x = EVEN(pmv[3].x);
1727                          pmv[3].y = EVEN(pmv[3].y);                          pmv[3].y = EVEN(pmv[3].y);
1728                          }                          }
1729                          CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                                  CHECK_MV8_CANDIDATE(pmv[3].x,
1730                                                                                                                                            pmv[3].y);
1731                  }                  }
1732          }          }
1733    
1734            if ((MVzero(*currMV)) &&
1735                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
1736                    iMinSAD -= MV8_00_BIAS;
1737    
1738    
1739  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
1740     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.
1741  */  */
1742    
1743          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[iSubBlock]) && (iMinSAD < pMB->sad8[iSubBlock]) ) )          if ((iMinSAD <= threshA) ||
1744          {                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
1745                     ((uint32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
1746                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1747                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
1748                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1421  Line 1762 
1762          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1763    
1764  /* 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 */
1765          iSAD = Diamond8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
1766                                           x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
1767                                           currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx,
1768                                           pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
1769                                                      iQuant, iFound);
1770    
1771          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
1772                  *currMV = newMV;                  *currMV = newMV;
1773                  iMinSAD = iSAD;                  iMinSAD = iSAD;
1774          }          }
1775    
1776          if (MotionFlags & PMV_EXTSEARCH8)          if (MotionFlags & PMV_EXTSEARCH8) {
         {  
1777  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1778    
1779                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
1780                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1781                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1782                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, pmv,
1783                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1784                                                                      iDiamondSize, iFcode, iQuant, iFound);
1785    
1786                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1787                          *currMV = newMV;                          *currMV = newMV;
1788                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1789                  }                  }
1790                  }                  }
1791    
1792                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
1793                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1794                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
1795                                                            0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy,
1796                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
1797                                                                      iQuant, iFound);
1798    
1799                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1800                          *currMV = newMV;                          *currMV = newMV;
1801                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1802                  }                  }
# Line 1469  Line 1809 
1809    
1810  PMVfast8_Terminate_with_Refine:  PMVfast8_Terminate_with_Refine:
1811          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
1812                  iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
1813                                                   x, y,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
1814                                                   currMV, iMinSAD,                                                          iMinSAD, pmv, min_dx, max_dx, min_dy, max_dy,
1815                                                   pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
1816    
1817    
1818  PMVfast8_Terminate_without_Refine:  PMVfast8_Terminate_without_Refine:
# Line 1482  Line 1822 
1822          return iMinSAD;          return iMinSAD;
1823  }  }
1824    
1825  int32_t EPZSSearch16(  int32_t
1826                                          const uint8_t * const pRef,  EPZSSearch16(const uint8_t * const pRef,
1827                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1828                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1829                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1830                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1831                                          const int x, const int y,                           const int x,
1832                             const int y,
1833                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
1834                             const uint32_t iQuant,
1835                             const uint32_t iFcode,
1836                                          const MBParam * const pParam,                                          const MBParam * const pParam,
1837                                          MACROBLOCK * const pMBs,                           const MACROBLOCK * const pMBs,
1838                             const MACROBLOCK * const prevMBs,
1839                                          VECTOR * const currMV,                                          VECTOR * const currMV,
1840                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
1841  {  {
1842          const uint32_t iWcount = pParam->mb_width;          const uint32_t iWcount = pParam->mb_width;
1843          const uint32_t iHcount = pParam->mb_height;          const uint32_t iHcount = pParam->mb_height;
         const int32_t iFcode = pParam->fixed_code;  
         const int32_t iQuant = pParam->quant;  
1844    
1845          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
1846          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
# Line 1518  Line 1860 
1860          int32_t psad[8];          int32_t psad[8];
1861    
1862          static MACROBLOCK * oldMBs = NULL;          static MACROBLOCK * oldMBs = NULL;
1863          MACROBLOCK * const pMB = pMBs + x + y * iWcount;  
1864    //  const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
1865            const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
1866          MACROBLOCK * oldMB = NULL;          MACROBLOCK * oldMB = NULL;
1867    
1868          static int32_t thresh2;           int32_t thresh2;
1869          int32_t bPredEq;          int32_t bPredEq;
1870          int32_t iMinSAD,iSAD=9999;          int32_t iMinSAD,iSAD=9999;
1871    
1872          MainSearch16FuncPtr EPZSMainSearchPtr;          MainSearch16FuncPtr MainSearchPtr;
1873    
1874          if (oldMBs == NULL)          if (oldMBs == NULL) {
1875          {       oldMBs = (MACROBLOCK*) calloc(1,iWcount*iHcount*sizeof(MACROBLOCK));                  oldMBs = (MACROBLOCK *) calloc(iWcount * iHcount, sizeof(MACROBLOCK));
1876                  fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));  //      fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));
1877          }          }
1878          oldMB = oldMBs + x + y * iWcount;          oldMB = oldMBs + x + y * iWcount;
1879    
1880  /* Get maximum range */  /* Get maximum range */
1881          get_range(&min_dx, &max_dx, &min_dy, &max_dy,          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight,
1882                          x, y, 16, iWidth, iHeight, iFcode);                            iFcode);
   
 /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */  
1883    
1884          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16)) {
1885          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
1886            max_dx = EVEN(max_dx);            max_dx = EVEN(max_dx);
1887            min_dy = EVEN(min_dy);            min_dy = EVEN(min_dy);
1888            max_dy = EVEN(max_dy);            max_dy = EVEN(max_dy);
1889          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
1890            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1891          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
1892            // bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
1893    
1894  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
1895          MinSAD=SAD          MinSAD=SAD
# Line 1558  Line 1901 
1901  // Prepare for main loop  // Prepare for main loop
1902    
1903          *currMV=pmv[0];         /* current best := median prediction */          *currMV=pmv[0];         /* current best := median prediction */
1904          if (!(MotionFlags & PMV_HALFPEL16))          if (!(MotionFlags & PMV_HALFPEL16)) {
         {  
1905                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
1906                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
1907          }          }
# Line 1575  Line 1917 
1917    
1918  /***************** This is predictor SET A: only median prediction ******************/  /***************** This is predictor SET A: only median prediction ******************/
1919    
1920          iMinSAD = sad16( cur,          iMinSAD =
1921                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  sad16(cur,
1922                  iEdgedWidth, MV_MAX_ERROR);                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
1923          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
1924            iMinSAD +=
1925                    calc_delta_16(currMV->x - pmv[0].x, currMV->y - pmv[0].y,
1926                                              (uint8_t) iFcode, iQuant);
1927    
1928  // thresh1 is fixed to 256  // thresh1 is fixed to 256
1929          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,pMB->mvs[0])) && (iMinSAD < pMB->sad16) ) )          if ((iMinSAD < 256) ||
1930                  {                  ((MVequal(*currMV, prevMB->mvs[0])) &&
1931                     ((uint32_t) iMinSAD < prevMB->sad16))) {
1932                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
1933                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
1934                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1592  Line 1938 
1938  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
1939    
1940  // previous frame MV  // previous frame MV
1941          CHECK_MV16_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);          CHECK_MV16_CANDIDATE(prevMB->mvs[0].x, prevMB->mvs[0].y);
1942    
1943  // set threshhold based on Min of Prediction and SAD of collocated block  // set threshhold based on Min of Prediction and SAD of collocated block
1944  // CHECK_MV16 always uses iSAD for the SAD of last vector to check, so now iSAD is what we want  // CHECK_MV16 always uses iSAD for the SAD of last vector to check, so now iSAD is what we want
1945    
1946          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
1947                  thresh2 =  512;                  thresh2 =  512;
1948          }          } else {
         else  
         {  
1949  /* T_k = 1.2 * MIN(SAD_top,SAD_left,SAD_topleft,SAD_coll) +128;   [Tourapis, 2002] */  /* T_k = 1.2 * MIN(SAD_top,SAD_left,SAD_topleft,SAD_coll) +128;   [Tourapis, 2002] */
1950    
1951                  thresh2 = MIN(psad[0],iSAD)*6/5 + 128;                  thresh2 = MIN(psad[0],iSAD)*6/5 + 128;
# Line 1614  Line 1957 
1957    
1958    
1959  // left neighbour, if allowed  // left neighbour, if allowed
1960          if (x != 0)          if (x != 0) {
1961          {                  if (!(MotionFlags & PMV_HALFPEL16)) {
1962                  if (!(MotionFlags & PMV_HALFPEL16 ))                          pmv[1].x = EVEN(pmv[1].x);
                 {       pmv[1].x = EVEN(pmv[1].x);  
1963                          pmv[1].y = EVEN(pmv[1].y);                          pmv[1].y = EVEN(pmv[1].y);
1964                  }                  }
1965                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1966          }          }
   
1967  // top neighbour, if allowed  // top neighbour, if allowed
1968          if (y != 0)          if (y != 0) {
1969          {                  if (!(MotionFlags & PMV_HALFPEL16)) {
1970                  if (!(MotionFlags & PMV_HALFPEL16 ))                          pmv[2].x = EVEN(pmv[2].x);
                 {       pmv[2].x = EVEN(pmv[2].x);  
1971                          pmv[2].y = EVEN(pmv[2].y);                          pmv[2].y = EVEN(pmv[2].y);
1972                  }                  }
1973                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1974    
1975  // top right neighbour, if allowed  // top right neighbour, if allowed
1976                  if (x != (iWcount-1))                  if ((uint32_t) x != (iWcount - 1)) {
1977                  {                          if (!(MotionFlags & PMV_HALFPEL16)) {
1978                          if (!(MotionFlags & PMV_HALFPEL16 ))                                  pmv[3].x = EVEN(pmv[3].x);
                         {       pmv[3].x = EVEN(pmv[3].x);  
1979                                  pmv[3].y = EVEN(pmv[3].y);                                  pmv[3].y = EVEN(pmv[3].y);
1980                          }                          }
1981                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);
# Line 1648  Line 1987 
1987  */  */
1988    
1989          if ( (iMinSAD <= thresh2)          if ( (iMinSAD <= thresh2)
1990                  || ( MVequal(*currMV,pMB->mvs[0]) && (iMinSAD <= pMB->sad16) ) )                  || (MVequal(*currMV, prevMB->mvs[0]) &&
1991                  {                          ((uint32_t) iMinSAD <= prevMB->sad16))) {
1992                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
1993                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
1994                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1658  Line 1997 
1997    
1998  /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/  /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/
1999    
2000          backupMV = pMB->mvs[0];                 // last MV          backupMV = prevMB->mvs[0];      // collocated MV
2001          backupMV.x += (pMB->mvs[0].x - oldMB->mvs[0].x );       // acceleration X          backupMV.x += (prevMB->mvs[0].x - oldMB->mvs[0].x);     // acceleration X
2002          backupMV.y += (pMB->mvs[0].y - oldMB->mvs[0].y );       // acceleration Y          backupMV.y += (prevMB->mvs[0].y - oldMB->mvs[0].y);     // acceleration Y
2003    
2004          CHECK_MV16_CANDIDATE(backupMV.x,backupMV.y);          CHECK_MV16_CANDIDATE(backupMV.x,backupMV.y);
2005    
2006  // left neighbour  // left neighbour
2007          if (x != 0)          if (x != 0)
2008                  CHECK_MV16_CANDIDATE((oldMB-1)->mvs[0].x,oldMB->mvs[0].y);                  CHECK_MV16_CANDIDATE((prevMB - 1)->mvs[0].x, (prevMB - 1)->mvs[0].y);
2009    
2010  // top neighbour  // top neighbour
2011          if (y != 0)          if (y != 0)
2012                  CHECK_MV16_CANDIDATE((oldMB-iWcount)->mvs[0].x,oldMB->mvs[0].y);                  CHECK_MV16_CANDIDATE((prevMB - iWcount)->mvs[0].x,
2013                                                             (prevMB - iWcount)->mvs[0].y);
2014    
2015  // right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs  // right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs
2016    
2017          if (x != iWcount-1)          if ((uint32_t) x != iWcount - 1)
2018                  CHECK_MV16_CANDIDATE((pMB+1)->mvs[0].x,oldMB->mvs[0].y);                  CHECK_MV16_CANDIDATE((prevMB + 1)->mvs[0].x, (prevMB + 1)->mvs[0].y);
2019    
2020  // bottom neighbour, dito  // bottom neighbour, dito
2021          if (y != iHcount-1)          if ((uint32_t) y != iHcount - 1)
2022                  CHECK_MV16_CANDIDATE((pMB+iWcount)->mvs[0].x,oldMB->mvs[0].y);                  CHECK_MV16_CANDIDATE((prevMB + iWcount)->mvs[0].x,
2023                                                             (prevMB + iWcount)->mvs[0].y);
2024    
2025  /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */  /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */
2026          if (iMinSAD <= thresh2)          if (iMinSAD <= thresh2) {
                 {  
2027                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2028                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2029                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1694  Line 2034 
2034    
2035          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
2036    
2037  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */          if (MotionFlags & PMV_USESQUARES8)
2038                    MainSearchPtr = Square16_MainSearch;
2039          if (MotionFlags & PMV_USESQUARES16)          else
2040                  EPZSMainSearchPtr = Square16_MainSearch;           if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2041                    MainSearchPtr = AdvDiamond16_MainSearch;
2042          else          else
2043                  EPZSMainSearchPtr = Diamond16_MainSearch;                  MainSearchPtr = Diamond16_MainSearch;
2044    
2045          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
                         x, y,  
                         currMV->x, currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,  
                         2, iFcode, iQuant, 0);  
2046    
2047          if (iSAD < iMinSAD)          iSAD =
2048          {                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2049                                                      currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx,
2050                                                      min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2051    
2052            if (iSAD < iMinSAD) {
2053                  *currMV = newMV;                  *currMV = newMV;
2054                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2055          }          }
2056    
2057    
2058          if (MotionFlags & PMV_EXTSEARCH16)          if (MotionFlags & PMV_EXTSEARCH16) {
         {  
2059  /* extended mode: search (up to) two more times: orignal prediction and (0,0) */  /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
2060    
2061                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2062                  {                          iSAD =
2063                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2064                                  x, y,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, pmv,
2065                                  pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2066                                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);                                                                    2, iFcode, iQuant, 0);
2067                  }                  }
2068    
2069                  if (iSAD < iMinSAD)                  if (iSAD < iMinSAD) {
                 {  
2070                          *currMV = newMV;                          *currMV = newMV;
2071                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2072                  }                  }
2073    
2074                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2075                  {                          iSAD =
2076                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2077                                  x, y,                                                                    iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy,
2078                          0, 0, iMinSAD, &newMV,                                                                    max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
                         pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, /*iDiamondSize*/ 2, iFcode, iQuant, 0);  
2079    
2080                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2081                                  *currMV = newMV;                                  *currMV = newMV;
2082                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2083                          }                          }
# Line 1750  Line 2088 
2088    
2089  EPZS16_Terminate_with_Refine:  EPZS16_Terminate_with_Refine:
2090          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
2091                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2092                                  x, y,                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2093                                  currMV, iMinSAD,                                                           iMinSAD, pmv, min_dx, max_dx, min_dy, max_dy,
2094                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                           iFcode, iQuant, iEdgedWidth);
2095    
2096  EPZS16_Terminate_without_Refine:  EPZS16_Terminate_without_Refine:
2097    
2098          *oldMB = *pMB;          *oldMB = *prevMB;
2099    
2100          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - pmv[0].x;
2101          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - pmv[0].y;
# Line 1765  Line 2103 
2103  }  }
2104    
2105    
2106  int32_t EPZSSearch8(  int32_t
2107                                          const uint8_t * const pRef,  EPZSSearch8(const uint8_t * const pRef,
2108                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
2109                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
2110                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
2111                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
2112                                          const int x, const int y,                          const int x,
2113                                          const int start_x, const int start_y,                          const int y,
2114                            const int start_x,
2115                            const int start_y,
2116                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
2117                            const uint32_t iQuant,
2118                            const uint32_t iFcode,
2119                                          const MBParam * const pParam,                                          const MBParam * const pParam,
2120                                          MACROBLOCK * const pMBs,                          const MACROBLOCK * const pMBs,
2121                            const MACROBLOCK * const prevMBs,
2122                                          VECTOR * const currMV,                                          VECTOR * const currMV,
2123                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
2124  {  {
2125          const uint32_t iWcount = pParam->mb_width;  /* Please not that EPZS might not be a good choice for 8x8-block motion search ! */
         const int32_t iFcode = pParam->fixed_code;  
         const int32_t iQuant = pParam->quant;  
2126    
2127            const uint32_t iWcount = pParam->mb_width;
2128          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
2129          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
2130          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
# Line 1804  Line 2146 
2146    
2147          const   int32_t iSubBlock = ((y&1)<<1) + (x&1);          const   int32_t iSubBlock = ((y&1)<<1) + (x&1);
2148    
2149          MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;  //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
2150            const MACROBLOCK *const prevMB = prevMBs + (x >> 1) + (y >> 1) * iWcount;
2151    
2152          int32_t bPredEq;          int32_t bPredEq;
2153          int32_t iMinSAD,iSAD=9999;          int32_t iMinSAD,iSAD=9999;
2154    
2155          MainSearch8FuncPtr EPZSMainSearchPtr;          MainSearch8FuncPtr MainSearchPtr;
2156    
2157  /* Get maximum range */  /* Get maximum range */
2158          get_range(&min_dx, &max_dx, &min_dy, &max_dy,          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 8, iWidth, iHeight,
2159                          x, y, 8, iWidth, iHeight, iFcode);                            iFcode);
2160    
2161  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
2162    
2163          if (!(MotionFlags & PMV_HALFPEL8 ))          if (!(MotionFlags & PMV_HALFPEL8)) {
2164          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
2165            max_dx = EVEN(max_dx);            max_dx = EVEN(max_dx);
2166            min_dy = EVEN(min_dy);            min_dy = EVEN(min_dy);
2167            max_dy = EVEN(max_dy);            max_dy = EVEN(max_dy);
2168          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
2169            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2170          bPredEq  = get_pmvdata(pMBs, x>>1, y>>1, iWcount, iSubBlock, pmv, psad);          bPredEq  = get_pmvdata(pMBs, x>>1, y>>1, iWcount, iSubBlock, pmv, psad);
2171            // bPredEq = get_pmvdata2(pMBs, iWcount, 0, x >> 1, y >> 1, iSubBlock, pmv, psad);
2172    
2173    
2174  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
# Line 1837  Line 2181 
2181  // Prepare for main loop  // Prepare for main loop
2182    
2183    
2184          if (!(MotionFlags & PMV_HALFPEL8))          if (!(MotionFlags & PMV_HALFPEL8)) {
         {  
2185                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
2186                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
2187          }          }
# Line 1855  Line 2198 
2198  /***************** This is predictor SET A: only median prediction ******************/  /***************** This is predictor SET A: only median prediction ******************/
2199    
2200    
2201          iMinSAD = sad8( cur,          iMinSAD =
2202                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),                  sad8(cur,
2203                  iEdgedWidth);                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
2204          iMinSAD += calc_delta_8(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;                                                  iEdgedWidth), iEdgedWidth);
2205            iMinSAD +=
2206                    calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y,
2207                                             (uint8_t) iFcode, iQuant);
2208    
2209    
2210  // thresh1 is fixed to 256  // thresh1 is fixed to 256
2211          if (iMinSAD < 256/4 )          if (iMinSAD < 256 / 4) {
                 {  
2212                          if (MotionFlags & PMV_QUICKSTOP8)                          if (MotionFlags & PMV_QUICKSTOP8)
2213                                  goto EPZS8_Terminate_without_Refine;                                  goto EPZS8_Terminate_without_Refine;
2214                          if (MotionFlags & PMV_EARLYSTOP8)                          if (MotionFlags & PMV_EARLYSTOP8)
# Line 1872  Line 2217 
2217    
2218  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
2219    
 // previous frame MV  
         CHECK_MV8_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);  
2220    
2221  // MV=(0,0) is often a good choice  // MV=(0,0) is often a good choice
   
2222          CHECK_MV8_ZERO;          CHECK_MV8_ZERO;
2223    
2224    // previous frame MV
2225            CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x, prevMB->mvs[iSubBlock].y);
2226    
2227    // left neighbour, if allowed
2228            if (psad[1] != MV_MAX_ERROR) {
2229                    if (!(MotionFlags & PMV_HALFPEL8)) {
2230                            pmv[1].x = EVEN(pmv[1].x);
2231                            pmv[1].y = EVEN(pmv[1].y);
2232                    }
2233                    CHECK_MV8_CANDIDATE(pmv[1].x, pmv[1].y);
2234            }
2235    // top neighbour, if allowed
2236            if (psad[2] != MV_MAX_ERROR) {
2237                    if (!(MotionFlags & PMV_HALFPEL8)) {
2238                            pmv[2].x = EVEN(pmv[2].x);
2239                            pmv[2].y = EVEN(pmv[2].y);
2240                    }
2241                    CHECK_MV8_CANDIDATE(pmv[2].x, pmv[2].y);
2242    
2243    // top right neighbour, if allowed
2244                    if (psad[3] != MV_MAX_ERROR) {
2245                            if (!(MotionFlags & PMV_HALFPEL8)) {
2246                                    pmv[3].x = EVEN(pmv[3].x);
2247                                    pmv[3].y = EVEN(pmv[3].y);
2248                            }
2249                            CHECK_MV8_CANDIDATE(pmv[3].x, pmv[3].y);
2250                    }
2251            }
2252    
2253    /*  // this bias is zero anyway, at the moment!
2254    
2255            if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) ) // && (iMinSAD <= iQuant * 96)
2256                    iMinSAD -= MV8_00_BIAS;
2257    
2258    */
2259    
2260  /* Terminate if MinSAD <= T_2  /* Terminate if MinSAD <= T_2
2261     Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]     Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
2262  */  */
2263    
2264          if (iMinSAD < 512/4)    /* T_2 == 512/4 hardcoded */          if (iMinSAD < 512 / 4) {        /* T_2 == 512/4 hardcoded */
                 {  
2265                          if (MotionFlags & PMV_QUICKSTOP8)                          if (MotionFlags & PMV_QUICKSTOP8)
2266                                  goto EPZS8_Terminate_without_Refine;                                  goto EPZS8_Terminate_without_Refine;
2267                          if (MotionFlags & PMV_EARLYSTOP8)                          if (MotionFlags & PMV_EARLYSTOP8)
2268                                  goto EPZS8_Terminate_with_Refine;                                  goto EPZS8_Terminate_with_Refine;
2269                  }                  }
2270    
2271  /************ (if Diamond Search)  **************/  /************ (Diamond Search)  **************/
2272    
2273          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
2274    
2275          if (!(MotionFlags & PMV_HALFPELDIAMOND8))          if (!(MotionFlags & PMV_HALFPELDIAMOND8))
2276                  iDiamondSize *= 2;                  iDiamondSize *= 2;
2277    
2278  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */  /* default: use best prediction as starting point for one call of EPZS_MainSearch */
2279    
2280    // there is no EPZS^2 for inter4v at the moment
2281    
2282  //      if (MotionFlags & PMV_USESQUARES8)  //      if (MotionFlags & PMV_USESQUARES8)
2283  //              EPZSMainSearchPtr = Square8_MainSearch;  //      MainSearchPtr = Square8_MainSearch;
2284  //      else  //      else
                 EPZSMainSearchPtr = Diamond8_MainSearch;  
2285    
2286          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,          if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2287                  x, y,                  MainSearchPtr = AdvDiamond8_MainSearch;
2288                  currMV->x, currMV->y, iMinSAD, &newMV,          else
2289                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,                  MainSearchPtr = Diamond8_MainSearch;
                 iDiamondSize, iFcode, iQuant, 00);  
2290    
2291            iSAD =
2292                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2293                                                      currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx,
2294                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2295                                                      iQuant, 0);
2296    
2297          if (iSAD < iMinSAD)  
2298          {          if (iSAD < iMinSAD) {
2299                  *currMV = newMV;                  *currMV = newMV;
2300                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2301          }          }
2302    
2303          if (MotionFlags & PMV_EXTSEARCH8)          if (MotionFlags & PMV_EXTSEARCH8) {
         {  
2304  /* extended mode: search (up to) two more times: orignal prediction and (0,0) */  /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
2305    
2306                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2307                  {                          iSAD =
2308                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2309                                  x, y,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, pmv,
2310                          pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2311                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);                                                                    iDiamondSize, iFcode, iQuant, 0);
2312    
2313                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2314                                  *currMV = newMV;                                  *currMV = newMV;
2315                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2316                          }                          }
2317                  }                  }
2318    
2319                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2320                  {                          iSAD =
2321                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2322                                  x, y,                                                                    iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy,
2323                          0, 0, iMinSAD, &newMV,                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
2324                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);                                                                    iQuant, 0);
2325    
2326                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2327                                  *currMV = newMV;                                  *currMV = newMV;
2328                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2329                          }                          }
# Line 1955  Line 2334 
2334    
2335  EPZS8_Terminate_with_Refine:  EPZS8_Terminate_with_Refine:
2336          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
2337                  iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2338                                  x, y,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2339                                  currMV, iMinSAD,                                                          iMinSAD, pmv, min_dx, max_dx, min_dy, max_dy,
2340                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
2341    
2342  EPZS8_Terminate_without_Refine:  EPZS8_Terminate_without_Refine:
2343    
# Line 1967  Line 2346 
2346          return iMinSAD;          return iMinSAD;
2347  }  }
2348    
2349    
2350    
2351    
2352    
2353    /* ***********************************************************
2354            bvop motion estimation
2355    // TODO: need to incorporate prediction here (eg. sad += calc_delta_16)
2356    ***************************************************************/
2357    
2358    
2359    void
2360    MotionEstimationBVOP(MBParam * const pParam,
2361                                             FRAMEINFO * const frame,
2362                                             // forward (past) reference
2363                                             const MACROBLOCK * const f_mbs,
2364                                             const IMAGE * const f_ref,
2365                                             const IMAGE * const f_refH,
2366                                             const IMAGE * const f_refV,
2367                                             const IMAGE * const f_refHV,
2368                                             // backward (future) reference
2369                                             const MACROBLOCK * const b_mbs,
2370                                             const IMAGE * const b_ref,
2371                                             const IMAGE * const b_refH,
2372                                             const IMAGE * const b_refV,
2373                                             const IMAGE * const b_refHV)
2374    {
2375            const uint32_t mb_width = pParam->mb_width;
2376            const uint32_t mb_height = pParam->mb_height;
2377            const int32_t edged_width = pParam->edged_width;
2378    
2379            uint32_t i, j;
2380    
2381            int32_t f_sad16;
2382            int32_t b_sad16;
2383            int32_t i_sad16;
2384            int32_t d_sad16;
2385            int32_t best_sad;
2386    
2387            VECTOR pmv_dontcare;
2388    
2389            // note: i==horizontal, j==vertical
2390            for (j = 0; j < mb_height; j++) {
2391                    for (i = 0; i < mb_width; i++) {
2392                            MACROBLOCK *mb = &frame->mbs[i + j * mb_width];
2393                            const MACROBLOCK *f_mb = &f_mbs[i + j * mb_width];
2394                            const MACROBLOCK *b_mb = &b_mbs[i + j * mb_width];
2395    
2396                            if (b_mb->mode == MODE_INTER && b_mb->cbp == 0 &&
2397                                    b_mb->mvs[0].x == 0 && b_mb->mvs[0].y == 0) {
2398                                    mb->mode = MODE_NOT_CODED;
2399                                    mb->mvs[0].x = 0;
2400                                    mb->mvs[0].y = 0;
2401                                    mb->b_mvs[0].x = 0;
2402                                    mb->b_mvs[0].y = 0;
2403                                    continue;
2404                            }
2405                    /* force F_SAD16
2406                            f_sad16 = 100;
2407                            b_sad16 = 65535;
2408    
2409                            mb->mode = MODE_FORWARD;
2410                            mb->mvs[0].x = 1;
2411                            mb->mvs[0].y = 1;
2412                            mb->b_mvs[0].x = 1;
2413                            mb->b_mvs[0].y = 1;
2414                            continue;
2415                     ^^ force F_SAD16 */
2416    
2417    
2418                            // forward search
2419                            f_sad16 =
2420                                    SEARCH16(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
2421                                                     &frame->image, i, j, frame->motion_flags,
2422                                                     frame->quant, frame->fcode, pParam,
2423                                                     f_mbs,  f_mbs, /* todo */
2424                                                     &mb->mvs[0], &pmv_dontcare);   // ignore pmv
2425    
2426                            // backward search
2427                            b_sad16 = SEARCH16(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
2428                                                    &frame->image, i, j, frame->motion_flags,
2429                                                    frame->quant, frame->bcode, pParam,
2430                                                    b_mbs, b_mbs,   /* todo */
2431                                                    &mb->b_mvs[0], &pmv_dontcare);  // ignore pmv
2432    
2433                            // interpolate search (simple, but effective)
2434                            i_sad16 = 65535;
2435    
2436                            /*
2437                            x/y range somewhat buggy
2438                            i_sad16 =
2439                                    sad16bi_c(frame->image.y + i * 16 + j * 16 * edged_width,
2440                                                      get_ref(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
2441                                                                      i, j, 16, mb->mvs[0].x, mb->mvs[0].y,
2442                                                                      edged_width), get_ref(b_ref->y, b_refH->y,
2443                                                                                                                    b_refV->y, b_refHV->y,
2444                                                                                                                    i, j, 16,
2445                                                                                                                    mb->b_mvs[0].x,
2446                                                                                                                    mb->b_mvs[0].x,
2447                                                                                                                    edged_width),
2448                                                      edged_width);
2449                            */
2450    
2451                            // TODO: direct search
2452                            // predictor + range of [-32,32]
2453                            d_sad16 = 65535;
2454    
2455    
2456                            if (f_sad16 < b_sad16) {
2457                                    best_sad = f_sad16;
2458                                    mb->mode = MODE_FORWARD;
2459                            } else {
2460                                    best_sad = b_sad16;
2461                                    mb->mode = MODE_BACKWARD;
2462                            }
2463    
2464                            if (i_sad16 < best_sad) {
2465                                    best_sad = i_sad16;
2466                                    mb->mode = MODE_INTERPOLATE;
2467                            }
2468    
2469                            if (d_sad16 < best_sad) {
2470                                    best_sad = d_sad16;
2471                                    mb->mode = MODE_DIRECT;
2472                            }
2473    
2474                    }
2475            }
2476    }

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

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