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

Diff of /trunk/xvidcore/src/motion/motion_est.c

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

revision 78, Thu Mar 28 20:57:25 2002 UTC revision 234, Sun Jun 23 03:58:32 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
10     *             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
12   *             PMVFast_Refine to support multiple searches with different start points   *             PMVFast_Refine to support multiple searches with different start points
13   *  07.01.2002 uv-block-based interpolation   *  07.01.2002 uv-block-based interpolation
# Line 31  Line 37 
37    
38  #include <assert.h>  #include <assert.h>
39  #include <stdio.h>  #include <stdio.h>
40    #include <stdlib.h>
41    
42  #include "../encoder.h"  #include "../encoder.h"
43  #include "../utils/mbfunctions.h"  #include "../utils/mbfunctions.h"
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 46  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 60  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    int32_t PMVfastSearch16(const uint8_t * const pRef,
83                                                    const uint8_t * const pRefH,
84                                                    const uint8_t * const pRefV,
85                                                    const uint8_t * const pRefHV,
86                                                    const IMAGE * const pCur,
87                                                    const int x,
88                                                    const int y,
89                                                    const uint32_t MotionFlags,
90                                                    const uint32_t iQuant,
91                                                    const uint32_t iFcode,
92                                                    const MBParam * const pParam,
93                                                    const MACROBLOCK * const pMBs,
94                                                    const MACROBLOCK * const prevMBs,
95                                                    VECTOR * const currMV,
96                                                    VECTOR * const currPMV);
97    
98  #define MIN(X, Y) ((X)<(Y)?(X):(Y))  int32_t EPZSSearch16(const uint8_t * const pRef,
99  #define MAX(X, Y) ((X)>(Y)?(X):(Y))                                           const uint8_t * const pRefH,
100  #define ABS(X)    (((X)>0)?(X):-(X))                                           const uint8_t * const pRefV,
101  #define SIGN(X)   (((X)>0)?1:-1)                                           const uint8_t * const pRefHV,
102                                             const IMAGE * const pCur,
103                                             const int x,
104                                             const int y,
105                                             const uint32_t MotionFlags,
106                                             const uint32_t iQuant,
107                                             const uint32_t iFcode,
108                                             const MBParam * const pParam,
109                                             const MACROBLOCK * const pMBs,
110                                             const MACROBLOCK * const prevMBs,
111                                             VECTOR * const currMV,
112                                             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 uint32_t iQuality,                                             const int start_x,
123          MBParam * const pParam,                                             const int start_y,
124          MACROBLOCK * const pMBs,                                             const uint32_t MotionFlags,
125                                               const uint32_t iQuant,
126                                               const uint32_t iFcode,
127                                               const MBParam * const pParam,
128                                               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 PMVfastSearch16(  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 uint32_t iQuality,                                          const int y,
140          MBParam * const pParam,                                          const int start_x,
141          MACROBLOCK * const pMBs,                                          const int start_y,
142                                            const uint32_t MotionFlags,
143                                            const uint32_t iQuant,
144                                            const uint32_t iFcode,
145                                            const MBParam * const pParam,
146                                            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) (const uint8_t * const pRef,
153                                                                       const uint8_t * const pRefH,
154                                                                       const uint8_t * const pRefV,
155                                                                       const uint8_t * const pRefHV,
156                                                                       const uint8_t * const cur,
157                                                                       const int x,
158                                                                       const int y,
159                                                                       int32_t startx,
160                                                                       int32_t starty,
161                                                                       int32_t iMinSAD,
162                                                                       VECTOR * const currMV,
163                                                                       const VECTOR * const pmv,
164                                                                       const int32_t min_dx,
165                                                                       const int32_t max_dx,
166                                                                       const int32_t min_dy,
167                                                                       const int32_t max_dy,
168                                                                       const int32_t iEdgedWidth,
169                                                                       const int32_t iDiamondSize,
170                                                                       const int32_t iFcode,
171                                                                       const int32_t iQuant,
172                                                                       int iFound);
173    
174    typedef MainSearch16Func *MainSearch16FuncPtr;
175    
 /*  
  * diamond search stuff  
  * keep the the sequence in circular order (so optimization works)  
  */  
