[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 195, Wed Jun 12 20:38:41 2002 UTC
# Line 2  Line 2 
2   *   *
3   *  Modifications:   *  Modifications:
4   *   *
5     *      01.05.2002      updated MotionEstimationBVOP
6     *      25.04.2002 partial prevMB conversion
7     *  22.04.2002 remove some compile warning by chenm001 <chenm001@163.com>
8     *  14.04.2002 added MotionEstimationBVOP()
9   *  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
10   *             EPZS and EPZS^2   *             EPZS and EPZS^2
11   *  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 44 
44  #include "../prediction/mbprediction.h"  #include "../prediction/mbprediction.h"
45  #include "../global.h"  #include "../global.h"
46  #include "../utils/timer.h"  #include "../utils/timer.h"
47    #include "motion.h"
48  #include "sad.h"  #include "sad.h"
49    
50  // very large value  // very large value
# Line 49  Line 54 
54  #define MV16_THRESHOLD  192  #define MV16_THRESHOLD  192
55  #define MV8_THRESHOLD   56  #define MV8_THRESHOLD   56
56    
57    #define NEIGH_MOVE_THRESH 0
58    // how much a block's MV must differ from his neighbour
59    // to be search for INTER4V. The more, the faster...
60    
61  /* sad16(0,0) bias; mpeg4 spec suggests nb/2+1 */  /* sad16(0,0) bias; mpeg4 spec suggests nb/2+1 */
62  /* nb  = vop pixels * 2^(bpp-8) */  /* nb  = vop pixels * 2^(bpp-8) */
63  #define MV16_00_BIAS    (128+1)  #define MV16_00_BIAS    (128+1)
64    #define MV8_00_BIAS     (0)
65    
66  /* INTER bias for INTER/INTRA decision; mpeg4 spec suggests 2*nb */  /* INTER bias for INTER/INTRA decision; mpeg4 spec suggests 2*nb */
67  #define INTER_BIAS      512  #define MV16_INTER_BIAS 512
68    
69  /* Parameters which control inter/inter4v decision */  /* Parameters which control inter/inter4v decision */
70  #define IMV16X16                        5  #define IMV16X16                        5
# Line 63  Line 73 
73  #define NEIGH_TEND_16X16        2  #define NEIGH_TEND_16X16        2
74  #define NEIGH_TEND_8X8          2  #define NEIGH_TEND_8X8          2
75    
   
76  // fast ((A)/2)*2  // fast ((A)/2)*2
77  #define EVEN(A)         (((A)<0?(A)+1:(A)) & ~1)  #define EVEN(A)         (((A)<0?(A)+1:(A)) & ~1)
78    
79    #define MVzero(A) ( ((A).x)==(0) && ((A).y)==(0) )
80    #define MVequal(A,B) ( ((A).x)==((B).x) && ((A).y)==((B).y) )
81    
82  #define MIN(X, Y) ((X)<(Y)?(X):(Y))  int32_t PMVfastSearch16(const uint8_t * const pRef,
 #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,  
83                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
84                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
85                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
86                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
87                                          const int x, const int y,                                                  const int x,
88                                                    const int y,
89                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
90                                                    const uint32_t iQuant,
91                                                    const uint32_t iFcode,
92                                          const MBParam * const pParam,                                          const MBParam * const pParam,
93                                          MACROBLOCK * const pMBs,                                                  const MACROBLOCK * const pMBs,
94                                                    const MACROBLOCK * const prevMBs,
95                                          VECTOR * const currMV,                                          VECTOR * const currMV,
96                                          VECTOR * const currPMV);                                          VECTOR * const currPMV);
97    
98  int32_t EPZSSearch16(  int32_t EPZSSearch16(const uint8_t * const pRef,
                                         const uint8_t * const pRef,  
99                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
100                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
101                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
102                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
103                                          const int x, const int y,                                           const int x,
104                                             const int y,
105                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
106                                             const uint32_t iQuant,
107                                             const uint32_t iFcode,
108                                          const MBParam * const pParam,                                          const MBParam * const pParam,
109                                          MACROBLOCK * const pMBs,                                           const MACROBLOCK * const pMBs,
110                                             const MACROBLOCK * const prevMBs,
111                                          VECTOR * const currMV,                                          VECTOR * const currMV,
112                                          VECTOR * const currPMV);                                          VECTOR * const currPMV);
113    
114    
115  int32_t PMVfastSearch8(  int32_t PMVfastSearch8(const uint8_t * const pRef,
                                         const uint8_t * const pRef,  
116                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
117                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
118                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
119                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
120                                          const int x, const int y,                                             const int x,
121                                          const int start_x, int start_y,                                             const int y,
122                                               const int start_x,
123                                               const int start_y,
124                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
125                                               const uint32_t iQuant,
126                                               const uint32_t iFcode,
127                                          const MBParam * const pParam,                                          const MBParam * const pParam,
128                                          MACROBLOCK * const pMBs,                                             const MACROBLOCK * const pMBs,
129                                               const MACROBLOCK * const prevMBs,
130                                          VECTOR * const currMV,                                          VECTOR * const currMV,
131                                          VECTOR * const currPMV);                                          VECTOR * const currPMV);
132    
133  int32_t EPZSSearch8(  int32_t EPZSSearch8(const uint8_t * const pRef,
                                         const uint8_t * const pRef,  
134                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
135                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
136                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
137                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
138                                          const int x, const int y,                                          const int x,
139                                          const int start_x, int start_y,                                          const int y,
140                                            const int start_x,
141                                            const int start_y,
142                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
143                                            const uint32_t iQuant,
144                                            const uint32_t iFcode,
145                                          const MBParam * const pParam,                                          const MBParam * const pParam,
146                                          MACROBLOCK * const pMBs,                                          const MACROBLOCK * const pMBs,
147                                            const MACROBLOCK * const prevMBs,
148                                          VECTOR * const currMV,                                          VECTOR * const currMV,
149                                          VECTOR * const currPMV);                                          VECTOR * const currPMV);
150    
151    
152  typedef int32_t (MainSearch16Func)(  typedef int32_t(MainSearch16Func) (const uint8_t * const pRef,
         const uint8_t * const pRef,  
153          const uint8_t * const pRefH,          const uint8_t * const pRefH,
154          const uint8_t * const pRefV,          const uint8_t * const pRefV,
155          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
156          const uint8_t * const cur,          const uint8_t * const cur,
157          const int x, const int y,                                                                     const int x,
158          int32_t startx, int32_t starty,                                                                     const int y,
159                                                                       int32_t startx,
160                                                                       int32_t starty,
161          int32_t iMinSAD,          int32_t iMinSAD,
162          VECTOR * const currMV,          VECTOR * const currMV,
163          const VECTOR * const pmv,          const VECTOR * const pmv,
164          const int32_t min_dx, const int32_t max_dx,                                                                     const int32_t min_dx,
165          const int32_t min_dy, const int32_t max_dy,                                                                     const int32_t max_dx,
166                                                                       const int32_t min_dy,
167                                                                       const int32_t max_dy,
168          const int32_t iEdgedWidth,          const int32_t iEdgedWidth,
169          const int32_t iDiamondSize,          const int32_t iDiamondSize,
170          const int32_t iFcode,          const int32_t iFcode,
# Line 151  Line 174 
174  typedef MainSearch16Func* MainSearch16FuncPtr;  typedef MainSearch16Func* MainSearch16FuncPtr;
175    
176    
177  typedef int32_t (MainSearch8Func)(  typedef int32_t(MainSearch8Func) (const uint8_t * const pRef,
         const uint8_t * const pRef,  
178          const uint8_t * const pRefH,          const uint8_t * const pRefH,
179          const uint8_t * const pRefV,          const uint8_t * const pRefV,
180          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
181          const uint8_t * const cur,          const uint8_t * const cur,
182          const int x, const int y,                                                                    const int x,
183          int32_t startx, int32_t starty,                                                                    const int y,
184                                                                      int32_t startx,
185                                                                      int32_t starty,
186          int32_t iMinSAD,          int32_t iMinSAD,
187          VECTOR * const currMV,          VECTOR * const currMV,
188          const VECTOR * const pmv,          const VECTOR * const pmv,
189          const int32_t min_dx, const int32_t max_dx,                                                                    const int32_t min_dx,
190          const int32_t min_dy, const int32_t max_dy,                                                                    const int32_t max_dx,
191                                                                      const int32_t min_dy,
192                                                                      const int32_t max_dy,
193          const int32_t iEdgedWidth,          const int32_t iEdgedWidth,
194          const int32_t iDiamondSize,          const int32_t iDiamondSize,
195          const int32_t iFcode,          const int32_t iFcode,
# Line 172  Line 198 
198    
199  typedef MainSearch8Func* MainSearch8FuncPtr;  typedef MainSearch8Func* MainSearch8FuncPtr;
200    
201    static int32_t lambda_vec16[32] =       /* rounded values for lambda param for weight of motion bits as in modified H.26L */
202    { 0, (int) (1.00235 + 0.5), (int) (1.15582 + 0.5), (int) (1.31976 + 0.5),
203                    (int) (1.49591 + 0.5), (int) (1.68601 + 0.5),
204            (int) (1.89187 + 0.5), (int) (2.11542 + 0.5), (int) (2.35878 + 0.5),
205                    (int) (2.62429 + 0.5), (int) (2.91455 + 0.5),
206            (int) (3.23253 + 0.5), (int) (3.58158 + 0.5), (int) (3.96555 + 0.5),
207                    (int) (4.38887 + 0.5), (int) (4.85673 + 0.5),
208            (int) (5.37519 + 0.5), (int) (5.95144 + 0.5), (int) (6.59408 + 0.5),
209                    (int) (7.31349 + 0.5), (int) (8.12242 + 0.5),
210            (int) (9.03669 + 0.5), (int) (10.0763 + 0.5), (int) (11.2669 + 0.5),
211                    (int) (12.6426 + 0.5), (int) (14.2493 + 0.5),
212            (int) (16.1512 + 0.5), (int) (18.442 + 0.5), (int) (21.2656 + 0.5),
213                    (int) (24.8580 + 0.5), (int) (29.6436 + 0.5),
214            (int) (36.4949 + 0.5)
215    };
216    
217    static int32_t *lambda_vec8 = lambda_vec16;     /* same table for INTER and INTER4V for now */
218    
219    
220    
221  // mv.length table  // mv.length table
222  static const uint32_t mvtab[33] = {  static const uint32_t mvtab[33] = {
223      1,  2,  3,  4,  6,  7,  7,  7,      1,  2,  3,  4,  6,  7,  7,  7,
# Line 181  Line 227 
227  };  };
228    
229    
230  static __inline uint32_t mv_bits(int32_t component, const uint32_t iFcode)  static __inline uint32_t
231    mv_bits(int32_t component,
232                    const uint32_t iFcode)
233  {  {
234      if (component == 0)      if (component == 0)
235                  return 1;                  return 1;
# Line 189  Line 237 
237      if (component < 0)      if (component < 0)
238                  component = -component;                  component = -component;
239    
240      if (iFcode == 1)          if (iFcode == 1) {
     {  
241                  if (component > 32)                  if (component > 32)
242                      component = 32;                      component = 32;
243    
# Line 207  Line 254 
254  }  }
255    
256    
257  static __inline uint32_t calc_delta_16(const int32_t dx, const int32_t dy, const uint32_t iFcode)  static __inline uint32_t
258    calc_delta_16(const int32_t dx,
259                              const int32_t dy,
260                              const uint32_t iFcode,
261                              const uint32_t iQuant)
262    {
263            return NEIGH_TEND_16X16 * lambda_vec16[iQuant] * (mv_bits(dx, iFcode) +
264                                                                                                              mv_bits(dy, iFcode));
265    }
266    
267    static __inline uint32_t
268    calc_delta_8(const int32_t dx,
269                             const int32_t dy,
270                             const uint32_t iFcode,
271                             const uint32_t iQuant)
272  {  {
273          return NEIGH_TEND_16X16 * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));          return NEIGH_TEND_8X8 * lambda_vec8[iQuant] * (mv_bits(dx, iFcode) +
274                                                                                                       mv_bits(dy, iFcode));
275  }  }
276    
 static __inline uint32_t calc_delta_8(const int32_t dx, const int32_t dy, const uint32_t iFcode)  
   
 {  
     return NEIGH_TEND_8X8 * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));  
 }  
   
   
277    
278    
 /* calculate the min/max range (in halfpixels)  
         relative to the _MACROBLOCK_ position  
 */  
   
 static void __inline get_range(  
         int32_t * const min_dx, int32_t * const max_dx,  
         int32_t * const min_dy, int32_t * const max_dy,  
         const uint32_t x, const uint32_t y,  
         const uint32_t block_sz,                                        // block dimension, 8 or 16  
         const uint32_t width, const uint32_t height,  
         const uint32_t fcode)  
 {  
279    
         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;  
         }  
   
 }  
280    
281  #ifndef SEARCH16  #ifndef SEARCH16
282  #define SEARCH16        PMVfastSearch16  #define SEARCH16        PMVfastSearch16
# Line 317  Line 289 
289  //#define SEARCH8       EPZSSearch8  //#define SEARCH8       EPZSSearch8
290  #endif  #endif
291    
292  bool MotionEstimation(  bool
293          MACROBLOCK * const pMBs,  MotionEstimation(MBParam * const pParam,
294          MBParam * const pParam,                                   FRAMEINFO * const current,
295          const IMAGE * const pRef,                                   FRAMEINFO * const reference,
296          const IMAGE * const pRefH,          const IMAGE * const pRefH,
297          const IMAGE * const pRefV,          const IMAGE * const pRefV,
298          const IMAGE * const pRefHV,          const IMAGE * const pRefHV,
         IMAGE * const pCurrent,  
299          const uint32_t iLimit)          const uint32_t iLimit)
   
300  {  {
301          const uint32_t iWcount = pParam->mb_width;          const uint32_t iWcount = pParam->mb_width;
302          const uint32_t iHcount = pParam->mb_height;          const uint32_t iHcount = pParam->mb_height;
303            MACROBLOCK *const pMBs = current->mbs;
304            MACROBLOCK *const prevMBs = reference->mbs;
305            const IMAGE *const pCurrent = &current->image;
306            const IMAGE *const pRef = &reference->image;
307    
308            const VECTOR zeroMV = { 0, 0 };
309    
310            int32_t x, y;
311            int32_t iIntra = 0;
312            VECTOR pmv;
313    
314            if (sadInit)
315                    (*sadInit) ();
316    
317            for (y = 0; y < iHcount; y++)
318                    for (x = 0; x < iWcount; x++) {
319                            MACROBLOCK *const pMB = &pMBs[x + y * iWcount];
320    
321                            pMB->sad16 =
322                                    SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,
323                                                     y, current->motion_flags, current->quant,
324                                                     current->fcode, pParam, pMBs, prevMBs, &pMB->mv16,
325                                                     &pMB->pmvs[0]);
326    
327          uint32_t i, j, iIntra = 0;                          if (0 < (pMB->sad16 - MV16_INTER_BIAS)) {
   
         VECTOR mv16;  
         VECTOR pmv16;  
   
         int32_t sad8 = 0;  
         int32_t sad16;  
328          int32_t deviation;          int32_t deviation;
329    
330          // note: i==horizontal, j==vertical                                  deviation =
331          for (i = 0; i < iHcount; i++)                                          dev16(pCurrent->y + x * 16 + y * 16 * pParam->edged_width,
332                  for (j = 0; j < iWcount; j++)                                                    pParam->edged_width);
                 {  
                         MACROBLOCK *pMB = &pMBs[j + i * iWcount];  
   
                         sad16 = SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,  
                                          j, i, pParam->motion_flags,  
                                          pParam, pMBs, &mv16, &pmv16);  
                         pMB->sad16=sad16;  
   
   
                         /* decide: MODE_INTER or MODE_INTRA  
                            if (dev_intra < sad_inter - 2 * nb) use_intra  
                         */  
   
                         deviation = dev16(pCurrent->y + j*16 + i*16*pParam->edged_width, pParam->edged_width);  
333    
334                          if (deviation < (sad16 - INTER_BIAS))                                  if (deviation < (pMB->sad16 - MV16_INTER_BIAS)) {
                         {  
335                                  pMB->mode = MODE_INTRA;                                  pMB->mode = MODE_INTRA;
336                                  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] =
337                                  pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = 0;                                                  pMB->mvs[3] = zeroMV;
338                                            pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =
339                                                    pMB->sad8[3] = 0;
340    
341                                  iIntra++;                                  iIntra++;
342                                  if(iIntra >= iLimit)                                  if(iIntra >= iLimit)
# Line 370  Line 344 
344    
345                                  continue;                                  continue;
346                          }                          }
   
                         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];  
347                          }                          }
348    
349                            pmv = pMB->pmvs[0];
350                            if (current->global_flags & XVID_INTER4V)
351                                    if ((!(current->global_flags & XVID_LUMIMASKING) ||
352                                             pMB->dquant == NO_CHANGE)) {
353                                            int32_t sad8 = IMV16X16 * current->quant;
354    
355                                            if (sad8 < pMB->sad16)
356    
357                                                    sad8 += pMB->sad8[0] =
358                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
359                                                                            pCurrent, 2 * x, 2 * y, pMB->mv16.x,
360                                                                            pMB->mv16.y, current->motion_flags,
361                                                                            current->quant, current->fcode, pParam,
362                                                                            pMBs, prevMBs, &pMB->mvs[0],
363                                                                            &pMB->pmvs[0]);
364    
365                                            if (sad8 < pMB->sad16)
366                                                    sad8 += pMB->sad8[1] =
367                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
368                                                                            pCurrent, 2 * x + 1, 2 * y, pMB->mv16.x,
369                                                                            pMB->mv16.y, current->motion_flags,
370                                                                            current->quant, current->fcode, pParam,
371                                                                            pMBs, prevMBs, &pMB->mvs[1],
372                                                                            &pMB->pmvs[1]);
373    
374                                            if (sad8 < pMB->sad16)
375                                                    sad8 += pMB->sad8[2] =
376                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
377                                                                            pCurrent, 2 * x, 2 * y + 1, pMB->mv16.x,
378                                                                            pMB->mv16.y, current->motion_flags,
379                                                                            current->quant, current->fcode, pParam,
380                                                                            pMBs, prevMBs, &pMB->mvs[2],
381                                                                            &pMB->pmvs[2]);
382    
383                                            if (sad8 < pMB->sad16)
384                                                    sad8 += pMB->sad8[3] =
385                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
386                                                                            pCurrent, 2 * x + 1, 2 * y + 1,
387                                                                            pMB->mv16.x, pMB->mv16.y,
388                                                                            current->motion_flags, current->quant,
389                                                                            current->fcode, pParam, pMBs, prevMBs,
390                                                                            &pMB->mvs[3], &pMB->pmvs[3]);
391    
392                          /* decide: MODE_INTER or MODE_INTER4V                          /* decide: MODE_INTER or MODE_INTER4V
393                             mpeg4:   if (sad8 < sad16 - nb/2+1) use_inter4v                                             mpeg4:   if (sad8 < pMB->sad16 - nb/2+1) use_inter4v
394                          */                          */
395    
396                          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  
397                                          pMB->mode = MODE_INTER4V;                                          pMB->mode = MODE_INTER4V;
398                          }                                                  pMB->sad8[0] *= 4;
399                          else                                                  pMB->sad8[1] *= 4;
400                          {                                                  pMB->sad8[2] *= 4;
401                                  sad8 = sad16;                                                  pMB->sad8[3] *= 4;
402                                  pMB->mode = MODE_INTER;                                                  continue;
                                 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;  
                         }  