176    
177  typedef struct  typedef int32_t(MainSearch8Func) (const uint8_t * const pRef,
178  {                                                                    const uint8_t * const pRefH,
179          int32_t dx;                                                                    const uint8_t * const pRefV,
180          int32_t dy;                                                                    const uint8_t * const pRefHV,
181  }                                                                    const uint8_t * const cur,
182  DPOINT;                                                                    const int x,
183                                                                      const int y,
184                                                                      int32_t startx,
185                                                                      int32_t starty,
186                                                                      int32_t iMinSAD,
187                                                                      VECTOR * const currMV,
188                                                                      const VECTOR * const pmv,
189                                                                      const int32_t min_dx,
190                                                                      const int32_t max_dx,
191                                                                      const int32_t min_dy,
192                                                                      const int32_t max_dy,
193                                                                      const int32_t iEdgedWidth,
194                                                                      const int32_t iDiamondSize,
195                                                                      const int32_t iFcode,
196                                                                      const int32_t iQuant,
197                                                                      int iFound);
198    
199    typedef MainSearch8Func *MainSearch8FuncPtr;
200    
201  static const DPOINT diamond_small[4] =  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          {0, 1}, {1, 0}, {0, -1}, {-1, 0}                  (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    
 static const DPOINT diamond_large[8] =  
 {  
         {0, 2}, {1, 1}, {2, 0}, {1, -1}, {0, -2}, {-1, -1}, {-2, 0}, {-1, 1}  
 };  
219    
220    
221  // mv.length table  // mv.length table
# Line 134  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 142  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 160  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          return NEIGH_TEND_16X16 * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));                            const int32_t dy,
260  }                            const uint32_t iFcode,
261                              const uint32_t iQuant)
262  static __inline uint32_t calc_delta_8(const int32_t dx, const int32_t dy, const uint32_t iFcode)  {
263            return NEIGH_TEND_16X16 * lambda_vec16[iQuant] * (mv_bits(dx, iFcode) +
264  {                                                                                                            mv_bits(dy, iFcode));
265      return NEIGH_TEND_8X8 * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));  }
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  /* calculate the min/max range (in halfpixels)                           const uint32_t iQuant)
         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)  
272  {  {
273            return NEIGH_TEND_8X8 * lambda_vec8[iQuant] * (mv_bits(dx, iFcode) +
274          const int search_range = 32 << (fcode - 1);                                                                                                     mv_bits(dy, iFcode));
         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;  
         }  
   
275  }  }
276    
277    
 /* 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)  
 {  
278    
         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;  
         }  
279    
 }  
280    
281  #ifndef SEARCH16  #ifndef SEARCH16
282  #define SEARCH16        PMVfastSearch16  #define SEARCH16        PMVfastSearch16
283    //#define SEARCH16  FullSearch16
284    //#define SEARCH16  EPZSSearch16
285  #endif  #endif
286    
287  #ifndef SEARCH8  #ifndef SEARCH8
288  #define SEARCH8         PMVfastSearch8  #define SEARCH8         PMVfastSearch8
289    //#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 320  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) { \
428        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);\
430        if (iSAD < iMinSAD) \
431        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
432    }
433    
434  #define CHECK_MV16_CANDIDATE(X,Y) { \  #define CHECK_MV16_CANDIDATE(X,Y) { \
435    if ( ((X) <= max_dx) && ((X) >= min_dx) \    if ( ((X) <= max_dx) && ((X) >= min_dx) \
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 408  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 418  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 426  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  }  }
471    
472    #define NOCHECK_MV8_CANDIDATE(X,Y) \
473      { \
474        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);\
476        if (iSAD < iMinSAD) \
477        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
478    }
479    
480  #define CHECK_MV8_CANDIDATE(X,Y) { \  #define CHECK_MV8_CANDIDATE(X,Y) { \
481    if ( ((X) <= max_dx) && ((X) >= min_dx) \    if ( ((X) <= max_dx) && ((X) >= min_dx) \
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 447  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 457  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 472  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 501  Line 548 
548  }  }
549  */  */
550    
551  int32_t PMVfastSearch16_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 525  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 536  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 PMVfastSearch16_Refine(  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          VECTOR * const currMV,                                          const int y,
622                                            int32_t startx,
623                                            int32_t starty,
624          int32_t iMinSAD,          int32_t iMinSAD,
625                                            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,
632                                            const int32_t iDiamondSize,
633          const int32_t iFcode,          const int32_t iFcode,
634          const int32_t iQuant,          const int32_t iQuant,
635          const int32_t iEdgedWidth)                                          int iFound)
636  {  {
637  /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */  /* Do a square search around given starting point, return SAD of best */
638    
639            int32_t iDirection = 0;
640          int32_t iSAD;          int32_t iSAD;
641          VECTOR backupMV = *currMV;          VECTOR backupMV;
642    
643          CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y-1);          backupMV.x = startx;
644          CHECK_MV16_CANDIDATE(backupMV.x  ,backupMV.y-1);          backupMV.y = starty;
645          CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y-1);  
646          CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y);  /* It's one search with full square pattern, and new parts for all following diamonds */
         CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y);  
         CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y+1);  
         CHECK_MV16_CANDIDATE(backupMV.x  ,backupMV.y+1);  
         CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y+1);  
647    
648    /*   new direction are extra, so 1-4 is normal diamond
649          537
650          1*2
651          648
652    */
653    
654            CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y, 1);
655            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y, 2);
656            CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);
657            CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);
658    
659            CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
660                                                             backupMV.y - iDiamondSize, 5);
661            CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
662                                                             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)
670                    while (!iFound) {
671                            iFound = 1;
672                            backupMV = *currMV;
673    
674                            switch (iDirection) {
675                            case 1:
676                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
677                                                                                       backupMV.y, 1);
678                                    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;
683                            case 2:
684                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y,
685                                                                                     2);
686                                    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;
691    
692                            case 3:
693                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize,
694                                                                                     4);
695                                    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;
700    
701                            case 4:
702                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize,
703                                                                                     3);
704                                    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;
709    
710                            case 5:
711                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y,
712                                                                                     1);
713                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize,
714                                                                                     3);
715                                    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;
722    
723                            case 6:
724                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y,
725                                                                                     2);
726                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize,
727                                                                                     3);
728    
729                                    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;
737    
738                            case 7:
739                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
740                                                                                       backupMV.y, 1);
741                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize,
742                                                                                     4);
743                                    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;
750    
751                            case 8:
752                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y,
753                                                                                     2);
754                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize,
755                                                                                     4);
756                                    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;
763                            default:
764                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y,
765                                                                                     1);
766                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y,
767                                                                                     2);
768                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize,
769                                                                                     3);
770                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize,
771                                                                                     4);
772    
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;
782                            }
783            } else {
784                    currMV->x = startx;
785                    currMV->y = starty;
786            }
787          return iMinSAD;          return iMinSAD;
788  }  }
789    
 #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)  
790    
791  int32_t PMVfastSearch16(  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 IMAGE * const pCur,                                    const uint8_t * const cur,
797          const int x, const int y,                                    const int x,
798          const uint32_t MotionFlags,                                    const int y,
799          MBParam * const pParam,                                    int32_t startx,
800          MACROBLOCK * const pMBs,                                    int32_t starty,
801                                      int32_t iMinSAD,
802          VECTOR * const currMV,          VECTOR * const currMV,
803          VECTOR * const currPMV)                                    const VECTOR * const pmv,
804                                      const int32_t min_dx,
805                                      const int32_t max_dx,
806                                      const int32_t min_dy,
807                                      const int32_t max_dy,
808                                      const int32_t iEdgedWidth,
809                                      const int32_t iDiamondSize,
810                                      const int32_t iFcode,
811                                      const int32_t iQuant,
812                                      int iFound)
813  {  {
814          const uint32_t iWcount = pParam->mb_width;          int32_t iSAD;
815          const int32_t iFcode = pParam->fixed_code;          int32_t dx, dy;
816          const int32_t iQuant = pParam->quant;          VECTOR backupMV;
         const int32_t iWidth = pParam->width;  
         const int32_t iHeight = pParam->height;  
         const int32_t iEdgedWidth = pParam->edged_width;  
   
         const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;  
   
         int32_t iDiamondSize;  
817    
818          int32_t min_dx;          backupMV.x = startx;
819          int32_t max_dx;          backupMV.y = starty;
         int32_t min_dy;  
         int32_t max_dy;  
820    
821          int32_t iFound;          for (dx = min_dx; dx <= max_dx; dx += iDiamondSize)
822                    for (dy = min_dy; dy <= max_dy; dy += iDiamondSize)
823                            NOCHECK_MV16_CANDIDATE(dx, dy);
824    
825          VECTOR newMV;          return iMinSAD;
826          VECTOR backupMV;        /* just for PMVFAST */  }
827    
828          VECTOR pmv[4];  int32_t
829          int32_t psad[4];  AdvDiamond16_MainSearch(const uint8_t * const pRef,
830                                                    const uint8_t * const pRefH,
831                                                    const uint8_t * const pRefV,
832                                                    const uint8_t * const pRefHV,
833                                                    const uint8_t * const cur,
834                                                    const int x,
835                                                    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          MACROBLOCK * const pMB = pMBs + x + y * iWcount;          int32_t iSAD;
853    
854          static int32_t threshA,threshB;  /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
         int32_t bPredEq;  
         int32_t iMinSAD,iSAD;  
855    
856  /* Get maximum range */          if (iDirection) {
857          get_range(&min_dx, &max_dx, &min_dy, &max_dy,                  CHECK_MV16_CANDIDATE(startx - iDiamondSize, starty);
858                    x, y, 16, iWidth, iHeight, iFcode);                  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  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */  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          if (!(MotionFlags & PMV_HALFPEL16 ))          int32_t iSAD;
         { min_dx = EVEN(min_dx);  
         max_dx = EVEN(max_dx);  
         min_dy = EVEN(min_dy);  
         max_dy = EVEN(max_dy);  
         }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */  
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    
         bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);  
1142    
1143          if ((x==0) && (y==0) )  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,
1154                                     VECTOR * const currMV,
1155                                     const VECTOR * const pmv,
1156                                     const int32_t min_dx,
1157                                     const int32_t max_dx,
1158                                     const int32_t min_dy,
1159                                     const int32_t max_dy,
1160                                     const int32_t iEdgedWidth,
1161                                     const int32_t iDiamondSize,
1162                                     const int32_t iFcode,
1163                                     const int32_t iQuant,
1164                                     int iFound)
1165          {          {
1166                  threshA =  512;          int32_t iSAD;
1167                  threshB = 1024;          int32_t dx, dy;
1168            VECTOR backupMV;
1169    
1170            backupMV.x = startx;
1171            backupMV.y = starty;
1172    
1173            for (dx = min_dx; dx <= max_dx; dx += iDiamondSize)
1174                    for (dy = min_dy; dy <= max_dy; dy += iDiamondSize)
1175                            NOCHECK_MV8_CANDIDATE(dx, dy);
1176    
1177            return iMinSAD;
1178          }          }
1179          else  
1180    
1181    
1182    int32_t
1183    Halfpel16_Refine(const uint8_t * const pRef,
1184                                     const uint8_t * const pRefH,
1185                                     const uint8_t * const pRefV,
1186                                     const uint8_t * const pRefHV,
1187                                     const uint8_t * const cur,
1188                                     const int x,
1189                                     const int y,
1190                                     VECTOR * const currMV,
1191                                     int32_t iMinSAD,
1192                                     const VECTOR * const pmv,
1193                                     const int32_t min_dx,
1194                                     const int32_t max_dx,
1195                                     const int32_t min_dy,
1196                                     const int32_t max_dy,
1197                                     const int32_t iFcode,
1198                                     const int32_t iQuant,
1199                                     const int32_t iEdgedWidth)
1200          {          {
1201                  threshA = psad[0];  /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */
1202                  threshB = threshA+256;  
1203                  if (threshA< 512) threshA =  512;          int32_t iSAD;
1204                  if (threshA>1024) threshA = 1024;          VECTOR backupMV = *currMV;
1205                  if (threshB>1792) threshB = 1792;  
1206            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y - 1);
1207            CHECK_MV16_CANDIDATE(backupMV.x, backupMV.y - 1);
1208            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y - 1);
1209            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y);
1210            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y);
1211            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y + 1);
1212            CHECK_MV16_CANDIDATE(backupMV.x, backupMV.y + 1);
1213            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y + 1);
1214    
1215            return iMinSAD;
1216          }          }
1217    
1218          iFound=0;  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)
1219    
 /* 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  
 */  