403                  }                  }
404    
         return 0;  
405  }  }
406    
407  #define MVzero(A) ( ((A).x)==(0) && ((A).y)==(0) )                          pMB->mode = MODE_INTER;
408                            pMB->pmvs[0] = pmv;     /* pMB->pmvs[1] = pMB->pmvs[2] = pMB->pmvs[3]  are not needed for INTER */
409  #define MVequal(A,B) ( ((A).x)==((B).x) && ((A).y)==((B).y) )                          pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mv16;
410                            pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] =
411                                    pMB->sad16;
412    
413                    }
414            return 0;
415    }
416    
417  #define CHECK_MV16_ZERO {\  #define CHECK_MV16_ZERO {\
418    if ( (0 <= max_dx) && (0 >= min_dx) \    if ( (0 <= max_dx) && (0 >= min_dx) \
419      && (0 <= max_dy) && (0 >= min_dy) ) \      && (0 <= max_dy) && (0 >= min_dy) ) \
420    { \    { \
421      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); \
422      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; \  
423      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
424      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \
425  }  }
426    
427  #define NOCHECK_MV16_CANDIDATE(X,Y) { \  #define NOCHECK_MV16_CANDIDATE(X,Y) { \
428      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); \
429      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);\
430      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
431      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
432  }  }
# Line 454  Line 436 
436      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
437    { \    { \
438      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); \
439      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);\
440      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
441      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
442  }  }
# Line 464  Line 446 
446      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
447    { \    { \
448      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); \
449      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);\
450      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
451      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
452  }  }
# Line 474  Line 456 
456      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
457    { \    { \
458      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); \
459      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);\
460      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
461      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
462  }  }
# Line 482  Line 464 
464    
465  #define CHECK_MV8_ZERO {\  #define CHECK_MV8_ZERO {\
466    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); \
467    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);\
468    if (iSAD < iMinSAD) \    if (iSAD < iMinSAD) \
469    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \
470  }  }
# Line 490  Line 472 
472  #define NOCHECK_MV8_CANDIDATE(X,Y) \  #define NOCHECK_MV8_CANDIDATE(X,Y) \
473    { \    { \
474      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); \
475      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);\
476      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
477      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
478  }  }
# Line 500  Line 482 
482      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
483    { \    { \
484      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); \
485      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);\
486      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
487      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
488  }  }
# Line 510  Line 492 
492      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
493    { \    { \
494      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); \
495      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);\
496      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
497      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
498  }  }
# Line 520  Line 502 
502      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
503    { \    { \
504      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); \
505      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);\
506      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
507      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
508  }  }
# Line 535  Line 517 
517                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
518                                          const int x, const int y,                                          const int x, const int y,
519                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
520                                            const uint32_t iQuant,
521                                            const uint32_t iFcode,
522                                          MBParam * const pParam,                                          MBParam * const pParam,
523                                          MACROBLOCK * const pMBs,                                          const MACROBLOCK * const pMBs,
524                                            const MACROBLOCK * const prevMBs,
525                                          VECTOR * const currMV,                                          VECTOR * const currMV,
526                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
527  {  {
528          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
         const int32_t iQuant = pParam->quant;  
529          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
530          int32_t iSAD;          int32_t iSAD;
531          int32_t pred_x,pred_y;          int32_t pred_x,pred_y;
# Line 564  Line 548 
548  }  }
549  */  */
550    
551  int32_t Diamond16_MainSearch(  int32_t
552          const uint8_t * const pRef,  Diamond16_MainSearch(const uint8_t * const pRef,
553          const uint8_t * const pRefH,          const uint8_t * const pRefH,
554          const uint8_t * const pRefV,          const uint8_t * const pRefV,
555          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
556          const uint8_t * const cur,          const uint8_t * const cur,
557          const int x, const int y,                                           const int x,
558          int32_t startx, int32_t starty,                                           const int y,
559                                             int32_t startx,
560                                             int32_t starty,
561          int32_t iMinSAD,          int32_t iMinSAD,
562          VECTOR * const currMV,          VECTOR * const currMV,
563          const VECTOR * const pmv,          const VECTOR * const pmv,
564          const int32_t min_dx, const int32_t max_dx,                                           const int32_t min_dx,
565          const int32_t min_dy, const int32_t max_dy,                                           const int32_t max_dx,
566                                             const int32_t min_dy,
567                                             const int32_t max_dy,
568          const int32_t iEdgedWidth,          const int32_t iEdgedWidth,
569          const int32_t iDiamondSize,          const int32_t iDiamondSize,
570          const int32_t iFcode,          const int32_t iFcode,
# Line 588  Line 576 
576          int32_t iDirection=0;          int32_t iDirection=0;
577          int32_t iSAD;          int32_t iSAD;
578          VECTOR backupMV;          VECTOR backupMV;
579    
580          backupMV.x = startx;          backupMV.x = startx;
581          backupMV.y = starty;          backupMV.y = starty;
582    
# Line 599  Line 588 
588          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
589    
590          if (iDirection)          if (iDirection)
591                  while (!iFound)                  while (!iFound) {
                 {  
592                          iFound = 1;                          iFound = 1;
593                          backupMV=*currMV;                          backupMV=*currMV;
594    
595                          if ( iDirection != 2)                          if ( iDirection != 2)
596                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
597                                                                                       backupMV.y, 1);
598                          if ( iDirection != 1)                          if ( iDirection != 1)
599                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
600                                                                                       backupMV.y, 2);
601                          if ( iDirection != 4)                          if ( iDirection != 4)
602                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
603                                                                                       backupMV.y - iDiamondSize, 3);
604                          if ( iDirection != 3)                          if ( iDirection != 3)
605                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
606                  }                                                                                     backupMV.y + iDiamondSize, 4);
607          else          } else {
         {  
608                  currMV->x = startx;                  currMV->x = startx;
609                  currMV->y = starty;                  currMV->y = starty;
610          }          }
611          return iMinSAD;          return iMinSAD;
612  }  }
613    
614  int32_t Square16_MainSearch(  int32_t
615                                          const uint8_t * const pRef,  Square16_MainSearch(const uint8_t * const pRef,
616                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
617                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
618                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
619                                          const uint8_t * const cur,                                          const uint8_t * const cur,
620                                          const int x, const int y,                                          const int x,
621                                          int32_t startx, int32_t starty,                                          const int y,
622                                            int32_t startx,
623                                            int32_t starty,
624                                          int32_t iMinSAD,                                          int32_t iMinSAD,
625                                          VECTOR * const currMV,                                          VECTOR * const currMV,
626                                          const VECTOR * const pmv,                                          const VECTOR * const pmv,
627                                          const int32_t min_dx, const int32_t max_dx,                                          const int32_t min_dx,
628                                          const int32_t min_dy, const int32_t max_dy,                                          const int32_t max_dx,
629                                            const int32_t min_dy,
630                                            const int32_t max_dy,
631                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
632                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
633                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 645  Line 639 
639          int32_t iDirection=0;          int32_t iDirection=0;
640          int32_t iSAD;          int32_t iSAD;
641          VECTOR backupMV;          VECTOR backupMV;
642    
643          backupMV.x = startx;          backupMV.x = startx;
644          backupMV.y = starty;          backupMV.y = starty;
645    
# Line 661  Line 656 
656          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
657          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
658    
659          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);          CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
660          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                           backupMV.y - iDiamondSize, 5);
661          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);          CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
662          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                                           backupMV.y + iDiamondSize, 6);
663            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
664                                                             backupMV.y - iDiamondSize, 7);
665            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
666                                                             backupMV.y + iDiamondSize, 8);
667    
668    
669          if (iDirection)          if (iDirection)
670                  while (!iFound)                  while (!iFound) {
                 {  
671                          iFound = 1;                          iFound = 1;
672                          backupMV=*currMV;                          backupMV=*currMV;
673    
674                          switch (iDirection)                          switch (iDirection) {
                         {  
675                                  case 1:                                  case 1:
676                                          CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
677                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                     backupMV.y, 1);
678                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
679                                                                                     backupMV.y - iDiamondSize, 5);
680                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
681                                                                                     backupMV.y - iDiamondSize, 7);
682                                          break;                                          break;
683                                  case 2:                                  case 2:
684                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y,
685                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                                                   2);
686                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
687                                                                                     backupMV.y + iDiamondSize, 6);
688                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
689                                                                                     backupMV.y + iDiamondSize, 8);
690                                          break;                                          break;
691    
692                                  case 3:                                  case 3:
693                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize,
694                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
695                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
696                                                                                     backupMV.y - iDiamondSize, 7);
697                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
698                                                                                     backupMV.y + iDiamondSize, 8);
699                                          break;                                          break;
700    
701                                  case 4:                                  case 4:
702                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize,
703                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
704                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
705                                                                                     backupMV.y - iDiamondSize, 5);
706                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
707                                                                                     backupMV.y + iDiamondSize, 6);
708                                          break;                                          break;
709    
710                                  case 5:                                  case 5:
711                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y,
712                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                   1);
713                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize,
714                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                                                   3);
715                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
716                                                                                     backupMV.y - iDiamondSize, 5);
717                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
718                                                                                     backupMV.y + iDiamondSize, 6);
719                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
720                                                                                     backupMV.y - iDiamondSize, 7);
721                                          break;                                          break;
722    
723                                  case 6:                                  case 6:
724                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y,
725                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                   2);
726                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize,
727                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
728                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);  
729                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
730                                                                                     backupMV.y - iDiamondSize, 5);
731                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
732                                                                                     backupMV.y + iDiamondSize, 6);
733                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
734                                                                                     backupMV.y + iDiamondSize, 8);
735    
736                                          break;                                          break;
737    
738                                  case 7:                                  case 7:
739                                          CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
740                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                     backupMV.y, 1);
741                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize,
742                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
743                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
744                                                                                     backupMV.y - iDiamondSize, 5);
745                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
746                                                                                     backupMV.y - iDiamondSize, 7);
747                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
748                                                                                     backupMV.y + iDiamondSize, 8);
749                                          break;                                          break;
750    
751                                  case 8:                                  case 8:
752                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y,
753                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                   2);
754                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize,
755                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
756                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
757                                                                                     backupMV.y + iDiamondSize, 6);
758                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
759                                                                                     backupMV.y - iDiamondSize, 7);
760                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
761                                                                                     backupMV.y + iDiamondSize, 8);
762                                          break;                                          break;
763                          default:                          default:
764                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y,
765                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                                                                   1);
766                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y,
767                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                   2);
768                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize,
769                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
770                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize,
771                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
772                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);  
773                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
774                                                                                     backupMV.y - iDiamondSize, 5);
775                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
776                                                                                     backupMV.y + iDiamondSize, 6);
777                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
778                                                                                     backupMV.y - iDiamondSize, 7);
779                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
780                                                                                     backupMV.y + iDiamondSize, 8);
781                                          break;                                          break;
782                          }                          }
783                  }          } else {
         else  
                 {  
784                          currMV->x = startx;                          currMV->x = startx;
785                          currMV->y = starty;                          currMV->y = starty;
786                  }                  }
# Line 753  Line 788 
788  }  }
789    
790    
791  int32_t Full16_MainSearch(  int32_t
792                                          const uint8_t * const pRef,  Full16_MainSearch(const uint8_t * const pRef,
793                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
794                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
795                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
796                                          const uint8_t * const cur,                                          const uint8_t * const cur,
797                                          const int x, const int y,                                    const int x,
798                                          int32_t startx, int32_t starty,                                    const int y,
799                                      int32_t startx,
800                                      int32_t starty,
801                                          int32_t iMinSAD,                                          int32_t iMinSAD,
802                                          VECTOR * const currMV,                                          VECTOR * const currMV,
803                                          const VECTOR * const pmv,                                          const VECTOR * const pmv,
804                                          const int32_t min_dx, const int32_t max_dx,                                    const int32_t min_dx,
805                                          const int32_t min_dy, const int32_t max_dy,                                    const int32_t max_dx,
806                                      const int32_t min_dy,
807                                      const int32_t max_dy,
808                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
809                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
810                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 775  Line 814 
814          int32_t iSAD;          int32_t iSAD;
815          int32_t dx,dy;          int32_t dx,dy;
816          VECTOR backupMV;          VECTOR backupMV;
817    
818          backupMV.x = startx;          backupMV.x = startx;
819          backupMV.y = starty;          backupMV.y = starty;
820    
# Line 785  Line 825 
825          return iMinSAD;          return iMinSAD;
826  }  }
827    
828  int32_t Full8_MainSearch(  int32_t
829                                          const uint8_t * const pRef,  AdvDiamond16_MainSearch(const uint8_t * const pRef,
830                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
831                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
832                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
833                                          const uint8_t * const cur,                                          const uint8_t * const cur,
834                                          const int x, const int y,                                                  const int x,
835                                          int32_t startx, int32_t starty,                                                  const int y,
836                                                    int32_t startx,
837                                                    int32_t starty,
838                                                    int32_t iMinSAD,
839                                                    VECTOR * const currMV,
840                                                    const VECTOR * const pmv,
841                                                    const int32_t min_dx,
842                                                    const int32_t max_dx,
843                                                    const int32_t min_dy,
844                                                    const int32_t max_dy,
845                                                    const int32_t iEdgedWidth,
846                                                    const int32_t iDiamondSize,
847                                                    const int32_t iFcode,
848                                                    const int32_t iQuant,
849                                                    int iDirection)
850    {
851    
852            int32_t iSAD;
853    
854    /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
855    
856            if (iDirection) {
857                    CHECK_MV16_CANDIDATE(startx - iDiamondSize, starty);
858                    CHECK_MV16_CANDIDATE(startx + iDiamondSize, starty);
859                    CHECK_MV16_CANDIDATE(startx, starty - iDiamondSize);
860                    CHECK_MV16_CANDIDATE(startx, starty + iDiamondSize);
861            } else {
862                    int bDirection = 1 + 2 + 4 + 8;
863    
864                    do {
865                            iDirection = 0;
866                            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)
867                                    CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize, starty, 1);
868    
869                            if (bDirection & 2)
870                                    CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize, starty, 2);
871    
872                            if (bDirection & 4)
873                                    CHECK_MV16_CANDIDATE_DIR(startx, starty - iDiamondSize, 4);
874    
875                            if (bDirection & 8)
876                                    CHECK_MV16_CANDIDATE_DIR(startx, starty + iDiamondSize, 8);
877    
878                            /* now we're doing diagonal checks near our candidate */
879    
880                            if (iDirection)         //checking if anything found
881                            {
882                                    bDirection = iDirection;
883                                    iDirection = 0;
884                                    startx = currMV->x;
885                                    starty = currMV->y;
886                                    if (bDirection & 3)     //our candidate is left or right
887                                    {
888                                            CHECK_MV16_CANDIDATE_DIR(startx, starty + iDiamondSize, 8);
889                                            CHECK_MV16_CANDIDATE_DIR(startx, starty - iDiamondSize, 4);
890                                    } else                  // what remains here is up or down
891                                    {
892                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize, starty, 2);
893                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize, starty, 1);
894                                    }
895    
896                                    if (iDirection) {
897                                            bDirection += iDirection;
898                                            startx = currMV->x;
899                                            starty = currMV->y;
900                                    }
901                            } else                          //about to quit, eh? not so fast....
902                            {
903                                    switch (bDirection) {
904                                    case 2:
905                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
906                                                                                             starty - iDiamondSize, 2 + 4);
907                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
908                                                                                             starty + iDiamondSize, 2 + 8);
909                                            break;
910                                    case 1:
911                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
912                                                                                             starty - iDiamondSize, 1 + 4);
913                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
914                                                                                             starty + iDiamondSize, 1 + 8);
915                                            break;
916                                    case 2 + 4:
917                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
918                                                                                             starty - iDiamondSize, 1 + 4);
919                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
920                                                                                             starty - iDiamondSize, 2 + 4);
921                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
922                                                                                             starty + iDiamondSize, 2 + 8);
923                                            break;
924                                    case 4:
925                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
926                                                                                             starty - iDiamondSize, 2 + 4);
927                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
928                                                                                             starty - iDiamondSize, 1 + 4);
929                                            break;
930                                    case 8:
931                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
932                                                                                             starty + iDiamondSize, 2 + 8);
933                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
934                                                                                             starty + iDiamondSize, 1 + 8);
935                                            break;
936                                    case 1 + 4:
937                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
938                                                                                             starty + iDiamondSize, 1 + 8);
939                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
940                                                                                             starty - iDiamondSize, 1 + 4);
941                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
942                                                                                             starty - iDiamondSize, 2 + 4);
943                                            break;
944                                    case 2 + 8:
945                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
946                                                                                             starty - iDiamondSize, 1 + 4);
947                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
948                                                                                             starty + iDiamondSize, 1 + 8);
949                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
950                                                                                             starty + iDiamondSize, 2 + 8);
951                                            break;
952                                    case 1 + 8:
953                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
954                                                                                             starty - iDiamondSize, 2 + 4);
955                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
956                                                                                             starty + iDiamondSize, 2 + 8);
957                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
958                                                                                             starty + iDiamondSize, 1 + 8);
959                                            break;
960                                    default:                //1+2+4+8 == we didn't find anything at all
961                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
962                                                                                             starty - iDiamondSize, 1 + 4);
963                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
964                                                                                             starty + iDiamondSize, 1 + 8);
965                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
966                                                                                             starty - iDiamondSize, 2 + 4);
967                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
968                                                                                             starty + iDiamondSize, 2 + 8);
969                                            break;
970                                    }
971                                    if (!iDirection)
972                                            break;          //ok, the end. really
973                                    else {
974                                            bDirection = iDirection;
975                                            startx = currMV->x;
976                                            starty = currMV->y;
977                                    }
978                            }
979                    }
980                    while (1);                              //forever
981            }
982            return iMinSAD;
983    }
984    
985    int32_t
986    AdvDiamond8_MainSearch(const uint8_t * const pRef,
987                                               const uint8_t * const pRefH,
988                                               const uint8_t * const pRefV,
989                                               const uint8_t * const pRefHV,
990                                               const uint8_t * const cur,
991                                               const int x,
992                                               const int y,
993                                               int32_t startx,
994                                               int32_t starty,
995                                               int32_t iMinSAD,
996                                               VECTOR * const currMV,
997                                               const VECTOR * const pmv,
998                                               const int32_t min_dx,
999                                               const int32_t max_dx,
1000                                               const int32_t min_dy,
1001                                               const int32_t max_dy,
1002                                               const int32_t iEdgedWidth,
1003                                               const int32_t iDiamondSize,
1004                                               const int32_t iFcode,
1005                                               const int32_t iQuant,
1006                                               int iDirection)
1007    {
1008    
1009            int32_t iSAD;
1010    
1011    /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
1012    
1013            if (iDirection) {
1014                    CHECK_MV8_CANDIDATE(startx - iDiamondSize, starty);
1015                    CHECK_MV8_CANDIDATE(startx + iDiamondSize, starty);
1016                    CHECK_MV8_CANDIDATE(startx, starty - iDiamondSize);
1017                    CHECK_MV8_CANDIDATE(startx, starty + iDiamondSize);
1018            } else {
1019                    int bDirection = 1 + 2 + 4 + 8;
1020    
1021                    do {
1022                            iDirection = 0;
1023                            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)
1024                                    CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize, starty, 1);
1025    
1026                            if (bDirection & 2)
1027                                    CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize, starty, 2);
1028    
1029                            if (bDirection & 4)
1030                                    CHECK_MV8_CANDIDATE_DIR(startx, starty - iDiamondSize, 4);
1031    
1032                            if (bDirection & 8)
1033                                    CHECK_MV8_CANDIDATE_DIR(startx, starty + iDiamondSize, 8);
1034    
1035                            /* now we're doing diagonal checks near our candidate */
1036    
1037                            if (iDirection)         //checking if anything found
1038                            {
1039                                    bDirection = iDirection;
1040                                    iDirection = 0;
1041                                    startx = currMV->x;
1042                                    starty = currMV->y;
1043                                    if (bDirection & 3)     //our candidate is left or right
1044                                    {
1045                                            CHECK_MV8_CANDIDATE_DIR(startx, starty + iDiamondSize, 8);
1046                                            CHECK_MV8_CANDIDATE_DIR(startx, starty - iDiamondSize, 4);
1047                                    } else                  // what remains here is up or down
1048                                    {
1049                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize, starty, 2);
1050                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize, starty, 1);
1051                                    }
1052    
1053                                    if (iDirection) {
1054                                            bDirection += iDirection;
1055                                            startx = currMV->x;
1056                                            starty = currMV->y;
1057                                    }
1058                            } else                          //about to quit, eh? not so fast....
1059                            {
1060                                    switch (bDirection) {
1061                                    case 2:
1062                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
1063                                                                                            starty - iDiamondSize, 2 + 4);
1064                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
1065                                                                                            starty + iDiamondSize, 2 + 8);
1066                                            break;
1067                                    case 1:
1068                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
1069                                                                                            starty - iDiamondSize, 1 + 4);
1070                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
1071                                                                                            starty + iDiamondSize, 1 + 8);
1072                                            break;
1073                                    case 2 + 4:
1074                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
1075                                                                                            starty - iDiamondSize, 1 + 4);
1076                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
1077                                                                                            starty - iDiamondSize, 2 + 4);
1078                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
1079                                                                                            starty + iDiamondSize, 2 + 8);
1080                                            break;
1081                                    case 4:
1082                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
1083                                                                                            starty - iDiamondSize, 2 + 4);
1084                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
1085                                                                                            starty - iDiamondSize, 1 + 4);
1086                                            break;
1087                                    case 8:
1088                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
1089                                                                                            starty + iDiamondSize, 2 + 8);
1090                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
1091                                                                                            starty + iDiamondSize, 1 + 8);
1092                                            break;
1093                                    case 1 + 4:
1094                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
1095                                                                                            starty + iDiamondSize, 1 + 8);
1096                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
1097                                                                                            starty - iDiamondSize, 1 + 4);
1098                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
1099                                                                                            starty - iDiamondSize, 2 + 4);
1100                                            break;
1101                                    case 2 + 8:
1102                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
1103                                                                                            starty - iDiamondSize, 1 + 4);
1104                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
1105                                                                                            starty + iDiamondSize, 1 + 8);
1106                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
1107                                                                                            starty + iDiamondSize, 2 + 8);
1108                                            break;
1109                                    case 1 + 8:
1110                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
1111                                                                                            starty - iDiamondSize, 2 + 4);
1112                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
1113                                                                                            starty + iDiamondSize, 2 + 8);
1114                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
1115                                                                                            starty + iDiamondSize, 1 + 8);
1116                                            break;
1117                                    default:                //1+2+4+8 == we didn't find anything at all
1118                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
1119                                                                                            starty - iDiamondSize, 1 + 4);
1120                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
1121                                                                                            starty + iDiamondSize, 1 + 8);
1122                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
1123                                                                                            starty - iDiamondSize, 2 + 4);
1124                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
1125                                                                                            starty + iDiamondSize, 2 + 8);
1126                                            break;
1127                                    }
1128                                    if (!(iDirection))
1129                                            break;          //ok, the end. really
1130                                    else {
1131                                            bDirection = iDirection;
1132                                            startx = currMV->x;
1133                                            starty = currMV->y;
1134                                    }
1135                            }
1136                    }
1137                    while (1);                              //forever
1138            }
1139            return iMinSAD;
1140    }
1141    
1142    
1143    int32_t
1144    Full8_MainSearch(const uint8_t * const pRef,
1145                                     const uint8_t * const pRefH,
1146                                     const uint8_t * const pRefV,
1147                                     const uint8_t * const pRefHV,
1148                                     const uint8_t * const cur,
1149                                     const int x,
1150                                     const int y,
1151                                     int32_t startx,
1152                                     int32_t starty,
1153                                          int32_t iMinSAD,                                          int32_t iMinSAD,
1154                                          VECTOR * const currMV,                                          VECTOR * const currMV,
1155                                          const VECTOR * const pmv,                                          const VECTOR * const pmv,
1156                                          const int32_t min_dx, const int32_t max_dx,                                   const int32_t min_dx,
1157                                          const int32_t min_dy, const int32_t max_dy,                                   const int32_t max_dx,
1158                                     const int32_t min_dy,
1159                                     const int32_t max_dy,
1160                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
1161                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
1162                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 807  Line 1166 
1166          int32_t iSAD;          int32_t iSAD;
1167          int32_t dx,dy;          int32_t dx,dy;
1168          VECTOR backupMV;          VECTOR backupMV;
1169    
1170          backupMV.x = startx;          backupMV.x = startx;
1171          backupMV.y = starty;          backupMV.y = starty;
1172    
# Line 819  Line 1179 
1179    
1180    
1181    
1182  int32_t Halfpel16_Refine(  int32_t
1183          const uint8_t * const pRef,  Halfpel16_Refine(const uint8_t * const pRef,
1184          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1185          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1186          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1187          const uint8_t * const cur,          const uint8_t * const cur,
1188          const int x, const int y,                                   const int x,
1189                                     const int y,
1190          VECTOR * const currMV,          VECTOR * const currMV,
1191          int32_t iMinSAD,          int32_t iMinSAD,
1192          const VECTOR * const pmv,          const VECTOR * const pmv,
1193          const int32_t min_dx, const int32_t max_dx,                                   const int32_t min_dx,
1194          const int32_t min_dy, const int32_t max_dy,                                   const int32_t max_dx,
1195                                     const int32_t min_dy,
1196                                     const int32_t max_dy,
1197          const int32_t iFcode,          const int32_t iFcode,
1198          const int32_t iQuant,          const int32_t iQuant,
1199          const int32_t iEdgedWidth)          const int32_t iEdgedWidth)
# Line 855  Line 1218 
1218  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)
1219    
1220    
1221  int32_t PMVfastSearch16(  int32_t
1222                                          const uint8_t * const pRef,  PMVfastSearch16(const uint8_t * const pRef,
1223                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1224                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1225                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1226                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1227                                          const int x, const int y,                                  const int x,
1228                                    const int y,
1229                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
1230                                    const uint32_t iQuant,
1231                                    const uint32_t iFcode,
1232                                          const MBParam * const pParam,                                          const MBParam * const pParam,
1233                                          MACROBLOCK * const pMBs,                                  const MACROBLOCK * const pMBs,
1234                                    const MACROBLOCK * const prevMBs,
1235                                          VECTOR * const currMV,                                          VECTOR * const currMV,
1236                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
1237  {  {
1238          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;  
1239          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
1240          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
1241          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
# Line 892  Line 1257 
1257          VECTOR pmv[4];          VECTOR pmv[4];
1258          int32_t psad[4];          int32_t psad[4];
1259    
1260          MACROBLOCK * const pMB = pMBs + x + y * iWcount;          MainSearch16FuncPtr MainSearchPtr;
1261    
1262    //  const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
1263            const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
1264    
1265          static int32_t threshA,threshB;          static int32_t threshA,threshB;
1266          int32_t bPredEq;          int32_t bPredEq;
1267          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
1268    
1269  /* Get maximum range */  /* Get maximum range */
1270          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,
1271                    x, y, 16, iWidth, iHeight, iFcode);                            iFcode);
1272    
1273  /* 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 */
1274    
1275          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16)) {
1276          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
1277          max_dx = EVEN(max_dx);          max_dx = EVEN(max_dx);
1278          min_dy = EVEN(min_dy);          min_dy = EVEN(min_dy);
1279          max_dy = EVEN(max_dy);          max_dy = EVEN(max_dy);
1280          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
   
1281    
1282            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1283          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
1284    
1285          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
1286                  threshA =  512;                  threshA =  512;
1287                  threshB = 1024;                  threshB = 1024;
1288    
1289          }          } else {
         else  
         {  
1290                  threshA = psad[0];                  threshA = psad[0];
1291                  threshB = threshA+256;                  threshB = threshA+256;
1292                  if (threshA< 512) threshA =  512;                  if (threshA < 512)
1293                  if (threshA>1024) threshA = 1024;                          threshA = 512;
1294                  if (threshB>1792) threshB = 1792;                  if (threshA > 1024)
1295                            threshA = 1024;
1296                    if (threshB > 1792)
1297                            threshB = 1792;
1298          }          }
1299    
1300          iFound=0;          iFound=0;
1301    
 /* 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[0]) ) )  
                 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) || (bPredEq) )  
                 iDiamondSize=1; // halfpel!  
         else  
                 iDiamondSize=2; // halfpel!  
   
         if (!(MotionFlags & PMV_HALFPELDIAMOND16) )  
                 iDiamondSize*=2;  
   
1302  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
1303     MinSAD=SAD     MinSAD=SAD
1304     If Motion Vector equal to Previous frame motion vector     If Motion Vector equal to Previous frame motion vector
# Line 958  Line 1306 
1306     If SAD<=256 goto Step 10.     If SAD<=256 goto Step 10.
1307  */  */
1308    
   
 // Prepare for main loop  
   