1220    
1221          if ((bPredEq) && (MVequal(pmv[0],pMB->mvs[0]) ) )  int32_t
1222                  iFound=2;  PMVfastSearch16(const uint8_t * const pRef,
1223                                    const uint8_t * const pRefH,
1224                                    const uint8_t * const pRefV,
1225                                    const uint8_t * const pRefHV,
1226                                    const IMAGE * const pCur,
1227                                    const int x,
1228                                    const int y,
1229                                    const uint32_t MotionFlags,
1230                                    const uint32_t iQuant,
1231                                    const uint32_t iFcode,
1232                                    const MBParam * const pParam,
1233                                    const MACROBLOCK * const pMBs,
1234                                    const MACROBLOCK * const prevMBs,
1235                                    VECTOR * const currMV,
1236                                    VECTOR * const currPMV)
1237    {
1238            const uint32_t iWcount = pParam->mb_width;
1239            const int32_t iWidth = pParam->width;
1240            const int32_t iHeight = pParam->height;
1241            const int32_t iEdgedWidth = pParam->edged_width;
1242    
1243  /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.          const uint8_t *cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;
    Otherwise select large Diamond Search.  
 */  
1244    
1245          if ( (pmv[0].x != 0) || (pmv[0].y != 0) || (threshB<1536) || (bPredEq) )          int32_t iDiamondSize;
                 iDiamondSize=1; // halfpel!  
         else  
                 iDiamondSize=2; // halfpel!  
1246    
1247          if (!(MotionFlags & PMV_HALFPELDIAMOND16) )          int32_t min_dx;
1248                  iDiamondSize*=2;          int32_t max_dx;
1249            int32_t min_dy;
1250            int32_t max_dy;
1251    
1252            int32_t iFound;
1253    
1254            VECTOR newMV;
1255            VECTOR backupMV;                        /* just for PMVFAST */
1256    
1257            VECTOR pmv[4];
1258            int32_t psad[4];
1259    
1260            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;
1266            int32_t bPredEq;
1267            int32_t iMinSAD, iSAD;
1268    
1269    /* Get maximum range */
1270            get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight,
1271                              iFcode);
1272    
1273    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
1274    
1275            if (!(MotionFlags & PMV_HALFPEL16)) {
1276                    min_dx = EVEN(min_dx);
1277                    max_dx = EVEN(max_dx);
1278                    min_dy = EVEN(min_dy);
1279                    max_dy = EVEN(max_dy);
1280            }
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);
1284    
1285            if ((x == 0) && (y == 0)) {
1286                    threshA = 512;
1287                    threshB = 1024;
1288    
1289            } else {
1290                    threshA = psad[0];
1291                    threshB = threshA + 256;
1292                    if (threshA < 512)
1293                            threshA = 512;
1294                    if (threshA > 1024)
1295                            threshA = 1024;
1296                    if (threshB > 1792)
1297                            threshB = 1792;
1298            }
1299    
1300            iFound = 0;
1301    
1302  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
1303     MinSAD=SAD     MinSAD=SAD
# Line 696  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 step10b;                          goto PMVfast16_Terminate_without_Refine;
1350                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
1351                          goto step10;                          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 step10b;                          goto PMVfast16_Terminate_without_Refine;
1445                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
1446                          goto step10;                          goto PMVfast16_Terminate_with_Refine;
1447          }          }
1448    
1449    
# Line 804  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 = PMVfastSearch16_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 = PMVfastSearch16_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 = PMVfastSearch16_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 853  Line 1512 
1512     Step 10:  The motion vector is chosen according to the block corresponding to MinSAD.     Step 10:  The motion vector is chosen according to the block corresponding to MinSAD.
1513  */  */
1514    
1515   step10:    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 = PMVfastSearch16_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   step10b:    PMVfast16_Terminate_without_Refine:
1523          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - pmv[0].x;
1524          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - pmv[0].y;
1525          return iMinSAD;          return iMinSAD;
# Line 871  Line 1530 
1530    
1531    
1532    
1533  int32_t PMVfastSearch8_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 895  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 906  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 PMVfastSearch8_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 964  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          MBParam * const pParam,                             const uint32_t iQuant,
1647          MACROBLOCK * const pMBs,                             const uint32_t iFcode,
1648                               const MBParam * const pParam,
1649                               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 999  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    
1721  /* Step 2: Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion  /* Step 4: Calculate SAD around the Median prediction.
1722       MinSAD=SAD
1723       If Motion Vector equal to Previous frame motion vector
1724       and MinSAD<PrevFrmSAD goto Step 10.
1725       If SAD<=256 goto Step 10.
1726    */
1727    
1728    
1729    // Prepare for main loop
1730    
1731    //  if (MotionFlags & PMV_USESQUARES8)
1732    //      MainSearchPtr = Square8_MainSearch;
1733    //  else
1734    
1735            if (MotionFlags & PMV_ADVANCEDDIAMOND8)
1736                    MainSearchPtr = AdvDiamond8_MainSearch;
1737            else
1738                    MainSearchPtr = Diamond8_MainSearch;
1739    
1740    
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)
1755                            goto PMVfast8_Terminate_without_Refine;
1756                    if (MotionFlags & PMV_EARLYSTOP16)
1757                            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.     vector of the median.
1762     If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2     If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
1763  */  */
1764    
1765          if ((bPredEq) && (MVequal(pmv[0],pMB->mvs[iSubBlock]) ) )          if ((bPredEq) && (MVequal(pmv[0], prevMB->mvs[iSubBlock])))
1766                  iFound=2;                  iFound=2;
1767    
1768  /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.  /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
1769     Otherwise select large Diamond Search.     Otherwise select large Diamond Search.
1770  */  */
1771    
1772          if ( (pmv[0].x != 0) || (pmv[0].y != 0) || (threshB<1536/4) || (bPredEq) )          if ((!MVzero(pmv[0])) || (threshB < 1536 / 4) || (bPredEq))
1773                  iDiamondSize=1; // 1 halfpel!                  iDiamondSize=1; // 1 halfpel!
1774          else          else
1775                  iDiamondSize=2; // 2 halfpel = 1 full pixel!                  iDiamondSize=2; // 2 halfpel = 1 full pixel!
# Line 1061  Line 1777 
1777          if (!(MotionFlags & PMV_HALFPELDIAMOND8) )          if (!(MotionFlags & PMV_HALFPELDIAMOND8) )
1778                  iDiamondSize*=2;                  iDiamondSize*=2;
1779    
 /* Step 4: Calculate SAD around the Median prediction.  
    MinSAD=SAD  
    If Motion Vector equal to Previous frame motion vector  
    and MinSAD<PrevFrmSAD goto Step 10.  
    If SAD<=256 goto Step 10.  
 */  
   
   
 // Prepare for main loop  
   
         currMV->x=start_x;              /* start with mv16 */  
         currMV->y=start_y;  
   
         iMinSAD = sad8( cur,  
                         get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),  
                         iEdgedWidth);  
         iMinSAD += calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y, (uint8_t)iFcode) * iQuant;  
   
         if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,pMB->mvs[iSubBlock])) && (iMinSAD < pMB->sad8[iSubBlock]) ) )  
         {  
                 if (MotionFlags & PMV_QUICKSTOP8)  
                         goto step10_8b;  
                 if (MotionFlags & PMV_EARLYSTOP8)  
                         goto step10_8;  
         }  
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                  if (MotionFlags & PMV_QUICKSTOP8)                   ((uint32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
1867                          goto step10_8b;                  if (MotionFlags & PMV_QUICKSTOP16)
1868                  if (MotionFlags & PMV_EARLYSTOP8)                          goto PMVfast8_Terminate_without_Refine;
1869                          goto step10_8;                  if (MotionFlags & PMV_EARLYSTOP16)
1870                            goto PMVfast8_Terminate_with_Refine;
1871          }          }
1872    
1873  /************ (Diamond Search)  **************/  /************ (Diamond Search)  **************/
# Line 1158  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 = PMVfastSearch8_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 = PMVfastSearch16_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 = PMVfastSearch16_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 1204  Line 1928 
1928     By performing an optional local half-pixel search, we can refine this result even further.     By performing an optional local half-pixel search, we can refine this result even further.
1929  */  */
1930    
1931   step10_8:    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 = PMVfastSearch8_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:
1940            currPMV->x = currMV->x - pmv[0].x;
1941            currPMV->y = currMV->y - pmv[0].y;
1942    
1943            return iMinSAD;
1944    }
1945    
1946    int32_t
1947    EPZSSearch16(const uint8_t * const pRef,
1948                             const uint8_t * const pRefH,
1949                             const uint8_t * const pRefV,
1950                             const uint8_t * const pRefHV,
1951                             const IMAGE * const pCur,
1952                             const int x,
1953                             const int y,
1954                             const uint32_t MotionFlags,
1955                             const uint32_t iQuant,
1956                             const uint32_t iFcode,
1957                             const MBParam * const pParam,
1958                             const MACROBLOCK * const pMBs,
1959                             const MACROBLOCK * const prevMBs,
1960                             VECTOR * const currMV,
1961                             VECTOR * const currPMV)
1962    {
1963            const uint32_t iWcount = pParam->mb_width;
1964            const uint32_t iHcount = pParam->mb_height;
1965    
1966            const int32_t iWidth = pParam->width;
1967            const int32_t iHeight = pParam->height;
1968            const int32_t iEdgedWidth = pParam->edged_width;
1969    
1970            const uint8_t *cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;
1971    
1972            int32_t min_dx;
1973            int32_t max_dx;
1974            int32_t min_dy;
1975            int32_t max_dy;
1976    
1977            VECTOR newMV;
1978            VECTOR backupMV;
1979    
1980            VECTOR pmv[4];
1981            int32_t psad[8];
1982    
1983            static MACROBLOCK *oldMBs = NULL;
1984    
1985    //  const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
1986            const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
1987            MACROBLOCK *oldMB = NULL;
1988    
1989            static int32_t thresh2;
1990            int32_t bPredEq;
1991            int32_t iMinSAD, iSAD = 9999;
1992    
1993            MainSearch16FuncPtr MainSearchPtr;
1994    
1995            if (oldMBs == NULL) {
1996                    oldMBs = (MACROBLOCK *) calloc(iWcount * iHcount, sizeof(MACROBLOCK));
1997    //      fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));
1998            }
1999            oldMB = oldMBs + x + y * iWcount;
2000    
2001    /* Get maximum range */
2002            get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight,
2003                              iFcode);
2004    
2005            if (!(MotionFlags & PMV_HALFPEL16)) {
2006                    min_dx = EVEN(min_dx);
2007                    max_dx = EVEN(max_dx);
2008                    min_dy = EVEN(min_dy);
2009                    max_dy = EVEN(max_dy);
2010            }
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);
2013    
2014    /* Step 4: Calculate SAD around the Median prediction.
2015            MinSAD=SAD
2016            If Motion Vector equal to Previous frame motion vector
2017                    and MinSAD<PrevFrmSAD goto Step 10.
2018            If SAD<=256 goto Step 10.
2019    */
2020    
2021    // Prepare for main loop
2022    
2023            *currMV = pmv[0];                       /* current best := median prediction */
2024            if (!(MotionFlags & PMV_HALFPEL16)) {
2025                    currMV->x = EVEN(currMV->x);
2026                    currMV->y = EVEN(currMV->y);
2027            }
2028    
2029            if (currMV->x > max_dx)
2030                    currMV->x = max_dx;
2031            if (currMV->x < min_dx)
2032                    currMV->x = min_dx;
2033            if (currMV->y > max_dy)
2034                    currMV->y = max_dy;
2035            if (currMV->y < min_dy)
2036                    currMV->y = min_dy;
2037    
2038    /***************** This is predictor SET A: only median prediction ******************/
2039    
2040            iMinSAD =
2041                    sad16(cur,
2042                              get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
2043                                                     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
2049            if ((iMinSAD < 256) ||
2050                    ((MVequal(*currMV, prevMB->mvs[0])) &&
2051                     ((uint32_t) iMinSAD < prevMB->sad16))) {
2052                    if (MotionFlags & PMV_QUICKSTOP16)
2053                            goto EPZS16_Terminate_without_Refine;
2054                    if (MotionFlags & PMV_EARLYSTOP16)
2055                            goto EPZS16_Terminate_with_Refine;
2056            }
2057    
2058    /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
2059    
2060    // previous frame MV
2061            CHECK_MV16_CANDIDATE(prevMB->mvs[0].x, prevMB->mvs[0].y);
2062    
2063   step10_8b:  // 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
2065    
2066            if ((x == 0) && (y == 0)) {
2067                    thresh2 = 512;
2068            } else {
2069    /* 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;
2072            }
2073    
2074    // MV=(0,0) is often a good choice
2075    
2076            CHECK_MV16_ZERO;
2077    
2078    
2079    // left neighbour, if allowed
2080            if (x != 0) {
2081                    if (!(MotionFlags & PMV_HALFPEL16)) {
2082                            pmv[1].x = EVEN(pmv[1].x);
2083                            pmv[1].y = EVEN(pmv[1].y);
2084                    }
2085                    CHECK_MV16_CANDIDATE(pmv[1].x, pmv[1].y);
2086            }
2087    // top neighbour, if allowed
2088            if (y != 0) {
2089                    if (!(MotionFlags & PMV_HALFPEL16)) {
2090                            pmv[2].x = EVEN(pmv[2].x);
2091                            pmv[2].y = EVEN(pmv[2].y);
2092                    }
2093                    CHECK_MV16_CANDIDATE(pmv[2].x, pmv[2].y);
2094    
2095    // top right neighbour, if allowed
2096                    if ((uint32_t) x != (iWcount - 1)) {
2097                            if (!(MotionFlags & PMV_HALFPEL16)) {
2098                                    pmv[3].x = EVEN(pmv[3].x);
2099                                    pmv[3].y = EVEN(pmv[3].y);
2100                            }
2101                            CHECK_MV16_CANDIDATE(pmv[3].x, pmv[3].y);
2102                    }
2103            }
2104    
2105    /* Terminate if MinSAD <= T_2
2106       Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
2107    */
2108    
2109            if ((iMinSAD <= thresh2)
2110                    || (MVequal(*currMV, prevMB->mvs[0]) &&
2111                            ((uint32_t) iMinSAD <= prevMB->sad16))) {
2112                    if (MotionFlags & PMV_QUICKSTOP16)
2113                            goto EPZS16_Terminate_without_Refine;
2114                    if (MotionFlags & PMV_EARLYSTOP16)
2115                            goto EPZS16_Terminate_with_Refine;
2116            }
2117    
2118    /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/
2119    
2120            backupMV = prevMB->mvs[0];      // collocated MV
2121            backupMV.x += (prevMB->mvs[0].x - oldMB->mvs[0].x);     // acceleration X
2122            backupMV.y += (prevMB->mvs[0].y - oldMB->mvs[0].y);     // acceleration Y
2123    
2124            CHECK_MV16_CANDIDATE(backupMV.x, backupMV.y);
2125    
2126    // left neighbour
2127            if (x != 0)
2128                    CHECK_MV16_CANDIDATE((prevMB - 1)->mvs[0].x, (prevMB - 1)->mvs[0].y);
2129    
2130    // top neighbour
2131            if (y != 0)
2132                    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
2136    
2137            if ((uint32_t) x != iWcount - 1)
2138                    CHECK_MV16_CANDIDATE((prevMB + 1)->mvs[0].x, (prevMB + 1)->mvs[0].y);
2139    
2140    // bottom neighbour, dito
2141            if ((uint32_t) y != iHcount - 1)
2142                    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)  */
2146            if (iMinSAD <= thresh2) {
2147                    if (MotionFlags & PMV_QUICKSTOP16)
2148                            goto EPZS16_Terminate_without_Refine;
2149                    if (MotionFlags & PMV_EARLYSTOP16)
2150                            goto EPZS16_Terminate_with_Refine;
2151            }
2152    
2153    /************ (if Diamond Search)  **************/
2154    
2155            backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
2156    
2157            if (MotionFlags & PMV_USESQUARES8)
2158                    MainSearchPtr = Square16_MainSearch;
2159            else
2160             if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2161                    MainSearchPtr = AdvDiamond16_MainSearch;
2162            else
2163                    MainSearchPtr = Diamond16_MainSearch;
2164    
2165    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
2166    
2167            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;
2174                    iMinSAD = iSAD;
2175            }
2176    
2177    
2178            if (MotionFlags & PMV_EXTSEARCH16) {
2179    /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
2180    
2181                    if (!(MVequal(pmv[0], backupMV))) {
2182                            iSAD =
2183                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2184                                                                      pmv[0].x, pmv[0].y, iMinSAD, &newMV, pmv,
2185                                                                      min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2186                                                                      2, iFcode, iQuant, 0);
2187                    }
2188    
2189                    if (iSAD < iMinSAD) {
2190                            *currMV = newMV;
2191                            iMinSAD = iSAD;
2192                    }
2193    
2194                    if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2195                            iSAD =
2196                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2197                                                                      iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy,
2198                                                                      max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2199    
2200                            if (iSAD < iMinSAD) {
2201                                    *currMV = newMV;
2202                                    iMinSAD = iSAD;
2203                            }
2204                    }
2205            }
2206    
2207    /***************        Choose best MV found     **************/
2208    
2209      EPZS16_Terminate_with_Refine:
2210            if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step
2211                    iMinSAD =
2212                            Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2213                                                             iMinSAD, pmv, min_dx, max_dx, min_dy, max_dy,
2214                                                             iFcode, iQuant, iEdgedWidth);
2215    
2216      EPZS16_Terminate_without_Refine:
2217    
2218            *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;
2222            return iMinSAD;
2223    }
2224    
2225    
2226    int32_t
2227    EPZSSearch8(const uint8_t * const pRef,
2228                            const uint8_t * const pRefH,
2229                            const uint8_t * const pRefV,
2230                            const uint8_t * const pRefHV,
2231                            const IMAGE * const pCur,
2232                            const int x,
2233                            const int y,
2234                            const int start_x,
2235                            const int start_y,
2236                            const uint32_t MotionFlags,
2237                            const uint32_t iQuant,
2238                            const uint32_t iFcode,
2239                            const MBParam * const pParam,
2240                            const MACROBLOCK * const pMBs,
2241                            const MACROBLOCK * const prevMBs,
2242                            VECTOR * const currMV,
2243                            VECTOR * const currPMV)
2244    {
2245    /* Please not that EPZS might not be a good choice for 8x8-block motion search ! */
2246    
2247            const uint32_t iWcount = pParam->mb_width;
2248            const int32_t iWidth = pParam->width;
2249            const int32_t iHeight = pParam->height;
2250            const int32_t iEdgedWidth = pParam->edged_width;
2251    
2252            const uint8_t *cur = pCur->y + x * 8 + y * 8 * iEdgedWidth;
2253    
2254            int32_t iDiamondSize = 1;
2255    
2256            int32_t min_dx;
2257            int32_t max_dx;
2258            int32_t min_dy;
2259            int32_t max_dy;
2260    
2261            VECTOR newMV;
2262            VECTOR backupMV;
2263    
2264            VECTOR pmv[4];
2265            int32_t psad[8];
2266    
2267            const int32_t iSubBlock = ((y & 1) << 1) + (x & 1);
2268    
2269    //  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;
2273            int32_t iMinSAD, iSAD = 9999;
2274    
2275            MainSearch8FuncPtr MainSearchPtr;
2276    
2277    /* Get maximum range */
2278            get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 8, iWidth, iHeight,
2279                              iFcode);
2280    
2281    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
2282    
2283            if (!(MotionFlags & PMV_HALFPEL8)) {
2284                    min_dx = EVEN(min_dx);
2285                    max_dx = EVEN(max_dx);
2286                    min_dy = EVEN(min_dy);
2287                    max_dy = EVEN(max_dy);
2288            }
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);
2291    
2292    
2293    /* Step 4: Calculate SAD around the Median prediction.
2294            MinSAD=SAD
2295            If Motion Vector equal to Previous frame motion vector
2296                    and MinSAD<PrevFrmSAD goto Step 10.
2297            If SAD<=256 goto Step 10.
2298    */
2299    
2300    // Prepare for main loop
2301    
2302    
2303            if (!(MotionFlags & PMV_HALFPEL8)) {
2304                    currMV->x = EVEN(currMV->x);
2305                    currMV->y = EVEN(currMV->y);
2306            }
2307    
2308            if (currMV->x > max_dx)
2309                    currMV->x = max_dx;
2310            if (currMV->x < min_dx)
2311                    currMV->x = min_dx;
2312            if (currMV->y > max_dy)
2313                    currMV->y = max_dy;
2314            if (currMV->y < min_dy)
2315                    currMV->y = min_dy;
2316    
2317    /***************** This is predictor SET A: only median prediction ******************/
2318    
2319    
2320            iMinSAD =
2321                    sad8(cur,
2322                             get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
2323                                                    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
2330            if (iMinSAD < 256 / 4) {
2331                    if (MotionFlags & PMV_QUICKSTOP8)
2332                            goto EPZS8_Terminate_without_Refine;
2333                    if (MotionFlags & PMV_EARLYSTOP8)
2334                            goto EPZS8_Terminate_with_Refine;
2335            }
2336    
2337    /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
2338    
2339    
2340    // MV=(0,0) is often a good choice
2341            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
2380       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 */
2384                    if (MotionFlags & PMV_QUICKSTOP8)
2385                            goto EPZS8_Terminate_without_Refine;
2386                    if (MotionFlags & PMV_EARLYSTOP8)
2387                            goto EPZS8_Terminate_with_Refine;
2388            }
2389    
2390    /************ (Diamond Search)  **************/
2391    
2392            backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
2393    
2394            if (!(MotionFlags & PMV_HALFPELDIAMOND8))
2395                    iDiamondSize *= 2;
2396    
2397    /* 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)
2402    //      MainSearchPtr = Square8_MainSearch;
2403    //  else
2404    
2405            if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2406                    MainSearchPtr = AdvDiamond8_MainSearch;
2407            else
2408                    MainSearchPtr = Diamond8_MainSearch;
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    
2417            if (iSAD < iMinSAD) {
2418                    *currMV = newMV;
2419                    iMinSAD = iSAD;
2420            }
2421    
2422            if (MotionFlags & PMV_EXTSEARCH8) {
2423    /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
2424    
2425                    if (!(MVequal(pmv[0], backupMV))) {
2426                            iSAD =
2427                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2428                                                                      pmv[0].x, pmv[0].y, iMinSAD, &newMV, pmv,
2429                                                                      min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2430                                                                      iDiamondSize, iFcode, iQuant, 0);
2431    
2432                            if (iSAD < iMinSAD) {
2433                                    *currMV = newMV;
2434                                    iMinSAD = iSAD;
2435                            }
2436                    }
2437    
2438                    if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2439                            iSAD =
2440                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2441                                                                      iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy,
2442                                                                      max_dy, iEdgedWidth, iDiamondSize, iFcode,
2443                                                                      iQuant, 0);
2444    
2445                            if (iSAD < iMinSAD) {
2446                                    *currMV = newMV;
2447                                    iMinSAD = iSAD;
2448                            }
2449                    }
2450            }
2451    
2452    /***************        Choose best MV found     **************/
2453    
2454      EPZS8_Terminate_with_Refine:
2455            if (MotionFlags & PMV_HALFPELREFINE8)   // perform final half-pel step
2456                    iMinSAD =
2457                            Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2458                                                            iMinSAD, pmv, min_dx, max_dx, min_dy, max_dy,
2459                                                            iFcode, iQuant, iEdgedWidth);
2460    
2461      EPZS8_Terminate_without_Refine:
2462    
2463            currPMV->x = currMV->x - pmv[0].x;
2464            currPMV->y = currMV->y - pmv[0].y;
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                    /* force F_SAD16
2525                            f_sad16 = 100;
2526                            b_sad16 = 65535;
2527    
2528                            mb->mode = MODE_FORWARD;
2529                            mb->mvs[0].x = 1;
2530                            mb->mvs[0].y = 1;
2531                            mb->b_mvs[0].x = 1;
2532                            mb->b_mvs[0].y = 1;
2533                            continue;
2534                     ^^ force F_SAD16 */
2535    
2536    
2537                            // forward search
2538                            f_sad16 =
2539                                    SEARCH16(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
2540                                                     &frame->image, i, j, frame->motion_flags,
2541                                                     frame->quant, frame->fcode, pParam,
2542                                                     f_mbs,  f_mbs, /* todo */
2543                                                     &mb->mvs[0], &pmv_dontcare);   // ignore pmv
2544    
2545                            // backward search
2546                            b_sad16 = SEARCH16(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
2547                                                    &frame->image, i, j, frame->motion_flags,
2548                                                    frame->quant, frame->bcode, pParam,
2549                                                    b_mbs, b_mbs,   /* todo */
2550                                                    &mb->b_mvs[0], &pmv_dontcare);  // ignore pmv
2551    
2552                            // interpolate search (simple, but effective)
2553                            i_sad16 = 65535;
2554    
2555                            /*
2556                            x/y range somewhat buggy
2557                            i_sad16 =
2558                                    sad16bi_c(frame->image.y + i * 16 + j * 16 * edged_width,
2559                                                      get_ref(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
2560                                                                      i, j, 16, mb->mvs[0].x, mb->mvs[0].y,
2561                                                                      edged_width), get_ref(b_ref->y, b_refH->y,
2562                                                                                                                    b_refV->y, b_refHV->y,
2563                                                                                                                    i, j, 16,
2564                                                                                                                    mb->b_mvs[0].x,
2565                                                                                                                    mb->b_mvs[0].x,
2566                                                                                                                    edged_width),
2567                                                      edged_width);
2568                            */
2569    
2570                            // TODO: direct search
2571                            // predictor + range of [-32,32]
2572                            d_sad16 = 65535;
2573    
2574    
2575                            if (f_sad16 < b_sad16) {
2576                                    best_sad = f_sad16;
2577                                    mb->mode = MODE_FORWARD;
2578                            } else {
2579                                    best_sad = b_sad16;
2580                                    mb->mode = MODE_BACKWARD;
2581                            }
2582    
2583                            if (i_sad16 < best_sad) {
2584                                    best_sad = i_sad16;
2585                                    mb->mode = MODE_INTERPOLATE;
2586                            }
2587    
2588                            if (d_sad16 < best_sad) {
2589                                    best_sad = d_sad16;
2590                                    mb->mode = MODE_DIRECT;
2591                            }
2592    
2593                    }
2594            }
2595    }

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

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