1309          *currMV=pmv[0];         /* current best := prediction */          *currMV=pmv[0];         /* current best := prediction */
1310          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16)) {   /* This should NOT be necessary! */
         {       /* This should NOT be necessary! */  
1311                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
1312                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
1313          }          }
1314    
1315          if (currMV->x > max_dx)          if (currMV->x > max_dx) {
         {  
1316                  currMV->x=max_dx;                  currMV->x=max_dx;
1317          }          }
1318          if (currMV->x < min_dx)          if (currMV->x < min_dx) {
         {  
1319                  currMV->x=min_dx;                  currMV->x=min_dx;
1320          }          }
1321          if (currMV->y > max_dy)          if (currMV->y > max_dy) {
         {  
1322                  currMV->y=max_dy;                  currMV->y=max_dy;
1323          }          }
1324          if (currMV->y < min_dy)          if (currMV->y < min_dy) {
         {  
1325                  currMV->y=min_dy;                  currMV->y=min_dy;
1326          }          }
1327    
1328          iMinSAD = sad16( cur,          iMinSAD =
1329                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  sad16(cur,
1330                           iEdgedWidth, MV_MAX_ERROR);                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
1331          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
1332            iMinSAD +=
1333          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,pMB->mvs[0])) && (iMinSAD < pMB->sad16) ) )                  calc_delta_16(currMV->x - pmv[0].x, currMV->y - pmv[0].y,
1334          {                                            (uint8_t) iFcode, iQuant);
1335    
1336            if ((iMinSAD < 256) ||
1337                    ((MVequal(*currMV, prevMB->mvs[0])) &&
1338                     ((uint32_t) iMinSAD < prevMB->sad16))) {
1339                    if (iMinSAD < 2 * iQuant)       // high chances for SKIP-mode
1340                    {
1341                            if (!MVzero(*currMV)) {
1342                                    iMinSAD += MV16_00_BIAS;
1343                                    CHECK_MV16_ZERO;        // (0,0) saves space for letterboxed pictures
1344                                    iMinSAD -= MV16_00_BIAS;
1345                            }
1346                    }
1347    
1348                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1349                          goto PMVfast16_Terminate_without_Refine;                          goto PMVfast16_Terminate_without_Refine;
# Line 999  Line 1351 
1351                          goto PMVfast16_Terminate_with_Refine;                          goto PMVfast16_Terminate_with_Refine;
1352          }          }
1353    
1354    
1355    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
1356       vector of the median.
1357       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
1358    */
1359    
1360            if ((bPredEq) && (MVequal(pmv[0], prevMB->mvs[0])))
1361                    iFound = 2;
1362    
1363    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
1364       Otherwise select large Diamond Search.
1365    */
1366    
1367            if ((!MVzero(pmv[0])) || (threshB < 1536) || (bPredEq))
1368                    iDiamondSize = 1;               // halfpel!
1369            else
1370                    iDiamondSize = 2;               // halfpel!
1371    
1372            if (!(MotionFlags & PMV_HALFPELDIAMOND16))
1373                    iDiamondSize *= 2;
1374    
1375  /*  /*
1376     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.
1377     Also calculate (0,0) but do not subtract offset.     Also calculate (0,0) but do not subtract offset.
1378     Let MinSAD be the smallest SAD up to this point.     Let MinSAD be the smallest SAD up to this point.
1379     If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
1380  */  */
1381    
1382  // (0,0) is always possible  // (0,0) is always possible
1383    
1384            if (!MVzero(pmv[0]))
1385          CHECK_MV16_ZERO;          CHECK_MV16_ZERO;
1386    
1387  // previous frame MV is always possible  // previous frame MV is always possible
1388          CHECK_MV16_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);  
1389            if (!MVzero(prevMB->mvs[0]))
1390                    if (!MVequal(prevMB->mvs[0], pmv[0]))
1391                            CHECK_MV16_CANDIDATE(prevMB->mvs[0].x, prevMB->mvs[0].y);
1392    
1393  // left neighbour, if allowed  // left neighbour, if allowed
1394          if (x != 0)  
1395          {          if (!MVzero(pmv[1]))
1396                  if (!(MotionFlags & PMV_HALFPEL16 ))                  if (!MVequal(pmv[1], prevMB->mvs[0]))
1397                  {       pmv[1].x = EVEN(pmv[1].x);                          if (!MVequal(pmv[1], pmv[0])) {
1398                                    if (!(MotionFlags & PMV_HALFPEL16)) {
1399                                            pmv[1].x = EVEN(pmv[1].x);
1400                  pmv[1].y = EVEN(pmv[1].y);                  pmv[1].y = EVEN(pmv[1].y);
1401                  }                  }
1402    
1403                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1404          }          }
   
1405  // top neighbour, if allowed  // top neighbour, if allowed
1406          if (y != 0)          if (!MVzero(pmv[2]))
1407          {                  if (!MVequal(pmv[2], prevMB->mvs[0]))
1408                  if (!(MotionFlags & PMV_HALFPEL16 ))                          if (!MVequal(pmv[2], pmv[0]))
1409                  {       pmv[2].x = EVEN(pmv[2].x);                                  if (!MVequal(pmv[2], pmv[1])) {
1410                                            if (!(MotionFlags & PMV_HALFPEL16)) {
1411                                                    pmv[2].x = EVEN(pmv[2].x);
1412                  pmv[2].y = EVEN(pmv[2].y);                  pmv[2].y = EVEN(pmv[2].y);
1413                  }                  }
1414                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1415    
1416  // top right neighbour, if allowed  // top right neighbour, if allowed
1417                  if (x != (iWcount-1))                                          if (!MVzero(pmv[3]))
1418                  {                                                  if (!MVequal(pmv[3], prevMB->mvs[0]))
1419                          if (!(MotionFlags & PMV_HALFPEL16 ))                                                          if (!MVequal(pmv[3], pmv[0]))
1420                          {       pmv[3].x = EVEN(pmv[3].x);                                                                  if (!MVequal(pmv[3], pmv[1]))
1421                                                                            if (!MVequal(pmv[3], pmv[2])) {
1422                                                                                    if (!(MotionFlags & PMV_HALFPEL16)) {
1423                                                                                            pmv[3].x = EVEN(pmv[3].x);
1424                          pmv[3].y = EVEN(pmv[3].y);                          pmv[3].y = EVEN(pmv[3].y);
1425                          }                          }
1426                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                  CHECK_MV16_CANDIDATE(pmv[3].x,
1427                                                                                                                             pmv[3].y);
1428                  }                  }
1429          }          }
1430    
1431            if ((MVzero(*currMV)) &&
1432                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
1433                    iMinSAD -= MV16_00_BIAS;
1434    
1435    
1436  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
1437     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.
1438  */  */
1439    
1440          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[0]) && (iMinSAD < pMB->sad16) ) )          if ((iMinSAD <= threshA) ||
1441          {                  (MVequal(*currMV, prevMB->mvs[0]) &&
1442                     ((uint32_t) iMinSAD < prevMB->sad16))) {
1443                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1444                          goto PMVfast16_Terminate_without_Refine;                          goto PMVfast16_Terminate_without_Refine;
1445                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1066  Line 1457 
1457     Refine by using small diamond and goto step 10.     Refine by using small diamond and goto step 10.
1458  */  */
1459    
1460            if (MotionFlags & PMV_USESQUARES16)
1461                    MainSearchPtr = Square16_MainSearch;
1462            else if (MotionFlags & PMV_ADVANCEDDIAMOND16)
1463                    MainSearchPtr = AdvDiamond16_MainSearch;
1464            else
1465                    MainSearchPtr = Diamond16_MainSearch;
1466    
1467          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1468    
1469  /* 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 */
1470          iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
1471                                            x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
1472                                            currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx,
1473                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
1474                                                      iQuant, iFound);
1475    
1476          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
1477                  *currMV = newMV;                  *currMV = newMV;
1478                  iMinSAD = iSAD;                  iMinSAD = iSAD;
1479          }          }
1480    
1481          if (MotionFlags & PMV_EXTSEARCH16)          if (MotionFlags & PMV_EXTSEARCH16) {
         {  
1482  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1483    
1484                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
1485                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1486                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1487                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, pmv,
1488                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1489                                                                      iDiamondSize, iFcode, iQuant, iFound);
1490    
1491                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1492                          *currMV = newMV;                          *currMV = newMV;
1493                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1494                  }                  }
1495                  }                  }
1496    
1497                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
1498                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1499                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
1500                                                            0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy,
1501                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
1502                                                                      iQuant, iFound);
1503    
1504                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1505                          *currMV = newMV;                          *currMV = newMV;
1506                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1507                  }                  }
# Line 1117  Line 1514 
1514    
1515  PMVfast16_Terminate_with_Refine:  PMVfast16_Terminate_with_Refine:
1516          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
1517                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
1518                                    x, y,                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
1519                                    currMV, iMinSAD,                                                           iMinSAD, pmv, min_dx, max_dx, min_dy, max_dy,
1520                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                           iFcode, iQuant, iEdgedWidth);
1521    
1522  PMVfast16_Terminate_without_Refine:  PMVfast16_Terminate_without_Refine:
1523          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - pmv[0].x;
# Line 1133  Line 1530 
1530    
1531    
1532    
1533  int32_t Diamond8_MainSearch(  int32_t
1534          const uint8_t * const pRef,  Diamond8_MainSearch(const uint8_t * const pRef,
1535          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1536          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1537          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1538          const uint8_t * const cur,          const uint8_t * const cur,
1539          const int x, const int y,                                          const int x,
1540          int32_t startx, int32_t starty,                                          const int y,
1541                                            int32_t startx,
1542                                            int32_t starty,
1543          int32_t iMinSAD,          int32_t iMinSAD,
1544          VECTOR * const currMV,          VECTOR * const currMV,
1545          const VECTOR * const pmv,          const VECTOR * const pmv,
1546          const int32_t min_dx, const int32_t max_dx,                                          const int32_t min_dx,
1547          const int32_t min_dy, const int32_t max_dy,                                          const int32_t max_dx,
1548                                            const int32_t min_dy,
1549                                            const int32_t max_dy,
1550          const int32_t iEdgedWidth,          const int32_t iEdgedWidth,
1551          const int32_t iDiamondSize,          const int32_t iDiamondSize,
1552          const int32_t iFcode,          const int32_t iFcode,
# Line 1157  Line 1558 
1558          int32_t iDirection=0;          int32_t iDirection=0;
1559          int32_t iSAD;          int32_t iSAD;
1560          VECTOR backupMV;          VECTOR backupMV;
1561    
1562          backupMV.x = startx;          backupMV.x = startx;
1563          backupMV.y = starty;          backupMV.y = starty;
1564    
# Line 1168  Line 1570 
1570          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
1571    
1572          if (iDirection)          if (iDirection)
1573                  while (!iFound)                  while (!iFound) {
                 {  
1574                          iFound = 1;                          iFound = 1;
1575                          backupMV=*currMV;       // since iDirection!=0, this is well defined!                          backupMV=*currMV;       // since iDirection!=0, this is well defined!
1576    
1577                          if ( iDirection != 2)                          if ( iDirection != 2)
1578                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1579                                                                                      backupMV.y, 1);
1580                          if ( iDirection != 1)                          if ( iDirection != 1)
1581                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1582                                                                                      backupMV.y, 2);
1583                          if ( iDirection != 4)                          if ( iDirection != 4)
1584                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1585                                                                                      backupMV.y - iDiamondSize, 3);
1586                          if ( iDirection != 3)                          if ( iDirection != 3)
1587                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1588                  }                                                                                    backupMV.y + iDiamondSize, 4);
1589          else          } else {
         {  
1590                  currMV->x = startx;                  currMV->x = startx;
1591                  currMV->y = starty;                  currMV->y = starty;
1592          }          }
1593          return iMinSAD;          return iMinSAD;
1594  }  }
1595    
1596  int32_t Halfpel8_Refine(  int32_t
1597          const uint8_t * const pRef,  Halfpel8_Refine(const uint8_t * const pRef,
1598          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1599          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1600          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1601          const uint8_t * const cur,          const uint8_t * const cur,
1602          const int x, const int y,                                  const int x,
1603                                    const int y,
1604          VECTOR * const currMV,          VECTOR * const currMV,
1605          int32_t iMinSAD,          int32_t iMinSAD,
1606          const VECTOR * const pmv,          const VECTOR * const pmv,
1607          const int32_t min_dx, const int32_t max_dx,                                  const int32_t min_dx,
1608          const int32_t min_dy, const int32_t max_dy,                                  const int32_t max_dx,
1609                                    const int32_t min_dy,
1610                                    const int32_t max_dy,
1611          const int32_t iFcode,          const int32_t iFcode,
1612          const int32_t iQuant,          const int32_t iQuant,
1613          const int32_t iEdgedWidth)          const int32_t iEdgedWidth)
# Line 1226  Line 1632 
1632    
1633  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)
1634    
1635  int32_t PMVfastSearch8(  int32_t
1636                                          const uint8_t * const pRef,  PMVfastSearch8(const uint8_t * const pRef,
1637                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1638                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1639                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1640                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1641                                          const int x, const int y,                             const int x,
1642                                          const int start_x, int start_y,                             const int y,
1643                               const int start_x,
1644                               const int start_y,
1645                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
1646                               const uint32_t iQuant,
1647                               const uint32_t iFcode,
1648                                          const MBParam * const pParam,                                          const MBParam * const pParam,
1649                                          MACROBLOCK * const pMBs,                             const MACROBLOCK * const pMBs,
1650                               const MACROBLOCK * const prevMBs,
1651                                          VECTOR * const currMV,                                          VECTOR * const currMV,
1652                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
1653  {  {
1654          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;  
1655          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
1656          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
1657          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
# Line 1261  Line 1669 
1669          int32_t psad[4];          int32_t psad[4];
1670          VECTOR newMV;          VECTOR newMV;
1671          VECTOR backupMV;          VECTOR backupMV;
1672            VECTOR startMV;
1673    
1674          MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;  //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1675            const MACROBLOCK *const prevMB = prevMBs + (x >> 1) + (y >> 1) * iWcount;
1676    
1677          static int32_t threshA,threshB;          static int32_t threshA,threshB;
1678          int32_t iFound,bPredEq;          int32_t iFound,bPredEq;
1679          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
1680    
1681          int32_t iSubBlock = ((y&1)<<1) + (x&1);          int32_t iSubBlock = (y & 1) + (y & 1) + (x & 1);
1682    
1683  /* Get maximum range */          MainSearch8FuncPtr MainSearchPtr;
         get_range(&min_dx, &max_dx, &min_dy, &max_dy,  
                   x, y, 8, iWidth, iHeight, iFcode);  
1684    
1685  /* we work with abs. MVs, not relative to prediction, so range is relative to 0,0 */          /* Init variables */
1686            startMV.x = start_x;
1687            startMV.y = start_y;
1688    
1689          if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))          /* Get maximum range */
1690          { min_dx = EVEN(min_dx);          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 8, iWidth, iHeight,
1691                              iFcode);
1692    
1693            if (!(MotionFlags & PMV_HALFPELDIAMOND8)) {
1694                    min_dx = EVEN(min_dx);
1695          max_dx = EVEN(max_dx);          max_dx = EVEN(max_dx);
1696          min_dy = EVEN(min_dy);          min_dy = EVEN(min_dy);
1697          max_dy = EVEN(max_dy);          max_dy = EVEN(max_dy);
1698          }               /* because we might use IF (dx>max_dx) THEN dx=max_dx; */          }
   
1699    
1700          bPredEq  = get_pmvdata(pMBs, (x>>1), (y>>1), iWcount, iSubBlock, pmv, psad);          /* because we might use IF (dx>max_dx) THEN dx=max_dx; */
1701            bPredEq =
1702                    get_pmvdata(pMBs, (x >> 1), (y >> 1), iWcount, iSubBlock, pmv, psad);
1703    
1704          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
1705                  threshA =  512/4;                  threshA =  512/4;
1706                  threshB = 1024/4;                  threshB = 1024/4;
1707    
1708          }          } else {
         else  
         {  
1709                  threshA = psad[0]/4;                    /* good estimate */                  threshA = psad[0]/4;                    /* good estimate */
1710                  threshB = threshA+256/4;                  threshB = threshA+256/4;
1711                  if (threshA< 512/4) threshA =  512/4;                  if (threshA < 512 / 4)
1712                  if (threshA>1024/4) threshA = 1024/4;                          threshA = 512 / 4;
1713                  if (threshB>1792/4) threshB = 1792/4;                  if (threshA > 1024 / 4)
1714                            threshA = 1024 / 4;
1715                    if (threshB > 1792 / 4)
1716                            threshB = 1792 / 4;
1717          }          }
1718    
1719          iFound=0;          iFound=0;
1720    
 /* 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;  
   
1721  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
1722     MinSAD=SAD     MinSAD=SAD
1723     If Motion Vector equal to Previous frame motion vector     If Motion Vector equal to Previous frame motion vector
# Line 1333  Line 1728 
1728    
1729  // Prepare for main loop  // Prepare for main loop
1730    
1731          currMV->x=start_x;              /* start with mv16 */  //  if (MotionFlags & PMV_USESQUARES8)
1732          currMV->y=start_y;  //      MainSearchPtr = Square8_MainSearch;
1733    //  else
1734    
1735          iMinSAD = sad8( cur,          if (MotionFlags & PMV_ADVANCEDDIAMOND8)
1736                          get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),                  MainSearchPtr = AdvDiamond8_MainSearch;
1737                          iEdgedWidth);          else
1738          iMinSAD += calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y, (uint8_t)iFcode) * iQuant;                  MainSearchPtr = Diamond8_MainSearch;
1739    
1740          if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,pMB->mvs[iSubBlock])) && (iMinSAD < pMB->sad8[iSubBlock]) ) )  
1741          {          *currMV = startMV;
1742    
1743            iMinSAD =
1744                    sad8(cur,
1745                             get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
1746                                                    iEdgedWidth), iEdgedWidth);
1747            iMinSAD +=
1748                    calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y,
1749                                             (uint8_t) iFcode, iQuant);
1750    
1751            if ((iMinSAD < 256 / 4) || ((MVequal(*currMV, prevMB->mvs[iSubBlock]))
1752                                                                    && ((uint32_t) iMinSAD <
1753                                                                            prevMB->sad8[iSubBlock]))) {
1754                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1755                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
1756                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
1757                          goto PMVfast8_Terminate_with_Refine;                          goto PMVfast8_Terminate_with_Refine;
1758          }          }
1759    
1760    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
1761       vector of the median.
1762       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
1763    */
1764    
1765            if ((bPredEq) && (MVequal(pmv[0], prevMB->mvs[iSubBlock])))
1766                    iFound = 2;
1767    
1768    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
1769       Otherwise select large Diamond Search.
1770    */
1771    
1772            if ((!MVzero(pmv[0])) || (threshB < 1536 / 4) || (bPredEq))
1773                    iDiamondSize = 1;               // 1 halfpel!
1774            else
1775                    iDiamondSize = 2;               // 2 halfpel = 1 full pixel!
1776    
1777            if (!(MotionFlags & PMV_HALFPELDIAMOND8))
1778                    iDiamondSize *= 2;
1779    
1780    
1781  /*  /*
1782     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.
1783     Also calculate (0,0) but do not subtract offset.     Also calculate (0,0) but do not subtract offset.
1784     Let MinSAD be the smallest SAD up to this point.     Let MinSAD be the smallest SAD up to this point.
1785     If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
1786  */  */
1787    
1788  // the prediction might be even better than mv16  // the median prediction might be even better than mv16
1789    
1790            if (!MVequal(pmv[0], startMV))
1791          CHECK_MV8_CANDIDATE(pmv[0].x,pmv[0].y);          CHECK_MV8_CANDIDATE(pmv[0].x,pmv[0].y);
1792    
1793  // (0,0) is always possible  // (0,0) if needed
1794            if (!MVzero(pmv[0]))
1795                    if (!MVzero(startMV))
1796          CHECK_MV8_ZERO;          CHECK_MV8_ZERO;
1797    
1798  // previous frame MV is always possible  // previous frame MV if needed
1799          CHECK_MV8_CANDIDATE(pMB->mvs[iSubBlock].x,pMB->mvs[iSubBlock].y);          if (!MVzero(prevMB->mvs[iSubBlock]))
1800                    if (!MVequal(prevMB->mvs[iSubBlock], startMV))
1801                            if (!MVequal(prevMB->mvs[iSubBlock], pmv[0]))
1802                                    CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,
1803                                                                            prevMB->mvs[iSubBlock].y);
1804    
1805            if ((iMinSAD <= threshA) ||
1806                    (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
1807                     ((uint32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
1808                    if (MotionFlags & PMV_QUICKSTOP16)
1809                            goto PMVfast8_Terminate_without_Refine;
1810                    if (MotionFlags & PMV_EARLYSTOP16)
1811                            goto PMVfast8_Terminate_with_Refine;
1812            }
1813    
1814  // left neighbour, if allowed  // left neighbour, if allowed and needed
1815          if (psad[1] != MV_MAX_ERROR)          if (!MVzero(pmv[1]))
1816          {                  if (!MVequal(pmv[1], startMV))
1817                  if (!(MotionFlags & PMV_HALFPEL8 ))                          if (!MVequal(pmv[1], prevMB->mvs[iSubBlock]))
1818                  {       pmv[1].x = EVEN(pmv[1].x);                                  if (!MVequal(pmv[1], pmv[0])) {
1819                                            if (!(MotionFlags & PMV_HALFPEL8)) {
1820                                                    pmv[1].x = EVEN(pmv[1].x);
1821                  pmv[1].y = EVEN(pmv[1].y);                  pmv[1].y = EVEN(pmv[1].y);
1822                  }                  }
1823                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
1824          }          }
1825    // top neighbour, if allowed and needed
1826  // top neighbour, if allowed          if (!MVzero(pmv[2]))
1827          if (psad[2] != MV_MAX_ERROR)                  if (!MVequal(pmv[2], startMV))
1828          {                          if (!MVequal(pmv[2], prevMB->mvs[iSubBlock]))
1829                  if (!(MotionFlags & PMV_HALFPEL8 ))                                  if (!MVequal(pmv[2], pmv[0]))
1830                  {       pmv[2].x = EVEN(pmv[2].x);                                          if (!MVequal(pmv[2], pmv[1])) {
1831                                                    if (!(MotionFlags & PMV_HALFPEL8)) {
1832                                                            pmv[2].x = EVEN(pmv[2].x);
1833                  pmv[2].y = EVEN(pmv[2].y);                  pmv[2].y = EVEN(pmv[2].y);
1834                  }                  }
1835                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
1836    
1837  // top right neighbour, if allowed  // top right neighbour, if allowed and needed
1838                  if (psad[3] != MV_MAX_ERROR)                                                  if (!MVzero(pmv[3]))
1839                  {                                                          if (!MVequal(pmv[3], startMV))
1840                          if (!(MotionFlags & PMV_HALFPEL8 ))                                                                  if (!MVequal(pmv[3], prevMB->mvs[iSubBlock]))
1841                          {       pmv[3].x = EVEN(pmv[3].x);                                                                          if (!MVequal(pmv[3], pmv[0]))
1842                                                                                    if (!MVequal(pmv[3], pmv[1]))
1843                                                                                            if (!MVequal(pmv[3], pmv[2])) {
1844                                                                                                    if (!
1845                                                                                                            (MotionFlags &
1846                                                                                                             PMV_HALFPEL8)) {
1847                                                                                                            pmv[3].x = EVEN(pmv[3].x);
1848                          pmv[3].y = EVEN(pmv[3].y);                          pmv[3].y = EVEN(pmv[3].y);
1849                          }                          }
1850                          CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                                  CHECK_MV8_CANDIDATE(pmv[3].x,
1851                                                                                                                                            pmv[3].y);
1852                  }                  }
1853          }          }
1854    
1855            if ((MVzero(*currMV)) &&
1856                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
1857                    iMinSAD -= MV8_00_BIAS;
1858    
1859    
1860  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
1861     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.
1862  */  */
1863    
1864          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[iSubBlock]) && (iMinSAD < pMB->sad8[iSubBlock]) ) )          if ((iMinSAD <= threshA) ||
1865          {                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
1866                     ((uint32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
1867                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1868                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
1869                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1421  Line 1883 
1883          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1884    
1885  /* 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 */
1886          iSAD = Diamond8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
1887                                           x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
1888                                           currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx,
1889                                           pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
1890                                                      iQuant, iFound);
1891    
1892          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
1893                  *currMV = newMV;                  *currMV = newMV;
1894                  iMinSAD = iSAD;                  iMinSAD = iSAD;
1895          }          }
1896    
1897          if (MotionFlags & PMV_EXTSEARCH8)          if (MotionFlags & PMV_EXTSEARCH8) {
         {  
1898  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1899    
1900                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
1901                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1902                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1903                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, pmv,
1904                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1905                                                                      iDiamondSize, iFcode, iQuant, iFound);
1906    
1907                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1908                          *currMV = newMV;                          *currMV = newMV;
1909                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1910                  }                  }
1911                  }                  }
1912    
1913                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
1914                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1915                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
1916                                                            0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy,
1917                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
1918                                                                      iQuant, iFound);
1919    
1920                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1921                          *currMV = newMV;                          *currMV = newMV;
1922                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1923                  }                  }
# Line 1469  Line 1930 
1930    
1931  PMVfast8_Terminate_with_Refine:  PMVfast8_Terminate_with_Refine:
1932          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
1933                  iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
1934                                                   x, y,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
1935                                                   currMV, iMinSAD,                                                          iMinSAD, pmv, min_dx, max_dx, min_dy, max_dy,
1936                                                   pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
1937    
1938    
1939  PMVfast8_Terminate_without_Refine:  PMVfast8_Terminate_without_Refine:
# Line 1482  Line 1943 
1943          return iMinSAD;          return iMinSAD;
1944  }  }
1945    
1946  int32_t EPZSSearch16(  int32_t
1947                                          const uint8_t * const pRef,  EPZSSearch16(const uint8_t * const pRef,
1948                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1949                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1950                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1951                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1952                                          const int x, const int y,                           const int x,
1953                             const int y,
1954                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
1955                             const uint32_t iQuant,
1956                             const uint32_t iFcode,
1957                                          const MBParam * const pParam,                                          const MBParam * const pParam,
1958                                          MACROBLOCK * const pMBs,                           const MACROBLOCK * const pMBs,
1959                             const MACROBLOCK * const prevMBs,
1960                                          VECTOR * const currMV,                                          VECTOR * const currMV,
1961                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
1962  {  {
1963          const uint32_t iWcount = pParam->mb_width;          const uint32_t iWcount = pParam->mb_width;
1964          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;  
1965    
1966          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
1967          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
# Line 1518  Line 1981 
1981          int32_t psad[8];          int32_t psad[8];
1982    
1983          static MACROBLOCK * oldMBs = NULL;          static MACROBLOCK * oldMBs = NULL;
1984          MACROBLOCK * const pMB = pMBs + x + y * iWcount;  
1985    //  const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
1986            const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
1987          MACROBLOCK * oldMB = NULL;          MACROBLOCK * oldMB = NULL;
1988    
1989          static int32_t thresh2;          static int32_t thresh2;
1990          int32_t bPredEq;          int32_t bPredEq;
1991          int32_t iMinSAD,iSAD=9999;          int32_t iMinSAD,iSAD=9999;
1992    
1993          MainSearch16FuncPtr EPZSMainSearchPtr;          MainSearch16FuncPtr MainSearchPtr;
1994    
1995          if (oldMBs == NULL)          if (oldMBs == NULL) {
1996          {       oldMBs = (MACROBLOCK*) calloc(1,iWcount*iHcount*sizeof(MACROBLOCK));                  oldMBs = (MACROBLOCK *) calloc(iWcount * iHcount, sizeof(MACROBLOCK));
1997                  fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));  //      fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));
1998          }          }
1999          oldMB = oldMBs + x + y * iWcount;          oldMB = oldMBs + x + y * iWcount;
2000    
2001  /* Get maximum range */  /* Get maximum range */
2002          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,
2003                          x, y, 16, iWidth, iHeight, iFcode);                            iFcode);
2004    
2005  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */          if (!(MotionFlags & PMV_HALFPEL16)) {
2006                    min_dx = EVEN(min_dx);
         if (!(MotionFlags & PMV_HALFPEL16 ))  
         { min_dx = EVEN(min_dx);  
2007            max_dx = EVEN(max_dx);            max_dx = EVEN(max_dx);
2008            min_dy = EVEN(min_dy);            min_dy = EVEN(min_dy);
2009            max_dy = EVEN(max_dy);            max_dy = EVEN(max_dy);
2010          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
2011            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2012          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
2013    
2014  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
# Line 1558  Line 2021 
2021  // Prepare for main loop  // Prepare for main loop
2022    
2023          *currMV=pmv[0];         /* current best := median prediction */          *currMV=pmv[0];         /* current best := median prediction */
2024          if (!(MotionFlags & PMV_HALFPEL16))          if (!(MotionFlags & PMV_HALFPEL16)) {
         {  
2025                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
2026                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
2027          }          }
# Line 1575  Line 2037 
2037    
2038  /***************** This is predictor SET A: only median prediction ******************/  /***************** This is predictor SET A: only median prediction ******************/
2039    
2040          iMinSAD = sad16( cur,          iMinSAD =
2041                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  sad16(cur,
2042                  iEdgedWidth, MV_MAX_ERROR);                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
2043          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
2044            iMinSAD +=
2045                    calc_delta_16(currMV->x - pmv[0].x, currMV->y - pmv[0].y,
2046                                              (uint8_t) iFcode, iQuant);
2047    
2048  // thresh1 is fixed to 256  // thresh1 is fixed to 256
2049          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,pMB->mvs[0])) && (iMinSAD < pMB->sad16) ) )          if ((iMinSAD < 256) ||
2050                  {                  ((MVequal(*currMV, prevMB->mvs[0])) &&
2051                     ((uint32_t) iMinSAD < prevMB->sad16))) {
2052                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2053                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2054                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1592  Line 2058 
2058  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
2059    
2060  // previous frame MV  // previous frame MV
2061          CHECK_MV16_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);          CHECK_MV16_CANDIDATE(prevMB->mvs[0].x, prevMB->mvs[0].y);
2062    
2063  // set threshhold based on Min of Prediction and SAD of collocated block  // set threshhold based on Min of Prediction and SAD of collocated block
2064  // 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
2065    
2066          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
2067                  thresh2 =  512;                  thresh2 =  512;
2068          }          } else {
         else  
         {  
2069  /* 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] */
2070    
2071                  thresh2 = MIN(psad[0],iSAD)*6/5 + 128;                  thresh2 = MIN(psad[0],iSAD)*6/5 + 128;
# Line 1614  Line 2077 
2077    
2078    
2079  // left neighbour, if allowed  // left neighbour, if allowed
2080          if (x != 0)          if (x != 0) {
2081          {                  if (!(MotionFlags & PMV_HALFPEL16)) {
2082                  if (!(MotionFlags & PMV_HALFPEL16 ))                          pmv[1].x = EVEN(pmv[1].x);
                 {       pmv[1].x = EVEN(pmv[1].x);  
2083                          pmv[1].y = EVEN(pmv[1].y);                          pmv[1].y = EVEN(pmv[1].y);
2084                  }                  }
2085                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
2086          }          }
   
2087  // top neighbour, if allowed  // top neighbour, if allowed
2088          if (y != 0)          if (y != 0) {
2089          {                  if (!(MotionFlags & PMV_HALFPEL16)) {
2090                  if (!(MotionFlags & PMV_HALFPEL16 ))                          pmv[2].x = EVEN(pmv[2].x);
                 {       pmv[2].x = EVEN(pmv[2].x);  
2091                          pmv[2].y = EVEN(pmv[2].y);                          pmv[2].y = EVEN(pmv[2].y);
2092                  }                  }
2093                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
2094    
2095  // top right neighbour, if allowed  // top right neighbour, if allowed
2096                  if (x != (iWcount-1))                  if ((uint32_t) x != (iWcount - 1)) {
2097                  {                          if (!(MotionFlags & PMV_HALFPEL16)) {
2098                          if (!(MotionFlags & PMV_HALFPEL16 ))                                  pmv[3].x = EVEN(pmv[3].x);
                         {       pmv[3].x = EVEN(pmv[3].x);  
2099                                  pmv[3].y = EVEN(pmv[3].y);                                  pmv[3].y = EVEN(pmv[3].y);
2100                          }                          }
2101                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);
# Line 1648  Line 2107 
2107  */  */
2108    
2109          if ( (iMinSAD <= thresh2)          if ( (iMinSAD <= thresh2)
2110                  || ( MVequal(*currMV,pMB->mvs[0]) && (iMinSAD <= pMB->sad16) ) )                  || (MVequal(*currMV, prevMB->mvs[0]) &&
2111                  {                          ((uint32_t) iMinSAD <= prevMB->sad16))) {
2112                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2113                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2114                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1658  Line 2117 
2117    
2118  /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/  /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/
2119    
2120          backupMV = pMB->mvs[0];                 // last MV          backupMV = prevMB->mvs[0];      // collocated MV
2121          backupMV.x += (pMB->mvs[0].x - oldMB->mvs[0].x );       // acceleration X          backupMV.x += (prevMB->mvs[0].x - oldMB->mvs[0].x);     // acceleration X
2122          backupMV.y += (pMB->mvs[0].y - oldMB->mvs[0].y );       // acceleration Y          backupMV.y += (prevMB->mvs[0].y - oldMB->mvs[0].y);     // acceleration Y
2123    
2124          CHECK_MV16_CANDIDATE(backupMV.x,backupMV.y);          CHECK_MV16_CANDIDATE(backupMV.x,backupMV.y);
2125    
2126  // left neighbour  // left neighbour
2127          if (x != 0)          if (x != 0)
2128                  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);
2129    
2130  // top neighbour  // top neighbour
2131          if (y != 0)          if (y != 0)
2132                  CHECK_MV16_CANDIDATE((oldMB-iWcount)->mvs[0].x,oldMB->mvs[0].y);                  CHECK_MV16_CANDIDATE((prevMB - iWcount)->mvs[0].x,
2133                                                             (prevMB - iWcount)->mvs[0].y);
2134    
2135  // 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
2136    
2137          if (x != iWcount-1)          if ((uint32_t) x != iWcount - 1)
2138                  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);
2139    
2140  // bottom neighbour, dito  // bottom neighbour, dito
2141          if (y != iHcount-1)          if ((uint32_t) y != iHcount - 1)
2142                  CHECK_MV16_CANDIDATE((pMB+iWcount)->mvs[0].x,oldMB->mvs[0].y);                  CHECK_MV16_CANDIDATE((prevMB + iWcount)->mvs[0].x,
2143                                                             (prevMB + iWcount)->mvs[0].y);
2144    
2145  /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */  /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */
2146          if (iMinSAD <= thresh2)          if (iMinSAD <= thresh2) {
                 {  
2147                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2148                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2149                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1694  Line 2154 
2154    
2155          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
2156    
2157  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */          if (MotionFlags & PMV_USESQUARES8)
2158                    MainSearchPtr = Square16_MainSearch;
         if (MotionFlags & PMV_USESQUARES16)  
                 EPZSMainSearchPtr = Square16_MainSearch;  
2159          else          else
2160                  EPZSMainSearchPtr = Diamond16_MainSearch;           if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2161                    MainSearchPtr = AdvDiamond16_MainSearch;
2162            else
2163                    MainSearchPtr = Diamond16_MainSearch;
2164    
2165          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);  
2166    
2167          if (iSAD < iMinSAD)          iSAD =
2168          {                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2169                                                      currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx,
2170                                                      min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2171    
2172            if (iSAD < iMinSAD) {
2173                  *currMV = newMV;                  *currMV = newMV;
2174                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2175          }          }
2176    
2177    
2178          if (MotionFlags & PMV_EXTSEARCH16)          if (MotionFlags & PMV_EXTSEARCH16) {
         {  
2179  /* 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) */
2180    
2181                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2182                  {                          iSAD =
2183                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2184                                  x, y,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, pmv,
2185                                  pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2186                                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);                                                                    2, iFcode, iQuant, 0);
2187                  }                  }
2188    
2189                  if (iSAD < iMinSAD)                  if (iSAD < iMinSAD) {
                 {  
2190                          *currMV = newMV;                          *currMV = newMV;
2191                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2192                  }                  }
2193    
2194                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2195                  {                          iSAD =
2196                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2197                                  x, y,                                                                    iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy,
2198                          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);  
2199    
2200                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2201                                  *currMV = newMV;                                  *currMV = newMV;
2202                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2203                          }                          }
# Line 1750  Line 2208 
2208    
2209  EPZS16_Terminate_with_Refine:  EPZS16_Terminate_with_Refine:
2210          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
2211                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2212                                  x, y,                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2213                                  currMV, iMinSAD,                                                           iMinSAD, pmv, min_dx, max_dx, min_dy, max_dy,
2214                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                           iFcode, iQuant, iEdgedWidth);
2215    
2216  EPZS16_Terminate_without_Refine:  EPZS16_Terminate_without_Refine:
2217    
2218          *oldMB = *pMB;          *oldMB = *prevMB;
2219    
2220          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - pmv[0].x;
2221          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - pmv[0].y;
# Line 1765  Line 2223 
2223  }  }
2224    
2225    
2226  int32_t EPZSSearch8(  int32_t
2227                                          const uint8_t * const pRef,  EPZSSearch8(const uint8_t * const pRef,
2228                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
2229                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
2230                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
2231                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
2232                                          const int x, const int y,                          const int x,
2233                                          const int start_x, const int start_y,                          const int y,
2234                            const int start_x,
2235                            const int start_y,
2236                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
2237                            const uint32_t iQuant,
2238                            const uint32_t iFcode,
2239                                          const MBParam * const pParam,                                          const MBParam * const pParam,
2240                                          MACROBLOCK * const pMBs,                          const MACROBLOCK * const pMBs,
2241                            const MACROBLOCK * const prevMBs,
2242                                          VECTOR * const currMV,                                          VECTOR * const currMV,
2243                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
2244  {  {
2245          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;  
2246    
2247            const uint32_t iWcount = pParam->mb_width;
2248          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
2249          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
2250          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
# Line 1804  Line 2266 
2266    
2267          const   int32_t iSubBlock = ((y&1)<<1) + (x&1);          const   int32_t iSubBlock = ((y&1)<<1) + (x&1);
2268    
2269          MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;  //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
2270            const MACROBLOCK *const prevMB = prevMBs + (x >> 1) + (y >> 1) * iWcount;
2271    
2272          int32_t bPredEq;          int32_t bPredEq;
2273          int32_t iMinSAD,iSAD=9999;          int32_t iMinSAD,iSAD=9999;
2274    
2275          MainSearch8FuncPtr EPZSMainSearchPtr;          MainSearch8FuncPtr MainSearchPtr;
2276    
2277  /* Get maximum range */  /* Get maximum range */
2278          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,
2279                          x, y, 8, iWidth, iHeight, iFcode);                            iFcode);
2280    
2281  /* 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 */
2282    
2283          if (!(MotionFlags & PMV_HALFPEL8 ))          if (!(MotionFlags & PMV_HALFPEL8)) {
2284          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
2285            max_dx = EVEN(max_dx);            max_dx = EVEN(max_dx);
2286            min_dy = EVEN(min_dy);            min_dy = EVEN(min_dy);
2287            max_dy = EVEN(max_dy);            max_dy = EVEN(max_dy);
2288          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
2289            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2290          bPredEq  = get_pmvdata(pMBs, x>>1, y>>1, iWcount, iSubBlock, pmv, psad);          bPredEq  = get_pmvdata(pMBs, x>>1, y>>1, iWcount, iSubBlock, pmv, psad);
2291    
2292    
# Line 1837  Line 2300 
2300  // Prepare for main loop  // Prepare for main loop
2301    
2302    
2303          if (!(MotionFlags & PMV_HALFPEL8))          if (!(MotionFlags & PMV_HALFPEL8)) {
         {  
2304                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
2305                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
2306          }          }
# Line 1855  Line 2317 
2317  /***************** This is predictor SET A: only median prediction ******************/  /***************** This is predictor SET A: only median prediction ******************/
2318    
2319    
2320          iMinSAD = sad8( cur,          iMinSAD =
2321                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),                  sad8(cur,
2322                  iEdgedWidth);                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
2323          iMinSAD += calc_delta_8(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;                                                  iEdgedWidth), iEdgedWidth);
2324            iMinSAD +=
2325                    calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y,
2326                                             (uint8_t) iFcode, iQuant);
2327    
2328    
2329  // thresh1 is fixed to 256  // thresh1 is fixed to 256
2330          if (iMinSAD < 256/4 )          if (iMinSAD < 256 / 4) {
                 {  
2331                          if (MotionFlags & PMV_QUICKSTOP8)                          if (MotionFlags & PMV_QUICKSTOP8)
2332                                  goto EPZS8_Terminate_without_Refine;                                  goto EPZS8_Terminate_without_Refine;
2333                          if (MotionFlags & PMV_EARLYSTOP8)                          if (MotionFlags & PMV_EARLYSTOP8)
# Line 1872  Line 2336 
2336    
2337  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
2338    
 // previous frame MV  
         CHECK_MV8_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);  
2339    
2340  // MV=(0,0) is often a good choice  // MV=(0,0) is often a good choice
   
2341          CHECK_MV8_ZERO;          CHECK_MV8_ZERO;
2342    
2343    // previous frame MV
2344            CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x, prevMB->mvs[iSubBlock].y);
2345    
2346    // left neighbour, if allowed
2347            if (psad[1] != MV_MAX_ERROR) {
2348                    if (!(MotionFlags & PMV_HALFPEL8)) {
2349                            pmv[1].x = EVEN(pmv[1].x);
2350                            pmv[1].y = EVEN(pmv[1].y);
2351                    }
2352                    CHECK_MV8_CANDIDATE(pmv[1].x, pmv[1].y);
2353            }
2354    // top neighbour, if allowed
2355            if (psad[2] != MV_MAX_ERROR) {
2356                    if (!(MotionFlags & PMV_HALFPEL8)) {
2357                            pmv[2].x = EVEN(pmv[2].x);
2358                            pmv[2].y = EVEN(pmv[2].y);
2359                    }
2360                    CHECK_MV8_CANDIDATE(pmv[2].x, pmv[2].y);
2361    
2362    // top right neighbour, if allowed
2363                    if (psad[3] != MV_MAX_ERROR) {
2364                            if (!(MotionFlags & PMV_HALFPEL8)) {
2365                                    pmv[3].x = EVEN(pmv[3].x);
2366                                    pmv[3].y = EVEN(pmv[3].y);
2367                            }
2368                            CHECK_MV8_CANDIDATE(pmv[3].x, pmv[3].y);
2369                    }
2370            }
2371    
2372    /*  // this bias is zero anyway, at the moment!
2373    
2374            if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) ) // && (iMinSAD <= iQuant * 96)
2375                    iMinSAD -= MV8_00_BIAS;
2376    
2377    */
2378    
2379  /* Terminate if MinSAD <= T_2  /* Terminate if MinSAD <= T_2
2380     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]
2381  */  */
2382    
2383          if (iMinSAD < 512/4)    /* T_2 == 512/4 hardcoded */          if (iMinSAD < 512 / 4) {        /* T_2 == 512/4 hardcoded */
                 {  
2384                          if (MotionFlags & PMV_QUICKSTOP8)                          if (MotionFlags & PMV_QUICKSTOP8)
2385                                  goto EPZS8_Terminate_without_Refine;                                  goto EPZS8_Terminate_without_Refine;
2386                          if (MotionFlags & PMV_EARLYSTOP8)                          if (MotionFlags & PMV_EARLYSTOP8)
2387                                  goto EPZS8_Terminate_with_Refine;                                  goto EPZS8_Terminate_with_Refine;
2388                  }                  }
2389    
2390  /************ (if Diamond Search)  **************/  /************ (Diamond Search)  **************/
2391    
2392          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
2393    
2394          if (!(MotionFlags & PMV_HALFPELDIAMOND8))          if (!(MotionFlags & PMV_HALFPELDIAMOND8))
2395                  iDiamondSize *= 2;                  iDiamondSize *= 2;
2396    
2397  /* 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 */
2398    
2399    // there is no EPZS^2 for inter4v at the moment
2400    
2401  //      if (MotionFlags & PMV_USESQUARES8)  //      if (MotionFlags & PMV_USESQUARES8)
2402  //              EPZSMainSearchPtr = Square8_MainSearch;  //      MainSearchPtr = Square8_MainSearch;
2403  //      else  //      else
                 EPZSMainSearchPtr = Diamond8_MainSearch;  
2404    
2405          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,          if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2406                  x, y,                  MainSearchPtr = AdvDiamond8_MainSearch;
2407                  currMV->x, currMV->y, iMinSAD, &newMV,          else
2408                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,                  MainSearchPtr = Diamond8_MainSearch;
                 iDiamondSize, iFcode, iQuant, 00);  
2409    
2410            iSAD =
2411                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2412                                                      currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx,
2413                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2414                                                      iQuant, 0);
2415    
2416          if (iSAD < iMinSAD)  
2417          {          if (iSAD < iMinSAD) {
2418                  *currMV = newMV;                  *currMV = newMV;
2419                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2420          }          }
2421    
2422          if (MotionFlags & PMV_EXTSEARCH8)          if (MotionFlags & PMV_EXTSEARCH8) {
         {  
2423  /* 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) */
2424    
2425                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2426                  {                          iSAD =
2427                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2428                                  x, y,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, pmv,
2429                          pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2430                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);                                                                    iDiamondSize, iFcode, iQuant, 0);
2431    
2432                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2433                                  *currMV = newMV;                                  *currMV = newMV;
2434                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2435                          }                          }
2436                  }                  }
2437    
2438                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2439                  {                          iSAD =
2440                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2441                                  x, y,                                                                    iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy,
2442                          0, 0, iMinSAD, &newMV,                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
2443                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);                                                                    iQuant, 0);
2444    
2445                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2446                                  *currMV = newMV;                                  *currMV = newMV;
2447                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2448                          }                          }
# Line 1955  Line 2453 
2453    
2454  EPZS8_Terminate_with_Refine:  EPZS8_Terminate_with_Refine:
2455          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
2456                  iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2457                                  x, y,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2458                                  currMV, iMinSAD,                                                          iMinSAD, pmv, min_dx, max_dx, min_dy, max_dy,
2459                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
2460    
2461  EPZS8_Terminate_without_Refine:  EPZS8_Terminate_without_Refine:
2462    
# Line 1967  Line 2465 
2465          return iMinSAD;          return iMinSAD;
2466  }  }
2467    
2468    
2469    
2470    
2471    
2472    /* ***********************************************************
2473            bvop motion estimation
2474    // TODO: need to incorporate prediction here (eg. sad += calc_delta_16)
2475    ***************************************************************/
2476    
2477    
2478    void
2479    MotionEstimationBVOP(MBParam * const pParam,
2480                                             FRAMEINFO * const frame,
2481                                             // forward (past) reference
2482                                             const MACROBLOCK * const f_mbs,
2483                                             const IMAGE * const f_ref,
2484                                             const IMAGE * const f_refH,
2485                                             const IMAGE * const f_refV,
2486                                             const IMAGE * const f_refHV,
2487                                             // backward (future) reference
2488                                             const MACROBLOCK * const b_mbs,
2489                                             const IMAGE * const b_ref,
2490                                             const IMAGE * const b_refH,
2491                                             const IMAGE * const b_refV,
2492                                             const IMAGE * const b_refHV)
2493    {
2494            const uint32_t mb_width = pParam->mb_width;
2495            const uint32_t mb_height = pParam->mb_height;
2496            const int32_t edged_width = pParam->edged_width;
2497    
2498            uint32_t i, j;
2499    
2500            int32_t f_sad16;
2501            int32_t b_sad16;
2502            int32_t i_sad16;
2503            int32_t d_sad16;
2504            int32_t best_sad;
2505    
2506            VECTOR pmv_dontcare;
2507    
2508            // note: i==horizontal, j==vertical
2509            for (j = 0; j < mb_height; j++) {
2510                    for (i = 0; i < mb_width; i++) {
2511                            MACROBLOCK *mb = &frame->mbs[i + j * mb_width];
2512                            const MACROBLOCK *f_mb = &f_mbs[i + j * mb_width];
2513                            const MACROBLOCK *b_mb = &b_mbs[i + j * mb_width];
2514    
2515                            if (b_mb->mode == MODE_INTER && b_mb->cbp == 0 &&
2516                                    b_mb->mvs[0].x == 0 && b_mb->mvs[0].y == 0) {
2517                                    mb->mode = MODE_NOT_CODED;
2518                                    mb->mvs[0].x = 0;
2519                                    mb->mvs[0].y = 0;
2520                                    mb->b_mvs[0].x = 0;
2521                                    mb->b_mvs[0].y = 0;
2522                                    continue;
2523                            }
2524    
2525                            // forward search
2526                            f_sad16 =
2527                                    SEARCH16(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
2528                                                     &frame->image, i, j, frame->motion_flags,
2529                                                     frame->quant, frame->fcode, pParam, f_mbs,
2530                                                     f_mbs /* todo */ ,
2531                                                     &mb->mvs[0], &pmv_dontcare);   // ignore pmv
2532    
2533                            // backward search
2534                            b_sad16 = SEARCH16(b_ref->y, b_refH->y, b_refV->y, b_refHV->y, &frame->image, i, j, frame->motion_flags, frame->quant, frame->bcode, pParam, b_mbs, b_mbs,      /* todo */
2535                                                               &mb->b_mvs[0], &pmv_dontcare);       // ignore pmv
2536    
2537                            // interpolate search (simple, but effective)
2538                            i_sad16 =
2539                                    sad16bi_c(frame->image.y + i * 16 + j * 16 * edged_width,
2540                                                      get_ref(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
2541                                                                      i, j, 16, mb->mvs[0].x, mb->mvs[0].y,
2542                                                                      edged_width), get_ref(b_ref->y, b_refH->y,
2543                                                                                                                    b_refV->y, b_refHV->y,
2544                                                                                                                    i, j, 16,
2545                                                                                                                    mb->b_mvs[0].x,
2546                                                                                                                    mb->b_mvs[0].x,
2547                                                                                                                    edged_width),
2548                                                      edged_width);
2549    
2550                            // TODO: direct search
2551                            // predictor + range of [-32,32]
2552                            d_sad16 = 65535;
2553    
2554    
2555                            if (f_sad16 < b_sad16) {
2556                                    best_sad = f_sad16;
2557                                    mb->mode = MODE_FORWARD;
2558                            } else {
2559                                    best_sad = b_sad16;
2560                                    mb->mode = MODE_BACKWARD;
2561                            }
2562    
2563                            if (i_sad16 < best_sad) {
2564                                    best_sad = i_sad16;
2565                                    mb->mode = MODE_INTERPOLATE;
2566                            }
2567    
2568                            if (d_sad16 < best_sad) {
2569                                    best_sad = d_sad16;
2570                                    mb->mode = MODE_DIRECT;
2571                            }
2572    
2573                    }
2574            }
2575    }

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

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